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:
parent
346421fd9a
commit
171b5c4049
6 changed files with 86 additions and 45 deletions
|
|
@ -85,8 +85,12 @@ export class Match {
|
|||
this.calculateUserInfo();
|
||||
}
|
||||
break;
|
||||
case 'sayText2':
|
||||
handleSayText2(packet, this);
|
||||
case 'userMessage':
|
||||
switch (packet.userMessageType) {
|
||||
case 'sayText2':
|
||||
handleSayText2(packet, this);
|
||||
break;
|
||||
}
|
||||
break;
|
||||
case 'gameEvent':
|
||||
handleGameEvent(packet, this);
|
||||
|
|
|
|||
|
|
@ -18,11 +18,11 @@ export enum MessageType {
|
|||
}
|
||||
|
||||
export interface BaseMessage {
|
||||
tick: number;
|
||||
rawData: BitStream;
|
||||
}
|
||||
|
||||
export interface PacketMessage extends BaseMessage {
|
||||
tick: number;
|
||||
type: MessageType.Packet;
|
||||
packets: Packet[];
|
||||
viewOrigin: [Vector, Vector];
|
||||
|
|
@ -36,30 +36,35 @@ export interface PacketMessage extends BaseMessage {
|
|||
export type SigonMessage = PacketMessage;
|
||||
|
||||
export interface SyncTickMessage extends BaseMessage {
|
||||
tick: number;
|
||||
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 {
|
||||
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 {
|
||||
tick: number;
|
||||
type: MessageType.StringTables;
|
||||
tables: StringTable[];
|
||||
}
|
||||
|
|
|
|||
|
|
@ -66,7 +66,8 @@ export interface BaseDataUserPacket {
|
|||
}
|
||||
|
||||
export interface SayText2Packet {
|
||||
packetType: 'sayText2';
|
||||
packetType: 'userMessage',
|
||||
userMessageType: 'sayText2';
|
||||
client: number;
|
||||
raw: number;
|
||||
kind: 'TF_Chat_All' | 'TF_Chat_Team' | 'TF_Chat_AllDead';
|
||||
|
|
@ -82,28 +83,33 @@ export enum HudTextLocation {
|
|||
}
|
||||
|
||||
export interface TextMessagePacket {
|
||||
packetType: 'textMsg';
|
||||
packetType: 'userMessage',
|
||||
userMessageType: 'textMsg';
|
||||
destType: HudTextLocation;
|
||||
text: string;
|
||||
}
|
||||
|
||||
export interface ResetHUDPacket extends BaseDataUserPacket {
|
||||
packetType: 'resetHUD';
|
||||
packetType: 'userMessage',
|
||||
userMessageType: 'resetHUD';
|
||||
}
|
||||
|
||||
export interface TrainPacket extends BaseDataUserPacket {
|
||||
packetType: 'train';
|
||||
packetType: 'userMessage',
|
||||
userMessageType: 'train';
|
||||
}
|
||||
|
||||
export interface VoiceSubtitlePacket {
|
||||
packetType: 'voiceSubtitle';
|
||||
packetType: 'userMessage',
|
||||
userMessageType: 'voiceSubtitle';
|
||||
client: number;
|
||||
menu: number;
|
||||
item: number;
|
||||
}
|
||||
|
||||
export interface ShakePacket {
|
||||
packetType: 'shake';
|
||||
packetType: 'userMessage',
|
||||
userMessageType: 'shake';
|
||||
command: number;
|
||||
amplitude: number;
|
||||
frequency: number;
|
||||
|
|
@ -116,11 +122,13 @@ export interface UnknownUserMessageBasePacket {
|
|||
}
|
||||
|
||||
export interface BreakModelPumpkinPacket extends UnknownUserMessageBasePacket {
|
||||
packetType: 'breakModelPumpkin';
|
||||
packetType: 'userMessage',
|
||||
userMessageType: 'breakModelPumpkin';
|
||||
}
|
||||
|
||||
export interface GenericUnknownUserMessagePacket extends UnknownUserMessageBasePacket {
|
||||
packetType: 'unknownUserMessage';
|
||||
packetType: 'userMessage',
|
||||
userMessageType: 'unknownUserMessage';
|
||||
}
|
||||
|
||||
export type UnknownUserMessagePacket = GenericUnknownUserMessagePacket |
|
||||
|
|
@ -135,6 +143,8 @@ export type UserMessagePacket = SayText2Packet
|
|||
| BreakModelPumpkinPacket
|
||||
| ShakePacket;
|
||||
|
||||
export type UserMessagePacketType = UserMessagePacket['userMessageType'];
|
||||
|
||||
export interface UserMessageTypeMap {
|
||||
sayText2: SayText2Packet;
|
||||
textMsg: TextMessagePacket;
|
||||
|
|
@ -146,13 +156,14 @@ export interface UserMessageTypeMap {
|
|||
shake: ShakePacket;
|
||||
}
|
||||
|
||||
export const UserMessagePacketTypeMap: Map<UserMessagePacket['packetType'], UserMessageType> =
|
||||
new Map<UserMessagePacket['packetType'], UserMessageType>([
|
||||
export const UserMessagePacketTypeMap: Map<UserMessagePacketType, UserMessageType> =
|
||||
new Map<UserMessagePacketType, UserMessageType>([
|
||||
['sayText2', UserMessageType.SayText2],
|
||||
['textMsg', UserMessageType.TextMsg],
|
||||
['train', UserMessageType.Train],
|
||||
['voiceSubtitle', UserMessageType.VoiceSubtitle],
|
||||
['breakModelPumpkin', UserMessageType.BreakModel_Pumpkin],
|
||||
['resetHUD', UserMessageType.ResetHUD],
|
||||
['shake', UserMessageType.Shake]
|
||||
['shake', UserMessageType.Shake],
|
||||
['unknownUserMessage', -1]
|
||||
]);
|
||||
|
|
|
|||
|
|
@ -1,16 +1,20 @@
|
|||
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 {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 items = parts.map((part) => {
|
||||
return part.split('{');
|
||||
}).filter((part) => part[0]);
|
||||
const parser: Parser<PacketMapType[T]> = (stream: BitStream) => {
|
||||
const result = {
|
||||
packetType: name
|
||||
};
|
||||
const result = Object.assign({}, extraData);
|
||||
result[nameKey] = name;
|
||||
try {
|
||||
for (const group of items) {
|
||||
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]]);
|
||||
}
|
||||
};
|
||||
return {parser, encoder};
|
||||
return {parser, encoder, name};
|
||||
}
|
||||
|
||||
function readItem(stream: BitStream, description: string, data) {
|
||||
|
|
|
|||
|
|
@ -2,21 +2,21 @@ import {BitStream} from 'bit-buffer';
|
|||
import {
|
||||
UnknownUserMessageBasePacket,
|
||||
UnknownUserMessagePacket,
|
||||
UserMessagePacket,
|
||||
UserMessagePacket, UserMessagePacketType,
|
||||
UserMessagePacketTypeMap,
|
||||
UserMessageType,
|
||||
UserMessageTypeMap
|
||||
} from '../../Data/UserMessage';
|
||||
import {EncodeSayText2, ParseSayText2} from '../UserMessage/SayText2';
|
||||
import {PacketHandler} from './Parser';
|
||||
import {make} from './ParserGenerator';
|
||||
import {make, NamedPacketHandler} 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 {
|
||||
parser: (data: BitStream) => {
|
||||
return {
|
||||
packetType,
|
||||
type: UserMessagePacketTypeMap.get(packetType),
|
||||
packetType: 'userMessage',
|
||||
userMessageType,
|
||||
type: UserMessagePacketTypeMap.get(userMessageType),
|
||||
data
|
||||
} as UserMessageTypeMap[T];
|
||||
},
|
||||
|
|
@ -24,23 +24,38 @@ function unknownPacketHandler<T extends UnknownUserMessagePacket['packetType']>(
|
|||
packet.data.index = 0;
|
||||
data.writeBitStream(packet.data);
|
||||
packet.data.index = 0;
|
||||
}
|
||||
},
|
||||
name: userMessageType
|
||||
};
|
||||
}
|
||||
|
||||
const userMessageParsers: Map<UserMessageType, PacketHandler<UserMessagePacket>> =
|
||||
new Map<UserMessageType, PacketHandler<UserMessagePacket>>([
|
||||
[UserMessageType.SayText2, {parser: ParseSayText2, encoder: EncodeSayText2}],
|
||||
[UserMessageType.TextMsg, make('textMsg', 'destType{8}text{s}substitute1{s}substitute2{s}substitute3{s}substitute4{s}')],
|
||||
[UserMessageType.ResetHUD, make('resetHUD', 'data{8}')],
|
||||
[UserMessageType.Train, make('train', 'data{8}')],
|
||||
[UserMessageType.VoiceSubtitle, make('voiceSubtitle', 'client{8}menu{8}item{8}')],
|
||||
const userMessageParsers: Map<UserMessageType, NamedPacketHandler<UserMessagePacket, UserMessagePacketType>> =
|
||||
new Map<UserMessageType, NamedPacketHandler<UserMessagePacket, UserMessagePacketType>>([
|
||||
[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', {
|
||||
packetType: 'userMessage'
|
||||
})],
|
||||
[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.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
|
||||
const s = stream.index;
|
||||
const type = stream.readUint8();
|
||||
const length = stream.readBits(11);
|
||||
const messageData = stream.readBitStream(length);
|
||||
|
|
@ -49,7 +64,8 @@ export function ParseUserMessage(stream: BitStream): UserMessagePacket { // 23:
|
|||
|
||||
if (!handler) {
|
||||
return {
|
||||
packetType: 'unknownUserMessage',
|
||||
packetType: 'userMessage',
|
||||
userMessageType: 'unknownUserMessage',
|
||||
type,
|
||||
data: messageData
|
||||
};
|
||||
|
|
@ -59,14 +75,14 @@ export function ParseUserMessage(stream: BitStream): UserMessagePacket { // 23:
|
|||
}
|
||||
|
||||
export function EncodeUserMessage(packet: UserMessagePacket, stream: BitStream) {
|
||||
if (packet.packetType === 'unknownUserMessage') {
|
||||
if (packet.userMessageType === 'unknownUserMessage') {
|
||||
stream.writeUint8(packet.type);
|
||||
stream.writeBits(packet.data.length, 11);
|
||||
packet.data.index = 0;
|
||||
stream.writeBitStream(packet.data);
|
||||
packet.data.index = 0;
|
||||
} else {
|
||||
const messageType = UserMessagePacketTypeMap.get(packet.packetType);
|
||||
const messageType = UserMessagePacketTypeMap.get(packet.userMessageType);
|
||||
if (!messageType) {
|
||||
throw new Error(`Unknown userMessage type ${messageType}`);
|
||||
}
|
||||
|
|
@ -78,7 +94,7 @@ export function EncodeUserMessage(packet: UserMessagePacket, stream: BitStream)
|
|||
|
||||
const handler = userMessageParsers.get(messageType);
|
||||
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);
|
||||
|
|
|
|||
|
|
@ -44,7 +44,8 @@ export function ParseSayText2(stream: BitStream): SayText2Packet { // 4: ParseSa
|
|||
}
|
||||
|
||||
return {
|
||||
packetType: 'sayText2',
|
||||
packetType: 'userMessage',
|
||||
userMessageType: 'sayText2',
|
||||
client,
|
||||
raw,
|
||||
kind,
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue