Skip to content
Browse files

Initial version based on valve's stuff

  • Loading branch information...
0 parents commit 4ca45a87c631787eab140d313a3f21210b543741 @mitsuhiko committed Apr 27, 2012
Showing with 3,529 additions and 0 deletions.
  1. +4 −0 .gitignore
  2. +32 −0 Makefile
  3. +94 −0 README.txt
  4. +646 −0 ai_activity.proto
  5. +214 −0 demo.proto
  6. +213 −0 demofile.cpp
  7. +140 −0 demofile.h
  8. +494 −0 demofiledump.cpp
  9. +55 −0 demofiledump.h
  10. +44 −0 demoinfo2.cpp
  11. +86 −0 dota_commonmessages.proto
  12. +99 −0 dota_modifiers.proto
  13. +538 −0 dota_usermessages.proto
  14. +567 −0 netmessages.proto
  15. +303 −0 usermessages.proto
4 .gitignore
@@ -0,0 +1,4 @@
+*.dem
+*.o
+demoinfo2
+output.txt
32 Makefile
@@ -0,0 +1,32 @@
+EXECUTABLE=demoinfo2
+
+CPP_FILES=$(wildcard *.cpp)
+OBJ_FILES=$(CPP_FILES:.cpp=.o)
+PROTO_SRC_FILES=$(wildcard *.proto)
+PROTO_CPP_FILES=$(addprefix generated_proto/,$(PROTO_SRC_FILES:.proto=.pb.cc))
+PROTO_OBJ_FILES=$(PROTO_CPP_FILES:.cc=.o)
+
+LD_FLAGS=-lsnappy -lprotobuf -L/usr/local/lib
+CC_FLAGS=-I/usr/local/include
+PROTOBUF_FLAGS=-I/usr/local/include
+
+all: ${EXECUTABLE}
+
+clean:
+ rm -f ${EXECUTABLE}
+ rm -f *.o
+ rm -f generated_proto/*
+
+generated_proto/%.pb.cc: %.proto
+ protoc ${PROTO_SRC_FILES} ${PROTOBUF_FLAGS} -I. --cpp_out=generated_proto
+
+${EXECUTABLE}: ${PROTO_OBJ_FILES} ${OBJ_FILES}
+ g++ ${LD_FLAGS} -o $@ ${OBJ_FILES} ${PROTO_OBJ_FILES}
+
+.cpp.o: ${CPP_FILES}
+ g++ ${CC_FLAGS} -c -o $@ $<
+
+.cc.o: ${PROTO_CPP_FILES}
+ g++ ${CC_FLAGS} -c -o $@ $<
+
+.PHONY: all clean
94 README.txt
@@ -0,0 +1,94 @@
+Note Armin: This is the same thing as was released by Valve just that
+windows specific stuff was changed so that it compiles on OS X (and
+hopefully Linux).
+
+
+-------------------------------------------------------------------------
+
+Original Readme:
+
+Demoinfo2.exe is a tool that will parse Dota 2 demo files (ending in .dem)
+and dump out every message in the demo. Using this tool, third parties
+can parse the demo for various game events to generate information and
+statistics.
+
+You can use demoinfo2.exe by itself and parse the demo. We have also
+included the source code to the program itself to show how to parse and
+retrieve information directly.
+
+Dota 2's demo format is built around using Google's Protocol Buffers
+(protobuf). Protobuf is a message/object serialization language that
+generates code to serialize the objects efficiently. If you wish to
+understand more about protobuf, check out
+http://code.google.com/p/protobuf/
+
+In order to build demoinfo2 yourself, you will need Visual Studio 2010.
+You will also need to download Google's protobuf and snappy libraries.
+
+- Extract demoinfo2.zip and it will make a new folder named "demoinfo2".
+
+- Download protobuf from
+http://code.google.com/p/protobuf/downloads/detail?name=protobuf-2.4.1.zip
+Install this directly in the protobuf-2.4.1 directory that was created
+when you extracted demoinfo2.
+
+- Open protobuf-2.4.1\vsprojects\protobuf.sln into Visual Studio 2010.
+You will be asked to convert it, please do so. Once loaded, select
+Release version from the build target in the toolbar. Build the
+libprotobuf project by right clicking it in the solution list and hitting
+"build." You do not need to build the other protobuf projects.
+
+- Download protoc (the protobuf compiler) from
+http://code.google.com/p/protobuf/downloads/detail?name=protoc-2.4.1-win32.zip
+and extract this into the protoc-2.4.1-win32 folder that was created when
+you extracted demoinfo2. This is the protobuf compiler that parses .proto
+files and generates C++ code to parse the messages in the demo file.
+
+- The last library needed is Google's snappy compression library.
+Download it from
+http://code.google.com/p/snappy/downloads/detail?name=snappy-1.0.5.tar.gz
+and extract it into the snappy-1.0.5 folder.
+
+Once those libraries are installed, you can now open demoinfo2.sln and
+build your own demoinfo2.exe binary. Select the Release build target from
+the toolbar and hit build! You will have a new binary in
+demoinfo2\Release\demoinfo2.exe.
+
+To parse a demo, just download one in Dota 2. They will be in C:\Program
+Files (x86)\Steam\steamapps\common\dota 2 beta\dota\replays\*.dem. To
+dump a demo, just run "demoinfo2 xxx.dem" and it will print out all the
+messages in the demo.
+
+Google's protobuf can generate parses in Java and Python using the same
+.proto files. People proficient in those languages can use protoc.exe to
+generate code that parses the protobuf messages and parse the demo file in
+those languages.
+
+We are curious to see what people come up with using this tool and please
+do post questions and comments about it on the Replay section of the Dota
+ 2 Development Forums at http://dev.dota2.com/forumdisplay.php?f=19
+
+====== Copyright (c) 2012, Valve Corporation, All rights reserved. ========
+
+ Redistribution and use in source and binary forms, with or without
+ modification, are permitted provided that the following conditions are met:
+
+ Redistributions of source code must retain the above copyright notice, this
+ list of conditions and the following disclaimer.
+ Redistributions in binary form must reproduce the above copyright notice,
+ this list of conditions and the following disclaimer in the documentation
+ and/or other materials provided with the distribution.
+
+ THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
+ LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
+ THE POSSIBILITY OF SUCH DAMAGE.
+===========================================================================
+
646 ai_activity.proto
@@ -0,0 +1,646 @@
+//====== Copyright (c) 2012, Valve Corporation, All rights reserved. ========//
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are met:
+//
+// Redistributions of source code must retain the above copyright notice, this
+// list of conditions and the following disclaimer.
+// Redistributions in binary form must reproduce the above copyright notice,
+// this list of conditions and the following disclaimer in the documentation
+// and/or other materials provided with the distribution.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+// ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
+// LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+// CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+// SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+// INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+// ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
+// THE POSSIBILITY OF SUCH DAMAGE.
+//===========================================================================//
+
+// We care more about speed than code size
+option optimize_for = SPEED;
+
+// We don't use the service generation functionality
+option cc_generic_services = false;
+
+enum Activity
+{
+ ACT_INVALID = -1; // So we have something more succint to check for than '-1'
+ ACT_RESET = 0; // Set m_Activity to this invalid value to force a reset to m_IdealActivity
+ ACT_IDLE = 1;
+ ACT_TRANSITION = 2;
+ ACT_COVER = 3; // FIXME: obsolete? redundant with ACT_COVER_LOW?
+ ACT_COVER_MED = 4; // FIXME: unsupported?
+ ACT_COVER_LOW = 5; // FIXME: rename ACT_IDLE_CROUCH?
+ ACT_WALK = 6;
+ ACT_WALK_AIM = 7;
+ ACT_WALK_CROUCH = 8;
+ ACT_WALK_CROUCH_AIM = 9;
+ ACT_RUN = 10;
+ ACT_RUN_AIM = 11;
+ ACT_RUN_CROUCH = 12;
+ ACT_RUN_CROUCH_AIM = 13;
+ ACT_RUN_PROTECTED = 14;
+ ACT_SCRIPT_CUSTOM_MOVE = 15;
+ ACT_RANGE_ATTACK1 = 16;
+ ACT_RANGE_ATTACK2 = 17;
+ ACT_RANGE_ATTACK1_LOW = 18; // FIXME: not used yet crouched versions of the range attack
+ ACT_RANGE_ATTACK2_LOW = 19; // FIXME: not used yet crouched versions of the range attack
+ ACT_DIESIMPLE = 20;
+ ACT_DIEBACKWARD = 21;
+ ACT_DIEFORWARD = 22;
+ ACT_DIEVIOLENT = 23;
+ ACT_DIERAGDOLL = 24;
+ ACT_FLY = 25; // Fly (and flap if appropriate)
+ ACT_HOVER = 26;
+ ACT_GLIDE = 27;
+ ACT_SWIM = 28;
+ ACT_JUMP = 29;
+ ACT_HOP = 30; // vertical jump
+ ACT_LEAP = 31; // long forward jump
+ ACT_LAND = 32;
+ ACT_CLIMB_UP = 33;
+ ACT_CLIMB_DOWN = 34;
+ ACT_CLIMB_DISMOUNT = 35;
+ ACT_SHIPLADDER_UP = 36;
+ ACT_SHIPLADDER_DOWN = 37;
+ ACT_STRAFE_LEFT = 38;
+ ACT_STRAFE_RIGHT = 39;
+ ACT_ROLL_LEFT = 40; // tuck and roll left
+ ACT_ROLL_RIGHT = 41; // tuck and roll right
+ ACT_TURN_LEFT = 42; // turn quickly left (stationary)
+ ACT_TURN_RIGHT = 43; // turn quickly right (stationary)
+ ACT_CROUCH = 44; // FIXME: obsolete? only used be soldier (the act of crouching down from a standing position)
+ ACT_CROUCHIDLE = 45; // FIXME: obsolete? only used be soldier (holding body in crouched position (loops))
+ ACT_STAND = 46; // FIXME: obsolete? should be transition (the act of standing from a crouched position)
+ ACT_USE = 47;
+ ACT_ALIEN_BURROW_IDLE = 48;
+ ACT_ALIEN_BURROW_OUT = 49;
+
+ ACT_SIGNAL1 = 50;
+ ACT_SIGNAL2 = 51;
+ ACT_SIGNAL3 = 52;
+
+ ACT_SIGNAL_ADVANCE = 53; // Squad handsignals specific.
+ ACT_SIGNAL_FORWARD = 54;
+ ACT_SIGNAL_GROUP = 55;
+ ACT_SIGNAL_HALT = 56;
+ ACT_SIGNAL_LEFT = 57;
+ ACT_SIGNAL_RIGHT = 58;
+ ACT_SIGNAL_TAKECOVER = 59;
+
+ ACT_LOOKBACK_RIGHT = 60; // look back over shoulder without turning around.
+ ACT_LOOKBACK_LEFT = 61;
+ ACT_COWER = 62; // FIXME: unused should be more extreme version of crouching
+ ACT_SMALL_FLINCH = 63; // FIXME: needed? shouldn't flinching be down with overlays?
+ ACT_BIG_FLINCH = 64;
+ ACT_MELEE_ATTACK1 = 65;
+ ACT_MELEE_ATTACK2 = 66;
+ ACT_RELOAD = 67;
+ ACT_RELOAD_START = 68;
+ ACT_RELOAD_FINISH = 69;
+ ACT_RELOAD_LOW = 70;
+ ACT_ARM = 71; // pull out gun for instance
+ ACT_DISARM = 72; // reholster gun
+ ACT_DROP_WEAPON = 73;
+ ACT_DROP_WEAPON_SHOTGUN = 74;
+ ACT_PICKUP_GROUND = 75; // pick up something in front of you on the ground
+ ACT_PICKUP_RACK = 76; // pick up something from a rack or shelf in front of you.
+ ACT_IDLE_ANGRY = 77; // FIXME: being used as an combat ready idle? alternate idle animation in which the monster is clearly agitated. (loop)
+
+ ACT_IDLE_RELAXED = 78;
+ ACT_IDLE_STIMULATED = 79;
+ ACT_IDLE_AGITATED = 80;
+ ACT_IDLE_STEALTH = 81;
+ ACT_IDLE_HURT = 82;
+
+ ACT_WALK_RELAXED = 83;
+ ACT_WALK_STIMULATED = 84;
+ ACT_WALK_AGITATED = 85;
+ ACT_WALK_STEALTH = 86;
+
+ ACT_RUN_RELAXED = 87;
+ ACT_RUN_STIMULATED = 88;
+ ACT_RUN_AGITATED = 89;
+ ACT_RUN_STEALTH = 90;
+
+ ACT_IDLE_AIM_RELAXED = 91;
+ ACT_IDLE_AIM_STIMULATED = 92;
+ ACT_IDLE_AIM_AGITATED = 93;
+ ACT_IDLE_AIM_STEALTH = 94;
+
+ ACT_WALK_AIM_RELAXED = 95;
+ ACT_WALK_AIM_STIMULATED = 96;
+ ACT_WALK_AIM_AGITATED = 97;
+ ACT_WALK_AIM_STEALTH = 98;
+
+ ACT_RUN_AIM_RELAXED = 99;
+ ACT_RUN_AIM_STIMULATED = 100;
+ ACT_RUN_AIM_AGITATED = 101;
+ ACT_RUN_AIM_STEALTH = 102;
+
+ ACT_CROUCHIDLE_STIMULATED = 103;
+ ACT_CROUCHIDLE_AIM_STIMULATED = 104;
+ ACT_CROUCHIDLE_AGITATED = 105;
+
+ ACT_WALK_HURT = 106; // limp (loop)
+ ACT_RUN_HURT = 107; // limp (loop)
+ ACT_SPECIAL_ATTACK1 = 108; // very monster specific special attacks.
+ ACT_SPECIAL_ATTACK2 = 109;
+ ACT_COMBAT_IDLE = 110; // FIXME: unused? agitated idle.
+ ACT_WALK_SCARED = 111;
+ ACT_RUN_SCARED = 112;
+ ACT_VICTORY_DANCE = 113; // killed a player do a victory dance.
+ ACT_DIE_HEADSHOT = 114; // die hit in head.
+ ACT_DIE_CHESTSHOT = 115; // die hit in chest
+ ACT_DIE_GUTSHOT = 116; // die hit in gut
+ ACT_DIE_BACKSHOT = 117; // die hit in back
+ ACT_FLINCH_HEAD = 118;
+ ACT_FLINCH_CHEST = 119;
+ ACT_FLINCH_STOMACH = 120;
+ ACT_FLINCH_LEFTARM = 121;
+ ACT_FLINCH_RIGHTARM = 122;
+ ACT_FLINCH_LEFTLEG = 123;
+ ACT_FLINCH_RIGHTLEG = 124;
+ ACT_FLINCH_PHYSICS = 125;
+ ACT_FLINCH_HEAD_BACK = 126;
+ ACT_FLINCH_CHEST_BACK = 127;
+ ACT_FLINCH_STOMACH_BACK = 128;
+ ACT_FLINCH_CROUCH_FRONT = 129;
+ ACT_FLINCH_CROUCH_BACK = 130;
+ ACT_FLINCH_CROUCH_LEFT = 131;
+ ACT_FLINCH_CROUCH_RIGHT = 132;
+
+ ACT_IDLE_ON_FIRE = 133; // ON FIRE animations
+ ACT_WALK_ON_FIRE = 134;
+ ACT_RUN_ON_FIRE = 135;
+
+ ACT_RAPPEL_LOOP = 136; // Rappel down a rope!
+
+ ACT_180_LEFT = 137; // 180 degree left turn
+ ACT_180_RIGHT = 138;
+
+ ACT_90_LEFT = 139; // 90 degree turns
+ ACT_90_RIGHT = 140;
+
+ ACT_STEP_LEFT = 141; // Single steps
+ ACT_STEP_RIGHT = 142;
+ ACT_STEP_BACK = 143;
+ ACT_STEP_FORE = 144;
+
+ ACT_GESTURE_RANGE_ATTACK1 = 145;
+ ACT_GESTURE_RANGE_ATTACK2 = 146;
+ ACT_GESTURE_MELEE_ATTACK1 = 147;
+ ACT_GESTURE_MELEE_ATTACK2 = 148;
+ ACT_GESTURE_RANGE_ATTACK1_LOW = 149; // FIXME: not used yet crouched versions of the range attack
+ ACT_GESTURE_RANGE_ATTACK2_LOW = 150; // FIXME: not used yet crouched versions of the range attack
+
+ ACT_MELEE_ATTACK_SWING_GESTURE = 151;
+
+ ACT_GESTURE_SMALL_FLINCH = 152;
+ ACT_GESTURE_BIG_FLINCH = 153;
+ ACT_GESTURE_FLINCH_BLAST = 154; // Startled by an explosion
+ ACT_GESTURE_FLINCH_BLAST_SHOTGUN = 155;
+ ACT_GESTURE_FLINCH_BLAST_DAMAGED = 156; // Damaged by an explosion
+ ACT_GESTURE_FLINCH_BLAST_DAMAGED_SHOTGUN = 157;
+ ACT_GESTURE_FLINCH_HEAD = 158;
+ ACT_GESTURE_FLINCH_CHEST = 159;
+ ACT_GESTURE_FLINCH_STOMACH = 160;
+ ACT_GESTURE_FLINCH_LEFTARM = 161;
+ ACT_GESTURE_FLINCH_RIGHTARM = 162;
+ ACT_GESTURE_FLINCH_LEFTLEG = 163;
+ ACT_GESTURE_FLINCH_RIGHTLEG = 164;
+
+ ACT_GESTURE_TURN_LEFT = 165;
+ ACT_GESTURE_TURN_RIGHT = 166;
+ ACT_GESTURE_TURN_LEFT45 = 167;
+ ACT_GESTURE_TURN_RIGHT45 = 168;
+ ACT_GESTURE_TURN_LEFT90 = 169;
+ ACT_GESTURE_TURN_RIGHT90 = 170;
+ ACT_GESTURE_TURN_LEFT45_FLAT = 171;
+ ACT_GESTURE_TURN_RIGHT45_FLAT = 172;
+ ACT_GESTURE_TURN_LEFT90_FLAT = 173;
+ ACT_GESTURE_TURN_RIGHT90_FLAT = 174;
+
+ // HALF-LIFE 1 compatability stuff goes here. Temporary!
+ ACT_BARNACLE_HIT = 175; // barnacle tongue hits a monster
+ ACT_BARNACLE_PULL = 176; // barnacle is lifting the monster ( loop )
+ ACT_BARNACLE_CHOMP = 177; // barnacle latches on to the monster
+ ACT_BARNACLE_CHEW = 178; // barnacle is holding the monster in its mouth ( loop )
+
+ // Sometimes you just want to set an NPC's sequence to a sequence that doesn't actually
+ // have an activity. The AI will reset the NPC's sequence to whatever its IDEAL activity
+ // is though. So if you set ideal activity to DO_NOT_DISTURB the AI will not interfere
+ // with the NPC's current sequence. (SJB)
+ ACT_DO_NOT_DISTURB = 179;
+
+ ACT_SPECIFIC_SEQUENCE = 180;
+
+ // viewmodel (weapon) activities
+ // FIXME: move these to the specific viewmodels no need to make global
+ ACT_VM_DRAW = 181;
+ ACT_VM_HOLSTER = 182;
+ ACT_VM_IDLE = 183;
+ ACT_VM_FIDGET = 184;
+ ACT_VM_PULLBACK = 185;
+ ACT_VM_PULLBACK_HIGH = 186;
+ ACT_VM_PULLBACK_LOW = 187;
+ ACT_VM_THROW = 188;
+ ACT_VM_PULLPIN = 189;
+ ACT_VM_PRIMARYATTACK = 190; // fire
+ ACT_VM_SECONDARYATTACK = 191; // alt. fire
+ ACT_VM_RELOAD = 192;
+ ACT_VM_DRYFIRE = 193; // fire with no ammo loaded.
+ ACT_VM_HITLEFT = 194; // bludgeon swing to left - hit (primary attk)
+ ACT_VM_HITLEFT2 = 195; // bludgeon swing to left - hit (secondary attk)
+ ACT_VM_HITRIGHT = 196; // bludgeon swing to right - hit (primary attk)
+ ACT_VM_HITRIGHT2 = 197; // bludgeon swing to right - hit (secondary attk)
+ ACT_VM_HITCENTER = 198; // bludgeon swing center - hit (primary attk)
+ ACT_VM_HITCENTER2 = 199; // bludgeon swing center - hit (secondary attk)
+ ACT_VM_MISSLEFT = 200; // bludgeon swing to left - miss (primary attk)
+ ACT_VM_MISSLEFT2 = 201; // bludgeon swing to left - miss (secondary attk)
+ ACT_VM_MISSRIGHT = 202; // bludgeon swing to right - miss (primary attk)
+ ACT_VM_MISSRIGHT2 = 203; // bludgeon swing to right - miss (secondary attk)
+ ACT_VM_MISSCENTER = 204; // bludgeon swing center - miss (primary attk)
+ ACT_VM_MISSCENTER2 = 205; // bludgeon swing center - miss (secondary attk)
+ ACT_VM_HAULBACK = 206; // bludgeon haul the weapon back for a hard strike (secondary attk)
+ ACT_VM_SWINGHARD = 207; // bludgeon release the hard strike (secondary attk)
+ ACT_VM_SWINGMISS = 208;
+ ACT_VM_SWINGHIT = 209;
+ ACT_VM_IDLE_TO_LOWERED = 210;
+ ACT_VM_IDLE_LOWERED = 211;
+ ACT_VM_LOWERED_TO_IDLE = 212;
+ ACT_VM_RECOIL1 = 213;
+ ACT_VM_RECOIL2 = 214;
+ ACT_VM_RECOIL3 = 215;
+ ACT_VM_PICKUP = 216;
+ ACT_VM_RELEASE = 217;
+
+ ACT_VM_ATTACH_SILENCER = 218;
+ ACT_VM_DETACH_SILENCER = 219;
+
+//===========================
+// HL2 Specific Activities
+//===========================
+ // SLAM Specialty Activities
+ ACT_SLAM_STICKWALL_IDLE = 220;
+ ACT_SLAM_STICKWALL_ND_IDLE = 221;
+ ACT_SLAM_STICKWALL_ATTACH = 222;
+ ACT_SLAM_STICKWALL_ATTACH2 = 223;
+ ACT_SLAM_STICKWALL_ND_ATTACH = 224;
+ ACT_SLAM_STICKWALL_ND_ATTACH2 = 225;
+ ACT_SLAM_STICKWALL_DETONATE = 226;
+ ACT_SLAM_STICKWALL_DETONATOR_HOLSTER = 227;
+ ACT_SLAM_STICKWALL_DRAW = 228;
+ ACT_SLAM_STICKWALL_ND_DRAW = 229;
+ ACT_SLAM_STICKWALL_TO_THROW = 230;
+ ACT_SLAM_STICKWALL_TO_THROW_ND = 231;
+ ACT_SLAM_STICKWALL_TO_TRIPMINE_ND = 232;
+ ACT_SLAM_THROW_IDLE = 233;
+ ACT_SLAM_THROW_ND_IDLE = 234;
+ ACT_SLAM_THROW_THROW = 235;
+ ACT_SLAM_THROW_THROW2 = 236;
+ ACT_SLAM_THROW_THROW_ND = 237;
+ ACT_SLAM_THROW_THROW_ND2 = 238;
+ ACT_SLAM_THROW_DRAW = 239;
+ ACT_SLAM_THROW_ND_DRAW = 240;
+ ACT_SLAM_THROW_TO_STICKWALL = 241;
+ ACT_SLAM_THROW_TO_STICKWALL_ND = 242;
+ ACT_SLAM_THROW_DETONATE = 243;
+ ACT_SLAM_THROW_DETONATOR_HOLSTER = 244;
+ ACT_SLAM_THROW_TO_TRIPMINE_ND = 245;
+ ACT_SLAM_TRIPMINE_IDLE = 246;
+ ACT_SLAM_TRIPMINE_DRAW = 247;
+ ACT_SLAM_TRIPMINE_ATTACH = 248;
+ ACT_SLAM_TRIPMINE_ATTACH2 = 249;
+ ACT_SLAM_TRIPMINE_TO_STICKWALL_ND = 250;
+ ACT_SLAM_TRIPMINE_TO_THROW_ND = 251;
+ ACT_SLAM_DETONATOR_IDLE = 252;
+ ACT_SLAM_DETONATOR_DRAW = 253;
+ ACT_SLAM_DETONATOR_DETONATE = 254;
+ ACT_SLAM_DETONATOR_HOLSTER = 255;
+ ACT_SLAM_DETONATOR_STICKWALL_DRAW = 256;
+ ACT_SLAM_DETONATOR_THROW_DRAW = 257;
+
+ // Shotgun Specialty Activities
+ ACT_SHOTGUN_RELOAD_START = 258;
+ ACT_SHOTGUN_RELOAD_FINISH = 259;
+ ACT_SHOTGUN_PUMP = 260;
+
+ // SMG2 special activities
+ ACT_SMG2_IDLE2 = 261;
+ ACT_SMG2_FIRE2 = 262;
+ ACT_SMG2_DRAW2 = 263;
+ ACT_SMG2_RELOAD2 = 264;
+ ACT_SMG2_DRYFIRE2 = 265;
+ ACT_SMG2_TOAUTO = 266;
+ ACT_SMG2_TOBURST = 267;
+
+ // Physcannon special activities
+ ACT_PHYSCANNON_UPGRADE = 268;
+
+ // weapon override activities
+ ACT_RANGE_ATTACK_AR1 = 269;
+ ACT_RANGE_ATTACK_AR2 = 270;
+ ACT_RANGE_ATTACK_AR2_LOW = 271;
+ ACT_RANGE_ATTACK_AR2_GRENADE = 272;
+ ACT_RANGE_ATTACK_HMG1 = 273;
+ ACT_RANGE_ATTACK_ML = 274;
+ ACT_RANGE_ATTACK_SMG1 = 275;
+ ACT_RANGE_ATTACK_SMG1_LOW = 276;
+ ACT_RANGE_ATTACK_SMG2 = 277;
+ ACT_RANGE_ATTACK_SHOTGUN = 278;
+ ACT_RANGE_ATTACK_SHOTGUN_LOW = 279;
+ ACT_RANGE_ATTACK_PISTOL = 280;
+ ACT_RANGE_ATTACK_PISTOL_LOW = 281;
+ ACT_RANGE_ATTACK_SLAM = 282;
+ ACT_RANGE_ATTACK_TRIPWIRE = 283;
+ ACT_RANGE_ATTACK_THROW = 284;
+ ACT_RANGE_ATTACK_SNIPER_RIFLE = 285;
+ ACT_RANGE_ATTACK_RPG = 286;
+ ACT_MELEE_ATTACK_SWING = 287;
+
+ ACT_RANGE_AIM_LOW = 288;
+ ACT_RANGE_AIM_SMG1_LOW = 289;
+ ACT_RANGE_AIM_PISTOL_LOW = 290;
+ ACT_RANGE_AIM_AR2_LOW = 291;
+
+ ACT_COVER_PISTOL_LOW = 292;
+ ACT_COVER_SMG1_LOW = 293;
+
+ // weapon override activities
+ ACT_GESTURE_RANGE_ATTACK_AR1 = 294;
+ ACT_GESTURE_RANGE_ATTACK_AR2 = 295;
+ ACT_GESTURE_RANGE_ATTACK_AR2_GRENADE = 296;
+ ACT_GESTURE_RANGE_ATTACK_HMG1 = 297;
+ ACT_GESTURE_RANGE_ATTACK_ML = 298;
+ ACT_GESTURE_RANGE_ATTACK_SMG1 = 299;
+ ACT_GESTURE_RANGE_ATTACK_SMG1_LOW = 300;
+ ACT_GESTURE_RANGE_ATTACK_SMG2 = 301;
+ ACT_GESTURE_RANGE_ATTACK_SHOTGUN = 302;
+ ACT_GESTURE_RANGE_ATTACK_PISTOL = 303;
+ ACT_GESTURE_RANGE_ATTACK_PISTOL_LOW = 304;
+ ACT_GESTURE_RANGE_ATTACK_SLAM = 305;
+ ACT_GESTURE_RANGE_ATTACK_TRIPWIRE = 306;
+ ACT_GESTURE_RANGE_ATTACK_THROW = 307;
+ ACT_GESTURE_RANGE_ATTACK_SNIPER_RIFLE = 308;
+ ACT_GESTURE_MELEE_ATTACK_SWING = 309;
+
+ ACT_IDLE_RIFLE = 310;
+ ACT_IDLE_SMG1 = 311;
+ ACT_IDLE_ANGRY_SMG1 = 312;
+ ACT_IDLE_PISTOL = 313;
+ ACT_IDLE_ANGRY_PISTOL = 314;
+ ACT_IDLE_ANGRY_SHOTGUN = 315;
+ ACT_IDLE_STEALTH_PISTOL = 316;
+
+ ACT_IDLE_PACKAGE = 317;
+ ACT_WALK_PACKAGE = 318;
+ ACT_IDLE_SUITCASE = 319;
+ ACT_WALK_SUITCASE = 320;
+
+ ACT_IDLE_SMG1_RELAXED = 321;
+ ACT_IDLE_SMG1_STIMULATED = 322;
+ ACT_WALK_RIFLE_RELAXED = 323;
+ ACT_RUN_RIFLE_RELAXED = 324;
+ ACT_WALK_RIFLE_STIMULATED = 325;
+ ACT_RUN_RIFLE_STIMULATED = 326;
+
+ ACT_IDLE_AIM_RIFLE_STIMULATED = 327;
+ ACT_WALK_AIM_RIFLE_STIMULATED = 328;
+ ACT_RUN_AIM_RIFLE_STIMULATED = 329;
+
+ ACT_IDLE_SHOTGUN_RELAXED = 330;
+ ACT_IDLE_SHOTGUN_STIMULATED = 331;
+ ACT_IDLE_SHOTGUN_AGITATED = 332;
+
+ // Policing activities
+ ACT_WALK_ANGRY = 333;
+ ACT_POLICE_HARASS1 = 334;
+ ACT_POLICE_HARASS2 = 335;
+
+ // Manned guns
+ ACT_IDLE_MANNEDGUN = 336;
+
+ // Melee weapon
+ ACT_IDLE_MELEE = 337;
+ ACT_IDLE_ANGRY_MELEE = 338;
+
+ // RPG activities
+ ACT_IDLE_RPG_RELAXED = 339;
+ ACT_IDLE_RPG = 340;
+ ACT_IDLE_ANGRY_RPG = 341;
+ ACT_COVER_LOW_RPG = 342;
+ ACT_WALK_RPG = 343;
+ ACT_RUN_RPG = 344;
+ ACT_WALK_CROUCH_RPG = 345;
+ ACT_RUN_CROUCH_RPG = 346;
+ ACT_WALK_RPG_RELAXED = 347;
+ ACT_RUN_RPG_RELAXED = 348;
+
+ ACT_WALK_RIFLE = 349;
+ ACT_WALK_AIM_RIFLE = 350;
+ ACT_WALK_CROUCH_RIFLE = 351;
+ ACT_WALK_CROUCH_AIM_RIFLE = 352;
+ ACT_RUN_RIFLE = 353;
+ ACT_RUN_AIM_RIFLE = 354;
+ ACT_RUN_CROUCH_RIFLE = 355;
+ ACT_RUN_CROUCH_AIM_RIFLE = 356;
+ ACT_RUN_STEALTH_PISTOL = 357;
+
+ ACT_WALK_AIM_SHOTGUN = 358;
+ ACT_RUN_AIM_SHOTGUN = 359;
+
+ ACT_WALK_PISTOL = 360;
+ ACT_RUN_PISTOL = 361;
+ ACT_WALK_AIM_PISTOL = 362;
+ ACT_RUN_AIM_PISTOL = 363;
+ ACT_WALK_STEALTH_PISTOL = 364;
+ ACT_WALK_AIM_STEALTH_PISTOL = 365;
+ ACT_RUN_AIM_STEALTH_PISTOL = 366;
+
+ // Reloads
+ ACT_RELOAD_PISTOL = 367;
+ ACT_RELOAD_PISTOL_LOW = 368;
+ ACT_RELOAD_SMG1 = 369;
+ ACT_RELOAD_SMG1_LOW = 370;
+ ACT_RELOAD_SHOTGUN = 371;
+ ACT_RELOAD_SHOTGUN_LOW = 372;
+
+ ACT_GESTURE_RELOAD = 373;
+ ACT_GESTURE_RELOAD_PISTOL = 374;
+ ACT_GESTURE_RELOAD_SMG1 = 375;
+ ACT_GESTURE_RELOAD_SHOTGUN = 376;
+
+ // Busy animations
+ ACT_BUSY_LEAN_LEFT = 377;
+ ACT_BUSY_LEAN_LEFT_ENTRY = 378;
+ ACT_BUSY_LEAN_LEFT_EXIT = 379;
+ ACT_BUSY_LEAN_BACK = 380;
+ ACT_BUSY_LEAN_BACK_ENTRY = 381;
+ ACT_BUSY_LEAN_BACK_EXIT = 382;
+ ACT_BUSY_SIT_GROUND = 383;
+ ACT_BUSY_SIT_GROUND_ENTRY = 384;
+ ACT_BUSY_SIT_GROUND_EXIT = 385;
+ ACT_BUSY_SIT_CHAIR = 386;
+ ACT_BUSY_SIT_CHAIR_ENTRY = 387;
+ ACT_BUSY_SIT_CHAIR_EXIT = 388;
+ ACT_BUSY_STAND = 389;
+ ACT_BUSY_QUEUE = 390;
+
+ // Dodge animations
+ ACT_DUCK_DODGE = 391;
+
+ // For NPCs being lifted/eaten by barnacles:
+ // being swallowed by a barnacle
+ ACT_DIE_BARNACLE_SWALLOW = 392;
+ // being lifted by a barnacle
+ ACT_GESTURE_BARNACLE_STRANGLE = 393;
+
+ ACT_PHYSCANNON_DETACH = 394; // An activity to be played if we're picking this up with the physcannon
+ ACT_PHYSCANNON_ANIMATE = 395; // An activity to be played by an object being picked up with the physcannon but has different behavior to DETACH
+ ACT_PHYSCANNON_ANIMATE_PRE = 396; // An activity to be played by an object being picked up with the physcannon before playing the ACT_PHYSCANNON_ANIMATE
+ ACT_PHYSCANNON_ANIMATE_POST = 397; // An activity to be played by an object being picked up with the physcannon after playing the ACT_PHYSCANNON_ANIMATE
+
+ ACT_DIE_FRONTSIDE = 398;
+ ACT_DIE_RIGHTSIDE = 399;
+ ACT_DIE_BACKSIDE = 400;
+ ACT_DIE_LEFTSIDE = 401;
+
+ ACT_OPEN_DOOR = 402;
+
+ // Dynamic interactions
+ ACT_DI_ALYX_ZOMBIE_MELEE = 403;
+ ACT_DI_ALYX_ZOMBIE_TORSO_MELEE = 404;
+ ACT_DI_ALYX_HEADCRAB_MELEE = 405;
+ ACT_DI_ALYX_ANTLION = 406;
+
+ ACT_DI_ALYX_ZOMBIE_SHOTGUN64 = 407;
+ ACT_DI_ALYX_ZOMBIE_SHOTGUN26 = 408;
+
+ ACT_READINESS_RELAXED_TO_STIMULATED = 409;
+ ACT_READINESS_RELAXED_TO_STIMULATED_WALK = 410;
+ ACT_READINESS_AGITATED_TO_STIMULATED = 411;
+ ACT_READINESS_STIMULATED_TO_RELAXED = 412;
+
+ ACT_READINESS_PISTOL_RELAXED_TO_STIMULATED = 413;
+ ACT_READINESS_PISTOL_RELAXED_TO_STIMULATED_WALK = 414;
+ ACT_READINESS_PISTOL_AGITATED_TO_STIMULATED = 415;
+ ACT_READINESS_PISTOL_STIMULATED_TO_RELAXED = 416;
+
+ ACT_IDLE_CARRY = 417;
+ ACT_WALK_CARRY = 418;
+
+ ///******************
+ ///DOTA ANIMATIONS
+ ///******************
+
+ ACT_DOTA_IDLE = 419;
+//REMOVED ACT_DOTA_IDLE_ALT = 420;
+ ACT_DOTA_IDLE_RARE = 421;
+ ACT_DOTA_RUN = 422;
+//REMOVED ACT_DOTA_RUN_ALT = 423;
+ ACT_DOTA_ATTACK = 424;
+ ACT_DOTA_ATTACK2 = 425;
+ ACT_DOTA_ATTACK_EVENT = 426;
+ ACT_DOTA_DIE = 427;
+ ACT_DOTA_FLINCH = 428;
+ ACT_DOTA_FLAIL = 429;
+ ACT_DOTA_DISABLED = 430;
+ ACT_DOTA_CAST_ABILITY_1 = 431;
+ ACT_DOTA_CAST_ABILITY_2 = 432;
+ ACT_DOTA_CAST_ABILITY_3 = 433;
+ ACT_DOTA_CAST_ABILITY_4 = 434;
+ ACT_DOTA_CAST_ABILITY_5 = 435;
+ ACT_DOTA_CAST_ABILITY_6 = 436;
+ ACT_DOTA_OVERRIDE_ABILITY_1 = 437;
+ ACT_DOTA_OVERRIDE_ABILITY_2 = 438;
+ ACT_DOTA_OVERRIDE_ABILITY_3 = 439;
+ ACT_DOTA_OVERRIDE_ABILITY_4 = 440;
+ ACT_DOTA_CHANNEL_ABILITY_1 = 441;
+ ACT_DOTA_CHANNEL_ABILITY_2 = 442;
+ ACT_DOTA_CHANNEL_ABILITY_3 = 443;
+ ACT_DOTA_CHANNEL_ABILITY_4 = 444;
+ ACT_DOTA_CHANNEL_ABILITY_5 = 445;
+ ACT_DOTA_CHANNEL_ABILITY_6 = 446;
+ ACT_DOTA_CHANNEL_END_ABILITY_1 = 447;
+ ACT_DOTA_CHANNEL_END_ABILITY_2 = 448;
+ ACT_DOTA_CHANNEL_END_ABILITY_3 = 449;
+ ACT_DOTA_CHANNEL_END_ABILITY_4 = 450;
+ ACT_DOTA_CHANNEL_END_ABILITY_5 = 451;
+ ACT_DOTA_CHANNEL_END_ABILITY_6 = 452;
+ ACT_DOTA_CONSTANT_LAYER = 453;
+ ACT_DOTA_CAPTURE = 454;
+ ACT_DOTA_SPAWN = 455;
+ ACT_DOTA_KILLTAUNT = 456;
+ ACT_DOTA_TAUNT = 457;
+
+ //Hero specific (I hate my life)
+ ACT_DOTA_THIRST = 458;
+ ACT_DOTA_CAST_DRAGONBREATH = 459;
+ ACT_DOTA_ECHO_SLAM = 460;
+ ACT_DOTA_CAST_ABILITY_1_END = 461;
+ ACT_DOTA_CAST_ABILITY_2_END = 462;
+ ACT_DOTA_CAST_ABILITY_3_END = 463;
+ ACT_DOTA_CAST_ABILITY_4_END = 464;
+ ACT_MIRANA_LEAP_END = 465;
+ ACT_WAVEFORM_START = 466;
+ ACT_WAVEFORM_END = 467;
+ ACT_DOTA_CAST_ABILITY_ROT = 468;
+ ACT_DOTA_DIE_SPECIAL = 469;
+ ACT_DOTA_RATTLETRAP_BATTERYASSAULT = 470;
+ ACT_DOTA_RATTLETRAP_POWERCOGS = 471;
+ ACT_DOTA_RATTLETRAP_HOOKSHOT_START = 472;
+ ACT_DOTA_RATTLETRAP_HOOKSHOT_LOOP = 473;
+ ACT_DOTA_RATTLETRAP_HOOKSHOT_END = 474;
+ ACT_STORM_SPIRIT_OVERLOAD_RUN_OVERRIDE = 475;
+ ACT_DOTA_TINKER_REARM1 = 476;
+ ACT_DOTA_TINKER_REARM2 = 477;
+ ACT_DOTA_TINKER_REARM3 = 478;
+ ACT_TINY_AVALANCHE = 479;
+ ACT_TINY_TOSS = 480;
+ ACT_TINY_GROWL = 481;
+ ACT_DOTA_WEAVERBUG_ATTACH = 482;
+ ACT_DOTA_CAST_WILD_AXES_END = 483;
+ ACT_DOTA_CAST_LIFE_BREAK_START = 484;
+ ACT_DOTA_CAST_LIFE_BREAK_END = 485;
+ ACT_DOTA_NIGHTSTALKER_TRANSITION = 486;
+ ACT_DOTA_LIFESTEALER_RAGE = 487;
+ ACT_DOTA_LIFESTEALER_OPEN_WOUNDS = 488;
+ ACT_DOTA_SAND_KING_BURROW_IN = 489;
+ ACT_DOTA_SAND_KING_BURROW_OUT = 490;
+ ACT_DOTA_EARTHSHAKER_TOTEM_ATTACK = 491;
+ ACT_DOTA_WHEEL_LAYER = 492;
+ ACT_DOTA_ALCHEMIST_CHEMICAL_RAGE_START = 493;
+ ACT_DOTA_ALCHEMIST_CONCOCTION = 494;
+ ACT_DOTA_JAKIRO_LIQUIDFIRE_START = 495;
+ ACT_DOTA_JAKIRO_LIQUIDFIRE_LOOP = 496;
+ ACT_DOTA_LIFESTEALER_INFEST = 497;
+ ACT_DOTA_LIFESTEALER_INFEST_END = 498;
+ ACT_DOTA_LASSO_LOOP = 499;
+ ACT_DOTA_ALCHEMIST_CONCOCTION_THROW = 500;
+ ACT_DOTA_ALCHEMIST_CHEMICAL_RAGE_END = 501;
+ ACT_DOTA_CAST_COLD_SNAP = 502;
+ ACT_DOTA_CAST_GHOST_WALK = 503;
+ ACT_DOTA_CAST_TORNADO = 504;
+ ACT_DOTA_CAST_EMP = 505;
+ ACT_DOTA_CAST_ALACRITY = 506;
+ ACT_DOTA_CAST_CHAOS_METEOR = 507;
+ ACT_DOTA_CAST_SUN_STRIKE = 508;
+ ACT_DOTA_CAST_FORGE_SPIRIT = 509;
+ ACT_DOTA_CAST_ICE_WALL = 510;
+ ACT_DOTA_CAST_DEAFENING_BLAST = 511;
+ ACT_DOTA_VICTORY = 512;
+ ACT_DOTA_DEFEAT = 513;
+ ACT_DOTA_SPIRIT_BREAKER_CHARGE_POSE = 514;
+ ACT_DOTA_SPIRIT_BREAKER_CHARGE_END = 515;
+ ACT_DOTA_TELEPORT = 516;
+ ACT_DOTA_TELEPORT_END = 517;
+};
+
+
214 demo.proto
@@ -0,0 +1,214 @@
+//====== Copyright (c) 2012, Valve Corporation, All rights reserved. ========//
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are met:
+//
+// Redistributions of source code must retain the above copyright notice, this
+// list of conditions and the following disclaimer.
+// Redistributions in binary form must reproduce the above copyright notice,
+// this list of conditions and the following disclaimer in the documentation
+// and/or other materials provided with the distribution.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+// ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
+// LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+// CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+// SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+// INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+// ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
+// THE POSSIBILITY OF SUCH DAMAGE.
+//===========================================================================//
+//
+// Purpose: The file defines our Google Protocol Buffers which are used in over
+// the wire messages for the Source engine.
+//
+//=============================================================================
+
+// Note about encoding:
+// http://code.google.com/apis/protocolbuffers/docs/encoding.html
+//
+// TL;DR: Use sint32/sint64 for values that may be negative.
+//
+// There is an important difference between the signed int types (sint32 and sint64)
+// and the "standard" int types (int32 and int64) when it comes to encoding negative
+// numbers. If you use int32 or int64 as the type for a negative number, the
+// resulting varint is always ten bytes long – it is, effectively, treated like a
+// very large unsigned integer. If you use one of the signed types, the resulting
+// varint uses ZigZag encoding, which is much more efficient.
+
+
+// Commenting this out allows it to be compiled for SPEED or LITE_RUNTIME.
+// option optimize_for = SPEED;
+
+// We don't use the service generation functionality
+option cc_generic_services = false;
+
+
+//
+// STYLE NOTES:
+//
+// Use CamelCase CMsgMyMessageName style names for messages.
+//
+// Use lowercase _ delimited names like my_steam_id for field names, this is non-standard for Steam,
+// but plays nice with the Google formatted code generation.
+//
+// Try not to use required fields ever. Only do so if you are really really sure you'll never want them removed.
+// Optional should be preffered as it will make versioning easier and cleaner in the future if someone refactors
+// your message and wants to remove or rename fields.
+//
+// Use fixed64 for JobId_t, GID_t, or SteamID. This is appropriate for any field that is normally
+// going to be larger than 2^56. Otherwise use int64 for 64 bit values that are frequently smaller
+// than 2^56 as it will safe space on the wire in those cases.
+//
+// Similar to fixed64, use fixed32 for RTime32 or other 32 bit values that are frequently larger than
+// 2^28. It will safe space in those cases, otherwise use int32 which will safe space for smaller values.
+// An exception to this rule for RTime32 is if the value will frequently be zero rather than set to an actual
+// time.
+//
+
+import "google/protobuf/descriptor.proto";
+
+enum EDemoCommands
+{
+ DEM_Error = -1;
+ DEM_Stop = 0;
+ DEM_FileHeader = 1;
+ DEM_FileInfo = 2;
+ DEM_SyncTick = 3;
+ DEM_SendTables = 4;
+ DEM_ClassInfo = 5;
+ DEM_StringTables = 6;
+ DEM_Packet = 7;
+ DEM_SignonPacket = 8;
+ DEM_ConsoleCmd = 9;
+ DEM_CustomData = 10;
+ DEM_CustomDataCallbacks = 11;
+ DEM_UserCmd = 12;
+ DEM_FullPacket = 13;
+
+ DEM_Max = 14;
+ DEM_IsCompressed = 0x70;
+}
+
+message CDemoFileHeader
+{
+ required string demo_file_stamp = 1;
+ optional int32 network_protocol = 2;
+ optional string server_name = 3;
+ optional string client_name = 4;
+ optional string map_name = 5;
+ optional string game_directory = 6;
+ optional int32 fullpackets_version = 7;
+ optional bool allow_clientside_entities = 8;
+}
+
+message CGameInfo
+{
+ message CDotaGameInfo
+ {
+ message CPlayerInfo
+ {
+ optional string hero_name = 1;
+ optional string player_name = 2;
+ optional bool is_fake_client = 3;
+ }
+
+ optional uint32 match_id = 1;
+ optional int32 game_mode = 2;
+ optional int32 game_winner = 3;
+ repeated CPlayerInfo player_info = 4;
+ }
+
+ optional CDotaGameInfo dota = 4;
+}
+
+message CDemoFileInfo
+{
+ optional float playback_time = 1;
+ optional int32 playback_ticks = 2;
+ optional int32 playback_frames = 3;
+ optional CGameInfo game_info = 4;
+}
+
+message CDemoPacket
+{
+ optional int32 sequence_in = 1;
+ optional int32 sequence_out_ack = 2;
+ optional bytes data = 3;
+}
+
+message CDemoFullPacket
+{
+ optional CDemoStringTables string_table = 1;
+ optional CDemoPacket packet = 2;
+}
+
+message CDemoSyncTick
+{
+}
+
+message CDemoConsoleCmd
+{
+ optional string cmdstring = 1;
+}
+
+message CDemoSendTables
+{
+ optional bytes data = 1;
+}
+
+message CDemoClassInfo
+{
+ message class_t
+ {
+ optional int32 class_id = 1;
+ optional string network_name = 2;
+ optional string table_name = 3;
+ }
+
+ repeated class_t classes = 1;
+}
+
+message CDemoCustomData
+{
+ optional int32 callback_index = 1;
+ optional bytes data = 2;
+}
+
+message CDemoCustomDataCallbacks
+{
+ repeated string save_id = 1;
+}
+
+message CDemoStringTables
+{
+ message items_t
+ {
+ optional string str = 1;
+ optional bytes data = 2;
+ }
+
+ message table_t
+ {
+ optional string table_name = 1;
+ repeated items_t items = 2;
+ repeated items_t items_clientside = 3;
+ optional int32 table_flags = 4;
+ }
+
+ repeated table_t tables = 1;
+}
+
+message CDemoStop
+{
+}
+
+message CDemoUserCmd
+{
+ optional int32 cmd_number = 1;
+ optional bytes data = 2;
+}
+
213 demofile.cpp
@@ -0,0 +1,213 @@
+//====== Copyright (c) 2012, Valve Corporation, All rights reserved. ========//
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are met:
+//
+// Redistributions of source code must retain the above copyright notice, this
+// list of conditions and the following disclaimer.
+// Redistributions in binary form must reproduce the above copyright notice,
+// this list of conditions and the following disclaimer in the documentation
+// and/or other materials provided with the distribution.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+// ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
+// LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+// CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+// SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+// INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+// ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
+// THE POSSIBILITY OF SUCH DAMAGE.
+//===========================================================================//
+
+#include <assert.h>
+#include "demofile.h"
+#include "snappy.h"
+
+uint32 ReadVarInt32( const std::string& buf, size_t& index )
+{
+ uint32 b;
+ int count = 0;
+ uint32 result = 0;
+
+ do
+ {
+ if ( count == 5 )
+ {
+ // If we get here it means that the fifth bit had its
+ // high bit set, which implies corrupt data.
+ assert( 0 );
+ return result;
+ }
+ else if ( index >= buf.size() )
+ {
+ assert( 0 );
+ return result;
+ }
+
+ b = buf[ index++ ];
+ result |= ( b & 0x7F ) << ( 7 * count );
+ ++count;
+ } while ( b & 0x80 );
+
+ return result;
+}
+
+CDemoFile::CDemoFile() :
+ m_fileBufferPos( 0 )
+{
+}
+
+CDemoFile::~CDemoFile()
+{
+ Close();
+}
+
+bool CDemoFile::IsDone()
+{
+ return m_fileBufferPos >= m_fileBuffer.size();
+}
+
+EDemoCommands CDemoFile::ReadMessageType( int *pTick, bool *pbCompressed )
+{
+ uint32 Cmd = ReadVarInt32( m_fileBuffer, m_fileBufferPos );
+
+ if( pbCompressed )
+ *pbCompressed = !!( Cmd & DEM_IsCompressed );
+
+ Cmd = ( Cmd & ~DEM_IsCompressed );
+
+ int Tick = ReadVarInt32( m_fileBuffer, m_fileBufferPos );
+ if( pTick )
+ *pTick = Tick;
+
+ if( m_fileBufferPos >= m_fileBuffer.size() )
+ return DEM_Error;
+
+ return ( EDemoCommands )Cmd;
+}
+
+bool CDemoFile::ReadMessage( IDemoMessage *pMsg, bool bCompressed, int *pSize, int *pUncompressedSize )
+{
+ int Size = ReadVarInt32( m_fileBuffer, m_fileBufferPos );
+
+ if( pSize )
+ {
+ *pSize = Size;
+ }
+ if( pUncompressedSize )
+ {
+ *pUncompressedSize = 0;
+ }
+
+ if( m_fileBufferPos + Size > m_fileBuffer.size() )
+ {
+ assert( 0 );
+ return false;
+ }
+
+ if( pMsg )
+ {
+ const char *parseBuffer = &m_fileBuffer[ m_fileBufferPos ];
+ m_fileBufferPos += Size;
+
+ if( bCompressed )
+ {
+ if ( snappy::IsValidCompressedBuffer( parseBuffer, Size ) )
+ {
+ size_t uDecompressedLen;
+
+ if ( snappy::GetUncompressedLength( parseBuffer, Size, &uDecompressedLen ) )
+ {
+ if( pUncompressedSize )
+ {
+ *pUncompressedSize = uDecompressedLen;
+ }
+
+ m_parseBufferSnappy.resize( uDecompressedLen );
+ char *parseBufferUncompressed = &m_parseBufferSnappy[ 0 ];
+
+ if ( snappy::RawUncompress( parseBuffer, Size, parseBufferUncompressed ) )
+ {
+ if ( pMsg->GetProtoMsg().ParseFromArray( parseBufferUncompressed, uDecompressedLen ) )
+ {
+ return true;
+ }
+ }
+ }
+ }
+
+ assert( 0 );
+ fprintf( stderr, "CDemoFile::ReadMessage() snappy::RawUncompress failed.\n" );
+ return false;
+ }
+
+ return pMsg->GetProtoMsg().ParseFromArray( parseBuffer, Size );
+ }
+ else
+ {
+ m_fileBufferPos += Size;
+ return true;
+ }
+}
+
+bool CDemoFile::Open( const char *name )
+{
+ Close();
+
+ FILE *fp = fopen( name, "rb" );
+ if( fp )
+ {
+ size_t Length;
+ protodemoheader_t DotaDemoHeader;
+
+ fseek( fp, 0, SEEK_END );
+ Length = ftell( fp );
+ fseek( fp, 0, SEEK_SET );
+
+ if( Length < sizeof( DotaDemoHeader ) )
+ {
+ fprintf( stderr, "CDemoFile::Open: file too small. %s.\n", name );
+ return false;
+ }
+
+ fread( &DotaDemoHeader, 1, sizeof( DotaDemoHeader ), fp );
+ Length -= sizeof( DotaDemoHeader );
+
+ if( strcmp( DotaDemoHeader.demofilestamp, PROTODEMO_HEADER_ID ) )
+ {
+ fprintf( stderr, "CDemoFile::Open: demofilestamp doesn't match. %s.\n", name );
+ return false;
+ }
+
+ m_fileBuffer.resize( Length );
+ fread( &m_fileBuffer[ 0 ], 1, Length, fp );
+
+ fclose( fp );
+ fp = NULL;
+ }
+
+ if ( !m_fileBuffer.size() )
+ {
+ fprintf( stderr, "CDemoFile::Open: couldn't open file %s.\n", name );
+ Close();
+ return false;
+ }
+
+ m_fileBufferPos = 0;
+ m_szFileName = name;
+ return true;
+}
+
+void CDemoFile::Close()
+{
+ m_szFileName.clear();
+
+ m_fileBufferPos = 0;
+ m_fileBuffer.clear();
+
+ m_parseBufferSnappy.clear();
+}
+
140 demofile.h
@@ -0,0 +1,140 @@
+//====== Copyright (c) 2012, Valve Corporation, All rights reserved. ========//
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are met:
+//
+// Redistributions of source code must retain the above copyright notice, this
+// list of conditions and the following disclaimer.
+// Redistributions in binary form must reproduce the above copyright notice,
+// this list of conditions and the following disclaimer in the documentation
+// and/or other materials provided with the distribution.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+// ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
+// LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+// CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+// SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+// INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+// ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
+// THE POSSIBILITY OF SUCH DAMAGE.
+//===========================================================================//
+
+#ifndef DEMOFILE_H
+#define DEMOFILE_H
+
+#include "generated_proto/demo.pb.h"
+
+typedef int32_t int32;
+typedef uint32_t uint32;
+typedef uint64_t uint64;
+typedef uint32_t CRC32_t;
+
+#define PROTODEMO_HEADER_ID "PBUFDEM"
+#define DEMOFILE_FULLPACKETS_VERSION 2
+
+struct protodemoheader_t
+{
+ char demofilestamp[ 8 ]; // PROTODEMO_HEADER_ID
+ int32 fileinfo_offset;
+};
+
+#define MAX_PLAYER_NAME_LENGTH 32
+#define MAX_CUSTOM_FILES 4 // max 4 files
+#define SIGNED_GUID_LEN 32 // Hashed CD Key (32 hex alphabetic chars + 0 terminator )
+
+typedef struct player_info_s
+{
+ // network xuid
+ uint64 xuid;
+ // scoreboard information
+ char name[MAX_PLAYER_NAME_LENGTH];
+ // local server user ID, unique while server is running
+ int userID;
+ // global unique player identifer
+ char guid[SIGNED_GUID_LEN + 1];
+ // friends identification number
+ uint32 friendsID;
+ // friends name
+ char friendsName[MAX_PLAYER_NAME_LENGTH];
+ // true, if player is a bot controlled by game.dll
+ bool fakeplayer;
+ // true if player is the HLTV proxy
+ bool ishltv;
+#if defined( REPLAY_ENABLED )
+ // true if player is the Replay proxy
+ bool isreplay;
+#endif
+ // custom files CRC for this player
+ CRC32_t customFiles[MAX_CUSTOM_FILES];
+ // this counter increases each time the server downloaded a new file
+ unsigned char filesDownloaded;
+} player_info_t;
+
+class IDemoMessage
+{
+public:
+ virtual ~IDemoMessage() {};
+
+ virtual EDemoCommands GetType( void ) const = 0; // returns module specific header tag
+ virtual size_t GetSize() const = 0;
+ virtual ::google::protobuf::Message& GetProtoMsg() = 0;
+};
+
+template< EDemoCommands msgType, typename PB_OBJECT_TYPE >
+class CDemoMessagePB : public IDemoMessage, public PB_OBJECT_TYPE
+{
+public:
+ CDemoMessagePB() {}
+ virtual ~CDemoMessagePB() {}
+
+ virtual EDemoCommands GetType() const { return msgType; }
+ virtual size_t GetSize() const { return sizeof( *this ); }
+ virtual ::google::protobuf::Message& GetProtoMsg() { return *this; }
+};
+
+typedef CDemoMessagePB< DEM_FileHeader, CDemoFileHeader > CDemoFileHeader_t;
+typedef CDemoMessagePB< DEM_FileInfo, CDemoFileInfo > CDemoFileInfo_t;
+typedef CDemoMessagePB< DEM_Stop, CDemoStop > CDemoStop_t;
+typedef CDemoMessagePB< DEM_SyncTick, CDemoSyncTick > CDemoSyncTick_t;
+typedef CDemoMessagePB< DEM_SendTables, CDemoSendTables > CDemoSendTables_t;
+typedef CDemoMessagePB< DEM_ClassInfo, CDemoClassInfo > CDemoClassInfo_t;
+typedef CDemoMessagePB< DEM_StringTables, CDemoStringTables > CDemoStringTables_t;
+typedef CDemoMessagePB< DEM_ConsoleCmd, CDemoConsoleCmd > CDemoConsoleCmd_t;
+typedef CDemoMessagePB< DEM_CustomData, CDemoCustomData > CDemoCustomData_t;
+typedef CDemoMessagePB< DEM_CustomDataCallbacks, CDemoCustomDataCallbacks > CDemoCustomDataCallbacks_t;
+typedef CDemoMessagePB< DEM_UserCmd, CDemoUserCmd > CDemoUserCmd_t;
+typedef CDemoMessagePB< DEM_FullPacket, CDemoFullPacket > CDemoFullPacket_t;
+typedef CDemoMessagePB< DEM_Packet, CDemoPacket > CDemoPacket_t;
+
+//-----------------------------------------------------------------------------
+// Demo file
+//-----------------------------------------------------------------------------
+class CDemoFile
+{
+public:
+ CDemoFile();
+ ~CDemoFile();
+
+ bool Open(const char *name);
+ void Close();
+ bool IsDone();
+
+ EDemoCommands ReadMessageType( int *pTick, bool *pbCompressed );
+ bool ReadMessage( IDemoMessage *pMsg, bool bCompressed, int *pSize = NULL, int *pUncompressedSize = NULL );
+
+private:
+ std::string m_szFileName;
+
+ size_t m_fileBufferPos;
+ std::string m_fileBuffer;
+
+ std::string m_parseBufferSnappy;
+};
+
+uint32 ReadVarInt32( const std::string& buf, size_t& index );
+
+#endif // DEMOFILE_H
+
494 demofiledump.cpp
@@ -0,0 +1,494 @@
+//====== Copyright (c) 2012, Valve Corporation, All rights reserved. ========//
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are met:
+//
+// Redistributions of source code must retain the above copyright notice, this
+// list of conditions and the following disclaimer.
+// Redistributions in binary form must reproduce the above copyright notice,
+// this list of conditions and the following disclaimer in the documentation
+// and/or other materials provided with the distribution.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+// ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
+// LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+// CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+// SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+// INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+// ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
+// THE POSSIBILITY OF SUCH DAMAGE.
+//===========================================================================//
+
+#include <stdarg.h>
+#include "demofile.h"
+#include "demofiledump.h"
+
+#include "google/protobuf/descriptor.h"
+#include "google/protobuf/reflection_ops.h"
+#include "google/protobuf/descriptor.pb.h"
+
+#include "generated_proto/usermessages.pb.h"
+#include "generated_proto/ai_activity.pb.h"
+#include "generated_proto/dota_modifiers.pb.h"
+#include "generated_proto/dota_commonmessages.pb.h"
+#include "generated_proto/dota_usermessages.pb.h"
+
+void fatal_errorf( const char* fmt, ... )
+{
+ va_list vlist;
+ char buf[ 1024 ];
+
+ va_start( vlist, fmt);
+ vsnprintf( buf, sizeof( buf ), fmt, vlist );
+ buf[ sizeof( buf ) - 1 ] = 0;
+ va_end( vlist );
+
+ fprintf( stderr, "\nERROR: %s\n", buf );
+ exit( -1 );
+}
+
+bool CDemoFileDump::Open( const char *filename )
+{
+ if ( !m_demofile.Open( filename ) )
+ {
+ fprintf( stderr, "Couldn't open '%s'\n", filename );
+ return false;
+ }
+
+ return true;
+}
+
+void CDemoFileDump::MsgPrintf( const ::google::protobuf::Message& msg, int size, const char *fmt, ... )
+{
+ va_list vlist;
+ const std::string& TypeName = msg.GetTypeName();
+
+ // Print the message type and size
+ printf( "---- %s (%d bytes) -----------------\n", TypeName.c_str(), size );
+
+ va_start( vlist, fmt);
+ vprintf( fmt, vlist );
+ va_end( vlist );
+}
+
+template < class T, int msgType >
+void PrintUserMessage( CDemoFileDump& Demo, const void *parseBuffer, int BufferSize )
+{
+ T msg;
+
+ if( msg.ParseFromArray( parseBuffer, BufferSize ) )
+ {
+ Demo.MsgPrintf( msg, BufferSize, "%s", msg.DebugString().c_str() );
+ }
+}
+
+void CDemoFileDump::DumpUserMessage( const void *parseBuffer, int BufferSize )
+{
+ CSVCMsg_UserMessage userMessage;
+
+ if( userMessage.ParseFromArray( parseBuffer, BufferSize ) )
+ {
+ int Cmd = userMessage.msg_type();
+ int SizeUM = userMessage.msg_data().size();
+ const void *parseBufferUM = &userMessage.msg_data()[ 0 ];
+
+ switch( Cmd )
+ {
+#define HANDLE_UserMsg( _x ) case UM_ ## _x: PrintUserMessage< CUserMsg_ ## _x, UM_ ## _x >( *this, parseBufferUM, SizeUM ); break
+#define HANDLE_DOTA_UserMsg( _x ) case DOTA_UM_ ## _x: PrintUserMessage< CDOTAUserMsg_ ## _x, DOTA_UM_ ## _x >( *this, parseBufferUM, SizeUM ); break
+
+ default:
+ printf( "WARNING. DumpUserMessage(): Unknown user message %d.\n", Cmd );
+ break;
+
+ HANDLE_UserMsg( AchievementEvent ); // 1,
+ HANDLE_UserMsg( CloseCaption ); // 2,
+ //$ HANDLE_UserMsg( CloseCaptionDirect ); // 3,
+ HANDLE_UserMsg( CurrentTimescale ); // 4,
+ HANDLE_UserMsg( DesiredTimescale ); // 5,
+ HANDLE_UserMsg( Fade ); // 6,
+ HANDLE_UserMsg( GameTitle ); // 7,
+ HANDLE_UserMsg( Geiger ); // 8,
+ HANDLE_UserMsg( HintText ); // 9,
+ HANDLE_UserMsg( HudMsg ); // 10,
+ HANDLE_UserMsg( HudText ); // 11,
+ HANDLE_UserMsg( KeyHintText ); // 12,
+ HANDLE_UserMsg( MessageText ); // 13,
+ HANDLE_UserMsg( RequestState ); // 14,
+ HANDLE_UserMsg( ResetHUD ); // 15,
+ HANDLE_UserMsg( Rumble ); // 16,
+ HANDLE_UserMsg( SayText ); // 17,
+ HANDLE_UserMsg( SayText2 ); // 18,
+ HANDLE_UserMsg( SayTextChannel ); // 19,
+ HANDLE_UserMsg( Shake ); // 20,
+ HANDLE_UserMsg( ShakeDir ); // 21,
+ HANDLE_UserMsg( StatsCrawlMsg ); // 22,
+ HANDLE_UserMsg( StatsSkipState ); // 23,
+ HANDLE_UserMsg( TextMsg ); // 24,
+ HANDLE_UserMsg( Tilt ); // 25,
+ HANDLE_UserMsg( Train ); // 26,
+ HANDLE_UserMsg( VGUIMenu ); // 27,
+ HANDLE_UserMsg( VoiceMask ); // 28,
+ HANDLE_UserMsg( VoiceSubtitle ); // 29,
+ HANDLE_UserMsg( SendAudio ); // 30,
+
+ //$ HANDLE_DOTA_UserMsg( AddUnitToSelection ); // 64,
+ HANDLE_DOTA_UserMsg( AIDebugLine ); // 65,
+ HANDLE_DOTA_UserMsg( ChatEvent ); // 66,
+ HANDLE_DOTA_UserMsg( CombatHeroPositions ); // 67,
+ HANDLE_DOTA_UserMsg( CombatLogData ); // 68,
+ //$ HANDLE_DOTA_UserMsg( CombatLogName ); // 69,
+ HANDLE_DOTA_UserMsg( CombatLogShowDeath ); // 70,
+ HANDLE_DOTA_UserMsg( CreateLinearProjectile ); // 71,
+ HANDLE_DOTA_UserMsg( DestroyLinearProjectile ); // 72,
+ HANDLE_DOTA_UserMsg( DodgeTrackingProjectiles );// 73,
+ HANDLE_DOTA_UserMsg( GlobalLightColor ); // 74,
+ HANDLE_DOTA_UserMsg( GlobalLightDirection ); // 75,
+ HANDLE_DOTA_UserMsg( InvalidCommand ); // 76,
+ HANDLE_DOTA_UserMsg( LocationPing ); // 77,
+ HANDLE_DOTA_UserMsg( MapLine ); // 78,
+ HANDLE_DOTA_UserMsg( MiniKillCamInfo ); // 79,
+ HANDLE_DOTA_UserMsg( MinimapDebugPoint ); // 80,
+ HANDLE_DOTA_UserMsg( MinimapEvent ); // 81,
+ HANDLE_DOTA_UserMsg( NevermoreRequiem ); // 82,
+ HANDLE_DOTA_UserMsg( OverheadEvent ); // 83,
+ HANDLE_DOTA_UserMsg( SetNextAutobuyItem ); // 84,
+ HANDLE_DOTA_UserMsg( SharedCooldown ); // 85,
+ HANDLE_DOTA_UserMsg( SpectatorPlayerClick ); // 86,
+ HANDLE_DOTA_UserMsg( TutorialTipInfo ); // 87,
+ HANDLE_DOTA_UserMsg( UnitEvent ); // 88,
+ HANDLE_DOTA_UserMsg( ParticleManager ); // 89,
+ HANDLE_DOTA_UserMsg( BotChat ); // 90,
+ HANDLE_DOTA_UserMsg( HudError ); // 91,
+ HANDLE_DOTA_UserMsg( ItemPurchased ); // 92,
+ HANDLE_DOTA_UserMsg( Ping ); // 93
+
+#undef HANDLE_UserMsg
+#undef HANDLE_DOTA_UserMsg
+ }
+ }
+}
+
+template < class T, int msgType >
+void PrintNetMessage( CDemoFileDump& Demo, const void *parseBuffer, int BufferSize )
+{
+ T msg;
+
+ if( msg.ParseFromArray( parseBuffer, BufferSize ) )
+ {
+ if( msgType == svc_GameEventList )
+ {
+ Demo.m_GameEventList.CopyFrom( msg );
+ }
+
+ Demo.MsgPrintf( msg, BufferSize, "%s", msg.DebugString().c_str() );
+ }
+}
+
+template <>
+void PrintNetMessage< CSVCMsg_UserMessage, svc_UserMessage >( CDemoFileDump& Demo, const void *parseBuffer, int BufferSize )
+{
+ Demo.DumpUserMessage( parseBuffer, BufferSize );
+}
+
+template <>
+void PrintNetMessage< CSVCMsg_GameEvent, svc_GameEvent >( CDemoFileDump& Demo, const void *parseBuffer, int BufferSize )
+{
+ CSVCMsg_GameEvent msg;
+
+ if( msg.ParseFromArray( parseBuffer, BufferSize ) )
+ {
+ int iDescriptor;
+
+ for( iDescriptor = 0; iDescriptor < Demo.m_GameEventList.descriptors().size(); iDescriptor++ )
+ {
+ const CSVCMsg_GameEventList::descriptor_t& Descriptor = Demo.m_GameEventList.descriptors( iDescriptor );
+
+ if( Descriptor.eventid() == msg.eventid() )
+ break;
+ }
+
+ if( iDescriptor == Demo.m_GameEventList.descriptors().size() )
+ {
+ printf( "%s", msg.DebugString().c_str() );
+ }
+ else
+ {
+ int numKeys = msg.keys().size();
+ const CSVCMsg_GameEventList::descriptor_t& Descriptor = Demo.m_GameEventList.descriptors( iDescriptor );
+
+ printf( "%s eventid:%d %s\n", Descriptor.name().c_str(), msg.eventid(),
+ msg.has_event_name() ? msg.event_name().c_str() : "" );
+
+ for( int i = 0; i < numKeys; i++ )
+ {
+ const CSVCMsg_GameEventList::key_t& Key = Descriptor.keys( i );
+ const CSVCMsg_GameEvent::key_t& KeyValue = msg.keys( i );
+
+ printf(" %s: ", Key.name().c_str() );
+
+ if( KeyValue.has_val_string() )
+ printf( "%s ", KeyValue.val_string().c_str() );
+ if( KeyValue.has_val_float() )
+ printf( "%f ", KeyValue.val_float() );
+ if( KeyValue.has_val_long() )
+ printf( "%d ", KeyValue.val_long() );
+ if( KeyValue.has_val_short() )
+ printf( "%d ", KeyValue.val_short() );
+ if( KeyValue.has_val_byte() )
+ printf( "%d ", KeyValue.val_byte() );
+ if( KeyValue.has_val_bool() )
+ printf( "%d ", KeyValue.val_bool() );
+ if( KeyValue.has_val_uint64() )
+ printf( "%lld ", KeyValue.val_uint64() );
+
+ printf( "\n" );
+ }
+ }
+ }
+}
+
+static std::string GetNetMsgName( int Cmd )
+{
+ if( NET_Messages_IsValid( Cmd ) )
+ {
+ return NET_Messages_Name( ( NET_Messages )Cmd );
+ }
+ else if( SVC_Messages_IsValid( Cmd ) )
+ {
+ return SVC_Messages_Name( ( SVC_Messages )Cmd );
+ }
+
+ assert( 0 );
+ return "NETMSG_???";
+}
+
+void CDemoFileDump::DumpDemoPacket( const std::string& buf )
+{
+ size_t index = 0;
+
+ while( index < buf.size() )
+ {
+ int Cmd = ReadVarInt32( buf, index );
+ uint32 Size = ReadVarInt32( buf, index );
+
+ if( index + Size > buf.size() )
+ {
+ const std::string& strName = GetNetMsgName( Cmd );
+
+ fatal_errorf( "buf.ReadBytes() failed. Cmd:%d '%s' \n", Cmd, strName.c_str() );
+ }
+
+ switch( Cmd )
+ {
+#define HANDLE_NetMsg( _x ) case net_ ## _x: PrintNetMessage< CNETMsg_ ## _x, net_ ## _x >( *this, &buf[ index ], Size ); break
+#define HANDLE_SvcMsg( _x ) case svc_ ## _x: PrintNetMessage< CSVCMsg_ ## _x, svc_ ## _x >( *this, &buf[ index ], Size ); break
+
+ default:
+ printf( "WARNING. DumpUserMessage(): Unknown netmessage %d.\n", Cmd );
+ break;
+
+ HANDLE_NetMsg( NOP ); // 0
+ HANDLE_NetMsg( Disconnect ); // 1
+ HANDLE_NetMsg( File ); // 2
+ HANDLE_NetMsg( SplitScreenUser ); // 3
+ HANDLE_NetMsg( Tick ); // 4
+ HANDLE_NetMsg( StringCmd ); // 5
+ HANDLE_NetMsg( SetConVar ); // 6
+ HANDLE_NetMsg( SignonState ); // 7
+ HANDLE_SvcMsg( ServerInfo ); // 8
+ HANDLE_SvcMsg( SendTable ); // 9
+ HANDLE_SvcMsg( ClassInfo ); // 10
+ HANDLE_SvcMsg( SetPause ); // 11
+ HANDLE_SvcMsg( CreateStringTable ); // 12
+ HANDLE_SvcMsg( UpdateStringTable ); // 13
+ HANDLE_SvcMsg( VoiceInit ); // 14
+ HANDLE_SvcMsg( VoiceData ); // 15
+ HANDLE_SvcMsg( Print ); // 16
+ HANDLE_SvcMsg( Sounds ); // 17
+ HANDLE_SvcMsg( SetView ); // 18
+ HANDLE_SvcMsg( FixAngle ); // 19
+ HANDLE_SvcMsg( CrosshairAngle ); // 20
+ HANDLE_SvcMsg( BSPDecal ); // 21
+ HANDLE_SvcMsg( SplitScreen ); // 22
+ HANDLE_SvcMsg( UserMessage ); // 23
+ //$ HANDLE_SvcMsg( EntityMessage ); // 24
+ HANDLE_SvcMsg( GameEvent ); // 25
+ HANDLE_SvcMsg( PacketEntities ); // 26
+ HANDLE_SvcMsg( TempEntities ); // 27
+ HANDLE_SvcMsg( Prefetch ); // 28
+ HANDLE_SvcMsg( Menu ); // 29
+ HANDLE_SvcMsg( GameEventList ); // 30
+ HANDLE_SvcMsg( GetCvarValue ); // 31
+
+#undef HANDLE_SvcMsg
+#undef HANDLE_NetMsg
+ }
+
+ index += Size;
+ }
+}
+
+static bool DumpDemoStringTable( CDemoFileDump& Demo, const CDemoStringTables& StringTables )
+{
+ for( int i = 0; i < StringTables.tables().size(); i++ )
+ {
+ const CDemoStringTables::table_t& Table = StringTables.tables( i );
+
+ printf( "#%d %s flags:0x%x (%d Items) %d bytes\n",
+ i, Table.table_name().c_str(), Table.table_flags(),
+ Table.items().size() + Table.items_clientside().size(), Table.ByteSize() );
+
+ bool bIsActiveModifiersTable = !strcmp( Table.table_name().c_str(), "ActiveModifiers" );
+ bool bIsUserInfo = !strcmp( Table.table_name().c_str(), "userinfo" );
+
+ // Only spew out the stringtables (really big) if verbose is on.
+ for( int itemid = 0; itemid < Table.items().size(); itemid++ )
+ {
+ const CDemoStringTables::items_t& Item = Table.items( itemid );
+
+ if( bIsActiveModifiersTable )
+ {
+ CDOTAModifierBuffTableEntry Entry;
+
+ if( Entry.ParseFromString( Item.data() ) )
+ {
+ std::string EntryStr = Entry.DebugString();
+ printf( " #%d %s", itemid, EntryStr.c_str() );
+ continue;
+ }
+ }
+ else if( bIsUserInfo && Item.data().size() == sizeof( player_info_s ) )
+ {
+ const player_info_s *pPlayerInfo = ( const player_info_s * )&Item.data()[ 0 ];
+
+ printf(" xuid:%lld name:%s userID:%d guid:%s friendsID:%d friendsName:%s fakeplayer:%d ishltv:%d filesDownloaded:%d\n",
+ pPlayerInfo->xuid, pPlayerInfo->name, pPlayerInfo->userID, pPlayerInfo->guid, pPlayerInfo->friendsID,
+ pPlayerInfo->friendsName, pPlayerInfo->fakeplayer, pPlayerInfo->ishltv, pPlayerInfo->filesDownloaded );
+ }
+
+ printf( " #%d '%s' (%d bytes)\n", itemid, Item.str().c_str(), (int)Item.data().size() );
+ }
+
+ for( int itemid = 0; itemid < Table.items_clientside().size(); itemid++ )
+ {
+ const CDemoStringTables::items_t& Item = Table.items_clientside( itemid );
+
+ printf( " %d. '%s' (%d bytes)\n", itemid, Item.str().c_str(), (int)Item.data().size() );
+ }
+ }
+
+ return true;
+}
+
+void CDemoFileDump::PrintDemoHeader( EDemoCommands DemoCommand, int tick, int size, int uncompressed_size )
+{
+ const std::string& DemoCommandName = EDemoCommands_Name( DemoCommand );
+
+ printf( "==== #%d: Tick:%d '%s' Size:%d UncompressedSize:%d ====\n",
+ m_nFrameNumber, tick, DemoCommandName.c_str(), size, uncompressed_size );
+}
+
+template < class DEMCLASS >
+void PrintDemoMessage( CDemoFileDump& Demo, bool bCompressed, int tick, int& size, int& uncompressed_size )
+{
+ DEMCLASS Msg;
+
+ if( Demo.m_demofile.ReadMessage( &Msg, bCompressed, &size, &uncompressed_size ) )
+ {
+ Demo.PrintDemoHeader( Msg.GetType(), tick, size, uncompressed_size );
+
+ Demo.MsgPrintf( Msg, size, "%s", Msg.DebugString().c_str() );
+ }
+}
+
+template <>
+void PrintDemoMessage<CDemoStringTables_t>( CDemoFileDump& Demo, bool bCompressed, int tick, int& size, int& uncompressed_size )
+{
+ CDemoStringTables_t Msg;
+
+ if( Demo.m_demofile.ReadMessage( &Msg, bCompressed, &size, &uncompressed_size ) )
+ {
+ Demo.PrintDemoHeader( Msg.GetType(), tick, size, uncompressed_size );
+
+ DumpDemoStringTable( Demo, Msg );
+ }
+}
+
+void CDemoFileDump::DoDump()
+{
+ bool bStopReading = false;
+
+ for( m_nFrameNumber = 0; !bStopReading; m_nFrameNumber++ )
+ {
+ int tick = 0;
+ int size = 0;
+ bool bCompressed;
+ int uncompressed_size = 0;
+
+ if( m_demofile.IsDone() )
+ break;
+
+ EDemoCommands DemoCommand = m_demofile.ReadMessageType( &tick, &bCompressed );
+
+ switch( DemoCommand )
+ {
+#define HANDLE_DemoMsg( _x ) case DEM_ ## _x: PrintDemoMessage< CDemo ## _x ## _t >( *this, bCompressed, tick, size, uncompressed_size ); break
+
+ HANDLE_DemoMsg( FileHeader );
+ HANDLE_DemoMsg( FileInfo );
+ HANDLE_DemoMsg( Stop );
+ HANDLE_DemoMsg( SyncTick );
+ HANDLE_DemoMsg( ConsoleCmd );
+ HANDLE_DemoMsg( SendTables );
+ HANDLE_DemoMsg( ClassInfo );
+ HANDLE_DemoMsg( StringTables );
+ HANDLE_DemoMsg( UserCmd );
+ HANDLE_DemoMsg( CustomDataCallbacks );
+ HANDLE_DemoMsg( CustomData );
+
+#undef HANDLE_DemoMsg
+
+ case DEM_FullPacket:
+ {
+ CDemoFullPacket_t FullPacket;
+
+ if( m_demofile.ReadMessage( &FullPacket, bCompressed, &size, &uncompressed_size ) )
+ {
+ PrintDemoHeader( DemoCommand, tick, size, uncompressed_size );
+
+ // Spew the stringtable
+ DumpDemoStringTable( *this, FullPacket.string_table() );
+
+ // Ok, now the packet.
+ DumpDemoPacket( FullPacket.packet().data() );
+ }
+ }
+ break;
+
+ case DEM_Packet:
+ case DEM_SignonPacket:
+ {
+ CDemoPacket_t Packet;
+
+ if( m_demofile.ReadMessage( &Packet, bCompressed, &size, &uncompressed_size ) )
+ {
+ PrintDemoHeader( DemoCommand, tick, size, uncompressed_size );
+
+ DumpDemoPacket( Packet.data() );
+ }
+ }
+ break;
+
+ default:
+ case DEM_Error:
+ bStopReading = true;
+ fatal_errorf( "Shouldn't ever get this demo command?!? %d\n", DemoCommand );
+ break;
+ }
+ }
+}
+
55 demofiledump.h
@@ -0,0 +1,55 @@
+//====== Copyright (c) 2012, Valve Corporation, All rights reserved. ========//
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are met:
+//
+// Redistributions of source code must retain the above copyright notice, this
+// list of conditions and the following disclaimer.
+// Redistributions in binary form must reproduce the above copyright notice,
+// this list of conditions and the following disclaimer in the documentation
+// and/or other materials provided with the distribution.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+// ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
+// LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+// CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+// SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+// INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+// ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
+// THE POSSIBILITY OF SUCH DAMAGE.
+//===========================================================================//
+
+#ifndef DEMOFILEDUMP_H
+#define DEMOFILEDUMP_H
+
+#include "demofile.h"
+
+#include "generated_proto/netmessages.pb.h"
+
+class CDemoFileDump
+{
+public:
+ CDemoFileDump() : m_nFrameNumber( 0 ) {}
+ ~CDemoFileDump() {}
+
+ bool Open( const char *filename );
+ void DoDump();
+
+public:
+ void DumpDemoPacket( const std::string& buf );
+ void DumpUserMessage( const void *parseBuffer, int BufferSize );
+ void PrintDemoHeader( EDemoCommands DemoCommand, int tick, int size, int uncompressed_size );
+ void MsgPrintf( const ::google::protobuf::Message& msg, int size, const char *fmt, ... );
+
+public:
+ CDemoFile m_demofile;
+ CSVCMsg_GameEventList m_GameEventList;
+
+ int m_nFrameNumber;
+};
+
+#endif // DEMOFILEDUMP_H
+
44 demoinfo2.cpp
@@ -0,0 +1,44 @@
+//====== Copyright (c) 2012, Valve Corporation, All rights reserved. ========//
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are met:
+//
+// Redistributions of source code must retain the above copyright notice, this
+// list of conditions and the following disclaimer.
+// Redistributions in binary form must reproduce the above copyright notice,
+// this list of conditions and the following disclaimer in the documentation
+// and/or other materials provided with the distribution.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+// ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
+// LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+// CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+// SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+// INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+// ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
+// THE POSSIBILITY OF SUCH DAMAGE.
+//===========================================================================//
+
+#include "demofiledump.h"
+
+int main( int argc, char *argv[] )
+{
+ CDemoFileDump DemoFileDump;
+
+ if( argc <= 1 )
+ {
+ printf( "demoinfo2_public.exe filename.dem\n" );
+ exit( 0 );
+ }
+
+ if( DemoFileDump.Open( argv[ 1 ] ) )
+ {
+ DemoFileDump.DoDump();
+ }
+
+ return 1;
+}
+
86 dota_commonmessages.proto
@@ -0,0 +1,86 @@
+//====== Copyright (c) 2012, Valve Corporation, All rights reserved. ========//
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are met:
+//
+// Redistributions of source code must retain the above copyright notice, this
+// list of conditions and the following disclaimer.
+// Redistributions in binary form must reproduce the above copyright notice,
+// this list of conditions and the following disclaimer in the documentation
+// and/or other materials provided with the distribution.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+// ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
+// LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+// CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+// SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+// INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+// ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
+// THE POSSIBILITY OF SUCH DAMAGE.
+//===========================================================================//
+//
+// Purpose: The file defines our Google Protocol Buffers which are used in over
+// the wire messages for the Source engine.
+//
+//=============================================================================
+
+// We care more about speed than code size
+option optimize_for = SPEED;
+
+// We don't use the service generation functionality
+option cc_generic_services = false;
+
+
+//
+// STYLE NOTES:
+//
+// Use CamelCase CMsgMyMessageName style names for messages.
+//
+// Use lowercase _ delimited names like my_steam_id for field names, this is non-standard for Steam,
+// but plays nice with the Google formatted code generation.
+//
+// Try not to use required fields ever. Only do so if you are really really sure you'll never want them removed.
+// Optional should be preffered as it will make versioning easier and cleaner in the future if someone refactors
+// your message and wants to remove or rename fields.
+//
+// Use fixed64 for JobId_t, GID_t, or SteamID. This is appropriate for any field that is normally
+// going to be larger than 2^56. Otherwise use int64 for 64 bit values that are frequently smaller
+// than 2^56 as it will safe space on the wire in those cases.
+//
+// Similar to fixed64, use fixed32 for RTime32 or other 32 bit values that are frequently larger than
+// 2^28. It will safe space in those cases, otherwise use int32 which will safe space for smaller values.
+// An exception to this rule for RTime32 is if the value will frequently be zero rather than set to an actual
+// time.
+//
+
+import "google/protobuf/descriptor.proto";
+
+// for CMsgVector, etc.
+import "netmessages.proto";
+
+//=============================================================================
+// Dota Common Messages
+//=============================================================================
+
+message CDOTAMsg_LocationPing
+{
+ optional int32 x = 1;
+ optional int32 y = 2;
+ optional int32 target = 3;
+ optional bool direct_ping = 4;
+}
+
+message CDOTAMsg_MapLine
+{
+ optional int32 x = 1;
+ optional int32 y = 2;
+ optional bool initial = 3;
+}
+
+
+//=============================================================================
+
+
99 dota_modifiers.proto
@@ -0,0 +1,99 @@
+//====== Copyright (c) 2012, Valve Corporation, All rights reserved. ========//
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are met:
+//
+// Redistributions of source code must retain the above copyright notice, this
+// list of conditions and the following disclaimer.
+// Redistributions in binary form must reproduce the above copyright notice,
+// this list of conditions and the following disclaimer in the documentation
+// and/or other materials provided with the distribution.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+// ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
+// LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+// CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+// SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+// INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+// ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
+// THE POSSIBILITY OF SUCH DAMAGE.
+//===========================================================================//
+//
+// Purpose: The file defines our Google Protocol Buffers which are used in over
+// the wire messages for the Source engine.
+//
+//=============================================================================
+
+// We care more about speed than code size
+option optimize_for = SPEED;
+
+// We don't use the service generation functionality
+option cc_generic_services = false;
+
+
+//
+// STYLE NOTES:
+//
+// Use CamelCase CMsgMyMessageName style names for messages.
+//
+// Use lowercase _ delimited names like my_steam_id for field names, this is non-standard for Steam,
+// but plays nice with the Google formatted code generation.
+//
+// Try not to use required fields ever. Only do so if you are really really sure you'll never want them removed.
+// Optional should be preffered as it will make versioning easier and cleaner in the future if someone refactors
+// your message and wants to remove or rename fields.
+//
+// Use fixed64 for JobId_t, GID_t, or SteamID. This is appropriate for any field that is normally
+// going to be larger than 2^56. Otherwise use int64 for 64 bit values that are frequently smaller
+// than 2^56 as it will safe space on the wire in those cases.
+//
+// Similar to fixed64, use fixed32 for RTime32 or other 32 bit values that are frequently larger than
+// 2^28. It will safe space in those cases, otherwise use int32 which will safe space for smaller values.
+// An exception to this rule for RTime32 is if the value will frequently be zero rather than set to an actual
+// time.
+//
+
+import "google/protobuf/descriptor.proto";
+
+// for CMsgVector, etc.
+import "netmessages.proto";
+
+enum DOTA_MODIFIER_ENTRY_TYPE
+{
+ DOTA_MODIFIER_ENTRY_TYPE_ACTIVE = 1;
+ DOTA_MODIFIER_ENTRY_TYPE_REMOVED = 2;
+};
+
+message CDOTAModifierBuffTableEntry
+{
+ required DOTA_MODIFIER_ENTRY_TYPE entry_type = 1;
+ required int32 parent = 2; // ehandle to parent owner
+ required int32 index = 3; // index into the modifier list on the entity (local to each entity)
+ required int32 serial_num = 4; // global serial number
+
+ optional int32 name = 5; // index into the modifier name string table
+ optional int32 ability_level = 6;
+ optional int32 stack_count = 7;
+ optional float creation_time = 8;
+ optional float duration = 9 [ default = -1.0 ];
+ optional int32 caster = 10;
+ optional int32 ability = 11;
+
+ // optional custom data
+ optional int32 armor = 12; // used by invoker
+ optional float fade_time = 13; // used by invisiblity
+ optional bool subtle = 14; // used by invisiblity
+ optional float channel_time = 15; // used by teleport
+ optional CMsgVector v_start = 16; // used by teleport
+ optional CMsgVector v_end = 17; // used by teleport
+ optional string portal_loop_appear = 18; // used by teleport
+ optional string portal_loop_disappear = 19; // used by teleport
+ optional string hero_loop_appear = 20; // used by teleport
+ optional string hero_loop_disappear = 21; // used by teleport
+ optional int32 movement_speed = 22; // used by smoke of deceit
+ optional bool aura = 23;
+}
+
538 dota_usermessages.proto
@@ -0,0 +1,538 @@
+//====== Copyright (c) 2012, Valve Corporation, All rights reserved. ========//
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are met:
+//
+// Redistributions of source code must retain the above copyright notice, this
+// list of conditions and the following disclaimer.
+// Redistributions in binary form must reproduce the above copyright notice,
+// this list of conditions and the following disclaimer in the documentation
+// and/or other materials provided with the distribution.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+// ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
+// LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+// CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+// SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+// INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+// ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
+// THE POSSIBILITY OF SUCH DAMAGE.
+//===========================================================================//
+//
+// Purpose: The file defines our Google Protocol Buffers which are used in over
+// the wire messages for the Source engine.
+//
+//=============================================================================
+
+// We care more about speed than code size
+option optimize_for = SPEED;
+
+// We don't use the service generation functionality
+option cc_generic_services = false;
+
+
+//
+// STYLE NOTES:
+//
+// Use CamelCase CMsgMyMessageName style names for messages.
+//
+// Use lowercase _ delimited names like my_steam_id for field names, this is non-standard for Steam,
+// but plays nice with the Google formatted code generation.
+//
+// Try not to use required fields ever. Only do so if you are really really sure you'll never want them removed.
+// Optional should be preffered as it will make versioning easier and cleaner in the future if someone refactors
+// your message and wants to remove or rename fields.
+//
+// Use fixed64 for JobId_t, GID_t, or SteamID. This is appropriate for any field that is normally
+// going to be larger than 2^56. Otherwise use int64 for 64 bit values that are frequently smaller
+// than 2^56 as it will safe space on the wire in those cases.
+//
+// Similar to fixed64, use fixed32 for RTime32 or other 32 bit values that are frequently larger than
+// 2^28. It will safe space in those cases, otherwise use int32 which will safe space for smaller values.
+// An exception to this rule for RTime32 is if the value will frequently be zero rather than set to an actual
+// time.
+//
+
+import "google/protobuf/descriptor.proto";
+
+// for CMsgVector, etc.
+import "netmessages.proto";
+
+// for Activity
+import "ai_activity.proto";
+
+// for structures shared between user and client messages
+import "dota_commonmessages.proto";
+
+//=============================================================================
+// Dota User Messages
+//=============================================================================
+
+enum EDotaUserMessages
+{
+ DOTA_UM_AddUnitToSelection = 64;
+ DOTA_UM_AIDebugLine = 65;
+ DOTA_UM_ChatEvent = 66;
+ DOTA_UM_CombatHeroPositions = 67;
+ DOTA_UM_CombatLogData = 68;
+ DOTA_UM_CombatLogShowDeath = 70;
+ DOTA_UM_CreateLinearProjectile = 71;
+ DOTA_UM_DestroyLinearProjectile = 72;
+ DOTA_UM_DodgeTrackingProjectiles = 73;
+ DOTA_UM_GlobalLightColor = 74;
+ DOTA_UM_GlobalLightDirection = 75;
+ DOTA_UM_InvalidCommand = 76;
+ DOTA_UM_LocationPing = 77;
+ DOTA_UM_MapLine = 78;
+ DOTA_UM_MiniKillCamInfo = 79;
+ DOTA_UM_MinimapDebugPoint = 80;
+ DOTA_UM_MinimapEvent = 81;
+ DOTA_UM_NevermoreRequiem = 82;
+ DOTA_UM_OverheadEvent = 83;
+ DOTA_UM_SetNextAutobuyItem = 84;
+ DOTA_UM_SharedCooldown = 85;
+ DOTA_UM_SpectatorPlayerClick = 86;
+ DOTA_UM_TutorialTipInfo = 87;
+ DOTA_UM_UnitEvent = 88;
+ DOTA_UM_ParticleManager = 89;
+ DOTA_UM_BotChat = 90;
+ DOTA_UM_HudError = 91;
+ DOTA_UM_ItemPurchased = 92;
+ DOTA_UM_Ping = 93;
+ DOTA_UM_ItemFound = 94;
+}
+
+//=============================================================================
+
+message CDOTAUserMsg_AIDebugLine
+{
+ optional string message = 1;
+}
+
+message CDOTAUserMsg_Ping
+{
+ optional string message = 1;
+}
+
+enum DOTA_CHAT_MESSAGE
+{
+ CHAT_MESSAGE_INVALID = -1;
+
+ CHAT_MESSAGE_HERO_KILL = 0;
+ CHAT_MESSAGE_HERO_DENY = 1;
+ CHAT_MESSAGE_BARRACKS_KILL = 2;
+ CHAT_MESSAGE_TOWER_KILL = 3;
+ CHAT_MESSAGE_TOWER_DENY = 4;
+ CHAT_MESSAGE_FIRSTBLOOD = 5;
+ CHAT_MESSAGE_STREAK_KILL = 6;
+ CHAT_MESSAGE_BUYBACK = 7;
+ CHAT_MESSAGE_AEGIS = 8;
+ CHAT_MESSAGE_ROSHAN_KILL = 9;
+ CHAT_MESSAGE_COURIER_LOST = 10;
+ CHAT_MESSAGE_COURIER_RESPAWNED = 11;
+ CHAT_MESSAGE_GLYPH_USED = 12;
+ CHAT_MESSAGE_ITEM_PURCHASE = 13;
+ CHAT_MESSAGE_CONNECT = 14;
+ CHAT_MESSAGE_DISCONNECT = 15;
+ CHAT_MESSAGE_DISCONNECT_WAIT_FOR_RECONNECT = 16;
+ CHAT_MESSAGE_DISCONNECT_TIME_REMAINING = 17;
+ CHAT_MESSAGE_DISCONNECT_TIME_REMAINING_PLURAL = 18;
+ CHAT_MESSAGE_RECONNECT = 19;
+ CHAT_MESSAGE_ABANDON = 20;
+ CHAT_MESSAGE_SAFE_TO_LEAVE = 21;
+ CHAT_MESSAGE_RUNE_PICKUP = 22;
+ CHAT_MESSAGE_RUNE_BOTTLE = 23;
+ CHAT_MESSAGE_INTHEBAG = 24;
+ CHAT_MESSAGE_SECRETSHOP = 25;
+ CHAT_MESSAGE_ITEM_AUTOPURCHASED = 26;
+ CHAT_MESSAGE_ITEMS_COMBINED = 27;
+ CHAT_MESSAGE_SUPER_CREEPS = 28;
+ CHAT_MESSAGE_CANT_USE_ACTION_ITEM = 29;
+ CHAT_MESSAGE_CHARGES_EXHAUSTED = 30;
+ CHAT_MESSAGE_CANTPAUSE = 31;
+ CHAT_MESSAGE_NOPAUSESLEFT = 32;
+ CHAT_MESSAGE_CANTPAUSEYET = 33;
+ CHAT_MESSAGE_PAUSED = 34;
+ CHAT_MESSAGE_UNPAUSE_COUNTDOWN = 35;
+ CHAT_MESSAGE_UNPAUSED = 36;
+ CHAT_MESSAGE_AUTO_UNPAUSED = 37;
+ CHAT_MESSAGE_YOUPAUSED = 38;
+ CHAT_MESSAGE_CANTUNPAUSETEAM = 39;
+ CHAT_MESSAGE_SAFE_TO_LEAVE_ABANDONER = 40;
+ CHAT_MESSAGE_VOICE_TEXT_BANNED = 41;
+ CHAT_MESSAGE_SPECTATORS_WATCHING_THIS_GAME = 42;
+ CHAT_MESSAGE_REPORT_REMINDER = 43;
+ CHAT_MESSAGE_ECON_ITEM = 44;
+ CHAT_MESSAGE_TAUNT = 45;
+ CHAT_MESSAGE_RANDOM = 46;
+ CHAT_MESSAGE_RD_TURN = 47;
+}
+
+message CDOTAUserMsg_ChatEvent
+{
+ required DOTA_CHAT_MESSAGE type = 1;
+
+ optional uint32 value = 2;
+
+ // ugh
+ optional sint32 playerid_1 = 3 [ default = -1 ];
+ optional sint32 playerid_2 = 4 [ default = -1 ];
+ optional sint32 playerid_3 = 5 [ default = -1 ];
+ optional sint32 playerid_4 = 6 [ default = -1 ];
+ optional sint32 playerid_5 = 7 [ default = -1 ];
+ optional sint32 playerid_6 = 8 [ default = -1 ];
+}
+
+message CDOTAUserMsg_CombatLogData
+{
+ optional uint32 type = 1;
+ optional uint32 target_name = 2;
+ optional uint32 attacker_name = 3;
+ optional bool attacker_illusion = 4;
+ optional bool target_illusion = 5;
+ optional uint32 inflictor_name = 6;
+ optional int32 value = 7;
+ optional int32 health = 8;
+ optional float time = 9;
+}
+
+message CDOTAUserMsg_CombatLogShowDeath
+{
+}
+
+message CDOTAUserMsg_BotChat
+{
+ optional uint32 player_id = 1;
+ optional string format = 2;
+ optional string message = 3;
+ optional string target = 4;
+}
+
+message CDOTAUserMsg_CombatHeroPositions
+{
+ optional uint32 index = 1;
+ optional int32 time = 2;
+ optional CMsgVector2D world_pos = 3;
+ optional int32 health = 4;
+}
+
+message CDOTAUserMsg_MiniKillCamInfo
+{
+ message Attacker
+ {
+ optional uint32 attacker = 1;
+ optional int32 total_damage = 2;
+
+ message Ability
+ {
+ optional uint32 ability = 1;
+ optional int32 damage = 2;
+ }
+ repeated Ability abilities = 3;
+ }
+ repeated Attacker attackers = 1;
+}
+
+message CDOTAUserMsg_GlobalLightColor
+{
+ optional uint32 color = 1;
+ optional float duration = 2;
+}
+
+message CDOTAUserMsg_GlobalLightDirection
+{
+ optional CMsgVector direction = 1;
+ optional float duration = 2;
+}
+
+message CDOTAUserMsg_LocationPing
+{
+ optional uint32 player_id = 1;
+ optional CDOTAMsg_LocationPing location_ping = 2;
+}
+
+message CDOTAUserMsg_MinimapEvent
+{
+ optional int32 event_type = 1;
+ optional int32 entity_handle = 2;
+ optional int32 x = 3;
+ optional int32 y = 4;
+ optional int32 duration = 5;
+}
+
+message CDOTAUserMsg_MapLine
+{
+ optional int32 player_id = 1;
+ optional CDOTAMsg_MapLine mapline = 2;
+}
+
+message CDOTAUserMsg_MinimapDebugPoint
+{
+ optional CMsgVector location = 1;
+ optional uint32 color = 2;
+ optional int32 size = 3;
+ optional float duration = 4;
+}
+
+message CDOTAUserMsg_CreateLinearProjectile
+{
+ optional CMsgVector origin = 1;
+ optional CMsgVector2D velocity = 2;
+ optional int32 latency = 3;
+ optional int32 entindex = 4;
+ optional int32 particle_index = 5;
+ optional int32 handle = 6;
+}
+
+message CDOTAUserMsg_DestroyLinearProjectile
+{
+ optional int32 handle = 1;
+}
+
+message CDOTAUserMsg_DodgeTrackingProjectiles
+{
+ required int32 entindex = 1;
+}
+
+message CDOTAUserMsg_SpectatorPlayerClick
+{
+ required int32 entindex = 1;
+ optional int32 order_type = 2;
+ optional int32 target_index = 3;
+}
+
+message CDOTAUserMsg_NevermoreRequiem
+{
+ optional int32 entity_handle = 1;
+ optional int32 lines = 2;
+ optional CMsgVector origin = 3;
+}
+
+message CDOTAUserMsg_InvalidCommand
+{
+ optional string message = 1;
+}
+
+message CDOTAUserMsg_HudError
+{
+ optional int32 order_id = 1;
+}
+
+message CDOTAUserMsg_SharedCooldown
+{
+ optional int32 entindex = 1;
+ optional string name = 2;
+ optional float cooldown = 3;
+ optional int32 name_index = 4;
+}
+
+message CDOTAUserMsg_SetNextAutobuyItem
+{
+ optional string name = 1;
+}
+
+enum EDotaEntityMessages
+{
+ DOTA_UNIT_SPEECH = 0;
+ DOTA_UNIT_SPEECH_MUTE = 1;
+ DOTA_UNIT_ADD_GESTURE = 2;
+ DOTA_UNIT_REMOVE_GESTURE = 3;
+ DOTA_UNIT_REMOVE_ALL_GESTURES = 4;
+ DOTA_UNIT_FADE_GESTURE = 6;
+}
+
+message CDOTAUserMsg_UnitEvent
+{
+ required EDotaEntityMessages msg_type = 1;
+ required int32 entity_index = 2;
+
+ message Speech
+ {
+ optional int32 concept = 1;
+ optional string response = 2;
+ optional int32 recipient_type = 3;
+ optional int32 level = 4;
+ }
+
+ optional Speech speech = 3;
+
+ message SpeechMute
+ {
+ optional float delay = 1 [default = 0.5];
+ }
+
+ optional SpeechMute speech_mute = 4;
+
+ message AddGesture
+ {
+ optional Activity activity = 1;
+ optional int32 slot = 2;
+ optional float fade_in = 3 [default = 0];
+ optional float fade_out = 4 [default = 0.1];
+ }
+
+ optional AddGesture add_gesture = 5;
+
+ message RemoveGesture
+ {
+ optional Activity activity = 1;
+ }
+
+ optional RemoveGesture remove_gesture = 6;
+
+ message BloodImpact
+ {
+ optional int32 scale = 1;
+ optional int32 x_normal = 2;
+ optional int32 y_normal = 3;
+ }
+
+ optional BloodImpact blood_impact = 7;
+
+ message FadeGesture
+ {
+ optional Activity activity = 1;
+ }
+
+ optional FadeGesture fade_gesture = 8;
+}
+
+message CDOTAUserMsg_ItemPurchased
+{
+ optional int32 item_index = 1;
+}
+
+message CDOTAUserMsg_ItemFound
+{
+ optional int32 player = 1;
+ optional int32 quality = 2;
+ optional int32 rarity = 3;
+ optional int32 method = 4;
+ optional int32 itemdef = 5;
+}
+
+enum DOTA_PARTICLE_MESSAGE
+{
+ DOTA_PARTICLE_MANAGER_EVENT_CREATE = 0;
+ DOTA_PARTICLE_MANAGER_EVENT_UPDATE = 1;
+ DOTA_PARTICLE_MANAGER_EVENT_UPDATE_FORWARD = 2;
+ DOTA_PARTICLE_MANAGER_EVENT_UPDATE_ORIENTATION = 3;
+ DOTA_PARTICLE_MANAGER_EVENT_UPDATE_FALLBACK = 4;
+ DOTA_PARTICLE_MANAGER_EVENT_UPDATE_ENT = 5;
+ DOTA_PARTICLE_MANAGER_EVENT_UPDATE_OFFSET = 6;
+ DOTA_PARTICLE_MANAGER_EVENT_DESTROY = 7;
+ DOTA_PARTICLE_MANAGER_EVENT_DESTROY_INVOLVING = 8;
+ DOTA_PARTICLE_MANAGER_EVENT_RELEASE = 9;
+ DOTA_PARTICLE_MANAGER_EVENT_LATENCY = 10;
+};
+
+message CDOTAUserMsg_ParticleManager
+{
+ message ReleaseParticleIndex
+ {
+ }
+ message CreateParticle
+ {
+ optional int32 particle_name_index = 1;
+ optional int32 attach_type = 2;
+ optional int32 entity_handle = 3;
+ }
+ message DestroyParticle
+ {
+ optional bool destroy_immediately = 1;
+ }
+ message DestroyParticleInvolving
+ {
+ optional bool destroy_immediately = 1;
+ optional int32 entity_handle = 3;
+ }
+ message UpdateParticle
+ {
+ optional int32 control_point = 1;
+ optional CMsgVector position = 2;
+ }
+ message UpdateParticleFwd
+ {
+ optional int32 control_point = 1;
+ optional CMsgVector forward = 2;
+ }
+ message UpdateParticleOrient
+ {
+ optional int32 control_point = 1;
+ optional CMsgVector forward = 2;
+ optional CMsgVector right = 3;
+ optional CMsgVector up = 4;
+ }
+ message UpdateParticleFallback
+ {
+ optional int32 control_point = 1;
+ optional CMsgVector position = 2;
+ }
+ message UpdateParticleOffset
+ {
+ optional int32 control_point = 1;
+ optional CMsgVector origin_offset = 2;
+ }
+ message UpdateParticleEnt
+ {
+ optional int32 control_point = 1;
+ optional int32 entity_handle = 2;
+ optional int32 attach_type = 3;
+ optional int32 attachment = 4;
+ optional CMsgVector fallback_position = 5;
+ }
+ message UpdateParticleLatency
+ {
+ optional int32 player_latency = 1;
+ optional int32 tick = 2;
+ }
+
+ required DOTA_PARTICLE_MESSAGE type = 1;
+ required uint32 index = 2;
+
+