Ru-MaNGOS

Ru-MaNGOS (http://mangos.ytdb.ru/index.php)
-   Tools (http://mangos.ytdb.ru/forumdisplay.php?f=22)
-   -   [разработка]Wow Packet Parser (http://mangos.ytdb.ru/showthread.php?t=1750)

alien 11.07.2010 21:43

[разработка]Wow Packet Parser
 
Вложений: 1
Вот решил заняться разработкой утилитки для парсинга снифов.
Видел что существуют такие и даже какое то время пользовался WoWPacketViewer(я его тут выкладывал недавно)
Но все что я видел оно довольно неудобно.
И вот взялся за написание.
Пока проект в стадии активного написания. Во вложение набросок интерфейса(там где список пакетов планируется таблица в которой будет номер пакета, а также разный цвет фона в зависимости от направления)

Основная фишка парсера в том чтобы добавить поддержку разбора нового пакета не нужно перекомпилировать полностью приложение. Разбор осуществляет Скрипт на Lua
Вот пример скрипта разбора CMSG_AUTH_SESSION
Код:

ClientBuild=Packet:ReadInt32()
unk=Packet:ReadInt32()
acc=Packet:ReadString()
function GetClientBuild()
        return "Client: "..ClientBuild.."\n";
end

function Tmpe()
        Packet:DeCompress();
        local addon_count=Packet:ReadInt32();
        local addonTable={};
        for i=1,addon_count do
                local addonName = Packet:ReadString();
                        local enabled = Packet:ReadByte();
                        local crc = Packet:ReadUInt32();
                        local unk4 = Packet:ReadUInt32();
                table.insert(addonTable,{["name"]=addonName,["value"]={{["name"]="Enabled",value=enabled},{["name"]="Crc",value=crc},{["name"]="Unk4",value=unk4}}});
                end
        return {{["name"]="Addon Count",value=addon_count},{["name"]="Addons",value=addonTable}};
end

function GetTextResult()
        return GetClientBuild().."unk0: "..unk.."\nAccount: "..acc;
end

testtableret={
{["name"]="Client",value=ClientBuild},
{["name"]="Unk",value=unk},
{["name"]="Account",value=acc},
{["name"]="Unk2",value=Packet:ReadInt32()},
{["name"]="Client Seed",value=Packet:ReadInt32()},
{["name"]="Unk3",value=Packet:ReadInt64()},
{["name"]="Digest",value=Packet:HexPrint(Packet:ReadBytes(20))},
{["name"]="Decompressed",value=Tmpe()},
{["name"]="Unk5",value=Packet:ReadUInt32()},

}

Да скрипт пока выглядит не очень эстетично но это еще из-за того что не решил еще полностью как лучше будет сделать.
В общем проект лично для меня носит обучающий характер. В написании используется Qt+luabind
Если есть желающие присоединится милости прошу(скорее всего как только будет что не стыдно показать в качестве сорцов проект будет опенсорс)

RomanRom2 11.07.2010 22:41

насколько я понял речь идет именно о pktViewer? парсер обычно парсит инфу и куда то ее складывает.

да, давно пора. я тоже хотел сделать код, который бы не нужно было перекомпилять, что бы добавить новый опкод. какой нибудь описатель делать и подкладывать его в каталог. не придумал как сделать такое:

Код:

  pkt.AddLong(itAttributesCount);
  for i:=1 to itAttributesCount do
    begin
      pkt.AddLong(ItemTPL[item_id].itAttributes[i].ItemStatType);
      pkt.AddLong(ItemTPL[item_id].itAttributes[i].ItemStatValue);
    end;

я скрипты не люблю, пытаюсь их максимально исключить. и придумать что то вроде на манер:

Код:

SpellCastTimes.ini
[TYPE]
0=index
[FIELD]
0=id
1=casting_time_1
2=step
3=casting_time_2


alien 11.07.2010 23:20

Да наверно парсер неправильное слово в данном контексте )
Но WoWPacketViewer уже есть ) можно конечно назвать что-то типа wpView ))
Ладно название программы не самое важное.
А насчет скриптов. Да было бы хорошо обойтись без скриптов. Но тут скорее всего не получится(вовсяком случае простым способом, придется жестко извращаться)

