forked from mwo/ServVenge
-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathac.js
More file actions
211 lines (175 loc) · 5.9 KB
/
ac.js
File metadata and controls
211 lines (175 loc) · 5.9 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
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
const WebSocket = require('ws'),
msgpack = require('msgpack-lite');
let getType = t => t.constructor.name.toLowerCase();
Array.prototype.check = function (...types) {
return this.map(getType).every((e, i) => e == types[i]) && this.length == types.length;
}
Array.prototype.un = function () {
return this.map(e => e / 5);
}
Array.prototype.vector = function () {
return {
x: this[0],
y: this[1],
z: this[2]
};
}
class ssac {
constructor(ws, plr, callback, debug = ()=>{}) { //optional debugging callback
//onsend aka incoming
let send = ws.send;
ws.send = (...args) => {
this.onsend(args);
return send.apply(this, args)
}
//constructor
this.ws = ws;
this.callback = callback;
this.log = debug;
this.immune = true; //so respawning doesn't trigger ac
//actual player object from constructor
this.plr = plr;
//damages
this.damages = {
Sniper: {
body: 95
},
Scar: {
body: 15
},
"Tec-9": {
body: 12
},
Shotgun: {
body: 12
}
}
//information tracking on player
this.player = {
s: {
w: !1,
a: !1,
s: !1,
d: !1,
f: !1
},
speed: 0,
lastp: null,
e: ''
}
this.speedLimit = 3.5; // speed cap
this.mMap = {
//set up parsing for inputs and validate position.
p: msg => {
//type check
this.check(msg, 'string', 'number', 'number', 'number', 'number', 'number')
//get player positions
let p = this.player,
pos = msg.slice(1).slice(0, 3).un(), //extract and decode positions
vec = pos.vector();
//make sure we have a last position to compare to
if (!p.lastP) return;
//player var and distance
let lp = p.lastP.vector(),
dist = this.getDist(lp.x, lp.z, vec.x, vec.z);
//save speed to player obj
p.speed = dist;
//check if immune or over speed limit
if (!this.immune && p.speed >= this.speedLimit) this.isc(msg[0]);
//save position
p.lastP = pos;
},
throw: msg => {
//type check
this.check(msg, 'string', 'string', 'number', 'number', 'number', 'number', 'number', 'number')
},
s: msg => {
//type check
this.check(msg, 'string', 'string', 'boolean');
//keeping in order
let cur = this.player.s;
cur[msg[1]] = !cur[msg[1]];
if (cur[msg[1]] != msg[2]) this.isc(msg[0]);
},
da: msg => {
//type check
this.check(msg, 'string', 'number', 'number', 'boolean', 'number', 'number', 'number');
//cant fire unless animation is playing
if (!this.player.s.f) this.isc(msg[0]);
//generate server side damage and compare note: (this should be server side anyway)
//vars
let dmg = msg[2],
weapon = this.damages[this.plr.weapon];
//make sure weapon is in damages obj
if (!weapon) return;
let sdmg = weapon.body + (msg[3] ? 5 : 0); //calculate damage
//comparing
if (dmg != sdmg) this.isc('Manipulated damage value');
},
point: msg => {
//type check
this.check(msg, 'string');
},
guard: msg => {
//type check
this.check(msg, 'string', 'boolean');
},
show: msg => {
//type check
this.check(msg, 'string', 'boolean');
},
chat: msg => {
//type check
this.check(msg, 'string', 'string');
},
e: msg => {
//type check
this.check(msg, 'string', 'string');
//vars
let p = this.player,
k = msg[1],
brh = () => this.isc(msg.slice(0, 2).join(' '));
if (k == 'connected') return; //doesn't trigger speed detect on spawn
//cant jump more than twice ???? without landing
if (p.e.includes('jjj')) brh();
(p.e += k).slice(0, 3);
},
weapon: msg => {
//type check
this.check(msg, 'string', 'string');
},
vote: msg => {
//type check
this.check(msg, 'string', 'string');
//value check
let prop = msg[1];
//if (prop != "Sierra" || prop != "Xibalba") this.isc(msg[0]);
}
}
//onmessage aka outgoing
ws.on('message', this.message.bind(this));
}
sComp(a, b) {
return a == b && getType(a) == getType(b);
}
getDist(a, b, c, d) {
return Math.sqrt(Math.abs(a - c) ** 2 + Math.abs(b - d) ** 2);
}
check(msg, ...args) {
if (!msg.check(...args)) this.isc('type error');
}
isc(reason) {
this.callback(this.ws, reason, this.speed);
}
message(_, msg = msgpack.decode(_)) {
let f = this.mMap[msg[0]];
if (f) f(msg);
}
onsend(msg) {
if (msg[0] == 'respawn' && msg[1] == this.plr.playerId) {
this.immune = true;
setTimeout(() => this.immune = false, 2e3);
}
}
}
module.exports = ssac;