PDA

View Full Version : structvis.pl patched to work with 05/20 live



tanner
05-20-2005, 03:20 PM
Took ksmith's structvis.pl patched it to work on 05/20 live packets.

There are a couple issue that I need to speak with ksmith about, so do -not- just cut-n-paste the PP from everquest.h into structvis, the PP in structvis is hand tweaked.



#!/usr/bin/perl -w

use strict;

my $charProfile = << 'END'
/*
** Player Profile
** Length: 18496 Octets
** OpCode: CharProfileCode
*/
struct charProfileStruct
{
/*0000*/ uint32_t checksum; //
/*0004*/ char name[64]; // Name of player
/*0068*/ char lastName[32]; // Last name of player
/*0100*/ uint32_t gender; // Player Gender - 0 Male, 1 Female
/*0104*/ uint32_t race; // Player race
/*0108*/ uint32_t class_; // Player class
/*0112*/ uint32_t unknown0112; // *** Placeholder
/*0116*/ uint32_t level; // Level of player (might be one byte)
/*0120*/ uint32_t bind_zone_id[5]; // Bind info (zone, x, y, z, heading)
/*0140*/ float bind_x[5]; // 0 is normal bind
/*0160*/ float bind_y[5]; // 5 is some weird point in newbie zone
/*0180*/ float bind_z[5]; // (which is secondary bind for wiz/dru?)
/*0200*/ float bind_heading[5]; // Unused slots show newbie bind
/*0220*/ uint32_t deity; // deity
/*0224*/ int32_t guildID; // guildID
/*0228*/ uint32_t birthdayTime; // character birthday
/*0232*/ uint32_t lastSaveTime; // character last save time
/*0236*/ uint32_t timePlayedMin; // time character played
/*0240*/ uint8_t pvp; // 1=pvp, 0=not pvp
/*0241*/ uint8_t level1; // Level of Player
/*0242*/ uint8_t anon; // 2=roleplay, 1=anon, 0=not anon
/*0243*/ uint8_t gm; // 0=no, 1=yes
/*0244*/ int8_t guildstatus; // 0=member, 1=officer, 2=guildleader
/*0245*/ uint8_t unknown0245[7]; // *** Placeholder
/*0252*/ uint32_t intoxication; // Alcohol level (in ticks till sober?)
/*0256*/ uint32_t spellSlotRefresh[9]; // Refresh time (millis)
/*0292*/ uint8_t unknown0292[8]; // *** Placeholder
/*0300*/ uint8_t haircolor; // Player hair color
/*0301*/ uint8_t beardcolor; // Player beard color
/*0302*/ uint8_t eyecolor1; // Player left eye color
/*0303*/ uint8_t eyecolor2; // Player right eye color
/*0304*/ uint8_t hairstyle; // Player hair style
/*0305*/ uint8_t beard; // Player beard type
/*0306*/ uint8_t unknown0302[6]; // *** Placeholder
/*0312*/ uint32_t item_material[9]; // Item texture/material of worn items
/*0348*/ uint8_t unknown0348[48]; // *** Placeholder
/*0396*/ Color_Struct item_tint[9]; // RR GG BB 00
/*0432*/ AA_Array aa_array[240]; // AAs
/*2352*/ char servername[32]; // server the char was created on
/*2384*/ char title[32]; // Current character title
/*2416*/ char suffix[32]; // Current character suffix
/*2448*/ uint8_t unknown2448[4]; // *** Placeholder
/*2452*/ uint32_t exp; // Current Experience
/*2456*/ uint32_t unknown2456; // *** Placeholder
/*2460*/ uint32_t points; // Unspent Practice points
/*2464*/ uint32_t MANA; // Current MANA
/*2468*/ uint32_t curHp; // Current HP without +HP equipment
/*2472*/ uint32_t unknown1512; // 0x05
/*2476*/ uint32_t STR; // Strength
/*2480*/ uint32_t STA; // Stamina
/*2484*/ uint32_t CHA; // Charisma
/*2488*/ uint32_t DEX; // Dexterity
/*2492*/ uint32_t INT; // Intelligence
/*2496*/ uint32_t AGI; // Agility
/*2500*/ uint32_t WIS; // Wisdom
/*2504*/ uint8_t face; // Player face
/*2505*/ uint8_t unknown2505[47]; // *** Placeholder
/*2552*/ uint8_t languages[25]; // List of languages (MAX_KNOWN_LANGS)
/*2577*/ uint8_t unknown2577[7]; // All 0x00 (language buffer?)
/*2584*/ int32_t sSpellBook[400]; // List of the Spells in spellbook
/*4184*/ uint8_t unknown4184[448]; // all 0xff after last spell
/*4632*/ int32_t sMemSpells[9]; // List of spells memorized
/*4668*/ uint8_t unknown4668[32]; // *** Placeholder
/*4700*/ float x; // Players x position
/*4704*/ float y; // Players y position
/*4708*/ float z; // Players z position
/*4712*/ float heading; // Players heading
/*4716*/ uint8_t unknown4716[4]; // *** Placeholder
/*4720*/ uint32_t platinum; // Platinum Pieces on player
/*4724*/ uint32_t gold; // Gold Pieces on player
/*4728*/ uint32_t silver; // Silver Pieces on player
/*4732*/ uint32_t copper; // Copper Pieces on player
/*4736*/ uint32_t platinum_bank; // Platinum Pieces in Bank
/*4740*/ uint32_t gold_bank; // Gold Pieces in Bank
/*4744*/ uint32_t silver_bank; // Silver Pieces in Bank
/*4748*/ uint32_t copper_bank; // Copper Pieces in Bank
/*4752*/ uint32_t platinum_cursor; // Platinum Pieces on cursor
/*4756*/ uint32_t gold_cursor; // Gold Pieces on cursor
/*4760*/ uint32_t silver_cursor; // Silver Pieces on cursor
/*4764*/ uint32_t copper_cursor; // Copper Pieces on cursor
/*4768*/ uint32_t platinum_shared; // Shared platinum pieces
/*4772*/ uint8_t unknown4772[24]; // Unknown - all zero
/*4796*/ uint32_t skills[75]; // List of skills (MAX_KNOWN_SKILLS)
/*5096*/ uint8_t unknown5096[312]; // *** Placeholder
/*5408*/ uint32_t autosplit; // 0 = off, 1 = on
/*5412*/ uint8_t unknown5412[8]; // *** Placeholder
/*5420*/ uint32_t saveCounter; // Number of times your char has saved
/*5424*/ uint8_t unknown5424[28]; // *** Placeholder
/*5452*/ uint32_t expansions; // Bitmask for expansions
/*5456*/ uint32_t toxicity; // Potion Toxicity (15=too toxic, each potion adds 3)
/*5460*/ uint8_t unknown5460[16]; // *** Placeholder
/*5476*/ uint32_t hunger; // Food (ticks till next eat)
/*5480*/ uint32_t thirst; // Drink (ticks till next drink)
/*5484*/ uint8_t unknown5484[20]; // *** Placeholder
/*5504*/ uint16_t zoneId; // see zones.h
/*5506*/ uint16_t zoneInstance; // Instance id
/*5508*/ spellBuff buffs[25]; // Buffs currently on the player
/*6008*/ char groupMembers[384];// all the members in group, including self
/*6392*/ uint8_t unknown6392[668]; // *** Placeholder
/*7060*/ uint32_t ldon_guk_points; // Earned GUK points
/*7064*/ uint32_t ldon_mir_points; // Earned MIR points
/*7068*/ uint32_t ldon_mmc_points; // Earned MMC points
/*7072*/ uint32_t ldon_ruj_points; // Earned RUJ points
/*7076*/ uint32_t ldon_tak_points; // Earned TAK points
/*7080*/ uint32_t ldon_avail_points; // Available LDON points
/*7084*/ uint8_t unknown6124[112]; // *** Placeholder
/*7196*/ uint32_t tributeTime; // Time remaining on tribute (millisecs)
/*7200*/ uint32_t unknown6240; // *** Placeholder
/*7204*/ uint32_t careerTribute; // Total favor points for this char
/*7208*/ uint32_t unknown6248; // *** Placeholder
/*7212*/ uint32_t currentTribute; // Current tribute points
/*7216*/ uint32_t unknown6256; // *** Placeholder
/*7220*/ uint32_t tributeActive; // 0 = off, 1=on
/*7224*/ TributeStruct tributes[5]; // Current tribute loadout
/*7264*/ uint32_t disciplines[50]; // Known disciplines
/*7464*/ uint8_t unknown6504[440]; // *** Placeholder
/*7904*/ uint32_t endurance; // Current endurance
/*7908*/ uint32_t expGroupLeadAA; // Current group lead AA exp (0-1000)
/*7912*/ uint32_t expRaidLeadAA; // Current raid lead AA exp (0-2000)
/*7916*/ uint32_t groupLeadAAUnspent; // Unspent group lead AA points
/*7920*/ uint32_t raidLeadAAUnspent; // Unspent raid lead AA points
/*7924*/ uint32_t leadershipAAs[32]; // Leader AA ranks
/*8052*/ uint8_t unknown7092[132]; // *** Placeholder
/*8184*/ uint32_t airRemaining; // Air supply (seconds)
/*8188*/ uint8_t unknown7228[4608]; // *** Placeholder
/*12796*/ uint32_t aa_spent; // Number of spent AA points
/*12800*/ uint32_t expAA; // Exp earned in current AA point
/*12804*/ uint32_t aa_unspent; // Unspent AA points
/*12808*/ uint8_t unknown11848[36]; // *** Placeholder
/*12844*/ BandolierStruct bandoliers[4]; // bandolier contents
/*14124*/ uint8_t unknown13164[5120]; // *** Placeholder
/*19244*/ InlineItem potionBelt[4]; // potion belt
/*19532*/ uint8_t unknown18572[8]; // *** Placeholder
/*19540*/ uint32_t currentRadCrystals; // Current count of radiant crystals
/*19544*/ uint32_t careerRadCrystals; // Total count of radiant crystals ever
/*19548*/ uint32_t currentEbonCrystals;// Current count of ebon crystals
/*19552*/ uint32_t careerEbonCrystals; // Total count of ebon crystals ever
/*19556*/ uint32_t unknown18596; // *** Placeholder
}; /* 19560 */
END
;

