Ru-MaNGOS

Вернуться   Ru-MaNGOS > Дополнения > Tools

Важная информация

Tools Обсуждение программ для MaNGOS

Ответ
 
Опции темы Поиск в этой теме Опции просмотра
Старый 11.07.2010, 21:43   #1
alien
Ученый
 
Регистрация: 17.05.2010
Сообщений: 148
Сказал(а) спасибо: 18
Поблагодарили 25 раз(а) в 22 сообщениях
alien На верном пути
По умолчанию [разработка]Wow Packet Parser

Вот решил заняться разработкой утилитки для парсинга снифов.
Видел что существуют такие и даже какое то время пользовался 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
Если есть желающие присоединится милости прошу(скорее всего как только будет что не стыдно показать в качестве сорцов проект будет опенсорс)
Миниатюры
Нажмите на изображение для увеличения
Название: packview.JPG
Просмотров: 1242
Размер:	119.3 Кб
ID:	535  
alien вне форума   Ответить с цитированием
Старый 11.07.2010, 22:41   #2
RomanRom2
WowCore Dev
 
Аватар для RomanRom2
 
Регистрация: 31.03.2010
Сообщений: 468
Сказал(а) спасибо: 73
Поблагодарили 106 раз(а) в 70 сообщениях
RomanRom2 Это имя известно всемRomanRom2 Это имя известно всемRomanRom2 Это имя известно всемRomanRom2 Это имя известно всемRomanRom2 Это имя известно всемRomanRom2 Это имя известно всем
По умолчанию

насколько я понял речь идет именно о 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
RomanRom2 вне форума   Ответить с цитированием
Старый 11.07.2010, 23:20   #3
alien
Ученый
 
Регистрация: 17.05.2010
Сообщений: 148
Сказал(а) спасибо: 18
Поблагодарили 25 раз(а) в 22 сообщениях
alien На верном пути
По умолчанию

Да наверно парсер неправильное слово в данном контексте )
Но WoWPacketViewer уже есть ) можно конечно назвать что-то типа wpView ))
Ладно название программы не самое важное.
А насчет скриптов. Да было бы хорошо обойтись без скриптов. Но тут скорее всего не получится(вовсяком случае простым способом, придется жестко извращаться)
alien вне форума   Ответить с цитированием
Старый 11.07.2010, 23:27   #4
RomanRom2
WowCore Dev
 
Аватар для RomanRom2
 
Регистрация: 31.03.2010
Сообщений: 468
Сказал(а) спасибо: 73
Поблагодарили 106 раз(а) в 70 сообщениях
RomanRom2 Это имя известно всемRomanRom2 Это имя известно всемRomanRom2 Это имя известно всемRomanRom2 Это имя известно всемRomanRom2 Это имя известно всемRomanRom2 Это имя известно всем
По умолчанию

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

Последний раз редактировалось RomanRom2; 11.07.2010 в 23:33.
RomanRom2 вне форума   Ответить с цитированием
Старый 11.07.2010, 23:59   #5
Konctantin
RuDB Dev
 
Аватар для Konctantin
 
Регистрация: 01.02.2010
Адрес: localhost
Сообщений: 592
Сказал(а) спасибо: 323
Поблагодарили 283 раз(а) в 122 сообщениях
Записей в дневнике: 2
Konctantin Это имя известно всемKonctantin Это имя известно всемKonctantin Это имя известно всемKonctantin Это имя известно всемKonctantin Это имя известно всемKonctantin Это имя известно всем
По умолчанию

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

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

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

Последний раз редактировалось Konctantin; 12.07.2010 в 00:03.
Konctantin вне форума   Ответить с цитированием
Старый 12.07.2010, 00:12   #6
RomanRom2
WowCore Dev
 
Аватар для RomanRom2
 
Регистрация: 31.03.2010
Сообщений: 468
Сказал(а) спасибо: 73
Поблагодарили 106 раз(а) в 70 сообщениях
RomanRom2 Это имя известно всемRomanRom2 Это имя известно всемRomanRom2 Это имя известно всемRomanRom2 Это имя известно всемRomanRom2 Это имя известно всемRomanRom2 Это имя известно всем
По умолчанию

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

ну или плагины можно сделать. каждый опкод будет отдельным плагином. и грузите их. не знаю только, можно ли сделать так, что бы плагины можно было писать на разных языках, что бы они потом работали на дельфевом приложении.
RomanRom2 вне форума   Ответить с цитированием
Старый 12.07.2010, 00:33   #7
alien
Ученый
 
