1
0
Fork 0
mirror of https://github.com/demostf/demo.js synced 2026-06-04 00:54:14 +02:00

move handlers for each packet to their own file

This commit is contained in:
Robin Appelman 2015-04-01 20:56:04 +02:00
commit 9d5e599f89
13 changed files with 431 additions and 392 deletions

View file

@ -0,0 +1,47 @@
var getCoord = function (stream) {
var hasInt = !!stream.readBits(1);
var hasFract = !!stream.readBits(1);
var value = 0;
if (hasInt || hasFract) {
var sign = !!stream.readBits(1);
if (hasInt) {
value += stream.readBits(14) + 1;
}
if (hasFract) {
value += stream.readBits(5) * (1 / 32);
}
if (sign) {
value = -value;
}
}
return value;
};
var getVecCoord = function (stream) {
var hasX = !!stream.readBits(1);
var hasY = !!stream.readBits(1);
var hasZ = !!stream.readBits(1);
return {
x: hasX ? getCoord(stream) : 0,
y: hasY ? getCoord(stream) : 0,
z: hasZ ? getCoord(stream) : 0
}
};
module.exports = function (stream) { // 21: BSPDecal
var position = getVecCoord(stream);
var textureIndex = stream.readBits(9);
if (stream.readBits(1)) {
var entIndex = stream.readBits(11);
var modelIndex = stream.readBits(12);
}
var lowPriority = !!stream.readBits(1);
return {
packetType : 'BSPDecal',
position : position,
textureIndex: textureIndex,
entIndex : entIndex,
modelIndex : modelIndex,
lowPriority : lowPriority
}
};

View file

@ -0,0 +1,30 @@
function logBase2(num) {
var result = 0;
while ((num >>= 1) != 0) {
result++;
}
return result;
}
module.exports = function (stream) { // 10: classInfo
var number = stream.readBits(16);
var create = !!stream.readBits(1);
var entries = [];
if (!create) {
var bits = logBase2(number) + 1;
for (var i = 0; i < number; i++) {
var entry = {
'classId' : stream.readBits(bits),
'className' : stream.readASCIIString(),
'dataTableName': stream.readASCIIString()
};
entries.push(entry);
}
}
return {
'packetType': 'classInfo',
number : number,
create : create,
entries : entries
}
};

View file

@ -0,0 +1,10 @@
var PacketStringTable = require('../../packetstringtable');
module.exports = function (stream) { // 12: createStringTable
var stringTable = new PacketStringTable(stream);
var tables = stringTable.parse();
return {
packetType: 'createStringTable',
table : tables
};
};

View file

@ -0,0 +1,50 @@
var parseGameEvent = function (eventId, stream, events) {
if (!events[eventId]) {
return 'unknown';
}
var eventDescription = events[eventId];
var values = {};
for (var i = 0; i < eventDescription.entries.length; i++) {
var entry = eventDescription.entries[i];
values[entry.name] = getGameEventValue(stream, entry);
}
return {
name : eventDescription.name,
type : eventDescription.type,
values: values
};
};
var getGameEventValue = function (stream, entry) {
switch (entry.type) {
case 1:
return stream.readUTF8String();
case 2:
return stream.readFloat32();
case 3:
return stream.readInt32();
case 4:
return stream.readBits(16);
case 5:
return stream.readBits(8);
case 6:
return !!stream.readBits(1);
case 7:
return 'local value';
default:
throw 'invalid game event type';
}
};
module.exports = function (stream, events) { // 25: game event
var length = stream.readBits(11);
var end = stream._index + length;
var eventId = stream.readBits(9);
var event = parseGameEvent(eventId, stream, events);
stream._index = end;
return {
packetType: 'gameEvent',
event : event
}
};

View file