# load struct
my @struct = ();

while ($charProfile =~ /^(.*)$/mcg) {
my $line = $1;
if ($line =~ /^.*\s(\S+)\s+(\S+)\;/) {
my $type = $1;
my $name = $2;

push(@struct, { 'name' => $name, 'type' => $type } );
}
}

# load data
my @data = ();
my $goodpacket = 0;
my $timestamp = "";

open(PACKET, "./zone.log");
while (my $line = <PACKET>) {
# Sep 07 2004 23:13:30:968 [Decoded] [Server->Client] [Size: 11120]
# [OPCode: 0x006b]

# empty line is end of packet
if ($line =~ /^$/) {
if ($goodpacket) {
print "\n$timestamp\n";
decode(@data);
}

$goodpacket = 0;
@data = ();
}

# looking for a timestamp
if ($line =~ /^[A-Z][a-z]{2} \d{2} \d{4}/) {
$timestamp = $line;
}

# looking for a charprofile packet
if ($line =~ /^\[OPCode: 0x1f1c\]/) {
$goodpacket = 1;
}

if ($goodpacket && $line =~ /^\d+ \| ([0-9a-f ]+) \|/) {
$line = $1;
while ($line =~ /([0-9a-f]{2})/mcg) {
push(@data, hex($1));
}
}
}
close(PACKET);