RomanRom2 11.07.2010 23:27

название не самое главное, да. но... как корабль назовешь, так он и поплывет :)
мой так называется - zPktViewer. буковка z - ну так уж вышло, сортировка что бы в конец списка выводила :)

Konctantin 11.07.2010 23:59

Не знаю как в делфи, но в С# есть такая штука как CodeDomProvider
то есть получается на лету можно вставлять программный код и сразу его выполнять.

ЗЫ. Можно хранить отдельные парсеры для разных опкодов, а когда нужно, просто загружать.
как при старте программы, так и при работе.

или же есть CSharpCodeProvider, то же самое, только более специфическое.

RomanRom2 12.07.2010 00:12

это фишка исключительно C#, в дельфи такого нет, к сожалению.
в дельфи либо внешние скриптовые движки либо думать, как сделать инишник. засада там только одна - счетчики данных.

ну или плагины можно сделать. каждый опкод будет отдельным плагином. и грузите их. не знаю только, можно ли сделать так, что бы плагины можно было писать на разных языках, что бы они потом работали на дельфевом приложении.

alien 12.07.2010 00:33

Цитата:

не знаю только, можно ли сделать так, что бы плагины можно было писать на разных языках, что бы они потом работали на дельфевом приложении.
Можно.
Только зачем тогда проще подключить внешний скриптовый двиг который все и будет делать.
Цитата:

ЗЫ. Можно хранить отдельные парсеры для разных опкодов, а когда нужно, просто загружать.
как при старте программы, так и при работе.
У меня например так и есть для каждого пакета свой файл.
Скрипт выполняется когда выбираешь пакет в списке.

Йоха 12.07.2010 08:13

а что данные содержашиеся в пакетах настолько нетривиальны что требуют обработки скриптом ? Недостаточно задать описание структуры данных, и обрабатывать их в движке, а не писать скрипт для каждого опкода

RomanRom2 12.07.2010 09:26

они тривиальны до тех пор, пока нет счетчиков

field_count;
{
field_count_val1,
field_count_val2,
...
field_count_val(count)
}

как описать это?

LordJZ 12.07.2010 10:06

Цитата:

Сообщение от RomanRom2 (Сообщение 10564)
они тривиальны до тех пор, пока нет счетчиков

field_count;
{
field_count_val1,
field_count_val2,
...
field_count_val(count)
}

как описать это?

В WCell — через xml...

RomanRom2 12.07.2010 10:31

получается так или иначе городить какой то "умный" парсер. формат на самом деле значения не имеет, что xml, что какой то свой формат...

alien 12.07.2010 11:55

Да и вот еще не только счетчики могут быть.
От значения определенного поля размер и формат пакета тоже может меняться.

Konctantin 12.07.2010 12:18

С помощью структуры можно разбирать только примитивные пакеты с прямолинейной структурой, без сложных зависимостей, а так надо прибегать к скриптам.

Или же разделить как-то, простые пакеты обрабатывать по структуре, а сложные скриптом.

Konctantin 16.08.2010 06:16

Тема еще актуальна?

Fmut 18.08.2010 15:53

Вот держите, Наш вариант lua парсера :)
Код:

--[[ описание комманды  CMSG_CHAR_ENUM и обслуживающая функция ]]--

local CEnumCode, nCEnumCode = 55, 'CMSG_CHAR_ENUM'
local CEnumVers = 'Версия клиента: 3.3.5 [12340], Дата изменения: 07.07.2010'

CMSG_CHAR_ENUM = function (dBuf, lBuf, index)
        AddCodeNameMem (index, CEnumCode, nCEnumCode, lBuf)
        AddMem2(CEnumVers)
end

--[[ описание комманды  SMSG_CHAR_ENUM и обслуживающая функция ]]--

local SEnumCode, nSEnumCode = 59, 'SMSG_CHAR_ENUM'
local SEnumVers = 'Версия клиента: 3.3.5 [12340], Дата изменения: 08.07.2010'

