-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathscheduler.ts
More file actions
112 lines (93 loc) · 2.87 KB
/
Copy pathscheduler.ts
File metadata and controls
112 lines (93 loc) · 2.87 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
import { Process } from "./process";
const RunService = game.GetService("RunService");
/**
*
*/
export class ProcessScheduler {
private static TPS = 20; // Grab value from tina.yaml when able
private lastTick: number;
private timeBetweenTicks: number;
private connection?: RBXScriptConnection;
private processes: Array<Process> = new Array();
private processesToRemove: Array<Process> = new Array();
/** Used to keep track of when the .update() method is running since .removeProcess() could be called during a Process callback. */
private updating = false;
constructor() {
this.timeBetweenTicks = 1 / ProcessScheduler.TPS;
this.lastTick = os.clock();
}
private onHeartbeat(): void {
const currentTick = os.clock();
const deltaTime = currentTick - this.lastTick;
if (deltaTime >= this.timeBetweenTicks) {
// Adjust lastTick to based on timeBetweenTicks to keep interval relatively stable
this.lastTick = currentTick - (deltaTime % this.timeBetweenTicks);
this.update(deltaTime);
}
}
private update(dt: number): void {
// Update has started
this.updating = true;
for (const process of this.processes) {
// Update suspended processes
if (process.isSuspended) {
process.suspensionTime -= 1;
if (process.suspensionTime < 0) {
process.isSuspended = false;
}
}
// Run active processes
if (process.isSuspended) continue;
try {
process.tick(dt);
} catch (error) {
// TODO: log any errors properly.
}
}
// Remove processes in queue
for (const process of this.processesToRemove) {
this._removeProcess(process);
}
this.processesToRemove = new Array();
// Update has finished
this.updating = false;
}
public addProcess(process: Process): void {
if (this.processes.includes(process)) return;
this.processes.push(process);
}
public removeProcess(process: Process): void {
// If Processes are currently being updated then deffer removal until updating has finished
if (this.updating) {
this.processesToRemove.push(process);
} else {
this._removeProcess(process);
}
}
private _removeProcess(process: Process): void {
const index = this.processes.indexOf(process);
if (index < 0) return;
this.processes.remove(index);
}
public hasProcess(name: string): boolean {
return !!this.processes.find(p => p.name === name);
}
public getProcess(name: string): Process | undefined {
return this.processes.find(p => p.name === name);
}
public start(): void {
if (this.connection) return; // TODO: log that they're doing something stupid.
this.connection = RunService.Heartbeat.Connect(() => this.onHeartbeat());
}
/**
* @hidden
* Remove all references and disconnect all connections
*/
public destroy(): void {
this.connection?.Disconnect();
this.processes = new Array();
this.processesToRemove = new Array();
}
}
const Scheduler = new ProcessScheduler();
export default Scheduler;