/
tick.ts
113 lines (91 loc) · 3.12 KB
/
tick.ts
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
113
import { Character } from '@AthenaShared/interfaces/character';
import * as alt from 'alt-server';
import { PLAYER_SYNCED_META } from '../../shared/enums/playerSynced';
import { SYSTEM_EVENTS } from '../../shared/enums/system';
import * as Athena from '../api';
const timeBetweenPings = 4950;
alt.onClient(SYSTEM_EVENTS.PLAYER_TICK, handlePing);
/**
* Used to save the player every once in a while.
*
*
* @param {alt.Player} player An alt:V Player Entity
* @return {Promise<void>}
*/
export async function onTick(player: alt.Player): Promise<void> {
if (Overrides.onTick) {
return Overrides.onTick(player);
}
let injections: Partial<Character> = {};
if (!player || !player.valid) {
return;
}
const data = Athena.document.character.get(player);
if (typeof data === 'undefined') {
return;
}
const dist = Athena.utility.vector.distance2d(player.pos, data.pos as alt.Vector2);
if (player && player.pos && dist >= 1) {
injections.pos = player.pos;
}
if (player.health !== data.health) {
injections.health = player.health;
}
if (player.armour !== data.armour) {
injections.armour = player.armour;
}
if (Object.keys(injections).length <= 0) {
return;
}
Athena.document.character.setBulk(player, injections);
}
/**
* This is a tick event that is sent up from the player.
* This tick event is then used to process specific player events.
* This varies from player revival, coordinate processing, etc.
* Helps push the load onto the server, rather than the player.
* @param {alt.Player} player An alt:V Player Entity
* @return {void}
*/
function handlePing(player: alt.Player): void {
if (Overrides.handlePing) {
return Overrides.handlePing(player);
}
if (!player.nextPingTime) {
player.nextPingTime = Date.now() + timeBetweenPings;
}
if (Date.now() < player.nextPingTime) {
return;
}
player.setSyncedMeta(PLAYER_SYNCED_META.PING, player.ping);
player.setSyncedMeta(PLAYER_SYNCED_META.POSITION, player.pos);
player.nextPingTime = Date.now() + timeBetweenPings;
// Handles General Saving / Synchronization
onTick(player);
Athena.player.sync.syncedMeta(player);
if (!player.nextPlayTime || Date.now() > player.nextPlayTime) {
player.nextPlayTime = Date.now() + 60000;
Athena.player.sync.playTime(player);
}
// Only the driver of the vehicle should be responsible for vehicle updates.
if (player.vehicle && player.vehicle.driver === player) {
Athena.vehicle.controls.update(player.vehicle);
}
}
interface TickFuncs {
onTick: typeof onTick;
handlePing: typeof handlePing;
}
const Overrides: Partial<TickFuncs> = {};
export function override(functionName: 'onTick', callback: typeof onTick);
export function override(functionName: 'handlePing', callback: typeof handlePing);
/**
* Used to override player tick functionality
*
*
* @param {keyof TickFuncs} functionName
* @param {*} callback
*/
export function override(functionName: keyof TickFuncs, callback: any): void {
Overrides[functionName] = callback;
}