Регистрация: 17.05.2010
Сообщений: 148
Сказал(а) спасибо: 18
Поблагодарили 25 раз(а) в 22 сообщениях
alien На верном пути
По умолчанию

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

Последний раз редактировалось alien; 12.07.2010 в 00:37.
alien вне форума   Ответить с цитированием
Старый 12.07.2010, 08:13   #8
Йоха
Умный
 
Регистрация: 02.07.2010
Сообщений: 434
Сказал(а) спасибо: 27
Поблагодарили 73 раз(а) в 45 сообщениях
Йоха Скоро придёт к известности
По умолчанию

а что данные содержашиеся в пакетах настолько нетривиальны что требуют обработки скриптом ? Недостаточно задать описание структуры данных, и обрабатывать их в движке, а не писать скрипт для каждого опкода
Йоха вне форума   Ответить с цитированием
Старый 12.07.2010, 09:26   #9
RomanRom2
WowCore Dev
 
Аватар для RomanRom2
 
Регистрация: 31.03.2010
Сообщений: 468
Сказал(а) спасибо: 73
Поблагодарили 106 раз(а) в 70 сообщениях
RomanRom2 Это имя известно всемRomanRom2 Это имя известно всемRomanRom2 Это имя известно всемRomanRom2 Это имя известно всемRomanRom2 Это имя известно всемRomanRom2 Это имя известно всем
По умолчанию

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

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

как описать это?
RomanRom2 вне форума   Ответить с цитированием
Старый 12.07.2010, 10:06   #10
LordJZ
Супер-модератор
 
Аватар для LordJZ
 
Регистрация: 07.03.2010
Сообщений: 647
Сказал(а) спасибо: 100
Поблагодарили 252 раз(а) в 123 сообщениях
LordJZ Как самоцвет среди гранитаLordJZ Как самоцвет среди гранитаLordJZ Как самоцвет среди гранита
По умолчанию

Цитата:
Сообщение от RomanRom2 Посмотреть сообщение
они тривиальны до тех пор, пока нет счетчиков

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

как описать это?
В WCell — через xml...
LordJZ вне форума   Ответить с цитированием
Пользователь сказал cпасибо:
Старый 12.07.2010, 10:31   #11
RomanRom2
WowCore Dev
 
Аватар для RomanRom2
 
Регистрация: 31.03.2010
Сообщений: 468
Сказал(а) спасибо: 73
Поблагодарили 106 раз(а) в 70 сообщениях
RomanRom2 Это имя известно всемRomanRom2 Это имя известно всемRomanRom2 Это имя известно всемRomanRom2 Это имя известно всемRomanRom2 Это имя известно всемRomanRom2 Это имя известно всем
По умолчанию

получается так или иначе городить какой то "умный" парсер. формат на самом деле значения не имеет, что xml, что какой то свой формат...
RomanRom2 вне форума   Ответить с цитированием
Старый 12.07.2010, 11:55   #12
alien
Ученый
 
Регистрация: 17.05.2010
Сообщений: 148
Сказал(а) спасибо: 18
Поблагодарили 25 раз(а) в 22 сообщениях
alien На верном пути
По умолчанию

Да и вот еще не только счетчики могут быть.
От значения определенного поля размер и формат пакета тоже может меняться.
alien вне форума   Ответить с цитированием
Старый 12.07.2010, 12:18   #13
Konctantin
RuDB Dev
 
Аватар для Konctantin
 
Регистрация: 01.02.2010
Адрес: localhost
Сообщений: 592
Сказал(а) спасибо: 323
Поблагодарили 283 раз(а) в 122 сообщениях
Записей в дневнике: 2
Konctantin Это имя известно всемKonctantin Это имя известно всемKonctantin Это имя известно всемKonctantin Это имя известно всемKonctantin Это имя известно всемKonctantin Это имя известно всем
По умолчанию

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

Или же разделить как-то, простые пакеты обрабатывать по структуре, а сложные скриптом.
__________________
Konctantin вне форума   Ответить с цитированием
Старый 16.08.2010, 06:16   #14
Konctantin
RuDB Dev
 
Аватар для Konctantin
 
Регистрация: 01.02.2010
Адрес: localhost
Сообщений: 592
Сказал(а) спасибо: 323
Поблагодарили 283 раз(а) в 122 сообщениях
Записей в дневнике: 2
Konctantin Это имя известно всемKonctantin Это имя известно всемKonctantin Это имя известно всемKonctantin Это имя известно всемKonctantin Это имя известно всемKonctantin Это имя известно всем
По умолчанию

Тема еще актуальна?
__________________
Konctantin вне форума   Ответить с цитированием
Старый 18.08.2010, 15:53   #15
Fmut
Пользователь
 
Регистрация: 20.06.2010
Сообщений: 42
Сказал(а) спасибо: 4
Поблагодарили 5 раз(а) в 5 сообщениях
Fmut На верном пути
По умолчанию

Вот держите, Наш вариант 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)
Fmut вне форума   Ответить с цитированием
Пользователь сказал cпасибо:
alien (22.09.2010)
Старый 18.08.2010, 16:11   #16
Konctantin
RuDB Dev
 
Аватар для Konctantin
 
Регистрация: 01.02.2010
Адрес: localhost
Сообщений: 592
Сказал(а) спасибо: 323
Поблагодарили 283 раз(а) в 122 сообщениях
Записей в дневнике: 2
Konctantin Это имя известно всемKonctantin Это имя известно всемKonctantin Это имя известно всемKonctantin Это имя известно всемKonctantin Это имя известно всемKonctantin Это имя известно всем
По умолчанию

а у нас есть 2 вида парсеров ХМЛ структуры и хард код, править структуры (ХМЛ парсер) можно не закрывая сам парсер, есть возможность перегрузки структур.
__________________
Konctantin вне форума   Ответить с цитированием
Старый 20.08.2010, 18:48   #17
alien
Ученый
 
Регистрация: 17.05.2010
Сообщений: 148
Сказал(а) спасибо: 18
Поблагодарили 25 раз(а) в 22 сообщениях
alien На верном пути
По умолчанию

да тема актуально. Просто я щас в таком месте где компа под рукой нету. как приеду буду дописывать.
Зы у меня тоже скрипты луашные тоже без перезапуска программы обновляются
alien вне форума   Ответить с цитированием
Старый 21.08.2010, 08:32   #18
ispanec
Новичок
 
Регистрация: 08.03.2010
Сообщений: 26
Сказал(а) спасибо: 1
Поблагодарили 4 раз(а) в 4 сообщениях
ispanec На верном пути
По умолчанию

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