SMSG_CHAR_ENUM = function (dBuf, lBuf, index)
        AddCodeNameMem (index, SEnumCode, nSEnumCode, lBuf)
        AddMem2(SEnumVers)
        AddMem2('')
        local CharCount, Iter, Val = 0, 4, 0
        CharCount, Iter = ReadByte(dBuf, Iter)
        AddMem2('Characters count (byte) = '..CharCount..' ($'..ByteToHexStr(CharCount)..')')
        local i, j = 0, 0
        while i < CharCount do
          AddMem2('')
          AddMem2('-------------------- Char '..i..' --------------------')
          Val, Iter = ReadInt64Hex(dBuf, Iter)
          AddMem2('CharGUID (int64) = $'..Val)
          Val, Iter = ReadString(dBuf, Iter)
          AddMem2('Name (str) = '..Val)
          Val, Iter = ReadByte(dBuf, Iter)
          AddMem2('Race (byte) = '..Val..' ($'..ByteToHexStr(Val)..')')
          Val, Iter = ReadByte(dBuf, Iter)
          AddMem2('Class (byte) = '..Val..' ($'..ByteToHexStr(Val)..')')
          Val, Iter = ReadByte(dBuf, Iter)
          AddMem2('Gender (byte) = '..Val..' ($'..ByteToHexStr(Val)..')')
          Val, Iter = ReadByte(dBuf, Iter)
          AddMem2('Skin (byte) = '..Val..' ($'..ByteToHexStr(Val)..')')
          Val, Iter = ReadByte(dBuf, Iter)
          AddMem2('Face (byte) = '..Val..' ($'..ByteToHexStr(Val)..')')
          Val, Iter = ReadByte(dBuf, Iter)
          AddMem2('HairStyle (byte) = '..Val..' ($'..ByteToHexStr(Val)..')')
          Val, Iter = ReadByte(dBuf, Iter)
          AddMem2('HairColour (byte) = '..Val..' ($'..ByteToHexStr(Val)..')')
          Val, Iter = ReadByte(dBuf, Iter)
          AddMem2('FacialHair (byte) = '..Val..' ($'..ByteToHexStr(Val)..')')
          Val, Iter = ReadByte(dBuf, Iter)
          AddMem2('Level (byte) = '..Val..' ($'..ByteToHexStr(Val)..')')
          Val, Iter = ReadInteger(dBuf, Iter)
          AddMem2('ZoneId (int) = '..Val..' ($'..IntToHexStr(Val)..')')
          Val, Iter = ReadInteger(dBuf, Iter)
          AddMem2('MapId (int) = '..Val..' ($'..IntToHexStr(Val)..')')
          Val, Iter = ReadFloat(dBuf, Iter)
          AddMem2('PosX (float) = '..Val)
          Val, Iter = ReadFloat(dBuf, Iter)
          AddMem2('PosY (float) = '..Val)
          Val, Iter = ReadFloat(dBuf, Iter)
          AddMem2('PosZ (float) = '..Val)
          Val, Iter = ReadInteger(dBuf, Iter)
          AddMem2('GuildId (int) = '..Val..' ($'..IntToHexStr(Val)..')')
          Val, Iter = ReadInteger(dBuf, Iter)
          AddMem2('EnumFlag (int) = '..Val..' ($'..IntToHexStr(Val)..')')
          Val, Iter = ReadInteger(dBuf, Iter)
          AddMem2('Unk_Wotlk (int) = '..Val..' ($'..IntToHexStr(Val)..')')
          Val, Iter = ReadByte(dBuf, Iter)
          AddMem2('Rested (byte) = '..Val..' ($'..ByteToHexStr(Val)..')')
          Val, Iter = ReadInteger(dBuf, Iter)
          AddMem2('PetInfoId (int) = '..Val..' ($'..IntToHexStr(Val)..')')
          Val, Iter = ReadInteger(dBuf, Iter)
          AddMem2('PetLevel (int) = '..Val..' ($'..IntToHexStr(Val)..')')
          Val, Iter = ReadInteger(dBuf, Iter)
          AddMem2('PetFamilyId (int) = '..Val..' ($'..IntToHexStr(Val)..')')
          for j = 0, 19, 1 do
            AddMem2(' ============== Item '..j..' ==============')
            Val, Iter = ReadInteger(dBuf, Iter)
            AddMem2('  Model (int) = '..Val..' ($'..IntToHexStr(Val)..')')
            Val, Iter = ReadByte(dBuf, Iter)
            AddMem2('  InvType (byte) = '..Val..' ($'..ByteToHexStr(Val)..')')
            Val, Iter = ReadInteger(dBuf, Iter)
            AddMem2('  Unk (int) = '..Val..' ($'..IntToHexStr(Val)..')')
          end
          i = i + 1
        end
