Просмотр полной версии : О плагинах для l2phx 3.4.1+
Итак вот подробное описание того какой должна быть структура плагина:
library plugin_demo2;
{$define Release} // для совместимости с релизом пакетхака, при дебуге можно закоментировать
uses
FastMM4,
Coding in 'Coding.pas'; // модуль с описаниями основных типов
// используемых в плагине и программе
var {version} {revision}
min_ver_a: array[0..3] of Byte = ( 3,4,1, 46 );
min_ver: Integer absolute min_ver_a; // минимальная поддерживаемая версия программы
ps: TPluginStruct; // структура передаваемая в плагин
// Обязательно вызываемая функция.
// Должна вернуть описание плагина,
// заодно может проверить версию программы
function GetPluginInfo(const ver: Integer): PChar; stdcall;
begin
if ver<min_ver then
Result:='Демонстрационный Plugin к программе l2phx'+sLineBreak+
'Для версий 3.4.0+'+sLineBreak+
'У вас старая версия программы! Плагин не сможет корректно с ней работать!'
else
Result:='Демонстрационный Plugin к программе l2phx'+sLineBreak+
'Для версий 3.4.0+';
end;
// Обязательно вызываемая функция.
// Получает структуру с ссылками на все функции основной программы,
// которые могут вызываться из плагина.
// Если вернёт False то плагин выгружается.
function SetStruct(const struct: TPluginStruct): Boolean; stdcall;
begin
ps:=struct;
Result:=True;
end;
// Необязательно вызываемая функция. (может отсутствовать в плагине)
// Вызывается при установки соединения (cnt) с клиентом (withServer=False)
// или сервером (withServer=True)
procedure OnConnect(const cnt: Cardinal; // номер соединения
const withServer: Boolean); stdcall; // с сервером?
begin
end;
// Необязательно вызываемая функция. (может отсутствовать в плагине)
// Вызывается при разрыве соединения (cnt) с клиентом (withServer=False)
// или сервером (withServer=True)
procedure OnDisconnect(const cnt: Cardinal; // номер соединения
const withServer: Boolean); stdcall; // с сервером?
begin
end;
// Необязательно вызываемая функция. (может отсутствовать в плагине)
// Вызывается при выгрузке плагине
procedure OnFree; stdcall;
begin
end;
// Необязательно вызываемая функция. (может отсутствовать в плагине)
// Вызывается при загрузке плагине
procedure OnLoad; stdcall;
begin
end;
// Необязательно вызываемая функция. (может отсутствовать в плагине)
// Вызывается при вызове скриптовой функции обьявленной в RefreshPrecompile
function OnCallMethod(const MethodName: String; // имя функции в верхнем регистре
var Params, // параметры функции
FuncResult: Variant // результат функции
): Boolean; stdcall; // если вернёт True то дальнейшая
// обработка функции прекратиться
begin
Result:=False; // передаём обработку функции программе
if MethodName='PI' then begin
Result:=True; // запрещаем дальнейшую обработку функции в программе
FuncResult:=Pi;
end;
end;
// Необязательно вызываемая функция. (может отсутствовать в плагине)
// Вызывается перед компиляцией скриптов
function OnRefreshPrecompile(var funcs: TStringArray): Integer; stdcall;
begin
SetLength(funcs,1); // указываем количество добавляемых в скрипт функций
funcs[0]:='function Pi:Extended'; // одна из добавляемых функций
end;
// Необязательно вызываемая функция. (может отсутствовать в плагине)
// Вызывается при приходе пакета, параметры:
// cnt - номер соединения
// fromServer - если пакет от сервера равна True, если от клиента то False
// pck - собственно пакет (в виде массива)
procedure OnPacket(const cnt: Cardinal; const fromServer: Boolean; var pck: TPacket); stdcall;
begin
if pck.size<3 then exit; // на случай если предыдущие плагины обнулили пакет
end;
// экспортируем используемые программой функции
exports
GetPluginInfo,
SetStruct,
OnPacket,
OnConnect,
OnDisconnect,
OnLoad,
OnFree,
OnCallMethod,
OnRefreshPrecompile;
begin
end.
о передоваемой плагину структуре TPluginStruct:
TPluginStruct = packed record
Threads: PThreads; // указатель на первый элемент массива TThread
// через него можно получить доступ к любой переменной соединения
ThreadsCount: Integer; // максимальное число соединений
//(не путать с количеством реально установленых соединений!)
// функции отправки пакета:
SendPck: TSendPacket;
SendPckStr: TSendPckStr;
SendPckData: TSendPckData;
// функции преобразования:
DataPckToStrPck: TDataPckToStrPck; // преобразует пакет из массива в строку и отрезает 2 байта длинны
HexToString:THexToString; // преобразует Hex пакета в просто пакет в виде строки
StringToHex:TStringToHex; // наоборот
// функции чтения из пакета в виде строки:
ReadC: TReadC;
ReadH: TReadH;
ReadD: TReadD;
ReadF: TReadF;
ReadS: TReadS;
// функции чтения из пакета в виде массива:
ReadCEx: TReadCEx;
ReadHEx: TReadHEx;
ReadDEx: TReadDEx;
ReadFEx: TReadFEx;
ReadSEx: TReadSEx;
// функции записи в пакет в виде строки:
WriteC: TWriteC;
WriteH: TWriteH;
WriteD: TWriteD;
WriteF: TWriteF;
WriteS: TWriteS;
// функции записи в пакет в виде массива:
WriteCEx: TWriteCEx;
WriteHEx: TWriteHEx;
WriteDEx: TWriteDEx;
WriteFEx: TWriteFEx;
WriteSEx: TWriteSEx;
// функции работы с таймером на основе отдельного потока:
CreateAndRunTimerThread: TCreateAndRunTimerThread; // создаёт и запускает таймер
ChangeTimerThread: TChangeTimerThread; // может изменить интервал, параметр
// пользователя и процедуру вызываемую таймером
DestroyTimerThread: TDestroyTimerThread; // останавливает и уничтожает таймер
end;
у функций чтения первый параметр это пакет, второй - позиция с которой производиться чтение
у функций записи первый параметр это пакет, второй - записываемые данные, третий - индекс в который производиться запись, если 3й параметр не задан или равен -1, то данные пишутся в конец пакета
о параметрах остальных функций из структуры:
procedure SendPacket(Size: Word; // размер пакета (размер pck +2)
pck: string; // пакет в виде строки без первых 2х байт длинны
tid: Byte; // номер соединения
ToServer: Boolean); // направление отсылки, если True то на сервер
procedure SendPckStr(pck: string; // пакет в виде строки без первых 2х байт длинны
const tid: Byte; // номер соединения
const ToServer: Boolean); // направление отсылки, если True то на сервер
procedure SendPckData(var pck; // пакет в виде массива
const tid: Byte; // номер соединения
const ToServer: Boolean // направление отсылки, если True то на сервер
); stdcall;
function DataPckToStrPck(var pck // пакет в виде массива
): string; stdcall; // возвращает пакет в виде строки
function HexToString(Hex:String // HEX строка
):String;
function StringToHex(s, // пакет в виде строки
Separator:String // разделитель между байтами
):String;
function CreateAndRunTimerThread(const interval, // интервал срабатывания таймера
usrParam: Cardinal; // параметр передаваемый в процедуру OnTimerProc
const OnTimerProc: TOnTimer // вызывается при срабатывании таймера
): Pointer; stdcall; // возвращает указатель на объект потока
procedure ChangeTimerThread(const timer: Pointer; // указатель на объект потока
const interval: Cardinal; // интервал срабатывания таймера
const usrParam: Cardinal = $ffffffff;
// параметр передаваемый в процедуру OnTimerProc,
// если равен $ffffffff, то не меняется
const OnTimerProc: TOnTimer = nil
// вызывается при срабатывании таймера, если nil - не меняется
); stdcall;
procedure DestroyTimerThread(var timer: Pointer // указатель на объект потока
); stdcall;
Ещё пожалуй расскажу о том как наиболее удобно отлаживать плагин
Вариант 1 (отладка только плагина):
1. Компилим плагин
2. Запускаем пакетхак
3. В delphi выбираем меню Run -> Attach to Process...
4. там находим и выбираем l2pbx.exe, убираем галочку "Pause After Attach" и жмём Attach
5. В пакетхаке подключаем плагин
6. Усё, можем ставить бряки в плагине
Вариант 2 (отладка программы вместе с плагином):
1. В дельфи создаём группу из проекта программы и проекта плагина
2. Компилим оба проекта (не забываем указать путь компиляции для плагина в папку plugins)
3. Запускаем программу с дебугом
4. В программе подключаем плагин и дельфи автоматически распознаёт что эта dll из группы и даёт возможность ставить бряки и в проекте плагина
Первый вариант позволяет отлаживать плагин без перекомпиляции основной программы, тоесть можно работать только с плагином
Второй позволяет отлаживать всё сразу
ЗЫ описание на основе дельфи 2007, но в 2006 скорее всего всё так же, а в более ранних версиях думаю тоже должны быть аналогичные возможности, но возможно немного в других местах
А как насчёт расписать TPacket?
Что включает параметр size, data?
Например содержится ли TPacket.id ещё и в TPacket.data[0]?
TPacket.size указывает размер всего пакета, или только данных? (хотя по проверке pck.size<3 я считаю что это длина всего пакета с байтами длины и айдишкой, но лучше перестраховаться)
Xelat, структура TPacket описана в файле Coding.pas вот так:
PPacket = ^TPacket;
TPacket = record
size: Word;
id: Byte;
data: array[Word] of Byte;
end;
Ну блин, структуру я не идиот, там и смотрел! :)
Я ж не структу прошу расписать, а ньюансы полей.
А вот в SendPckData с массивом вообще не понятно, ну передам я массив байт, а как определяется конец пакета? Или надо передавать массив вместе с длиной пакета?
А так же в чём разница между процедурами SendPacket и SendPckStr? Первая отсекает строку заданного размера?
Вобщем подробностей бы побольше! :)
А в плагинах VCL можно использовать?
А в плагинах VCL можно использовать?можно, только осторожно =) и вообще нафиг тебе VCL?
Хочу сервер сделать с помощью компонента ServerSocket, чтоб можно было проходящие пакеты удаленно принимать.
Хочу сервер сделать с помощью компонента ServerSocket, чтоб можно было проходящие пакеты удаленно принимать.да вы. батенька, маньяк =) не иначе что-то хитрое задумал =)
Ничего хитрого, просто GG всю отладку рубит, хотю на другой машине или под виртуалкой это делать :)
я уже написал такой плагин, использую для своего бота... использовал в нём ICS.
Ну поделись если не жалко. Я пока непойму как назначить обработчик события без наличия формы, такая конструкция Serversocket1.OnClientRead:=Serversocket1ClientRea d; непрокатывает...
У тебя наверное Serversocket1.OnClientRead -> метод класса, а Serversocket1ClientRea -> процедура и ты их напрямую пытаешься присвоить. Только у методов класса два указателя - на инстанцию класса и на сам метод, поэтому и не получается. Попробуй свою процедуру Serversocket1ClientRea засунь в какой-нибудь класс, и тогда присваивай.
бери пример от ICS - ConSrv1
и от него уже пляши, я так и делал.
если тебе не интересно самому разрабатывать плагин, а нужен только результат - стучи в аську.
Ничего хитрого, просто GG всю отладку рубит, хотю на другой машине или под виртуалкой это делать :)
А примотать к Л2пх сокс прокси не проще?
приветы,
вот возникла такая вот ситуевина:
procedure OnPacket(const cnt: Cardinal; const fromServer: Boolean; var pck: TPacket); stdcall;
begin
if pck.size<3 then
exit;
if not FromServer and(pck.id=$49)and(bot.cntID=0)then
begin
// если в процедуре вызвать ps.ReadSEx
// то после завершения процедурки
// выскакивает ексепшн EInvalidPointer
if(lowercase(ps.ReadSEx(pck,3))='set')then
begin
pck.size:=2; // не пропускаем пакет
bot.cntID:=cnt;
Say('Выбрано это соединение.',bot.cntID);
end;
end;
end;
пробывал заменить на
s:=ps.DataPckToStrPck(pck);
if(lowercase(ps.ReadS(s,2))='set')then
выходит аналогичная ошибка.
мб ктонить подскажет, в какую сторону копать.
зы: HB T1.5, пхикс 3.4.81 ( 3.4.68 ) под ХП СП3 крутится на виртуальной машине
alexsl, дельфа какая версия?
QaK, угу забыл указать юзаю Д7. спсб, попробую скомпилить под Д2005
alexsl, вот поэтому и эксепшн вылазит, перекомпиль в 200х норм должно пхать, хз с чем связано ...
как не печально но при компиляции под D2005 результат тот же :(
ошибка:
================================================== ============================
= 26.01.2009 7:19:07 =
================================================== ============================
EInvalidPointer.
Exception class: EInvalidPointer
Exception address: 009F2990
------------------------------------------------------------------------------
System : Windows XP Professional, Version: 5.1, Build: A28, "Service Pack 3"
Processor: Intel, Pentium(R) Dual-Core CPU E5200 @ 2.50GHz, 2490 MHz MMX 64 bits
Memory: 255; free 136
Display : 688x595 pixels, 32 bpp
------------------------------------------------------------------------------
List of loaded modules:
[00340000] C:\WINDOWS\system32\oledlg.dll
<7DFC0000> 5.1.2600.5512 - 1.0 (xpsp.080413-2108)
Поддержка интерфейса пользователя OLE 2.0 для Microsoft WindowsR
[00400000] C:\WINDOWS\system32\Normaliz.dll
6.0.5441.0 - 6.0.5441.0 (winmain(wmbla).060628-1735)
Unicode Normalization DLL
[009F0000] Z:\L2PHX34159\plugins\helper.dll
<00400000> (no version info)
[00EA0000] Z:\L2PHX34159\newxor.dll
<00400000> (no version info)
[01520000] Z:\L2PHX34159\plugins\plugin_bd.dll
<00400000> (no version info)
[13140000] Z:\L2PHX34159\l2pbx.exe
3.4.1.59 - 3.4.1.59
[43090000] C:\WINDOWS\system32\iertutil.dll
7.0.6000.20772 - 7.00.6000.20772 (vista_ldr.080213-1606)
Run time utility for Internet Explorer
[43310000] C:\WINDOWS\system32\wininet.dll
7.0.6000.20772 - 7.00.6000.20772 (vista_ldr.080213-1606)
Internet Extensions for Win32
[5B260000] C:\WINDOWS\system32\uxtheme.dll
6.0.2900.5512 - 6.00.2900.5512 (xpsp.080413-2105)
Библиотека тем UxTheme (Microsoft)
[5F2F0000] C:\WINDOWS\system32\olepro32.dll
5.1.2600.5512 - 5.1.2600.5512
[698B0000] C:\WINDOWS\system32\hnetcfg.dll
5.1.2600.5589 - 5.1.2600.5589 (xpsp_sp3_qfe.080428-1317)
Диспетчер конфигурации домашней сети
[71A30000] C:\WINDOWS\system32\mswsock.dll
5.1.2600.5512 - 5.1.2600.5512 (xpsp.080413-0852)
Расширение поставщика службы API Microsoft Windows Sockets 2.0
[71A70000] C:\WINDOWS\System32\wshtcpip.dll
5.1.2600.5512 - 5.1.2600.5512 (xpsp.080413-0852)
Windows Sockets Helper DLL
[71A80000] C:\WINDOWS\system32\WS2HELP.dll
5.1.2600.5512 - 5.1.2600.5512 (xpsp.080413-0852)
Модуль поддержки Windows Socket 2.0 для Windows NT
[71A90000] C:\WINDOWS\system32\WS2_32.dll
5.1.2600.5512 - 5.1.2600.5512 (xpsp.080413-0852)
Windows Socket 2.0 32-Bit DLL
[71AB0000] C:\WINDOWS\system32\wsock32.dll
5.1.2600.5512 - 5.1.2600.5512 (xpsp.080413-0852)
32-разрядная библиотека Windows Socket
[71B00000] C:\WINDOWS\system32\mpr.dll
5.1.2600.5512 - 5.1.2600.5512 (xpsp.080413-0852)
Библиотека маршрутизации для нескольких служб доступа
[72FC0000] C:\WINDOWS\system32\winspool.drv
5.1.2600.5512 - 5.1.2600.5512 (xpsp.080413-0852)
Драйвер диспетчера очереди Windows
[746E0000] C:\WINDOWS\system32\MSCTF.dll
5.1.2600.5512 - 5.1.2600.5512 (xpsp.080413-2105)
Библиотека (DLL) MSCTF-сервера
[74DF0000] C:\WINDOWS\system32\RICHED20.DLL
5.30.23.1230 - 5.30.23.1230
Rich Text Edit Control, v3.0
[75310000] C:\WINDOWS\system32\msctfime.ime
5.1.2600.5512 - 5.1.2600.5512 (xpsp.080413-2105)
Microsoft Text Frame Work Service IME
[76360000] C:\WINDOWS\system32\IMM32.DLL
5.1.2600.5512 - 5.1.2600.5512 (xpsp.080413-2105)
Windows XP IMM32 API Client DLL
[76380000] C:\WINDOWS\system32\comdlg32.dll
6.0.2900.5512 - 6.00.2900.5512 (xpsp.080413-2105)
Библиотека общих диалоговых окон
[76BE0000] C:\WINDOWS\system32\PSAPI.dll
5.1.2600.5512 - 5.1.2600.5512 (xpsp.080413-2105)
Process Status Helper
[77110000] C:\WINDOWS\system32\oleaut32.dll
5.1.2600.5512 - 5.1.2600.5512
[773C0000] C:\WINDOWS\WinSxS\x86_Microsoft.Windows.Common-Controls_6595b64144ccf1df_6.0.2600.5512_x-ww_35d4ce83\comctl32.dll
6.0.2900.5512 - 6.0 (xpsp.080413-2105)
User Experience Controls Library
[774D0000] C:\WINDOWS\system32\ole32.dll
5.1.2600.5512 - 5.1.2600.5512 (xpsp.080413-2108)
Microsoft OLE для Windows
[77BF0000] C:\WINDOWS\system32\version.dll
5.1.2600.5512 - 5.1.2600.5512 (xpsp.080413-2105)
Version Checking and File Installation Libraries
[77C00000] C:\WINDOWS\system32\msvcrt.dll
7.0.2600.5512 - 7.0.2600.5512 (xpsp.080413-2111)
Windows NT CRT DLL
[77DC0000] C:\WINDOWS\system32\ADVAPI32.dll
5.1.2600.5512 - 5.1.2600.5512 (xpsp.080413-2113)
Расширенная библиотека API Windows 32
[77E70000] C:\WINDOWS\system32\RPCRT4.dll
5.1.2600.5512 - 5.1.2600.5512 (xpsp.080413-2108)
Remote Procedure Call Runtime
[77F10000] C:\WINDOWS\system32\GDI32.dll
5.1.2600.5512 - 5.1.2600.5512 (xpsp.080413-2105)
GDI Client DLL
[77F60000] C:\WINDOWS\system32\SHLWAPI.dll
6.0.2900.2995 - 6.00.2900.2995 (xpsp.060913-0019)
Библиотека небольших программ оболочки
[77FE0000] C:\WINDOWS\system32\Secur32.dll
5.1.2600.5512 - 5.1.2600.5512 (xpsp.080413-2113)
Security Support Provider Interface
[7C800000] C:\WINDOWS\system32\kernel32.dll
5.1.2600.5512 - 5.1.2600.5512 (xpsp.080413-2111)
Библиотека клиента Windows NT BASE API
[7C900000] C:\WINDOWS\system32\ntdll.dll
5.1.2600.5594 - 5.1.2600.5594 (xpsp_sp3_qfe.080503-1404)
Системная библиотека NT
[7C9C0000] C:\WINDOWS\system32\shell32.dll
6.0.2900.5512 - 6.00.2900.5512 (xpsp.080413-2105)
Общая библиотека оболочки Windows
[7E360000] C:\WINDOWS\system32\USER32.dll
5.1.2600.5512 - 5.1.2600.5512 (xpsp.080413-2105)
Библиотека клиента USER API Windows XP
------------------------------------------------------------------------------
Active Controls hierarchy:
TCheckListBox "clbPluginsList"
TGroupBox "GroupBox5"
TTabSheet "tsPluginsTab"
TPageControl "PageControl1"
TL2PacketHackMain "L2PacketHackMain"
------------------------------------------------------------------------------
а это лог из самого плагина:
26.01.2009 7:24:59 - Для выбора нужного соединения наберите в чате слово "set" и отправьте
26.01.2009 7:24:59 - Invalid pointer operation
26.01.2009 7:25:08 - Выбрано это соединение.
26.01.2009 7:25:08 - Invalid pointer operation
зы: мб поделитесь инфой кто компилил работающий плагин под какой дельфи и пхикс.
Я компилил под 2006 (с хкор"овского фтпшника) для ПНХ 80/81.
Добавлено через 46 секунд
Кинь исходник или сюда или в личку стукни - спишемся.
кстати какие опции компиляции у тя стоят?
у муну в Д7:
-$A8
-$B-
-$C+
-$D+
-$E-
-$F-
-$G+
-$H+
-$I+
-$J-
-$K-
-$L+
-$M-
-$N+
-$O+
-$P+
-$Q-
-$R-
-$S-
-$T-
-$U-
-$V+
-$W-
-$X+
-$YD
-$Z1
-cg
-AWinTypes=Windows;WinProcs=Windows;DbiTypes=BDE;Db iProcs=BDE;DbiErrs=BDE;
-H+
-W+
-M
-$M16384,1048576
-K$00400000
-E"C:\Temp\L2PHX34159\plugins"
-LE"c:\program files\borland\delphi7\Projects\Bpl"
-LN"c:\program files\borland\delphi7\Projects\Bpl"
-w-UNSAFE_TYPE
-w-UNSAFE_CODE
-w-UNSAFE_CAST
Delphi 2007 c библиотеками которые нужны для компила пакетхака. на других обычно критует или длл или пакетхак. кароче хз в чем трабла :) а так работает и развивается потихоньку
Добавлено через 58 секунд
Зы брал у xkor'a c ftp
ИМХО в общем с менеджером памяти FastMM какая то замарочка,
он идет начиная с Д2007.
вот может поможет, лог:
--------------------------------2009/1/26 14:38:36--------------------------------
FastMM has detected an error during a FreeMem operation. The block header has been corrupted.
The current thread ID is 0x7D4, and the stack trace (return addresses) leading to this error is:
C12993 [System][@FreeMem]
C64B39 [C:\Work\l2phx.3.4.1.81\Source\helper.dpr][helper][OnLoad][128]
55E338 [phxPlugins.pas][phxPlugins][phxPlugins.TPlugin.LoadPlugin][188]
572E99 [main.pas][main][main.TL2PacketHackMain.clbPluginsListClickCheck][3750]
46F9C7 [Controls.pas][Controls][Controls.TControl.DoMouseDown][5252]
46FA15 [Controls.pas][Controls][Controls.TControl.WMLButtonDown][5261]
4733E4 [Controls.pas][Controls][Controls.TWinControl.WndProc][7304]
44CB88 [StdCtrls.pas][StdCtrls][StdCtrls.TCustomListBox.WndProc][4790]
472B0B [Controls.pas][Controls][Controls.TWinControl.MainWndProc][7073]
42F91E [common\Classes.pas][Classes][Classes.StdWndProc][11583]
7E368734 [Unknown function at GetDC]
--------------------------------2009/1/26 14:39:05--------------------------------
This application has leaked memory. The small block leaks are (excluding expected leaks registered by pointer):
5 - 12 bytes: AnsiString x 1
Note: Memory leak detail is logged to a text file in the same folder as this application. To disable this memory leak check, undefine "EnableMemoryLeakReporting".
зы: поиграюсь с опциями FastMM, мб че получится
Добавлено через 4 часа 43 минуты
в общем разобрался,если юзать оригинальный файл FastMM4Options.inc и объявить дерективы ShareMM и AttemptToUseSharedMM в проекте то все работает норм. проверено Д7, думаю д2005 и 2006 норм должны компилится.
зы: юзал ФастММ 4.92 и 4.9
кусок дллки для Д7, чтоб компилился нормально
library mylib;
{$define ShareMM}
{$define AttemptToUseSharedMM}
{$define RELEASE} // для совместимости с релизом пакетхака, при дебуге можно закоментировать
uses
FastMM4,
SysUtils,
Windows
.....
FastMM лежит тут http://fastmm.sourceforge.net
FastMM4Options.inc брал оригинальный
Начал попытки переписки скриптов в плагины, появились несколько вопросов
1.TReadDEx,TReadSEx и т.п при чтении не смещают index на количество прочтенных байт как в скрипте, так и должно быть?
2.как работает TDataPckToStrPck строка получается hex? или как?
и кто знает как отлаживать в в седьмой делфи, у меня никак не получилось(, аттачу ПХ и он отлаживать сразу начинает, даж плагин не включить!
p.s хорошо бы для образца каконибуть исходник плагина, или описание работы процедур и функций)
1.TReadDEx,TReadSEx и т.п при чтении не смещают index на количество прочтенных байт как в скрипте, так и должно быть?
угу, поскольку в качестве параметра может быть не только переменная но и просто число в плагине нельзя реализовать это как в скрипте.
2.как работает TDataPckToStrPck строка получается hex? или как?преобразует пакет из просто последовательности байт в памяти в строку, которая по сути та же последовательность байт, но с ней часто удобнее работать, hex тут не при чем...
и кто знает как отлаживать в в седьмой делфи, у меня никак не получилось(, аттачу ПХ и он отлаживать сразу начинает, даж плагин не включить!ну после атача просто нажимаешь F9, в пакетхаке подключаешь плагин и вуаля - можно останавливать бряки в плагине.
Только надо чтобы дельфя плагин компилила сразу в папку плагинов пакетхака, иначе она не поймет что тот плагин который ты включил тот же самый что ты отлаживаеш..
p.s хорошо бы для образца каконибуть исходник плагина, или описание работы процедур и функций)в SVN лежит два исходника плагинов - plugin_demo и plugin_demo2
Не мог разобраться с реализацией таймера плагине соорудил следующую конструкцию, вроде работает, но правильно ли? не будет затупов при долгой работе?:unknw:
также прописываются и другие события):cool:
......
type
aaa = class(TObject)
public
procedure CheckTime(Sender: TObject);
procedure FormClose(Sender: TObject; var Action: TCloseAction);
end;
var
FormMain : TForm;
CheckTimer: TTimer;
Msg : TMemo;
...........
.............
function Create_FormMain : TForm;
...........
.......
Result := TForm.Create(nil);
TRY
.......
Result.OnClose := aaa.Create.FormClose;
........
end;
...........
............
//чтобы форма не закрывалась
procedure aaa.FormClose(Sender: TObject; var Action: TCloseAction);
begin
Action:=caNone;
end;
//событие таймера
procedure aaa.CheckTime(Sender: TObject);
begin
msg.Lines.Add('test');
end;
procedure OnLoad; stdcall;
begin
FormMain:=Create_FormMain;
CheckTimer:=TTimer.Create(Application);
CheckTimer.OnTimer:=aaa.Create.CheckTime;
CheckTimer.interval:=2000; //время задержки
CheckTimer.enabled:=false;
end;
.........
а для чего в проекте используется FastMM4?
FastMM4 используеться для улутшения работы с памятью... восновном сказываеться на стабильность работы бинарника ;-)
а для чего в проекте используется FastMM4?
для того чтобы плагины и программа юзали один менаджер памяти, иначе нельзя бы было передавать стринги между плагином и программой и другие динамические массивы...
Драсте.
В гайде ФС:
Вы не можете объявить класс в скрипте, но вы можете использовать внешние классы, объявленные в вашем приложении или в дополнительных модулях.
Собстно вопрос: как из скрипта обратится к классу объявленному в ДЛЛ, или , что значит "можете использовать внешние классы"??
Добавлено через 53 минуты
или может так:
В длл есть возможность експортировать переменные, у меня эта переменная имеет тип класса объявленного в длл. Как из скрипта достучаться до этой переменной??
alexteam
20.05.2009, 12:10
никак. пх 2.5.х и ниже может експортировать из длл только процедуры/функции.
пх 2.5.х и че за версия? может 3.5.х
alexteam
20.05.2009, 12:58
упс... опичаталси... :p
ну я бы ещё уточнил что из длл не только в пакетхаке нельзя классы экспортировать, как правило их вообще нельзя экспортировать из длл
исключения составляют только длл на .НЕТ (но их можно юзать только из программ на .НЕТ) и пакеты дельфи (но они собсно тоже не обычные длл а очень специфические)
из дллок экспортируют только интерфейсы (это что то типа расширения классов)
ЗЫ кстати в 3.6.х версиях пакетхака вроде можно создавать свои классы в скриптах
ЗЫ а вообще под внешними классами имелись в виду базовые классы встроенные в программу типа TForm, TButton...
Мучался-мучался с попытками создать хотя бы один плагин под последний зарелизеный пакетхак, но ничего у меня не получилось, то не к той памяти обратится, то вообще вылетит и ничего не скажет, а потом решил посмотреть на Changelog к последней версии, и обнаружил там следующую весчь:
в onpacket функцию плагинов теперь передается имя соединения (TOnPacket = procedure(const cnt: Cardinal; const fromServer: Boolean; const connectionname:string; var packet : tpacket); stdcall;)
И соответсвенно у меня просьба=) где можно узнать, или у кого, обо всех таких изменениях?) ну и как минимум последний uSharedStructs бы вытянуть
Kennedy, на SVN (http://l2phx.pp.ru/wsvn/listing.php?repname=l2phx3&path=%2F&sc=1) посмотреть отличия версий.
Спасибо за столь быстрый ответ;)
Однако добиться исправной работы даже порезанного demo плагина у меня не получилось.Вот то что я сделал в итоге с исходником после нескольких часов его мучения:
library plugin_demo;
uses
FastMM4 in '..\fastmm\FastMM4.pas',
FastMM4Messages in '..\fastmm\FastMM4Messages.pas',
SysUtils,
Windows,
dialogs,
Classes,
usharedstructs in '..\units\usharedstructs.pas';
var {version} {revision}
min_ver_a: array[0..3] of Byte = ( 3,5,12, 120 );
min_ver: Integer absolute min_ver_a;
ps: TPluginStruct;
pps: PPluginStruct;
ppck: PPacket;
const
pause=15000;
var
ColvoHP, CharObjID, ItemObjHP: integer;
CurHP, MaxHP, lastHP, cntHP:integer;
TimerHP: Boolean;
StatusHP: Boolean;
function GetPluginInfo(const ver: Integer): PChar; stdcall;
begin
if ver<min_ver then
Result:='плаг'+sLineBreak+
'Для версий 3.5.12.120+'+sLineBreak+
'стар'
else
Result:='плаг'+sLineBreak+
'Для версий 3.5.12.120+'+sLineBreak+
'Автовыпивалка НР бутылок';
end;
procedure Say(msg:string); stdcall;
var
buf:String;
begin
ps.WriteC(buf,$4A);
ps.WriteD(buf,0);
ps.WriteD(buf,2);
ps.WriteS(buf,'AutoHP');
ps.WriteS(buf,msg + ps.getConnectionName(cntHP));
ps.WriteH(buf,0);
ps.SendPacketStr(buf,cntHP,False);
end;
function SetStruct(const struct: PPluginStruct): Boolean; stdcall;
begin
ps := TPluginStruct(struct^);
pps := struct;
Result:=True;
end;
procedure StatsUpdate;
var
i: integer;
begin
for i:=0 to ps.ReadDEx(ppck^,7)-1 do
case ppck^.data[i*8+8] of
$09: CurHP:=ps.ReadDEx(ppck^,i*8+15);
$0A: MaxHP:=ps.ReadDEx(ppck^,i*8+15);
end;
say('CurHP/MaxHP = '+inttostr(curhp)+'/'+inttostr(maxhp));
if (CurHP<=MaxHP-50) then TimerHP:=true else TimerHP:=false;
end;
procedure OnLoad; stdcall;
begin
statusHP:=false;
CharObjID:=0;
ItemObjHP:=0;
TimerHP:=false;
lastHP:=0;
cntHP := -1;
end;
procedure OnPacket(const cnt: Cardinal; const fromServer: Boolean; const connectionname:string; var pck: Tpacket); stdcall;
begin
if pck.size<3 then exit;
ppck:=@pck;
if not FromServer and(pck.pckId=$49)and(cntHP=-1)then
if(ps.ReadSEx(pck,3)='set')then begin
pck.pckSize:=0;
cntHP:=cnt;
Say('Выбрано это соединение.');
Say('Для...');
end;
end;
exports
GetPluginInfo,
OnPacket,
OnLoad,
SetStruct;
begin
end.
Плагин загружаю когда чара уже выбрали, дальше пишу set и в чат клиента пишется всего одна строчка "Выбрано это соединение" вместе с месседжем:
Application error. Exception EInvalidPointer in module plugin_demo.dll at xxx
Т.е. раз сообщение дошло то строчка в процедуре Say ps.SendPacketStr(buf,cntHP,False);
выполняется. И исключение срабатывает на выходе из этой процедуры.
Использую CodeGear Delphi 2007. Оригинальный плагин plugin_demo.pas из SVN.
alexteam
25.07.2009, 12:39
сломаны они, мне некогда переделывать взад. и остальным походу тоже.
юзаем рев 83.
Ммм... неужели с 83-й плагины не работали не разу?
В принципе есть желание заняться, только не все компоненты сторонние нашел для сборки пакетхака, если нетрудно сцыльте, перечислите или что-нить в этом роде)
Ммм... неужели с 83-й плагины не работали не разу?
В принципе есть желание заняться, только не все компоненты сторонние нашел для сборки пакетхака, если нетрудно сцыльте, перечислите или что-нить в этом роде)
Загляни в эту тему (http://coderx.ru/showthread.php?t=618), там всё есть. Xkor'a спроси доступ на SVN для записи. Удачи.
Kennedy, c 83й версии алекстим что-то с TPluginstruct намудрил, нужно привести в исходное состояние.
Тоже наткнулся на EInvalidPointer при написании плагинов...
Вообщето проблема эта давно известная при создании обычной dll в делфях есть забавный заголовок который нужно читать, там в начале написано что стринг нежелательно использовать а надо либо пчар либо шортстринг.
но а например WriteD не хочет принимать shortstring совсем....
alexteam
11.08.2009, 18:55
про пчары наем. замесы со стрингом тянуцца бог знает с какой версии -)
в принципе стоило бы реализовать readx по аналогии с онным в скриптовом движке (тобиш передача офсета в этой функции онли, а не гоняние строки с офсетом туды-сюды)
и ваабще. не работают readx ? реализуйте их сами в плагине!
структура ведь с данными о пришедшем пакете передается и весьма успешно. читайте прям с нее своими функциями минуя багнутые функции "импортируемые" с пх
//Qak: ага, как ломать - так все бацаки, а как починить - так все чатлане
Не могу понять как средствами плагина отправить пакет серверу, т.е. чтобы плагин отправлял параметр в скрипт и скрипт отправлял на сервер, или (лучше) сам плагин отправлял пакет.
Можно самый простой, например "Hello World"?
procedure SendPacket(Size: Word;pck: string; tid: Byte; ToServer: Boolean);
где
Size - размер пакета (размер pck +2)
pck - сам пакет
tid - номер соединения
ToServer - направление отсылки, True на сервер, False - на клиент
alexteam
10.05.2010, 16:45
через прослойку-скрипт чуть геморней.. но 100% работоспособно.
да и собирать/разбирать пакеты удобней.. во всяком случае плагин трогать не приходится.
Zergatul
18.08.2012, 17:38
Как правильно передавать параметр pck в
procedure SendPacketData(var pck; const tid: integer; const ToServer: Boolean); Virtual; Abstract;
Динамический массив? Если так, то почему тип не прописан статически
Добавлено через 2 часа 35 минут
Еще один вопрос:
пишу в коде
ps.SendPacketStr(#$46, cnt, true);
Типа RequestRestart для интерлюда, в итоге после выполнения этой строки происходит дисконект. Если отправлять через вкладку "Посылка", все работает корректно.
Версия: 3.5.34.176
alexteam
19.08.2012, 03:49
Динамический массив?
нет.
то почему тип не прописан
что значит "типо не прописан" ? он прописан. в явном виде.
var buf - указатель на данные.
пишу в коде
ты в качестве поинтера пытаешся какуюто хрень передать.
правильней так.
var
pck : TPacket;
begin
pck.size := 3;
pck.pckId := $46;
ps.SendPacketStr(pck, cnt, true);
Zergatul
20.08.2012, 14:47
var buf - указатель на данные.
Я предполагал, что это указатель на данные, но если это так, откуда процедура знает длину этих данных, если она просто смотрит на нее как на массив байт?
А под "не прописан тип" я имел ввиду, почему buf нетипизированый параметр
Добавлено через 2 минуты
ты в качестве поинтера пытаешся какуюто хрень передать.
правильней так.
var
pck : TPacket;
begin
pck.size := 3;
pck.pckId := $46;
ps.SendPacketStr(pck, cnt, true);
Эта функция требует первый параметр строку
Zergatul
20.08.2012, 23:17
procedure OnPacket(const cnt: Cardinal; const fromServer: Boolean; const connectionName: String; var pck: String); stdcall;
var
p: TPacket;
begin
if pck = #$1B#02#00#00#00 then
begin
p.pckSize := 3;
p.pckId := $46;
ps.SendPacketData(p, cnt, true);
Exit
end;
end;
Вот такой код, при выполнении вылетает. Лог на всякий случай прикрепил.
Может у меня старый юнит usharedstructs? Где можно взять самый новый?
vBulletin® v3.6.11, Copyright ©2000-2024, Jelsoft Enterprises Ltd. Перевод: zCarot