mirror of
https://github.com/demostf/demo.js
synced 2026-06-04 09:04:13 +02:00
more usermessages and stricter parser generator
This commit is contained in:
parent
cd5d0b0e86
commit
b744efe0a4
7 changed files with 206 additions and 107 deletions
|
|
@ -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
141
src/Data/UserMessage.ts
Normal 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]
|
||||||
|
]);
|
||||||
|
|
@ -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({
|
||||||
|
|
|
||||||
|
|
@ -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,
|
||||||
|
|
|
||||||
|
|
@ -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]]);
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -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);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -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();
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue