QuestState and QuestTimer class cleanups.

This commit is contained in:
MobiusDevelopment
2020-01-26 16:53:48 +00:00
parent 8b5af84230
commit 990d3b590b
72 changed files with 1754 additions and 2673 deletions

View File

@@ -261,7 +261,7 @@ public class AdminQuest implements IAdminCommandHandler
{
for (QuestTimer timer : list)
{
timers += "<tr><td colspan=\"4\"><table width=270 border=0 bgcolor=131210><tr><td width=270><font color=\"LEVEL\">" + timer.getName() + ":</font> <font color=00FF00>Active: " + timer.isActive() + " Repeatable: " + timer.isRepeating() + " Player: " + timer.getPlayer() + " Npc: " + timer.getNpc() + "</font></td></tr></table></td></tr>";
timers += "<tr><td colspan=\"4\"><table width=270 border=0 bgcolor=131210><tr><td width=270><font color=\"LEVEL\">" + timer.toString() + ":</font> <font color=00FF00>Active: " + timer.isActive() + " Repeatable: " + timer.isRepeating() + " Player: " + timer.getPlayer() + " Npc: " + timer.getNpc() + "</font></td></tr></table></td></tr>";
counter++;
if (counter > 10)
{

View File

@@ -329,7 +329,7 @@ public class Quest extends AbstractScript implements IIdentifiable
{
for (QuestTimer timer : timers)
{
if ((timer != null) && timer.isMatch(this, name, npc, player))
if ((timer != null) && timer.equals(this, name, npc, player))
{
return timer;
}
@@ -387,7 +387,7 @@ public class Quest extends AbstractScript implements IIdentifiable
final QuestTimer timer = getQuestTimer(name, npc, player);
if (timer != null)
{
timer.cancelAndRemove();
timer.cancel();
}
}
@@ -400,7 +400,7 @@ public class Quest extends AbstractScript implements IIdentifiable
{
if ((timer != null) && (_questTimers != null))
{
final List<QuestTimer> timers = getQuestTimers().get(timer.getName());
final List<QuestTimer> timers = getQuestTimers().get(timer.toString());
if (timers != null)
{
_writeLock.lock();

View File

@@ -136,31 +136,29 @@ public class QuestState
/**
* @param state the new state of the quest to set
* @return {@code true} if state was changed, {@code false} otherwise
* @see #setState(byte state, boolean saveInDb)
* @see org.l2jmobius.gameserver.model.quest.State
*/
public boolean setState(byte state)
public void setState(byte state)
{
return setState(state, true);
setState(state, true);
}
/**
* Change the state of this quest to the specified value.
* @param state the new state of the quest to set
* @param saveInDb if {@code true}, will save the state change in the database
* @return {@code true} if state was changed, {@code false} otherwise
* @see org.l2jmobius.gameserver.model.quest.State
*/
public boolean setState(byte state, boolean saveInDb)
public void setState(byte state, boolean saveInDb)
{
if (_simulated)
{
return false;
return;
}
if (_state == state)
{
return false;
return;
}
final boolean newQuest = isCreated();
_state = state;
@@ -177,20 +175,18 @@ public class QuestState
}
_player.sendPacket(new QuestList(_player));
return true;
}
/**
* Add parameter used in quests.
* @param var String pointing out the name of the variable for quest
* @param value String pointing out the value of the variable for quest
* @return String (equal to parameter "value")
*/
public String setInternal(String var, String value)
public void setInternal(String var, String value)
{
if (_simulated)
{
return null;
return;
}
if (_vars == null)
@@ -204,16 +200,15 @@ public class QuestState
}
_vars.put(var, value);
return value;
}
public String set(String var, int value)
public void set(String var, int value)
{
if (_simulated)
{
return null;
return;
}
return set(var, Integer.toString(value));
set(var, Integer.toString(value));
}
/**
@@ -229,13 +224,12 @@ public class QuestState
* <ul>
* @param var String indicating the name of the variable for quest
* @param value String indicating the value of the variable for quest
* @return String (equal to parameter "value")
*/
public String set(String var, String value)
public void set(String var, String value)
{
if (_simulated)
{
return null;
return;
}
if (_vars == null)
@@ -279,8 +273,6 @@ public class QuestState
LOGGER.log(Level.WARNING, _player.getName() + ", " + _questName + " cond [" + value + "] is not an integer. Value stored, but no packet was sent: " + e.getMessage(), e);
}
}
return value;
}
/**
@@ -325,20 +317,15 @@ public class QuestState
// case 1: No steps have been skipped so far...
if (completedStateFlags == 0)
{
// check if this step also doesn't skip anything. If so, no further work is needed
// also, in this case, no work is needed if the state is being reset to a smaller value
// in those cases, skip forward to informing the client about the change...
// Check if this step also doesn't skip anything. If so, no further work is needed also, in this case, no work is needed if the state is being reset to a smaller value in those cases, skip forward to informing the client about the change...
// ELSE, if we just now skipped for the first time...prepare the flags!!!
if (cond > (old + 1))
{
// set the most significant bit to 1 (indicates that there exist skipped states)
// also, ensure that the least significant bit is an 1 (the first step is never skipped, no matter
// what the cond says)
// also, ensure that the least significant bit is an 1 (the first step is never skipped, no matter what the cond says)
completedStateFlags = 0x80000001;
// since no flag had been skipped until now, the least significant bits must all
// be set to 1, up until "old" number of bits.
// since no flag had been skipped until now, the least significant bits must all be set to 1, up until "old" number of bits.
completedStateFlags |= (1 << old) - 1;
// now, just set the bit corresponding to the passed cond to 1 (current step)
@@ -347,11 +334,9 @@ public class QuestState
}
}
// case 2: There were exist previously skipped steps
// if this is a push back to a previous step, clear all completion flags ahead
else if (cond < old)
else if (cond < old) // if this is a push back to a previous step, clear all completion flags ahead
{
// note, this also unsets the flag indicating that there exist skips
completedStateFlags &= (1 << cond) - 1;
completedStateFlags &= (1 << cond) - 1; // note, this also unsets the flag indicating that there exist skips
// now, check if this resulted in no steps being skipped any more
if (completedStateFlags == ((1 << cond) - 1))
@@ -361,8 +346,7 @@ public class QuestState
else
{
// set the most significant bit back to 1 again, to correctly indicate that this skips states.
// also, ensure that the least significant bit is an 1 (the first step is never skipped, no matter
// what the cond says)
// also, ensure that the least significant bit is an 1 (the first step is never skipped, no matter what the cond says)
completedStateFlags |= 0x80000001;
set("__compltdStateFlags", String.valueOf(completedStateFlags));
}
@@ -388,18 +372,17 @@ public class QuestState
/**
* Removes a quest variable from the list of existing quest variables.
* @param var the name of the variable to remove
* @return the previous value of the variable or {@code null} if none were found
*/
public String unset(String var)
public void unset(String var)
{
if (_simulated)
{
return null;
return;
}
if (_vars == null)
{
return null;
return;
}
final String old = _vars.remove(var);
@@ -407,7 +390,6 @@ public class QuestState
{
Quest.deleteQuestVarInDb(this, var);
}
return old;
}
/**
@@ -468,22 +450,21 @@ public class QuestState
/**
* Sets the quest state progress ({@code cond}) to the specified step.
* @param value the new value of the quest state progress
* @return this {@link QuestState} object
* @see #set(String var, String value)
* @see #setCond(int, boolean)
*/
public QuestState setCond(int value)
public void setCond(int value)
{
if (_simulated)
{
return null;
return;
}
if (isStarted())
{
set("cond", Integer.toString(value));
}
return this;
return;
}
/**
@@ -529,20 +510,19 @@ public class QuestState
* Sets the quest state progress ({@code cond}) to the specified step.
* @param value the new value of the quest state progress
* @param playQuestMiddle if {@code true}, plays "ItemSound.quest_middle"
* @return this {@link QuestState} object
* @see #setCond(int value)
* @see #set(String var, String value)
*/
public QuestState setCond(int value, boolean playQuestMiddle)
public void setCond(int value, boolean playQuestMiddle)
{
if (_simulated)
{
return null;
return;
}
if (!isStarted())
{
return this;
return;
}
set("cond", String.valueOf(value));
@@ -550,17 +530,15 @@ public class QuestState
{
_player.sendPacket(QuestSound.ITEMSOUND_QUEST_MIDDLE.getPacket());
}
return this;
}
public QuestState setMemoState(int value)
public void setMemoState(int value)
{
if (_simulated)
{
return null;
return;
}
set("memoState", String.valueOf(value));
return this;
}
/**
@@ -598,16 +576,14 @@ public class QuestState
* Sets the memo state ex.
* @param slot the slot where the value will be saved
* @param value the value
* @return this QuestState
*/
public QuestState setMemoStateEx(int slot, int value)
public void setMemoStateEx(int slot, int value)
{
if (_simulated)
{
return null;
return;
}
set("memoStateEx" + slot, String.valueOf(value));
return this;
}
/**
@@ -644,13 +620,12 @@ public class QuestState
/**
* Set condition to 1, state to STARTED and play the "ItemSound.quest_accept".<br>
* Works only if state is CREATED and the quest is not a custom quest.
* @return the newly created {@code QuestState} object
*/
public QuestState startQuest()
public void startQuest()
{
if (_simulated)
{
return null;
return;
}
if (isCreated() && !getQuest().isCustomQuest())
{
@@ -659,23 +634,21 @@ public class QuestState
_player.sendPacket(QuestSound.ITEMSOUND_QUEST_ACCEPT.getPacket());
getQuest().sendNpcLogList(getPlayer());
}
return this;
}
/**
* Finishes the quest and removes all quest items associated with this quest from the player's inventory.<br>
* If {@code type} is {@code QuestType.ONE_TIME}, also removes all other quest data associated with this quest.
* @param type the {@link QuestType} of the quest
* @return this {@link QuestState} object
* @see #exitQuest(QuestType type, boolean playExitQuest)
* @see #exitQuest(boolean repeatable)
* @see #exitQuest(boolean repeatable, boolean playExitQuest)
*/
public QuestState exitQuest(QuestType type)
public void exitQuest(QuestType type)
{
if (_simulated)
{
return null;
return;
}
switch (type)
@@ -697,8 +670,6 @@ public class QuestState
// Notify to scripts
EventDispatcher.getInstance().notifyEventAsync(new OnPlayerQuestComplete(_player, getQuest().getId(), type), _player);
return this;
}
/**
@@ -706,46 +677,43 @@ public class QuestState
* If {@code type} is {@code QuestType.ONE_TIME}, also removes all other quest data associated with this quest.
* @param type the {@link QuestType} of the quest
* @param playExitQuest if {@code true}, plays "ItemSound.quest_finish"
* @return this {@link QuestState} object
* @see #exitQuest(QuestType type)
* @see #exitQuest(boolean repeatable)
* @see #exitQuest(boolean repeatable, boolean playExitQuest)
*/
public QuestState exitQuest(QuestType type, boolean playExitQuest)
public void exitQuest(QuestType type, boolean playExitQuest)
{
if (_simulated)
{
return null;
return;
}
exitQuest(type);
if (playExitQuest)
{
_player.sendPacket(QuestSound.ITEMSOUND_QUEST_FINISH.getPacket());
}
return this;
}
/**
* Finishes the quest and removes all quest items associated with this quest from the player's inventory.<br>
* If {@code repeatable} is set to {@code false}, also removes all other quest data associated with this quest.
* @param repeatable if {@code true}, deletes all data and variables of this quest, otherwise keeps them
* @return this {@link QuestState} object
* @see #exitQuest(QuestType type)
* @see #exitQuest(QuestType type, boolean playExitQuest)
* @see #exitQuest(boolean repeatable, boolean playExitQuest)
*/
private QuestState exitQuest(boolean repeatable)
private void exitQuest(boolean repeatable)
{
if (_simulated)
{
return null;
return;
}
_player.removeNotifyQuestOfDeath(this);
if (!isStarted())
{
return this;
return;
}
// Clean registered quest items
@@ -762,7 +730,6 @@ public class QuestState
setState(State.COMPLETED);
}
_vars = null;
return this;
}
/**
@@ -770,16 +737,15 @@ public class QuestState
* If {@code repeatable} is set to {@code false}, also removes all other quest data associated with this quest.
* @param repeatable if {@code true}, deletes all data and variables of this quest, otherwise keeps them
* @param playExitQuest if {@code true}, plays "ItemSound.quest_finish"
* @return this {@link QuestState} object
* @see #exitQuest(QuestType type)
* @see #exitQuest(QuestType type, boolean playExitQuest)
* @see #exitQuest(boolean repeatable)
*/
public QuestState exitQuest(boolean repeatable, boolean playExitQuest)
public void exitQuest(boolean repeatable, boolean playExitQuest)
{
if (_simulated)
{
return null;
return;
}
exitQuest(repeatable);
@@ -790,7 +756,7 @@ public class QuestState
// Notify to scripts
EventDispatcher.getInstance().notifyEventAsync(new OnPlayerQuestComplete(_player, getQuest().getId(), repeatable ? QuestType.REPEATABLE : QuestType.ONE_TIME), _player);
return this;
return;
}
/**

View File

@@ -17,8 +17,6 @@
package org.l2jmobius.gameserver.model.quest;
import java.util.concurrent.ScheduledFuture;
import java.util.logging.Level;
import java.util.logging.Logger;
import org.l2jmobius.commons.concurrent.ThreadPool;
import org.l2jmobius.gameserver.model.actor.Npc;
@@ -26,106 +24,68 @@ import org.l2jmobius.gameserver.model.actor.instance.PlayerInstance;
public class QuestTimer
{
protected static final Logger LOGGER = Logger.getLogger(QuestTimer.class.getName());
public class ScheduleTimerTask implements Runnable
{
@Override
public void run()
{
if (!_isActive)
{
return;
}
try
{
if (!_isRepeating)
{
cancelAndRemove();
}
_quest.notifyEvent(_name, _npc, _player);
}
catch (Exception e)
{
LOGGER.log(Level.SEVERE, "", e);
}
}
}
boolean _isActive = true;
final String _name;
final Quest _quest;
final Npc _npc;
final PlayerInstance _player;
final boolean _isRepeating;
private final ScheduledFuture<?> _scheduler;
private final String _name;
private final Quest _quest;
private final Npc _npc;
private final PlayerInstance _player;
private final boolean _isRepeating;
private ScheduledFuture<?> _scheduler;
public QuestTimer(Quest quest, String name, long time, Npc npc, PlayerInstance player, boolean repeating)
{
_name = name;
_quest = quest;
_player = player;
_name = name;
_npc = npc;
_player = player;
_isRepeating = repeating;
_scheduler = repeating ? ThreadPool.scheduleAtFixedRate(new ScheduleTimerTask(), time, time) : ThreadPool.schedule(new ScheduleTimerTask(), time);
}
public QuestTimer(Quest quest, String name, long time, Npc npc, PlayerInstance player)
{
this(quest, name, time, npc, player, false);
}
public QuestTimer(QuestState qs, String name, long time)
{
this(qs.getQuest(), name, time, null, qs.getPlayer(), false);
}
/**
* Cancel this quest timer.
*/
public void cancel()
{
_isActive = false;
if (_scheduler != null)
if (repeating)
{
_scheduler.cancel(false);
_scheduler = ThreadPool.scheduleAtFixedRate(new ScheduleTimerTask(), time, time); // Prepare auto end task
}
else
{
_scheduler = ThreadPool.schedule(new ScheduleTimerTask(), time); // Prepare auto end task
}
}
/**
* Cancel this quest timer and remove it from the associated quest.
*/
public void cancelAndRemove()
public void cancel()
{
cancel();
if (_scheduler != null)
{
_scheduler.cancel(false);
_scheduler = null;
}
_quest.removeQuestTimer(this);
}
/**
* Compares if this timer matches with the key attributes passed.
* @param quest the quest to which the timer is attached
* @param name the name of the timer
* @param npc the NPC attached to the desired timer (null if no NPC attached)
* @param player the player attached to the desired timer (null if no player attached)
* @return
* public method to compare if this timer matches with the key attributes passed.
* @param quest : Quest instance to which the timer is attached
* @param name : Name of the timer
* @param npc : Npc instance attached to the desired timer (null if no npc attached)
* @param player : Player instance attached to the desired timer (null if no player attached)
* @return boolean
*/
public boolean isMatch(Quest quest, String name, Npc npc, PlayerInstance player)
public boolean equals(Quest quest, String name, Npc npc, PlayerInstance player)
{
if ((quest == null) || (name == null))
if ((quest == null) || (quest != _quest))
{
return false;
}
if ((quest != _quest) || !name.equalsIgnoreCase(_name))
if ((name == null) || !name.equals(_name))
{
return false;
}
return ((npc == _npc) && (player == _player));
return (npc == _npc) && (player == _player);
}
public boolean isActive()
{
return _isActive;
return (_scheduler != null) && !_scheduler.isCancelled() && !_scheduler.isDone();
}
public boolean isRepeating()
@@ -158,4 +118,23 @@ public class QuestTimer
{
return _name;
}
public class ScheduleTimerTask implements Runnable
{
@Override
public void run()
{
if (_scheduler == null)
{
return;
}
if (!_isRepeating)
{
cancel();
}
_quest.notifyEvent(_name, _npc, _player);
}
}
}

View File

@@ -261,7 +261,7 @@ public class AdminQuest implements IAdminCommandHandler
{
for (QuestTimer timer : list)
{
timers += "<tr><td colspan=\"4\"><table width=270 border=0 bgcolor=131210><tr><td width=270><font color=\"LEVEL\">" + timer.getName() + ":</font> <font color=00FF00>Active: " + timer.isActive() + " Repeatable: " + timer.isRepeating() + " Player: " + timer.getPlayer() + " Npc: " + timer.getNpc() + "</font></td></tr></table></td></tr>";
timers += "<tr><td colspan=\"4\"><table width=270 border=0 bgcolor=131210><tr><td width=270><font color=\"LEVEL\">" + timer.toString() + ":</font> <font color=00FF00>Active: " + timer.isActive() + " Repeatable: " + timer.isRepeating() + " Player: " + timer.getPlayer() + " Npc: " + timer.getNpc() + "</font></td></tr></table></td></tr>";
counter++;
if (counter > 10)
{

View File

@@ -331,7 +331,7 @@ public class Quest extends AbstractScript implements IIdentifiable
{
for (QuestTimer timer : timers)
{
if ((timer != null) && timer.isMatch(this, name, npc, player))
if ((timer != null) && timer.equals(this, name, npc, player))
{
return timer;
}
@@ -389,7 +389,7 @@ public class Quest extends AbstractScript implements IIdentifiable
final QuestTimer timer = getQuestTimer(name, npc, player);
if (timer != null)
{
timer.cancelAndRemove();
timer.cancel();
}
}
@@ -402,7 +402,7 @@ public class Quest extends AbstractScript implements IIdentifiable
{
if ((timer != null) && (_questTimers != null))
{
final List<QuestTimer> timers = getQuestTimers().get(timer.getName());
final List<QuestTimer> timers = getQuestTimers().get(timer.toString());
if (timers != null)
{
_writeLock.lock();

View File

@@ -136,31 +136,29 @@ public class QuestState
/**
* @param state the new state of the quest to set
* @return {@code true} if state was changed, {@code false} otherwise
* @see #setState(byte state, boolean saveInDb)
* @see org.l2jmobius.gameserver.model.quest.State
*/
public boolean setState(byte state)
public void setState(byte state)
{
return setState(state, true);
setState(state, true);
}
/**
* Change the state of this quest to the specified value.
* @param state the new state of the quest to set
* @param saveInDb if {@code true}, will save the state change in the database
* @return {@code true} if state was changed, {@code false} otherwise
* @see org.l2jmobius.gameserver.model.quest.State
*/
public boolean setState(byte state, boolean saveInDb)
public void setState(byte state, boolean saveInDb)
{
if (_simulated)
{
return false;
return;
}
if (_state == state)
{
return false;
return;
}
final boolean newQuest = isCreated();
_state = state;
@@ -177,20 +175,18 @@ public class QuestState
}
_player.sendPacket(new QuestList(_player));
return true;
}
/**
* Add parameter used in quests.
* @param var String pointing out the name of the variable for quest
* @param value String pointing out the value of the variable for quest
* @return String (equal to parameter "value")
*/
public String setInternal(String var, String value)
public void setInternal(String var, String value)
{
if (_simulated)
{
return null;
return;
}
if (_vars == null)
@@ -204,16 +200,15 @@ public class QuestState
}
_vars.put(var, value);
return value;
}
public String set(String var, int value)
public void set(String var, int value)
{
if (_simulated)
{
return null;
return;
}
return set(var, Integer.toString(value));
set(var, Integer.toString(value));
}
/**
@@ -229,13 +224,12 @@ public class QuestState
* <ul>
* @param var String indicating the name of the variable for quest
* @param value String indicating the value of the variable for quest
* @return String (equal to parameter "value")
*/
public String set(String var, String value)
public void set(String var, String value)
{
if (_simulated)
{
return null;
return;
}
if (_vars == null)
@@ -279,8 +273,6 @@ public class QuestState
LOGGER.log(Level.WARNING, _player.getName() + ", " + _questName + " cond [" + value + "] is not an integer. Value stored, but no packet was sent: " + e.getMessage(), e);
}
}
return value;
}
/**
@@ -325,20 +317,15 @@ public class QuestState
// case 1: No steps have been skipped so far...
if (completedStateFlags == 0)
{
// check if this step also doesn't skip anything. If so, no further work is needed
// also, in this case, no work is needed if the state is being reset to a smaller value
// in those cases, skip forward to informing the client about the change...
// Check if this step also doesn't skip anything. If so, no further work is needed also, in this case, no work is needed if the state is being reset to a smaller value in those cases, skip forward to informing the client about the change...
// ELSE, if we just now skipped for the first time...prepare the flags!!!
if (cond > (old + 1))
{
// set the most significant bit to 1 (indicates that there exist skipped states)
// also, ensure that the least significant bit is an 1 (the first step is never skipped, no matter
// what the cond says)
// also, ensure that the least significant bit is an 1 (the first step is never skipped, no matter what the cond says)
completedStateFlags = 0x80000001;
// since no flag had been skipped until now, the least significant bits must all
// be set to 1, up until "old" number of bits.
// since no flag had been skipped until now, the least significant bits must all be set to 1, up until "old" number of bits.
completedStateFlags |= (1 << old) - 1;
// now, just set the bit corresponding to the passed cond to 1 (current step)
@@ -347,11 +334,9 @@ public class QuestState
}
}
// case 2: There were exist previously skipped steps
// if this is a push back to a previous step, clear all completion flags ahead
else if (cond < old)
else if (cond < old) // if this is a push back to a previous step, clear all completion flags ahead
{
// note, this also unsets the flag indicating that there exist skips
completedStateFlags &= (1 << cond) - 1;
completedStateFlags &= (1 << cond) - 1; // note, this also unsets the flag indicating that there exist skips
// now, check if this resulted in no steps being skipped any more
if (completedStateFlags == ((1 << cond) - 1))
@@ -361,8 +346,7 @@ public class QuestState
else
{
// set the most significant bit back to 1 again, to correctly indicate that this skips states.
// also, ensure that the least significant bit is an 1 (the first step is never skipped, no matter
// what the cond says)
// also, ensure that the least significant bit is an 1 (the first step is never skipped, no matter what the cond says)
completedStateFlags |= 0x80000001;
set("__compltdStateFlags", String.valueOf(completedStateFlags));
}
@@ -388,18 +372,17 @@ public class QuestState
/**
* Removes a quest variable from the list of existing quest variables.
* @param var the name of the variable to remove
* @return the previous value of the variable or {@code null} if none were found
*/
public String unset(String var)
public void unset(String var)
{
if (_simulated)
{
return null;
return;
}
if (_vars == null)
{
return null;
return;
}
final String old = _vars.remove(var);
@@ -407,7 +390,6 @@ public class QuestState
{
Quest.deleteQuestVarInDb(this, var);
}
return old;
}
/**
@@ -468,22 +450,21 @@ public class QuestState
/**
* Sets the quest state progress ({@code cond}) to the specified step.
* @param value the new value of the quest state progress
* @return this {@link QuestState} object
* @see #set(String var, String value)
* @see #setCond(int, boolean)
*/
public QuestState setCond(int value)
public void setCond(int value)
{
if (_simulated)
{
return null;
return;
}
if (isStarted())
{
set("cond", Integer.toString(value));
}
return this;
return;
}
/**
@@ -529,20 +510,19 @@ public class QuestState
* Sets the quest state progress ({@code cond}) to the specified step.
* @param value the new value of the quest state progress
* @param playQuestMiddle if {@code true}, plays "ItemSound.quest_middle"
* @return this {@link QuestState} object
* @see #setCond(int value)
* @see #set(String var, String value)
*/
public QuestState setCond(int value, boolean playQuestMiddle)
public void setCond(int value, boolean playQuestMiddle)
{
if (_simulated)
{
return null;
return;
}
if (!isStarted())
{
return this;
return;
}
set("cond", String.valueOf(value));
@@ -550,17 +530,15 @@ public class QuestState
{
_player.sendPacket(QuestSound.ITEMSOUND_QUEST_MIDDLE.getPacket());
}
return this;
}
public QuestState setMemoState(int value)
public void setMemoState(int value)
{
if (_simulated)
{
return null;
return;
}
set("memoState", String.valueOf(value));
return this;
}
/**
@@ -598,16 +576,14 @@ public class QuestState
* Sets the memo state ex.
* @param slot the slot where the value will be saved
* @param value the value
* @return this QuestState
*/
public QuestState setMemoStateEx(int slot, int value)
public void setMemoStateEx(int slot, int value)
{
if (_simulated)
{
return null;
return;
}
set("memoStateEx" + slot, String.valueOf(value));
return this;
}
/**
@@ -644,13 +620,12 @@ public class QuestState
/**
* Set condition to 1, state to STARTED and play the "ItemSound.quest_accept".<br>
* Works only if state is CREATED and the quest is not a custom quest.
* @return the newly created {@code QuestState} object
*/
public QuestState startQuest()
public void startQuest()
{
if (_simulated)
{
return null;
return;
}
if (isCreated() && !getQuest().isCustomQuest())
{
@@ -659,23 +634,21 @@ public class QuestState
_player.sendPacket(QuestSound.ITEMSOUND_QUEST_ACCEPT.getPacket());
getQuest().sendNpcLogList(getPlayer());
}
return this;
}
/**
* Finishes the quest and removes all quest items associated with this quest from the player's inventory.<br>
* If {@code type} is {@code QuestType.ONE_TIME}, also removes all other quest data associated with this quest.
* @param type the {@link QuestType} of the quest
* @return this {@link QuestState} object
* @see #exitQuest(QuestType type, boolean playExitQuest)
* @see #exitQuest(boolean repeatable)
* @see #exitQuest(boolean repeatable, boolean playExitQuest)
*/
public QuestState exitQuest(QuestType type)
public void exitQuest(QuestType type)
{
if (_simulated)
{
return null;
return;
}
switch (type)
@@ -697,8 +670,6 @@ public class QuestState
// Notify to scripts
EventDispatcher.getInstance().notifyEventAsync(new OnPlayerQuestComplete(_player, getQuest().getId(), type), _player);
return this;
}
/**
@@ -706,46 +677,43 @@ public class QuestState
* If {@code type} is {@code QuestType.ONE_TIME}, also removes all other quest data associated with this quest.
* @param type the {@link QuestType} of the quest
* @param playExitQuest if {@code true}, plays "ItemSound.quest_finish"
* @return this {@link QuestState} object
* @see #exitQuest(QuestType type)
* @see #exitQuest(boolean repeatable)
* @see #exitQuest(boolean repeatable, boolean playExitQuest)
*/
public QuestState exitQuest(QuestType type, boolean playExitQuest)
public void exitQuest(QuestType type, boolean playExitQuest)
{
if (_simulated)
{
return null;
return;
}
exitQuest(type);
if (playExitQuest)
{
_player.sendPacket(QuestSound.ITEMSOUND_QUEST_FINISH.getPacket());
}
return this;
}
/**
* Finishes the quest and removes all quest items associated with this quest from the player's inventory.<br>
* If {@code repeatable} is set to {@code false}, also removes all other quest data associated with this quest.
* @param repeatable if {@code true}, deletes all data and variables of this quest, otherwise keeps them
* @return this {@link QuestState} object
* @see #exitQuest(QuestType type)
* @see #exitQuest(QuestType type, boolean playExitQuest)
* @see #exitQuest(boolean repeatable, boolean playExitQuest)
*/
private QuestState exitQuest(boolean repeatable)
private void exitQuest(boolean repeatable)
{
if (_simulated)
{
return null;
return;
}
_player.removeNotifyQuestOfDeath(this);
if (!isStarted())
{
return this;
return;
}
// Clean registered quest items
@@ -762,7 +730,6 @@ public class QuestState
setState(State.COMPLETED);
}
_vars = null;
return this;
}
/**
@@ -770,16 +737,15 @@ public class QuestState
* If {@code repeatable} is set to {@code false}, also removes all other quest data associated with this quest.
* @param repeatable if {@code true}, deletes all data and variables of this quest, otherwise keeps them
* @param playExitQuest if {@code true}, plays "ItemSound.quest_finish"
* @return this {@link QuestState} object
* @see #exitQuest(QuestType type)
* @see #exitQuest(QuestType type, boolean playExitQuest)
* @see #exitQuest(boolean repeatable)
*/
public QuestState exitQuest(boolean repeatable, boolean playExitQuest)
public void exitQuest(boolean repeatable, boolean playExitQuest)
{
if (_simulated)
{
return null;
return;
}
exitQuest(repeatable);
@@ -790,7 +756,7 @@ public class QuestState
// Notify to scripts
EventDispatcher.getInstance().notifyEventAsync(new OnPlayerQuestComplete(_player, getQuest().getId(), repeatable ? QuestType.REPEATABLE : QuestType.ONE_TIME), _player);
return this;
return;
}
/**

View File

@@ -17,8 +17,6 @@
package org.l2jmobius.gameserver.model.quest;
import java.util.concurrent.ScheduledFuture;
import java.util.logging.Level;
import java.util.logging.Logger;
import org.l2jmobius.commons.concurrent.ThreadPool;
import org.l2jmobius.gameserver.model.actor.Npc;
@@ -26,106 +24,68 @@ import org.l2jmobius.gameserver.model.actor.instance.PlayerInstance;
public class QuestTimer
{
protected static final Logger LOGGER = Logger.getLogger(QuestTimer.class.getName());
public class ScheduleTimerTask implements Runnable
{
@Override
public void run()
{
if (!_isActive)
{
return;
}
try
{
if (!_isRepeating)
{
cancelAndRemove();
}
_quest.notifyEvent(_name, _npc, _player);
}
catch (Exception e)
{
LOGGER.log(Level.SEVERE, "", e);
}
}
}
boolean _isActive = true;
final String _name;
final Quest _quest;
final Npc _npc;
final PlayerInstance _player;
final boolean _isRepeating;
private final ScheduledFuture<?> _scheduler;
private final String _name;
private final Quest _quest;
private final Npc _npc;
private final PlayerInstance _player;
private final boolean _isRepeating;
private ScheduledFuture<?> _scheduler;
public QuestTimer(Quest quest, String name, long time, Npc npc, PlayerInstance player, boolean repeating)
{
_name = name;
_quest = quest;
_player = player;
_name = name;
_npc = npc;
_player = player;
_isRepeating = repeating;
_scheduler = repeating ? ThreadPool.scheduleAtFixedRate(new ScheduleTimerTask(), time, time) : ThreadPool.schedule(new ScheduleTimerTask(), time);
}
public QuestTimer(Quest quest, String name, long time, Npc npc, PlayerInstance player)
{
this(quest, name, time, npc, player, false);
}
public QuestTimer(QuestState qs, String name, long time)
{
this(qs.getQuest(), name, time, null, qs.getPlayer(), false);
}
/**
* Cancel this quest timer.
*/
public void cancel()
{
_isActive = false;
if (_scheduler != null)
if (repeating)
{
_scheduler.cancel(false);
_scheduler = ThreadPool.scheduleAtFixedRate(new ScheduleTimerTask(), time, time); // Prepare auto end task
}
else
{
_scheduler = ThreadPool.schedule(new ScheduleTimerTask(), time); // Prepare auto end task
}
}
/**
* Cancel this quest timer and remove it from the associated quest.
*/
public void cancelAndRemove()
public void cancel()
{
cancel();
if (_scheduler != null)
{
_scheduler.cancel(false);
_scheduler = null;
}
_quest.removeQuestTimer(this);
}
/**
* Compares if this timer matches with the key attributes passed.
* @param quest the quest to which the timer is attached
* @param name the name of the timer
* @param npc the NPC attached to the desired timer (null if no NPC attached)
* @param player the player attached to the desired timer (null if no player attached)
* @return
* public method to compare if this timer matches with the key attributes passed.
* @param quest : Quest instance to which the timer is attached
* @param name : Name of the timer
* @param npc : Npc instance attached to the desired timer (null if no npc attached)
* @param player : Player instance attached to the desired timer (null if no player attached)
* @return boolean
*/
public boolean isMatch(Quest quest, String name, Npc npc, PlayerInstance player)
public boolean equals(Quest quest, String name, Npc npc, PlayerInstance player)
{
if ((quest == null) || (name == null))
if ((quest == null) || (quest != _quest))
{
return false;
}
if ((quest != _quest) || !name.equalsIgnoreCase(_name))
if ((name == null) || !name.equals(_name))
{
return false;
}
return ((npc == _npc) && (player == _player));
return (npc == _npc) && (player == _player);
}
public boolean isActive()
{
return _isActive;
return (_scheduler != null) && !_scheduler.isCancelled() && !_scheduler.isDone();
}
public boolean isRepeating()
@@ -158,4 +118,23 @@ public class QuestTimer
{
return _name;
}
public class ScheduleTimerTask implements Runnable
{
@Override
public void run()
{
if (_scheduler == null)
{
return;
}
if (!_isRepeating)
{
cancel();
}
_quest.notifyEvent(_name, _npc, _player);
}
}
}

View File

@@ -261,7 +261,7 @@ public class AdminQuest implements IAdminCommandHandler
{
for (QuestTimer timer : list)
{
timers += "<tr><td colspan=\"4\"><table width=270 border=0 bgcolor=131210><tr><td width=270><font color=\"LEVEL\">" + timer.getName() + ":</font> <font color=00FF00>Active: " + timer.isActive() + " Repeatable: " + timer.isRepeating() + " Player: " + timer.getPlayer() + " Npc: " + timer.getNpc() + "</font></td></tr></table></td></tr>";
timers += "<tr><td colspan=\"4\"><table width=270 border=0 bgcolor=131210><tr><td width=270><font color=\"LEVEL\">" + timer.toString() + ":</font> <font color=00FF00>Active: " + timer.isActive() + " Repeatable: " + timer.isRepeating() + " Player: " + timer.getPlayer() + " Npc: " + timer.getNpc() + "</font></td></tr></table></td></tr>";
counter++;
if (counter > 10)
{

View File

@@ -332,7 +332,7 @@ public class Quest extends AbstractScript implements IIdentifiable
{
for (QuestTimer timer : timers)
{
if ((timer != null) && timer.isMatch(this, name, npc, player))
if ((timer != null) && timer.equals(this, name, npc, player))
{
return timer;
}
@@ -390,7 +390,7 @@ public class Quest extends AbstractScript implements IIdentifiable
final QuestTimer timer = getQuestTimer(name, npc, player);
if (timer != null)
{
timer.cancelAndRemove();
timer.cancel();
}
}
@@ -403,7 +403,7 @@ public class Quest extends AbstractScript implements IIdentifiable
{
if ((timer != null) && (_questTimers != null))
{
final List<QuestTimer> timers = getQuestTimers().get(timer.getName());
final List<QuestTimer> timers = getQuestTimers().get(timer.toString());
if (timers != null)
{
_writeLock.lock();

View File

@@ -136,31 +136,29 @@ public class QuestState
/**
* @param state the new state of the quest to set
* @return {@code true} if state was changed, {@code false} otherwise
* @see #setState(byte state, boolean saveInDb)
* @see org.l2jmobius.gameserver.model.quest.State
*/
public boolean setState(byte state)
public void setState(byte state)
{
return setState(state, true);
setState(state, true);
}
/**
* Change the state of this quest to the specified value.
* @param state the new state of the quest to set
* @param saveInDb if {@code true}, will save the state change in the database
* @return {@code true} if state was changed, {@code false} otherwise
* @see org.l2jmobius.gameserver.model.quest.State
*/
public boolean setState(byte state, boolean saveInDb)
public void setState(byte state, boolean saveInDb)
{
if (_simulated)
{
return false;
return;
}
if (_state == state)
{
return false;
return;
}
final boolean newQuest = isCreated();
_state = state;
@@ -177,20 +175,18 @@ public class QuestState
}
_player.sendPacket(new QuestList(_player));
return true;
}
/**
* Add parameter used in quests.
* @param var String pointing out the name of the variable for quest
* @param value String pointing out the value of the variable for quest
* @return String (equal to parameter "value")
*/
public String setInternal(String var, String value)
public void setInternal(String var, String value)
{
if (_simulated)
{
return null;
return;
}
if (_vars == null)
@@ -204,16 +200,15 @@ public class QuestState
}
_vars.put(var, value);
return value;
}
public String set(String var, int value)
public void set(String var, int value)
{
if (_simulated)
{
return null;
return;
}
return set(var, Integer.toString(value));
set(var, Integer.toString(value));
}
/**
@@ -229,13 +224,12 @@ public class QuestState
* <ul>
* @param var String indicating the name of the variable for quest
* @param value String indicating the value of the variable for quest
* @return String (equal to parameter "value")
*/
public String set(String var, String value)
public void set(String var, String value)
{
if (_simulated)
{
return null;
return;
}
if (_vars == null)
@@ -279,8 +273,6 @@ public class QuestState
LOGGER.log(Level.WARNING, _player.getName() + ", " + _questName + " cond [" + value + "] is not an integer. Value stored, but no packet was sent: " + e.getMessage(), e);
}
}
return value;
}
/**
@@ -325,20 +317,15 @@ public class QuestState
// case 1: No steps have been skipped so far...
if (completedStateFlags == 0)
{
// check if this step also doesn't skip anything. If so, no further work is needed
// also, in this case, no work is needed if the state is being reset to a smaller value
// in those cases, skip forward to informing the client about the change...
// Check if this step also doesn't skip anything. If so, no further work is needed also, in this case, no work is needed if the state is being reset to a smaller value in those cases, skip forward to informing the client about the change...
// ELSE, if we just now skipped for the first time...prepare the flags!!!
if (cond > (old + 1))
{
// set the most significant bit to 1 (indicates that there exist skipped states)
// also, ensure that the least significant bit is an 1 (the first step is never skipped, no matter
// what the cond says)
// also, ensure that the least significant bit is an 1 (the first step is never skipped, no matter what the cond says)
completedStateFlags = 0x80000001;
// since no flag had been skipped until now, the least significant bits must all
// be set to 1, up until "old" number of bits.
// since no flag had been skipped until now, the least significant bits must all be set to 1, up until "old" number of bits.
completedStateFlags |= (1 << old) - 1;
// now, just set the bit corresponding to the passed cond to 1 (current step)
@@ -347,11 +334,9 @@ public class QuestState
}
}
// case 2: There were exist previously skipped steps
// if this is a push back to a previous step, clear all completion flags ahead
else if (cond < old)
else if (cond < old) // if this is a push back to a previous step, clear all completion flags ahead
{
// note, this also unsets the flag indicating that there exist skips
completedStateFlags &= (1 << cond) - 1;
completedStateFlags &= (1 << cond) - 1; // note, this also unsets the flag indicating that there exist skips
// now, check if this resulted in no steps being skipped any more
if (completedStateFlags == ((1 << cond) - 1))
@@ -361,8 +346,7 @@ public class QuestState
else
{
// set the most significant bit back to 1 again, to correctly indicate that this skips states.
// also, ensure that the least significant bit is an 1 (the first step is never skipped, no matter
// what the cond says)
// also, ensure that the least significant bit is an 1 (the first step is never skipped, no matter what the cond says)
completedStateFlags |= 0x80000001;
set("__compltdStateFlags", String.valueOf(completedStateFlags));
}
@@ -388,18 +372,17 @@ public class QuestState
/**
* Removes a quest variable from the list of existing quest variables.
* @param var the name of the variable to remove
* @return the previous value of the variable or {@code null} if none were found
*/
public String unset(String var)
public void unset(String var)
{
if (_simulated)
{
return null;
return;
}
if (_vars == null)
{
return null;
return;
}
final String old = _vars.remove(var);
@@ -407,7 +390,6 @@ public class QuestState
{
Quest.deleteQuestVarInDb(this, var);
}
return old;
}
/**
@@ -468,22 +450,21 @@ public class QuestState
/**
* Sets the quest state progress ({@code cond}) to the specified step.
* @param value the new value of the quest state progress
* @return this {@link QuestState} object
* @see #set(String var, String value)
* @see #setCond(int, boolean)
*/
public QuestState setCond(int value)
public void setCond(int value)
{
if (_simulated)
{
return null;
return;
}
if (isStarted())
{
set("cond", Integer.toString(value));
}
return this;
return;
}
/**
@@ -529,20 +510,19 @@ public class QuestState
* Sets the quest state progress ({@code cond}) to the specified step.
* @param value the new value of the quest state progress
* @param playQuestMiddle if {@code true}, plays "ItemSound.quest_middle"
* @return this {@link QuestState} object
* @see #setCond(int value)
* @see #set(String var, String value)
*/
public QuestState setCond(int value, boolean playQuestMiddle)
public void setCond(int value, boolean playQuestMiddle)
{
if (_simulated)
{
return null;
return;
}
if (!isStarted())
{
return this;
return;
}
set("cond", String.valueOf(value));
@@ -550,17 +530,15 @@ public class QuestState
{
_player.sendPacket(QuestSound.ITEMSOUND_QUEST_MIDDLE.getPacket());
}
return this;
}
public QuestState setMemoState(int value)
public void setMemoState(int value)
{
if (_simulated)
{
return null;
return;
}
set("memoState", String.valueOf(value));
return this;
}
/**
@@ -598,16 +576,14 @@ public class QuestState
* Sets the memo state ex.
* @param slot the slot where the value will be saved
* @param value the value
* @return this QuestState
*/
public QuestState setMemoStateEx(int slot, int value)
public void setMemoStateEx(int slot, int value)
{
if (_simulated)
{
return null;
return;
}
set("memoStateEx" + slot, String.valueOf(value));
return this;
}
/**
@@ -644,13 +620,12 @@ public class QuestState
/**
* Set condition to 1, state to STARTED and play the "ItemSound.quest_accept".<br>
* Works only if state is CREATED and the quest is not a custom quest.
* @return the newly created {@code QuestState} object
*/
public QuestState startQuest()
public void startQuest()
{
if (_simulated)
{
return null;
return;
}
if (isCreated() && !getQuest().isCustomQuest())
{
@@ -659,23 +634,21 @@ public class QuestState
_player.sendPacket(QuestSound.ITEMSOUND_QUEST_ACCEPT.getPacket());
getQuest().sendNpcLogList(getPlayer());
}
return this;
}
/**
* Finishes the quest and removes all quest items associated with this quest from the player's inventory.<br>
* If {@code type} is {@code QuestType.ONE_TIME}, also removes all other quest data associated with this quest.
* @param type the {@link QuestType} of the quest
* @return this {@link QuestState} object
* @see #exitQuest(QuestType type, boolean playExitQuest)
* @see #exitQuest(boolean repeatable)
* @see #exitQuest(boolean repeatable, boolean playExitQuest)
*/
public QuestState exitQuest(QuestType type)
public void exitQuest(QuestType type)
{
if (_simulated)
{
return null;
return;
}
switch (type)
@@ -697,8 +670,6 @@ public class QuestState
// Notify to scripts
EventDispatcher.getInstance().notifyEventAsync(new OnPlayerQuestComplete(_player, getQuest().getId(), type), _player);
return this;
}
/**
@@ -706,46 +677,43 @@ public class QuestState
* If {@code type} is {@code QuestType.ONE_TIME}, also removes all other quest data associated with this quest.
* @param type the {@link QuestType} of the quest
* @param playExitQuest if {@code true}, plays "ItemSound.quest_finish"
* @return this {@link QuestState} object
* @see #exitQuest(QuestType type)
* @see #exitQuest(boolean repeatable)
* @see #exitQuest(boolean repeatable, boolean playExitQuest)
*/
public QuestState exitQuest(QuestType type, boolean playExitQuest)
public void exitQuest(QuestType type, boolean playExitQuest)
{
if (_simulated)
{
return null;
return;
}
exitQuest(type);
if (playExitQuest)
{
_player.sendPacket(QuestSound.ITEMSOUND_QUEST_FINISH.getPacket());
}
return this;
}
/**
* Finishes the quest and removes all quest items associated with this quest from the player's inventory.<br>
* If {@code repeatable} is set to {@code false}, also removes all other quest data associated with this quest.
* @param repeatable if {@code true}, deletes all data and variables of this quest, otherwise keeps them
* @return this {@link QuestState} object
* @see #exitQuest(QuestType type)
* @see #exitQuest(QuestType type, boolean playExitQuest)
* @see #exitQuest(boolean repeatable, boolean playExitQuest)
*/
private QuestState exitQuest(boolean repeatable)
private void exitQuest(boolean repeatable)
{
if (_simulated)
{
return null;
return;
}
_player.removeNotifyQuestOfDeath(this);
if (!isStarted())
{
return this;
return;
}
// Clean registered quest items
@@ -762,7 +730,6 @@ public class QuestState
setState(State.COMPLETED);
}
_vars = null;
return this;
}
/**
@@ -770,16 +737,15 @@ public class QuestState
* If {@code repeatable} is set to {@code false}, also removes all other quest data associated with this quest.
* @param repeatable if {@code true}, deletes all data and variables of this quest, otherwise keeps them
* @param playExitQuest if {@code true}, plays "ItemSound.quest_finish"
* @return this {@link QuestState} object
* @see #exitQuest(QuestType type)
* @see #exitQuest(QuestType type, boolean playExitQuest)
* @see #exitQuest(boolean repeatable)
*/
public QuestState exitQuest(boolean repeatable, boolean playExitQuest)
public void exitQuest(boolean repeatable, boolean playExitQuest)
{
if (_simulated)
{
return null;
return;
}
exitQuest(repeatable);
@@ -790,7 +756,7 @@ public class QuestState
// Notify to scripts
EventDispatcher.getInstance().notifyEventAsync(new OnPlayerQuestComplete(_player, getQuest().getId(), repeatable ? QuestType.REPEATABLE : QuestType.ONE_TIME), _player);
return this;
return;
}
/**

View File

@@ -17,8 +17,6 @@
package org.l2jmobius.gameserver.model.quest;
import java.util.concurrent.ScheduledFuture;
import java.util.logging.Level;
import java.util.logging.Logger;
import org.l2jmobius.commons.concurrent.ThreadPool;
import org.l2jmobius.gameserver.model.actor.Npc;
@@ -26,106 +24,68 @@ import org.l2jmobius.gameserver.model.actor.instance.PlayerInstance;
public class QuestTimer
{
protected static final Logger LOGGER = Logger.getLogger(QuestTimer.class.getName());
public class ScheduleTimerTask implements Runnable
{
@Override
public void run()
{
if (!_isActive)
{
return;
}
try
{
if (!_isRepeating)
{
cancelAndRemove();
}
_quest.notifyEvent(_name, _npc, _player);
}
catch (Exception e)
{
LOGGER.log(Level.SEVERE, "", e);
}
}
}
boolean _isActive = true;
final String _name;
final Quest _quest;
final Npc _npc;
final PlayerInstance _player;
final boolean _isRepeating;
private final ScheduledFuture<?> _scheduler;
private final String _name;
private final Quest _quest;
private final Npc _npc;
private final PlayerInstance _player;
private final boolean _isRepeating;
private ScheduledFuture<?> _scheduler;
public QuestTimer(Quest quest, String name, long time, Npc npc, PlayerInstance player, boolean repeating)
{
_name = name;
_quest = quest;
_player = player;
_name = name;
_npc = npc;
_player = player;
_isRepeating = repeating;
_scheduler = repeating ? ThreadPool.scheduleAtFixedRate(new ScheduleTimerTask(), time, time) : ThreadPool.schedule(new ScheduleTimerTask(), time);
}
public QuestTimer(Quest quest, String name, long time, Npc npc, PlayerInstance player)
{
this(quest, name, time, npc, player, false);
}
public QuestTimer(QuestState qs, String name, long time)
{
this(qs.getQuest(), name, time, null, qs.getPlayer(), false);
}
/**
* Cancel this quest timer.
*/
public void cancel()
{
_isActive = false;
if (_scheduler != null)
if (repeating)
{
_scheduler.cancel(false);
_scheduler = ThreadPool.scheduleAtFixedRate(new ScheduleTimerTask(), time, time); // Prepare auto end task
}
else
{
_scheduler = ThreadPool.schedule(new ScheduleTimerTask(), time); // Prepare auto end task
}
}
/**
* Cancel this quest timer and remove it from the associated quest.
*/
public void cancelAndRemove()
public void cancel()
{
cancel();
if (_scheduler != null)
{
_scheduler.cancel(false);
_scheduler = null;
}
_quest.removeQuestTimer(this);
}
/**
* Compares if this timer matches with the key attributes passed.
* @param quest the quest to which the timer is attached
* @param name the name of the timer
* @param npc the NPC attached to the desired timer (null if no NPC attached)
* @param player the player attached to the desired timer (null if no player attached)
* @return
* public method to compare if this timer matches with the key attributes passed.
* @param quest : Quest instance to which the timer is attached
* @param name : Name of the timer
* @param npc : Npc instance attached to the desired timer (null if no npc attached)
* @param player : Player instance attached to the desired timer (null if no player attached)
* @return boolean
*/
public boolean isMatch(Quest quest, String name, Npc npc, PlayerInstance player)
public boolean equals(Quest quest, String name, Npc npc, PlayerInstance player)
{
if ((quest == null) || (name == null))
if ((quest == null) || (quest != _quest))
{
return false;
}
if ((quest != _quest) || !name.equalsIgnoreCase(_name))
if ((name == null) || !name.equals(_name))
{
return false;
}
return ((npc == _npc) && (player == _player));
return (npc == _npc) && (player == _player);
}
public boolean isActive()
{
return _isActive;
return (_scheduler != null) && !_scheduler.isCancelled() && !_scheduler.isDone();
}
public boolean isRepeating()
@@ -158,4 +118,23 @@ public class QuestTimer
{
return _name;
}
public class ScheduleTimerTask implements Runnable
{
@Override
public void run()
{
if (_scheduler == null)
{
return;
}
if (!_isRepeating)
{
cancel();
}
_quest.notifyEvent(_name, _npc, _player);
}
}
}

View File

@@ -261,7 +261,7 @@ public class AdminQuest implements IAdminCommandHandler
{
for (QuestTimer timer : list)
{
timers += "<tr><td colspan=\"4\"><table width=270 border=0 bgcolor=131210><tr><td width=270><font color=\"LEVEL\">" + timer.getName() + ":</font> <font color=00FF00>Active: " + timer.isActive() + " Repeatable: " + timer.isRepeating() + " Player: " + timer.getPlayer() + " Npc: " + timer.getNpc() + "</font></td></tr></table></td></tr>";
timers += "<tr><td colspan=\"4\"><table width=270 border=0 bgcolor=131210><tr><td width=270><font color=\"LEVEL\">" + timer.toString() + ":</font> <font color=00FF00>Active: " + timer.isActive() + " Repeatable: " + timer.isRepeating() + " Player: " + timer.getPlayer() + " Npc: " + timer.getNpc() + "</font></td></tr></table></td></tr>";
counter++;
if (counter > 10)
{

View File

@@ -332,7 +332,7 @@ public class Quest extends AbstractScript implements IIdentifiable
{
for (QuestTimer timer : timers)
{
if ((timer != null) && timer.isMatch(this, name, npc, player))
if ((timer != null) && timer.equals(this, name, npc, player))
{
return timer;
}
@@ -390,7 +390,7 @@ public class Quest extends AbstractScript implements IIdentifiable
final QuestTimer timer = getQuestTimer(name, npc, player);
if (timer != null)
{
timer.cancelAndRemove();
timer.cancel();
}
}
@@ -403,7 +403,7 @@ public class Quest extends AbstractScript implements IIdentifiable
{
if ((timer != null) && (_questTimers != null))
{
final List<QuestTimer> timers = getQuestTimers().get(timer.getName());
final List<QuestTimer> timers = getQuestTimers().get(timer.toString());
if (timers != null)
{
_writeLock.lock();

View File

@@ -136,31 +136,29 @@ public class QuestState
/**
* @param state the new state of the quest to set
* @return {@code true} if state was changed, {@code false} otherwise
* @see #setState(byte state, boolean saveInDb)
* @see org.l2jmobius.gameserver.model.quest.State
*/
public boolean setState(byte state)
public void setState(byte state)
{
return setState(state, true);
setState(state, true);
}
/**
* Change the state of this quest to the specified value.
* @param state the new state of the quest to set
* @param saveInDb if {@code true}, will save the state change in the database
* @return {@code true} if state was changed, {@code false} otherwise
* @see org.l2jmobius.gameserver.model.quest.State
*/
public boolean setState(byte state, boolean saveInDb)
public void setState(byte state, boolean saveInDb)
{
if (_simulated)
{
return false;
return;
}
if (_state == state)
{
return false;
return;
}
final boolean newQuest = isCreated();
_state = state;
@@ -177,20 +175,18 @@ public class QuestState
}
_player.sendPacket(new QuestList(_player));
return true;
}
/**
* Add parameter used in quests.
* @param var String pointing out the name of the variable for quest
* @param value String pointing out the value of the variable for quest
* @return String (equal to parameter "value")
*/
public String setInternal(String var, String value)
public void setInternal(String var, String value)
{
if (_simulated)
{
return null;
return;
}
if (_vars == null)
@@ -204,16 +200,15 @@ public class QuestState
}
_vars.put(var, value);
return value;
}
public String set(String var, int value)
public void set(String var, int value)
{
if (_simulated)
{
return null;
return;
}
return set(var, Integer.toString(value));
set(var, Integer.toString(value));
}
/**
@@ -229,13 +224,12 @@ public class QuestState
* <ul>
* @param var String indicating the name of the variable for quest
* @param value String indicating the value of the variable for quest
* @return String (equal to parameter "value")
*/
public String set(String var, String value)
public void set(String var, String value)
{
if (_simulated)
{
return null;
return;
}
if (_vars == null)
@@ -279,8 +273,6 @@ public class QuestState
LOGGER.log(Level.WARNING, _player.getName() + ", " + _questName + " cond [" + value + "] is not an integer. Value stored, but no packet was sent: " + e.getMessage(), e);
}
}
return value;
}
/**
@@ -325,20 +317,15 @@ public class QuestState
// case 1: No steps have been skipped so far...
if (completedStateFlags == 0)
{
// check if this step also doesn't skip anything. If so, no further work is needed
// also, in this case, no work is needed if the state is being reset to a smaller value
// in those cases, skip forward to informing the client about the change...
// Check if this step also doesn't skip anything. If so, no further work is needed also, in this case, no work is needed if the state is being reset to a smaller value in those cases, skip forward to informing the client about the change...
// ELSE, if we just now skipped for the first time...prepare the flags!!!
if (cond > (old + 1))
{
// set the most significant bit to 1 (indicates that there exist skipped states)
// also, ensure that the least significant bit is an 1 (the first step is never skipped, no matter
// what the cond says)
// also, ensure that the least significant bit is an 1 (the first step is never skipped, no matter what the cond says)
completedStateFlags = 0x80000001;
// since no flag had been skipped until now, the least significant bits must all
// be set to 1, up until "old" number of bits.
// since no flag had been skipped until now, the least significant bits must all be set to 1, up until "old" number of bits.
completedStateFlags |= (1 << old) - 1;
// now, just set the bit corresponding to the passed cond to 1 (current step)
@@ -347,11 +334,9 @@ public class QuestState
}
}
// case 2: There were exist previously skipped steps
// if this is a push back to a previous step, clear all completion flags ahead
else if (cond < old)
else if (cond < old) // if this is a push back to a previous step, clear all completion flags ahead
{
// note, this also unsets the flag indicating that there exist skips
completedStateFlags &= (1 << cond) - 1;
completedStateFlags &= (1 << cond) - 1; // note, this also unsets the flag indicating that there exist skips
// now, check if this resulted in no steps being skipped any more
if (completedStateFlags == ((1 << cond) - 1))
@@ -361,8 +346,7 @@ public class QuestState
else
{
// set the most significant bit back to 1 again, to correctly indicate that this skips states.
// also, ensure that the least significant bit is an 1 (the first step is never skipped, no matter
// what the cond says)
// also, ensure that the least significant bit is an 1 (the first step is never skipped, no matter what the cond says)
completedStateFlags |= 0x80000001;
set("__compltdStateFlags", String.valueOf(completedStateFlags));
}
@@ -388,18 +372,17 @@ public class QuestState
/**
* Removes a quest variable from the list of existing quest variables.
* @param var the name of the variable to remove
* @return the previous value of the variable or {@code null} if none were found
*/
public String unset(String var)
public void unset(String var)
{
if (_simulated)
{
return null;
return;
}
if (_vars == null)
{
return null;
return;
}
final String old = _vars.remove(var);
@@ -407,7 +390,6 @@ public class QuestState
{
Quest.deleteQuestVarInDb(this, var);
}
return old;
}
/**
@@ -468,22 +450,21 @@ public class QuestState
/**
* Sets the quest state progress ({@code cond}) to the specified step.
* @param value the new value of the quest state progress
* @return this {@link QuestState} object
* @see #set(String var, String value)
* @see #setCond(int, boolean)
*/
public QuestState setCond(int value)
public void setCond(int value)
{
if (_simulated)
{
return null;
return;
}
if (isStarted())
{
set("cond", Integer.toString(value));
}
return this;
return;
}
/**
@@ -529,20 +510,19 @@ public class QuestState
* Sets the quest state progress ({@code cond}) to the specified step.
* @param value the new value of the quest state progress
* @param playQuestMiddle if {@code true}, plays "ItemSound.quest_middle"
* @return this {@link QuestState} object
* @see #setCond(int value)
* @see #set(String var, String value)
*/
public QuestState setCond(int value, boolean playQuestMiddle)
public void setCond(int value, boolean playQuestMiddle)
{
if (_simulated)
{
return null;
return;
}
if (!isStarted())
{
return this;
return;
}
set("cond", String.valueOf(value));
@@ -550,17 +530,15 @@ public class QuestState
{
_player.sendPacket(QuestSound.ITEMSOUND_QUEST_MIDDLE.getPacket());
}
return this;
}
public QuestState setMemoState(int value)
public void setMemoState(int value)
{
if (_simulated)
{
return null;
return;
}
set("memoState", String.valueOf(value));
return this;
}
/**
@@ -598,16 +576,14 @@ public class QuestState
* Sets the memo state ex.
* @param slot the slot where the value will be saved
* @param value the value
* @return this QuestState
*/
public QuestState setMemoStateEx(int slot, int value)
public void setMemoStateEx(int slot, int value)
{
if (_simulated)
{
return null;
return;
}
set("memoStateEx" + slot, String.valueOf(value));
return this;
}
/**
@@ -644,13 +620,12 @@ public class QuestState
/**
* Set condition to 1, state to STARTED and play the "ItemSound.quest_accept".<br>
* Works only if state is CREATED and the quest is not a custom quest.
* @return the newly created {@code QuestState} object
*/
public QuestState startQuest()
public void startQuest()
{
if (_simulated)
{
return null;
return;
}
if (isCreated() && !getQuest().isCustomQuest())
{
@@ -659,23 +634,21 @@ public class QuestState
_player.sendPacket(QuestSound.ITEMSOUND_QUEST_ACCEPT.getPacket());
getQuest().sendNpcLogList(getPlayer());
}
return this;
}
/**
* Finishes the quest and removes all quest items associated with this quest from the player's inventory.<br>
* If {@code type} is {@code QuestType.ONE_TIME}, also removes all other quest data associated with this quest.
* @param type the {@link QuestType} of the quest
* @return this {@link QuestState} object
* @see #exitQuest(QuestType type, boolean playExitQuest)
* @see #exitQuest(boolean repeatable)
* @see #exitQuest(boolean repeatable, boolean playExitQuest)
*/
public QuestState exitQuest(QuestType type)
public void exitQuest(QuestType type)
{
if (_simulated)
{
return null;
return;
}
switch (type)
@@ -697,8 +670,6 @@ public class QuestState
// Notify to scripts
EventDispatcher.getInstance().notifyEventAsync(new OnPlayerQuestComplete(_player, getQuest().getId(), type), _player);
return this;
}
/**
@@ -706,46 +677,43 @@ public class QuestState
* If {@code type} is {@code QuestType.ONE_TIME}, also removes all other quest data associated with this quest.
* @param type the {@link QuestType} of the quest
* @param playExitQuest if {@code true}, plays "ItemSound.quest_finish"
* @return this {@link QuestState} object
* @see #exitQuest(QuestType type)
* @see #exitQuest(boolean repeatable)
* @see #exitQuest(boolean repeatable, boolean playExitQuest)
*/
public QuestState exitQuest(QuestType type, boolean playExitQuest)
public void exitQuest(QuestType type, boolean playExitQuest)
{
if (_simulated)
{
return null;
return;
}
exitQuest(type);
if (playExitQuest)
{
_player.sendPacket(QuestSound.ITEMSOUND_QUEST_FINISH.getPacket());
}
return this;
}
/**
* Finishes the quest and removes all quest items associated with this quest from the player's inventory.<br>
* If {@code repeatable} is set to {@code false}, also removes all other quest data associated with this quest.
* @param repeatable if {@code true}, deletes all data and variables of this quest, otherwise keeps them
* @return this {@link QuestState} object
* @see #exitQuest(QuestType type)
* @see #exitQuest(QuestType type, boolean playExitQuest)
* @see #exitQuest(boolean repeatable, boolean playExitQuest)
*/
private QuestState exitQuest(boolean repeatable)
private void exitQuest(boolean repeatable)
{
if (_simulated)
{
return null;
return;
}
_player.removeNotifyQuestOfDeath(this);
if (!isStarted())
{
return this;
return;
}
// Clean registered quest items
@@ -762,7 +730,6 @@ public class QuestState
setState(State.COMPLETED);
}
_vars = null;
return this;
}
/**
@@ -770,16 +737,15 @@ public class QuestState
* If {@code repeatable} is set to {@code false}, also removes all other quest data associated with this quest.
* @param repeatable if {@code true}, deletes all data and variables of this quest, otherwise keeps them
* @param playExitQuest if {@code true}, plays "ItemSound.quest_finish"
* @return this {@link QuestState} object
* @see #exitQuest(QuestType type)
* @see #exitQuest(QuestType type, boolean playExitQuest)
* @see #exitQuest(boolean repeatable)
*/
public QuestState exitQuest(boolean repeatable, boolean playExitQuest)
public void exitQuest(boolean repeatable, boolean playExitQuest)
{
if (_simulated)
{
return null;
return;
}
exitQuest(repeatable);
@@ -790,7 +756,7 @@ public class QuestState
// Notify to scripts
EventDispatcher.getInstance().notifyEventAsync(new OnPlayerQuestComplete(_player, getQuest().getId(), repeatable ? QuestType.REPEATABLE : QuestType.ONE_TIME), _player);
return this;
return;
}
/**

View File

@@ -17,8 +17,6 @@
package org.l2jmobius.gameserver.model.quest;
import java.util.concurrent.ScheduledFuture;
import java.util.logging.Level;
import java.util.logging.Logger;
import org.l2jmobius.commons.concurrent.ThreadPool;
import org.l2jmobius.gameserver.model.actor.Npc;
@@ -26,106 +24,68 @@ import org.l2jmobius.gameserver.model.actor.instance.PlayerInstance;
public class QuestTimer
{
protected static final Logger LOGGER = Logger.getLogger(QuestTimer.class.getName());
public class ScheduleTimerTask implements Runnable
{
@Override
public void run()
{
if (!_isActive)
{
return;
}
try
{
if (!_isRepeating)
{
cancelAndRemove();
}
_quest.notifyEvent(_name, _npc, _player);
}
catch (Exception e)
{
LOGGER.log(Level.SEVERE, "", e);
}
}
}
boolean _isActive = true;
final String _name;
final Quest _quest;
final Npc _npc;
final PlayerInstance _player;
final boolean _isRepeating;
private final ScheduledFuture<?> _scheduler;
private final String _name;
private final Quest _quest;
private final Npc _npc;
private final PlayerInstance _player;
private final boolean _isRepeating;
private ScheduledFuture<?> _scheduler;
public QuestTimer(Quest quest, String name, long time, Npc npc, PlayerInstance player, boolean repeating)
{
_name = name;
_quest = quest;
_player = player;
_name = name;
_npc = npc;
_player = player;
_isRepeating = repeating;
_scheduler = repeating ? ThreadPool.scheduleAtFixedRate(new ScheduleTimerTask(), time, time) : ThreadPool.schedule(new ScheduleTimerTask(), time);
}
public QuestTimer(Quest quest, String name, long time, Npc npc, PlayerInstance player)
{
this(quest, name, time, npc, player, false);
}
public QuestTimer(QuestState qs, String name, long time)
{
this(qs.getQuest(), name, time, null, qs.getPlayer(), false);
}
/**
* Cancel this quest timer.
*/
public void cancel()
{
_isActive = false;
if (_scheduler != null)
if (repeating)
{
_scheduler.cancel(false);
_scheduler = ThreadPool.scheduleAtFixedRate(new ScheduleTimerTask(), time, time); // Prepare auto end task
}
else
{
_scheduler = ThreadPool.schedule(new ScheduleTimerTask(), time); // Prepare auto end task
}
}
/**
* Cancel this quest timer and remove it from the associated quest.
*/
public void cancelAndRemove()
public void cancel()
{
cancel();
if (_scheduler != null)
{
_scheduler.cancel(false);
_scheduler = null;
}
_quest.removeQuestTimer(this);
}
/**
* Compares if this timer matches with the key attributes passed.
* @param quest the quest to which the timer is attached
* @param name the name of the timer
* @param npc the NPC attached to the desired timer (null if no NPC attached)
* @param player the player attached to the desired timer (null if no player attached)
* @return
* public method to compare if this timer matches with the key attributes passed.
* @param quest : Quest instance to which the timer is attached
* @param name : Name of the timer
* @param npc : Npc instance attached to the desired timer (null if no npc attached)
* @param player : Player instance attached to the desired timer (null if no player attached)
* @return boolean
*/
public boolean isMatch(Quest quest, String name, Npc npc, PlayerInstance player)
public boolean equals(Quest quest, String name, Npc npc, PlayerInstance player)
{
if ((quest == null) || (name == null))
if ((quest == null) || (quest != _quest))
{
return false;
}
if ((quest != _quest) || !name.equalsIgnoreCase(_name))
if ((name == null) || !name.equals(_name))
{
return false;
}
return ((npc == _npc) && (player == _player));
return (npc == _npc) && (player == _player);
}
public boolean isActive()
{
return _isActive;
return (_scheduler != null) && !_scheduler.isCancelled() && !_scheduler.isDone();
}
public boolean isRepeating()
@@ -158,4 +118,23 @@ public class QuestTimer
{
return _name;
}
public class ScheduleTimerTask implements Runnable
{
@Override
public void run()
{
if (_scheduler == null)
{
return;
}
if (!_isRepeating)
{
cancel();
}
_quest.notifyEvent(_name, _npc, _player);
}
}
}

View File

@@ -261,7 +261,7 @@ public class AdminQuest implements IAdminCommandHandler
{
for (QuestTimer timer : list)
{
timers += "<tr><td colspan=\"4\"><table width=270 border=0 bgcolor=131210><tr><td width=270><font color=\"LEVEL\">" + timer.getName() + ":</font> <font color=00FF00>Active: " + timer.isActive() + " Repeatable: " + timer.isRepeating() + " Player: " + timer.getPlayer() + " Npc: " + timer.getNpc() + "</font></td></tr></table></td></tr>";
timers += "<tr><td colspan=\"4\"><table width=270 border=0 bgcolor=131210><tr><td width=270><font color=\"LEVEL\">" + timer.toString() + ":</font> <font color=00FF00>Active: " + timer.isActive() + " Repeatable: " + timer.isRepeating() + " Player: " + timer.getPlayer() + " Npc: " + timer.getNpc() + "</font></td></tr></table></td></tr>";
counter++;
if (counter > 10)
{

View File

@@ -332,7 +332,7 @@ public class Quest extends AbstractScript implements IIdentifiable
{
for (QuestTimer timer : timers)
{
if ((timer != null) && timer.isMatch(this, name, npc, player))
if ((timer != null) && timer.equals(this, name, npc, player))
{
return timer;
}
@@ -390,7 +390,7 @@ public class Quest extends AbstractScript implements IIdentifiable
final QuestTimer timer = getQuestTimer(name, npc, player);
if (timer != null)
{
timer.cancelAndRemove();
timer.cancel();
}
}
@@ -403,7 +403,7 @@ public class Quest extends AbstractScript implements IIdentifiable
{
if ((timer != null) && (_questTimers != null))
{
final List<QuestTimer> timers = getQuestTimers().get(timer.getName());
final List<QuestTimer> timers = getQuestTimers().get(timer.toString());
if (timers != null)
{
_writeLock.lock();

View File

@@ -136,31 +136,29 @@ public class QuestState
/**
* @param state the new state of the quest to set
* @return {@code true} if state was changed, {@code false} otherwise
* @see #setState(byte state, boolean saveInDb)
* @see org.l2jmobius.gameserver.model.quest.State
*/
public boolean setState(byte state)
public void setState(byte state)
{
return setState(state, true);
setState(state, true);
}
/**
* Change the state of this quest to the specified value.
* @param state the new state of the quest to set
* @param saveInDb if {@code true}, will save the state change in the database
* @return {@code true} if state was changed, {@code false} otherwise
* @see org.l2jmobius.gameserver.model.quest.State
*/
public boolean setState(byte state, boolean saveInDb)
public void setState(byte state, boolean saveInDb)
{
if (_simulated)
{
return false;
return;
}
if (_state == state)
{
return false;
return;
}
final boolean newQuest = isCreated();
_state = state;
@@ -177,20 +175,18 @@ public class QuestState
}
_player.sendPacket(new QuestList(_player));
return true;
}
/**
* Add parameter used in quests.
* @param var String pointing out the name of the variable for quest
* @param value String pointing out the value of the variable for quest
* @return String (equal to parameter "value")
*/
public String setInternal(String var, String value)
public void setInternal(String var, String value)
{
if (_simulated)
{
return null;
return;
}
if (_vars == null)
@@ -204,16 +200,15 @@ public class QuestState
}
_vars.put(var, value);
return value;
}
public String set(String var, int value)
public void set(String var, int value)
{
if (_simulated)
{
return null;
return;
}
return set(var, Integer.toString(value));
set(var, Integer.toString(value));
}
/**
@@ -229,13 +224,12 @@ public class QuestState
* <ul>
* @param var String indicating the name of the variable for quest
* @param value String indicating the value of the variable for quest
* @return String (equal to parameter "value")
*/
public String set(String var, String value)
public void set(String var, String value)
{
if (_simulated)
{
return null;
return;
}
if (_vars == null)
@@ -279,8 +273,6 @@ public class QuestState
LOGGER.log(Level.WARNING, _player.getName() + ", " + _questName + " cond [" + value + "] is not an integer. Value stored, but no packet was sent: " + e.getMessage(), e);
}
}
return value;
}
/**
@@ -325,20 +317,15 @@ public class QuestState
// case 1: No steps have been skipped so far...
if (completedStateFlags == 0)
{
// check if this step also doesn't skip anything. If so, no further work is needed
// also, in this case, no work is needed if the state is being reset to a smaller value
// in those cases, skip forward to informing the client about the change...
// Check if this step also doesn't skip anything. If so, no further work is needed also, in this case, no work is needed if the state is being reset to a smaller value in those cases, skip forward to informing the client about the change...
// ELSE, if we just now skipped for the first time...prepare the flags!!!
if (cond > (old + 1))
{
// set the most significant bit to 1 (indicates that there exist skipped states)
// also, ensure that the least significant bit is an 1 (the first step is never skipped, no matter
// what the cond says)
// also, ensure that the least significant bit is an 1 (the first step is never skipped, no matter what the cond says)
completedStateFlags = 0x80000001;
// since no flag had been skipped until now, the least significant bits must all
// be set to 1, up until "old" number of bits.
// since no flag had been skipped until now, the least significant bits must all be set to 1, up until "old" number of bits.
completedStateFlags |= (1 << old) - 1;
// now, just set the bit corresponding to the passed cond to 1 (current step)
@@ -347,11 +334,9 @@ public class QuestState
}
}
// case 2: There were exist previously skipped steps
// if this is a push back to a previous step, clear all completion flags ahead
else if (cond < old)
else if (cond < old) // if this is a push back to a previous step, clear all completion flags ahead
{
// note, this also unsets the flag indicating that there exist skips
completedStateFlags &= (1 << cond) - 1;
completedStateFlags &= (1 << cond) - 1; // note, this also unsets the flag indicating that there exist skips
// now, check if this resulted in no steps being skipped any more
if (completedStateFlags == ((1 << cond) - 1))
@@ -361,8 +346,7 @@ public class QuestState
else
{
// set the most significant bit back to 1 again, to correctly indicate that this skips states.
// also, ensure that the least significant bit is an 1 (the first step is never skipped, no matter
// what the cond says)
// also, ensure that the least significant bit is an 1 (the first step is never skipped, no matter what the cond says)
completedStateFlags |= 0x80000001;
set("__compltdStateFlags", String.valueOf(completedStateFlags));
}
@@ -388,18 +372,17 @@ public class QuestState
/**
* Removes a quest variable from the list of existing quest variables.
* @param var the name of the variable to remove
* @return the previous value of the variable or {@code null} if none were found
*/
public String unset(String var)
public void unset(String var)
{
if (_simulated)
{
return null;
return;
}
if (_vars == null)
{
return null;
return;
}
final String old = _vars.remove(var);
@@ -407,7 +390,6 @@ public class QuestState
{
Quest.deleteQuestVarInDb(this, var);
}
return old;
}
/**
@@ -468,22 +450,21 @@ public class QuestState
/**
* Sets the quest state progress ({@code cond}) to the specified step.
* @param value the new value of the quest state progress
* @return this {@link QuestState} object
* @see #set(String var, String value)
* @see #setCond(int, boolean)
*/
public QuestState setCond(int value)
public void setCond(int value)
{
if (_simulated)
{
return null;
return;
}
if (isStarted())
{
set("cond", Integer.toString(value));
}
return this;
return;
}
/**
@@ -529,20 +510,19 @@ public class QuestState
* Sets the quest state progress ({@code cond}) to the specified step.
* @param value the new value of the quest state progress
* @param playQuestMiddle if {@code true}, plays "ItemSound.quest_middle"
* @return this {@link QuestState} object
* @see #setCond(int value)
* @see #set(String var, String value)
*/
public QuestState setCond(int value, boolean playQuestMiddle)
public void setCond(int value, boolean playQuestMiddle)
{
if (_simulated)
{
return null;
return;
}
if (!isStarted())
{
return this;
return;
}
set("cond", String.valueOf(value));
@@ -550,17 +530,15 @@ public class QuestState
{
_player.sendPacket(QuestSound.ITEMSOUND_QUEST_MIDDLE.getPacket());
}
return this;
}
public QuestState setMemoState(int value)
public void setMemoState(int value)
{
if (_simulated)
{
return null;
return;
}
set("memoState", String.valueOf(value));
return this;
}
/**
@@ -598,16 +576,14 @@ public class QuestState
* Sets the memo state ex.
* @param slot the slot where the value will be saved
* @param value the value
* @return this QuestState
*/
public QuestState setMemoStateEx(int slot, int value)
public void setMemoStateEx(int slot, int value)
{
if (_simulated)
{
return null;
return;
}
set("memoStateEx" + slot, String.valueOf(value));
return this;
}
/**
@@ -644,13 +620,12 @@ public class QuestState
/**
* Set condition to 1, state to STARTED and play the "ItemSound.quest_accept".<br>
* Works only if state is CREATED and the quest is not a custom quest.
* @return the newly created {@code QuestState} object
*/
public QuestState startQuest()
public void startQuest()
{
if (_simulated)
{
return null;
return;
}
if (isCreated() && !getQuest().isCustomQuest())
{
@@ -659,23 +634,21 @@ public class QuestState
_player.sendPacket(QuestSound.ITEMSOUND_QUEST_ACCEPT.getPacket());
getQuest().sendNpcLogList(getPlayer());
}
return this;
}
/**
* Finishes the quest and removes all quest items associated with this quest from the player's inventory.<br>
* If {@code type} is {@code QuestType.ONE_TIME}, also removes all other quest data associated with this quest.
* @param type the {@link QuestType} of the quest
* @return this {@link QuestState} object
* @see #exitQuest(QuestType type, boolean playExitQuest)
* @see #exitQuest(boolean repeatable)
* @see #exitQuest(boolean repeatable, boolean playExitQuest)
*/
public QuestState exitQuest(QuestType type)
public void exitQuest(QuestType type)
{
if (_simulated)
{
return null;
return;
}
switch (type)
@@ -697,8 +670,6 @@ public class QuestState
// Notify to scripts
EventDispatcher.getInstance().notifyEventAsync(new OnPlayerQuestComplete(_player, getQuest().getId(), type), _player);
return this;
}
/**
@@ -706,46 +677,43 @@ public class QuestState
* If {@code type} is {@code QuestType.ONE_TIME}, also removes all other quest data associated with this quest.
* @param type the {@link QuestType} of the quest
* @param playExitQuest if {@code true}, plays "ItemSound.quest_finish"
* @return this {@link QuestState} object
* @see #exitQuest(QuestType type)
* @see #exitQuest(boolean repeatable)
* @see #exitQuest(boolean repeatable, boolean playExitQuest)
*/
public QuestState exitQuest(QuestType type, boolean playExitQuest)
public void exitQuest(QuestType type, boolean playExitQuest)
{
if (_simulated)
{
return null;
return;
}
exitQuest(type);
if (playExitQuest)
{
_player.sendPacket(QuestSound.ITEMSOUND_QUEST_FINISH.getPacket());
}
return this;
}
/**
* Finishes the quest and removes all quest items associated with this quest from the player's inventory.<br>
* If {@code repeatable} is set to {@code false}, also removes all other quest data associated with this quest.
* @param repeatable if {@code true}, deletes all data and variables of this quest, otherwise keeps them
* @return this {@link QuestState} object
* @see #exitQuest(QuestType type)
* @see #exitQuest(QuestType type, boolean playExitQuest)
* @see #exitQuest(boolean repeatable, boolean playExitQuest)
*/
private QuestState exitQuest(boolean repeatable)
private void exitQuest(boolean repeatable)
{
if (_simulated)
{
return null;
return;
}
_player.removeNotifyQuestOfDeath(this);
if (!isStarted())
{
return this;
return;
}
// Clean registered quest items
@@ -762,7 +730,6 @@ public class QuestState
setState(State.COMPLETED);
}
_vars = null;
return this;
}
/**
@@ -770,16 +737,15 @@ public class QuestState
* If {@code repeatable} is set to {@code false}, also removes all other quest data associated with this quest.
* @param repeatable if {@code true}, deletes all data and variables of this quest, otherwise keeps them
* @param playExitQuest if {@code true}, plays "ItemSound.quest_finish"
* @return this {@link QuestState} object
* @see #exitQuest(QuestType type)
* @see #exitQuest(QuestType type, boolean playExitQuest)
* @see #exitQuest(boolean repeatable)
*/
public QuestState exitQuest(boolean repeatable, boolean playExitQuest)
public void exitQuest(boolean repeatable, boolean playExitQuest)
{
if (_simulated)
{
return null;
return;
}
exitQuest(repeatable);
@@ -790,7 +756,7 @@ public class QuestState
// Notify to scripts
EventDispatcher.getInstance().notifyEventAsync(new OnPlayerQuestComplete(_player, getQuest().getId(), repeatable ? QuestType.REPEATABLE : QuestType.ONE_TIME), _player);
return this;
return;
}
/**

View File

@@ -17,8 +17,6 @@
package org.l2jmobius.gameserver.model.quest;
import java.util.concurrent.ScheduledFuture;
import java.util.logging.Level;
import java.util.logging.Logger;
import org.l2jmobius.commons.concurrent.ThreadPool;
import org.l2jmobius.gameserver.model.actor.Npc;
@@ -26,106 +24,68 @@ import org.l2jmobius.gameserver.model.actor.instance.PlayerInstance;
public class QuestTimer
{
protected static final Logger LOGGER = Logger.getLogger(QuestTimer.class.getName());
public class ScheduleTimerTask implements Runnable
{
@Override
public void run()
{
if (!_isActive)
{
return;
}
try
{
if (!_isRepeating)
{
cancelAndRemove();
}
_quest.notifyEvent(_name, _npc, _player);
}
catch (Exception e)
{
LOGGER.log(Level.SEVERE, "", e);
}
}
}
boolean _isActive = true;
final String _name;
final Quest _quest;
final Npc _npc;
final PlayerInstance _player;
final boolean _isRepeating;
private final ScheduledFuture<?> _scheduler;
private final String _name;
private final Quest _quest;
private final Npc _npc;
private final PlayerInstance _player;
private final boolean _isRepeating;
private ScheduledFuture<?> _scheduler;
public QuestTimer(Quest quest, String name, long time, Npc npc, PlayerInstance player, boolean repeating)
{
_name = name;
_quest = quest;
_player = player;
_name = name;
_npc = npc;
_player = player;
_isRepeating = repeating;
_scheduler = repeating ? ThreadPool.scheduleAtFixedRate(new ScheduleTimerTask(), time, time) : ThreadPool.schedule(new ScheduleTimerTask(), time);
}
public QuestTimer(Quest quest, String name, long time, Npc npc, PlayerInstance player)
{
this(quest, name, time, npc, player, false);
}
public QuestTimer(QuestState qs, String name, long time)
{
this(qs.getQuest(), name, time, null, qs.getPlayer(), false);
}
/**
* Cancel this quest timer.
*/
public void cancel()
{
_isActive = false;
if (_scheduler != null)
if (repeating)
{
_scheduler.cancel(false);
_scheduler = ThreadPool.scheduleAtFixedRate(new ScheduleTimerTask(), time, time); // Prepare auto end task
}
else
{
_scheduler = ThreadPool.schedule(new ScheduleTimerTask(), time); // Prepare auto end task
}
}
/**
* Cancel this quest timer and remove it from the associated quest.
*/
public void cancelAndRemove()
public void cancel()
{
cancel();
if (_scheduler != null)
{
_scheduler.cancel(false);
_scheduler = null;
}
_quest.removeQuestTimer(this);
}
/**
* Compares if this timer matches with the key attributes passed.
* @param quest the quest to which the timer is attached
* @param name the name of the timer
* @param npc the NPC attached to the desired timer (null if no NPC attached)
* @param player the player attached to the desired timer (null if no player attached)
* @return
* public method to compare if this timer matches with the key attributes passed.
* @param quest : Quest instance to which the timer is attached
* @param name : Name of the timer
* @param npc : Npc instance attached to the desired timer (null if no npc attached)
* @param player : Player instance attached to the desired timer (null if no player attached)
* @return boolean
*/
public boolean isMatch(Quest quest, String name, Npc npc, PlayerInstance player)
public boolean equals(Quest quest, String name, Npc npc, PlayerInstance player)
{
if ((quest == null) || (name == null))
if ((quest == null) || (quest != _quest))
{
return false;
}
if ((quest != _quest) || !name.equalsIgnoreCase(_name))
if ((name == null) || !name.equals(_name))
{
return false;
}
return ((npc == _npc) && (player == _player));
return (npc == _npc) && (player == _player);
}
public boolean isActive()
{
return _isActive;
return (_scheduler != null) && !_scheduler.isCancelled() && !_scheduler.isDone();
}
public boolean isRepeating()
@@ -158,4 +118,23 @@ public class QuestTimer
{
return _name;
}
public class ScheduleTimerTask implements Runnable
{
@Override
public void run()
{
if (_scheduler == null)
{
return;
}
if (!_isRepeating)
{
cancel();
}
_quest.notifyEvent(_name, _npc, _player);
}
}
}

View File

@@ -261,7 +261,7 @@ public class AdminQuest implements IAdminCommandHandler
{
for (QuestTimer timer : list)
{
timers += "<tr><td colspan=\"4\"><table width=270 border=0 bgcolor=131210><tr><td width=270><font color=\"LEVEL\">" + timer.getName() + ":</font> <font color=00FF00>Active: " + timer.isActive() + " Repeatable: " + timer.isRepeating() + " Player: " + timer.getPlayer() + " Npc: " + timer.getNpc() + "</font></td></tr></table></td></tr>";
timers += "<tr><td colspan=\"4\"><table width=270 border=0 bgcolor=131210><tr><td width=270><font color=\"LEVEL\">" + timer.toString() + ":</font> <font color=00FF00>Active: " + timer.isActive() + " Repeatable: " + timer.isRepeating() + " Player: " + timer.getPlayer() + " Npc: " + timer.getNpc() + "</font></td></tr></table></td></tr>";
counter++;
if (counter > 10)
{

View File

@@ -332,7 +332,7 @@ public class Quest extends AbstractScript implements IIdentifiable
{
for (QuestTimer timer : timers)
{
if ((timer != null) && timer.isMatch(this, name, npc, player))
if ((timer != null) && timer.equals(this, name, npc, player))
{
return timer;
}
@@ -390,7 +390,7 @@ public class Quest extends AbstractScript implements IIdentifiable
final QuestTimer timer = getQuestTimer(name, npc, player);
if (timer != null)
{
timer.cancelAndRemove();
timer.cancel();
}
}
@@ -403,7 +403,7 @@ public class Quest extends AbstractScript implements IIdentifiable
{
if ((timer != null) && (_questTimers != null))
{
final List<QuestTimer> timers = getQuestTimers().get(timer.getName());
final List<QuestTimer> timers = getQuestTimers().get(timer.toString());
if (timers != null)
{
_writeLock.lock();

View File

@@ -136,31 +136,29 @@ public class QuestState
/**
* @param state the new state of the quest to set
* @return {@code true} if state was changed, {@code false} otherwise
* @see #setState(byte state, boolean saveInDb)
* @see org.l2jmobius.gameserver.model.quest.State
*/
public boolean setState(byte state)
public void setState(byte state)
{
return setState(state, true);
setState(state, true);
}
/**
* Change the state of this quest to the specified value.
* @param state the new state of the quest to set
* @param saveInDb if {@code true}, will save the state change in the database
* @return {@code true} if state was changed, {@code false} otherwise
* @see org.l2jmobius.gameserver.model.quest.State
*/
public boolean setState(byte state, boolean saveInDb)
public void setState(byte state, boolean saveInDb)
{
if (_simulated)
{
return false;
return;
}
if (_state == state)
{
return false;
return;
}
final boolean newQuest = isCreated();
_state = state;
@@ -177,20 +175,18 @@ public class QuestState
}
_player.sendPacket(new QuestList(_player));
return true;
}
/**
* Add parameter used in quests.
* @param var String pointing out the name of the variable for quest
* @param value String pointing out the value of the variable for quest
* @return String (equal to parameter "value")
*/
public String setInternal(String var, String value)
public void setInternal(String var, String value)
{
if (_simulated)
{
return null;
return;
}
if (_vars == null)
@@ -204,16 +200,15 @@ public class QuestState
}
_vars.put(var, value);
return value;
}
public String set(String var, int value)
public void set(String var, int value)
{
if (_simulated)
{
return null;
return;
}
return set(var, Integer.toString(value));
set(var, Integer.toString(value));
}
/**
@@ -229,13 +224,12 @@ public class QuestState
* <ul>
* @param var String indicating the name of the variable for quest
* @param value String indicating the value of the variable for quest
* @return String (equal to parameter "value")
*/
public String set(String var, String value)
public void set(String var, String value)
{
if (_simulated)
{
return null;
return;
}
if (_vars == null)
@@ -279,8 +273,6 @@ public class QuestState
LOGGER.log(Level.WARNING, _player.getName() + ", " + _questName + " cond [" + value + "] is not an integer. Value stored, but no packet was sent: " + e.getMessage(), e);
}
}
return value;
}
/**
@@ -325,20 +317,15 @@ public class QuestState
// case 1: No steps have been skipped so far...
if (completedStateFlags == 0)
{
// check if this step also doesn't skip anything. If so, no further work is needed
// also, in this case, no work is needed if the state is being reset to a smaller value
// in those cases, skip forward to informing the client about the change...
// Check if this step also doesn't skip anything. If so, no further work is needed also, in this case, no work is needed if the state is being reset to a smaller value in those cases, skip forward to informing the client about the change...
// ELSE, if we just now skipped for the first time...prepare the flags!!!
if (cond > (old + 1))
{
// set the most significant bit to 1 (indicates that there exist skipped states)
// also, ensure that the least significant bit is an 1 (the first step is never skipped, no matter
// what the cond says)
// also, ensure that the least significant bit is an 1 (the first step is never skipped, no matter what the cond says)
completedStateFlags = 0x80000001;
// since no flag had been skipped until now, the least significant bits must all
// be set to 1, up until "old" number of bits.
// since no flag had been skipped until now, the least significant bits must all be set to 1, up until "old" number of bits.
completedStateFlags |= (1 << old) - 1;
// now, just set the bit corresponding to the passed cond to 1 (current step)
@@ -347,11 +334,9 @@ public class QuestState
}
}
// case 2: There were exist previously skipped steps
// if this is a push back to a previous step, clear all completion flags ahead
else if (cond < old)
else if (cond < old) // if this is a push back to a previous step, clear all completion flags ahead
{
// note, this also unsets the flag indicating that there exist skips
completedStateFlags &= (1 << cond) - 1;
completedStateFlags &= (1 << cond) - 1; // note, this also unsets the flag indicating that there exist skips
// now, check if this resulted in no steps being skipped any more
if (completedStateFlags == ((1 << cond) - 1))
@@ -361,8 +346,7 @@ public class QuestState
else
{
// set the most significant bit back to 1 again, to correctly indicate that this skips states.
// also, ensure that the least significant bit is an 1 (the first step is never skipped, no matter
// what the cond says)
// also, ensure that the least significant bit is an 1 (the first step is never skipped, no matter what the cond says)
completedStateFlags |= 0x80000001;
set("__compltdStateFlags", String.valueOf(completedStateFlags));
}
@@ -388,18 +372,17 @@ public class QuestState
/**
* Removes a quest variable from the list of existing quest variables.
* @param var the name of the variable to remove
* @return the previous value of the variable or {@code null} if none were found
*/
public String unset(String var)
public void unset(String var)
{
if (_simulated)
{
return null;
return;
}
if (_vars == null)
{
return null;
return;
}
final String old = _vars.remove(var);
@@ -407,7 +390,6 @@ public class QuestState
{
Quest.deleteQuestVarInDb(this, var);
}
return old;
}
/**
@@ -468,22 +450,21 @@ public class QuestState
/**
* Sets the quest state progress ({@code cond}) to the specified step.
* @param value the new value of the quest state progress
* @return this {@link QuestState} object
* @see #set(String var, String value)
* @see #setCond(int, boolean)
*/
public QuestState setCond(int value)
public void setCond(int value)
{
if (_simulated)
{
return null;
return;
}
if (isStarted())
{
set("cond", Integer.toString(value));
}
return this;
return;
}
/**
@@ -529,20 +510,19 @@ public class QuestState
* Sets the quest state progress ({@code cond}) to the specified step.
* @param value the new value of the quest state progress
* @param playQuestMiddle if {@code true}, plays "ItemSound.quest_middle"
* @return this {@link QuestState} object
* @see #setCond(int value)
* @see #set(String var, String value)
*/
public QuestState setCond(int value, boolean playQuestMiddle)
public void setCond(int value, boolean playQuestMiddle)
{
if (_simulated)
{
return null;
return;
}
if (!isStarted())
{
return this;
return;
}
set("cond", String.valueOf(value));
@@ -550,17 +530,15 @@ public class QuestState
{
_player.sendPacket(QuestSound.ITEMSOUND_QUEST_MIDDLE.getPacket());
}
return this;
}
public QuestState setMemoState(int value)
public void setMemoState(int value)
{
if (_simulated)
{
return null;
return;
}
set("memoState", String.valueOf(value));
return this;
}
/**
@@ -598,16 +576,14 @@ public class QuestState
* Sets the memo state ex.
* @param slot the slot where the value will be saved
* @param value the value
* @return this QuestState
*/
public QuestState setMemoStateEx(int slot, int value)
public void setMemoStateEx(int slot, int value)
{
if (_simulated)
{
return null;
return;
}
set("memoStateEx" + slot, String.valueOf(value));
return this;
}
/**
@@ -644,13 +620,12 @@ public class QuestState
/**
* Set condition to 1, state to STARTED and play the "ItemSound.quest_accept".<br>
* Works only if state is CREATED and the quest is not a custom quest.
* @return the newly created {@code QuestState} object
*/
public QuestState startQuest()
public void startQuest()
{
if (_simulated)
{
return null;
return;
}
if (isCreated() && !getQuest().isCustomQuest())
{
@@ -659,23 +634,21 @@ public class QuestState
_player.sendPacket(QuestSound.ITEMSOUND_QUEST_ACCEPT.getPacket());
getQuest().sendNpcLogList(getPlayer());
}
return this;
}
/**
* Finishes the quest and removes all quest items associated with this quest from the player's inventory.<br>
* If {@code type} is {@code QuestType.ONE_TIME}, also removes all other quest data associated with this quest.
* @param type the {@link QuestType} of the quest
* @return this {@link QuestState} object
* @see #exitQuest(QuestType type, boolean playExitQuest)
* @see #exitQuest(boolean repeatable)
* @see #exitQuest(boolean repeatable, boolean playExitQuest)
*/
public QuestState exitQuest(QuestType type)
public void exitQuest(QuestType type)
{
if (_simulated)
{
return null;
return;
}
switch (type)
@@ -697,8 +670,6 @@ public class QuestState
// Notify to scripts
EventDispatcher.getInstance().notifyEventAsync(new OnPlayerQuestComplete(_player, getQuest().getId(), type), _player);
return this;
}
/**
@@ -706,46 +677,43 @@ public class QuestState
* If {@code type} is {@code QuestType.ONE_TIME}, also removes all other quest data associated with this quest.
* @param type the {@link QuestType} of the quest
* @param playExitQuest if {@code true}, plays "ItemSound.quest_finish"
* @return this {@link QuestState} object
* @see #exitQuest(QuestType type)
* @see #exitQuest(boolean repeatable)
* @see #exitQuest(boolean repeatable, boolean playExitQuest)
*/
public QuestState exitQuest(QuestType type, boolean playExitQuest)
public void exitQuest(QuestType type, boolean playExitQuest)
{
if (_simulated)
{
return null;
return;
}
exitQuest(type);
if (playExitQuest)
{
_player.sendPacket(QuestSound.ITEMSOUND_QUEST_FINISH.getPacket());
}
return this;
}
/**
* Finishes the quest and removes all quest items associated with this quest from the player's inventory.<br>
* If {@code repeatable} is set to {@code false}, also removes all other quest data associated with this quest.
* @param repeatable if {@code true}, deletes all data and variables of this quest, otherwise keeps them
* @return this {@link QuestState} object
* @see #exitQuest(QuestType type)
* @see #exitQuest(QuestType type, boolean playExitQuest)
* @see #exitQuest(boolean repeatable, boolean playExitQuest)
*/
private QuestState exitQuest(boolean repeatable)
private void exitQuest(boolean repeatable)
{
if (_simulated)
{
return null;
return;
}
_player.removeNotifyQuestOfDeath(this);
if (!isStarted())
{
return this;
return;
}
// Clean registered quest items
@@ -762,7 +730,6 @@ public class QuestState
setState(State.COMPLETED);
}
_vars = null;
return this;
}
/**
@@ -770,16 +737,15 @@ public class QuestState
* If {@code repeatable} is set to {@code false}, also removes all other quest data associated with this quest.
* @param repeatable if {@code true}, deletes all data and variables of this quest, otherwise keeps them
* @param playExitQuest if {@code true}, plays "ItemSound.quest_finish"
* @return this {@link QuestState} object
* @see #exitQuest(QuestType type)
* @see #exitQuest(QuestType type, boolean playExitQuest)
* @see #exitQuest(boolean repeatable)
*/
public QuestState exitQuest(boolean repeatable, boolean playExitQuest)
public void exitQuest(boolean repeatable, boolean playExitQuest)
{
if (_simulated)
{
return null;
return;
}
exitQuest(repeatable);
@@ -790,7 +756,7 @@ public class QuestState
// Notify to scripts
EventDispatcher.getInstance().notifyEventAsync(new OnPlayerQuestComplete(_player, getQuest().getId(), repeatable ? QuestType.REPEATABLE : QuestType.ONE_TIME), _player);
return this;
return;
}
/**

View File

@@ -17,8 +17,6 @@
package org.l2jmobius.gameserver.model.quest;
import java.util.concurrent.ScheduledFuture;
import java.util.logging.Level;
import java.util.logging.Logger;
import org.l2jmobius.commons.concurrent.ThreadPool;
import org.l2jmobius.gameserver.model.actor.Npc;
@@ -26,106 +24,68 @@ import org.l2jmobius.gameserver.model.actor.instance.PlayerInstance;
public class QuestTimer
{
protected static final Logger LOGGER = Logger.getLogger(QuestTimer.class.getName());
public class ScheduleTimerTask implements Runnable
{
@Override
public void run()
{
if (!_isActive)
{
return;
}
try
{
if (!_isRepeating)
{
cancelAndRemove();
}
_quest.notifyEvent(_name, _npc, _player);
}
catch (Exception e)
{
LOGGER.log(Level.SEVERE, "", e);
}
}
}
boolean _isActive = true;
final String _name;
final Quest _quest;
final Npc _npc;
final PlayerInstance _player;
final boolean _isRepeating;
private final ScheduledFuture<?> _scheduler;
private final String _name;
private final Quest _quest;
private final Npc _npc;
private final PlayerInstance _player;
private final boolean _isRepeating;
private ScheduledFuture<?> _scheduler;
public QuestTimer(Quest quest, String name, long time, Npc npc, PlayerInstance player, boolean repeating)
{
_name = name;
_quest = quest;
_player = player;
_name = name;
_npc = npc;
_player = player;
_isRepeating = repeating;
_scheduler = repeating ? ThreadPool.scheduleAtFixedRate(new ScheduleTimerTask(), time, time) : ThreadPool.schedule(new ScheduleTimerTask(), time);
}
public QuestTimer(Quest quest, String name, long time, Npc npc, PlayerInstance player)
{
this(quest, name, time, npc, player, false);
}
public QuestTimer(QuestState qs, String name, long time)
{
this(qs.getQuest(), name, time, null, qs.getPlayer(), false);
}
/**
* Cancel this quest timer.
*/
public void cancel()
{
_isActive = false;
if (_scheduler != null)
if (repeating)
{
_scheduler.cancel(false);
_scheduler = ThreadPool.scheduleAtFixedRate(new ScheduleTimerTask(), time, time); // Prepare auto end task
}
else
{
_scheduler = ThreadPool.schedule(new ScheduleTimerTask(), time); // Prepare auto end task
}
}
/**
* Cancel this quest timer and remove it from the associated quest.
*/
public void cancelAndRemove()
public void cancel()
{
cancel();
if (_scheduler != null)
{
_scheduler.cancel(false);
_scheduler = null;
}
_quest.removeQuestTimer(this);
}
/**
* Compares if this timer matches with the key attributes passed.
* @param quest the quest to which the timer is attached
* @param name the name of the timer
* @param npc the NPC attached to the desired timer (null if no NPC attached)
* @param player the player attached to the desired timer (null if no player attached)
* @return
* public method to compare if this timer matches with the key attributes passed.
* @param quest : Quest instance to which the timer is attached
* @param name : Name of the timer
* @param npc : Npc instance attached to the desired timer (null if no npc attached)
* @param player : Player instance attached to the desired timer (null if no player attached)
* @return boolean
*/
public boolean isMatch(Quest quest, String name, Npc npc, PlayerInstance player)
public boolean equals(Quest quest, String name, Npc npc, PlayerInstance player)
{
if ((quest == null) || (name == null))
if ((quest == null) || (quest != _quest))
{
return false;
}
if ((quest != _quest) || !name.equalsIgnoreCase(_name))
if ((name == null) || !name.equals(_name))
{
return false;
}
return ((npc == _npc) && (player == _player));
return (npc == _npc) && (player == _player);
}
public boolean isActive()
{
return _isActive;
return (_scheduler != null) && !_scheduler.isCancelled() && !_scheduler.isDone();
}
public boolean isRepeating()
@@ -158,4 +118,23 @@ public class QuestTimer
{
return _name;
}
public class ScheduleTimerTask implements Runnable
{
@Override
public void run()
{
if (_scheduler == null)
{
return;
}
if (!_isRepeating)
{
cancel();
}
_quest.notifyEvent(_name, _npc, _player);
}
}
}

View File

@@ -261,7 +261,7 @@ public class AdminQuest implements IAdminCommandHandler
{
for (QuestTimer timer : list)
{
timers += "<tr><td colspan=\"4\"><table width=270 border=0 bgcolor=131210><tr><td width=270><font color=\"LEVEL\">" + timer.getName() + ":</font> <font color=00FF00>Active: " + timer.isActive() + " Repeatable: " + timer.isRepeating() + " Player: " + timer.getPlayer() + " Npc: " + timer.getNpc() + "</font></td></tr></table></td></tr>";
timers += "<tr><td colspan=\"4\"><table width=270 border=0 bgcolor=131210><tr><td width=270><font color=\"LEVEL\">" + timer.toString() + ":</font> <font color=00FF00>Active: " + timer.isActive() + " Repeatable: " + timer.isRepeating() + " Player: " + timer.getPlayer() + " Npc: " + timer.getNpc() + "</font></td></tr></table></td></tr>";
counter++;
if (counter > 10)
{

View File

@@ -332,7 +332,7 @@ public class Quest extends AbstractScript implements IIdentifiable
{
for (QuestTimer timer : timers)
{
if ((timer != null) && timer.isMatch(this, name, npc, player))
if ((timer != null) && timer.equals(this, name, npc, player))
{
return timer;
}
@@ -390,7 +390,7 @@ public class Quest extends AbstractScript implements IIdentifiable
final QuestTimer timer = getQuestTimer(name, npc, player);
if (timer != null)
{
timer.cancelAndRemove();
timer.cancel();
}
}
@@ -403,7 +403,7 @@ public class Quest extends AbstractScript implements IIdentifiable
{
if ((timer != null) && (_questTimers != null))
{
final List<QuestTimer> timers = getQuestTimers().get(timer.getName());
final List<QuestTimer> timers = getQuestTimers().get(timer.toString());
if (timers != null)
{
_writeLock.lock();

View File

@@ -136,31 +136,29 @@ public class QuestState
/**
* @param state the new state of the quest to set
* @return {@code true} if state was changed, {@code false} otherwise
* @see #setState(byte state, boolean saveInDb)
* @see org.l2jmobius.gameserver.model.quest.State
*/
public boolean setState(byte state)
public void setState(byte state)
{
return setState(state, true);
setState(state, true);
}
/**
* Change the state of this quest to the specified value.
* @param state the new state of the quest to set
* @param saveInDb if {@code true}, will save the state change in the database
* @return {@code true} if state was changed, {@code false} otherwise
* @see org.l2jmobius.gameserver.model.quest.State
*/
public boolean setState(byte state, boolean saveInDb)
public void setState(byte state, boolean saveInDb)
{
if (_simulated)
{
return false;
return;
}
if (_state == state)
{
return false;
return;
}
final boolean newQuest = isCreated();
_state = state;
@@ -177,20 +175,18 @@ public class QuestState
}
_player.sendPacket(new QuestList(_player));
return true;
}
/**
* Add parameter used in quests.
* @param var String pointing out the name of the variable for quest
* @param value String pointing out the value of the variable for quest
* @return String (equal to parameter "value")
*/
public String setInternal(String var, String value)
public void setInternal(String var, String value)
{
if (_simulated)
{
return null;
return;
}
if (_vars == null)
@@ -204,16 +200,15 @@ public class QuestState
}
_vars.put(var, value);
return value;
}
public String set(String var, int value)
public void set(String var, int value)
{
if (_simulated)
{
return null;
return;
}
return set(var, Integer.toString(value));
set(var, Integer.toString(value));
}
/**
@@ -229,13 +224,12 @@ public class QuestState
* <ul>
* @param var String indicating the name of the variable for quest
* @param value String indicating the value of the variable for quest
* @return String (equal to parameter "value")
*/
public String set(String var, String value)
public void set(String var, String value)
{
if (_simulated)
{
return null;
return;
}
if (_vars == null)
@@ -279,8 +273,6 @@ public class QuestState
LOGGER.log(Level.WARNING, _player.getName() + ", " + _questName + " cond [" + value + "] is not an integer. Value stored, but no packet was sent: " + e.getMessage(), e);
}
}
return value;
}
/**
@@ -325,20 +317,15 @@ public class QuestState
// case 1: No steps have been skipped so far...
if (completedStateFlags == 0)
{
// check if this step also doesn't skip anything. If so, no further work is needed
// also, in this case, no work is needed if the state is being reset to a smaller value
// in those cases, skip forward to informing the client about the change...
// Check if this step also doesn't skip anything. If so, no further work is needed also, in this case, no work is needed if the state is being reset to a smaller value in those cases, skip forward to informing the client about the change...
// ELSE, if we just now skipped for the first time...prepare the flags!!!
if (cond > (old + 1))
{
// set the most significant bit to 1 (indicates that there exist skipped states)
// also, ensure that the least significant bit is an 1 (the first step is never skipped, no matter
// what the cond says)
// also, ensure that the least significant bit is an 1 (the first step is never skipped, no matter what the cond says)
completedStateFlags = 0x80000001;
// since no flag had been skipped until now, the least significant bits must all
// be set to 1, up until "old" number of bits.
// since no flag had been skipped until now, the least significant bits must all be set to 1, up until "old" number of bits.
completedStateFlags |= (1 << old) - 1;
// now, just set the bit corresponding to the passed cond to 1 (current step)
@@ -347,11 +334,9 @@ public class QuestState
}
}
// case 2: There were exist previously skipped steps
// if this is a push back to a previous step, clear all completion flags ahead
else if (cond < old)
else if (cond < old) // if this is a push back to a previous step, clear all completion flags ahead
{
// note, this also unsets the flag indicating that there exist skips
completedStateFlags &= (1 << cond) - 1;
completedStateFlags &= (1 << cond) - 1; // note, this also unsets the flag indicating that there exist skips
// now, check if this resulted in no steps being skipped any more
if (completedStateFlags == ((1 << cond) - 1))
@@ -361,8 +346,7 @@ public class QuestState
else
{
// set the most significant bit back to 1 again, to correctly indicate that this skips states.
// also, ensure that the least significant bit is an 1 (the first step is never skipped, no matter
// what the cond says)
// also, ensure that the least significant bit is an 1 (the first step is never skipped, no matter what the cond says)
completedStateFlags |= 0x80000001;
set("__compltdStateFlags", String.valueOf(completedStateFlags));
}
@@ -388,18 +372,17 @@ public class QuestState
/**
* Removes a quest variable from the list of existing quest variables.
* @param var the name of the variable to remove
* @return the previous value of the variable or {@code null} if none were found
*/
public String unset(String var)
public void unset(String var)
{
if (_simulated)
{
return null;
return;
}
if (_vars == null)
{
return null;
return;
}
final String old = _vars.remove(var);
@@ -407,7 +390,6 @@ public class QuestState
{
Quest.deleteQuestVarInDb(this, var);
}
return old;
}
/**
@@ -468,22 +450,21 @@ public class QuestState
/**
* Sets the quest state progress ({@code cond}) to the specified step.
* @param value the new value of the quest state progress
* @return this {@link QuestState} object
* @see #set(String var, String value)
* @see #setCond(int, boolean)
*/
public QuestState setCond(int value)
public void setCond(int value)
{
if (_simulated)
{
return null;
return;
}
if (isStarted())
{
set("cond", Integer.toString(value));
}
return this;
return;
}
/**
@@ -529,20 +510,19 @@ public class QuestState
* Sets the quest state progress ({@code cond}) to the specified step.
* @param value the new value of the quest state progress
* @param playQuestMiddle if {@code true}, plays "ItemSound.quest_middle"
* @return this {@link QuestState} object
* @see #setCond(int value)
* @see #set(String var, String value)
*/
public QuestState setCond(int value, boolean playQuestMiddle)
public void setCond(int value, boolean playQuestMiddle)
{
if (_simulated)
{
return null;
return;
}
if (!isStarted())
{
return this;
return;
}
set("cond", String.valueOf(value));
@@ -550,17 +530,15 @@ public class QuestState
{
_player.sendPacket(QuestSound.ITEMSOUND_QUEST_MIDDLE.getPacket());
}
return this;
}
public QuestState setMemoState(int value)
public void setMemoState(int value)
{
if (_simulated)
{
return null;
return;
}
set("memoState", String.valueOf(value));
return this;
}
/**
@@ -598,16 +576,14 @@ public class QuestState
* Sets the memo state ex.
* @param slot the slot where the value will be saved
* @param value the value
* @return this QuestState
*/
public QuestState setMemoStateEx(int slot, int value)
public void setMemoStateEx(int slot, int value)
{
if (_simulated)
{
return null;
return;
}
set("memoStateEx" + slot, String.valueOf(value));
return this;
}
/**
@@ -644,13 +620,12 @@ public class QuestState
/**
* Set condition to 1, state to STARTED and play the "ItemSound.quest_accept".<br>
* Works only if state is CREATED and the quest is not a custom quest.
* @return the newly created {@code QuestState} object
*/
public QuestState startQuest()
public void startQuest()
{
if (_simulated)
{
return null;
return;
}
if (isCreated() && !getQuest().isCustomQuest())
{
@@ -659,23 +634,21 @@ public class QuestState
_player.sendPacket(QuestSound.ITEMSOUND_QUEST_ACCEPT.getPacket());
getQuest().sendNpcLogList(getPlayer());
}
return this;
}
/**
* Finishes the quest and removes all quest items associated with this quest from the player's inventory.<br>
* If {@code type} is {@code QuestType.ONE_TIME}, also removes all other quest data associated with this quest.
* @param type the {@link QuestType} of the quest
* @return this {@link QuestState} object
* @see #exitQuest(QuestType type, boolean playExitQuest)
* @see #exitQuest(boolean repeatable)
* @see #exitQuest(boolean repeatable, boolean playExitQuest)
*/
public QuestState exitQuest(QuestType type)
public void exitQuest(QuestType type)
{
if (_simulated)
{
return null;
return;
}
switch (type)
@@ -697,8 +670,6 @@ public class QuestState
// Notify to scripts
EventDispatcher.getInstance().notifyEventAsync(new OnPlayerQuestComplete(_player, getQuest().getId(), type), _player);
return this;
}
/**
@@ -706,46 +677,43 @@ public class QuestState
* If {@code type} is {@code QuestType.ONE_TIME}, also removes all other quest data associated with this quest.
* @param type the {@link QuestType} of the quest
* @param playExitQuest if {@code true}, plays "ItemSound.quest_finish"
* @return this {@link QuestState} object
* @see #exitQuest(QuestType type)
* @see #exitQuest(boolean repeatable)
* @see #exitQuest(boolean repeatable, boolean playExitQuest)
*/
public QuestState exitQuest(QuestType type, boolean playExitQuest)
public void exitQuest(QuestType type, boolean playExitQuest)
{
if (_simulated)
{
return null;
return;
}
exitQuest(type);
if (playExitQuest)
{
_player.sendPacket(QuestSound.ITEMSOUND_QUEST_FINISH.getPacket());
}
return this;
}
/**
* Finishes the quest and removes all quest items associated with this quest from the player's inventory.<br>
* If {@code repeatable} is set to {@code false}, also removes all other quest data associated with this quest.
* @param repeatable if {@code true}, deletes all data and variables of this quest, otherwise keeps them
* @return this {@link QuestState} object
* @see #exitQuest(QuestType type)
* @see #exitQuest(QuestType type, boolean playExitQuest)
* @see #exitQuest(boolean repeatable, boolean playExitQuest)
*/
private QuestState exitQuest(boolean repeatable)
private void exitQuest(boolean repeatable)
{
if (_simulated)
{
return null;
return;
}
_player.removeNotifyQuestOfDeath(this);
if (!isStarted())
{
return this;
return;
}
// Clean registered quest items
@@ -762,7 +730,6 @@ public class QuestState
setState(State.COMPLETED);
}
_vars = null;
return this;
}
/**
@@ -770,16 +737,15 @@ public class QuestState
* If {@code repeatable} is set to {@code false}, also removes all other quest data associated with this quest.
* @param repeatable if {@code true}, deletes all data and variables of this quest, otherwise keeps them
* @param playExitQuest if {@code true}, plays "ItemSound.quest_finish"
* @return this {@link QuestState} object
* @see #exitQuest(QuestType type)
* @see #exitQuest(QuestType type, boolean playExitQuest)
* @see #exitQuest(boolean repeatable)
*/
public QuestState exitQuest(boolean repeatable, boolean playExitQuest)
public void exitQuest(boolean repeatable, boolean playExitQuest)
{
if (_simulated)
{
return null;
return;
}
exitQuest(repeatable);
@@ -790,7 +756,7 @@ public class QuestState
// Notify to scripts
EventDispatcher.getInstance().notifyEventAsync(new OnPlayerQuestComplete(_player, getQuest().getId(), repeatable ? QuestType.REPEATABLE : QuestType.ONE_TIME), _player);
return this;
return;
}
/**

View File

@@ -17,8 +17,6 @@
package org.l2jmobius.gameserver.model.quest;
import java.util.concurrent.ScheduledFuture;
import java.util.logging.Level;
import java.util.logging.Logger;
import org.l2jmobius.commons.concurrent.ThreadPool;
import org.l2jmobius.gameserver.model.actor.Npc;
@@ -26,106 +24,68 @@ import org.l2jmobius.gameserver.model.actor.instance.PlayerInstance;
public class QuestTimer
{
protected static final Logger LOGGER = Logger.getLogger(QuestTimer.class.getName());
public class ScheduleTimerTask implements Runnable
{
@Override
public void run()
{
if (!_isActive)
{
return;
}
try
{
if (!_isRepeating)
{
cancelAndRemove();
}
_quest.notifyEvent(_name, _npc, _player);
}
catch (Exception e)
{
LOGGER.log(Level.SEVERE, "", e);
}
}
}
boolean _isActive = true;
final String _name;
final Quest _quest;
final Npc _npc;
final PlayerInstance _player;
final boolean _isRepeating;
private final ScheduledFuture<?> _scheduler;
private final String _name;
private final Quest _quest;
private final Npc _npc;
private final PlayerInstance _player;
private final boolean _isRepeating;
private ScheduledFuture<?> _scheduler;
public QuestTimer(Quest quest, String name, long time, Npc npc, PlayerInstance player, boolean repeating)
{
_name = name;
_quest = quest;
_player = player;
_name = name;
_npc = npc;
_player = player;
_isRepeating = repeating;
_scheduler = repeating ? ThreadPool.scheduleAtFixedRate(new ScheduleTimerTask(), time, time) : ThreadPool.schedule(new ScheduleTimerTask(), time);
}
public QuestTimer(Quest quest, String name, long time, Npc npc, PlayerInstance player)
{
this(quest, name, time, npc, player, false);
}
public QuestTimer(QuestState qs, String name, long time)
{
this(qs.getQuest(), name, time, null, qs.getPlayer(), false);
}
/**
* Cancel this quest timer.
*/
public void cancel()
{
_isActive = false;
if (_scheduler != null)
if (repeating)
{
_scheduler.cancel(false);
_scheduler = ThreadPool.scheduleAtFixedRate(new ScheduleTimerTask(), time, time); // Prepare auto end task
}
else
{
_scheduler = ThreadPool.schedule(new ScheduleTimerTask(), time); // Prepare auto end task
}
}
/**
* Cancel this quest timer and remove it from the associated quest.
*/
public void cancelAndRemove()
public void cancel()
{
cancel();
if (_scheduler != null)
{
_scheduler.cancel(false);
_scheduler = null;
}
_quest.removeQuestTimer(this);
}
/**
* Compares if this timer matches with the key attributes passed.
* @param quest the quest to which the timer is attached
* @param name the name of the timer
* @param npc the NPC attached to the desired timer (null if no NPC attached)
* @param player the player attached to the desired timer (null if no player attached)
* @return
* public method to compare if this timer matches with the key attributes passed.
* @param quest : Quest instance to which the timer is attached
* @param name : Name of the timer
* @param npc : Npc instance attached to the desired timer (null if no npc attached)
* @param player : Player instance attached to the desired timer (null if no player attached)
* @return boolean
*/
public boolean isMatch(Quest quest, String name, Npc npc, PlayerInstance player)
public boolean equals(Quest quest, String name, Npc npc, PlayerInstance player)
{
if ((quest == null) || (name == null))
if ((quest == null) || (quest != _quest))
{
return false;
}
if ((quest != _quest) || !name.equalsIgnoreCase(_name))
if ((name == null) || !name.equals(_name))
{
return false;
}
return ((npc == _npc) && (player == _player));
return (npc == _npc) && (player == _player);
}
public boolean isActive()
{
return _isActive;
return (_scheduler != null) && !_scheduler.isCancelled() && !_scheduler.isDone();
}
public boolean isRepeating()
@@ -158,4 +118,23 @@ public class QuestTimer
{
return _name;
}
public class ScheduleTimerTask implements Runnable
{
@Override
public void run()
{
if (_scheduler == null)
{
return;
}
if (!_isRepeating)
{
cancel();
}
_quest.notifyEvent(_name, _npc, _player);
}
}
}

View File

@@ -261,7 +261,7 @@ public class AdminQuest implements IAdminCommandHandler
{
for (QuestTimer timer : list)
{
timers += "<tr><td colspan=\"4\"><table width=270 border=0 bgcolor=131210><tr><td width=270><font color=\"LEVEL\">" + timer.getName() + ":</font> <font color=00FF00>Active: " + timer.isActive() + " Repeatable: " + timer.isRepeating() + " Player: " + timer.getPlayer() + " Npc: " + timer.getNpc() + "</font></td></tr></table></td></tr>";
timers += "<tr><td colspan=\"4\"><table width=270 border=0 bgcolor=131210><tr><td width=270><font color=\"LEVEL\">" + timer.toString() + ":</font> <font color=00FF00>Active: " + timer.isActive() + " Repeatable: " + timer.isRepeating() + " Player: " + timer.getPlayer() + " Npc: " + timer.getNpc() + "</font></td></tr></table></td></tr>";
counter++;
if (counter > 10)
{

View File

@@ -342,7 +342,7 @@ public class Quest extends AbstractScript implements IIdentifiable
{
for (QuestTimer timer : timers)
{
if ((timer != null) && timer.isMatch(this, name, npc, player))
if ((timer != null) && timer.equals(this, name, npc, player))
{
return timer;
}
@@ -400,7 +400,7 @@ public class Quest extends AbstractScript implements IIdentifiable
final QuestTimer timer = getQuestTimer(name, npc, player);
if (timer != null)
{
timer.cancelAndRemove();
timer.cancel();
}
}
@@ -413,7 +413,7 @@ public class Quest extends AbstractScript implements IIdentifiable
{
if ((timer != null) && (_questTimers != null))
{
final List<QuestTimer> timers = getQuestTimers().get(timer.getName());
final List<QuestTimer> timers = getQuestTimers().get(timer.toString());
if (timers != null)
{
_writeLock.lock();

View File

@@ -136,31 +136,29 @@ public class QuestState
/**
* @param state the new state of the quest to set
* @return {@code true} if state was changed, {@code false} otherwise
* @see #setState(byte state, boolean saveInDb)
* @see org.l2jmobius.gameserver.model.quest.State
*/
public boolean setState(byte state)
public void setState(byte state)
{
return setState(state, true);
setState(state, true);
}
/**
* Change the state of this quest to the specified value.
* @param state the new state of the quest to set
* @param saveInDb if {@code true}, will save the state change in the database
* @return {@code true} if state was changed, {@code false} otherwise
* @see org.l2jmobius.gameserver.model.quest.State
*/
public boolean setState(byte state, boolean saveInDb)
public void setState(byte state, boolean saveInDb)
{
if (_simulated)
{
return false;
return;
}
if (_state == state)
{
return false;
return;
}
final boolean newQuest = isCreated();
_state = state;
@@ -177,20 +175,18 @@ public class QuestState
}
_player.sendPacket(new QuestList(_player));
return true;
}
/**
* Add parameter used in quests.
* @param var String pointing out the name of the variable for quest
* @param value String pointing out the value of the variable for quest
* @return String (equal to parameter "value")
*/
public String setInternal(String var, String value)
public void setInternal(String var, String value)
{
if (_simulated)
{
return null;
return;
}
if (_vars == null)
@@ -204,16 +200,15 @@ public class QuestState
}
_vars.put(var, value);
return value;
}
public String set(String var, int value)
public void set(String var, int value)
{
if (_simulated)
{
return null;
return;
}
return set(var, Integer.toString(value));
set(var, Integer.toString(value));
}
/**
@@ -229,13 +224,12 @@ public class QuestState
* <ul>
* @param var String indicating the name of the variable for quest
* @param value String indicating the value of the variable for quest
* @return String (equal to parameter "value")
*/
public String set(String var, String value)
public void set(String var, String value)
{
if (_simulated)
{
return null;
return;
}
if (_vars == null)
@@ -279,8 +273,6 @@ public class QuestState
LOGGER.log(Level.WARNING, _player.getName() + ", " + _questName + " cond [" + value + "] is not an integer. Value stored, but no packet was sent: " + e.getMessage(), e);
}
}
return value;
}
/**
@@ -325,20 +317,15 @@ public class QuestState
// case 1: No steps have been skipped so far...
if (completedStateFlags == 0)
{
// check if this step also doesn't skip anything. If so, no further work is needed
// also, in this case, no work is needed if the state is being reset to a smaller value
// in those cases, skip forward to informing the client about the change...
// Check if this step also doesn't skip anything. If so, no further work is needed also, in this case, no work is needed if the state is being reset to a smaller value in those cases, skip forward to informing the client about the change...
// ELSE, if we just now skipped for the first time...prepare the flags!!!
if (cond > (old + 1))
{
// set the most significant bit to 1 (indicates that there exist skipped states)
// also, ensure that the least significant bit is an 1 (the first step is never skipped, no matter
// what the cond says)
// also, ensure that the least significant bit is an 1 (the first step is never skipped, no matter what the cond says)
completedStateFlags = 0x80000001;
// since no flag had been skipped until now, the least significant bits must all
// be set to 1, up until "old" number of bits.
// since no flag had been skipped until now, the least significant bits must all be set to 1, up until "old" number of bits.
completedStateFlags |= (1 << old) - 1;
// now, just set the bit corresponding to the passed cond to 1 (current step)
@@ -347,11 +334,9 @@ public class QuestState
}
}
// case 2: There were exist previously skipped steps
// if this is a push back to a previous step, clear all completion flags ahead
else if (cond < old)
else if (cond < old) // if this is a push back to a previous step, clear all completion flags ahead
{
// note, this also unsets the flag indicating that there exist skips
completedStateFlags &= (1 << cond) - 1;
completedStateFlags &= (1 << cond) - 1; // note, this also unsets the flag indicating that there exist skips
// now, check if this resulted in no steps being skipped any more
if (completedStateFlags == ((1 << cond) - 1))
@@ -361,8 +346,7 @@ public class QuestState
else
{
// set the most significant bit back to 1 again, to correctly indicate that this skips states.
// also, ensure that the least significant bit is an 1 (the first step is never skipped, no matter
// what the cond says)
// also, ensure that the least significant bit is an 1 (the first step is never skipped, no matter what the cond says)
completedStateFlags |= 0x80000001;
set("__compltdStateFlags", String.valueOf(completedStateFlags));
}
@@ -388,18 +372,17 @@ public class QuestState
/**
* Removes a quest variable from the list of existing quest variables.
* @param var the name of the variable to remove
* @return the previous value of the variable or {@code null} if none were found
*/
public String unset(String var)
public void unset(String var)
{
if (_simulated)
{
return null;
return;
}
if (_vars == null)
{
return null;
return;
}
final String old = _vars.remove(var);
@@ -407,7 +390,6 @@ public class QuestState
{
Quest.deleteQuestVarInDb(this, var);
}
return old;
}
/**
@@ -468,22 +450,21 @@ public class QuestState
/**
* Sets the quest state progress ({@code cond}) to the specified step.
* @param value the new value of the quest state progress
* @return this {@link QuestState} object
* @see #set(String var, String value)
* @see #setCond(int, boolean)
*/
public QuestState setCond(int value)
public void setCond(int value)
{
if (_simulated)
{
return null;
return;
}
if (isStarted())
{
set("cond", Integer.toString(value));
}
return this;
return;
}
/**
@@ -529,20 +510,19 @@ public class QuestState
* Sets the quest state progress ({@code cond}) to the specified step.
* @param value the new value of the quest state progress
* @param playQuestMiddle if {@code true}, plays "ItemSound.quest_middle"
* @return this {@link QuestState} object
* @see #setCond(int value)
* @see #set(String var, String value)
*/
public QuestState setCond(int value, boolean playQuestMiddle)
public void setCond(int value, boolean playQuestMiddle)
{
if (_simulated)
{
return null;
return;
}
if (!isStarted())
{
return this;
return;
}
set("cond", String.valueOf(value));
@@ -550,17 +530,15 @@ public class QuestState
{
_player.sendPacket(QuestSound.ITEMSOUND_QUEST_MIDDLE.getPacket());
}
return this;
}
public QuestState setMemoState(int value)
public void setMemoState(int value)
{
if (_simulated)
{
return null;
return;
}
set("memoState", String.valueOf(value));
return this;
}
/**
@@ -598,16 +576,14 @@ public class QuestState
* Sets the memo state ex.
* @param slot the slot where the value will be saved
* @param value the value
* @return this QuestState
*/
public QuestState setMemoStateEx(int slot, int value)
public void setMemoStateEx(int slot, int value)
{
if (_simulated)
{
return null;
return;
}
set("memoStateEx" + slot, String.valueOf(value));
return this;
}
/**
@@ -644,13 +620,12 @@ public class QuestState
/**
* Set condition to 1, state to STARTED and play the "ItemSound.quest_accept".<br>
* Works only if state is CREATED and the quest is not a custom quest.
* @return the newly created {@code QuestState} object
*/
public QuestState startQuest()
public void startQuest()
{
if (_simulated)
{
return null;
return;
}
if (isCreated() && !getQuest().isCustomQuest())
{
@@ -659,23 +634,21 @@ public class QuestState
_player.sendPacket(QuestSound.ITEMSOUND_QUEST_ACCEPT.getPacket());
getQuest().sendNpcLogList(getPlayer());
}
return this;
}
/**
* Finishes the quest and removes all quest items associated with this quest from the player's inventory.<br>
* If {@code type} is {@code QuestType.ONE_TIME}, also removes all other quest data associated with this quest.
* @param type the {@link QuestType} of the quest
* @return this {@link QuestState} object
* @see #exitQuest(QuestType type, boolean playExitQuest)
* @see #exitQuest(boolean repeatable)
* @see #exitQuest(boolean repeatable, boolean playExitQuest)
*/
public QuestState exitQuest(QuestType type)
public void exitQuest(QuestType type)
{
if (_simulated)
{
return null;
return;
}
switch (type)
@@ -697,8 +670,6 @@ public class QuestState
// Notify to scripts
EventDispatcher.getInstance().notifyEventAsync(new OnPlayerQuestComplete(_player, getQuest().getId(), type), _player);
return this;
}
/**
@@ -706,46 +677,43 @@ public class QuestState
* If {@code type} is {@code QuestType.ONE_TIME}, also removes all other quest data associated with this quest.
* @param type the {@link QuestType} of the quest
* @param playExitQuest if {@code true}, plays "ItemSound.quest_finish"
* @return this {@link QuestState} object
* @see #exitQuest(QuestType type)
* @see #exitQuest(boolean repeatable)
* @see #exitQuest(boolean repeatable, boolean playExitQuest)
*/
public QuestState exitQuest(QuestType type, boolean playExitQuest)
public void exitQuest(QuestType type, boolean playExitQuest)
{
if (_simulated)
{
return null;
return;
}
exitQuest(type);
if (playExitQuest)
{
_player.sendPacket(QuestSound.ITEMSOUND_QUEST_FINISH.getPacket());
}
return this;
}
/**
* Finishes the quest and removes all quest items associated with this quest from the player's inventory.<br>
* If {@code repeatable} is set to {@code false}, also removes all other quest data associated with this quest.
* @param repeatable if {@code true}, deletes all data and variables of this quest, otherwise keeps them
* @return this {@link QuestState} object
* @see #exitQuest(QuestType type)
* @see #exitQuest(QuestType type, boolean playExitQuest)
* @see #exitQuest(boolean repeatable, boolean playExitQuest)
*/
private QuestState exitQuest(boolean repeatable)
private void exitQuest(boolean repeatable)
{
if (_simulated)
{
return null;
return;
}
_player.removeNotifyQuestOfDeath(this);
if (!isStarted())
{
return this;
return;
}
// Clean registered quest items
@@ -762,7 +730,6 @@ public class QuestState
setState(State.COMPLETED);
}
_vars = null;
return this;
}
/**
@@ -770,16 +737,15 @@ public class QuestState
* If {@code repeatable} is set to {@code false}, also removes all other quest data associated with this quest.
* @param repeatable if {@code true}, deletes all data and variables of this quest, otherwise keeps them
* @param playExitQuest if {@code true}, plays "ItemSound.quest_finish"
* @return this {@link QuestState} object
* @see #exitQuest(QuestType type)
* @see #exitQuest(QuestType type, boolean playExitQuest)
* @see #exitQuest(boolean repeatable)
*/
public QuestState exitQuest(boolean repeatable, boolean playExitQuest)
public void exitQuest(boolean repeatable, boolean playExitQuest)
{
if (_simulated)
{
return null;
return;
}
exitQuest(repeatable);
@@ -790,7 +756,7 @@ public class QuestState
// Notify to scripts
EventDispatcher.getInstance().notifyEventAsync(new OnPlayerQuestComplete(_player, getQuest().getId(), repeatable ? QuestType.REPEATABLE : QuestType.ONE_TIME), _player);
return this;
return;
}
/**

View File

@@ -17,8 +17,6 @@
package org.l2jmobius.gameserver.model.quest;
import java.util.concurrent.ScheduledFuture;
import java.util.logging.Level;
import java.util.logging.Logger;
import org.l2jmobius.commons.concurrent.ThreadPool;
import org.l2jmobius.gameserver.model.actor.Npc;
@@ -26,106 +24,68 @@ import org.l2jmobius.gameserver.model.actor.instance.PlayerInstance;
public class QuestTimer
{
protected static final Logger LOGGER = Logger.getLogger(QuestTimer.class.getName());
public class ScheduleTimerTask implements Runnable
{
@Override
public void run()
{
if (!_isActive)
{
return;
}
try
{
if (!_isRepeating)
{
cancelAndRemove();
}
_quest.notifyEvent(_name, _npc, _player);
}
catch (Exception e)
{
LOGGER.log(Level.SEVERE, "", e);
}
}
}
boolean _isActive = true;
final String _name;
final Quest _quest;
final Npc _npc;
final PlayerInstance _player;
final boolean _isRepeating;
private final ScheduledFuture<?> _scheduler;
private final String _name;
private final Quest _quest;
private final Npc _npc;
private final PlayerInstance _player;
private final boolean _isRepeating;
private ScheduledFuture<?> _scheduler;
public QuestTimer(Quest quest, String name, long time, Npc npc, PlayerInstance player, boolean repeating)
{
_name = name;
_quest = quest;
_player = player;
_name = name;
_npc = npc;
_player = player;
_isRepeating = repeating;
_scheduler = repeating ? ThreadPool.scheduleAtFixedRate(new ScheduleTimerTask(), time, time) : ThreadPool.schedule(new ScheduleTimerTask(), time);
}
public QuestTimer(Quest quest, String name, long time, Npc npc, PlayerInstance player)
{
this(quest, name, time, npc, player, false);
}
public QuestTimer(QuestState qs, String name, long time)
{
this(qs.getQuest(), name, time, null, qs.getPlayer(), false);
}
/**
* Cancel this quest timer.
*/
public void cancel()
{
_isActive = false;
if (_scheduler != null)
if (repeating)
{
_scheduler.cancel(false);
_scheduler = ThreadPool.scheduleAtFixedRate(new ScheduleTimerTask(), time, time); // Prepare auto end task
}
else
{
_scheduler = ThreadPool.schedule(new ScheduleTimerTask(), time); // Prepare auto end task
}
}
/**
* Cancel this quest timer and remove it from the associated quest.
*/
public void cancelAndRemove()
public void cancel()
{
cancel();
if (_scheduler != null)
{
_scheduler.cancel(false);
_scheduler = null;
}
_quest.removeQuestTimer(this);
}
/**
* Compares if this timer matches with the key attributes passed.
* @param quest the quest to which the timer is attached
* @param name the name of the timer
* @param npc the NPC attached to the desired timer (null if no NPC attached)
* @param player the player attached to the desired timer (null if no player attached)
* @return
* public method to compare if this timer matches with the key attributes passed.
* @param quest : Quest instance to which the timer is attached
* @param name : Name of the timer
* @param npc : Npc instance attached to the desired timer (null if no npc attached)
* @param player : Player instance attached to the desired timer (null if no player attached)
* @return boolean
*/
public boolean isMatch(Quest quest, String name, Npc npc, PlayerInstance player)
public boolean equals(Quest quest, String name, Npc npc, PlayerInstance player)
{
if ((quest == null) || (name == null))
if ((quest == null) || (quest != _quest))
{
return false;
}
if ((quest != _quest) || !name.equalsIgnoreCase(_name))
if ((name == null) || !name.equals(_name))
{
return false;
}
return ((npc == _npc) && (player == _player));
return (npc == _npc) && (player == _player);
}
public boolean isActive()
{
return _isActive;
return (_scheduler != null) && !_scheduler.isCancelled() && !_scheduler.isDone();
}
public boolean isRepeating()
@@ -158,4 +118,23 @@ public class QuestTimer
{
return _name;
}
public class ScheduleTimerTask implements Runnable
{
@Override
public void run()
{
if (_scheduler == null)
{
return;
}
if (!_isRepeating)
{
cancel();
}
_quest.notifyEvent(_name, _npc, _player);
}
}
}

View File

@@ -42,6 +42,7 @@ import org.l2jmobius.gameserver.network.serverpackets.SystemMessage;
import org.l2jmobius.gameserver.network.serverpackets.TutorialShowQuestionMark;
/**
* Quest state class.
* @author Luis Arias
*/
public class QuestState
@@ -62,16 +63,16 @@ public class QuestState
public static final byte DROP_FIXED_COUNT = 2;
public static final byte DROP_FIXED_BOTH = 3;
/** Quest associated to the QuestState */
/** The name of the quest of this QuestState */
private final String _questName;
/** Player who engaged the quest */
/** The "owner" of this QuestState object */
private final PlayerInstance _player;
/** State of the quest */
/** The current state of the quest */
private byte _state;
/** List of couples (variable for quest,value of the variable for quest) */
/** A map of key->value pairs containing the quest state variables and their values */
private Map<String, String> _vars;
/**
@@ -81,30 +82,29 @@ public class QuestState
* <LI>Save informations in the object QuestState created (Quest, Player, Completion, State)</LI>
* <LI>Add the QuestState in the player's list of quests by using setQuestState()</LI>
* <LI>Add drops gotten by the quest</LI> <BR/>
* @param quest : quest associated with the QuestState
* @param player : PlayerInstance pointing out the player
* @param state : state of the quest
* @param quest the {@link Quest} object associated with the QuestState
* @param player the owner of this {@link QuestState} object
* @param state the initial state of the quest
*/
QuestState(Quest quest, PlayerInstance player, byte state)
public QuestState(Quest quest, PlayerInstance player, byte state)
{
_questName = quest.getName();
_player = player;
// Save the state of the quest for the player in the player's list of quest owned
_player.setQuestState(this);
// set the state of the quest
_state = state;
player.setQuestState(this);
}
/**
* @return the name of the quest of this QuestState
*/
public String getQuestName()
{
return _questName;
}
/**
* Return the quest
* @return Quest
* @return the {@link Quest} object of this QuestState
*/
public Quest getQuest()
{
@@ -112,8 +112,7 @@ public class QuestState
}
/**
* Return the PlayerInstance
* @return PlayerInstance
* @return the {@link PlayerInstance} object of the owner of this QuestState
*/
public PlayerInstance getPlayer()
{
@@ -121,8 +120,8 @@ public class QuestState
}
/**
* Return the state of the quest
* @return State
* @return the current State of this QuestState
* @see org.l2jmobius.gameserver.model.quest.State
*/
public byte getState()
{
@@ -130,21 +129,30 @@ public class QuestState
}
/**
* Return true if quest completed, false otherwise
* @return boolean
* @return {@code true} if the State of this QuestState is CREATED, {@code false} otherwise
* @see org.l2jmobius.gameserver.model.quest.State
*/
public boolean isCompleted()
public boolean isCreated()
{
return (_state == State.COMPLETED);
return _state == State.CREATED;
}
/**
* Return true if quest started, false otherwise
* @return boolean
* @return {@code true} if the State of this QuestState is STARTED, {@code false} otherwise
* @see org.l2jmobius.gameserver.model.quest.State
*/
public boolean isStarted()
{
return (_state == State.STARTED);
return _state == State.STARTED;
}
/**
* @return {@code true} if the State of this QuestState is COMPLETED, {@code false} otherwise
* @see org.l2jmobius.gameserver.model.quest.State
*/
public boolean isCompleted()
{
return _state == State.COMPLETED;
}
/**
@@ -162,9 +170,7 @@ public class QuestState
if (_state != state)
{
_state = state;
Quest.updateQuestInDb(this);
_player.sendPacket(new QuestList(_player));
}
}
@@ -218,11 +224,10 @@ public class QuestState
/**
* Add parameter used in quests.
* @param var : String pointing out the name of the variable for quest
* @param value : String pointing out the value of the variable for quest
* @return String (equal to parameter "value")
* @param var String pointing out the name of the variable for quest
* @param value String pointing out the value of the variable for quest
*/
public String setInternal(String var, String value)
public void setInternal(String var, String value)
{
if (_vars == null)
{
@@ -235,8 +240,6 @@ public class QuestState
}
_vars.put(var, value);
return value;
}
/**
@@ -263,9 +266,7 @@ public class QuestState
value = "";
}
// Map.put() returns previous value associated with specified key, or null if there was no mapping for key.
final String old = _vars.put(var, value);
if (old != null)
{
Quest.updateQuestVarInDb(this, var, value);
@@ -311,15 +312,15 @@ public class QuestState
*/
private void setCond(int cond, int old)
{
int completedStateFlags = 0; // initializing...
// if there is no change since last setting, there is nothing to do here
if (cond == old)
{
return;
}
// cond 0 and 1 do not need completedStateFlags. Also, if cond > 1, the 1st step must always exist (i.e. it can never be skipped). So if cond is 2, we can still safely assume no steps have been skipped.
int completedStateFlags = 0;
// cond 0 and 1 do not need completedStateFlags. Also, if cond > 1, the 1st step must
// always exist (i.e. it can never be skipped). So if cond is 2, we can still safely
// assume no steps have been skipped.
// Finally, more than 31 steps CANNOT be supported in any way with skipping.
if ((cond < 3) || (cond > 31))
{
@@ -367,7 +368,8 @@ public class QuestState
set("__compltdStateFlags", String.valueOf(completedStateFlags));
}
}
// if this moves forward, it changes nothing on previously skipped steps...so just mark this state and we are done
// If this moves forward, it changes nothing on previously skipped steps.
// Just mark this state and we are done.
else
{
completedStateFlags |= 1 << (cond - 1);
@@ -378,7 +380,6 @@ public class QuestState
_player.sendPacket(new QuestList(_player));
final int questId = getQuest().getQuestId();
if ((questId > 0) && (questId < 999) && (cond > 0))
{
_player.sendPacket(new ExShowQuestMark(questId));
@@ -386,10 +387,8 @@ public class QuestState
}
/**
* Remove the variable of quest from the list of variables for the quest.<BR>
* <BR>
* <U><I>Concept : </I></U> Remove the variable of quest represented by "var" from the class variable Map "vars" and from the database.
* @param var : String designating the variable for the quest to be deleted
* Removes a quest variable from the list of existing quest variables.
* @param var the name of the variable to remove
*/
public void unset(String var)
{

View File

@@ -17,7 +17,16 @@
package org.l2jmobius.gameserver.model.quest;
/**
* @author Luis Arias
* This class merely enumerates the three necessary states for all quests:<br>
* <ul>
* <li>CREATED: a quest state is created but the quest is not yet accepted.</li>
* <li>STARTED: the player has accepted the quest. Quest is currently in progress</li>
* <li>COMPLETED: the quest has been completed.</li>
* </ul>
* In addition, this class defines two functions for lookup and inverse lookup of the state given a name.<br>
* This is useful only for saving the state values into the database with a more readable form and then being able to read the string back and remap them to their correct states.<br>
* All quests have these and only these states.
* @author Luis Arias; version 2 by Fulminus
*/
public class State
{
@@ -25,7 +34,11 @@ public class State
public static final byte STARTED = 1;
public static final byte COMPLETED = 2;
// discover the string representation of the state, for readable DB storage
/**
* Get the quest state's string representation from its byte value.
* @param state the byte value of the state
* @return the String representation of the quest state (default: Start)
*/
public static String getStateName(byte state)
{
switch (state)
@@ -45,7 +58,11 @@ public class State
}
}
// discover the state from its string representation (for reconstruction after DB read)
/**
* Get the quest state's byte value from its string representation.
* @param statename the String representation of the state
* @return the byte value of the quest state (default: 0)
*/
public static byte getStateId(String statename)
{
switch (statename)

View File

@@ -245,7 +245,7 @@ public class AdminQuest implements IAdminCommandHandler
{
for (QuestTimer timer : list)
{
timers += "<tr><td colspan=\"4\"><table width=270 border=0 bgcolor=131210><tr><td width=270><font color=\"LEVEL\">" + timer.getName() + ":</font> <font color=00FF00>Active: " + timer.isActive() + " Repeatable: " + timer.isRepeating() + " Player: " + timer.getPlayer() + " Npc: " + timer.getNpc() + "</font></td></tr></table></td></tr>";
timers += "<tr><td colspan=\"4\"><table width=270 border=0 bgcolor=131210><tr><td width=270><font color=\"LEVEL\">" + timer.toString() + ":</font> <font color=00FF00>Active: " + timer.isActive() + " Repeatable: " + timer.isRepeating() + " Player: " + timer.getPlayer() + " Npc: " + timer.getNpc() + "</font></td></tr></table></td></tr>";
counter++;
if (counter > 10)
{

View File

@@ -207,7 +207,7 @@ public class Q00022_TragedyInVonHellmannForest extends Quest
final QuestTimer qt = getQuestTimer("DESPAWN_GHOST2", npc, player);
if ((qt != null) && (npc.getScriptValue() == player.getObjectId()))
{
qt.cancelAndRemove();
qt.cancel();
npc.setScriptValue(0);
startQuestTimer("DESPAWN_GHOST2", 1000 * 3, npc, player);
qs.setCond(8);

View File

@@ -305,7 +305,7 @@ public class Quest extends AbstractScript implements IIdentifiable
{
for (QuestTimer timer : timers)
{
if ((timer != null) && timer.isMatch(this, name, npc, player))
if ((timer != null) && timer.equals(this, name, npc, player))
{
return timer;
}
@@ -363,7 +363,7 @@ public class Quest extends AbstractScript implements IIdentifiable
final QuestTimer timer = getQuestTimer(name, npc, player);
if (timer != null)
{
timer.cancelAndRemove();
timer.cancel();
}
}
@@ -376,7 +376,7 @@ public class Quest extends AbstractScript implements IIdentifiable
{
if ((timer != null) && (_questTimers != null))
{
final List<QuestTimer> timers = getQuestTimers().get(timer.getName());
final List<QuestTimer> timers = getQuestTimers().get(timer.toString());
if (timers != null)
{
_writeLock.lock();

View File

@@ -138,27 +138,25 @@ public class QuestState
/**
* @param state the new state of the quest to set
* @return {@code true} if state was changed, {@code false} otherwise
* @see #setState(byte state, boolean saveInDb)
* @see org.l2jmobius.gameserver.model.quest.State
*/
public boolean setState(byte state)
public void setState(byte state)
{
return setState(state, true);
setState(state, true);
}
/**
* Change the state of this quest to the specified value.
* @param state the new state of the quest to set
* @param saveInDb if {@code true}, will save the state change in the database
* @return {@code true} if state was changed, {@code false} otherwise
* @see org.l2jmobius.gameserver.model.quest.State
*/
public boolean setState(byte state, boolean saveInDb)
public void setState(byte state, boolean saveInDb)
{
if (_state == state)
{
return false;
return;
}
final boolean newQuest = isCreated();
_state = state;
@@ -175,16 +173,14 @@ public class QuestState
}
_player.sendPacket(new QuestList(_player));
return true;
}
/**
* Add parameter used in quests.
* @param var String pointing out the name of the variable for quest
* @param value String pointing out the value of the variable for quest
* @return String (equal to parameter "value")
*/
public String setInternal(String var, String value)
public void setInternal(String var, String value)
{
if (_vars == null)
{
@@ -197,12 +193,11 @@ public class QuestState
}
_vars.put(var, value);
return value;
}
public String set(String var, int value)
public void set(String var, int value)
{
return set(var, Integer.toString(value));
set(var, Integer.toString(value));
}
/**
@@ -218,9 +213,8 @@ public class QuestState
* <ul>
* @param var String indicating the name of the variable for quest
* @param value String indicating the value of the variable for quest
* @return String (equal to parameter "value")
*/
public String set(String var, String value)
public void set(String var, String value)
{
if (_vars == null)
{
@@ -262,8 +256,6 @@ public class QuestState
LOGGER.log(Level.WARNING, _player.getName() + ", " + _questName + " cond [" + value + "] is not an integer. Value stored, but no packet was sent: " + e.getMessage(), e);
}
}
return value;
}
/**
@@ -303,20 +295,15 @@ public class QuestState
// case 1: No steps have been skipped so far...
if (completedStateFlags == 0)
{
// check if this step also doesn't skip anything. If so, no further work is needed
// also, in this case, no work is needed if the state is being reset to a smaller value
// in those cases, skip forward to informing the client about the change...
// Check if this step also doesn't skip anything. If so, no further work is needed also, in this case, no work is needed if the state is being reset to a smaller value in those cases, skip forward to informing the client about the change...
// ELSE, if we just now skipped for the first time...prepare the flags!!!
if (cond > (old + 1))
{
// set the most significant bit to 1 (indicates that there exist skipped states)
// also, ensure that the least significant bit is an 1 (the first step is never skipped, no matter
// what the cond says)
// also, ensure that the least significant bit is an 1 (the first step is never skipped, no matter what the cond says)
completedStateFlags = 0x80000001;
// since no flag had been skipped until now, the least significant bits must all
// be set to 1, up until "old" number of bits.
// since no flag had been skipped until now, the least significant bits must all be set to 1, up until "old" number of bits.
completedStateFlags |= (1 << old) - 1;
// now, just set the bit corresponding to the passed cond to 1 (current step)
@@ -325,11 +312,9 @@ public class QuestState
}
}
// case 2: There were exist previously skipped steps
// if this is a push back to a previous step, clear all completion flags ahead
else if (cond < old)
else if (cond < old) // if this is a push back to a previous step, clear all completion flags ahead
{
// note, this also unsets the flag indicating that there exist skips
completedStateFlags &= (1 << cond) - 1;
completedStateFlags &= (1 << cond) - 1; // note, this also unsets the flag indicating that there exist skips
// now, check if this resulted in no steps being skipped any more
if (completedStateFlags == ((1 << cond) - 1))
@@ -339,8 +324,7 @@ public class QuestState
else
{
// set the most significant bit back to 1 again, to correctly indicate that this skips states.
// also, ensure that the least significant bit is an 1 (the first step is never skipped, no matter
// what the cond says)
// also, ensure that the least significant bit is an 1 (the first step is never skipped, no matter what the cond says)
completedStateFlags |= 0x80000001;
set("__compltdStateFlags", String.valueOf(completedStateFlags));
}
@@ -366,13 +350,12 @@ public class QuestState
/**
* Removes a quest variable from the list of existing quest variables.
* @param var the name of the variable to remove
* @return the previous value of the variable or {@code null} if none were found
*/
public String unset(String var)
public void unset(String var)
{
if (_vars == null)
{
return null;
return;
}
final String old = _vars.remove(var);
@@ -380,7 +363,6 @@ public class QuestState
{
Quest.deleteQuestVarInDb(this, var);
}
return old;
}
/**
@@ -441,17 +423,15 @@ public class QuestState
/**
* Sets the quest state progress ({@code cond}) to the specified step.
* @param value the new value of the quest state progress
* @return this {@link QuestState} object
* @see #set(String var, String value)
* @see #setCond(int, boolean)
*/
public QuestState setCond(int value)
public void setCond(int value)
{
if (isStarted())
{
set("cond", Integer.toString(value));
}
return this;
}
/**
@@ -483,15 +463,14 @@ public class QuestState
* Sets the quest state progress ({@code cond}) to the specified step.
* @param value the new value of the quest state progress
* @param playQuestMiddle if {@code true}, plays "ItemSound.quest_middle"
* @return this {@link QuestState} object
* @see #setCond(int value)
* @see #set(String var, String value)
*/
public QuestState setCond(int value, boolean playQuestMiddle)
public void setCond(int value, boolean playQuestMiddle)
{
if (!isStarted())
{
return this;
return;
}
set("cond", String.valueOf(value));
@@ -499,13 +478,11 @@ public class QuestState
{
_player.sendPacket(QuestSound.ITEMSOUND_QUEST_MIDDLE.getPacket());
}
return this;
}
public QuestState setMemoState(int value)
public void setMemoState(int value)
{
set("memoState", String.valueOf(value));
return this;
}
/**
@@ -543,12 +520,10 @@ public class QuestState
* Sets the memo state ex.
* @param slot the slot where the value will be saved
* @param value the value
* @return this QuestState
*/
public QuestState setMemoStateEx(int slot, int value)
public void setMemoStateEx(int slot, int value)
{
set("memoStateEx" + slot, String.valueOf(value));
return this;
}
/**
@@ -595,9 +570,8 @@ public class QuestState
/**
* Set condition to 1, state to STARTED and play the "ItemSound.quest_accept".<br>
* Works only if state is CREATED and the quest is not a custom quest.
* @return the newly created {@code QuestState} object
*/
public QuestState startQuest()
public void startQuest()
{
if (isCreated() && !getQuest().isCustomQuest())
{
@@ -605,19 +579,17 @@ public class QuestState
setState(State.STARTED);
_player.sendPacket(QuestSound.ITEMSOUND_QUEST_ACCEPT.getPacket());
}
return this;
}
/**
* Finishes the quest and removes all quest items associated with this quest from the player's inventory.<br>
* If {@code type} is {@code QuestType.ONE_TIME}, also removes all other quest data associated with this quest.
* @param type the {@link QuestType} of the quest
* @return this {@link QuestState} object
* @see #exitQuest(QuestType type, boolean playExitQuest)
* @see #exitQuest(boolean repeatable)
* @see #exitQuest(boolean repeatable, boolean playExitQuest)
*/
public QuestState exitQuest(QuestType type)
public void exitQuest(QuestType type)
{
switch (type)
{
@@ -635,7 +607,6 @@ public class QuestState
break;
}
}
return this;
}
/**
@@ -643,37 +614,34 @@ public class QuestState
* If {@code type} is {@code QuestType.ONE_TIME}, also removes all other quest data associated with this quest.
* @param type the {@link QuestType} of the quest
* @param playExitQuest if {@code true}, plays "ItemSound.quest_finish"
* @return this {@link QuestState} object
* @see #exitQuest(QuestType type)
* @see #exitQuest(boolean repeatable)
* @see #exitQuest(boolean repeatable, boolean playExitQuest)
*/
public QuestState exitQuest(QuestType type, boolean playExitQuest)
public void exitQuest(QuestType type, boolean playExitQuest)
{
exitQuest(type);
if (playExitQuest)
{
_player.sendPacket(QuestSound.ITEMSOUND_QUEST_FINISH.getPacket());
}
return this;
}
/**
* Finishes the quest and removes all quest items associated with this quest from the player's inventory.<br>
* If {@code repeatable} is set to {@code false}, also removes all other quest data associated with this quest.
* @param repeatable if {@code true}, deletes all data and variables of this quest, otherwise keeps them
* @return this {@link QuestState} object
* @see #exitQuest(QuestType type)
* @see #exitQuest(QuestType type, boolean playExitQuest)
* @see #exitQuest(boolean repeatable, boolean playExitQuest)
*/
public QuestState exitQuest(boolean repeatable)
public void exitQuest(boolean repeatable)
{
_player.removeNotifyQuestOfDeath(this);
if (!isStarted())
{
return this;
return;
}
// Clean registered quest items
@@ -690,7 +658,6 @@ public class QuestState
setState(State.COMPLETED);
}
_vars = null;
return this;
}
/**
@@ -698,19 +665,18 @@ public class QuestState
* If {@code repeatable} is set to {@code false}, also removes all other quest data associated with this quest.
* @param repeatable if {@code true}, deletes all data and variables of this quest, otherwise keeps them
* @param playExitQuest if {@code true}, plays "ItemSound.quest_finish"
* @return this {@link QuestState} object
* @see #exitQuest(QuestType type)
* @see #exitQuest(QuestType type, boolean playExitQuest)
* @see #exitQuest(boolean repeatable)
*/
public QuestState exitQuest(boolean repeatable, boolean playExitQuest)
public void exitQuest(boolean repeatable, boolean playExitQuest)
{
exitQuest(repeatable);
if (playExitQuest)
{
_player.sendPacket(QuestSound.ITEMSOUND_QUEST_FINISH.getPacket());
}
return this;
return;
}
public void showQuestionMark(int number)

View File

@@ -17,8 +17,6 @@
package org.l2jmobius.gameserver.model.quest;
import java.util.concurrent.ScheduledFuture;
import java.util.logging.Level;
import java.util.logging.Logger;
import org.l2jmobius.commons.concurrent.ThreadPool;
import org.l2jmobius.gameserver.model.actor.Npc;
@@ -26,106 +24,68 @@ import org.l2jmobius.gameserver.model.actor.instance.PlayerInstance;
public class QuestTimer
{
protected static final Logger LOGGER = Logger.getLogger(QuestTimer.class.getName());
public class ScheduleTimerTask implements Runnable
{
@Override
public void run()
{
if (!_isActive)
{
return;
}
try
{
if (!_isRepeating)
{
cancelAndRemove();
}
_quest.notifyEvent(_name, _npc, _player);
}
catch (Exception e)
{
LOGGER.log(Level.SEVERE, "", e);
}
}
}
boolean _isActive = true;
final String _name;
final Quest _quest;
final Npc _npc;
final PlayerInstance _player;
final boolean _isRepeating;
private final ScheduledFuture<?> _schedular;
private final String _name;
private final Quest _quest;
private final Npc _npc;
private final PlayerInstance _player;
private final boolean _isRepeating;
private ScheduledFuture<?> _scheduler;
public QuestTimer(Quest quest, String name, long time, Npc npc, PlayerInstance player, boolean repeating)
{
_name = name;
_quest = quest;
_player = player;
_name = name;
_npc = npc;
_player = player;
_isRepeating = repeating;
_schedular = repeating ? ThreadPool.scheduleAtFixedRate(new ScheduleTimerTask(), time, time) : ThreadPool.schedule(new ScheduleTimerTask(), time);
}
public QuestTimer(Quest quest, String name, long time, Npc npc, PlayerInstance player)
{
this(quest, name, time, npc, player, false);
}
public QuestTimer(QuestState qs, String name, long time)
{
this(qs.getQuest(), name, time, null, qs.getPlayer(), false);
}
/**
* Cancel this quest timer.
*/
public void cancel()
{
_isActive = false;
if (_schedular != null)
if (repeating)
{
_schedular.cancel(false);
_scheduler = ThreadPool.scheduleAtFixedRate(new ScheduleTimerTask(), time, time); // Prepare auto end task
}
else
{
_scheduler = ThreadPool.schedule(new ScheduleTimerTask(), time); // Prepare auto end task
}
}
/**
* Cancel this quest timer and remove it from the associated quest.
*/
public void cancelAndRemove()
public void cancel()
{
cancel();
if (_scheduler != null)
{
_scheduler.cancel(false);
_scheduler = null;
}
_quest.removeQuestTimer(this);
}
/**
* Compares if this timer matches with the key attributes passed.
* @param quest the quest to which the timer is attached
* @param name the name of the timer
* @param npc the NPC attached to the desired timer (null if no NPC attached)
* @param player the player attached to the desired timer (null if no player attached)
* @return
* public method to compare if this timer matches with the key attributes passed.
* @param quest : Quest instance to which the timer is attached
* @param name : Name of the timer
* @param npc : Npc instance attached to the desired timer (null if no npc attached)
* @param player : Player instance attached to the desired timer (null if no player attached)
* @return boolean
*/
public boolean isMatch(Quest quest, String name, Npc npc, PlayerInstance player)
public boolean equals(Quest quest, String name, Npc npc, PlayerInstance player)
{
if ((quest == null) || (name == null))
if ((quest == null) || (quest != _quest))
{
return false;
}
if ((quest != _quest) || !name.equalsIgnoreCase(_name))
if ((name == null) || !name.equals(_name))
{
return false;
}
return ((npc == _npc) && (player == _player));
return (npc == _npc) && (player == _player);
}
public boolean isActive()
{
return _isActive;
return (_scheduler != null) && !_scheduler.isCancelled() && !_scheduler.isDone();
}
public boolean isRepeating()
@@ -158,4 +118,23 @@ public class QuestTimer
{
return _name;
}
public class ScheduleTimerTask implements Runnable
{
@Override
public void run()
{
if (_scheduler == null)
{
return;
}
if (!_isRepeating)
{
cancel();
}
_quest.notifyEvent(_name, _npc, _player);
}
}
}

View File

@@ -245,7 +245,7 @@ public class AdminQuest implements IAdminCommandHandler
{
for (QuestTimer timer : list)
{
timers += "<tr><td colspan=\"4\"><table width=270 border=0 bgcolor=131210><tr><td width=270><font color=\"LEVEL\">" + timer.getName() + ":</font> <font color=00FF00>Active: " + timer.isActive() + " Repeatable: " + timer.isRepeating() + " Player: " + timer.getPlayer() + " Npc: " + timer.getNpc() + "</font></td></tr></table></td></tr>";
timers += "<tr><td colspan=\"4\"><table width=270 border=0 bgcolor=131210><tr><td width=270><font color=\"LEVEL\">" + timer.toString() + ":</font> <font color=00FF00>Active: " + timer.isActive() + " Repeatable: " + timer.isRepeating() + " Player: " + timer.getPlayer() + " Npc: " + timer.getNpc() + "</font></td></tr></table></td></tr>";
counter++;
if (counter > 10)
{

View File

@@ -207,7 +207,7 @@ public class Q00022_TragedyInVonHellmannForest extends Quest
final QuestTimer qt = getQuestTimer("DESPAWN_GHOST2", npc, player);
if ((qt != null) && (npc.getScriptValue() == player.getObjectId()))
{
qt.cancelAndRemove();
qt.cancel();
npc.setScriptValue(0);
startQuestTimer("DESPAWN_GHOST2", 1000 * 3, npc, player);
qs.setCond(8);

View File

@@ -307,7 +307,7 @@ public class Quest extends AbstractScript implements IIdentifiable
{
for (QuestTimer timer : timers)
{
if ((timer != null) && timer.isMatch(this, name, npc, player))
if ((timer != null) && timer.equals(this, name, npc, player))
{
return timer;
}
@@ -365,7 +365,7 @@ public class Quest extends AbstractScript implements IIdentifiable
final QuestTimer timer = getQuestTimer(name, npc, player);
if (timer != null)
{
timer.cancelAndRemove();
timer.cancel();
}
}
@@ -378,7 +378,7 @@ public class Quest extends AbstractScript implements IIdentifiable
{
if ((timer != null) && (_questTimers != null))
{
final List<QuestTimer> timers = getQuestTimers().get(timer.getName());
final List<QuestTimer> timers = getQuestTimers().get(timer.toString());
if (timers != null)
{
_writeLock.lock();

View File

@@ -138,27 +138,25 @@ public class QuestState
/**
* @param state the new state of the quest to set
* @return {@code true} if state was changed, {@code false} otherwise
* @see #setState(byte state, boolean saveInDb)
* @see org.l2jmobius.gameserver.model.quest.State
*/
public boolean setState(byte state)
public void setState(byte state)
{
return setState(state, true);
setState(state, true);
}
/**
* Change the state of this quest to the specified value.
* @param state the new state of the quest to set
* @param saveInDb if {@code true}, will save the state change in the database
* @return {@code true} if state was changed, {@code false} otherwise
* @see org.l2jmobius.gameserver.model.quest.State
*/
public boolean setState(byte state, boolean saveInDb)
public void setState(byte state, boolean saveInDb)
{
if (_state == state)
{
return false;
return;
}
final boolean newQuest = isCreated();
_state = state;
@@ -175,16 +173,14 @@ public class QuestState
}
_player.sendPacket(new QuestList(_player));
return true;
}
/**
* Add parameter used in quests.
* @param var String pointing out the name of the variable for quest
* @param value String pointing out the value of the variable for quest
* @return String (equal to parameter "value")
*/
public String setInternal(String var, String value)
public void setInternal(String var, String value)
{
if (_vars == null)
{
@@ -197,12 +193,11 @@ public class QuestState
}
_vars.put(var, value);
return value;
}
public String set(String var, int value)
public void set(String var, int value)
{
return set(var, Integer.toString(value));
set(var, Integer.toString(value));
}
/**
@@ -218,9 +213,8 @@ public class QuestState
* <ul>
* @param var String indicating the name of the variable for quest
* @param value String indicating the value of the variable for quest
* @return String (equal to parameter "value")
*/
public String set(String var, String value)
public void set(String var, String value)
{
if (_vars == null)
{
@@ -262,8 +256,6 @@ public class QuestState
LOGGER.log(Level.WARNING, _player.getName() + ", " + _questName + " cond [" + value + "] is not an integer. Value stored, but no packet was sent: " + e.getMessage(), e);
}
}
return value;
}
/**
@@ -303,20 +295,15 @@ public class QuestState
// case 1: No steps have been skipped so far...
if (completedStateFlags == 0)
{
// check if this step also doesn't skip anything. If so, no further work is needed
// also, in this case, no work is needed if the state is being reset to a smaller value
// in those cases, skip forward to informing the client about the change...
// Check if this step also doesn't skip anything. If so, no further work is needed also, in this case, no work is needed if the state is being reset to a smaller value in those cases, skip forward to informing the client about the change...
// ELSE, if we just now skipped for the first time...prepare the flags!!!
if (cond > (old + 1))
{
// set the most significant bit to 1 (indicates that there exist skipped states)
// also, ensure that the least significant bit is an 1 (the first step is never skipped, no matter
// what the cond says)
// also, ensure that the least significant bit is an 1 (the first step is never skipped, no matter what the cond says)
completedStateFlags = 0x80000001;
// since no flag had been skipped until now, the least significant bits must all
// be set to 1, up until "old" number of bits.
// since no flag had been skipped until now, the least significant bits must all be set to 1, up until "old" number of bits.
completedStateFlags |= (1 << old) - 1;
// now, just set the bit corresponding to the passed cond to 1 (current step)
@@ -325,11 +312,9 @@ public class QuestState
}
}
// case 2: There were exist previously skipped steps
// if this is a push back to a previous step, clear all completion flags ahead
else if (cond < old)
else if (cond < old) // if this is a push back to a previous step, clear all completion flags ahead
{
// note, this also unsets the flag indicating that there exist skips
completedStateFlags &= (1 << cond) - 1;
completedStateFlags &= (1 << cond) - 1; // note, this also unsets the flag indicating that there exist skips
// now, check if this resulted in no steps being skipped any more
if (completedStateFlags == ((1 << cond) - 1))
@@ -339,8 +324,7 @@ public class QuestState
else
{
// set the most significant bit back to 1 again, to correctly indicate that this skips states.
// also, ensure that the least significant bit is an 1 (the first step is never skipped, no matter
// what the cond says)
// also, ensure that the least significant bit is an 1 (the first step is never skipped, no matter what the cond says)
completedStateFlags |= 0x80000001;
set("__compltdStateFlags", String.valueOf(completedStateFlags));
}
@@ -366,13 +350,12 @@ public class QuestState
/**
* Removes a quest variable from the list of existing quest variables.
* @param var the name of the variable to remove
* @return the previous value of the variable or {@code null} if none were found
*/
public String unset(String var)
public void unset(String var)
{
if (_vars == null)
{
return null;
return;
}
final String old = _vars.remove(var);
@@ -380,7 +363,6 @@ public class QuestState
{
Quest.deleteQuestVarInDb(this, var);
}
return old;
}
/**
@@ -441,17 +423,15 @@ public class QuestState
/**
* Sets the quest state progress ({@code cond}) to the specified step.
* @param value the new value of the quest state progress
* @return this {@link QuestState} object
* @see #set(String var, String value)
* @see #setCond(int, boolean)
*/
public QuestState setCond(int value)
public void setCond(int value)
{
if (isStarted())
{
set("cond", Integer.toString(value));
}
return this;
}
/**
@@ -483,15 +463,14 @@ public class QuestState
* Sets the quest state progress ({@code cond}) to the specified step.
* @param value the new value of the quest state progress
* @param playQuestMiddle if {@code true}, plays "ItemSound.quest_middle"
* @return this {@link QuestState} object
* @see #setCond(int value)
* @see #set(String var, String value)
*/
public QuestState setCond(int value, boolean playQuestMiddle)
public void setCond(int value, boolean playQuestMiddle)
{
if (!isStarted())
{
return this;
return;
}
set("cond", String.valueOf(value));
@@ -499,13 +478,11 @@ public class QuestState
{
_player.sendPacket(QuestSound.ITEMSOUND_QUEST_MIDDLE.getPacket());
}
return this;
}
public QuestState setMemoState(int value)
public void setMemoState(int value)
{
set("memoState", String.valueOf(value));
return this;
}
/**
@@ -543,12 +520,10 @@ public class QuestState
* Sets the memo state ex.
* @param slot the slot where the value will be saved
* @param value the value
* @return this QuestState
*/
public QuestState setMemoStateEx(int slot, int value)
public void setMemoStateEx(int slot, int value)
{
set("memoStateEx" + slot, String.valueOf(value));
return this;
}
/**
@@ -595,9 +570,8 @@ public class QuestState
/**
* Set condition to 1, state to STARTED and play the "ItemSound.quest_accept".<br>
* Works only if state is CREATED and the quest is not a custom quest.
* @return the newly created {@code QuestState} object
*/
public QuestState startQuest()
public void startQuest()
{
if (isCreated() && !getQuest().isCustomQuest())
{
@@ -605,19 +579,17 @@ public class QuestState
setState(State.STARTED);
_player.sendPacket(QuestSound.ITEMSOUND_QUEST_ACCEPT.getPacket());
}
return this;
}
/**
* Finishes the quest and removes all quest items associated with this quest from the player's inventory.<br>
* If {@code type} is {@code QuestType.ONE_TIME}, also removes all other quest data associated with this quest.
* @param type the {@link QuestType} of the quest
* @return this {@link QuestState} object
* @see #exitQuest(QuestType type, boolean playExitQuest)
* @see #exitQuest(boolean repeatable)
* @see #exitQuest(boolean repeatable, boolean playExitQuest)
*/
public QuestState exitQuest(QuestType type)
public void exitQuest(QuestType type)
{
switch (type)
{
@@ -635,7 +607,6 @@ public class QuestState
break;
}
}
return this;
}
/**
@@ -643,37 +614,34 @@ public class QuestState
* If {@code type} is {@code QuestType.ONE_TIME}, also removes all other quest data associated with this quest.
* @param type the {@link QuestType} of the quest
* @param playExitQuest if {@code true}, plays "ItemSound.quest_finish"
* @return this {@link QuestState} object
* @see #exitQuest(QuestType type)
* @see #exitQuest(boolean repeatable)
* @see #exitQuest(boolean repeatable, boolean playExitQuest)
*/
public QuestState exitQuest(QuestType type, boolean playExitQuest)
public void exitQuest(QuestType type, boolean playExitQuest)
{
exitQuest(type);
if (playExitQuest)
{
_player.sendPacket(QuestSound.ITEMSOUND_QUEST_FINISH.getPacket());
}
return this;
}
/**
* Finishes the quest and removes all quest items associated with this quest from the player's inventory.<br>
* If {@code repeatable} is set to {@code false}, also removes all other quest data associated with this quest.
* @param repeatable if {@code true}, deletes all data and variables of this quest, otherwise keeps them
* @return this {@link QuestState} object
* @see #exitQuest(QuestType type)
* @see #exitQuest(QuestType type, boolean playExitQuest)
* @see #exitQuest(boolean repeatable, boolean playExitQuest)
*/
public QuestState exitQuest(boolean repeatable)
public void exitQuest(boolean repeatable)
{
_player.removeNotifyQuestOfDeath(this);
if (!isStarted())
{
return this;
return;
}
// Clean registered quest items
@@ -690,7 +658,6 @@ public class QuestState
setState(State.COMPLETED);
}
_vars = null;
return this;
}
/**
@@ -698,19 +665,18 @@ public class QuestState
* If {@code repeatable} is set to {@code false}, also removes all other quest data associated with this quest.
* @param repeatable if {@code true}, deletes all data and variables of this quest, otherwise keeps them
* @param playExitQuest if {@code true}, plays "ItemSound.quest_finish"
* @return this {@link QuestState} object
* @see #exitQuest(QuestType type)
* @see #exitQuest(QuestType type, boolean playExitQuest)
* @see #exitQuest(boolean repeatable)
*/
public QuestState exitQuest(boolean repeatable, boolean playExitQuest)
public void exitQuest(boolean repeatable, boolean playExitQuest)
{
exitQuest(repeatable);
if (playExitQuest)
{
_player.sendPacket(QuestSound.ITEMSOUND_QUEST_FINISH.getPacket());
}
return this;
return;
}
public void showQuestionMark(int number)

View File

@@ -17,8 +17,6 @@
package org.l2jmobius.gameserver.model.quest;
import java.util.concurrent.ScheduledFuture;
import java.util.logging.Level;
import java.util.logging.Logger;
import org.l2jmobius.commons.concurrent.ThreadPool;
import org.l2jmobius.gameserver.model.actor.Npc;
@@ -26,106 +24,68 @@ import org.l2jmobius.gameserver.model.actor.instance.PlayerInstance;
public class QuestTimer
{
protected static final Logger LOGGER = Logger.getLogger(QuestTimer.class.getName());
public class ScheduleTimerTask implements Runnable
{
@Override
public void run()
{
if (!_isActive)
{
return;
}
try
{
if (!_isRepeating)
{
cancelAndRemove();
}
_quest.notifyEvent(_name, _npc, _player);
}
catch (Exception e)
{
LOGGER.log(Level.SEVERE, "", e);
}
}
}
boolean _isActive = true;
final String _name;
final Quest _quest;
final Npc _npc;
final PlayerInstance _player;
final boolean _isRepeating;
private final ScheduledFuture<?> _schedular;
private final String _name;
private final Quest _quest;
private final Npc _npc;
private final PlayerInstance _player;
private final boolean _isRepeating;
private ScheduledFuture<?> _scheduler;
public QuestTimer(Quest quest, String name, long time, Npc npc, PlayerInstance player, boolean repeating)
{
_name = name;
_quest = quest;
_player = player;
_name = name;
_npc = npc;
_player = player;
_isRepeating = repeating;
_schedular = repeating ? ThreadPool.scheduleAtFixedRate(new ScheduleTimerTask(), time, time) : ThreadPool.schedule(new ScheduleTimerTask(), time);
}
public QuestTimer(Quest quest, String name, long time, Npc npc, PlayerInstance player)
{
this(quest, name, time, npc, player, false);
}
public QuestTimer(QuestState qs, String name, long time)
{
this(qs.getQuest(), name, time, null, qs.getPlayer(), false);
}
/**
* Cancel this quest timer.
*/
public void cancel()
{
_isActive = false;
if (_schedular != null)
if (repeating)
{
_schedular.cancel(false);
_scheduler = ThreadPool.scheduleAtFixedRate(new ScheduleTimerTask(), time, time); // Prepare auto end task
}
else
{
_scheduler = ThreadPool.schedule(new ScheduleTimerTask(), time); // Prepare auto end task
}
}
/**
* Cancel this quest timer and remove it from the associated quest.
*/
public void cancelAndRemove()
public void cancel()
{
cancel();
if (_scheduler != null)
{
_scheduler.cancel(false);
_scheduler = null;
}
_quest.removeQuestTimer(this);
}
/**
* Compares if this timer matches with the key attributes passed.
* @param quest the quest to which the timer is attached
* @param name the name of the timer
* @param npc the NPC attached to the desired timer (null if no NPC attached)
* @param player the player attached to the desired timer (null if no player attached)
* @return
* public method to compare if this timer matches with the key attributes passed.
* @param quest : Quest instance to which the timer is attached
* @param name : Name of the timer
* @param npc : Npc instance attached to the desired timer (null if no npc attached)
* @param player : Player instance attached to the desired timer (null if no player attached)
* @return boolean
*/
public boolean isMatch(Quest quest, String name, Npc npc, PlayerInstance player)
public boolean equals(Quest quest, String name, Npc npc, PlayerInstance player)
{
if ((quest == null) || (name == null))
if ((quest == null) || (quest != _quest))
{
return false;
}
if ((quest != _quest) || !name.equalsIgnoreCase(_name))
if ((name == null) || !name.equals(_name))
{
return false;
}
return ((npc == _npc) && (player == _player));
return (npc == _npc) && (player == _player);
}
public boolean isActive()
{
return _isActive;
return (_scheduler != null) && !_scheduler.isCancelled() && !_scheduler.isDone();
}
public boolean isRepeating()
@@ -158,4 +118,23 @@ public class QuestTimer
{
return _name;
}
public class ScheduleTimerTask implements Runnable
{
@Override
public void run()
{
if (_scheduler == null)
{
return;
}
if (!_isRepeating)
{
cancel();
}
_quest.notifyEvent(_name, _npc, _player);
}
}
}

View File

@@ -261,7 +261,7 @@ public class AdminQuest implements IAdminCommandHandler
{
for (QuestTimer timer : list)
{
timers += "<tr><td colspan=\"4\"><table width=270 border=0 bgcolor=131210><tr><td width=270><font color=\"LEVEL\">" + timer.getName() + ":</font> <font color=00FF00>Active: " + timer.isActive() + " Repeatable: " + timer.isRepeating() + " Player: " + timer.getPlayer() + " Npc: " + timer.getNpc() + "</font></td></tr></table></td></tr>";
timers += "<tr><td colspan=\"4\"><table width=270 border=0 bgcolor=131210><tr><td width=270><font color=\"LEVEL\">" + timer.toString() + ":</font> <font color=00FF00>Active: " + timer.isActive() + " Repeatable: " + timer.isRepeating() + " Player: " + timer.getPlayer() + " Npc: " + timer.getNpc() + "</font></td></tr></table></td></tr>";
counter++;
if (counter > 10)
{

View File

@@ -330,7 +330,7 @@ public class Quest extends AbstractScript implements IIdentifiable
{
for (QuestTimer timer : timers)
{
if ((timer != null) && timer.isMatch(this, name, npc, player))
if ((timer != null) && timer.equals(this, name, npc, player))
{
return timer;
}
@@ -388,7 +388,7 @@ public class Quest extends AbstractScript implements IIdentifiable
final QuestTimer timer = getQuestTimer(name, npc, player);
if (timer != null)
{
timer.cancelAndRemove();
timer.cancel();
}
}
@@ -401,7 +401,7 @@ public class Quest extends AbstractScript implements IIdentifiable
{
if ((timer != null) && (_questTimers != null))
{
final List<QuestTimer> timers = getQuestTimers().get(timer.getName());
final List<QuestTimer> timers = getQuestTimers().get(timer.toString());
if (timers != null)
{
_writeLock.lock();

View File

@@ -136,31 +136,29 @@ public class QuestState
/**
* @param state the new state of the quest to set
* @return {@code true} if state was changed, {@code false} otherwise
* @see #setState(byte state, boolean saveInDb)
* @see org.l2jmobius.gameserver.model.quest.State
*/
public boolean setState(byte state)
public void setState(byte state)
{
return setState(state, true);
setState(state, true);
}
/**
* Change the state of this quest to the specified value.
* @param state the new state of the quest to set
* @param saveInDb if {@code true}, will save the state change in the database
* @return {@code true} if state was changed, {@code false} otherwise
* @see org.l2jmobius.gameserver.model.quest.State
*/
public boolean setState(byte state, boolean saveInDb)
public void setState(byte state, boolean saveInDb)
{
if (_simulated)
{
return false;
return;
}
if (_state == state)
{
return false;
return;
}
final boolean newQuest = isCreated();
_state = state;
@@ -177,20 +175,18 @@ public class QuestState
}
_player.sendPacket(new QuestList(_player));
return true;
}
/**
* Add parameter used in quests.
* @param var String pointing out the name of the variable for quest
* @param value String pointing out the value of the variable for quest
* @return String (equal to parameter "value")
*/
public String setInternal(String var, String value)
public void setInternal(String var, String value)
{
if (_simulated)
{
return null;
return;
}
if (_vars == null)
@@ -204,16 +200,15 @@ public class QuestState
}
_vars.put(var, value);
return value;
}
public String set(String var, int value)
public void set(String var, int value)
{
if (_simulated)
{
return null;
return;
}
return set(var, Integer.toString(value));
set(var, Integer.toString(value));
}
/**
@@ -229,13 +224,12 @@ public class QuestState
* <ul>
* @param var String indicating the name of the variable for quest
* @param value String indicating the value of the variable for quest
* @return String (equal to parameter "value")
*/
public String set(String var, String value)
public void set(String var, String value)
{
if (_simulated)
{
return null;
return;
}
if (_vars == null)
@@ -279,8 +273,6 @@ public class QuestState
LOGGER.log(Level.WARNING, _player.getName() + ", " + _questName + " cond [" + value + "] is not an integer. Value stored, but no packet was sent: " + e.getMessage(), e);
}
}
return value;
}
/**
@@ -325,20 +317,15 @@ public class QuestState
// case 1: No steps have been skipped so far...
if (completedStateFlags == 0)
{
// check if this step also doesn't skip anything. If so, no further work is needed
// also, in this case, no work is needed if the state is being reset to a smaller value
// in those cases, skip forward to informing the client about the change...
// Check if this step also doesn't skip anything. If so, no further work is needed also, in this case, no work is needed if the state is being reset to a smaller value in those cases, skip forward to informing the client about the change...
// ELSE, if we just now skipped for the first time...prepare the flags!!!
if (cond > (old + 1))
{
// set the most significant bit to 1 (indicates that there exist skipped states)
// also, ensure that the least significant bit is an 1 (the first step is never skipped, no matter
// what the cond says)
// also, ensure that the least significant bit is an 1 (the first step is never skipped, no matter what the cond says)
completedStateFlags = 0x80000001;
// since no flag had been skipped until now, the least significant bits must all
// be set to 1, up until "old" number of bits.
// since no flag had been skipped until now, the least significant bits must all be set to 1, up until "old" number of bits.
completedStateFlags |= (1 << old) - 1;
// now, just set the bit corresponding to the passed cond to 1 (current step)
@@ -347,11 +334,9 @@ public class QuestState
}
}
// case 2: There were exist previously skipped steps
// if this is a push back to a previous step, clear all completion flags ahead
else if (cond < old)
else if (cond < old) // if this is a push back to a previous step, clear all completion flags ahead
{
// note, this also unsets the flag indicating that there exist skips
completedStateFlags &= (1 << cond) - 1;
completedStateFlags &= (1 << cond) - 1; // note, this also unsets the flag indicating that there exist skips
// now, check if this resulted in no steps being skipped any more
if (completedStateFlags == ((1 << cond) - 1))
@@ -361,8 +346,7 @@ public class QuestState
else
{
// set the most significant bit back to 1 again, to correctly indicate that this skips states.
// also, ensure that the least significant bit is an 1 (the first step is never skipped, no matter
// what the cond says)
// also, ensure that the least significant bit is an 1 (the first step is never skipped, no matter what the cond says)
completedStateFlags |= 0x80000001;
set("__compltdStateFlags", String.valueOf(completedStateFlags));
}
@@ -388,18 +372,17 @@ public class QuestState
/**
* Removes a quest variable from the list of existing quest variables.
* @param var the name of the variable to remove
* @return the previous value of the variable or {@code null} if none were found
*/
public String unset(String var)
public void unset(String var)
{
if (_simulated)
{
return null;
return;
}
if (_vars == null)
{
return null;
return;
}
final String old = _vars.remove(var);
@@ -407,7 +390,6 @@ public class QuestState
{
Quest.deleteQuestVarInDb(this, var);
}
return old;
}
/**
@@ -468,22 +450,21 @@ public class QuestState
/**
* Sets the quest state progress ({@code cond}) to the specified step.
* @param value the new value of the quest state progress
* @return this {@link QuestState} object
* @see #set(String var, String value)
* @see #setCond(int, boolean)
*/
public QuestState setCond(int value)
public void setCond(int value)
{
if (_simulated)
{
return null;
return;
}
if (isStarted())
{
set("cond", Integer.toString(value));
}
return this;
return;
}
/**
@@ -529,20 +510,19 @@ public class QuestState
* Sets the quest state progress ({@code cond}) to the specified step.
* @param value the new value of the quest state progress
* @param playQuestMiddle if {@code true}, plays "ItemSound.quest_middle"
* @return this {@link QuestState} object
* @see #setCond(int value)
* @see #set(String var, String value)
*/
public QuestState setCond(int value, boolean playQuestMiddle)
public void setCond(int value, boolean playQuestMiddle)
{
if (_simulated)
{
return null;
return;
}
if (!isStarted())
{
return this;
return;
}
set("cond", String.valueOf(value));
@@ -550,17 +530,15 @@ public class QuestState
{
_player.sendPacket(QuestSound.ITEMSOUND_QUEST_MIDDLE.getPacket());
}
return this;
}
public QuestState setMemoState(int value)
public void setMemoState(int value)
{
if (_simulated)
{
return null;
return;
}
set("memoState", String.valueOf(value));
return this;
}
/**
@@ -598,16 +576,14 @@ public class QuestState
* Sets the memo state ex.
* @param slot the slot where the value will be saved
* @param value the value
* @return this QuestState
*/
public QuestState setMemoStateEx(int slot, int value)
public void setMemoStateEx(int slot, int value)
{
if (_simulated)
{
return null;
return;
}
set("memoStateEx" + slot, String.valueOf(value));
return this;
}
/**
@@ -644,13 +620,12 @@ public class QuestState
/**
* Set condition to 1, state to STARTED and play the "ItemSound.quest_accept".<br>
* Works only if state is CREATED and the quest is not a custom quest.
* @return the newly created {@code QuestState} object
*/
public QuestState startQuest()
public void startQuest()
{
if (_simulated)
{
return null;
return;
}
if (isCreated() && !getQuest().isCustomQuest())
{
@@ -659,23 +634,21 @@ public class QuestState
_player.sendPacket(QuestSound.ITEMSOUND_QUEST_ACCEPT.getPacket());
getQuest().sendNpcLogList(getPlayer());
}
return this;
}
/**
* Finishes the quest and removes all quest items associated with this quest from the player's inventory.<br>
* If {@code type} is {@code QuestType.ONE_TIME}, also removes all other quest data associated with this quest.
* @param type the {@link QuestType} of the quest
* @return this {@link QuestState} object
* @see #exitQuest(QuestType type, boolean playExitQuest)
* @see #exitQuest(boolean repeatable)
* @see #exitQuest(boolean repeatable, boolean playExitQuest)
*/
public QuestState exitQuest(QuestType type)
public void exitQuest(QuestType type)
{
if (_simulated)
{
return null;
return;
}
switch (type)
@@ -697,8 +670,6 @@ public class QuestState
// Notify to scripts
EventDispatcher.getInstance().notifyEventAsync(new OnPlayerQuestComplete(_player, getQuest().getId(), type), _player);
return this;
}
/**
@@ -706,46 +677,43 @@ public class QuestState
* If {@code type} is {@code QuestType.ONE_TIME}, also removes all other quest data associated with this quest.
* @param type the {@link QuestType} of the quest
* @param playExitQuest if {@code true}, plays "ItemSound.quest_finish"
* @return this {@link QuestState} object
* @see #exitQuest(QuestType type)
* @see #exitQuest(boolean repeatable)
* @see #exitQuest(boolean repeatable, boolean playExitQuest)
*/
public QuestState exitQuest(QuestType type, boolean playExitQuest)
public void exitQuest(QuestType type, boolean playExitQuest)
{
if (_simulated)
{
return null;
return;
}
exitQuest(type);
if (playExitQuest)
{
_player.sendPacket(QuestSound.ITEMSOUND_QUEST_FINISH.getPacket());
}
return this;
}
/**
* Finishes the quest and removes all quest items associated with this quest from the player's inventory.<br>
* If {@code repeatable} is set to {@code false}, also removes all other quest data associated with this quest.
* @param repeatable if {@code true}, deletes all data and variables of this quest, otherwise keeps them
* @return this {@link QuestState} object
* @see #exitQuest(QuestType type)
* @see #exitQuest(QuestType type, boolean playExitQuest)
* @see #exitQuest(boolean repeatable, boolean playExitQuest)
*/
private QuestState exitQuest(boolean repeatable)
private void exitQuest(boolean repeatable)
{
if (_simulated)
{
return null;
return;
}
_player.removeNotifyQuestOfDeath(this);
if (!isStarted())
{
return this;
return;
}
// Clean registered quest items
@@ -762,7 +730,6 @@ public class QuestState
setState(State.COMPLETED);
}
_vars = null;
return this;
}
/**
@@ -770,16 +737,15 @@ public class QuestState
* If {@code repeatable} is set to {@code false}, also removes all other quest data associated with this quest.
* @param repeatable if {@code true}, deletes all data and variables of this quest, otherwise keeps them
* @param playExitQuest if {@code true}, plays "ItemSound.quest_finish"
* @return this {@link QuestState} object
* @see #exitQuest(QuestType type)
* @see #exitQuest(QuestType type, boolean playExitQuest)
* @see #exitQuest(boolean repeatable)
*/
public QuestState exitQuest(boolean repeatable, boolean playExitQuest)
public void exitQuest(boolean repeatable, boolean playExitQuest)
{
if (_simulated)
{
return null;
return;
}
exitQuest(repeatable);
@@ -790,7 +756,7 @@ public class QuestState
// Notify to scripts
EventDispatcher.getInstance().notifyEventAsync(new OnPlayerQuestComplete(_player, getQuest().getId(), repeatable ? QuestType.REPEATABLE : QuestType.ONE_TIME), _player);
return this;
return;
}
/**

View File

@@ -17,8 +17,6 @@
package org.l2jmobius.gameserver.model.quest;
import java.util.concurrent.ScheduledFuture;
import java.util.logging.Level;
import java.util.logging.Logger;
import org.l2jmobius.commons.concurrent.ThreadPool;
import org.l2jmobius.gameserver.model.actor.Npc;
@@ -26,106 +24,68 @@ import org.l2jmobius.gameserver.model.actor.instance.PlayerInstance;
public class QuestTimer
{
protected static final Logger LOGGER = Logger.getLogger(QuestTimer.class.getName());
public class ScheduleTimerTask implements Runnable
{
@Override
public void run()
{
if (!_isActive)
{
return;
}
try
{
if (!_isRepeating)
{
cancelAndRemove();
}
_quest.notifyEvent(_name, _npc, _player);
}
catch (Exception e)
{
LOGGER.log(Level.SEVERE, "", e);
}
}
}
boolean _isActive = true;
final String _name;
final Quest _quest;
final Npc _npc;
final PlayerInstance _player;
final boolean _isRepeating;
private final ScheduledFuture<?> _scheduler;
private final String _name;
private final Quest _quest;
private final Npc _npc;
private final PlayerInstance _player;
private final boolean _isRepeating;
private ScheduledFuture<?> _scheduler;
public QuestTimer(Quest quest, String name, long time, Npc npc, PlayerInstance player, boolean repeating)
{
_name = name;
_quest = quest;
_player = player;
_name = name;
_npc = npc;
_player = player;
_isRepeating = repeating;
_scheduler = repeating ? ThreadPool.scheduleAtFixedRate(new ScheduleTimerTask(), time, time) : ThreadPool.schedule(new ScheduleTimerTask(), time);
}
public QuestTimer(Quest quest, String name, long time, Npc npc, PlayerInstance player)
{
this(quest, name, time, npc, player, false);
}
public QuestTimer(QuestState qs, String name, long time)
{
this(qs.getQuest(), name, time, null, qs.getPlayer(), false);
}
/**
* Cancel this quest timer.
*/
public void cancel()
{
_isActive = false;
if (_scheduler != null)
if (repeating)
{
_scheduler.cancel(false);
_scheduler = ThreadPool.scheduleAtFixedRate(new ScheduleTimerTask(), time, time); // Prepare auto end task
}
else
{
_scheduler = ThreadPool.schedule(new ScheduleTimerTask(), time); // Prepare auto end task
}
}
/**
* Cancel this quest timer and remove it from the associated quest.
*/
public void cancelAndRemove()
public void cancel()
{
cancel();
if (_scheduler != null)
{
_scheduler.cancel(false);
_scheduler = null;
}
_quest.removeQuestTimer(this);
}
/**
* Compares if this timer matches with the key attributes passed.
* @param quest the quest to which the timer is attached
* @param name the name of the timer
* @param npc the NPC attached to the desired timer (null if no NPC attached)
* @param player the player attached to the desired timer (null if no player attached)
* @return
* public method to compare if this timer matches with the key attributes passed.
* @param quest : Quest instance to which the timer is attached
* @param name : Name of the timer
* @param npc : Npc instance attached to the desired timer (null if no npc attached)
* @param player : Player instance attached to the desired timer (null if no player attached)
* @return boolean
*/
public boolean isMatch(Quest quest, String name, Npc npc, PlayerInstance player)
public boolean equals(Quest quest, String name, Npc npc, PlayerInstance player)
{
if ((quest == null) || (name == null))
if ((quest == null) || (quest != _quest))
{
return false;
}
if ((quest != _quest) || !name.equalsIgnoreCase(_name))
if ((name == null) || !name.equals(_name))
{
return false;
}
return ((npc == _npc) && (player == _player));
return (npc == _npc) && (player == _player);
}
public boolean isActive()
{
return _isActive;
return (_scheduler != null) && !_scheduler.isCancelled() && !_scheduler.isDone();
}
public boolean isRepeating()
@@ -158,4 +118,23 @@ public class QuestTimer
{
return _name;
}
public class ScheduleTimerTask implements Runnable
{
@Override
public void run()
{
if (_scheduler == null)
{
return;
}
if (!_isRepeating)
{
cancel();
}
_quest.notifyEvent(_name, _npc, _player);
}
}
}

View File

@@ -261,7 +261,7 @@ public class AdminQuest implements IAdminCommandHandler
{
for (QuestTimer timer : list)
{
timers += "<tr><td colspan=\"4\"><table width=270 border=0 bgcolor=131210><tr><td width=270><font color=\"LEVEL\">" + timer.getName() + ":</font> <font color=00FF00>Active: " + timer.isActive() + " Repeatable: " + timer.isRepeating() + " Player: " + timer.getPlayer() + " Npc: " + timer.getNpc() + "</font></td></tr></table></td></tr>";
timers += "<tr><td colspan=\"4\"><table width=270 border=0 bgcolor=131210><tr><td width=270><font color=\"LEVEL\">" + timer.toString() + ":</font> <font color=00FF00>Active: " + timer.isActive() + " Repeatable: " + timer.isRepeating() + " Player: " + timer.getPlayer() + " Npc: " + timer.getNpc() + "</font></td></tr></table></td></tr>";
counter++;
if (counter > 10)
{

View File

@@ -330,7 +330,7 @@ public class Quest extends AbstractScript implements IIdentifiable
{
for (QuestTimer timer : timers)
{
if ((timer != null) && timer.isMatch(this, name, npc, player))
if ((timer != null) && timer.equals(this, name, npc, player))
{
return timer;
}
@@ -388,7 +388,7 @@ public class Quest extends AbstractScript implements IIdentifiable
final QuestTimer timer = getQuestTimer(name, npc, player);
if (timer != null)
{
timer.cancelAndRemove();
timer.cancel();
}
}
@@ -401,7 +401,7 @@ public class Quest extends AbstractScript implements IIdentifiable
{
if ((timer != null) && (_questTimers != null))
{
final List<QuestTimer> timers = getQuestTimers().get(timer.getName());
final List<QuestTimer> timers = getQuestTimers().get(timer.toString());
if (timers != null)
{
_writeLock.lock();

View File

@@ -136,31 +136,29 @@ public class QuestState
/**
* @param state the new state of the quest to set
* @return {@code true} if state was changed, {@code false} otherwise
* @see #setState(byte state, boolean saveInDb)
* @see org.l2jmobius.gameserver.model.quest.State
*/
public boolean setState(byte state)
public void setState(byte state)
{
return setState(state, true);
setState(state, true);
}
/**
* Change the state of this quest to the specified value.
* @param state the new state of the quest to set
* @param saveInDb if {@code true}, will save the state change in the database
* @return {@code true} if state was changed, {@code false} otherwise
* @see org.l2jmobius.gameserver.model.quest.State
*/
public boolean setState(byte state, boolean saveInDb)
public void setState(byte state, boolean saveInDb)
{
if (_simulated)
{
return false;
return;
}
if (_state == state)
{
return false;
return;
}
final boolean newQuest = isCreated();
_state = state;
@@ -177,20 +175,18 @@ public class QuestState
}
_player.sendPacket(new QuestList(_player));
return true;
}
/**
* Add parameter used in quests.
* @param var String pointing out the name of the variable for quest
* @param value String pointing out the value of the variable for quest
* @return String (equal to parameter "value")
*/
public String setInternal(String var, String value)
public void setInternal(String var, String value)
{
if (_simulated)
{
return null;
return;
}
if (_vars == null)
@@ -204,16 +200,15 @@ public class QuestState
}
_vars.put(var, value);
return value;
}
public String set(String var, int value)
public void set(String var, int value)
{
if (_simulated)
{
return null;
return;
}
return set(var, Integer.toString(value));
set(var, Integer.toString(value));
}
/**
@@ -229,13 +224,12 @@ public class QuestState
* <ul>
* @param var String indicating the name of the variable for quest
* @param value String indicating the value of the variable for quest
* @return String (equal to parameter "value")
*/
public String set(String var, String value)
public void set(String var, String value)
{
if (_simulated)
{
return null;
return;
}
if (_vars == null)
@@ -279,8 +273,6 @@ public class QuestState
LOGGER.log(Level.WARNING, _player.getName() + ", " + _questName + " cond [" + value + "] is not an integer. Value stored, but no packet was sent: " + e.getMessage(), e);
}
}
return value;
}
/**
@@ -325,20 +317,15 @@ public class QuestState
// case 1: No steps have been skipped so far...
if (completedStateFlags == 0)
{
// check if this step also doesn't skip anything. If so, no further work is needed
// also, in this case, no work is needed if the state is being reset to a smaller value
// in those cases, skip forward to informing the client about the change...
// Check if this step also doesn't skip anything. If so, no further work is needed also, in this case, no work is needed if the state is being reset to a smaller value in those cases, skip forward to informing the client about the change...
// ELSE, if we just now skipped for the first time...prepare the flags!!!
if (cond > (old + 1))
{
// set the most significant bit to 1 (indicates that there exist skipped states)
// also, ensure that the least significant bit is an 1 (the first step is never skipped, no matter
// what the cond says)
// also, ensure that the least significant bit is an 1 (the first step is never skipped, no matter what the cond says)
completedStateFlags = 0x80000001;
// since no flag had been skipped until now, the least significant bits must all
// be set to 1, up until "old" number of bits.
// since no flag had been skipped until now, the least significant bits must all be set to 1, up until "old" number of bits.
completedStateFlags |= (1 << old) - 1;
// now, just set the bit corresponding to the passed cond to 1 (current step)
@@ -347,11 +334,9 @@ public class QuestState
}
}
// case 2: There were exist previously skipped steps
// if this is a push back to a previous step, clear all completion flags ahead
else if (cond < old)
else if (cond < old) // if this is a push back to a previous step, clear all completion flags ahead
{
// note, this also unsets the flag indicating that there exist skips
completedStateFlags &= (1 << cond) - 1;
completedStateFlags &= (1 << cond) - 1; // note, this also unsets the flag indicating that there exist skips
// now, check if this resulted in no steps being skipped any more
if (completedStateFlags == ((1 << cond) - 1))
@@ -361,8 +346,7 @@ public class QuestState
else
{
// set the most significant bit back to 1 again, to correctly indicate that this skips states.
// also, ensure that the least significant bit is an 1 (the first step is never skipped, no matter
// what the cond says)
// also, ensure that the least significant bit is an 1 (the first step is never skipped, no matter what the cond says)
completedStateFlags |= 0x80000001;
set("__compltdStateFlags", String.valueOf(completedStateFlags));
}
@@ -388,18 +372,17 @@ public class QuestState
/**
* Removes a quest variable from the list of existing quest variables.
* @param var the name of the variable to remove
* @return the previous value of the variable or {@code null} if none were found
*/
public String unset(String var)
public void unset(String var)
{
if (_simulated)
{
return null;
return;
}
if (_vars == null)
{
return null;
return;
}
final String old = _vars.remove(var);
@@ -407,7 +390,6 @@ public class QuestState
{
Quest.deleteQuestVarInDb(this, var);
}
return old;
}
/**
@@ -468,22 +450,21 @@ public class QuestState
/**
* Sets the quest state progress ({@code cond}) to the specified step.
* @param value the new value of the quest state progress
* @return this {@link QuestState} object
* @see #set(String var, String value)
* @see #setCond(int, boolean)
*/
public QuestState setCond(int value)
public void setCond(int value)
{
if (_simulated)
{
return null;
return;
}
if (isStarted())
{
set("cond", Integer.toString(value));
}
return this;
return;
}
/**
@@ -529,20 +510,19 @@ public class QuestState
* Sets the quest state progress ({@code cond}) to the specified step.
* @param value the new value of the quest state progress
* @param playQuestMiddle if {@code true}, plays "ItemSound.quest_middle"
* @return this {@link QuestState} object
* @see #setCond(int value)
* @see #set(String var, String value)
*/
public QuestState setCond(int value, boolean playQuestMiddle)
public void setCond(int value, boolean playQuestMiddle)
{
if (_simulated)
{
return null;
return;
}
if (!isStarted())
{
return this;
return;
}
set("cond", String.valueOf(value));
@@ -550,17 +530,15 @@ public class QuestState
{
_player.sendPacket(QuestSound.ITEMSOUND_QUEST_MIDDLE.getPacket());
}
return this;
}
public QuestState setMemoState(int value)
public void setMemoState(int value)
{
if (_simulated)
{
return null;
return;
}
set("memoState", String.valueOf(value));
return this;
}
/**
@@ -598,16 +576,14 @@ public class QuestState
* Sets the memo state ex.
* @param slot the slot where the value will be saved
* @param value the value
* @return this QuestState
*/
public QuestState setMemoStateEx(int slot, int value)
public void setMemoStateEx(int slot, int value)
{
if (_simulated)
{
return null;
return;
}
set("memoStateEx" + slot, String.valueOf(value));
return this;
}
/**
@@ -644,13 +620,12 @@ public class QuestState
/**
* Set condition to 1, state to STARTED and play the "ItemSound.quest_accept".<br>
* Works only if state is CREATED and the quest is not a custom quest.
* @return the newly created {@code QuestState} object
*/
public QuestState startQuest()
public void startQuest()
{
if (_simulated)
{
return null;
return;
}
if (isCreated() && !getQuest().isCustomQuest())
{
@@ -659,23 +634,21 @@ public class QuestState
_player.sendPacket(QuestSound.ITEMSOUND_QUEST_ACCEPT.getPacket());
getQuest().sendNpcLogList(getPlayer());
}
return this;
}
/**
* Finishes the quest and removes all quest items associated with this quest from the player's inventory.<br>
* If {@code type} is {@code QuestType.ONE_TIME}, also removes all other quest data associated with this quest.
* @param type the {@link QuestType} of the quest
* @return this {@link QuestState} object
* @see #exitQuest(QuestType type, boolean playExitQuest)
* @see #exitQuest(boolean repeatable)
* @see #exitQuest(boolean repeatable, boolean playExitQuest)
*/
public QuestState exitQuest(QuestType type)
public void exitQuest(QuestType type)
{
if (_simulated)
{
return null;
return;
}
switch (type)
@@ -697,8 +670,6 @@ public class QuestState
// Notify to scripts
EventDispatcher.getInstance().notifyEventAsync(new OnPlayerQuestComplete(_player, getQuest().getId(), type), _player);
return this;
}
/**
@@ -706,46 +677,43 @@ public class QuestState
* If {@code type} is {@code QuestType.ONE_TIME}, also removes all other quest data associated with this quest.
* @param type the {@link QuestType} of the quest
* @param playExitQuest if {@code true}, plays "ItemSound.quest_finish"
* @return this {@link QuestState} object
* @see #exitQuest(QuestType type)
* @see #exitQuest(boolean repeatable)
* @see #exitQuest(boolean repeatable, boolean playExitQuest)
*/
public QuestState exitQuest(QuestType type, boolean playExitQuest)
public void exitQuest(QuestType type, boolean playExitQuest)
{
if (_simulated)
{
return null;
return;
}
exitQuest(type);
if (playExitQuest)
{
_player.sendPacket(QuestSound.ITEMSOUND_QUEST_FINISH.getPacket());
}
return this;
}
/**
* Finishes the quest and removes all quest items associated with this quest from the player's inventory.<br>
* If {@code repeatable} is set to {@code false}, also removes all other quest data associated with this quest.
* @param repeatable if {@code true}, deletes all data and variables of this quest, otherwise keeps them
* @return this {@link QuestState} object
* @see #exitQuest(QuestType type)
* @see #exitQuest(QuestType type, boolean playExitQuest)
* @see #exitQuest(boolean repeatable, boolean playExitQuest)
*/
private QuestState exitQuest(boolean repeatable)
private void exitQuest(boolean repeatable)
{
if (_simulated)
{
return null;
return;
}
_player.removeNotifyQuestOfDeath(this);
if (!isStarted())
{
return this;
return;
}
// Clean registered quest items
@@ -762,7 +730,6 @@ public class QuestState
setState(State.COMPLETED);
}
_vars = null;
return this;
}
/**
@@ -770,16 +737,15 @@ public class QuestState
* If {@code repeatable} is set to {@code false}, also removes all other quest data associated with this quest.
* @param repeatable if {@code true}, deletes all data and variables of this quest, otherwise keeps them
* @param playExitQuest if {@code true}, plays "ItemSound.quest_finish"
* @return this {@link QuestState} object
* @see #exitQuest(QuestType type)
* @see #exitQuest(QuestType type, boolean playExitQuest)
* @see #exitQuest(boolean repeatable)
*/
public QuestState exitQuest(boolean repeatable, boolean playExitQuest)
public void exitQuest(boolean repeatable, boolean playExitQuest)
{
if (_simulated)
{
return null;
return;
}
exitQuest(repeatable);
@@ -790,7 +756,7 @@ public class QuestState
// Notify to scripts
EventDispatcher.getInstance().notifyEventAsync(new OnPlayerQuestComplete(_player, getQuest().getId(), repeatable ? QuestType.REPEATABLE : QuestType.ONE_TIME), _player);
return this;
return;
}
/**

View File

@@ -17,8 +17,6 @@
package org.l2jmobius.gameserver.model.quest;
import java.util.concurrent.ScheduledFuture;
import java.util.logging.Level;
import java.util.logging.Logger;
import org.l2jmobius.commons.concurrent.ThreadPool;
import org.l2jmobius.gameserver.model.actor.Npc;
@@ -26,106 +24,68 @@ import org.l2jmobius.gameserver.model.actor.instance.PlayerInstance;
public class QuestTimer
{
protected static final Logger LOGGER = Logger.getLogger(QuestTimer.class.getName());
public class ScheduleTimerTask implements Runnable
{
@Override
public void run()
{
if (!_isActive)
{
return;
}
try
{
if (!_isRepeating)
{
cancelAndRemove();
}
_quest.notifyEvent(_name, _npc, _player);
}
catch (Exception e)
{
LOGGER.log(Level.SEVERE, "", e);
}
}
}
boolean _isActive = true;
final String _name;
final Quest _quest;
final Npc _npc;
final PlayerInstance _player;
final boolean _isRepeating;
private final ScheduledFuture<?> _scheduler;
private final String _name;
private final Quest _quest;
private final Npc _npc;
private final PlayerInstance _player;
private final boolean _isRepeating;
private ScheduledFuture<?> _scheduler;
public QuestTimer(Quest quest, String name, long time, Npc npc, PlayerInstance player, boolean repeating)
{
_name = name;
_quest = quest;
_player = player;
_name = name;
_npc = npc;
_player = player;
_isRepeating = repeating;
_scheduler = repeating ? ThreadPool.scheduleAtFixedRate(new ScheduleTimerTask(), time, time) : ThreadPool.schedule(new ScheduleTimerTask(), time);
}
public QuestTimer(Quest quest, String name, long time, Npc npc, PlayerInstance player)
{
this(quest, name, time, npc, player, false);
}
public QuestTimer(QuestState qs, String name, long time)
{
this(qs.getQuest(), name, time, null, qs.getPlayer(), false);
}
/**
* Cancel this quest timer.
*/
public void cancel()
{
_isActive = false;
if (_scheduler != null)
if (repeating)
{
_scheduler.cancel(false);
_scheduler = ThreadPool.scheduleAtFixedRate(new ScheduleTimerTask(), time, time); // Prepare auto end task
}
else
{
_scheduler = ThreadPool.schedule(new ScheduleTimerTask(), time); // Prepare auto end task
}
}
/**
* Cancel this quest timer and remove it from the associated quest.
*/
public void cancelAndRemove()
public void cancel()
{
cancel();
if (_scheduler != null)
{
_scheduler.cancel(false);
_scheduler = null;
}
_quest.removeQuestTimer(this);
}
/**
* Compares if this timer matches with the key attributes passed.
* @param quest the quest to which the timer is attached
* @param name the name of the timer
* @param npc the NPC attached to the desired timer (null if no NPC attached)
* @param player the player attached to the desired timer (null if no player attached)
* @return
* public method to compare if this timer matches with the key attributes passed.
* @param quest : Quest instance to which the timer is attached
* @param name : Name of the timer
* @param npc : Npc instance attached to the desired timer (null if no npc attached)
* @param player : Player instance attached to the desired timer (null if no player attached)
* @return boolean
*/
public boolean isMatch(Quest quest, String name, Npc npc, PlayerInstance player)
public boolean equals(Quest quest, String name, Npc npc, PlayerInstance player)
{
if ((quest == null) || (name == null))
if ((quest == null) || (quest != _quest))
{
return false;
}
if ((quest != _quest) || !name.equalsIgnoreCase(_name))
if ((name == null) || !name.equals(_name))
{
return false;
}
return ((npc == _npc) && (player == _player));
return (npc == _npc) && (player == _player);
}
public boolean isActive()
{
return _isActive;
return (_scheduler != null) && !_scheduler.isCancelled() && !_scheduler.isDone();
}
public boolean isRepeating()
@@ -158,4 +118,23 @@ public class QuestTimer
{
return _name;
}
public class ScheduleTimerTask implements Runnable
{
@Override
public void run()
{
if (_scheduler == null)
{
return;
}
if (!_isRepeating)
{
cancel();
}
_quest.notifyEvent(_name, _npc, _player);
}
}
}

View File

@@ -261,7 +261,7 @@ public class AdminQuest implements IAdminCommandHandler
{
for (QuestTimer timer : list)
{
timers += "<tr><td colspan=\"4\"><table width=270 border=0 bgcolor=131210><tr><td width=270><font color=\"LEVEL\">" + timer.getName() + ":</font> <font color=00FF00>Active: " + timer.isActive() + " Repeatable: " + timer.isRepeating() + " Player: " + timer.getPlayer() + " Npc: " + timer.getNpc() + "</font></td></tr></table></td></tr>";
timers += "<tr><td colspan=\"4\"><table width=270 border=0 bgcolor=131210><tr><td width=270><font color=\"LEVEL\">" + timer.toString() + ":</font> <font color=00FF00>Active: " + timer.isActive() + " Repeatable: " + timer.isRepeating() + " Player: " + timer.getPlayer() + " Npc: " + timer.getNpc() + "</font></td></tr></table></td></tr>";
counter++;
if (counter > 10)
{

View File

@@ -330,7 +330,7 @@ public class Quest extends AbstractScript implements IIdentifiable
{
for (QuestTimer timer : timers)
{
if ((timer != null) && timer.isMatch(this, name, npc, player))
if ((timer != null) && timer.equals(this, name, npc, player))
{
return timer;
}
@@ -388,7 +388,7 @@ public class Quest extends AbstractScript implements IIdentifiable
final QuestTimer timer = getQuestTimer(name, npc, player);
if (timer != null)
{
timer.cancelAndRemove();
timer.cancel();
}
}
@@ -401,7 +401,7 @@ public class Quest extends AbstractScript implements IIdentifiable
{
if ((timer != null) && (_questTimers != null))
{
final List<QuestTimer> timers = getQuestTimers().get(timer.getName());
final List<QuestTimer> timers = getQuestTimers().get(timer.toString());
if (timers != null)
{
_writeLock.lock();

View File

@@ -136,31 +136,29 @@ public class QuestState
/**
* @param state the new state of the quest to set
* @return {@code true} if state was changed, {@code false} otherwise
* @see #setState(byte state, boolean saveInDb)
* @see org.l2jmobius.gameserver.model.quest.State
*/
public boolean setState(byte state)
public void setState(byte state)
{
return setState(state, true);
setState(state, true);
}
/**
* Change the state of this quest to the specified value.
* @param state the new state of the quest to set
* @param saveInDb if {@code true}, will save the state change in the database
* @return {@code true} if state was changed, {@code false} otherwise
* @see org.l2jmobius.gameserver.model.quest.State
*/
public boolean setState(byte state, boolean saveInDb)
public void setState(byte state, boolean saveInDb)
{
if (_simulated)
{
return false;
return;
}
if (_state == state)
{
return false;
return;
}
final boolean newQuest = isCreated();
_state = state;
@@ -177,20 +175,18 @@ public class QuestState
}
_player.sendPacket(new QuestList(_player));
return true;
}
/**
* Add parameter used in quests.
* @param var String pointing out the name of the variable for quest
* @param value String pointing out the value of the variable for quest
* @return String (equal to parameter "value")
*/
public String setInternal(String var, String value)
public void setInternal(String var, String value)
{
if (_simulated)
{
return null;
return;
}
if (_vars == null)
@@ -204,16 +200,15 @@ public class QuestState
}
_vars.put(var, value);
return value;
}
public String set(String var, int value)
public void set(String var, int value)
{
if (_simulated)
{
return null;
return;
}
return set(var, Integer.toString(value));
set(var, Integer.toString(value));
}
/**
@@ -229,13 +224,12 @@ public class QuestState
* <ul>
* @param var String indicating the name of the variable for quest
* @param value String indicating the value of the variable for quest
* @return String (equal to parameter "value")
*/
public String set(String var, String value)
public void set(String var, String value)
{
if (_simulated)
{
return null;
return;
}
if (_vars == null)
@@ -279,8 +273,6 @@ public class QuestState
LOGGER.log(Level.WARNING, _player.getName() + ", " + _questName + " cond [" + value + "] is not an integer. Value stored, but no packet was sent: " + e.getMessage(), e);
}
}
return value;
}
/**
@@ -325,20 +317,15 @@ public class QuestState
// case 1: No steps have been skipped so far...
if (completedStateFlags == 0)
{
// check if this step also doesn't skip anything. If so, no further work is needed
// also, in this case, no work is needed if the state is being reset to a smaller value
// in those cases, skip forward to informing the client about the change...
// Check if this step also doesn't skip anything. If so, no further work is needed also, in this case, no work is needed if the state is being reset to a smaller value in those cases, skip forward to informing the client about the change...
// ELSE, if we just now skipped for the first time...prepare the flags!!!
if (cond > (old + 1))
{
// set the most significant bit to 1 (indicates that there exist skipped states)
// also, ensure that the least significant bit is an 1 (the first step is never skipped, no matter
// what the cond says)
// also, ensure that the least significant bit is an 1 (the first step is never skipped, no matter what the cond says)
completedStateFlags = 0x80000001;
// since no flag had been skipped until now, the least significant bits must all
// be set to 1, up until "old" number of bits.
// since no flag had been skipped until now, the least significant bits must all be set to 1, up until "old" number of bits.
completedStateFlags |= (1 << old) - 1;
// now, just set the bit corresponding to the passed cond to 1 (current step)
@@ -347,11 +334,9 @@ public class QuestState
}
}
// case 2: There were exist previously skipped steps
// if this is a push back to a previous step, clear all completion flags ahead
else if (cond < old)
else if (cond < old) // if this is a push back to a previous step, clear all completion flags ahead
{
// note, this also unsets the flag indicating that there exist skips
completedStateFlags &= (1 << cond) - 1;
completedStateFlags &= (1 << cond) - 1; // note, this also unsets the flag indicating that there exist skips
// now, check if this resulted in no steps being skipped any more
if (completedStateFlags == ((1 << cond) - 1))
@@ -361,8 +346,7 @@ public class QuestState
else
{
// set the most significant bit back to 1 again, to correctly indicate that this skips states.
// also, ensure that the least significant bit is an 1 (the first step is never skipped, no matter
// what the cond says)
// also, ensure that the least significant bit is an 1 (the first step is never skipped, no matter what the cond says)
completedStateFlags |= 0x80000001;
set("__compltdStateFlags", String.valueOf(completedStateFlags));
}
@@ -388,18 +372,17 @@ public class QuestState
/**
* Removes a quest variable from the list of existing quest variables.
* @param var the name of the variable to remove
* @return the previous value of the variable or {@code null} if none were found
*/
public String unset(String var)
public void unset(String var)
{
if (_simulated)
{
return null;
return;
}
if (_vars == null)
{
return null;
return;
}
final String old = _vars.remove(var);
@@ -407,7 +390,6 @@ public class QuestState
{
Quest.deleteQuestVarInDb(this, var);
}
return old;
}
/**
@@ -468,22 +450,21 @@ public class QuestState
/**
* Sets the quest state progress ({@code cond}) to the specified step.
* @param value the new value of the quest state progress
* @return this {@link QuestState} object
* @see #set(String var, String value)
* @see #setCond(int, boolean)
*/
public QuestState setCond(int value)
public void setCond(int value)
{
if (_simulated)
{
return null;
return;
}
if (isStarted())
{
set("cond", Integer.toString(value));
}
return this;
return;
}
/**
@@ -529,20 +510,19 @@ public class QuestState
* Sets the quest state progress ({@code cond}) to the specified step.
* @param value the new value of the quest state progress
* @param playQuestMiddle if {@code true}, plays "ItemSound.quest_middle"
* @return this {@link QuestState} object
* @see #setCond(int value)
* @see #set(String var, String value)
*/
public QuestState setCond(int value, boolean playQuestMiddle)
public void setCond(int value, boolean playQuestMiddle)
{
if (_simulated)
{
return null;
return;
}
if (!isStarted())
{
return this;
return;
}
set("cond", String.valueOf(value));
@@ -550,17 +530,15 @@ public class QuestState
{
_player.sendPacket(QuestSound.ITEMSOUND_QUEST_MIDDLE.getPacket());
}
return this;
}
public QuestState setMemoState(int value)
public void setMemoState(int value)
{
if (_simulated)
{
return null;
return;
}
set("memoState", String.valueOf(value));
return this;
}
/**
@@ -598,16 +576,14 @@ public class QuestState
* Sets the memo state ex.
* @param slot the slot where the value will be saved
* @param value the value
* @return this QuestState
*/
public QuestState setMemoStateEx(int slot, int value)
public void setMemoStateEx(int slot, int value)
{
if (_simulated)
{
return null;
return;
}
set("memoStateEx" + slot, String.valueOf(value));
return this;
}
/**
@@ -644,13 +620,12 @@ public class QuestState
/**
* Set condition to 1, state to STARTED and play the "ItemSound.quest_accept".<br>
* Works only if state is CREATED and the quest is not a custom quest.
* @return the newly created {@code QuestState} object
*/
public QuestState startQuest()
public void startQuest()
{
if (_simulated)
{
return null;
return;
}
if (isCreated() && !getQuest().isCustomQuest())
{
@@ -659,23 +634,21 @@ public class QuestState
_player.sendPacket(QuestSound.ITEMSOUND_QUEST_ACCEPT.getPacket());
getQuest().sendNpcLogList(getPlayer());
}
return this;
}
/**
* Finishes the quest and removes all quest items associated with this quest from the player's inventory.<br>
* If {@code type} is {@code QuestType.ONE_TIME}, also removes all other quest data associated with this quest.
* @param type the {@link QuestType} of the quest
* @return this {@link QuestState} object
* @see #exitQuest(QuestType type, boolean playExitQuest)
* @see #exitQuest(boolean repeatable)
* @see #exitQuest(boolean repeatable, boolean playExitQuest)
*/
public QuestState exitQuest(QuestType type)
public void exitQuest(QuestType type)
{
if (_simulated)
{
return null;
return;
}
switch (type)
@@ -697,8 +670,6 @@ public class QuestState
// Notify to scripts
EventDispatcher.getInstance().notifyEventAsync(new OnPlayerQuestComplete(_player, getQuest().getId(), type), _player);
return this;
}
/**
@@ -706,46 +677,43 @@ public class QuestState
* If {@code type} is {@code QuestType.ONE_TIME}, also removes all other quest data associated with this quest.
* @param type the {@link QuestType} of the quest
* @param playExitQuest if {@code true}, plays "ItemSound.quest_finish"
* @return this {@link QuestState} object
* @see #exitQuest(QuestType type)
* @see #exitQuest(boolean repeatable)
* @see #exitQuest(boolean repeatable, boolean playExitQuest)
*/
public QuestState exitQuest(QuestType type, boolean playExitQuest)
public void exitQuest(QuestType type, boolean playExitQuest)
{
if (_simulated)
{
return null;
return;
}
exitQuest(type);
if (playExitQuest)
{
_player.sendPacket(QuestSound.ITEMSOUND_QUEST_FINISH.getPacket());
}
return this;
}
/**
* Finishes the quest and removes all quest items associated with this quest from the player's inventory.<br>
* If {@code repeatable} is set to {@code false}, also removes all other quest data associated with this quest.
* @param repeatable if {@code true}, deletes all data and variables of this quest, otherwise keeps them
* @return this {@link QuestState} object
* @see #exitQuest(QuestType type)
* @see #exitQuest(QuestType type, boolean playExitQuest)
* @see #exitQuest(boolean repeatable, boolean playExitQuest)
*/
private QuestState exitQuest(boolean repeatable)
private void exitQuest(boolean repeatable)
{
if (_simulated)
{
return null;
return;
}
_player.removeNotifyQuestOfDeath(this);
if (!isStarted())
{
return this;
return;
}
// Clean registered quest items
@@ -762,7 +730,6 @@ public class QuestState
setState(State.COMPLETED);
}
_vars = null;
return this;
}
/**
@@ -770,16 +737,15 @@ public class QuestState
* If {@code repeatable} is set to {@code false}, also removes all other quest data associated with this quest.
* @param repeatable if {@code true}, deletes all data and variables of this quest, otherwise keeps them
* @param playExitQuest if {@code true}, plays "ItemSound.quest_finish"
* @return this {@link QuestState} object
* @see #exitQuest(QuestType type)
* @see #exitQuest(QuestType type, boolean playExitQuest)
* @see #exitQuest(boolean repeatable)
*/
public QuestState exitQuest(boolean repeatable, boolean playExitQuest)
public void exitQuest(boolean repeatable, boolean playExitQuest)
{
if (_simulated)
{
return null;
return;
}
exitQuest(repeatable);
@@ -790,7 +756,7 @@ public class QuestState
// Notify to scripts
EventDispatcher.getInstance().notifyEventAsync(new OnPlayerQuestComplete(_player, getQuest().getId(), repeatable ? QuestType.REPEATABLE : QuestType.ONE_TIME), _player);
return this;
return;
}
/**

View File

@@ -17,8 +17,6 @@
package org.l2jmobius.gameserver.model.quest;
import java.util.concurrent.ScheduledFuture;
import java.util.logging.Level;
import java.util.logging.Logger;
import org.l2jmobius.commons.concurrent.ThreadPool;
import org.l2jmobius.gameserver.model.actor.Npc;
@@ -26,106 +24,68 @@ import org.l2jmobius.gameserver.model.actor.instance.PlayerInstance;
public class QuestTimer
{
protected static final Logger LOGGER = Logger.getLogger(QuestTimer.class.getName());
public class ScheduleTimerTask implements Runnable
{
@Override
public void run()
{
if (!_isActive)
{
return;
}
try
{
if (!_isRepeating)
{
cancelAndRemove();
}
_quest.notifyEvent(_name, _npc, _player);
}
catch (Exception e)
{
LOGGER.log(Level.SEVERE, "", e);
}
}
}
boolean _isActive = true;
final String _name;
final Quest _quest;
final Npc _npc;
final PlayerInstance _player;
final boolean _isRepeating;
private final ScheduledFuture<?> _scheduler;
private final String _name;
private final Quest _quest;
private final Npc _npc;
private final PlayerInstance _player;
private final boolean _isRepeating;
private ScheduledFuture<?> _scheduler;
public QuestTimer(Quest quest, String name, long time, Npc npc, PlayerInstance player, boolean repeating)
{
_name = name;
_quest = quest;
_player = player;
_name = name;
_npc = npc;
_player = player;
_isRepeating = repeating;
_scheduler = repeating ? ThreadPool.scheduleAtFixedRate(new ScheduleTimerTask(), time, time) : ThreadPool.schedule(new ScheduleTimerTask(), time);
}
public QuestTimer(Quest quest, String name, long time, Npc npc, PlayerInstance player)
{
this(quest, name, time, npc, player, false);
}
public QuestTimer(QuestState qs, String name, long time)
{
this(qs.getQuest(), name, time, null, qs.getPlayer(), false);
}
/**
* Cancel this quest timer.
*/
public void cancel()
{
_isActive = false;
if (_scheduler != null)
if (repeating)
{
_scheduler.cancel(false);
_scheduler = ThreadPool.scheduleAtFixedRate(new ScheduleTimerTask(), time, time); // Prepare auto end task
}
else
{
_scheduler = ThreadPool.schedule(new ScheduleTimerTask(), time); // Prepare auto end task
}
}
/**
* Cancel this quest timer and remove it from the associated quest.
*/
public void cancelAndRemove()
public void cancel()
{
cancel();
if (_scheduler != null)
{
_scheduler.cancel(false);
_scheduler = null;
}
_quest.removeQuestTimer(this);
}
/**
* Compares if this timer matches with the key attributes passed.
* @param quest the quest to which the timer is attached
* @param name the name of the timer
* @param npc the NPC attached to the desired timer (null if no NPC attached)
* @param player the player attached to the desired timer (null if no player attached)
* @return
* public method to compare if this timer matches with the key attributes passed.
* @param quest : Quest instance to which the timer is attached
* @param name : Name of the timer
* @param npc : Npc instance attached to the desired timer (null if no npc attached)
* @param player : Player instance attached to the desired timer (null if no player attached)
* @return boolean
*/
public boolean isMatch(Quest quest, String name, Npc npc, PlayerInstance player)
public boolean equals(Quest quest, String name, Npc npc, PlayerInstance player)
{
if ((quest == null) || (name == null))
if ((quest == null) || (quest != _quest))
{
return false;
}
if ((quest != _quest) || !name.equalsIgnoreCase(_name))
if ((name == null) || !name.equals(_name))
{
return false;
}
return ((npc == _npc) && (player == _player));
return (npc == _npc) && (player == _player);
}
public boolean isActive()
{
return _isActive;
return (_scheduler != null) && !_scheduler.isCancelled() && !_scheduler.isDone();
}
public boolean isRepeating()
@@ -158,4 +118,23 @@ public class QuestTimer
{
return _name;
}
public class ScheduleTimerTask implements Runnable
{
@Override
public void run()
{
if (_scheduler == null)
{
return;
}
if (!_isRepeating)
{
cancel();
}
_quest.notifyEvent(_name, _npc, _player);
}
}
}

View File

@@ -261,7 +261,7 @@ public class AdminQuest implements IAdminCommandHandler
{
for (QuestTimer timer : list)
{
timers += "<tr><td colspan=\"4\"><table width=270 border=0 bgcolor=131210><tr><td width=270><font color=\"LEVEL\">" + timer.getName() + ":</font> <font color=00FF00>Active: " + timer.isActive() + " Repeatable: " + timer.isRepeating() + " Player: " + timer.getPlayer() + " Npc: " + timer.getNpc() + "</font></td></tr></table></td></tr>";
timers += "<tr><td colspan=\"4\"><table width=270 border=0 bgcolor=131210><tr><td width=270><font color=\"LEVEL\">" + timer.toString() + ":</font> <font color=00FF00>Active: " + timer.isActive() + " Repeatable: " + timer.isRepeating() + " Player: " + timer.getPlayer() + " Npc: " + timer.getNpc() + "</font></td></tr></table></td></tr>";
counter++;
if (counter > 10)
{

View File

@@ -330,7 +330,7 @@ public class Quest extends AbstractScript implements IIdentifiable
{
for (QuestTimer timer : timers)
{
if ((timer != null) && timer.isMatch(this, name, npc, player))
if ((timer != null) && timer.equals(this, name, npc, player))
{
return timer;
}
@@ -388,7 +388,7 @@ public class Quest extends AbstractScript implements IIdentifiable
final QuestTimer timer = getQuestTimer(name, npc, player);
if (timer != null)
{
timer.cancelAndRemove();
timer.cancel();
}
}
@@ -401,7 +401,7 @@ public class Quest extends AbstractScript implements IIdentifiable
{
if ((timer != null) && (_questTimers != null))
{
final List<QuestTimer> timers = getQuestTimers().get(timer.getName());
final List<QuestTimer> timers = getQuestTimers().get(timer.toString());
if (timers != null)
{
_writeLock.lock();

View File

@@ -136,31 +136,29 @@ public class QuestState
/**
* @param state the new state of the quest to set
* @return {@code true} if state was changed, {@code false} otherwise
* @see #setState(byte state, boolean saveInDb)
* @see org.l2jmobius.gameserver.model.quest.State
*/
public boolean setState(byte state)
public void setState(byte state)
{
return setState(state, true);
setState(state, true);
}
/**
* Change the state of this quest to the specified value.
* @param state the new state of the quest to set
* @param saveInDb if {@code true}, will save the state change in the database
* @return {@code true} if state was changed, {@code false} otherwise
* @see org.l2jmobius.gameserver.model.quest.State
*/
public boolean setState(byte state, boolean saveInDb)
public void setState(byte state, boolean saveInDb)
{
if (_simulated)
{
return false;
return;
}
if (_state == state)
{
return false;
return;
}
final boolean newQuest = isCreated();
_state = state;
@@ -177,20 +175,18 @@ public class QuestState
}
_player.sendPacket(new QuestList(_player));
return true;
}
/**
* Add parameter used in quests.
* @param var String pointing out the name of the variable for quest
* @param value String pointing out the value of the variable for quest
* @return String (equal to parameter "value")
*/
public String setInternal(String var, String value)
public void setInternal(String var, String value)
{
if (_simulated)
{
return null;
return;
}
if (_vars == null)
@@ -204,16 +200,15 @@ public class QuestState
}
_vars.put(var, value);
return value;
}
public String set(String var, int value)
public void set(String var, int value)
{
if (_simulated)
{
return null;
return;
}
return set(var, Integer.toString(value));
set(var, Integer.toString(value));
}
/**
@@ -229,13 +224,12 @@ public class QuestState
* <ul>
* @param var String indicating the name of the variable for quest
* @param value String indicating the value of the variable for quest
* @return String (equal to parameter "value")
*/
public String set(String var, String value)
public void set(String var, String value)
{
if (_simulated)
{
return null;
return;
}
if (_vars == null)
@@ -279,8 +273,6 @@ public class QuestState
LOGGER.log(Level.WARNING, _player.getName() + ", " + _questName + " cond [" + value + "] is not an integer. Value stored, but no packet was sent: " + e.getMessage(), e);
}
}
return value;
}
/**
@@ -325,20 +317,15 @@ public class QuestState
// case 1: No steps have been skipped so far...
if (completedStateFlags == 0)
{
// check if this step also doesn't skip anything. If so, no further work is needed
// also, in this case, no work is needed if the state is being reset to a smaller value
// in those cases, skip forward to informing the client about the change...
// Check if this step also doesn't skip anything. If so, no further work is needed also, in this case, no work is needed if the state is being reset to a smaller value in those cases, skip forward to informing the client about the change...
// ELSE, if we just now skipped for the first time...prepare the flags!!!
if (cond > (old + 1))
{
// set the most significant bit to 1 (indicates that there exist skipped states)
// also, ensure that the least significant bit is an 1 (the first step is never skipped, no matter
// what the cond says)
// also, ensure that the least significant bit is an 1 (the first step is never skipped, no matter what the cond says)
completedStateFlags = 0x80000001;
// since no flag had been skipped until now, the least significant bits must all
// be set to 1, up until "old" number of bits.
// since no flag had been skipped until now, the least significant bits must all be set to 1, up until "old" number of bits.
completedStateFlags |= (1 << old) - 1;
// now, just set the bit corresponding to the passed cond to 1 (current step)
@@ -347,11 +334,9 @@ public class QuestState
}
}
// case 2: There were exist previously skipped steps
// if this is a push back to a previous step, clear all completion flags ahead
else if (cond < old)
else if (cond < old) // if this is a push back to a previous step, clear all completion flags ahead
{
// note, this also unsets the flag indicating that there exist skips
completedStateFlags &= (1 << cond) - 1;
completedStateFlags &= (1 << cond) - 1; // note, this also unsets the flag indicating that there exist skips
// now, check if this resulted in no steps being skipped any more
if (completedStateFlags == ((1 << cond) - 1))
@@ -361,8 +346,7 @@ public class QuestState
else
{
// set the most significant bit back to 1 again, to correctly indicate that this skips states.
// also, ensure that the least significant bit is an 1 (the first step is never skipped, no matter
// what the cond says)
// also, ensure that the least significant bit is an 1 (the first step is never skipped, no matter what the cond says)
completedStateFlags |= 0x80000001;
set("__compltdStateFlags", String.valueOf(completedStateFlags));
}
@@ -388,18 +372,17 @@ public class QuestState
/**
* Removes a quest variable from the list of existing quest variables.
* @param var the name of the variable to remove
* @return the previous value of the variable or {@code null} if none were found
*/
public String unset(String var)
public void unset(String var)
{
if (_simulated)
{
return null;
return;
}
if (_vars == null)
{
return null;
return;
}
final String old = _vars.remove(var);
@@ -407,7 +390,6 @@ public class QuestState
{
Quest.deleteQuestVarInDb(this, var);
}
return old;
}
/**
@@ -468,22 +450,21 @@ public class QuestState
/**
* Sets the quest state progress ({@code cond}) to the specified step.
* @param value the new value of the quest state progress
* @return this {@link QuestState} object
* @see #set(String var, String value)
* @see #setCond(int, boolean)
*/
public QuestState setCond(int value)
public void setCond(int value)
{
if (_simulated)
{
return null;
return;
}
if (isStarted())
{
set("cond", Integer.toString(value));
}
return this;
return;
}
/**
@@ -529,20 +510,19 @@ public class QuestState
* Sets the quest state progress ({@code cond}) to the specified step.
* @param value the new value of the quest state progress
* @param playQuestMiddle if {@code true}, plays "ItemSound.quest_middle"
* @return this {@link QuestState} object
* @see #setCond(int value)
* @see #set(String var, String value)
*/
public QuestState setCond(int value, boolean playQuestMiddle)
public void setCond(int value, boolean playQuestMiddle)
{
if (_simulated)
{
return null;
return;
}
if (!isStarted())
{
return this;
return;
}
set("cond", String.valueOf(value));
@@ -550,17 +530,15 @@ public class QuestState
{
_player.sendPacket(QuestSound.ITEMSOUND_QUEST_MIDDLE.getPacket());
}
return this;
}
public QuestState setMemoState(int value)
public void setMemoState(int value)
{
if (_simulated)
{
return null;
return;
}
set("memoState", String.valueOf(value));
return this;
}
/**
@@ -598,16 +576,14 @@ public class QuestState
* Sets the memo state ex.
* @param slot the slot where the value will be saved
* @param value the value
* @return this QuestState
*/
public QuestState setMemoStateEx(int slot, int value)
public void setMemoStateEx(int slot, int value)
{
if (_simulated)
{
return null;
return;
}
set("memoStateEx" + slot, String.valueOf(value));
return this;
}
/**
@@ -644,13 +620,12 @@ public class QuestState
/**
* Set condition to 1, state to STARTED and play the "ItemSound.quest_accept".<br>
* Works only if state is CREATED and the quest is not a custom quest.
* @return the newly created {@code QuestState} object
*/
public QuestState startQuest()
public void startQuest()
{
if (_simulated)
{
return null;
return;
}
if (isCreated() && !getQuest().isCustomQuest())
{
@@ -659,23 +634,21 @@ public class QuestState
_player.sendPacket(QuestSound.ITEMSOUND_QUEST_ACCEPT.getPacket());
getQuest().sendNpcLogList(getPlayer());
}
return this;
}
/**
* Finishes the quest and removes all quest items associated with this quest from the player's inventory.<br>
* If {@code type} is {@code QuestType.ONE_TIME}, also removes all other quest data associated with this quest.
* @param type the {@link QuestType} of the quest
* @return this {@link QuestState} object
* @see #exitQuest(QuestType type, boolean playExitQuest)
* @see #exitQuest(boolean repeatable)
* @see #exitQuest(boolean repeatable, boolean playExitQuest)
*/
public QuestState exitQuest(QuestType type)
public void exitQuest(QuestType type)
{
if (_simulated)
{
return null;
return;
}
switch (type)
@@ -697,8 +670,6 @@ public class QuestState
// Notify to scripts
EventDispatcher.getInstance().notifyEventAsync(new OnPlayerQuestComplete(_player, getQuest().getId(), type), _player);
return this;
}
/**
@@ -706,46 +677,43 @@ public class QuestState
* If {@code type} is {@code QuestType.ONE_TIME}, also removes all other quest data associated with this quest.
* @param type the {@link QuestType} of the quest
* @param playExitQuest if {@code true}, plays "ItemSound.quest_finish"
* @return this {@link QuestState} object
* @see #exitQuest(QuestType type)
* @see #exitQuest(boolean repeatable)
* @see #exitQuest(boolean repeatable, boolean playExitQuest)
*/
public QuestState exitQuest(QuestType type, boolean playExitQuest)
public void exitQuest(QuestType type, boolean playExitQuest)
{
if (_simulated)
{
return null;
return;
}
exitQuest(type);
if (playExitQuest)
{
_player.sendPacket(QuestSound.ITEMSOUND_QUEST_FINISH.getPacket());
}
return this;
}
/**
* Finishes the quest and removes all quest items associated with this quest from the player's inventory.<br>
* If {@code repeatable} is set to {@code false}, also removes all other quest data associated with this quest.
* @param repeatable if {@code true}, deletes all data and variables of this quest, otherwise keeps them
* @return this {@link QuestState} object
* @see #exitQuest(QuestType type)
* @see #exitQuest(QuestType type, boolean playExitQuest)
* @see #exitQuest(boolean repeatable, boolean playExitQuest)
*/
private QuestState exitQuest(boolean repeatable)
private void exitQuest(boolean repeatable)
{
if (_simulated)
{
return null;
return;
}
_player.removeNotifyQuestOfDeath(this);
if (!isStarted())
{
return this;
return;
}
// Clean registered quest items
@@ -762,7 +730,6 @@ public class QuestState
setState(State.COMPLETED);
}
_vars = null;
return this;
}
/**
@@ -770,16 +737,15 @@ public class QuestState
* If {@code repeatable} is set to {@code false}, also removes all other quest data associated with this quest.
* @param repeatable if {@code true}, deletes all data and variables of this quest, otherwise keeps them
* @param playExitQuest if {@code true}, plays "ItemSound.quest_finish"
* @return this {@link QuestState} object
* @see #exitQuest(QuestType type)
* @see #exitQuest(QuestType type, boolean playExitQuest)
* @see #exitQuest(boolean repeatable)
*/
public QuestState exitQuest(boolean repeatable, boolean playExitQuest)
public void exitQuest(boolean repeatable, boolean playExitQuest)
{
if (_simulated)
{
return null;
return;
}
exitQuest(repeatable);
@@ -790,7 +756,7 @@ public class QuestState
// Notify to scripts
EventDispatcher.getInstance().notifyEventAsync(new OnPlayerQuestComplete(_player, getQuest().getId(), repeatable ? QuestType.REPEATABLE : QuestType.ONE_TIME), _player);
return this;
return;
}
/**

View File

@@ -17,8 +17,6 @@
package org.l2jmobius.gameserver.model.quest;
import java.util.concurrent.ScheduledFuture;
import java.util.logging.Level;
import java.util.logging.Logger;
import org.l2jmobius.commons.concurrent.ThreadPool;
import org.l2jmobius.gameserver.model.actor.Npc;
@@ -26,106 +24,68 @@ import org.l2jmobius.gameserver.model.actor.instance.PlayerInstance;
public class QuestTimer
{
protected static final Logger LOGGER = Logger.getLogger(QuestTimer.class.getName());
public class ScheduleTimerTask implements Runnable
{
@Override
public void run()
{
if (!_isActive)
{
return;
}
try
{
if (!_isRepeating)
{
cancelAndRemove();
}
_quest.notifyEvent(_name, _npc, _player);
}
catch (Exception e)
{
LOGGER.log(Level.SEVERE, "", e);
}
}
}
boolean _isActive = true;
final String _name;
final Quest _quest;
final Npc _npc;
final PlayerInstance _player;
final boolean _isRepeating;
private final ScheduledFuture<?> _scheduler;
private final String _name;
private final Quest _quest;
private final Npc _npc;
private final PlayerInstance _player;
private final boolean _isRepeating;
private ScheduledFuture<?> _scheduler;
public QuestTimer(Quest quest, String name, long time, Npc npc, PlayerInstance player, boolean repeating)
{
_name = name;
_quest = quest;
_player = player;
_name = name;
_npc = npc;
_player = player;
_isRepeating = repeating;
_scheduler = repeating ? ThreadPool.scheduleAtFixedRate(new ScheduleTimerTask(), time, time) : ThreadPool.schedule(new ScheduleTimerTask(), time);
}
public QuestTimer(Quest quest, String name, long time, Npc npc, PlayerInstance player)
{
this(quest, name, time, npc, player, false);
}
public QuestTimer(QuestState qs, String name, long time)
{
this(qs.getQuest(), name, time, null, qs.getPlayer(), false);
}
/**
* Cancel this quest timer.
*/
public void cancel()
{
_isActive = false;
if (_scheduler != null)
if (repeating)
{
_scheduler.cancel(false);
_scheduler = ThreadPool.scheduleAtFixedRate(new ScheduleTimerTask(), time, time); // Prepare auto end task
}
else
{
_scheduler = ThreadPool.schedule(new ScheduleTimerTask(), time); // Prepare auto end task
}
}
/**
* Cancel this quest timer and remove it from the associated quest.
*/
public void cancelAndRemove()
public void cancel()
{
cancel();
if (_scheduler != null)
{
_scheduler.cancel(false);
_scheduler = null;
}
_quest.removeQuestTimer(this);
}
/**
* Compares if this timer matches with the key attributes passed.
* @param quest the quest to which the timer is attached
* @param name the name of the timer
* @param npc the NPC attached to the desired timer (null if no NPC attached)
* @param player the player attached to the desired timer (null if no player attached)
* @return
* public method to compare if this timer matches with the key attributes passed.
* @param quest : Quest instance to which the timer is attached
* @param name : Name of the timer
* @param npc : Npc instance attached to the desired timer (null if no npc attached)
* @param player : Player instance attached to the desired timer (null if no player attached)
* @return boolean
*/
public boolean isMatch(Quest quest, String name, Npc npc, PlayerInstance player)
public boolean equals(Quest quest, String name, Npc npc, PlayerInstance player)
{
if ((quest == null) || (name == null))
if ((quest == null) || (quest != _quest))
{
return false;
}
if ((quest != _quest) || !name.equalsIgnoreCase(_name))
if ((name == null) || !name.equals(_name))
{
return false;
}
return ((npc == _npc) && (player == _player));
return (npc == _npc) && (player == _player);
}
public boolean isActive()
{
return _isActive;
return (_scheduler != null) && !_scheduler.isCancelled() && !_scheduler.isDone();
}
public boolean isRepeating()
@@ -158,4 +118,23 @@ public class QuestTimer
{
return _name;
}
public class ScheduleTimerTask implements Runnable
{
@Override
public void run()
{
if (_scheduler == null)
{
return;
}
if (!_isRepeating)
{
cancel();
}
_quest.notifyEvent(_name, _npc, _player);
}
}
}

View File

@@ -261,7 +261,7 @@ public class AdminQuest implements IAdminCommandHandler
{
for (QuestTimer timer : list)
{
timers += "<tr><td colspan=\"4\"><table width=270 border=0 bgcolor=131210><tr><td width=270><font color=\"LEVEL\">" + timer.getName() + ":</font> <font color=00FF00>Active: " + timer.isActive() + " Repeatable: " + timer.isRepeating() + " Player: " + timer.getPlayer() + " Npc: " + timer.getNpc() + "</font></td></tr></table></td></tr>";
timers += "<tr><td colspan=\"4\"><table width=270 border=0 bgcolor=131210><tr><td width=270><font color=\"LEVEL\">" + timer.toString() + ":</font> <font color=00FF00>Active: " + timer.isActive() + " Repeatable: " + timer.isRepeating() + " Player: " + timer.getPlayer() + " Npc: " + timer.getNpc() + "</font></td></tr></table></td></tr>";
counter++;
if (counter > 10)
{

View File

@@ -330,7 +330,7 @@ public class Quest extends AbstractScript implements IIdentifiable
{
for (QuestTimer timer : timers)
{
if ((timer != null) && timer.isMatch(this, name, npc, player))
if ((timer != null) && timer.equals(this, name, npc, player))
{
return timer;
}
@@ -388,7 +388,7 @@ public class Quest extends AbstractScript implements IIdentifiable
final QuestTimer timer = getQuestTimer(name, npc, player);
if (timer != null)
{
timer.cancelAndRemove();
timer.cancel();
}
}
@@ -401,7 +401,7 @@ public class Quest extends AbstractScript implements IIdentifiable
{
if ((timer != null) && (_questTimers != null))
{
final List<QuestTimer> timers = getQuestTimers().get(timer.getName());
final List<QuestTimer> timers = getQuestTimers().get(timer.toString());
if (timers != null)
{
_writeLock.lock();

View File

@@ -136,31 +136,29 @@ public class QuestState
/**
* @param state the new state of the quest to set
* @return {@code true} if state was changed, {@code false} otherwise
* @see #setState(byte state, boolean saveInDb)
* @see org.l2jmobius.gameserver.model.quest.State
*/
public boolean setState(byte state)
public void setState(byte state)
{
return setState(state, true);
setState(state, true);
}
/**
* Change the state of this quest to the specified value.
* @param state the new state of the quest to set
* @param saveInDb if {@code true}, will save the state change in the database
* @return {@code true} if state was changed, {@code false} otherwise
* @see org.l2jmobius.gameserver.model.quest.State
*/
public boolean setState(byte state, boolean saveInDb)
public void setState(byte state, boolean saveInDb)
{
if (_simulated)
{
return false;
return;
}
if (_state == state)
{
return false;
return;
}
final boolean newQuest = isCreated();
_state = state;
@@ -177,20 +175,18 @@ public class QuestState
}
_player.sendPacket(new QuestList(_player));
return true;
}
/**
* Add parameter used in quests.
* @param var String pointing out the name of the variable for quest
* @param value String pointing out the value of the variable for quest
* @return String (equal to parameter "value")
*/
public String setInternal(String var, String value)
public void setInternal(String var, String value)
{
if (_simulated)
{
return null;
return;
}
if (_vars == null)
@@ -204,16 +200,15 @@ public class QuestState
}
_vars.put(var, value);
return value;
}
public String set(String var, int value)
public void set(String var, int value)
{
if (_simulated)
{
return null;
return;
}
return set(var, Integer.toString(value));
set(var, Integer.toString(value));
}
/**
@@ -229,13 +224,12 @@ public class QuestState
* <ul>
* @param var String indicating the name of the variable for quest
* @param value String indicating the value of the variable for quest
* @return String (equal to parameter "value")
*/
public String set(String var, String value)
public void set(String var, String value)
{
if (_simulated)
{
return null;
return;
}
if (_vars == null)
@@ -279,8 +273,6 @@ public class QuestState
LOGGER.log(Level.WARNING, _player.getName() + ", " + _questName + " cond [" + value + "] is not an integer. Value stored, but no packet was sent: " + e.getMessage(), e);
}
}
return value;
}
/**
@@ -325,20 +317,15 @@ public class QuestState
// case 1: No steps have been skipped so far...
if (completedStateFlags == 0)
{
// check if this step also doesn't skip anything. If so, no further work is needed
// also, in this case, no work is needed if the state is being reset to a smaller value
// in those cases, skip forward to informing the client about the change...
// Check if this step also doesn't skip anything. If so, no further work is needed also, in this case, no work is needed if the state is being reset to a smaller value in those cases, skip forward to informing the client about the change...
// ELSE, if we just now skipped for the first time...prepare the flags!!!
if (cond > (old + 1))
{
// set the most significant bit to 1 (indicates that there exist skipped states)
// also, ensure that the least significant bit is an 1 (the first step is never skipped, no matter
// what the cond says)
// also, ensure that the least significant bit is an 1 (the first step is never skipped, no matter what the cond says)
completedStateFlags = 0x80000001;
// since no flag had been skipped until now, the least significant bits must all
// be set to 1, up until "old" number of bits.
// since no flag had been skipped until now, the least significant bits must all be set to 1, up until "old" number of bits.
completedStateFlags |= (1 << old) - 1;
// now, just set the bit corresponding to the passed cond to 1 (current step)
@@ -347,11 +334,9 @@ public class QuestState
}
}
// case 2: There were exist previously skipped steps
// if this is a push back to a previous step, clear all completion flags ahead
else if (cond < old)
else if (cond < old) // if this is a push back to a previous step, clear all completion flags ahead
{
// note, this also unsets the flag indicating that there exist skips
completedStateFlags &= (1 << cond) - 1;
completedStateFlags &= (1 << cond) - 1; // note, this also unsets the flag indicating that there exist skips
// now, check if this resulted in no steps being skipped any more
if (completedStateFlags == ((1 << cond) - 1))
@@ -361,8 +346,7 @@ public class QuestState
else
{
// set the most significant bit back to 1 again, to correctly indicate that this skips states.
// also, ensure that the least significant bit is an 1 (the first step is never skipped, no matter
// what the cond says)
// also, ensure that the least significant bit is an 1 (the first step is never skipped, no matter what the cond says)
completedStateFlags |= 0x80000001;
set("__compltdStateFlags", String.valueOf(completedStateFlags));
}
@@ -388,18 +372,17 @@ public class QuestState
/**
* Removes a quest variable from the list of existing quest variables.
* @param var the name of the variable to remove
* @return the previous value of the variable or {@code null} if none were found
*/
public String unset(String var)
public void unset(String var)
{
if (_simulated)
{
return null;
return;
}
if (_vars == null)
{
return null;
return;
}
final String old = _vars.remove(var);
@@ -407,7 +390,6 @@ public class QuestState
{
Quest.deleteQuestVarInDb(this, var);
}
return old;
}
/**
@@ -468,22 +450,21 @@ public class QuestState
/**
* Sets the quest state progress ({@code cond}) to the specified step.
* @param value the new value of the quest state progress
* @return this {@link QuestState} object
* @see #set(String var, String value)
* @see #setCond(int, boolean)
*/
public QuestState setCond(int value)
public void setCond(int value)
{
if (_simulated)
{
return null;
return;
}
if (isStarted())
{
set("cond", Integer.toString(value));
}
return this;
return;
}
/**
@@ -529,20 +510,19 @@ public class QuestState
* Sets the quest state progress ({@code cond}) to the specified step.
* @param value the new value of the quest state progress
* @param playQuestMiddle if {@code true}, plays "ItemSound.quest_middle"
* @return this {@link QuestState} object
* @see #setCond(int value)
* @see #set(String var, String value)
*/
public QuestState setCond(int value, boolean playQuestMiddle)
public void setCond(int value, boolean playQuestMiddle)
{
if (_simulated)
{
return null;
return;
}
if (!isStarted())
{
return this;
return;
}
set("cond", String.valueOf(value));
@@ -550,17 +530,15 @@ public class QuestState
{
_player.sendPacket(QuestSound.ITEMSOUND_QUEST_MIDDLE.getPacket());
}
return this;
}
public QuestState setMemoState(int value)
public void setMemoState(int value)
{
if (_simulated)
{
return null;
return;
}
set("memoState", String.valueOf(value));
return this;
}
/**
@@ -598,16 +576,14 @@ public class QuestState
* Sets the memo state ex.
* @param slot the slot where the value will be saved
* @param value the value
* @return this QuestState
*/
public QuestState setMemoStateEx(int slot, int value)
public void setMemoStateEx(int slot, int value)
{
if (_simulated)
{
return null;
return;
}
set("memoStateEx" + slot, String.valueOf(value));
return this;
}
/**
@@ -644,13 +620,12 @@ public class QuestState
/**
* Set condition to 1, state to STARTED and play the "ItemSound.quest_accept".<br>
* Works only if state is CREATED and the quest is not a custom quest.
* @return the newly created {@code QuestState} object
*/
public QuestState startQuest()
public void startQuest()
{
if (_simulated)
{
return null;
return;
}
if (isCreated() && !getQuest().isCustomQuest())
{
@@ -659,23 +634,21 @@ public class QuestState
_player.sendPacket(QuestSound.ITEMSOUND_QUEST_ACCEPT.getPacket());
getQuest().sendNpcLogList(getPlayer());
}
return this;
}
/**
* Finishes the quest and removes all quest items associated with this quest from the player's inventory.<br>
* If {@code type} is {@code QuestType.ONE_TIME}, also removes all other quest data associated with this quest.
* @param type the {@link QuestType} of the quest
* @return this {@link QuestState} object
* @see #exitQuest(QuestType type, boolean playExitQuest)
* @see #exitQuest(boolean repeatable)
* @see #exitQuest(boolean repeatable, boolean playExitQuest)
*/
public QuestState exitQuest(QuestType type)
public void exitQuest(QuestType type)
{
if (_simulated)
{
return null;
return;
}
switch (type)
@@ -697,8 +670,6 @@ public class QuestState
// Notify to scripts
EventDispatcher.getInstance().notifyEventAsync(new OnPlayerQuestComplete(_player, getQuest().getId(), type), _player);
return this;
}
/**
@@ -706,46 +677,43 @@ public class QuestState
* If {@code type} is {@code QuestType.ONE_TIME}, also removes all other quest data associated with this quest.
* @param type the {@link QuestType} of the quest
* @param playExitQuest if {@code true}, plays "ItemSound.quest_finish"
* @return this {@link QuestState} object
* @see #exitQuest(QuestType type)
* @see #exitQuest(boolean repeatable)
* @see #exitQuest(boolean repeatable, boolean playExitQuest)
*/
public QuestState exitQuest(QuestType type, boolean playExitQuest)
public void exitQuest(QuestType type, boolean playExitQuest)
{
if (_simulated)
{
return null;
return;
}
exitQuest(type);
if (playExitQuest)
{
_player.sendPacket(QuestSound.ITEMSOUND_QUEST_FINISH.getPacket());
}
return this;
}
/**
* Finishes the quest and removes all quest items associated with this quest from the player's inventory.<br>
* If {@code repeatable} is set to {@code false}, also removes all other quest data associated with this quest.
* @param repeatable if {@code true}, deletes all data and variables of this quest, otherwise keeps them
* @return this {@link QuestState} object
* @see #exitQuest(QuestType type)
* @see #exitQuest(QuestType type, boolean playExitQuest)
* @see #exitQuest(boolean repeatable, boolean playExitQuest)
*/
private QuestState exitQuest(boolean repeatable)
private void exitQuest(boolean repeatable)
{
if (_simulated)
{
return null;
return;
}
_player.removeNotifyQuestOfDeath(this);
if (!isStarted())
{
return this;
return;
}
// Clean registered quest items
@@ -762,7 +730,6 @@ public class QuestState
setState(State.COMPLETED);
}
_vars = null;
return this;
}
/**
@@ -770,16 +737,15 @@ public class QuestState
* If {@code repeatable} is set to {@code false}, also removes all other quest data associated with this quest.
* @param repeatable if {@code true}, deletes all data and variables of this quest, otherwise keeps them
* @param playExitQuest if {@code true}, plays "ItemSound.quest_finish"
* @return this {@link QuestState} object
* @see #exitQuest(QuestType type)
* @see #exitQuest(QuestType type, boolean playExitQuest)
* @see #exitQuest(boolean repeatable)
*/
public QuestState exitQuest(boolean repeatable, boolean playExitQuest)
public void exitQuest(boolean repeatable, boolean playExitQuest)
{
if (_simulated)
{
return null;
return;
}
exitQuest(repeatable);
@@ -790,7 +756,7 @@ public class QuestState
// Notify to scripts
EventDispatcher.getInstance().notifyEventAsync(new OnPlayerQuestComplete(_player, getQuest().getId(), repeatable ? QuestType.REPEATABLE : QuestType.ONE_TIME), _player);
return this;
return;
}
/**

View File

@@ -17,8 +17,6 @@
package org.l2jmobius.gameserver.model.quest;
import java.util.concurrent.ScheduledFuture;
import java.util.logging.Level;
import java.util.logging.Logger;
import org.l2jmobius.commons.concurrent.ThreadPool;
import org.l2jmobius.gameserver.model.actor.Npc;
@@ -26,106 +24,68 @@ import org.l2jmobius.gameserver.model.actor.instance.PlayerInstance;
public class QuestTimer
{
protected static final Logger LOGGER = Logger.getLogger(QuestTimer.class.getName());
public class ScheduleTimerTask implements Runnable
{
@Override
public void run()
{
if (!_isActive)
{
return;
}
try
{
if (!_isRepeating)
{
cancelAndRemove();
}
_quest.notifyEvent(_name, _npc, _player);
}
catch (Exception e)
{
LOGGER.log(Level.SEVERE, "", e);
}
}
}
boolean _isActive = true;
final String _name;
final Quest _quest;
final Npc _npc;
final PlayerInstance _player;
final boolean _isRepeating;
private final ScheduledFuture<?> _scheduler;
private final String _name;
private final Quest _quest;
private final Npc _npc;
private final PlayerInstance _player;
private final boolean _isRepeating;
private ScheduledFuture<?> _scheduler;
public QuestTimer(Quest quest, String name, long time, Npc npc, PlayerInstance player, boolean repeating)
{
_name = name;
_quest = quest;
_player = player;
_name = name;
_npc = npc;
_player = player;
_isRepeating = repeating;
_scheduler = repeating ? ThreadPool.scheduleAtFixedRate(new ScheduleTimerTask(), time, time) : ThreadPool.schedule(new ScheduleTimerTask(), time);
}
public QuestTimer(Quest quest, String name, long time, Npc npc, PlayerInstance player)
{
this(quest, name, time, npc, player, false);
}
public QuestTimer(QuestState qs, String name, long time)
{
this(qs.getQuest(), name, time, null, qs.getPlayer(), false);
}
/**
* Cancel this quest timer.
*/
public void cancel()
{
_isActive = false;
if (_scheduler != null)
if (repeating)
{
_scheduler.cancel(false);
_scheduler = ThreadPool.scheduleAtFixedRate(new ScheduleTimerTask(), time, time); // Prepare auto end task
}
else
{
_scheduler = ThreadPool.schedule(new ScheduleTimerTask(), time); // Prepare auto end task
}
}
/**
* Cancel this quest timer and remove it from the associated quest.
*/
public void cancelAndRemove()
public void cancel()
{
cancel();
if (_scheduler != null)
{
_scheduler.cancel(false);
_scheduler = null;
}
_quest.removeQuestTimer(this);
}
/**
* Compares if this timer matches with the key attributes passed.
* @param quest the quest to which the timer is attached
* @param name the name of the timer
* @param npc the NPC attached to the desired timer (null if no NPC attached)
* @param player the player attached to the desired timer (null if no player attached)
* @return
* public method to compare if this timer matches with the key attributes passed.
* @param quest : Quest instance to which the timer is attached
* @param name : Name of the timer
* @param npc : Npc instance attached to the desired timer (null if no npc attached)
* @param player : Player instance attached to the desired timer (null if no player attached)
* @return boolean
*/
public boolean isMatch(Quest quest, String name, Npc npc, PlayerInstance player)
public boolean equals(Quest quest, String name, Npc npc, PlayerInstance player)
{
if ((quest == null) || (name == null))
if ((quest == null) || (quest != _quest))
{
return false;
}
if ((quest != _quest) || !name.equalsIgnoreCase(_name))
if ((name == null) || !name.equals(_name))
{
return false;
}
return ((npc == _npc) && (player == _player));
return (npc == _npc) && (player == _player);
}
public boolean isActive()
{
return _isActive;
return (_scheduler != null) && !_scheduler.isCancelled() && !_scheduler.isDone();
}
public boolean isRepeating()
@@ -158,4 +118,23 @@ public class QuestTimer
{
return _name;
}
public class ScheduleTimerTask implements Runnable
{
@Override
public void run()
{
if (_scheduler == null)
{
return;
}
if (!_isRepeating)
{
cancel();
}
_quest.notifyEvent(_name, _npc, _player);
}
}
}

View File

@@ -261,7 +261,7 @@ public class AdminQuest implements IAdminCommandHandler
{
for (QuestTimer timer : list)
{
timers += "<tr><td colspan=\"4\"><table width=270 border=0 bgcolor=131210><tr><td width=270><font color=\"LEVEL\">" + timer.getName() + ":</font> <font color=00FF00>Active: " + timer.isActive() + " Repeatable: " + timer.isRepeating() + " Player: " + timer.getPlayer() + " Npc: " + timer.getNpc() + "</font></td></tr></table></td></tr>";
timers += "<tr><td colspan=\"4\"><table width=270 border=0 bgcolor=131210><tr><td width=270><font color=\"LEVEL\">" + timer.toString() + ":</font> <font color=00FF00>Active: " + timer.isActive() + " Repeatable: " + timer.isRepeating() + " Player: " + timer.getPlayer() + " Npc: " + timer.getNpc() + "</font></td></tr></table></td></tr>";
counter++;
if (counter > 10)
{

View File

@@ -330,7 +330,7 @@ public class Quest extends AbstractScript implements IIdentifiable
{
for (QuestTimer timer : timers)
{
if ((timer != null) && timer.isMatch(this, name, npc, player))
if ((timer != null) && timer.equals(this, name, npc, player))
{
return timer;
}
@@ -388,7 +388,7 @@ public class Quest extends AbstractScript implements IIdentifiable
final QuestTimer timer = getQuestTimer(name, npc, player);
if (timer != null)
{
timer.cancelAndRemove();
timer.cancel();
}
}
@@ -401,7 +401,7 @@ public class Quest extends AbstractScript implements IIdentifiable
{
if ((timer != null) && (_questTimers != null))
{
final List<QuestTimer> timers = getQuestTimers().get(timer.getName());
final List<QuestTimer> timers = getQuestTimers().get(timer.toString());
if (timers != null)
{
_writeLock.lock();

View File

@@ -136,31 +136,29 @@ public class QuestState
/**
* @param state the new state of the quest to set
* @return {@code true} if state was changed, {@code false} otherwise
* @see #setState(byte state, boolean saveInDb)
* @see org.l2jmobius.gameserver.model.quest.State
*/
public boolean setState(byte state)
public void setState(byte state)
{
return setState(state, true);
setState(state, true);
}
/**
* Change the state of this quest to the specified value.
* @param state the new state of the quest to set
* @param saveInDb if {@code true}, will save the state change in the database
* @return {@code true} if state was changed, {@code false} otherwise
* @see org.l2jmobius.gameserver.model.quest.State
*/
public boolean setState(byte state, boolean saveInDb)
public void setState(byte state, boolean saveInDb)
{
if (_simulated)
{
return false;
return;
}
if (_state == state)
{
return false;
return;
}
final boolean newQuest = isCreated();
_state = state;
@@ -177,20 +175,18 @@ public class QuestState
}
_player.sendPacket(new QuestList(_player));
return true;
}
/**
* Add parameter used in quests.
* @param var String pointing out the name of the variable for quest
* @param value String pointing out the value of the variable for quest
* @return String (equal to parameter "value")
*/
public String setInternal(String var, String value)
public void setInternal(String var, String value)
{
if (_simulated)
{
return null;
return;
}
if (_vars == null)
@@ -204,16 +200,15 @@ public class QuestState
}
_vars.put(var, value);
return value;
}
public String set(String var, int value)
public void set(String var, int value)
{
if (_simulated)
{
return null;
return;
}
return set(var, Integer.toString(value));
set(var, Integer.toString(value));
}
/**
@@ -229,13 +224,12 @@ public class QuestState
* <ul>
* @param var String indicating the name of the variable for quest
* @param value String indicating the value of the variable for quest
* @return String (equal to parameter "value")
*/
public String set(String var, String value)
public void set(String var, String value)
{
if (_simulated)
{
return null;
return;
}
if (_vars == null)
@@ -279,8 +273,6 @@ public class QuestState
LOGGER.log(Level.WARNING, _player.getName() + ", " + _questName + " cond [" + value + "] is not an integer. Value stored, but no packet was sent: " + e.getMessage(), e);
}
}
return value;
}
/**
@@ -325,20 +317,15 @@ public class QuestState
// case 1: No steps have been skipped so far...
if (completedStateFlags == 0)
{
// check if this step also doesn't skip anything. If so, no further work is needed
// also, in this case, no work is needed if the state is being reset to a smaller value
// in those cases, skip forward to informing the client about the change...
// Check if this step also doesn't skip anything. If so, no further work is needed also, in this case, no work is needed if the state is being reset to a smaller value in those cases, skip forward to informing the client about the change...
// ELSE, if we just now skipped for the first time...prepare the flags!!!
if (cond > (old + 1))
{
// set the most significant bit to 1 (indicates that there exist skipped states)
// also, ensure that the least significant bit is an 1 (the first step is never skipped, no matter
// what the cond says)
// also, ensure that the least significant bit is an 1 (the first step is never skipped, no matter what the cond says)
completedStateFlags = 0x80000001;
// since no flag had been skipped until now, the least significant bits must all
// be set to 1, up until "old" number of bits.
// since no flag had been skipped until now, the least significant bits must all be set to 1, up until "old" number of bits.
completedStateFlags |= (1 << old) - 1;
// now, just set the bit corresponding to the passed cond to 1 (current step)
@@ -347,11 +334,9 @@ public class QuestState
}
}
// case 2: There were exist previously skipped steps
// if this is a push back to a previous step, clear all completion flags ahead
else if (cond < old)
else if (cond < old) // if this is a push back to a previous step, clear all completion flags ahead
{
// note, this also unsets the flag indicating that there exist skips
completedStateFlags &= (1 << cond) - 1;
completedStateFlags &= (1 << cond) - 1; // note, this also unsets the flag indicating that there exist skips
// now, check if this resulted in no steps being skipped any more
if (completedStateFlags == ((1 << cond) - 1))
@@ -361,8 +346,7 @@ public class QuestState
else
{
// set the most significant bit back to 1 again, to correctly indicate that this skips states.
// also, ensure that the least significant bit is an 1 (the first step is never skipped, no matter
// what the cond says)
// also, ensure that the least significant bit is an 1 (the first step is never skipped, no matter what the cond says)
completedStateFlags |= 0x80000001;
set("__compltdStateFlags", String.valueOf(completedStateFlags));
}
@@ -388,18 +372,17 @@ public class QuestState
/**
* Removes a quest variable from the list of existing quest variables.
* @param var the name of the variable to remove
* @return the previous value of the variable or {@code null} if none were found
*/
public String unset(String var)
public void unset(String var)
{
if (_simulated)
{
return null;
return;
}
if (_vars == null)
{
return null;
return;
}
final String old = _vars.remove(var);
@@ -407,7 +390,6 @@ public class QuestState
{
Quest.deleteQuestVarInDb(this, var);
}
return old;
}
/**
@@ -468,22 +450,21 @@ public class QuestState
/**
* Sets the quest state progress ({@code cond}) to the specified step.
* @param value the new value of the quest state progress
* @return this {@link QuestState} object
* @see #set(String var, String value)
* @see #setCond(int, boolean)
*/
public QuestState setCond(int value)
public void setCond(int value)
{
if (_simulated)
{
return null;
return;
}
if (isStarted())
{
set("cond", Integer.toString(value));
}
return this;
return;
}
/**
@@ -529,20 +510,19 @@ public class QuestState
* Sets the quest state progress ({@code cond}) to the specified step.
* @param value the new value of the quest state progress
* @param playQuestMiddle if {@code true}, plays "ItemSound.quest_middle"
* @return this {@link QuestState} object
* @see #setCond(int value)
* @see #set(String var, String value)
*/
public QuestState setCond(int value, boolean playQuestMiddle)
public void setCond(int value, boolean playQuestMiddle)
{
if (_simulated)
{
return null;
return;
}
if (!isStarted())
{
return this;
return;
}
set("cond", String.valueOf(value));
@@ -550,17 +530,15 @@ public class QuestState
{
_player.sendPacket(QuestSound.ITEMSOUND_QUEST_MIDDLE.getPacket());
}
return this;
}
public QuestState setMemoState(int value)
public void setMemoState(int value)
{
if (_simulated)
{
return null;
return;
}
set("memoState", String.valueOf(value));
return this;
}
/**
@@ -598,16 +576,14 @@ public class QuestState
* Sets the memo state ex.
* @param slot the slot where the value will be saved
* @param value the value
* @return this QuestState
*/
public QuestState setMemoStateEx(int slot, int value)
public void setMemoStateEx(int slot, int value)
{
if (_simulated)
{
return null;
return;
}
set("memoStateEx" + slot, String.valueOf(value));
return this;
}
/**
@@ -644,13 +620,12 @@ public class QuestState
/**
* Set condition to 1, state to STARTED and play the "ItemSound.quest_accept".<br>
* Works only if state is CREATED and the quest is not a custom quest.
* @return the newly created {@code QuestState} object
*/
public QuestState startQuest()
public void startQuest()
{
if (_simulated)
{
return null;
return;
}
if (isCreated() && !getQuest().isCustomQuest())
{
@@ -659,23 +634,21 @@ public class QuestState
_player.sendPacket(QuestSound.ITEMSOUND_QUEST_ACCEPT.getPacket());
getQuest().sendNpcLogList(getPlayer());
}
return this;
}
/**
* Finishes the quest and removes all quest items associated with this quest from the player's inventory.<br>
* If {@code type} is {@code QuestType.ONE_TIME}, also removes all other quest data associated with this quest.
* @param type the {@link QuestType} of the quest
* @return this {@link QuestState} object
* @see #exitQuest(QuestType type, boolean playExitQuest)
* @see #exitQuest(boolean repeatable)
* @see #exitQuest(boolean repeatable, boolean playExitQuest)
*/
public QuestState exitQuest(QuestType type)
public void exitQuest(QuestType type)
{
if (_simulated)
{
return null;
return;
}
switch (type)
@@ -697,8 +670,6 @@ public class QuestState
// Notify to scripts
EventDispatcher.getInstance().notifyEventAsync(new OnPlayerQuestComplete(_player, getQuest().getId(), type), _player);
return this;
}
/**
@@ -706,46 +677,43 @@ public class QuestState
* If {@code type} is {@code QuestType.ONE_TIME}, also removes all other quest data associated with this quest.
* @param type the {@link QuestType} of the quest
* @param playExitQuest if {@code true}, plays "ItemSound.quest_finish"
* @return this {@link QuestState} object
* @see #exitQuest(QuestType type)
* @see #exitQuest(boolean repeatable)
* @see #exitQuest(boolean repeatable, boolean playExitQuest)
*/
public QuestState exitQuest(QuestType type, boolean playExitQuest)
public void exitQuest(QuestType type, boolean playExitQuest)
{
if (_simulated)
{
return null;
return;
}
exitQuest(type);
if (playExitQuest)
{
_player.sendPacket(QuestSound.ITEMSOUND_QUEST_FINISH.getPacket());
}
return this;
}
/**
* Finishes the quest and removes all quest items associated with this quest from the player's inventory.<br>
* If {@code repeatable} is set to {@code false}, also removes all other quest data associated with this quest.
* @param repeatable if {@code true}, deletes all data and variables of this quest, otherwise keeps them
* @return this {@link QuestState} object
* @see #exitQuest(QuestType type)
* @see #exitQuest(QuestType type, boolean playExitQuest)
* @see #exitQuest(boolean repeatable, boolean playExitQuest)
*/
private QuestState exitQuest(boolean repeatable)
private void exitQuest(boolean repeatable)
{
if (_simulated)
{
return null;
return;
}
_player.removeNotifyQuestOfDeath(this);
if (!isStarted())
{
return this;
return;
}
// Clean registered quest items
@@ -762,7 +730,6 @@ public class QuestState
setState(State.COMPLETED);
}
_vars = null;
return this;
}
/**
@@ -770,16 +737,15 @@ public class QuestState
* If {@code repeatable} is set to {@code false}, also removes all other quest data associated with this quest.
* @param repeatable if {@code true}, deletes all data and variables of this quest, otherwise keeps them
* @param playExitQuest if {@code true}, plays "ItemSound.quest_finish"
* @return this {@link QuestState} object
* @see #exitQuest(QuestType type)
* @see #exitQuest(QuestType type, boolean playExitQuest)
* @see #exitQuest(boolean repeatable)
*/
public QuestState exitQuest(boolean repeatable, boolean playExitQuest)
public void exitQuest(boolean repeatable, boolean playExitQuest)
{
if (_simulated)
{
return null;
return;
}
exitQuest(repeatable);
@@ -790,7 +756,7 @@ public class QuestState
// Notify to scripts
EventDispatcher.getInstance().notifyEventAsync(new OnPlayerQuestComplete(_player, getQuest().getId(), repeatable ? QuestType.REPEATABLE : QuestType.ONE_TIME), _player);
return this;
return;
}
/**

View File

@@ -17,8 +17,6 @@
package org.l2jmobius.gameserver.model.quest;
import java.util.concurrent.ScheduledFuture;
import java.util.logging.Level;
import java.util.logging.Logger;
import org.l2jmobius.commons.concurrent.ThreadPool;
import org.l2jmobius.gameserver.model.actor.Npc;
@@ -26,106 +24,68 @@ import org.l2jmobius.gameserver.model.actor.instance.PlayerInstance;
public class QuestTimer
{
protected static final Logger LOGGER = Logger.getLogger(QuestTimer.class.getName());
public class ScheduleTimerTask implements Runnable
{
@Override
public void run()
{
if (!_isActive)
{
return;
}
try
{
if (!_isRepeating)
{
cancelAndRemove();
}
_quest.notifyEvent(_name, _npc, _player);
}
catch (Exception e)
{
LOGGER.log(Level.SEVERE, "", e);
}
}
}
boolean _isActive = true;
final String _name;
final Quest _quest;
final Npc _npc;
final PlayerInstance _player;
final boolean _isRepeating;
private final ScheduledFuture<?> _scheduler;
private final String _name;
private final Quest _quest;
private final Npc _npc;
private final PlayerInstance _player;
private final boolean _isRepeating;
private ScheduledFuture<?> _scheduler;
public QuestTimer(Quest quest, String name, long time, Npc npc, PlayerInstance player, boolean repeating)
{
_name = name;
_quest = quest;
_player = player;
_name = name;
_npc = npc;
_player = player;
_isRepeating = repeating;
_scheduler = repeating ? ThreadPool.scheduleAtFixedRate(new ScheduleTimerTask(), time, time) : ThreadPool.schedule(new ScheduleTimerTask(), time);
}
public QuestTimer(Quest quest, String name, long time, Npc npc, PlayerInstance player)
{
this(quest, name, time, npc, player, false);
}
public QuestTimer(QuestState qs, String name, long time)
{
this(qs.getQuest(), name, time, null, qs.getPlayer(), false);
}
/**
* Cancel this quest timer.
*/
public void cancel()
{
_isActive = false;
if (_scheduler != null)
if (repeating)
{
_scheduler.cancel(false);
_scheduler = ThreadPool.scheduleAtFixedRate(new ScheduleTimerTask(), time, time); // Prepare auto end task
}
else
{
_scheduler = ThreadPool.schedule(new ScheduleTimerTask(), time); // Prepare auto end task
}
}
/**
* Cancel this quest timer and remove it from the associated quest.
*/
public void cancelAndRemove()
public void cancel()
{
cancel();
if (_scheduler != null)
{
_scheduler.cancel(false);
_scheduler = null;
}
_quest.removeQuestTimer(this);
}
/**
* Compares if this timer matches with the key attributes passed.
* @param quest the quest to which the timer is attached
* @param name the name of the timer
* @param npc the NPC attached to the desired timer (null if no NPC attached)
* @param player the player attached to the desired timer (null if no player attached)
* @return
* public method to compare if this timer matches with the key attributes passed.
* @param quest : Quest instance to which the timer is attached
* @param name : Name of the timer
* @param npc : Npc instance attached to the desired timer (null if no npc attached)
* @param player : Player instance attached to the desired timer (null if no player attached)
* @return boolean
*/
public boolean isMatch(Quest quest, String name, Npc npc, PlayerInstance player)
public boolean equals(Quest quest, String name, Npc npc, PlayerInstance player)
{
if ((quest == null) || (name == null))
if ((quest == null) || (quest != _quest))
{
return false;
}
if ((quest != _quest) || !name.equalsIgnoreCase(_name))
if ((name == null) || !name.equals(_name))
{
return false;
}
return ((npc == _npc) && (player == _player));
return (npc == _npc) && (player == _player);
}
public boolean isActive()
{
return _isActive;
return (_scheduler != null) && !_scheduler.isCancelled() && !_scheduler.isDone();
}
public boolean isRepeating()
@@ -158,4 +118,23 @@ public class QuestTimer
{
return _name;
}
public class ScheduleTimerTask implements Runnable
{
@Override
public void run()
{
if (_scheduler == null)
{
return;
}
if (!_isRepeating)
{
cancel();
}
_quest.notifyEvent(_name, _npc, _player);
}
}
}

View File

@@ -261,7 +261,7 @@ public class AdminQuest implements IAdminCommandHandler
{
for (QuestTimer timer : list)
{
timers += "<tr><td colspan=\"4\"><table width=270 border=0 bgcolor=131210><tr><td width=270><font color=\"LEVEL\">" + timer.getName() + ":</font> <font color=00FF00>Active: " + timer.isActive() + " Repeatable: " + timer.isRepeating() + " Player: " + timer.getPlayer() + " Npc: " + timer.getNpc() + "</font></td></tr></table></td></tr>";
timers += "<tr><td colspan=\"4\"><table width=270 border=0 bgcolor=131210><tr><td width=270><font color=\"LEVEL\">" + timer.toString() + ":</font> <font color=00FF00>Active: " + timer.isActive() + " Repeatable: " + timer.isRepeating() + " Player: " + timer.getPlayer() + " Npc: " + timer.getNpc() + "</font></td></tr></table></td></tr>";
counter++;
if (counter > 10)
{

View File

@@ -330,7 +330,7 @@ public class Quest extends AbstractScript implements IIdentifiable
{
for (QuestTimer timer : timers)
{
if ((timer != null) && timer.isMatch(this, name, npc, player))
if ((timer != null) && timer.equals(this, name, npc, player))
{
return timer;
}
@@ -388,7 +388,7 @@ public class Quest extends AbstractScript implements IIdentifiable
final QuestTimer timer = getQuestTimer(name, npc, player);
if (timer != null)
{
timer.cancelAndRemove();
timer.cancel();
}
}
@@ -401,7 +401,7 @@ public class Quest extends AbstractScript implements IIdentifiable
{
if ((timer != null) && (_questTimers != null))
{
final List<QuestTimer> timers = getQuestTimers().get(timer.getName());
final List<QuestTimer> timers = getQuestTimers().get(timer.toString());
if (timers != null)
{
_writeLock.lock();

View File

@@ -136,31 +136,29 @@ public class QuestState
/**
* @param state the new state of the quest to set
* @return {@code true} if state was changed, {@code false} otherwise
* @see #setState(byte state, boolean saveInDb)
* @see org.l2jmobius.gameserver.model.quest.State
*/
public boolean setState(byte state)
public void setState(byte state)
{
return setState(state, true);
setState(state, true);
}
/**
* Change the state of this quest to the specified value.
* @param state the new state of the quest to set
* @param saveInDb if {@code true}, will save the state change in the database
* @return {@code true} if state was changed, {@code false} otherwise
* @see org.l2jmobius.gameserver.model.quest.State
*/
public boolean setState(byte state, boolean saveInDb)
public void setState(byte state, boolean saveInDb)
{
if (_simulated)
{
return false;
return;
}
if (_state == state)
{
return false;
return;
}
final boolean newQuest = isCreated();
_state = state;
@@ -177,20 +175,18 @@ public class QuestState
}
_player.sendPacket(new QuestList(_player));
return true;
}
/**
* Add parameter used in quests.
* @param var String pointing out the name of the variable for quest
* @param value String pointing out the value of the variable for quest
* @return String (equal to parameter "value")
*/
public String setInternal(String var, String value)
public void setInternal(String var, String value)
{
if (_simulated)
{
return null;
return;
}
if (_vars == null)
@@ -204,16 +200,15 @@ public class QuestState
}
_vars.put(var, value);
return value;
}
public String set(String var, int value)
public void set(String var, int value)
{
if (_simulated)
{
return null;
return;
}
return set(var, Integer.toString(value));
set(var, Integer.toString(value));
}
/**
@@ -229,13 +224,12 @@ public class QuestState
* <ul>
* @param var String indicating the name of the variable for quest
* @param value String indicating the value of the variable for quest
* @return String (equal to parameter "value")
*/
public String set(String var, String value)
public void set(String var, String value)
{
if (_simulated)
{
return null;
return;
}
if (_vars == null)
@@ -279,8 +273,6 @@ public class QuestState
LOGGER.log(Level.WARNING, _player.getName() + ", " + _questName + " cond [" + value + "] is not an integer. Value stored, but no packet was sent: " + e.getMessage(), e);
}
}
return value;
}
/**
@@ -325,20 +317,15 @@ public class QuestState
// case 1: No steps have been skipped so far...
if (completedStateFlags == 0)
{
// check if this step also doesn't skip anything. If so, no further work is needed
// also, in this case, no work is needed if the state is being reset to a smaller value
// in those cases, skip forward to informing the client about the change...
// Check if this step also doesn't skip anything. If so, no further work is needed also, in this case, no work is needed if the state is being reset to a smaller value in those cases, skip forward to informing the client about the change...
// ELSE, if we just now skipped for the first time...prepare the flags!!!
if (cond > (old + 1))
{
// set the most significant bit to 1 (indicates that there exist skipped states)
// also, ensure that the least significant bit is an 1 (the first step is never skipped, no matter
// what the cond says)
// also, ensure that the least significant bit is an 1 (the first step is never skipped, no matter what the cond says)
completedStateFlags = 0x80000001;
// since no flag had been skipped until now, the least significant bits must all
// be set to 1, up until "old" number of bits.
// since no flag had been skipped until now, the least significant bits must all be set to 1, up until "old" number of bits.
completedStateFlags |= (1 << old) - 1;
// now, just set the bit corresponding to the passed cond to 1 (current step)
@@ -347,11 +334,9 @@ public class QuestState
}
}
// case 2: There were exist previously skipped steps
// if this is a push back to a previous step, clear all completion flags ahead
else if (cond < old)
else if (cond < old) // if this is a push back to a previous step, clear all completion flags ahead
{
// note, this also unsets the flag indicating that there exist skips
completedStateFlags &= (1 << cond) - 1;
completedStateFlags &= (1 << cond) - 1; // note, this also unsets the flag indicating that there exist skips
// now, check if this resulted in no steps being skipped any more
if (completedStateFlags == ((1 << cond) - 1))
@@ -361,8 +346,7 @@ public class QuestState
else
{
// set the most significant bit back to 1 again, to correctly indicate that this skips states.
// also, ensure that the least significant bit is an 1 (the first step is never skipped, no matter
// what the cond says)
// also, ensure that the least significant bit is an 1 (the first step is never skipped, no matter what the cond says)
completedStateFlags |= 0x80000001;
set("__compltdStateFlags", String.valueOf(completedStateFlags));
}
@@ -388,18 +372,17 @@ public class QuestState
/**
* Removes a quest variable from the list of existing quest variables.
* @param var the name of the variable to remove
* @return the previous value of the variable or {@code null} if none were found
*/
public String unset(String var)
public void unset(String var)
{
if (_simulated)
{
return null;
return;
}
if (_vars == null)
{
return null;
return;
}
final String old = _vars.remove(var);
@@ -407,7 +390,6 @@ public class QuestState
{
Quest.deleteQuestVarInDb(this, var);
}
return old;
}
/**
@@ -468,22 +450,21 @@ public class QuestState
/**
* Sets the quest state progress ({@code cond}) to the specified step.
* @param value the new value of the quest state progress
* @return this {@link QuestState} object
* @see #set(String var, String value)
* @see #setCond(int, boolean)
*/
public QuestState setCond(int value)
public void setCond(int value)
{
if (_simulated)
{
return null;
return;
}
if (isStarted())
{
set("cond", Integer.toString(value));
}
return this;
return;
}
/**
@@ -529,20 +510,19 @@ public class QuestState
* Sets the quest state progress ({@code cond}) to the specified step.
* @param value the new value of the quest state progress
* @param playQuestMiddle if {@code true}, plays "ItemSound.quest_middle"
* @return this {@link QuestState} object
* @see #setCond(int value)
* @see #set(String var, String value)
*/
public QuestState setCond(int value, boolean playQuestMiddle)
public void setCond(int value, boolean playQuestMiddle)
{
if (_simulated)
{
return null;
return;
}
if (!isStarted())
{
return this;
return;
}
set("cond", String.valueOf(value));
@@ -550,17 +530,15 @@ public class QuestState
{
_player.sendPacket(QuestSound.ITEMSOUND_QUEST_MIDDLE.getPacket());
}
return this;
}
public QuestState setMemoState(int value)
public void setMemoState(int value)
{
if (_simulated)
{
return null;
return;
}
set("memoState", String.valueOf(value));
return this;
}
/**
@@ -598,16 +576,14 @@ public class QuestState
* Sets the memo state ex.
* @param slot the slot where the value will be saved
* @param value the value
* @return this QuestState
*/
public QuestState setMemoStateEx(int slot, int value)
public void setMemoStateEx(int slot, int value)
{
if (_simulated)
{
return null;
return;
}
set("memoStateEx" + slot, String.valueOf(value));
return this;
}
/**
@@ -644,13 +620,12 @@ public class QuestState
/**
* Set condition to 1, state to STARTED and play the "ItemSound.quest_accept".<br>
* Works only if state is CREATED and the quest is not a custom quest.
* @return the newly created {@code QuestState} object
*/
public QuestState startQuest()
public void startQuest()
{
if (_simulated)
{
return null;
return;
}
if (isCreated() && !getQuest().isCustomQuest())
{
@@ -659,23 +634,21 @@ public class QuestState
_player.sendPacket(QuestSound.ITEMSOUND_QUEST_ACCEPT.getPacket());
getQuest().sendNpcLogList(getPlayer());
}
return this;
}
/**
* Finishes the quest and removes all quest items associated with this quest from the player's inventory.<br>
* If {@code type} is {@code QuestType.ONE_TIME}, also removes all other quest data associated with this quest.
* @param type the {@link QuestType} of the quest
* @return this {@link QuestState} object
* @see #exitQuest(QuestType type, boolean playExitQuest)
* @see #exitQuest(boolean repeatable)
* @see #exitQuest(boolean repeatable, boolean playExitQuest)
*/
public QuestState exitQuest(QuestType type)
public void exitQuest(QuestType type)
{
if (_simulated)
{
return null;
return;
}
switch (type)
@@ -697,8 +670,6 @@ public class QuestState
// Notify to scripts
EventDispatcher.getInstance().notifyEventAsync(new OnPlayerQuestComplete(_player, getQuest().getId(), type), _player);
return this;
}
/**
@@ -706,46 +677,43 @@ public class QuestState
* If {@code type} is {@code QuestType.ONE_TIME}, also removes all other quest data associated with this quest.
* @param type the {@link QuestType} of the quest
* @param playExitQuest if {@code true}, plays "ItemSound.quest_finish"
* @return this {@link QuestState} object
* @see #exitQuest(QuestType type)
* @see #exitQuest(boolean repeatable)
* @see #exitQuest(boolean repeatable, boolean playExitQuest)
*/
public QuestState exitQuest(QuestType type, boolean playExitQuest)
public void exitQuest(QuestType type, boolean playExitQuest)
{
if (_simulated)
{
return null;
return;
}
exitQuest(type);
if (playExitQuest)
{
_player.sendPacket(QuestSound.ITEMSOUND_QUEST_FINISH.getPacket());
}
return this;
}
/**
* Finishes the quest and removes all quest items associated with this quest from the player's inventory.<br>
* If {@code repeatable} is set to {@code false}, also removes all other quest data associated with this quest.
* @param repeatable if {@code true}, deletes all data and variables of this quest, otherwise keeps them
* @return this {@link QuestState} object
* @see #exitQuest(QuestType type)
* @see #exitQuest(QuestType type, boolean playExitQuest)
* @see #exitQuest(boolean repeatable, boolean playExitQuest)
*/
private QuestState exitQuest(boolean repeatable)
private void exitQuest(boolean repeatable)
{
if (_simulated)
{
return null;
return;
}
_player.removeNotifyQuestOfDeath(this);
if (!isStarted())
{
return this;
return;
}
// Clean registered quest items
@@ -762,7 +730,6 @@ public class QuestState
setState(State.COMPLETED);
}
_vars = null;
return this;
}
/**
@@ -770,16 +737,15 @@ public class QuestState
* If {@code repeatable} is set to {@code false}, also removes all other quest data associated with this quest.
* @param repeatable if {@code true}, deletes all data and variables of this quest, otherwise keeps them
* @param playExitQuest if {@code true}, plays "ItemSound.quest_finish"
* @return this {@link QuestState} object
* @see #exitQuest(QuestType type)
* @see #exitQuest(QuestType type, boolean playExitQuest)
* @see #exitQuest(boolean repeatable)
*/
public QuestState exitQuest(boolean repeatable, boolean playExitQuest)
public void exitQuest(boolean repeatable, boolean playExitQuest)
{
if (_simulated)
{
return null;
return;
}
exitQuest(repeatable);
@@ -790,7 +756,7 @@ public class QuestState
// Notify to scripts
EventDispatcher.getInstance().notifyEventAsync(new OnPlayerQuestComplete(_player, getQuest().getId(), repeatable ? QuestType.REPEATABLE : QuestType.ONE_TIME), _player);
return this;
return;
}
/**

View File

@@ -17,8 +17,6 @@
package org.l2jmobius.gameserver.model.quest;
import java.util.concurrent.ScheduledFuture;
import java.util.logging.Level;
import java.util.logging.Logger;
import org.l2jmobius.commons.concurrent.ThreadPool;
import org.l2jmobius.gameserver.model.actor.Npc;
@@ -26,106 +24,68 @@ import org.l2jmobius.gameserver.model.actor.instance.PlayerInstance;
public class QuestTimer
{
protected static final Logger LOGGER = Logger.getLogger(QuestTimer.class.getName());
public class ScheduleTimerTask implements Runnable
{
@Override
public void run()
{
if (!_isActive)
{
return;
}
try
{
if (!_isRepeating)
{
cancelAndRemove();
}
_quest.notifyEvent(_name, _npc, _player);
}
catch (Exception e)
{
LOGGER.log(Level.SEVERE, "", e);
}
}
}
boolean _isActive = true;
final String _name;
final Quest _quest;
final Npc _npc;
final PlayerInstance _player;
final boolean _isRepeating;
private final ScheduledFuture<?> _scheduler;
private final String _name;
private final Quest _quest;
private final Npc _npc;
private final PlayerInstance _player;
private final boolean _isRepeating;
private ScheduledFuture<?> _scheduler;
public QuestTimer(Quest quest, String name, long time, Npc npc, PlayerInstance player, boolean repeating)
{
_name = name;
_quest = quest;
_player = player;
_name = name;
_npc = npc;
_player = player;
_isRepeating = repeating;
_scheduler = repeating ? ThreadPool.scheduleAtFixedRate(new ScheduleTimerTask(), time, time) : ThreadPool.schedule(new ScheduleTimerTask(), time);
}
public QuestTimer(Quest quest, String name, long time, Npc npc, PlayerInstance player)
{
this(quest, name, time, npc, player, false);
}
public QuestTimer(QuestState qs, String name, long time)
{
this(qs.getQuest(), name, time, null, qs.getPlayer(), false);
}
/**
* Cancel this quest timer.
*/
public void cancel()
{
_isActive = false;
if (_scheduler != null)
if (repeating)
{
_scheduler.cancel(false);
_scheduler = ThreadPool.scheduleAtFixedRate(new ScheduleTimerTask(), time, time); // Prepare auto end task
}
else
{
_scheduler = ThreadPool.schedule(new ScheduleTimerTask(), time); // Prepare auto end task
}
}
/**
* Cancel this quest timer and remove it from the associated quest.
*/
public void cancelAndRemove()
public void cancel()
{
cancel();
if (_scheduler != null)
{
_scheduler.cancel(false);
_scheduler = null;
}
_quest.removeQuestTimer(this);
}
/**
* Compares if this timer matches with the key attributes passed.
* @param quest the quest to which the timer is attached
* @param name the name of the timer
* @param npc the NPC attached to the desired timer (null if no NPC attached)
* @param player the player attached to the desired timer (null if no player attached)
* @return
* public method to compare if this timer matches with the key attributes passed.
* @param quest : Quest instance to which the timer is attached
* @param name : Name of the timer
* @param npc : Npc instance attached to the desired timer (null if no npc attached)
* @param player : Player instance attached to the desired timer (null if no player attached)
* @return boolean
*/
public boolean isMatch(Quest quest, String name, Npc npc, PlayerInstance player)
public boolean equals(Quest quest, String name, Npc npc, PlayerInstance player)
{
if ((quest == null) || (name == null))
if ((quest == null) || (quest != _quest))
{
return false;
}
if ((quest != _quest) || !name.equalsIgnoreCase(_name))
if ((name == null) || !name.equals(_name))
{
return false;
}
return ((npc == _npc) && (player == _player));
return (npc == _npc) && (player == _player);
}
public boolean isActive()
{
return _isActive;
return (_scheduler != null) && !_scheduler.isCancelled() && !_scheduler.isDone();
}
public boolean isRepeating()
@@ -158,4 +118,23 @@ public class QuestTimer
{
return _name;
}
public class ScheduleTimerTask implements Runnable
{
@Override
public void run()
{
if (_scheduler == null)
{
return;
}
if (!_isRepeating)
{
cancel();
}
_quest.notifyEvent(_name, _npc, _player);
}
}
}