sub decode {

@data = @_;
print "Loaded ". ($#data + 1) ." bytes.\n";

# fill in struct
my $offset = 0;
foreach my $i (0..$#struct) {
my $type = $struct[$i]{'type'};
my $name = $struct[$i]{'name'};
my $alen = 0;
my $size = 0;

if ($name =~ /(\S+)\[([0-9]+)\]/) {
$name = $1;
$alen = $2 - 1;
}

if ($alen > 0) {
printf("%04d: %s\t%s[%d]: ", $offset, $type, $name, $alen + 1);
} else {
printf("%04d: %s\t%s: ", $offset, $type, $name);
}

if ($type eq "uint8_t") {
$size = 1;
foreach my $j (0..$alen) {
print unpack("C", pack("C", $data[$offset + $j * $size])) ." ";
}

} elsif ($type eq "uint16_t") {
$size = 2;
foreach my $j (0..$alen) {
print unpack("S", pack("CC", $data[$offset + $j * $size], $data[$offset + 1 + $j * $size])) ." ";
}

} elsif ($type eq "uint32_t") {
$size = 4;
foreach my $j (0..$alen) {
print unpack("L", pack("CCCC", $data[$offset + $j * $size], $data[$offset + 1 + $j * $size],
$data[$offset + 2 + $j * $size], $data[$offset + 3 + $j * $size])) ." ";
}

} elsif ($type eq "int8_t") {
$size = 1;
foreach my $j (0..$alen) {
print unpack("c", pack("C", $data[$offset + $j * $size])) ." ";
}

} elsif ($type eq "int16_t") {
$size = 2;
foreach my $j (0..$alen) {
print unpack("s", pack("CC", $data[$offset + $j * $size], $data[$offset + 1 + $j * $size])) ." ";
}

} elsif ($type eq "int32_t") {
$size = 4;
foreach my $j (0..$alen) {
print unpack("l", pack("CCCC", $data[$offset + $j * $size], $data[$offset + 1 + $j * $size],
$data[$offset + 2 + $j * $size], $data[$offset + 3 + $j * $size])) ." ";
}

} elsif ($type eq "float") {
$size = 4;
foreach my $j (0..$alen) {
my $num = pack("CCCC", $data[$offset + 0], $data[$offset + 1],
$data[$offset + 2], $data[$offset + 3]);

print unpack("f", $num) ." ";
}

} elsif ($type eq "char") {
foreach my $j (0..$alen) {
if ($data[$offset + $j] > 0x1f && $data[$offset + $j] < 0x80) {
printf("%c", $data[$offset+$j]);
} else {
print ".";
}
}
$size = 1;

} elsif ($type eq "Color_Struct") {
# B R G A
$size = 4;
} elsif ($type eq "AA_Array") {
# AA value
$size = 8;
} elsif ($type eq "spellBuff") {
# unknown0000 level unknown0002 unknown003 slotid duration effect playerId
$size = 20;
} elsif ($type eq "TributeStruct") {
# tribute value
$size = 8;
} elsif ($type eq "BandolierStruct") {
# char[32] mainHand offHand range ammo
$size = 320;
} elsif ($type eq "InlineItem") {
# itemId icon itemName[64]
$size = 72;
} else {
die "Unknown type: $type\n";

}

print "\n";

$offset += ($size * ($alen + 1));
}

printf("%04d: END\n", $offset);
}

BlueAdept
05-20-2005, 09:34 PM
Took ksmith's structvis.pl patched it to work on 05/20 live packets.

There are a couple issue that I need to speak with ksmith about, so do -not- just cut-n-paste the PP from everquest.h into structvis, the PP in structvis is hand tweaked.


Not too long ago, I had taken his script and updated it a bit to work with the player packet struct. I dont know perl so it probably isnt as pretty as it should be. The code that I had was a little different from the one that was posted. The link to the one that I modified is here: http://www.showeq.net/forums/showthread.php?t=5265&page=1&pp=15

I assume the problems you are having is with the variables for the max values in the player profile.

As you can see, I used the $alen to define it. I also had to add a section in the uint32_t and the char structures so it would pick up some of the sections.

tanner
05-21-2005, 08:11 AM
I assume the problems you are having is with the variables for the max values in the player profile.


Correct.

The other missing functionality is multi-dimension arrays.

/*6008*/ char groupMembers[MAX_GROUP_MEMBERS][64]; // all the members in gro up, including self

I don't see your patch(es)/code at the url. Did it get removed?

purple
05-21-2005, 08:42 AM
BA's update of ksmith's script is sitting right there in message 13. That's what I use.

BlueAdept
05-21-2005, 08:54 AM
#!/usr/bin/perl -w

use strict;

my $charProfile = << 'END'
/*
** Player Profile
** Length: 18496 Octets
** OpCode: CharProfileCode
*/

struct charProfileStruct
{
/*0000*/ uint32_t checksum; //
/*0004*/ char name[64]; // Name of player
/*0068*/ char lastName[32]; // Last name of player
/*0100*/ uint32_t gender; // Player Gender - 0 Male, 1 Female
/*0104*/ uint32_t race; // Player race
/*0108*/ uint32_t class_; // Player class
/*0112*/ uint32_t unknown0112; // *** Placeholder
/*0116*/ uint32_t level; // Level of player (might be one byte)
/*0120*/ uint32_t bind_zone_id[5]; // Bind info (zone, x, y, z, heading)
/*0140*/ float bind_x[5]; // 0 is normal bind
/*0160*/ float bind_y[5]; // 5 is some weird point in newbie zone
/*0180*/ float bind_z[5]; // (which is secondary bind for wiz/dru?)
/*0200*/ float bind_heading[5]; // Unused slots show newbie bind
/*0220*/ uint32_t deity; // deity
/*0224*/ int32_t guildID; // guildID
/*0228*/ uint32_t birthdayTime; // character birthday
/*0232*/ uint32_t lastSaveTime; // character last save time
/*0236*/ uint32_t timePlayedMin; // time character played
/*0240*/ uint8_t pvp; // 1=pvp, 0=not pvp
/*0241*/ uint8_t level1; // Level of Player
/*0242*/ uint8_t anon; // 2=roleplay, 1=anon, 0=not anon
/*0243*/ uint8_t gm; // 0=no, 1=yes
/*0244*/ int8_t guildstatus; // 0=member, 1=officer, 2=guildleader
/*0245*/ uint8_t unknown0245[55]; // *** Placeholder
/*0300*/ uint8_t haircolor; // Player hair color
/*0301*/ uint8_t beardcolor; // Player beard color
/*0302*/ uint8_t eyecolor1; // Player left eye color
/*0303*/ uint8_t eyecolor2; // Player right eye color
/*0304*/ uint8_t hairstyle; // Player hair style
/*0305*/ uint8_t beard; // Player beard type
/*0306*/ uint8_t unknown0302[6]; // *** Placeholder
/*0312*/ uint32_t item_material[9]; // Item texture/material of worn items
/*0348*/ uint8_t unknown0348[48]; // *** Placeholder
/*0396*/ Color_Struct item_tint[9]; // RR GG BB 00
/*0432*/ AA_Array aa_array[MAX_AA]; // AAs
/*1392*/ char servername[32]; // server the char was created on
/*1424*/ uint8_t unknown1452[68]; // *** Placeholder
/*1492*/ uint32_t exp; // Current Experience
/*1496*/ uint32_t unknown1496; // *** Placeholder
/*1500*/ uint32_t points; // Unspent Practice points
/*1504*/ uint32_t MANA; // Current MANA
/*1508*/ uint32_t curHp; // Current HP without +HP equipment
/*1512*/ uint32_t unknown1512; // 0x05
/*1516*/ uint32_t STR; // Strength
/*1520*/ uint32_t STA; // Stamina
/*1524*/ uint32_t CHA; // Charisma
/*1528*/ uint32_t DEX; // Dexterity
/*1532*/ uint32_t INT; // Intelligence
/*1536*/ uint32_t AGI; // Agility
/*1540*/ uint32_t WIS; // Wisdom
/*1544*/ uint8_t face; // Player face
/*1545*/ uint8_t unknown1545[47]; // *** Placeholder
/*1592*/ uint8_t languages[25]; // List of languages (MAX_KNOWN_LANGS)
/*1617*/ uint8_t unknown1617[7]; // All 0x00 (language buffer?)
/*1624*/ int32_t sSpellBook[400]; // List of the Spells in spellbook
/*3224*/ uint8_t unknown3224[448]; // all 0xff after last spell
/*3672*/ int32_t sMemSpells[9]; // List of spells memorized
/*3708*/ uint8_t unknown3708[32]; // *** Placeholder
/*3740*/ float x; // Players x position
/*3744*/ float y; // Players y position
/*3748*/ float z; // Players z position
/*3752*/ float heading; // Players heading
/*3756*/ uint8_t unknown3756[4]; // *** Placeholder
/*3760*/ uint32_t platinum; // Platinum Pieces on player
/*3764*/ uint32_t gold; // Gold Pieces on player
/*3768*/ uint32_t silver; // Silver Pieces on player
/*3772*/ uint32_t copper; // Copper Pieces on player
/*3776*/ uint32_t platinum_bank; // Platinum Pieces in Bank
/*3780*/ uint32_t gold_bank; // Gold Pieces in Bank
/*3784*/ uint32_t silver_bank; // Silver Pieces in Bank
/*3788*/ uint32_t copper_bank; // Copper Pieces in Bank
/*3792*/ uint32_t platinum_cursor; // Platinum Pieces on cursor
/*3796*/ uint32_t gold_cursor; // Gold Pieces on cursor
/*3800*/ uint32_t silver_cursor; // Silver Pieces on cursor
/*3804*/ uint32_t copper_cursor; // Copper Pieces on cursor
/*3808*/ uint32_t platinum_shared; // Shared platinum pieces
/*3812*/ uint8_t unknown3812[20]; // Unknown - all zero
/*3832*/ uint32_t skills[75]; // List of skills (MAX_KNOWN_SKILLS)
/*4132*/ uint8_t unknown4132[348]; // *** Placeholder
/*4480*/ uint32_t expAA; // Current AA experience
/*4484*/ uint8_t unknown4484[4]; // *** Placeholder
/*4488*/ uint32_t expansions; // Bitmask for expansions
/*4492*/ uint8_t unknown4492[20]; // *** Placeholder
/*4512*/ uint32_t hunger; // Food (ticks till next eat)
/*4516*/ uint32_t thirst; // Drink (ticks till next drink)
/*4520*/ uint8_t unknown4520[20]; // *** Placeholder
/*4540*/ uint16_t zoneId; // see zones.h
/*4542*/ uint16_t zoneInstance; // Instance id
/*4544*/ spellBuff buffs[MAX_BUFFS]; // Buffs currently on the player
/*4944*/ char groupMembers[MAX_GROUP_MEMBERS][64];// all the members in group, including self
/*5328*/ uint8_t unknown5328[668]; // *** Placeholder
/*5996*/ uint32_t ldon_guk_points; // Earned GUK points
/*6000*/ uint32_t ldon_mir_points; // Earned MIR points
/*6004*/ uint32_t ldon_mmc_points; // Earned MMC points
/*6008*/ uint32_t ldon_ruj_points; // Earned RUJ points
/*6012*/ uint32_t ldon_tak_points; // Earned TAK points
/*6016*/ uint32_t ldon_avail_points; // Available LDON points
/*6020*/ uint8_t unknown6020[112]; // *** Placeholder
/*6132*/ uint32_t tributeTime; // Time remaining on tribute (millisecs)
/*6136*/ uint32_t unknown6136; // *** Placeholder
/*6140*/ uint32_t careerTribute; // Total favor points for this char
/*6144*/ uint32_t unknown6144; // *** Placeholder
/*6148*/ uint32_t currentTribute; // Current tribute points
/*6152*/ uint32_t unknown6152; // *** Placeholder
/*6156*/ uint32_t tributeActive; // 0 = off, 1=on
/*6160*/ TributeStruct tributes[MAX_TRIBUTES]; // Current tribute loadout
/*6200*/ uint32_t disciplines[MAX_DISCIPLINES]; // Known disciplines
/*6400*/ uint8_t unknown6400[440]; // *** Placeholder
/*6840*/ uint32_t endurance; // Current endurance
/*6844*/ uint8_t unknown6844[276]; // *** Placeholder
/*7120*/ uint32_t airRemaining; // Air supply (seconds)
/*7124*/ uint8_t unknown7124[4608]; // *** Placeholder
/*11732*/ uint32_t aa_spent; // Number of spent AA points
/*11736*/ uint32_t unknown11736; // *** Placeholder
/*11740*/ uint32_t aa_unspent; // Unspent AA points
/*11744*/ uint8_t unknown11744[36]; // *** Placeholder
/*11780*/ BandolierStruct bandoliers[MAX_BANDOLIERS]; // bandolier contents
/*13060*/ uint8_t unknown13060[5120]; // *** Placeholder
/*18180*/ InlineItem potionBelt[MAX_POTIONS_IN_BELT]; // potion belt
/*18468*/ uint8_t unknown18468[8]; // *** Placeholder
/*18476*/ uint32_t currentRadCrystals; // Current count of radiant crystals
/*18480*/ uint32_t careerRadCrystals; // Total count of radiant crystals ever
/*18484*/ uint32_t currentEbonCrystals;// Current count of ebon crystals
/*18488*/ uint32_t careerEbonCrystals; // Total count of ebon crystals ever
/*18492*/ uint32_t unknown18492; // *** Placeholder
}; /* 18496 */

END
;

# load struct
my @struct = ();

while ($charProfile =~ /^(.*)$/mcg) {
my $line = $1;
if ($line =~ /^.*\s(\S+)\s+(\S+)\;/) {
my $type = $1;
my $name = $2;
push(@struct, { 'name' => $name, 'type' => $type } );
}
}

# load data
my @data = ();

open(PACKET, "./packet.txt");
while (my $line = <PACKET>) {
if ($line =~ /^\d+ \| ([0-9a-f ]+?) \|/) {
$line = $1;
while ($line =~ /([0-9a-f]{2})/mcg) {
push(@data, hex($1));
}
}
}
close(PACKET);

print "Loaded ". ($#data + 1) ." bytes.\n";


# fill in struct
my $offset = 0;
foreach my $i (0..$#struct) {
my $type = $struct[$i]{'type'};
my $name = $struct[$i]{'name'};
my $alen = 0;
my $size = 0;

if ($name =~ /(\S+)\[([0-9]+)\]/) {
$name = $1;
$alen = $2 - 1;
}

if ($alen > 0) {
printf("%04d: %s\t%s[%d]: ", $offset, $type, $name, $alen + 1);
} else {
printf("%04d: %s\t%s: ", $offset, $type, $name);
}

if ($type eq "uint8_t") {
$size = 1;
foreach my $j (0..$alen) {
print unpack("C", pack("C", $data[$offset + $j * $size])) ." ";
}

} elsif ($type eq "uint16_t") {
$size = 2;
foreach my $j (0..$alen) {
print unpack("S", pack("CC", $data[$offset + $j * $size], $data[$offset + 1 + $j * $size])) ." ";
}

} elsif ($type eq "uint32_t") {
if ($name eq "disciplines[MAX_DISCIPLINES]") {
$alen = 50 - 1;
$size = 4;
} else {
$size = 4;
foreach my $j (0..$alen) {
print unpack("L", pack("CCCC", $data[$offset + $j * $size], $data[$offset + 1 + $j * $size],
$data[$offset + 2 + $j * $size], $data[$offset + 3 + $j * $size])) ." ";
}
}
} elsif ($type eq "int8_t") {
$size = 1;
foreach my $j (0..$alen) {
print unpack("c", pack("C", $data[$offset + $j * $size])) ." ";
}

} elsif ($type eq "int16_t") {
$size = 2;
foreach my $j (0..$alen) {
print unpack("s", pack("CC", $data[$offset + $j * $size], $data[$offset + 1 + $j * $size])) ." ";
}

} elsif ($type eq "int32_t") {
$size = 4;
foreach my $j (0..$alen) {
print unpack("l", pack("CCCC", $data[$offset + $j * $size], $data[$offset + 1 + $j * $size],
$data[$offset + 2 + $j * $size], $data[$offset + 3 + $j * $size])) ." ";
}

} elsif ($type eq "float") {
$size = 4;
foreach my $j (0..$alen) {
my $num = pack("CCCC", $data[$offset + 0], $data[$offset + 1],
$data[$offset + 2], $data[$offset + 3]);

print unpack("f", $num) ." ";
}

} elsif ($type eq "char") {
if ($name eq "groupMembers[MAX_GROUP_MEMBERS]") {
$alen = 6 - 1;
$size = 64;
} else {
foreach my $j (0..$alen) {
if ($data[$offset + $j] > 0x1f && $data[$offset + $j] < 0x80) {
printf("%c", $data[$offset+$j]);
} else {
print ".";
}
}
$size = 1;
}
} elsif ($type eq "Color_Struct") {
# B R G A
$size = 4;

} elsif ($type eq "AA_Array") {
# AA value
$alen = 120 - 1;
$size = 8;

} elsif ($type eq "spellBuff") {
# slotid level effect spellid padding duration unknown
$alen = 25 - 1;
$size = 16;

} elsif ($name eq "groupMembers") {
# Group members
$alen = 6 - 1;
$size = 64;

} elsif ($type eq "TributeStruct") {
# Group Members
$alen = 5 - 1;
$size = 8;

} elsif ($type eq "BandolierStruct") {
# Bandolier Structure
$alen = 4 - 1;
$size = 320;

} elsif ($type eq "InlineItem") {
# Potion Belt
$alen = 4 - 1;
$size = 72;

} else {
die "Unknown type: $type\n";

}

print "\n";

$offset += ($size * ($alen + 1));
}

printf("%04d: END\n", $offset);


That is the one that I used. I haven't updated it to the current but it handles the max values. I'm sure it could be done correctly if I knew perl better, but it worked for what I needed it for.

BTW there are 2 that I didn't just use the alen to define the max values.



} elsif ($type eq "uint32_t") {
if ($name eq "disciplines[MAX_DISCIPLINES]") {
$alen = 50 - 1;
$size = 4;
} else {

and


} elsif ($type eq "char") {
if ($name eq "groupMembers[MAX_GROUP_MEMBERS]") {
$alen = 6 - 1;
$size = 64;
} else {