end

--[[ регистрация функций в основной программе ]]--

Register_Code(CEnumCode, nCEnumCode)
Register_Code(SEnumCode, nSEnumCode)


Konctantin 18.08.2010 16:11

а у нас есть 2 вида парсеров ХМЛ структуры и хард код, править структуры (ХМЛ парсер) можно не закрывая сам парсер, есть возможность перегрузки структур.

alien 20.08.2010 18:48

да тема актуально. Просто я щас в таком месте где компа под рукой нету. как приеду буду дописывать.
Зы у меня тоже скрипты луашные тоже без перезапуска программы обновляются

ispanec 21.08.2010 08:32

Цитата:

Сообщение от Konctantin (Сообщение 10574)
С помощью структуры можно разбирать только примитивные пакеты с прямолинейной структурой, без сложных зависимостей, а так надо прибегать к скриптам.

Или же разделить как-то, простые пакеты обрабатывать по структуре, а сложные скриптом.

"Работам техничкам ничо не знам" и сейчас может хрень спорю, но что мешает хранить всё в JSON (http://www.json.org/json-ru.html), а потом его "парсить" - есть готовые (де)сериализаторы.

Konctantin 21.08.2010 08:52

а это кому как удобней...

RomanRom2 18.04.2011 01:46

в общем повтыкал я в этот JSON...
все отлично, все замечательно просто, ровно до того места, когда нужно сделать зависимость от байта (или того интересней - от флага). или счетчики структур. короче не подходит. надо скриптовые движки использовать. ну или что то свое городить...

HuntsMan 20.04.2011 16:36

Я обработчики пишу на шарпе без привлечения сторонних движков, и не жалуюсь :)

Йоха 20.04.2011 16:45

Цитата:

Сообщение от HuntsMan (Сообщение 21329)
Я обработчики пишу на шарпе без привлечения сторонних движков, и не жалуюсь :)

Это не очень удобно, структура постоянно меняется от билда к билду, и с каждым билдом надо пересобирать программу. Потом по мере разбора новых опокодов опять дописывать код и компилировать ...
А со скриптами гораздо проще, поправил текстовый файлик и вперед

Lordronn 20.04.2011 16:49

Цитата:

Потом по мере разбора новых опокодов опять дописывать код и компилировать ...
Десериализация рулит

Йоха 20.04.2011 16:59

эм... не совсем понятно
объясни что имеется в виду

Lordronn 20.04.2011 19:18

Структура пакетов хранится в XML файле. При запуске программы файлы десериализуются. При выборе пакета создается ридер пакета, который читается по структуре из XML файла, которую мы уже занесли в List\Dictionary. реализовать можно довольно много:
switch
case
format (X4, X16...)
compare
Можно также указывать название enum - а

При необходимости легко можно сменить структуру без перезагрузки всего вайвера.

Скрытый текст (вы должны войти под своим логином или зарегистрироваться и иметь 50 сообщение(ий)):
У вас нет прав чтобы видеть скрытый текст, содержащейся здесь.

Йоха 20.04.2011 19:33

да епрст, ну об этом же и говорится, что формат пакетов задается внешними файлами.
там просто HuntsMan написал что у него обработчики захардкодены, вот это и неудобно

Lordronn 20.04.2011 19:56

Я сейчас с этим мучаюсь. Написал около 100 обработчиков в коде. Теперь мучаюсь с их переносом в XML-ки

LordJZ 20.04.2011 20:00

А у меня для обработки пакетов используется вот такой интерфейс:
Скрытый текст (вы должны войти под своим логином или зарегистрироваться и иметь 10 сообщение(ий)):
У вас нет прав чтобы видеть скрытый текст, содержащейся здесь.
*PROUD*

zergtmn 20.04.2011 21:03

Цитата:

Сообщение от Йоха (Сообщение 21343)
обработчики захардкодены, вот это и неудобно