@ -0,0 +1,29 @@
module.exports = function (stream, events) { // 30: gameEventList
// list of game events and parameters
var numEvents = stream.readBits(9);
var length = stream.readBits(20);
for (var i = 0; i < numEvents; i++) {
var id = stream.readBits(9);
var name = stream.readASCIIString();
var type = stream.readBits(3);
var entries = [];
while (type !== 0) {
var entryName = stream.readASCIIString();
entries.push({
type: type,
name: entryName
});
type = stream.readBits(3);
}
events[id] = {
id : id,
name : name,
type : type,
entries: entries
};
}
return {
packetType: 'gameEventList',
events : events
}
};

View file

@ -0,0 +1,81 @@
var PVS = {
PRESERVE: 0,
ENTER : 1,
LEAVE : 2,
DELETE : 3
};
function readIndex(stream, baseIndex) {
// https://github.com/skadistats/smoke/blob/a2954fbe2fa3936d64aee5b5567be294fef228e6/smoke/io/stream/entity.pyx#L15
var encodedIndex = stream.readBits(6);
if (encodedIndex & 0x30) {
var a = (encodedIndex >> 4) & 3;
var b = (a == 3) ? 16 : 0;
var i = stream.readBits(4 * a + b) << 4;
encodedIndex = i | (encodedIndex & 0x0f);
}
return baseIndex + encodedIndex + 1;
}
function readPVS(stream) {
// https://github.com/skadistats/smoke/blob/a2954fbe2fa3936d64aee5b5567be294fef228e6/smoke/io/stream/entity.pyx#L24
var pvs;
var hi = stream.readBoolean();
var low = stream.readBoolean();
if (low && !hi) {
pvs = PVS.ENTER;
} else if (!(hi || low)) {
pvs = PVS.PRESERVE;
} else if (hi) {
pvs = (low) ? (PVS.LEAVE | PVS.DELETE) : PVS.LEAVE;
} else {
pvs = -1;
}
return pvs;
}
module.exports = function (stream) { //26: packetEntities
// todo
var maxEntries = stream.readBits(11);
var isDelta = !!stream.readBits(1);
if (isDelta) {
var delta = stream.readInt32();
} else {
delta = null;
}
var baseLink = !!stream.readBits(1);
var updatedEntries = stream.readBits(11);
var length = stream.readBits(20);
var updatedBaseLink = !!stream.readBits(1);
var end = stream._index + length;
var entities = [];
//console.log('max: ' + maxEntries);
//var entityId = -1;
//
//for (var i = 0; i < updatedEntries; i++) {
// entityId = readIndex(stream, entityId);
// var pvs = readPVS(stream);
// if (pvs = PVS.PRESERVE) {
//
// }
//}
stream._index = end;
//var ent = {
// packetType : 'packetEntities',
// maxEntries : maxEntries,
// isDelta : isDelta,
// delta : delta,
// baseLink : baseLink,
// updatedEntries : updatedEntries,
// length : length,
// updatedBaseLink: updatedBaseLink
//};
//console.log(ent);
//console.log(entities);
//process.exit();
return {
packetType: 'packetEntities',
entities : entities
};
}

View file

@ -0,0 +1,12 @@
module.exports = function (stream) { // 17: parseSounds
var reliable = !!stream.readBits(1);
var num = (reliable) ? 1 : stream.readBits(8);
var length = (reliable) ? stream.readBits(8) : stream.readBits(16);
stream._index += length;
return {
packetType: 'parseSounds',
reliable : reliable,
num : num,
length : length
}
};

View file

@ -0,0 +1,11 @@
module.exports= function (stream) { // 5: setconvar
var count = stream.readBits(8);
var vars = {};
for (var i = 0; i < count; i++) {
vars[stream.readUTF8String()] = stream.readUTF8String();
}
return {
packetType: 'setConVar',
vars : vars
}
};

View file

@ -0,0 +1,10 @@
var PacketStringTable = require('../../packetstringtable');
module.exports = function (stream) { // 12: updateStringTable
var stringTable = new PacketStringTable(stream);
var tables = stringTable.parse();
return {
packetType: 'updateStringTable',
table : tables
};
};

View file

@ -0,0 +1,83 @@
var ParserGenerator = require('../../parsergenerator');
var userMessageParsers = {
4: require('../userMessage/SayText2'),
5: ParserGenerator.make('textMsg', 'destType{8}text{s}')
};
module.exports = function (stream) { // 23: user message
var type = stream.readBits(8);
var length = stream.readBits(11);
var pos = stream._index;
if (userMessageParsers[type]) {
var result = userMessageParsers[type](stream);
} else {
result = {
packetType: 'unknownUserMessage',
type : type
}
}
stream._index = pos + length;
return result;
};
var UserMessageType = {
Geiger : 0,
Train : 1,
HudText : 2,
SayText : 3,
SayText2 : 4,
TextMsg : 5,
ResetHUD : 6,
GameTitle : 7,
ItemPickup : 8,
ShowMenu : 9,
Shake : 10,
Fade : 11,
VGUIMenu : 12,
Rumble : 13,
CloseCaption : 14,
SendAudio : 15,
VoiceMask : 16,
RequestState : 17,
Damage : 18,
HintText : 19,
KeyHintText : 20,
HudMsg : 21,
AmmoDenied : 22,
AchievementEvent : 23,
UpdateRadar : 24,
VoiceSubtitle : 25,
HudNotify : 26,
HudNotifyCustom : 27,
PlayerStatsUpdate : 28,
PlayerIgnited : 29,
PlayerIgnitedInv : 30,
HudArenaNotify : 31,
UpdateAchievement : 32,
TrainingMsg : 33,
TrainingObjective : 34,
DamageDodged : 35,
PlayerJarated : 36,
PlayerExtinguished : 37,
PlayerJaratedFade : 38,
PlayerShieldBlocked: 39,
BreakModel : 40,
CheapBreakModel : 41,
BreakModel_Pumpkin : 42,
BreakModelRocketDud: 43,
CallVoteFailed : 44,
VoteStart : 45,
VotePass : 46,
VoteFailed : 47,
VoteSetup : 48,
PlayerBonusPoints : 49,
SpawnFlyingBird : 50,
PlayerGodRayEffect : 51,
SPHapWeapEvent : 52,
HapDmg : 53,
HapPunch : 54,
HapSetDrag : 55,
HapSet : 56,
HapMeleeContact : 57
};

View file

@ -0,0 +1,44 @@
module.exports = function (stream) { // 4: SayText2
var client = stream.readBits(8);
var raw = stream.readBits(8);
var pos = stream._index;
var from, text, kind, arg1, arg2;
if (stream.readBits(8) === 1) {
var first = stream.readBits(8);
if (first === 7) {
var color = stream.readUTF8String(6);
} else {
stream._index = pos + 8;
}
text = stream.readUTF8String();
if (text.substr(0, 6) === '*DEAD*') {
// grave talk is in the format '*DEAD* \u0003$from\u0001: $text'
var start = text.indexOf('\u0003');
var end = text.indexOf('\u0001');
from = text.substr(start + 1, end - start - 1);
text = text.substr(end + 5);
kind = 'TF_Chat_AllDead';
}
} else {
stream._index = pos;
kind = stream.readUTF8String();
from = stream.readUTF8String();
text = stream.readUTF8String();
stream.readASCIIString();
stream.readASCIIString();
}
// cleanup color codes
text = text.replace(/\u0001/g, '');
text = text.replace(/\u0003/g, '');
while ((pos = text.indexOf('\u0007')) !== -1) {
text = text.slice(0, pos) + text.slice(pos + 7);
}
return {
packetType: 'sayText2',
client : client,
raw : raw,
kind : kind,
from : from,
text : text
}
};

View file

@ -1,13 +1,14 @@
{ {
"name": "tf2-demo", "name": "tf2-demo",
"description": "A parser for TF2 demo files", "description": "A parser for TF2 demo files",
"version": "0.1.0", "version": "0.1.0",
"bin": { "bin": {
"demo-analyse": "./bin/analyse.js" "demo-analyse": "./bin/analyse.js"
}, },
"main": "demo.js", "main": "demo.js",
"dependencies": { "dependencies": {
"bit-buffer": "icewind1991/bit-buffer", "bit-buffer": "icewind1991/bit-buffer",
"minimist": "1.1.x" "buffertools": "^2.1.2",
} "minimist": "1.1.x"
}
} }

