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

better handling of user messages

This commit is contained in:
Robin Appelman 2017-09-27 01:26:27 +02:00
commit 171b5c4049
6 changed files with 86 additions and 45 deletions

View file

@ -85,9 +85,13 @@ export class Match {
this.calculateUserInfo(); this.calculateUserInfo();
} }
break; break;
case 'userMessage':
switch (packet.userMessageType) {
case 'sayText2': case 'sayText2':
handleSayText2(packet, this); handleSayText2(packet, this);
break; break;
}
break;
case 'gameEvent': case 'gameEvent':
handleGameEvent(packet, this); handleGameEvent(packet, this);
break; break;

View file

@ -18,11 +18,11 @@ export enum MessageType {
} }
export interface BaseMessage { export interface BaseMessage {
tick: number;
rawData: BitStream; rawData: BitStream;
} }
export interface PacketMessage extends BaseMessage { export interface PacketMessage extends BaseMessage {
tick: number;
type: MessageType.Packet; type: MessageType.Packet;
packets: Packet[]; packets: Packet[];
viewOrigin: [Vector, Vector]; viewOrigin: [Vector, Vector];
@ -36,30 +36,35 @@ export interface PacketMessage extends BaseMessage {
export type SigonMessage = PacketMessage; export type SigonMessage = PacketMessage;
export interface SyncTickMessage extends BaseMessage { export interface SyncTickMessage extends BaseMessage {
tick: number;
type: MessageType.SyncTick; type: MessageType.SyncTick;
} }
export interface ConsoleCmdMessage extends BaseMessage {
type: MessageType.ConsoleCmd;
command: string;
}
export interface UserCmdMessage extends BaseMessage {
type: MessageType.UserCmd;
sequenceOut: number;
}
export interface DataTablesMessage extends BaseMessage {
type: MessageType.DataTables;
tables: SendTable[];
serverClasses: ServerClass[];
}
export interface StopMessage extends BaseMessage { export interface StopMessage extends BaseMessage {
type: MessageType.Stop; type: MessageType.Stop;
} }
export interface ConsoleCmdMessage extends BaseMessage {
tick: number;
type: MessageType.ConsoleCmd;
command: string;
}
export interface UserCmdMessage extends BaseMessage {
tick: number;
type: MessageType.UserCmd;
sequenceOut: number;
}
export interface DataTablesMessage extends BaseMessage {
tick: number;
type: MessageType.DataTables;
tables: SendTable[];
serverClasses: ServerClass[];
}
export interface StringTablesMessage extends BaseMessage { export interface StringTablesMessage extends BaseMessage {
tick: number;
type: MessageType.StringTables; type: MessageType.StringTables;
tables: StringTable[]; tables: StringTable[];
} }

View file

@ -66,7 +66,8 @@ export interface BaseDataUserPacket {
} }
export interface SayText2Packet { export interface SayText2Packet {
packetType: 'sayText2'; packetType: 'userMessage',
userMessageType: 'sayText2';
client: number; client: number;
raw: number; raw: number;
kind: 'TF_Chat_All' | 'TF_Chat_Team' | 'TF_Chat_AllDead'; kind: 'TF_Chat_All' | 'TF_Chat_Team' | 'TF_Chat_AllDead';
@ -82,28 +83,33 @@ export enum HudTextLocation {
} }
export interface TextMessagePacket { export interface TextMessagePacket {
packetType: 'textMsg'; packetType: 'userMessage',
userMessageType: 'textMsg';
destType: HudTextLocation; destType: HudTextLocation;
text: string; text: string;
} }
export interface ResetHUDPacket extends BaseDataUserPacket { export interface ResetHUDPacket extends BaseDataUserPacket {
packetType: 'resetHUD'; packetType: 'userMessage',
userMessageType: 'resetHUD';
} }
export interface TrainPacket extends BaseDataUserPacket { export interface TrainPacket extends BaseDataUserPacket {
packetType: 'train'; packetType: 'userMessage',
userMessageType: 'train';
} }
export interface VoiceSubtitlePacket { export interface VoiceSubtitlePacket {
packetType: 'voiceSubtitle'; packetType: 'userMessage',
userMessageType: 'voiceSubtitle';
client: number; client: number;
menu: number; menu: number;
item: number; item: number;
} }
export interface ShakePacket { export interface ShakePacket {
packetType: 'shake'; packetType: 'userMessage',
userMessageType: 'shake';
command: number; command: number;
amplitude: number; amplitude: number;
frequency: number; frequency: number;
@ -116,11 +122,13 @@ export interface UnknownUserMessageBasePacket {
} }
export interface BreakModelPumpkinPacket extends UnknownUserMessageBasePacket { export interface BreakModelPumpkinPacket extends UnknownUserMessageBasePacket {
packetType: 'breakModelPumpkin'; packetType: 'userMessage',
userMessageType: 'breakModelPumpkin';
} }
export interface GenericUnknownUserMessagePacket extends UnknownUserMessageBasePacket { export interface GenericUnknownUserMessagePacket extends UnknownUserMessageBasePacket {
packetType: 'unknownUserMessage'; packetType: 'userMessage',
userMessageType: 'unknownUserMessage';
} }
export type UnknownUserMessagePacket = GenericUnknownUserMessagePacket | export type UnknownUserMessagePacket = GenericUnknownUserMessagePacket |
@ -135,6 +143,8 @@ export type UserMessagePacket = SayText2Packet
| BreakModelPumpkinPacket | BreakModelPumpkinPacket
| ShakePacket; | ShakePacket;
export type UserMessagePacketType = UserMessagePacket['userMessageType'];
export interface UserMessageTypeMap { export interface UserMessageTypeMap {
sayText2: SayText2Packet; sayText2: SayText2Packet;
textMsg: TextMessagePacket; textMsg: TextMessagePacket;
@ -146,13 +156,14 @@ export interface UserMessageTypeMap {
shake: ShakePacket; shake: ShakePacket;
} }
export const UserMessagePacketTypeMap: Map<UserMessagePacket['packetType'], UserMessageType> = export const UserMessagePacketTypeMap: Map<UserMessagePacketType, UserMessageType> =
new Map<UserMessagePacket['packetType'], UserMessageType>([ new Map<UserMessagePacketType, UserMessageType>([
['sayText2', UserMessageType.SayText2], ['sayText2', UserMessageType.SayText2],
['textMsg', UserMessageType.TextMsg], ['textMsg', UserMessageType.TextMsg],
['train', UserMessageType.Train], ['train', UserMessageType.Train],
['voiceSubtitle', UserMessageType.VoiceSubtitle], ['voiceSubtitle', UserMessageType.VoiceSubtitle],
['breakModelPumpkin', UserMessageType.BreakModel_Pumpkin], ['breakModelPumpkin', UserMessageType.BreakModel_Pumpkin],
['resetHUD', UserMessageType.ResetHUD], ['resetHUD', UserMessageType.ResetHUD],
['shake', UserMessageType.Shake] ['shake', UserMessageType.Shake],
['unknownUserMessage', -1]
]); ]);

View file

@ -1,16 +1,20 @@
import {BitStream} from 'bit-buffer'; import {BitStream} from 'bit-buffer';
import {PacketMapType, PacketType} from '../../Data/Packet'; import {Packet, PacketMapType, PacketType} from '../../Data/Packet';
import {Encoder, PacketHandler, Parser} from './Parser'; import {Encoder, PacketHandler, Parser} from './Parser';
import {UserMessagePacketType} from '../../Data/UserMessage';
export function make<T extends PacketType>(name: T, definition: string): PacketHandler<PacketMapType[T]> { export interface NamedPacketHandler<P extends Packet, N extends PacketType | UserMessagePacketType> extends PacketHandler<P> {
name: N;
}
export function make<T extends PacketType | UserMessagePacketType>(name: T, definition: string, nameKey: string = 'packetType', extraData: any = {}): NamedPacketHandler<PacketMapType[T], 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<PacketMapType[T]> = (stream: BitStream) => { const parser: Parser<PacketMapType[T]> = (stream: BitStream) => {
const result = { const result = Object.assign({}, extraData);
packetType: name result[nameKey] = name;
};
try { try {
for (const group of items) { for (const group of items) {
const value = readItem(stream, group[1], result); const value = readItem(stream, group[1], result);
@ -28,7 +32,7 @@ export function make<T extends PacketType>(name: T, definition: string): PacketH
writeItem(stream, group[1], packet, packet[group[0]]); writeItem(stream, group[1], packet, packet[group[0]]);
} }
}; };
return {parser, encoder}; return {parser, encoder, name};
} }
function readItem(stream: BitStream, description: string, data) { function readItem(stream: BitStream, description: string, data) {

View file

@ -2,21 +2,21 @@ import {BitStream} from 'bit-buffer';
import { import {
UnknownUserMessageBasePacket, UnknownUserMessageBasePacket,
UnknownUserMessagePacket, UnknownUserMessagePacket,
UserMessagePacket, UserMessagePacket, UserMessagePacketType,
UserMessagePacketTypeMap, UserMessagePacketTypeMap,
UserMessageType, UserMessageType,
UserMessageTypeMap UserMessageTypeMap
} from '../../Data/UserMessage'; } from '../../Data/UserMessage';
import {EncodeSayText2, ParseSayText2} from '../UserMessage/SayText2'; import {EncodeSayText2, ParseSayText2} from '../UserMessage/SayText2';
import {PacketHandler} from './Parser'; import {make, NamedPacketHandler} from './ParserGenerator';
import {make} from './ParserGenerator';
function unknownPacketHandler<T extends UnknownUserMessagePacket['packetType']>(packetType: T): PacketHandler<UserMessageTypeMap[T]> { function unknownPacketHandler<T extends UnknownUserMessagePacket['userMessageType']>(userMessageType: T): NamedPacketHandler<UserMessageTypeMap[T], UserMessagePacketType> {
return { return {
parser: (data: BitStream) => { parser: (data: BitStream) => {
return { return {
packetType, packetType: 'userMessage',
type: UserMessagePacketTypeMap.get(packetType), userMessageType,
type: UserMessagePacketTypeMap.get(userMessageType),
data data
} as UserMessageTypeMap[T]; } as UserMessageTypeMap[T];
}, },
@ -24,23 +24,38 @@ function unknownPacketHandler<T extends UnknownUserMessagePacket['packetType']>(
packet.data.index = 0; packet.data.index = 0;
data.writeBitStream(packet.data); data.writeBitStream(packet.data);
packet.data.index = 0; packet.data.index = 0;
} },
name: userMessageType
}; };
} }
const userMessageParsers: Map<UserMessageType, PacketHandler<UserMessagePacket>> = const userMessageParsers: Map<UserMessageType, NamedPacketHandler<UserMessagePacket, UserMessagePacketType>> =
new Map<UserMessageType, PacketHandler<UserMessagePacket>>([ new Map<UserMessageType, NamedPacketHandler<UserMessagePacket, UserMessagePacketType>>([
[UserMessageType.SayText2, {parser: ParseSayText2, encoder: EncodeSayText2}], [UserMessageType.SayText2, {parser: ParseSayText2, encoder: EncodeSayText2, name: 'sayText2'}],
[UserMessageType.TextMsg, make('textMsg', 'destType{8}text{s}substitute1{s}substitute2{s}substitute3{s}substitute4{s}')], [UserMessageType.TextMsg,
[UserMessageType.ResetHUD, make('resetHUD', 'data{8}')], make('textMsg', 'destType{8}text{s}substitute1{s}substitute2{s}substitute3{s}substitute4{s}', 'userMessageType', {
[UserMessageType.Train, make('train', 'data{8}')], packetType: 'userMessage'
[UserMessageType.VoiceSubtitle, make('voiceSubtitle', 'client{8}menu{8}item{8}')], })],
[UserMessageType.ResetHUD,
make('resetHUD', 'data{8}', 'userMessageType', {
packetType: 'userMessage'
})],
[UserMessageType.Train,
make('train', 'data{8}', 'userMessageType', {
packetType: 'userMessage'
})],
[UserMessageType.VoiceSubtitle,
make('voiceSubtitle', 'client{8}menu{8}item{8}', 'userMessageType', {
packetType: 'userMessage'
})],
[UserMessageType.BreakModel_Pumpkin, unknownPacketHandler('breakModelPumpkin')], [UserMessageType.BreakModel_Pumpkin, unknownPacketHandler('breakModelPumpkin')],
[UserMessageType.Shake, make('shake', 'command{8}amplitude{f32}frequency{f32}duration{f32}')] [UserMessageType.Shake,
make('shake', 'command{8}amplitude{f32}frequency{f32}duration{f32}', 'userMessageType', {
packetType: 'userMessage'
})]
]); ]);
export function ParseUserMessage(stream: BitStream): UserMessagePacket { // 23: user message export function ParseUserMessage(stream: BitStream): UserMessagePacket { // 23: user message
const s = stream.index;
const type = stream.readUint8(); const type = stream.readUint8();
const length = stream.readBits(11); const length = stream.readBits(11);
const messageData = stream.readBitStream(length); const messageData = stream.readBitStream(length);
@ -49,7 +64,8 @@ export function ParseUserMessage(stream: BitStream): UserMessagePacket { // 23:
if (!handler) { if (!handler) {
return { return {
packetType: 'unknownUserMessage', packetType: 'userMessage',
userMessageType: 'unknownUserMessage',
type, type,
data: messageData data: messageData
}; };
@ -59,14 +75,14 @@ export function ParseUserMessage(stream: BitStream): UserMessagePacket { // 23:
} }
export function EncodeUserMessage(packet: UserMessagePacket, stream: BitStream) { export function EncodeUserMessage(packet: UserMessagePacket, stream: BitStream) {
if (packet.packetType === 'unknownUserMessage') { if (packet.userMessageType === 'unknownUserMessage') {
stream.writeUint8(packet.type); stream.writeUint8(packet.type);
stream.writeBits(packet.data.length, 11); stream.writeBits(packet.data.length, 11);
packet.data.index = 0; packet.data.index = 0;
stream.writeBitStream(packet.data); stream.writeBitStream(packet.data);
packet.data.index = 0; packet.data.index = 0;
} else { } else {
const messageType = UserMessagePacketTypeMap.get(packet.packetType); const messageType = UserMessagePacketTypeMap.get(packet.userMessageType);
if (!messageType) { if (!messageType) {
throw new Error(`Unknown userMessage type ${messageType}`); throw new Error(`Unknown userMessage type ${messageType}`);
} }
@ -78,7 +94,7 @@ export function EncodeUserMessage(packet: UserMessagePacket, stream: BitStream)
const handler = userMessageParsers.get(messageType); const handler = userMessageParsers.get(messageType);
if (!handler) { if (!handler) {
throw new Error(`No encoder for userMessage ${packet.packetType}(${messageType})`); throw new Error(`No encoder for userMessage ${packet.userMessageType}(${messageType})`);
} }
handler.encoder(packet, stream); handler.encoder(packet, stream);

View file

@ -44,7 +44,8 @@ export function ParseSayText2(stream: BitStream): SayText2Packet { // 4: ParseSa
} }
return { return {
packetType: 'sayText2', packetType: 'userMessage',
userMessageType: 'sayText2',
client, client,
raw, raw,
kind, kind,