Зато удобно делать произвольную фильтрацию и собирать данные для внесения в базу.

Lordronn 20.04.2011 21:18

Это да, это можно только через код. Но речь идет о мелких пакетах типа CMSG_QUEST_QUERY и о пакетах из который не получить информации для базы. У меня для пакетов(респонзы, вендор лист, и т.п) сделан специальный оутпут в скул. Достаточно нажать на одну кнопочку в меню и выбрать директорию. Для UPDATE_OBJECT у меня плагин написан

TOM_RUS 21.04.2011 07:05

Поигрался седня ночью с сериализацией/десериализацией, очень удобная штука :)

http://paste2.org/p/1375139

Допустим есть пакет:
Код:

0x01, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00
Если например он имеет структуру:
Код:

uint32
uint32
uint32

то XML для него получается что-то типа:
Код:

<Definition xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema" Opcode="CMSG_TEST_ACTION">
<Fields xsi:type="Simple" Name="Field1" DataType="UInt32"/>
<Fields xsi:type="Simple" Name="Field2" DataType="UInt32"/>
<Fields xsi:type="Simple" Name="Field3" DataType="UInt32"/>
</Fields>
</Definition>

если например структура:
Код:

uint32
uint32
switch(uint32)
{
    case 3:
        break;
}

Код:

<Definition xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema" Opcode="CMSG_TEST_ACTION">
<Fields xsi:type="Simple" Name="Field1" DataType="UInt32"/>
<Fields xsi:type="Simple" Name="Field2" DataType="UInt32"/>
<Fields xsi:type="Switch" Name="Switch1" DataType="UInt32">
<Fields xsi:type="Case" Name="Case2" DataType="UInt32" CaseValue="3"/>
</Fields>
</Definition>

Код:

for(uint32)
{
    uint32
    uint32
}

Код:

<Definition xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema" Opcode="CMSG_TEST_ACTION">
<Fields xsi:type="DynamicLoop" Name="Loop1" DataType="UInt32">
<Fields xsi:type="Simple" Name="LoopField1" DataType="UInt32"/>
<Fields xsi:type="Simple" Name="LoopField2" DataType="UInt32"/>
</Fields>
</Definition>

Код:

for(1)
{
    uint32
    uint32
}

Код:

<Definition xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema" Opcode="CMSG_TEST_ACTION">
<Fields xsi:type="StaticLoop" Name="Loop1" DataType="UInt32" LoopLength="1">
<Fields xsi:type="Simple" Name="LoopField1" DataType="UInt32"/>
<Fields xsi:type="Simple" Name="LoopField2" DataType="UInt32"/>
</Fields>
</Definition>

Код:

if(uint32 == 1)
{
    uint32
    uint32
}

Код:

<Definition xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema" Opcode="CMSG_TEST_ACTION">
<Fields xsi:type="Condition" Name="Condition1" DataType="UInt32" ConditionType="Equal" ConditionValue="1">
<Fields xsi:type="Simple" Name="ConditionField1" DataType="UInt32"/>
<Fields xsi:type="Simple" Name="ConditionField2" DataType="UInt32"/>
</Fields>
</Definition>


HuntsMan 21.04.2011 07:41

Цитата:

Сообщение от Йоха (Сообщение 21330)
Это не очень удобно, структура постоянно меняется от билда к билду, и с каждым билдом надо пересобирать программу. Потом по мере разбора новых опокодов опять дописывать код и компилировать ...
А со скриптами гораздо проще, поправил текстовый файлик и вперед

Я в нем постоянно что-нибудь дописываю, поэтому запуск у меня по умолчанию идет в дебаге и из студии)

Опять же большую часть пакетов я стараюсь парсить и в sql. Например:
Код:

INSERT INTO `playercreateinfo_spell` (`race`,`class`,`Spell`,`Note`) VALUES ('@RACE', '@CLASS', '674', 'Бой двумя оружиями (674)');
INSERT INTO `playercreateinfo_spell` (`race`,`class`,`Spell`,`Note`) VALUES ('@RACE', '@CLASS', '6478', 'Открывание (6478)');
INSERT INTO `playercreateinfo_spell` (`race`,`class`,`Spell`,`Note`) VALUES ('@RACE', '@CLASS', '6603', 'Автоматическая атака (6603)');
INSERT INTO `playercreateinfo_spell` (`race`,`class`,`Spell`,`Note`) VALUES ('@RACE', '@CLASS', '45927', 'Призыв друга (45927)');
INSERT INTO `playercreateinfo_spell` (`race`,`class`,`Spell`,`Note`) VALUES ('@RACE', '@CLASS', '22027', 'Удаление знака отличия (22027)');
INSERT INTO `playercreateinfo_spell` (`race`,`class`,`Spell`,`Note`) VALUES ('@RACE', '@CLASS', '22810', 'Открытие - без текста (22810)');
INSERT INTO `playercreateinfo_spell` (`race`,`class`,`Spell`,`Note`) VALUES ('@RACE', '@CLASS', '2382', 'Стандартный (2382)');
INSERT INTO `playercreateinfo_spell` (`race`,`class`,`Spell`,`Note`) VALUES ('@RACE', '@CLASS', '3365', 'Открывание (3365)');
INSERT INTO `playercreateinfo_spell` (`race`,`class`,`Spell`,`Note`) VALUES ('@RACE', '@CLASS', '3050', 'Обнаружение (3050)');
INSERT INTO `playercreateinfo_spell` (`race`,`class`,`Spell`,`Note`) VALUES ('@RACE', '@CLASS', '9125', 'Стандартный (9125)');
INSERT INTO `playercreateinfo_spell` (`race`,`class`,`Spell`,`Note`) VALUES ('@RACE', '@CLASS', '21651', 'Открывание (21651)');
INSERT INTO `playercreateinfo_spell` (`race`,`class`,`Spell`,`Note`) VALUES ('@RACE', '@CLASS', '21652', 'Закрытие (21652)');
INSERT INTO `playercreateinfo_spell` (`race`,`class`,`Spell`,`Note`) VALUES ('@RACE', '@CLASS', '8386', 'Удар (8386)');
INSERT INTO `playercreateinfo_spell` (`race`,`class`,`Spell`,`Note`) VALUES ('@RACE', '@CLASS', '7266', 'Дуэль (7266)');
INSERT INTO `playercreateinfo_spell` (`race`,`class`,`Spell`,`Note`) VALUES ('@RACE', '@CLASS', '7267', 'Ползание (7267)');
INSERT INTO `playercreateinfo_spell` (`race`,`class`,`Spell`,`Note`) VALUES ('@RACE', '@CLASS', '7355', 'Застревание (7355)');
INSERT INTO `playercreateinfo_spell` (`race`,`class`,`Spell`,`Note`) VALUES ('@RACE', '@CLASS', '6233', 'Закрытие (6233)');
INSERT INTO `playercreateinfo_spell` (`race`,`class`,`Spell`,`Note`) VALUES ('@RACE', '@CLASS', '6246', 'Закрытие (6246)');
INSERT INTO `playercreateinfo_spell` (`race`,`class`,`Spell`,`Note`) VALUES ('@RACE', '@CLASS', '6247', 'Открывание (6247)');
INSERT INTO `playercreateinfo_spell` (`race`,`class`,`Spell`,`Note`) VALUES ('@RACE', '@CLASS', '6477', 'Открывание (6477)');
INSERT INTO `playercreateinfo_spell` (`race`,`class`,`Spell`,`Note`) VALUES ('@RACE', '@CLASS', '63645', 'Первый набор талантов (63645)');
INSERT INTO `playercreateinfo_spell` (`race`,`class`,`Spell`,`Note`) VALUES ('@RACE', '@CLASS', '63644', 'Второй набор талантов (63644)');
INSERT INTO `playercreateinfo_spell` (`race`,`class`,`Spell`,`Note`) VALUES ('@RACE', '@CLASS', '52665', 'Реликвия (52665)');
INSERT INTO `playercreateinfo_spell` (`race`,`class`,`Spell`,`Note`) VALUES ('@RACE', '@CLASS', '61437', 'Открывание (61437)');
INSERT INTO `playercreateinfo_spell` (`race`,`class`,`Spell`,`Note`) VALUES ('@RACE', '@CLASS', '68398', 'Открывание (68398)');
INSERT INTO `playercreateinfo_spell` (`race`,`class`,`Spell`,`Note`) VALUES ('@RACE', '@CLASS', '96220', 'Начальная фаза (96220)');
INSERT INTO `playercreateinfo_spell` (`race`,`class`,`Spell`,`Note`) VALUES ('@RACE', '@CLASS', '668', 'Всеобщий язык (668)');
INSERT INTO `playercreateinfo_spell` (`race`,`class`,`Spell`,`Note`) VALUES ('@RACE', '@CLASS', '202', 'Двуручные мечи (202)');
INSERT INTO `playercreateinfo_spell` (`race`,`class`,`Spell`,`Note`) VALUES ('@RACE', '@CLASS', '196', 'Одноручные топоры (196)');
INSERT INTO `playercreateinfo_spell` (`race`,`class`,`Spell`,`Note`) VALUES ('@RACE', '@CLASS', '197', 'Двуручные топоры (197)');
INSERT INTO `playercreateinfo_spell` (`race`,`class`,`Spell`,`Note`) VALUES ('@RACE', '@CLASS', '10846', 'Первая помощь (10846)');
INSERT INTO `playercreateinfo_spell` (`race`,`class`,`Spell`,`Note`) VALUES ('@RACE', '@CLASS', '3275', 'Льняные бинты (3275)');
INSERT INTO `playercreateinfo_spell` (`race`,`class`,`Spell`,`Note`) VALUES ('@RACE', '@CLASS', '18630', 'Плотные бинты из рунической ткани (18630)');
INSERT INTO `playercreateinfo_spell` (`race`,`class`,`Spell`,`Note`) VALUES ('@RACE', '@CLASS', '7934', 'Противоядие (7934)');
INSERT INTO `playercreateinfo_spell` (`race`,`class`,`Spell`,`Note`) VALUES ('@RACE', '@CLASS', '3276', 'Плотные льняные бинты (3276)');
INSERT INTO `playercreateinfo_spell` (`race`,`class`,`Spell`,`Note`) VALUES ('@RACE', '@CLASS', '3277', 'Шерстяные бинты (3277)');
INSERT INTO `playercreateinfo_spell` (`race`,`class`,`Spell`,`Note`) VALUES ('@RACE', '@CLASS', '3278', 'Плотные шерстяные бинты (3278)');
INSERT INTO `playercreateinfo_spell` (`race`,`class`,`Spell`,`Note`) VALUES ('@RACE', '@CLASS', '7928', 'Шелковые бинты (7928)');
INSERT INTO `playercreateinfo_spell` (`race`,`class`,`Spell`,`Note`) VALUES ('@RACE', '@CLASS', '7929', 'Плотные шелковые бинты (7929)');
INSERT INTO `playercreateinfo_spell` (`race`,`class`,`Spell`,`Note`) VALUES ('@RACE', '@CLASS', '10840', 'Бинты из магической ткани (10840)');
INSERT INTO `playercreateinfo_spell` (`race`,`class`,`Spell`,`Note`) VALUES ('@RACE', '@CLASS', '10841', 'Плотные бинты из магической ткани (10841)');
INSERT INTO `playercreateinfo_spell` (`race`,`class`,`Spell`,`Note`) VALUES ('@RACE', '@CLASS', '18629', 'Бинты из рунической ткани (18629)');
INSERT INTO `playercreateinfo_spell` (`race`,`class`,`Spell`,`Note`) VALUES ('@RACE', '@CLASS', '203', 'Рукопашный бой (203)');
INSERT INTO `playercreateinfo_spell` (`race`,`class`,`Spell`,`Note`) VALUES ('@RACE', '@CLASS', '750', 'Латы (750)');
INSERT INTO `playercreateinfo_spell` (`race`,`class`,`Spell`,`Note`) VALUES ('@RACE', '@CLASS', '8737', 'Кольчужные доспехи (8737)');
INSERT INTO `playercreateinfo_spell` (`race`,`class`,`Spell`,`Note`) VALUES ('@RACE', '@CLASS', '9077', 'Кожа (9077)');
INSERT INTO `playercreateinfo_spell` (`race`,`class`,`Spell`,`Note`) VALUES ('@RACE', '@CLASS', '200', 'Древковое оружие (200)');
INSERT INTO `playercreateinfo_spell` (`race`,`class`,`Spell`,`Note`) VALUES ('@RACE', '@CLASS', '199', 'Двуручное дробящее оружие (199)');
INSERT INTO `playercreateinfo_spell` (`race`,`class`,`Spell`,`Note`) VALUES ('@RACE', '@CLASS', '89964', 'Убрать символ (89964)');
INSERT INTO `playercreateinfo_spell` (`race`,`class`,`Spell`,`Note`) VALUES ('@RACE', '@CLASS', '45902', 'Кровавый удар (45902)');
INSERT INTO `playercreateinfo_spell` (`race`,`class`,`Spell`,`Note`) VALUES ('@RACE', '@CLASS', '49410', 'Силовое отражение (49410)');
INSERT INTO `playercreateinfo_spell` (`race`,`class`,`Spell`,`Note`) VALUES ('@RACE', '@CLASS', '82246', 'Парирование (82246)');
INSERT INTO `playercreateinfo_spell` (`race`,`class`,`Spell`,`Note`) VALUES ('@RACE', '@CLASS', '89832', 'Death Strike Enabler (89832)');
INSERT INTO `playercreateinfo_spell` (`race`,`class`,`Spell`,`Note`) VALUES ('@RACE', '@CLASS', '45477', 'Ледяное прикосновение (45477)');
INSERT INTO `playercreateinfo_spell` (`race`,`class`,`Spell`,`Note`) VALUES ('@RACE', '@CLASS', '48266', 'Власть льда (48266)');
INSERT INTO `playercreateinfo_spell` (`race`,`class`,`Spell`,`Note`) VALUES ('@RACE', '@CLASS', '59921', 'Озноб (59921)');
INSERT INTO `playercreateinfo_spell` (`race`,`class`,`Spell`,`Note`) VALUES ('@RACE', '@CLASS', '61455', 'Руническое средоточие (61455)');

ЗЫ: Лучше уж lua чем xml :)

TOM_RUS 21.04.2011 08:50

Цитата:

Сообщение от HuntsMan (Сообщение 21364)
ЗЫ: Лучше уж lua чем xml :)

И зачем этот геморой с lua, если даже встроенной поддержки lua в .NET Framework нет? С XML все прекрасно работает.

HuntsMan 21.04.2011 09:58

Цитата:

Сообщение от TOM_RUS (Сообщение 21368)
И зачем этот геморой с lua, если даже встроенной поддержки lua в .NET Framework нет? С XML все прекрасно работает.

lua визуально понятнее :)

Konctantin 21.04.2011 11:19

Ну если уж на то пошло, то проще тогда выполнять динамическую компиляцию, и писать все на С#, но не lua.

alien 21.04.2011 18:41

Я думаю что если пишешь на шарпе то лучше не паримся и юзаем XML
Если на C/C++ то тогде уже лучше lua прикрутить.

TOM_RUS 21.04.2011 18:57

Я в своем WoWPacketViewer прикрутил динамическую компиляцию парсеров для эксперимента (файл parsers\SMSG_TUTORIAL_FLAGS.cs компилится при выполнении программы).

Йоха 28.04.2011 10:38

Вложений: 1
Я не совсем понял есть ли в природе опенсоурс проект "просмотрщик пакетов" который поддерживается и развивается ? Или ситуация такая же как со сниферами - каждый делает себе свой ?

[добавлено]

Цитата:

Я думаю «народный» аналог PacketViewer-а от TOM_RUS или zPktViewer-а, с поддержкой последних форматов сниффов (у меня сейчас самые распространенные — три) был бы гораздо полезнее, чем народный-же сниффер.
Я набросал каркас приложения, но как мне кажется никто заниматься этим не будет ...

LordJZ 28.04.2011 14:47

Ну PacketViewer от TOM_RUS открытый.

Йоха 28.04.2011 14:55

но он не актуальный на данный момент ? я там глянул на опкоды, они все старые


Текущее время: 17:13. Часовой пояс GMT +3.

ru-mangos.ru - Русское сообщество MaNGOS