mirror of
https://github.com/demostf/demo.js
synced 2026-06-04 00:54:14 +02:00
add encoder for usermessage
This commit is contained in:
parent
430cf9ee4f
commit
55abaaff7a
5 changed files with 109 additions and 12 deletions
|
|
@ -62,7 +62,7 @@ export enum UserMessageType {
|
||||||
HapMeleeContact = 57,
|
HapMeleeContact = 57,
|
||||||
}
|
}
|
||||||
|
|
||||||
export interface BaseDataUserPacket {
|
export interface BaseDataUserPacket extends BasePacket {
|
||||||
data: number;
|
data: number;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -75,9 +75,16 @@ export interface SayText2Packet extends BasePacket {
|
||||||
text: string;
|
text: string;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export enum HudTextLocation {
|
||||||
|
HUD_PRINTNOTIFY = 1,
|
||||||
|
HUD_PRINTCONSOLE = 2,
|
||||||
|
HUD_PRINTTALK = 3,
|
||||||
|
HUD_PRINTCENTER = 4
|
||||||
|
}
|
||||||
|
|
||||||
export interface TextMessagePacket extends BasePacket {
|
export interface TextMessagePacket extends BasePacket {
|
||||||
packetType: 'textMsg';
|
packetType: 'textMsg';
|
||||||
destType: number;
|
destType: HudTextLocation;
|
||||||
text: string;
|
text: string;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -137,14 +144,15 @@ export type UserMessageTypeMap = {
|
||||||
voiceSubtitle: VoiceSubtitlePacket;
|
voiceSubtitle: VoiceSubtitlePacket;
|
||||||
breakModelPumpkin: BreakModelPumpkinPacket;
|
breakModelPumpkin: BreakModelPumpkinPacket;
|
||||||
resetHUD: ResetHUDPacket;
|
resetHUD: ResetHUDPacket;
|
||||||
|
shake: ShakePacket;
|
||||||
}
|
}
|
||||||
|
|
||||||
export const UserMessagePacketTypeMap: Map<UserMessagePacket['packetType'], UserMessageType> = new Map<UserMessagePacket['packetType'], UserMessageType>([
|
export const UserMessagePacketTypeMap: Map<UserMessagePacket['packetType'], UserMessageType> = new Map<UserMessagePacket['packetType'], UserMessageType>([
|
||||||
['unknownUserMessage', 0],
|
|
||||||
['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]
|
||||||
]);
|
]);
|
||||||
|
|
|
||||||
|
|
@ -10,15 +10,17 @@ import {EncodeParseSounds, ParseParseSounds} from '../Packet/ParseSounds';
|
||||||
import {EncodeSetConVar, ParseSetConVar} from '../Packet/SetConVar';
|
import {EncodeSetConVar, ParseSetConVar} from '../Packet/SetConVar';
|
||||||
import {ParseTempEntities} from '../Packet/TempEntities';
|
import {ParseTempEntities} from '../Packet/TempEntities';
|
||||||
import {EncodeUpdateStringTable, ParseUpdateStringTable} from '../Packet/UpdateStringTable';
|
import {EncodeUpdateStringTable, ParseUpdateStringTable} from '../Packet/UpdateStringTable';
|
||||||
import {ParseUserMessage} from '../Packet/UserMessage';
|
import {EncodeUserMessage, ParseUserMessage} from '../Packet/UserMessage';
|
||||||
import {EncodeVoiceData, ParseVoiceData} from '../Packet/VoiceData';
|
import {EncodeVoiceData, ParseVoiceData} from '../Packet/VoiceData';
|
||||||
import {EncodeVoiceInit, ParseVoiceInit} from '../Packet/VoiceInit';
|
import {EncodeVoiceInit, ParseVoiceInit} from '../Packet/VoiceInit';
|
||||||
import {Parser} from './Parser';
|
import {Parser} from './Parser';
|
||||||
|
|
||||||
import {Packet as IPacket, PacketTypeId} from '../../Data/Packet';
|
import {Packet as IPacket, PacketTypeId} from '../../Data/Packet';
|
||||||
|
|
||||||
|
type PacketHandlerMap = Map<PacketTypeId, PacketHandler<IPacket>>;
|
||||||
|
|
||||||
export class Packet extends Parser {
|
export class Packet extends Parser {
|
||||||
private static parsers: Map<PacketTypeId, PacketHandler<IPacket>> = new Map<PacketTypeId, PacketHandler<IPacket>>([
|
private static handlers: PacketHandlerMap = 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,
|
||||||
|
|
@ -57,7 +59,7 @@ export class Packet extends Parser {
|
||||||
[PacketTypeId.bspDecal,
|
[PacketTypeId.bspDecal,
|
||||||
{parser: ParseBSPDecal, encoder: EncodeBSPDecal}],
|
{parser: ParseBSPDecal, encoder: EncodeBSPDecal}],
|
||||||
[PacketTypeId.userMessage,
|
[PacketTypeId.userMessage,
|
||||||
{parser: ParseUserMessage, encoder: voidEncoder}],
|
{parser: ParseUserMessage, encoder: EncodeUserMessage}],
|
||||||
[PacketTypeId.entityMessage,
|
[PacketTypeId.entityMessage,
|
||||||
make('entityMessage', 'index{11}classId{9}length{11}data{$length}')],
|
make('entityMessage', 'index{11}classId{9}length{11}data{$length}')],
|
||||||
[PacketTypeId.gameEvent,
|
[PacketTypeId.gameEvent,
|
||||||
|
|
@ -84,7 +86,7 @@ export class Packet extends Parser {
|
||||||
while (this.bitsLeft > 6) { // last 6 bits for NOOP
|
while (this.bitsLeft > 6) { // last 6 bits for NOOP
|
||||||
const type = this.stream.readBits(6) as PacketTypeId;
|
const type = this.stream.readBits(6) as PacketTypeId;
|
||||||
if (type !== 0) {
|
if (type !== 0) {
|
||||||
const parser = Packet.parsers.get(type);
|
const parser = Packet.handlers.get(type);
|
||||||
if (parser) {
|
if (parser) {
|
||||||
const skip = this.skippedPackets.indexOf(type) !== -1;
|
const skip = this.skippedPackets.indexOf(type) !== -1;
|
||||||
const packet = parser.parser(this.stream, this.match, skip);
|
const packet = parser.parser(this.stream, this.match, skip);
|
||||||
|
|
|
||||||
|
|
@ -1,4 +1,4 @@
|
||||||
import {Packet, PacketMapType, PacketType} from '../../Data/Packet';
|
import {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';
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -22,8 +22,6 @@ function unknownPacketHandler<T extends UnknownUserMessagePacket['packetType']>(
|
||||||
},
|
},
|
||||||
encoder: (packet: UnknownUserMessageBasePacket, data: BitStream) => {
|
encoder: (packet: UnknownUserMessageBasePacket, data: BitStream) => {
|
||||||
packet.data.index = 0;
|
packet.data.index = 0;
|
||||||
data.writeUint8(packet.type);
|
|
||||||
data.writeBits(packet.data.length, 11);
|
|
||||||
data.writeBitStream(packet.data);
|
data.writeBitStream(packet.data);
|
||||||
packet.data.index = 0;
|
packet.data.index = 0;
|
||||||
}
|
}
|
||||||
|
|
@ -32,7 +30,7 @@ function unknownPacketHandler<T extends UnknownUserMessagePacket['packetType']>(
|
||||||
|
|
||||||
const userMessageParsers: Map<UserMessageType, PacketHandler<UserMessagePacket>> = new Map<UserMessageType, PacketHandler<UserMessagePacket>>([
|
const userMessageParsers: Map<UserMessageType, PacketHandler<UserMessagePacket>> = new Map<UserMessageType, PacketHandler<UserMessagePacket>>([
|
||||||
[UserMessageType.SayText2, {parser: ParseSayText2, encoder: EncodeSayText2}],
|
[UserMessageType.SayText2, {parser: ParseSayText2, encoder: EncodeSayText2}],
|
||||||
[UserMessageType.TextMsg, make('textMsg', 'destType{8}text{s}')],
|
[UserMessageType.TextMsg, make('textMsg', 'destType{8}text{s}substitute1{s}substitute2{s}substitute3{s}substitute4{s}')],
|
||||||
[UserMessageType.ResetHUD, make('resetHUD', 'data{8}')],
|
[UserMessageType.ResetHUD, make('resetHUD', 'data{8}')],
|
||||||
[UserMessageType.Train, make('train', 'data{8}')],
|
[UserMessageType.Train, make('train', 'data{8}')],
|
||||||
[UserMessageType.VoiceSubtitle, make('voiceSubtitle', 'client{8}menu{8}item{8}')],
|
[UserMessageType.VoiceSubtitle, make('voiceSubtitle', 'client{8}menu{8}item{8}')],
|
||||||
|
|
@ -41,6 +39,7 @@ const userMessageParsers: Map<UserMessageType, PacketHandler<UserMessagePacket>>
|
||||||
]);
|
]);
|
||||||
|
|
||||||
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);
|
||||||
|
|
@ -57,3 +56,37 @@ export function ParseUserMessage(stream: BitStream): UserMessagePacket { // 23:
|
||||||
return handler.parser(messageData);
|
return handler.parser(messageData);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export function EncodeUserMessage(packet: UserMessagePacket, stream: BitStream) {
|
||||||
|
if (packet.packetType === '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);
|
||||||
|
if (!messageType) {
|
||||||
|
throw new Error(`Unknown userMessage type ${messageType}`);
|
||||||
|
}
|
||||||
|
stream.writeUint8(messageType);
|
||||||
|
|
||||||
|
const lengthStart = stream.index;
|
||||||
|
stream.index += 11;
|
||||||
|
const messageDataStart = stream.index;
|
||||||
|
|
||||||
|
const handler = userMessageParsers.get(messageType);
|
||||||
|
if (!handler) {
|
||||||
|
throw new Error(`No encoder for userMessage ${packet.packetType}(${messageType})`);
|
||||||
|
}
|
||||||
|
|
||||||
|
handler.encoder(packet, stream);
|
||||||
|
|
||||||
|
const messageDataEnd = stream.index;
|
||||||
|
stream.index = lengthStart;
|
||||||
|
stream.writeBits(messageDataEnd - messageDataStart, 11);
|
||||||
|
|
||||||
|
stream.index = messageDataEnd;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
|
||||||
54
src/tests/unit/Parser/Packet/UserMessageTest.ts
Normal file
54
src/tests/unit/Parser/Packet/UserMessageTest.ts
Normal file
|
|
@ -0,0 +1,54 @@
|
||||||
|
import {BitStream} from 'bit-buffer';
|
||||||
|
import {assertEncoder, assertParser, getStream} from './PacketTest';
|
||||||
|
import {EncodeUserMessage, ParseUserMessage} from '../../../../Parser/Packet/UserMessage';
|
||||||
|
import {HudTextLocation} from '../../../../Data/UserMessage';
|
||||||
|
|
||||||
|
const data = [
|
||||||
|
5,
|
||||||
|
200,
|
||||||
|
8,
|
||||||
|
24,
|
||||||
|
57,
|
||||||
|
10,
|
||||||
|
107,
|
||||||
|
43,
|
||||||
|
251,
|
||||||
|
26,
|
||||||
|
123,
|
||||||
|
115,
|
||||||
|
115,
|
||||||
|
43,
|
||||||
|
27,
|
||||||
|
163,
|
||||||
|
43,
|
||||||
|
35,
|
||||||
|
3,
|
||||||
|
152,
|
||||||
|
43,
|
||||||
|
91,
|
||||||
|
147,
|
||||||
|
3,
|
||||||
|
0,
|
||||||
|
0,
|
||||||
|
0,
|
||||||
|
24];
|
||||||
|
|
||||||
|
const expected = {
|
||||||
|
packetType: 'textMsg',
|
||||||
|
destType: HudTextLocation.HUD_PRINTNOTIFY,
|
||||||
|
text: '#Game_connected',
|
||||||
|
substitute1: 'sekr',
|
||||||
|
substitute2: '',
|
||||||
|
substitute3: '',
|
||||||
|
substitute4: '',
|
||||||
|
};
|
||||||
|
|
||||||
|
suite('SayText2', () => {
|
||||||
|
test('Parse sayText2', () => {
|
||||||
|
assertParser(ParseUserMessage, getStream(data), expected, 219);
|
||||||
|
});
|
||||||
|
|
||||||
|
test('Encode sayText2', () => {
|
||||||
|
assertEncoder(ParseUserMessage, EncodeUserMessage, expected, 219);
|
||||||
|
});
|
||||||
|
});
|
||||||
Loading…
Add table
Add a link
Reference in a new issue