393
packet.js
View file

@ -1,20 +1,10 @@
var ParserGenerator = require('./parsergenerator'); var ParserGenerator = require('./parsergenerator');
var StringTable = require('./stringtable');
var PacketStringTable = require('./packetstringtable');
// https://code.google.com/p/coldemoplayer/source/browse/branches/2.0/compLexity+Demo+Player/CDP.Source/Messages/?r=219 // https://code.google.com/p/coldemoplayer/source/browse/branches/2.0/compLexity+Demo+Player/CDP.Source/Messages/?r=219
// https://github.com/TimePath/hl2-toolkit/tree/master/src/main/java/com/timepath/hl2/io/demo // https://github.com/TimePath/hl2-toolkit/tree/master/src/main/java/com/timepath/hl2/io/demo
// https://github.com/stgn/netdecode/blob/master/Packet.cs // https://github.com/stgn/netdecode/blob/master/Packet.cs
// https://github.com/LestaD/SourceEngine2007/blob/master/src_main/common/netmessages.cpp // https://github.com/LestaD/SourceEngine2007/blob/master/src_main/common/netmessages.cpp
function logBase2(num) {
var result = 0;
while ((num >>= 1) != 0) {
result++;
}
return result;
}
var Packet = function (type, tick, stream, length) { var Packet = function (type, tick, stream, length) {
this.type = type; this.type = type;
this.tick = tick; this.tick = tick;
@ -39,7 +29,7 @@ Packet.prototype.parse = function () {
while (this.bitsLeft > 6) { // last 6 bits for NOOP while (this.bitsLeft > 6) { // last 6 bits for NOOP
var type = this.stream.readBits(6); var type = this.stream.readBits(6);
if (Packet.parsers[type]) { if (Packet.parsers[type]) {
var packet = Packet.parsers[type].call(this, this.stream); var packet = Packet.parsers[type].call(this, this.stream, Packet.gameEventMap);
//console.log(packet); //console.log(packet);
packets.push(packet); packets.push(packet);
} else { } else {
@ -49,398 +39,39 @@ Packet.prototype.parse = function () {
return packets; return packets;
}; };
Packet.parseGameEvent = function (eventId, stream) {
if (!Packet.gameEventMap[eventId]) {
return 'unknown';
}
var eventDescription = this.gameEventMap[eventId];
var values = {};
for (var i = 0; i < eventDescription.entries.length; i++) {
var entry = eventDescription.entries[i];
values[entry.name] = Packet.getGameEventValue(stream, entry);
}
//console.log(eventDescription.name);
return {
name : eventDescription.name,
type : eventDescription.type,
values: values
};
};
Packet.getGameEventValue = function (stream, entry) {
switch (entry.type) {
case 1:
return stream.readUTF8String();
case 2:
return stream.readFloat32();
case 3:
return stream.readInt32();
case 4:
return stream.readBits(16);
case 5:
return stream.readBits(8);
case 6:
return !!stream.readBits(1);
case 7:
return 'local value';
default:
throw 'invalid game event type';
}
};
Packet.parsers = { Packet.parsers = {
0 : function () { 0 : function () {//NOOP
}, },
2 : ParserGenerator.make('file', 'transferId{32}fileName{s}requested{b}'), 2 : ParserGenerator.make('file', 'transferId{32}fileName{s}requested{b}'),
3 : ParserGenerator.make('netTick', 'tick{32}frameTime{16}stdDev{16}'), 3 : ParserGenerator.make('netTick', 'tick{32}frameTime{16}stdDev{16}'),
4 : ParserGenerator.make('stringCmd', 'command{s}'), 4 : ParserGenerator.make('stringCmd', 'command{s}'),
5 : function (stream) { // setconvar 5 : require('./handlers/packet/setConVar'),
var count = stream.readBits(8);
var vars = {};
for (var i = 0; i < count; i++) {
vars[stream.readUTF8String()] = stream.readUTF8String();
}
return {
packetType: 'setConVar',
vars : vars
}
},
6 : ParserGenerator.make('sigOnState', 'state{8}count{32}'), 6 : ParserGenerator.make('sigOnState', 'state{8}count{32}'),
7 : ParserGenerator.make('print', 'value{s}'), 7 : ParserGenerator.make('print', 'value{s}'),
8 : ParserGenerator.make('serverInfo', 8 : ParserGenerator.make('serverInfo',
'version{16}serverCount{32}stv{b}dedicated{b}maxCrc{32}maxClasses{16}' + 'version{16}serverCount{32}stv{b}dedicated{b}maxCrc{32}maxClasses{16}' +
'mapHash{128}playerCount{8}maxPlayerCount{8}intervalPerTick{f32}platform{s1}' + 'mapHash{128}playerCount{8}maxPlayerCount{8}intervalPerTick{f32}platform{s1}' +
'game{s}map{s}skybox{s}serverName{s}replay{b}'), 'game{s}map{s}skybox{s}serverName{s}replay{b}'),
10: function (stream) { //classInfo 10: require('./handlers/packet/classInfo'),
var number = stream.readBits(16);
var create = !!stream.readBits(1);
var entries = [];
if (!create) {
var bits = logBase2(number) + 1;
for (var i = 0; i < number; i++) {
var entry = {
'classId' : stream.readBits(bits),
'className' : stream.readASCIIString(),
'dataTableName': stream.readASCIIString()
};
entries.push(entry);
}
}
return {
'packetType': 'classInfo',
number : number,
create : create,
entries : entries
}
},
11: ParserGenerator.make('setPause', 'paused{b}'), 11: ParserGenerator.make('setPause', 'paused{b}'),
12: function (stream) { 12: require('./handlers/packet/createStringTable'),
var stringTable = new PacketStringTable(stream); 13: require('./handlers/packet/updateStringTable'),
var tables = stringTable.parse();
return {
packetType: 'createStringTable',
table : tables
};
},
13: function (stream) { //updatestringTable
var stringTable = new PacketStringTable(stream);
var tables = stringTable.parse();
return {
packetType: 'updateStringTable',
table : tables
};
var tableId = stream.readBits(5);
var changeEntries = stream.readBits(1) ? stream.readBits(16) : 1;
var length = stream.readBits(20);
var end = stream._index + length;
stream.readBits(7);
var strings = {};
//var table = StringTable.tables[tableId];
// no idea why but it mostly works
var a = stream.readBits(1);
var b = stream.readBits(1);
if (a && !b) {
stream.readBits(12);
} else if (!b) {
stream.readBits(16);
} else {
stream.readBits(6);
}
stream._index = end;
//throw false;
return {
packetType : 'updateStringTables',
tableId : tableId,
changedEntries: changeEntries,
length : length,
strings : strings
}
},
14: ParserGenerator.make('voiceInit', 'codec{s}quality{8}'), 14: ParserGenerator.make('voiceInit', 'codec{s}quality{8}'),
15: ParserGenerator.make('voiceData', 'client{8}proximity{8}length{16}_{$length}'), 15: ParserGenerator.make('voiceData', 'client{8}proximity{8}length{16}_{$length}'),
17: function (stream) { //parseSounds 17: require('./handlers/packet/parseSounds'),
var reliable = !!stream.readBits(1);
var num = (reliable) ? 1 : stream.readBits(8);
var length = (reliable) ? stream.readBits(8) : stream.readBits(16);
stream._index += length;
return {
packetType: 'parseSounds',
reliable : reliable,
num : num,
length : length
}
},
18: ParserGenerator.make('setView', 'index{11}'), 18: ParserGenerator.make('setView', 'index{11}'),
19: ParserGenerator.make('fixAngle', 'relative{b}x{16}y{16}z{16}'), 19: ParserGenerator.make('fixAngle', 'relative{b}x{16}y{16}z{16}'),
21: function (stream) { //BSPDecal 21: require('./handlers/packet/bspDecal'),
var getCoord = function (stream) { 23: require('./handlers/packet/userMessage'),
var hasInt = !!stream.readBits(1);
var hasFract = !!stream.readBits(1);
var value = 0;
if (hasInt || hasFract) {
var sign = !!stream.readBits(1);
if (hasInt) {
value += stream.readBits(14) + 1;
}
if (hasFract) {
value += stream.readBits(5) * (1 / 32);
}
if (sign) {
value = -value;
}
}
return value;
};
var getVecCoord = function (stream) {
var hasX = !!stream.readBits(1);
var hasY = !!stream.readBits(1);
var hasZ = !!stream.readBits(1);
return {
x: hasX ? getCoord(stream) : 0,
y: hasY ? getCoord(stream) : 0,
z: hasZ ? getCoord(stream) : 0
}
};
var position = getVecCoord(stream);
var textureIndex = stream.readBits(9);
if (stream.readBits(1)) {
var entIndex = stream.readBits(11);
var modelIndex = stream.readBits(12);
}
var lowPriority = !!stream.readBits(1);
return {
packetType : 'BSPDecal',
position : position,
textureIndex: textureIndex,
entIndex : entIndex,
modelIndex : modelIndex,
lowPriority : lowPriority
}
},
23: function (stream) { // user message
// user message
var type = stream.readBits(8);
var length = stream.readBits(11);
var pos = stream._index;
if (Packet.userMessageParsers[type]) {
var result = Packet.userMessageParsers[type](stream);
} else {
result = {
packetType: 'unknownUserMessage',
type : type
}
}
//console.log(result);
//console.log(((pos + length) - stream._index) + ' bits left');
stream._index = pos + length;
return result;
},
24: ParserGenerator.make('entityMessage', 'index{11}id{9}length{11}data{$length}'), 24: ParserGenerator.make('entityMessage', 'index{11}id{9}length{11}data{$length}'),
25: function (stream) { //game event 25: require('./handlers/packet/gameEvent'),
var length = stream.readBits(11); 26: require('./handlers/packet/packetEntities'),
var end = stream._index + length;
var eventId = stream.readBits(9);
var event = Packet.parseGameEvent(eventId, stream);
stream._index = end;
return {
packetType: 'gameEvent',
event : event
}
},
26: function (stream) { //packetEntities
// todo
var maxEntries = stream.readBits(11);
var isDelta = !!stream.readBits(1);
if (isDelta) {
var delta = stream.readInt32();
} else {
delta = null;
}
var baseLink = !!stream.readBits(1);
var updatedEntries = stream.readBits(11);
var length = stream.readBits(20);
var updatedBaseLink = !!stream.readBits(1);
stream._index += length;
return {
packetType : 'packetEntities',
maxEntries : maxEntries,
isDelta : isDelta,
delta : delta,
baseLink : baseLink,
updatedEntries : updatedEntries,
length : length,
updatedBaseLink: updatedBaseLink
}
},
27: ParserGenerator.make('tempEntities', 'count{8}length{17}_{$length}'), 27: ParserGenerator.make('tempEntities', 'count{8}length{17}_{$length}'),
28: ParserGenerator.make('preFetch', 'index{14}'), 28: ParserGenerator.make('preFetch', 'index{14}'),
29: ParserGenerator.make('menu', 'type{16}length{16}_{$length}_{$length}_{$length}_{$length}_{$length}_{$length}_{$length}'),//length*8 29: ParserGenerator.make('menu', 'type{16}length{16}_{$length}_{$length}_{$length}_{$length}_{$length}_{$length}_{$length}'),//length*8
30: function (stream) { //gameEventList 30: require('./handlers/packet/gameEventList'),
// list of game events and parameters
var numEvents = stream.readBits(9);
var length = stream.readBits(20);
var events = {};
for (var i = 0; i < numEvents; i++) {
var id = stream.readBits(9);
var name = stream.readASCIIString();
var type = stream.readBits(3);
var entries = [];
while (type !== 0) {
var entryName = stream.readASCIIString();
entries.push({
type: type,
name: entryName
});
type = stream.readBits(3);
}
events[id] = {
id : id,
name : name,
type : type,
entries: entries
};
}
Packet.gameEventMap = events;
return {
packetType: 'gameEventList',
events : events
}
},
31: ParserGenerator.make('getCvarValue', 'cookie{32}value{s}'), 31: ParserGenerator.make('getCvarValue', 'cookie{32}value{s}'),
32: ParserGenerator.make('cmdKeyValues', 'length{32}data{$length}') 32: ParserGenerator.make('cmdKeyValues', 'length{32}data{$length}')
}; };
Packet.userMessageParsers = {
4: function (stream) {
var client = stream.readBits(8);
var raw = stream.readBits(8);
var pos = stream._index;
var from, text, kind, arg1, arg2;
if (stream.readBits(8) === 1) {
var first = stream.readBits(8);
if (first === 7) {
var color = stream.readUTF8String(6);
} else {
stream._index = pos + 8;
}
text = stream.readUTF8String();
if (text.substr(0, 6) === '*DEAD*') {
// grave talk is in the format '*DEAD* \u0003$from\u0001: $text'
var start = text.indexOf('\u0003');
var end = text.indexOf('\u0001');
from = text.substr(start + 1, end - start - 1);
text = text.substr(end + 5);
kind = 'TF_Chat_AllDead';
}
} else {
stream._index = pos;
kind = stream.readUTF8String();
from = stream.readUTF8String();
text = stream.readUTF8String();
stream.readASCIIString();
stream.readASCIIString();
}
// cleanup color codes
text = text.replace(/\u0001/g, '');
text = text.replace(/\u0003/g, '');
while ((pos = text.indexOf('\u0007')) !== -1) {
text = text.slice(0, pos) + text.slice(pos + 7);
}
return {
packetType: 'sayText2',
client : client,
raw : raw,
kind : kind,
from : from,
text : text
}
},
//4: ParserGenerator.make('sayText2', 'client{8}raw{8}kind{s}from{s}text{s}arg1{s}arg2{s}'),
5: ParserGenerator.make('textMsg', 'destType{8}text{s}')
};
var UserMessageType = {
Geiger : 0,
Train : 1,
HudText : 2,
SayText : 3,
SayText2 : 4,
TextMsg : 5,
ResetHUD : 6,
GameTitle : 7,
ItemPickup : 8,
ShowMenu : 9,
Shake : 10,
Fade : 11,
VGUIMenu : 12,
Rumble : 13,
CloseCaption : 14,
SendAudio : 15,
VoiceMask : 16,
RequestState : 17,
Damage : 18,
HintText : 19,
KeyHintText : 20,
HudMsg : 21,
AmmoDenied : 22,
AchievementEvent : 23,
UpdateRadar : 24,
VoiceSubtitle : 25,
HudNotify : 26,
HudNotifyCustom : 27,
PlayerStatsUpdate : 28,
PlayerIgnited : 29,
PlayerIgnitedInv : 30,
HudArenaNotify : 31,
UpdateAchievement : 32,
TrainingMsg : 33,
TrainingObjective : 34,
DamageDodged : 35,
PlayerJarated : 36,
PlayerExtinguished : 37,
PlayerJaratedFade : 38,
PlayerShieldBlocked: 39,
BreakModel : 40,
CheapBreakModel : 41,
BreakModel_Pumpkin : 42,
BreakModelRocketDud: 43,
CallVoteFailed : 44,
VoteStart : 45,
VotePass : 46,
VoteFailed : 47,
VoteSetup : 48,
PlayerBonusPoints : 49,
SpawnFlyingBird : 50,
PlayerGodRayEffect : 51,
SPHapWeapEvent : 52,
HapDmg : 53,
HapPunch : 54,
HapSetDrag : 55,
HapSet : 56,
HapMeleeContact : 57
};
module.exports = Packet; module.exports = Packet;