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

more usermessages and stricter parser generator

This commit is contained in:
Robin Appelman 2017-09-03 15:40:07 +02:00
commit b744efe0a4
7 changed files with 206 additions and 107 deletions

View file

@ -6,6 +6,11 @@ import {ServerClass} from './ServerClass';
import {StringTable, StringTableEntry} from './StringTable'; import {StringTable, StringTableEntry} from './StringTable';
import {Vector} from './Vector'; import {Vector} from './Vector';
import {GameEvent, GameEventType} from './GameEventTypes'; import {GameEvent, GameEventType} from './GameEventTypes';
import {
BreakModelPumpkinPacket, ResetHUDPacket, TextMessagePacket, TrainPacket, UnknownUserMessagePacket,
UserMessagePacket, UserMessageType,
UserMessageTypeMap, VoiceSubtitlePacket, SayText2Packet
} from './UserMessage';
export interface BasePacket { export interface BasePacket {
} }
@ -105,27 +110,6 @@ export interface TempEntitiesPacket extends BasePacket {
entities: PacketEntity[]; entities: PacketEntity[];
} }
export interface SayText2Packet extends BasePacket {
packetType: 'sayText2';
client: number;
raw: number;
kind: 'TF_Chat_All' | 'TF_Chat_Team' | 'TF_Chat_AllDead';
from: string;
text: string;
}
export interface TextMessagePacket extends BasePacket {
packetType: 'textMsg';
destType: number;
text: string;
}
export interface UnknownUserMessagePacket extends BasePacket {
packetType: 'unknownUserMessage';
type: number;
data: BitStream;
}
export interface VoiceInitPacket extends BasePacket { export interface VoiceInitPacket extends BasePacket {
packetType: 'voiceInit'; packetType: 'voiceInit';
codec: string; codec: string;
@ -225,19 +209,17 @@ export interface FixAnglePacket extends BasePacket {
z: number; z: number;
} }
export interface PreFetchPacket { export interface PreFetchPacket extends BasePacket {
packetType: 'preFetch'; packetType: 'preFetch';
index: number; index: number;
} }
export interface GetCvarValuePacket { export interface GetCvarValuePacket extends BasePacket {
packetType: 'getCvarValue'; packetType: 'getCvarValue';
cookie: number; cookie: number;
value: string; value: string;
} }
export type UserMessagePacket = SayText2Packet | TextMessagePacket | UnknownUserMessagePacket;
export type Packet = BSPDecalPacket | export type Packet = BSPDecalPacket |
StringTablePacket | StringTablePacket |
CreateStringTablePacket | CreateStringTablePacket |
@ -273,7 +255,7 @@ export type Packet = BSPDecalPacket |
export type PacketType = Packet['packetType']; export type PacketType = Packet['packetType'];
export type PacketMapType = { export type PacketMapType = {
bSPDecal: BSPDecalPacket; bspDecal: BSPDecalPacket;
stringTable: StringTablePacket; stringTable: StringTablePacket;
createStringTable: CreateStringTablePacket; createStringTable: CreateStringTablePacket;
updateStringTable: UpdateStringTablePacket; updateStringTable: UpdateStringTablePacket;
@ -304,7 +286,7 @@ export type PacketMapType = {
fixAngle: FixAnglePacket; fixAngle: FixAnglePacket;
preFetch: PreFetchPacket; preFetch: PreFetchPacket;
getCvarValue: GetCvarValuePacket; getCvarValue: GetCvarValuePacket;
} } & UserMessageTypeMap;
export enum PacketTypeId { export enum PacketTypeId {
file = 2, file = 2,

141
src/Data/UserMessage.ts Normal file
View file

@ -0,0 +1,141 @@
import {BasePacket} from './Packet';
import {BitStream} from 'bit-buffer';
export enum 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,
}
export interface BaseDataUserPacket {
data: number;
}
export interface SayText2Packet extends BasePacket {
packetType: 'sayText2';
client: number;
raw: number;
kind: 'TF_Chat_All' | 'TF_Chat_Team' | 'TF_Chat_AllDead';
from: string;
text: string;
}
export interface TextMessagePacket extends BasePacket {
packetType: 'textMsg';
destType: number;
text: string;
}
export interface ResetHUDPacket extends BaseDataUserPacket {
packetType: 'resetHUD';
}
export interface TrainPacket extends BaseDataUserPacket {
packetType: 'train';
}
export interface VoiceSubtitlePacket extends BasePacket {
packetType: 'voiceSubtitle';
client: number;
menu: number;
item: number;
}
export interface UnknownUserMessageBasePacket extends BasePacket {
data: BitStream;
type: number;
}
export interface BreakModelPumpkinPacket extends UnknownUserMessageBasePacket {
packetType: 'breakModelPumpkin';
}
export interface GenericUnknownUserMessagePacket extends UnknownUserMessageBasePacket {
packetType: 'unknownUserMessage';
}
export type UnknownUserMessagePacket = GenericUnknownUserMessagePacket |
BreakModelPumpkinPacket;
export type UserMessagePacket = SayText2Packet
| TextMessagePacket
| ResetHUDPacket
| UnknownUserMessagePacket
| TrainPacket
| VoiceSubtitlePacket
| BreakModelPumpkinPacket;
export type UserMessageTypeMap = {
sayText2: SayText2Packet;
textMsg: TextMessagePacket;
unknownUserMessage: GenericUnknownUserMessagePacket;
train: TrainPacket;
voiceSubtitle: VoiceSubtitlePacket;
breakModelPumpkin: BreakModelPumpkinPacket;
resetHUD: ResetHUDPacket;
}
export const UserMessagePacketTypeMap: Map<UserMessagePacket['packetType'], UserMessageType> = new Map<UserMessagePacket['packetType'], UserMessageType>([
['unknownUserMessage', 0],
['sayText2', UserMessageType.SayText2],
['textMsg', UserMessageType.TextMsg],
['train', UserMessageType.Train],
['voiceSubtitle', UserMessageType.VoiceSubtitle],
['breakModelPumpkin', UserMessageType.BreakModel_Pumpkin],
['resetHUD', UserMessageType.ResetHUD]
]);

View file

@ -1,5 +1,5 @@
import {Match} from '../Data/Match'; import {Match} from '../Data/Match';
import {SayText2Packet} from '../Data/Packet'; import {SayText2Packet} from '../Data/UserMessage';
export function handleSayText2(packet: SayText2Packet, match: Match) { export function handleSayText2(packet: SayText2Packet, match: Match) {
match.chat.push({ match.chat.push({

View file

@ -18,7 +18,7 @@ import {Parser} from './Parser';
import {Packet as IPacket, PacketTypeId} from '../../Data/Packet'; import {Packet as IPacket, PacketTypeId} from '../../Data/Packet';
export class Packet extends Parser { export class Packet extends Parser {
private static parsers: Map<PacketTypeId, PacketHandler<IPacket>> = new Map([ private static parsers: Map<PacketTypeId, PacketHandler<IPacket>> = new Map<PacketTypeId, PacketHandler<IPacket>>([
[PacketTypeId.file, [PacketTypeId.file,
make('file', 'transferId{32}fileName{s}requested{b}')], make('file', 'transferId{32}fileName{s}requested{b}')],
[PacketTypeId.netTick, [PacketTypeId.netTick,

View file

@ -1,13 +1,13 @@
import {Packet, PacketType} from '../../Data/Packet'; import {Packet, PacketMapType, PacketType} from '../../Data/Packet';
import {Encoder, PacketHandler, Parser} from './Parser'; import {Encoder, PacketHandler, Parser} from './Parser';
import {BitStream} from 'bit-buffer'; import {BitStream} from 'bit-buffer';
export function make<P extends Packet>(name: PacketType, definition: string): PacketHandler<P> { export function make<T extends PacketType>(name: T, definition: string): PacketHandler<PacketMapType[T]> {
const parts = definition.split('}'); const parts = definition.split('}');
const items = parts.map((part) => { const items = parts.map((part) => {
return part.split('{'); return part.split('{');
}).filter(part => part[0]); }).filter(part => part[0]);
const parser: Parser<P> = (stream: BitStream) => { const parser: Parser<PacketMapType[T]> = (stream: BitStream) => {
const result = { const result = {
packetType: name, packetType: name,
}; };
@ -21,9 +21,9 @@ export function make<P extends Packet>(name: PacketType, definition: string): Pa
} catch (e) { } catch (e) {
throw new Error('Failed reading pattern ' + definition + '. ' + e); throw new Error('Failed reading pattern ' + definition + '. ' + e);
} }
return result as P; return result as PacketMapType[T];
}; };
const encoder: Encoder<P> = (packet: P, stream: BitStream) => { const encoder: Encoder<PacketMapType[T]> = (packet: PacketMapType[T], stream: BitStream) => {
for (const group of items) { for (const group of items) {
writeItem(stream, group[1], packet, packet[group[0]]); writeItem(stream, group[1], packet, packet[group[0]]);
} }

View file

@ -1,83 +1,59 @@
import {BitStream} from 'bit-buffer'; import {BitStream} from 'bit-buffer';
import {UserMessagePacket} from '../../Data/Packet'; import {EncodeSayText2, ParseSayText2} from '../UserMessage/SayText2';
import {ParseSayText2} from '../UserMessage/SayText2';
import {make} from './ParserGenerator'; import {make} from './ParserGenerator';
import {voidEncoder} from './Parser'; import {PacketHandler} from './Parser';
import {
UserMessageType,
UserMessagePacket,
UnknownUserMessagePacket,
UnknownUserMessageBasePacket,
UserMessageTypeMap,
UserMessagePacketTypeMap
} from '../../Data/UserMessage';
enum UserMessageType { function unknownPacketHandler<T extends UnknownUserMessagePacket['packetType']>(packetType: T): PacketHandler<UserMessageTypeMap[T]> {
Geiger = 0, return {
Train = 1, parser: (data: BitStream) => {
HudText = 2, return {
SayText = 3, packetType,
SayText2 = 4, type: UserMessagePacketTypeMap.get(packetType),
TextMsg = 5, data
ResetHUD = 6, } as UserMessageTypeMap[T];
GameTitle = 7, },
ItemPickup = 8, encoder: (packet: UnknownUserMessageBasePacket, data: BitStream) => {
ShowMenu = 9, packet.data.index = 0;
Shake = 10, data.writeUint8(packet.type);
Fade = 11, data.writeBits(packet.data.length, 11);
VGUIMenu = 12, data.writeBitStream(packet.data);
Rumble = 13, packet.data.index = 0;
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,
} }
const userMessageParsers = { const userMessageParsers: Map<UserMessageType, PacketHandler<UserMessagePacket>> = new Map<UserMessageType, PacketHandler<UserMessagePacket>>([
4: {parser: ParseSayText2, voidEncoder}, [UserMessageType.SayText2, {parser: ParseSayText2, encoder: EncodeSayText2}],
5: make('textMsg', 'destType{8}text{s}'), [UserMessageType.TextMsg, make('textMsg', 'destType{8}text{s}')],
}; [UserMessageType.ResetHUD, make('resetHUD', 'data{8}')],
[UserMessageType.Train, make('train', 'data{8}')],
[UserMessageType.VoiceSubtitle, make('voiceSubtitle', 'client{8}menu{8}item{8}')],
[UserMessageType.BreakModel_Pumpkin, unknownPacketHandler('breakModelPumpkin')]
]);
export function ParseUserMessage(stream: BitStream): UserMessagePacket { // 23: user message export function ParseUserMessage(stream: BitStream): UserMessagePacket { // 23: user message
const type = stream.readBits(8); const type = stream.readUint8();
const length = stream.readBits(11); const length = stream.readBits(11);
const messageData = stream.readBitStream(length); const messageData = stream.readBitStream(length);
return userMessageParsers[type] ? userMessageParsers[type].parser(messageData) : { const handler = userMessageParsers.get(type);
packetType: 'unknownUserMessage',
type, if (!handler) {
data: messageData, // throw new Error(`packet ${UserMessageType[type]} length:${length} data: ${messageData.readASCIIString()}`);
}; return {
packetType: 'unknownUserMessage',
type,
data: messageData,
};
} else {
return handler.parser(messageData);
}
} }

View file

@ -1,5 +1,5 @@
import {BitStream} from 'bit-buffer'; import {BitStream} from 'bit-buffer';
import {SayText2Packet} from '../../Data/Packet'; import {SayText2Packet} from '../../Data/UserMessage';
export function ParseSayText2(stream: BitStream): SayText2Packet { // 4: ParseSayText2 export function ParseSayText2(stream: BitStream): SayText2Packet { // 4: ParseSayText2
const client = stream.readUint8(); const client = stream.readUint8();