Или же разделить как-то, простые пакеты обрабатывать по структуре, а сложные скриптом.
"Работам техничкам ничо не знам" и сейчас может хрень спорю, но что мешает хранить всё в JSON (http://www.json.org/json-ru.html), а потом его "парсить" - есть готовые (де)сериализаторы.
ispanec вне форума   Ответить с цитированием
Старый 21.08.2010, 08:52   #19
Konctantin
RuDB Dev
 
Аватар для Konctantin
 
Регистрация: 01.02.2010
Адрес: localhost
Сообщений: 592
Сказал(а) спасибо: 323
Поблагодарили 283 раз(а) в 122 сообщениях
Записей в дневнике: 2
Konctantin Это имя известно всемKonctantin Это имя известно всемKonctantin Это имя известно всемKonctantin Это имя известно всемKonctantin Это имя известно всемKonctantin Это имя известно всем
По умолчанию

а это кому как удобней...
__________________
Konctantin вне форума   Ответить с цитированием
Старый 18.04.2011, 01:46   #20
RomanRom2
WowCore Dev
 
Аватар для RomanRom2
 
Регистрация: 31.03.2010
Сообщений: 468
Сказал(а) спасибо: 73
Поблагодарили 106 раз(а) в 70 сообщениях
RomanRom2 Это имя известно всемRomanRom2 Это имя известно всемRomanRom2 Это имя известно всемRomanRom2 Это имя известно всемRomanRom2 Это имя известно всемRomanRom2 Это имя известно всем
По умолчанию

в общем повтыкал я в этот JSON...
все отлично, все замечательно просто, ровно до того места, когда нужно сделать зависимость от байта (или того интересней - от флага). или счетчики структур. короче не подходит. надо скриптовые движки использовать. ну или что то свое городить...
RomanRom2 вне форума   Ответить с цитированием
Старый 20.04.2011, 16:36   #21
HuntsMan
Ученый
 
Аватар для HuntsMan
 
Регистрация: 19.12.2010
Сообщений: 221
Сказал(а) спасибо: 64
Поблагодарили 12 раз(а) в 9 сообщениях
Записей в дневнике: 2
HuntsMan На верном пути
По умолчанию

Я обработчики пишу на шарпе без привлечения сторонних движков, и не жалуюсь
HuntsMan вне форума   Ответить с цитированием
Старый 20.04.2011, 16:45   #22
Йоха
Умный
 
Регистрация: 02.07.2010
Сообщений: 434
Сказал(а) спасибо: 27
Поблагодарили 73 раз(а) в 45 сообщениях
Йоха Скоро придёт к известности
По умолчанию

Цитата:
Сообщение от HuntsMan Посмотреть сообщение
Я обработчики пишу на шарпе без привлечения сторонних движков, и не жалуюсь
Это не очень удобно, структура постоянно меняется от билда к билду, и с каждым билдом надо пересобирать программу. Потом по мере разбора новых опокодов опять дописывать код и компилировать ...
А со скриптами гораздо проще, поправил текстовый файлик и вперед
Йоха вне форума   Ответить с цитированием
Старый 20.04.2011, 16:49   #23
Lordronn
Умный
 
Регистрация: 17.06.2010
Сообщений: 397
Сказал(а) спасибо: 58
Поблагодарили 55 раз(а) в 38 сообщениях
Lordronn Скоро придёт к известности
По умолчанию

Цитата:
Потом по мере разбора новых опокодов опять дописывать код и компилировать ...
Десериализация рулит
Lordronn вне форума   Ответить с цитированием
Старый 20.04.2011, 16:59   #24
Йоха
Умный
 
Регистрация: 02.07.2010
Сообщений: 434
Сказал(а) спасибо: 27
Поблагодарили 73 раз(а) в 45 сообщениях
Йоха Скоро придёт к известности
По умолчанию

эм... не совсем понятно
объясни что имеется в виду
Йоха вне форума   Ответить с цитированием
Старый 20.04.2011, 19:18   #25
Lordronn
Умный
 
Регистрация: 17.06.2010
Сообщений: 397
Сказал(а) спасибо: 58
Поблагодарили 55 раз(а) в 38 сообщениях
Lordronn Скоро придёт к известности
По умолчанию

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

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

Скрытый текст (вы должны войти под своим логином или зарегистрироваться и иметь 50 сообщение(ий)):
У вас нет прав чтобы видеть скрытый текст, содержащейся здесь.
Lordronn вне форума   Ответить с цитированием
Старый 20.04.2011, 19:33   #26
Йоха
Умный
 
Регистрация: 02.07.2010
Сообщений: 434
Сказал(а) спасибо: 27
Поблагодарили 73 раз(а) в 45 сообщениях
Йоха Скоро придёт к известности
По умолчанию

да епрст, ну об этом же и говорится, что формат пакетов задается внешними файлами.
там просто HuntsMan написал что у него обработчики захардкодены, вот это и неудобно
Йоха вне форума   Ответить с цитированием
Старый 20.04.2011, 19:56   #27
Lordronn
Умный
 
Регистрация: 17.06.2010
Сообщений: 397
Сказал(а) спасибо: 58
Поблагодарили 55 раз(а) в 38 сообщениях
Lordronn Скоро придёт к известности
По умолчанию

Я сейчас с этим мучаюсь. Написал около 100 обработчиков в коде. Теперь мучаюсь с их переносом в XML-ки
Lordronn вне форума   Ответить с цитированием
Старый 20.04.2011, 20:00   #28
LordJZ
Супер-модератор
 
Аватар для LordJZ
 
Регистрация: 07.03.2010
Сообщений: 647
Сказал(а) спасибо: 100
Поблагодарили 252 раз(а) в 123 сообщениях
LordJZ Как самоцвет среди гранитаLordJZ Как самоцвет среди гранитаLordJZ Как самоцвет среди гранита
По умолчанию

А у меня для обработки пакетов используется вот такой интерфейс:
Скрытый текст (вы должны войти под своим логином или зарегистрироваться и иметь 10 сообщение(ий)):
У вас нет прав чтобы видеть скрытый текст, содержащейся здесь.
*PROUD*
LordJZ вне форума   Ответить с цитированием
Старый 20.04.2011, 21:03   #29
zergtmn
MaNGOS Dev
 
Аватар для zergtmn
 
Регистрация: 07.03.2010
Сообщений: 314
Сказал(а) спасибо: 30
Поблагодарили 153 раз(а) в 83 сообщениях
zergtmn Обладатель прекрасной аурыzergtmn Обладатель прекрасной ауры
По умолчанию

Цитата:
Сообщение от Йоха Посмотреть сообщение
обработчики захардкодены, вот это и неудобно
Зато удобно делать произвольную фильтрацию и собирать данные для внесения в базу.
zergtmn вне форума   Ответить с цитированием
Старый 20.04.2011, 21:18   #30
Lordronn
Умный
 
Регистрация: 17.06.2010
Сообщений: 397
Сказал(а) спасибо: 58
Поблагодарили 55 раз(а) в 38 сообщениях
Lordronn Скоро придёт к известности
По умолчанию

Это да, это можно только через код. Но речь идет о мелких пакетах типа CMSG_QUEST_QUERY и о пакетах из который не получить информации для базы. У меня для пакетов(респонзы, вендор лист, и т.п) сделан специальный оутпут в скул. Достаточно нажать на одну кнопочку в меню и выбрать директорию. Для UPDATE_OBJECT у меня плагин написан
Lordronn вне форума   Ответить с цитированием
Старый 21.04.2011, 07:05   #31
TOM_RUS
MaNGOS Dev
 
Регистрация: 11.03.2010
Сообщений: 468
Сказал(а) спасибо: 0
Поблагодарили 514 раз(а) в 163 сообщениях
TOM_RUS Как свет с небесTOM_RUS Как свет с небесTOM_RUS Как свет с небесTOM_RUS Как свет с небесTOM_RUS Как свет с небесTOM_RUS Как свет с небес
По умолчанию

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

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>

Последний раз редактировалось TOM_RUS; 21.04.2011 в 07:17.
TOM_RUS вне форума   Ответить с цитированием
Старый 21.04.2011, 07:41   #32
HuntsMan
Ученый
 
Аватар для HuntsMan
 
Регистрация: 19.12.2010
Сообщений: 221
Сказал(а) спасибо: 64
Поблагодарили 12 раз(а) в 9 сообщениях
Записей в дневнике: 2
HuntsMan На верном пути
По умолчанию

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

Опять же большую часть пакетов я стараюсь парсить и в 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

Последний раз редактировалось HuntsMan; 21.04.2011 в 07:50.
HuntsMan вне форума   Ответить с цитированием
Старый 21.04.2011, 08:50   #33
TOM_RUS
MaNGOS Dev
 
Регистрация: 11.03.2010
Сообщений: 468
Сказал(а) спасибо: 0
Поблагодарили 514 раз(а) в 163 сообщениях
TOM_RUS Как свет с небесTOM_RUS Как свет с небесTOM_RUS Как свет с небесTOM_RUS Как свет с небесTOM_RUS Как свет с небесTOM_RUS Как свет с небес
По умолчанию

Цитата:
Сообщение от HuntsMan Посмотреть сообщение
ЗЫ: Лучше уж lua чем xml
И зачем этот геморой с lua, если даже встроенной поддержки lua в .NET Framework нет? С XML все прекрасно работает.
TOM_RUS вне форума   Ответить с цитированием
Старый 21.04.2011, 09:58   #34
HuntsMan
Ученый
 
Аватар для HuntsMan
 
Регистрация: 19.12.2010
Сообщений: 221
Сказал(а) спасибо: 64
Поблагодарили 12 раз(а) в 9 сообщениях
Записей в дневнике: 2
HuntsMan На верном пути
По умолчанию

Цитата:
Сообщение от TOM_RUS Посмотреть сообщение
И зачем этот геморой с lua, если даже встроенной поддержки lua в .NET Framework нет? С XML все прекрасно работает.
lua визуально понятнее
HuntsMan вне форума   Ответить с цитированием
Старый 21.04.2011, 11:19   #35
Konctantin
RuDB Dev
 
Аватар для Konctantin
 
Регистрация: 01.02.2010
Адрес: localhost
Сообщений: 592
Сказал(а) спасибо: 323
Поблагодарили 283 раз(а) в 122 сообщениях
Записей в дневнике: 2
Konctantin Это имя известно всемKonctantin Это имя известно всемKonctantin Это имя известно всемKonctantin Это имя известно всемKonctantin Это имя известно всемKonctantin Это имя известно всем
По умолчанию

Ну если уж на то пошло, то проще тогда выполнять динамическую компиляцию, и писать все на С#, но не lua.
__________________
Konctantin вне форума   Ответить с цитированием
Старый 21.04.2011, 18:41   #36
alien
Ученый
 
Регистрация: 17.05.2010
Сообщений: 148
Сказал(а) спасибо: 18
Поблагодарили 25 раз(а) в 22 сообщениях
alien На верном пути
По умолчанию

Я думаю что если пишешь на шарпе то лучше не паримся и юзаем XML
Если на C/C++ то тогде уже лучше lua прикрутить.
alien вне форума   Ответить с цитированием
Старый 21.04.2011, 18:57   #37
TOM_RUS
MaNGOS Dev
 
Регистрация: 11.03.2010
Сообщений: 468
Сказал(а) спасибо: 0
Поблагодарили 514 раз(а) в 163 сообщениях
TOM_RUS Как свет с небесTOM_RUS Как свет с небесTOM_RUS Как свет с небесTOM_RUS Как свет с небесTOM_RUS Как свет с небесTOM_RUS Как свет с небес
По умолчанию

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

Последний раз редактировалось TOM_RUS; 21.04.2011 в 19:01.
TOM_RUS вне форума   Ответить с цитированием
Старый 28.04.2011, 10:38   #38
Йоха
Умный
 
Регистрация: 02.07.2010
Сообщений: 434
Сказал(а) спасибо: 27
Поблагодарили 73 раз(а) в 45 сообщениях
Йоха Скоро придёт к известности
По умолчанию

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

[добавлено]

Цитата:
Я думаю «народный» аналог PacketViewer-а от TOM_RUS или zPktViewer-а, с поддержкой последних форматов сниффов (у меня сейчас самые распространенные — три) был бы гораздо полезнее, чем народный-же сниффер.
Я набросал каркас приложения, но как мне кажется никто заниматься этим не будет ...
Миниатюры
Нажмите на изображение для увеличения
Название: screen.jpg
Просмотров: 763
Размер:	25.3 Кб
ID:	866  

Последний раз редактировалось Йоха; 28.04.2011 в 13:07.
Йоха вне форума   Ответить с цитированием
Старый 28.04.2011, 14:47   #39
LordJZ
Супер-модератор
 
Аватар для LordJZ
 
Регистрация: 07.03.2010
Сообщений: 647
Сказал(а) спасибо: 100
Поблагодарили 252 раз(а) в 123 сообщениях
LordJZ Как самоцвет среди гранитаLordJZ Как самоцвет среди гранитаLordJZ Как самоцвет среди гранита
По умолчанию

Ну PacketViewer от TOM_RUS открытый.
LordJZ вне форума   Ответить с цитированием
Старый 28.04.2011, 14:55   #40
Йоха
Умный
 
Регистрация: 02.07.2010
Сообщений: 434
Сказал(а) спасибо: 27
Поблагодарили 73 раз(а) в 45 сообщениях
Йоха Скоро придёт к известности
По умолчанию

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

Опции темы Поиск в этой теме
Поиск в этой теме:

Расширенный поиск
Опции просмотра

Ваши права в разделе
Вы не можете создавать новые темы
Вы не можете отвечать в темах
Вы не можете прикреплять вложения
Вы не можете редактировать свои сообщения

BB коды Вкл.
Смайлы Вкл.
[IMG] код Вкл.
HTML код Выкл.


Похожие темы
Тема Автор Раздел Ответов Последнее сообщение
Parser 4.x.x ANTOMA Tools 3 10.12.2010 18:15
MaNGOS баг-трекер (разработка) KiriX WWW 34 26.10.2010 12:45
wdb-parser Konctantin Tools 0 23.08.2010 11:14
[git] Командная разработка Hantet Новичкам 3 06.07.2010 09:01
Глобальный FAQ (разработка) Konctantin Новичкам 6 14.03.2010 10:46


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


ru-mangos.ru - Русское сообщество MaNGOS
Главная цель проекта MaNGOS - обучающая, поэтому разрешается использовать исходный код и собранную программу только для образовательных целей.
Вы не можете использовать MaNGOS в коммерческих целях, а также не разрешается устанавливать публичные серверы на базе MaNGOS.
Любое копирование материалов, информации в любом виде без указания источника - форума Ru-MaNGOS будет считаться нарушением авторских прав и нарушением Уголовного Кодекса РФ, ст. 146 ст. 147.
Перевод vBulletin: zCarot