{
Summary:
Timer class
## $Id: timers.pas,v 1.12 2004/04/01 13:04:32 druid Exp $
}
unit timers;
interface
uses
{$IFDEF WIN32}
Windows,
{$ENDIF}
SysUtils,
Classes,
skills,
dtypes,
chars;
type
TIMER_FUNC = procedure;
SPEC_FUNC = procedure(ch, victim : GCharacter; sn : GSkill);
GTimer = class
private
_name : string;
_counter : integer;
timer_func : TIMER_FUNC;
timeout : integer;
looping : boolean;
published
constructor Create(const name_ : string; func_ : TIMER_FUNC; timeout_ : integer; looping_ : boolean);
property name : string read _name;
property counter : integer read _counter write _counter;
end;
GSpecTimer = class (GTimer)
private
spec_func : SPEC_FUNC;
ch, victim : GCharacter;
timer_type : integer;
sn : GSkill;
published
constructor Create(const name_ : string; timer_type_ : integer; func_ : SPEC_FUNC; timeout_ : integer; ch_, victim_ : GCharacter; sn_ : GSkill);
end;
GTimerThread = class (TThread)
private
last_update : TDateTime;
protected
procedure Execute; override;
published
constructor Create();
property lastUpdate : TDateTime read last_update;
end;
var
timer_list : GDLinkedList;
procedure registerTimer(const name : string; func : TIMER_FUNC; timeout : integer; looping : boolean); overload;
procedure registerTimer(const name : string; timer_type : integer; func : SPEC_FUNC; timeout : integer; ch, victim : GCharacter; sn : GSkill); overload;
procedure unregisterTimer(const name_ : string); overload;
procedure unregisterTimer(ch : GCharacter; timer_type : integer); overload;
function hasTimer(ch : GCharacter; timer_type : integer) : GTimer; overload;
function hasTimer(ch : GCharacter; const timer_name : string) : GTimer; overload;
procedure initTimers();
procedure cleanupTimers();
implementation
uses
{$IFDEF WIN32}
Winsock2,
{$ENDIF}
constants,
console,
mudsystem,
util,
commands,
update,
area,
debug,
conns,
player,
server,
Channels;
// GTimer
constructor GTimer.Create(const name_ : string; func_ : TIMER_FUNC; timeout_ : integer; looping_ : boolean);
begin
inherited Create;
Self._name := name_;
Self._counter := timeout_;
Self.timer_func := func_;
Self.timeout := timeout_;
Self.looping := looping_;
end;
// GSpecTimer
constructor GSpecTimer.Create(const name_ : string; timer_type_ : integer; func_ : SPEC_FUNC; timeout_ : integer; ch_, victim_ : GCharacter; sn_ : GSkill);
begin
inherited Create(name_, nil, timeout_, false);
Self.spec_func := func_;
Self.timer_type := timer_type_;
Self.ch := ch_;
Self.victim := victim_;
Self.sn := sn_;
end;
// GTimerThread
constructor GTimerThread.Create();
begin
inherited Create(false);
last_update := Now();
end;
{ TODO remove nodes }
procedure GTimerThread.Execute();
var
node, node_next : GListNode;
timer : GTimer;
spec : GSpecTimer;
begin
while (not Terminated) do
begin
last_update := Now();
node := timer_list.head;
while (node <> nil) do
begin
timer := GTimer(node.element);
node_next := node.next;
try
dec(timer._counter);
if (timer._counter = 0) then
begin
if (timer is GSpecTimer) then
begin
spec := GSpecTimer(timer);
if (assigned(spec.spec_func)) then
spec.spec_func(spec.ch, spec.victim, spec.sn);
end
else
if (assigned(timer.timer_func)) then
timer.timer_func;
if (not timer.looping) then
begin
timer_list.remove(node);
timer.Free();
end
else
timer._counter := timer.timeout;
end;
except
on E : Exception do
begin
reportException(E, 'GTimerThread.Execute');
timer_list.remove(node);
timer.Free();
end;
end;
node := node_next;
end;
Sleep(250);
end;
end;
procedure registerTimer(const name : string; func : TIMER_FUNC; timeout : integer; looping : boolean);
var
timer : GTimer;
begin
timer := GTimer.Create(name, func, timeout, looping);
timer_list.insertLast(timer);
end;
procedure registerTimer(const name : string; timer_type : integer; func : SPEC_FUNC; timeout : integer; ch, victim : GCharacter; sn : GSkill);
var
timer : GSpecTimer;
begin
timer := GSpecTimer.Create(name, timer_type, func, timeout, ch, victim, sn);
timer_list.insertLast(timer);
end;
{ TODO remove nodes }
procedure unregisterTimer(const name_ : string);
var
timer : GTimer;
node : GListNode;
begin
node := timer_list.head;
while (node <> nil) do
begin
timer := GTimer(node.element);
if (timer.name = name_) then
begin
timer_list.remove(node);
timer.Free();
break;
end;
node := node.next;
end;
end;
{ TODO remove nodes }
procedure unregisterTimer(ch : GCharacter; timer_type : integer);
var
timer : GTimer;
spec : GSpecTimer;
node : GListNode;
begin
node := timer_list.head;
while (node <> nil) do
begin
timer := GTimer(node.element);
if (timer is GSpecTimer) then
begin
spec := GSpecTimer(timer);
if (spec.ch = ch) and (spec.timer_type = timer_type) then
begin
timer_list.remove(node);
timer.Free();
break;
end;
end;
node := node.next;
end;
end;
function hasTimer(ch : GCharacter; timer_type : integer) : GTimer;
var
timer : GTimer;
spec : GSpecTimer;
iterator : GIterator;
begin
Result := nil;
iterator := timer_list.iterator();
while (iterator.hasNext()) do
begin
timer := GTimer(iterator.next());
if (timer is GSpecTimer) then
begin
spec := GSpecTimer(timer);
if (spec.ch = ch) and (spec.timer_type = timer_type) and (spec.counter > 0) then
begin
Result := timer;
break;
end;
end;
end;
iterator.Free();
end;
function hasTimer(ch : GCharacter; const timer_name : string) : GTimer;
var
timer : GTimer;
spec : GSpecTimer;
iterator : GIterator;
begin
Result := nil;
iterator := timer_list.iterator();
while (iterator.hasNext()) do
begin
timer := GTimer(iterator.next());
if (timer is GSpecTimer) then
begin
spec := GSpecTimer(timer);
if (spec.ch = ch) and (spec.name = timer_name) and (spec.counter > 0) then
begin
Result := timer;
break;
end;
end;
end;
iterator.Free();
end;
// main timers
procedure update_auction;
begin
if (auction_good.pulse > 0) then
dec(auction_good.pulse)
else
if (auction_good.item <> nil) then
begin
auction_good.update;
auction_good.pulse := CPULSE_AUCTION;
end;
if (auction_evil.pulse > 0) then
dec(auction_evil.pulse)
else
if (auction_evil.item <> nil) then
begin
auction_evil.update;
auction_evil.pulse := CPULSE_AUCTION;
end;
end;
procedure update_main();
var
iterator : GIterator;
conn : GPlayerConnection;
begin
iterator := connection_list.iterator();
while (iterator.hasNext()) do
begin
conn := GPlayerConnection(iterator.next());
conn.pulse();
end;
iterator.Free();
end;
procedure update_gamehour();
var
iterator : GIterator;
area : GArea;
ch : GCharacter;
begin
{$IFDEF WIN32}
status := GetHeapStatus;
{$ENDIF}
update_affects;
update_tracks;
{ update age of areas and reset if hit timer }
iterator := area_list.iterator();
while (iterator.hasNext()) do
begin
area := GArea(iterator.next());
area.update();
end;
iterator.Free();
iterator := char_list.iterator();
while (iterator.hasNext()) do
begin
ch := GCharacter(iterator.next());
if (not ch.IS_NPC) and (IS_SET(GPlayer(ch).flags, PLR_LINKLESS)) then
begin
inc(GPlayer(ch).ld_timer);
if (GPlayer(ch).ld_timer > IDLE_LINKDEAD) then
begin
GPlayer(ch).quit;
continue;
end;
end;
end;
iterator.Free();
end;
procedure update_sec();
begin
calculateonline();
if (bg_info.count > 0) then
begin
dec(bg_info.count);
case bg_info.count of
60,30,10,5,2 : battlegroundMessage();
0 : startBattleground();
end;
end;
regenerate_chars();
end;
procedure initTimers();
begin
timer_list := GDLinkedList.Create();
registerTimer('main', update_main, 1, true);
registerTimer('auction', update_auction, 1, true);
registerTimer('gamehour', update_gamehour, CPULSE_GAMEHOUR, true);
registerTimer('second', update_sec, CPULSE_PER_SEC, true);
end;
procedure cleanupTimers();
begin
timer_list.clear();
timer_list.Free();
end;
end.