You've already forked rdsspy-lua-host
mirror of
https://github.com/KubaPro010/rdsspy-lua-host.git
synced 2026-02-26 18:35:01 +01:00
console as one way interface, and custom command along other things
This commit is contained in:
220
datxchng.dpr
Normal file
220
datxchng.dpr
Normal file
@@ -0,0 +1,220 @@
|
||||
library datxchng;
|
||||
|
||||
uses
|
||||
SysUtils, StrUtils, IniFiles,
|
||||
Classes;
|
||||
|
||||
{$R *.res}
|
||||
|
||||
type TRecord = record
|
||||
Key: shortstring;
|
||||
Value: shortstring;
|
||||
end;
|
||||
|
||||
type TPRecord = record
|
||||
Key: PChar;
|
||||
Value: PChar;
|
||||
end;
|
||||
|
||||
type TDB = record
|
||||
Count: integer;
|
||||
Records: array [0..255] of TRecord;
|
||||
end;
|
||||
PTDB = ^TDB;
|
||||
|
||||
const
|
||||
EBU: array [128..254] of Char =
|
||||
('á','a','é','e','í','i','ó','o','ú','u','N','Ç','ª','ß','I', #0,
|
||||
'â','ä','e','ë','î','i','ô','ö','u','ü','n','ç','º', #0,'i', #0,
|
||||
#0, #0,'©','‰', #0,'ì','ò','õ', #0, #0, #0,'$', #0, #0, #0, #0,
|
||||
#0, #0, #0, #0,'±','I','ñ','û','µ','?','÷','°', #0, #0, #0,'§',
|
||||
'Á','A','É','E','Í','I','Ó','O','Ú','U','Ø','È','Š','Ž','Ð','L',
|
||||
'Â','Ä','E','Ë','Î','I','Ô','Ö','U','Ü','ø','è','š','ž','ð','l',
|
||||
#0, #0, #0, #0, #0,'Ý', #0, #0, #0, #0,'À','Æ','Œ','<27>', #0, #0,
|
||||
#0, #0, #0, #0, #0,'ý', #0, #0, #0, #0,'à','æ','œ','Ÿ', #0);
|
||||
|
||||
var
|
||||
Param1: array [0..1023] of char;
|
||||
Param2: array [0..1023] of char;
|
||||
WorkDir: string;
|
||||
|
||||
function ReadValue(Key: PChar; DBPointer: PTDB): PChar; stdcall;
|
||||
var a,i: integer;
|
||||
SKey: shortstring;
|
||||
begin
|
||||
Result:='';
|
||||
SKey:=shortstring(Key);
|
||||
a:=DBPointer^.Count;
|
||||
if (a>length(DBPointer^.Records)) then a:=length(DBPointer^.Records); //ochrana
|
||||
for i:=1 to a do
|
||||
begin
|
||||
if (DBPointer^.Records[i-1].Key=SKey) then
|
||||
begin Result:=StrPCopy(Param1,DBPointer^.Records[i-1].Value); exit; end;
|
||||
end;
|
||||
end;
|
||||
|
||||
function ReadRecord(Index: integer; DBPointer: PTDB): TPRecord; stdcall;
|
||||
begin
|
||||
if (Index>=DBPointer^.Count) or (Index>=length(DBPointer^.Records)) then
|
||||
begin
|
||||
Result.Key:='';
|
||||
Result.Value:='';
|
||||
end else begin
|
||||
Result.Key:=StrPCopy(Param1,DBPointer^.Records[Index].Key);
|
||||
Result.Value:=StrPCopy(Param2,DBPointer^.Records[Index].Value);
|
||||
end;
|
||||
end;
|
||||
|
||||
procedure AddValue(Key, Value: PChar; DBPointer: PTDB); stdcall;
|
||||
var a,i: integer;
|
||||
SKey, SValue: shortstring;
|
||||
ASValue: string;
|
||||
begin
|
||||
SKey:=shortstring(Key);
|
||||
ASValue:=Value;
|
||||
if (length(ASValue)>255) then ASValue:=LeftStr(ASValue,252)+'...';
|
||||
SValue:=shortstring(ASValue);
|
||||
a:=DBPointer^.Count;
|
||||
if (a>length(DBPointer^.Records)) then a:=length(DBPointer^.Records); //ochrana
|
||||
for i:=1 to a do
|
||||
begin
|
||||
if (DBPointer^.Records[i-1].Key=SKey) then
|
||||
begin DBPointer^.Records[i-1].Value:=SValue; exit; end;
|
||||
end;
|
||||
if (a<length(DBPointer^.Records)-1) then
|
||||
begin
|
||||
DBPointer^.Count:=a+1;
|
||||
DBPointer^.Records[a].Value:=SValue;
|
||||
DBPointer^.Records[a].Key:=SKey;
|
||||
exit;
|
||||
end;
|
||||
if (SKey='COMMAND') then
|
||||
begin
|
||||
a:=length(DBPointer^.Records)-1;
|
||||
DBPointer^.Records[a].Key:=SKey;
|
||||
DBPointer^.Records[a].Value:=SValue;
|
||||
end;
|
||||
end;
|
||||
|
||||
procedure ResetValues(DBPointer: PTDB); stdcall;
|
||||
begin
|
||||
DBPointer^.Count:=0;
|
||||
end;
|
||||
|
||||
function CountRecords(DBPointer: PTDB): integer; stdcall;
|
||||
var a: integer;
|
||||
begin
|
||||
a:=DBPointer^.Count;
|
||||
if (a>length(DBPointer^.Records)) then a:=length(DBPointer^.Records);
|
||||
Result:=a;
|
||||
end;
|
||||
|
||||
procedure SavePChar(Filename, Section, Key, Value: PChar); stdcall;
|
||||
var Reg: TIniFile;
|
||||
begin
|
||||
Chdir(WorkDir);
|
||||
try
|
||||
Reg:=TIniFile.Create(string(Filename));
|
||||
try
|
||||
Reg.WriteString(string(Section), string(Key), string(Value));
|
||||
finally
|
||||
Reg.Free;
|
||||
end;
|
||||
except
|
||||
end;
|
||||
end;
|
||||
|
||||
procedure SaveInteger(Filename, Section, Key: Pchar; Value: integer); stdcall;
|
||||
var Reg: TIniFile;
|
||||
begin
|
||||
Chdir(WorkDir);
|
||||
try
|
||||
Reg:=TIniFile.Create(string(Filename));
|
||||
try
|
||||
Reg.WriteInteger(string(Section), string(Key), Value);
|
||||
finally
|
||||
Reg.Free;
|
||||
end;
|
||||
except
|
||||
end;
|
||||
end;
|
||||
|
||||
procedure SaveBoolean(Filename, Section, Key: Pchar; Value: boolean); stdcall;
|
||||
var Reg: TIniFile;
|
||||
begin
|
||||
Chdir(WorkDir);
|
||||
try
|
||||
Reg:=TIniFile.Create(string(Filename));
|
||||
try
|
||||
Reg.WriteBool(string(Section), string(Key), Value);
|
||||
finally
|
||||
Reg.Free;
|
||||
end;
|
||||
except
|
||||
end;
|
||||
end;
|
||||
|
||||
function LoadPChar(Filename, Section, Key, DefaultValue: PChar): PChar; stdcall;
|
||||
var Reg: TIniFile;
|
||||
begin
|
||||
Chdir(WorkDir);
|
||||
Result:=DefaultValue;
|
||||
try
|
||||
Reg:=TIniFile.Create(string(Filename));
|
||||
try
|
||||
Result:=StrPCopy(Param1,Reg.ReadString(string(Section), string(Key), string(DefaultValue)));
|
||||
finally
|
||||
Reg.Free;
|
||||
end;
|
||||
except
|
||||
end;
|
||||
end;
|
||||
|
||||
function LoadInteger(Filename, Section, Key: Pchar; DefaultValue: integer): integer; stdcall;
|
||||
var Reg: TIniFile;
|
||||
begin
|
||||
Chdir(WorkDir);
|
||||
Result:=DefaultValue;
|
||||
try
|
||||
Reg:=TIniFile.Create(string(Filename));
|
||||
try
|
||||
Result:=Reg.ReadInteger(string(Section), string(Key), DefaultValue);
|
||||
finally
|
||||
Reg.Free;
|
||||
end;
|
||||
except
|
||||
end;
|
||||
end;
|
||||
|
||||
function LoadBoolean(Filename, Section, Key: Pchar; DefaultValue: boolean): boolean; stdcall;
|
||||
var Reg: TIniFile;
|
||||
begin
|
||||
Chdir(WorkDir);
|
||||
Result:=DefaultValue;
|
||||
try
|
||||
Reg:=TIniFile.Create(string(Filename));
|
||||
try
|
||||
Result:=Reg.ReadBool(string(Section), string(Key), DefaultValue);
|
||||
finally
|
||||
Reg.Free;
|
||||
end;
|
||||
except
|
||||
end;
|
||||
end;
|
||||
|
||||
function CharConv(Ch, CT: Byte): Byte; stdcall;
|
||||
begin
|
||||
Result:=Ch;
|
||||
if (Ch>=128) and (Ch<255) then
|
||||
if (EBU[Ch]<>#0) then Result:=Ord(EBU[Ch]);
|
||||
end;
|
||||
|
||||
Exports
|
||||
ReadValue, ReadRecord, AddValue, ResetValues, CountRecords,
|
||||
SavePChar, SaveInteger, SaveBoolean, LoadPChar, LoadInteger, LoadBoolean,
|
||||
CharConv;
|
||||
|
||||
begin
|
||||
WorkDir:=ExtractFilePath(ParamStr(0));
|
||||
end.
|
||||
|
||||
3
docs/Commands.md
Normal file
3
docs/Commands.md
Normal file
@@ -0,0 +1,3 @@
|
||||
# Commands
|
||||
|
||||
Just wanted to tell you that they also have a "SUPERPI" command, the param is just the hex encoded pi text ("AAAA")
|
||||
BIN
docs/spyapi.pdf
Normal file
BIN
docs/spyapi.pdf
Normal file
Binary file not shown.
@@ -1,18 +1,23 @@
|
||||
ert_group = -1
|
||||
ert_string = string.rep(" ", 128)
|
||||
local ert_group = -1
|
||||
local ert_string = string.rep("_", 128)
|
||||
local ert_last_carriage = -1
|
||||
local ert_console_log = false
|
||||
|
||||
function command(cmd, param)
|
||||
if cmd:lower() == "request" then
|
||||
if cmd:lower() == "request" and param:lower() == "decoderdata" then
|
||||
local cr_pos = ert_string:find("\r", 1, true) -- true means "plain search" (faster)
|
||||
local display_text
|
||||
|
||||
if cr_pos then
|
||||
display_text = ert_string:sub(1, cr_pos - 1)
|
||||
else
|
||||
-- No CR found yet, show the whole 128 bytes (trimmed of trailing spaces)
|
||||
display_text = ert_string:gsub("%s+$", "")
|
||||
if cr_pos then display_text = ert_string:sub(1, cr_pos - 1)
|
||||
else display_text = ert_string:gsub("%s+$", "")
|
||||
end
|
||||
db.add_value("ERT", display_text)
|
||||
elseif cmd:lower() == "resetdata" then
|
||||
ert_group = -1
|
||||
ert_string = string.rep("_", 128)
|
||||
ert_last_carriage = -1
|
||||
if ert_console_log then log("ERT data reset.")
|
||||
else set_console_mode(true) end
|
||||
end
|
||||
end
|
||||
|
||||
@@ -20,7 +25,7 @@ function group(stream, b_corr, a, b, c, d)
|
||||
if stream ~= 0 and a ~= 0 then return
|
||||
elseif stream ~= 0 and not db.load_boolean("rdsspy.ini", "General", "Tunnelling", false) then return end
|
||||
|
||||
if b_corr then return end
|
||||
if b_corr or b < 0 or c < 0 or d < 0 then return end
|
||||
|
||||
local group = (b & 0xf000) >> 12
|
||||
local group_version = (b & 0x800) >> 11
|
||||
@@ -41,5 +46,18 @@ function group(stream, b_corr, a, b, c, d)
|
||||
local new_chars = char1..char2..char3..char4
|
||||
local start_pos = (ert_state * 4) + 1
|
||||
ert_string = ert_string:sub(1, start_pos - 1) .. new_chars .. ert_string:sub(start_pos + 4)
|
||||
|
||||
local ert_carriage = ert_string:find("\r", 1, true)
|
||||
if ert_carriage ~= ert_last_carriage and ert_carriage ~= nil and ert_console_log then
|
||||
log("New ERT string received.")
|
||||
ert_last_carriage = ert_carriage
|
||||
elseif not ert_console_log then
|
||||
local display_text
|
||||
|
||||
if ert_carriage then display_text = ert_string:sub(1, ert_carriage - 1)
|
||||
else display_text = ert_string:gsub("%s+$", "") end
|
||||
|
||||
set_console(string.format("ERT: %s", display_text))
|
||||
end
|
||||
end
|
||||
end
|
||||
280
plugin.c
280
plugin.c
@@ -47,6 +47,7 @@ static lua_State* L = NULL;
|
||||
static HWND hEditControl = NULL;
|
||||
static TDB* g_DBPointer = NULL;
|
||||
|
||||
|
||||
static const unsigned char EBU[127] = {
|
||||
0xE1, 'a', 0xE9, 'e', 0xED, 'i', 0xF3, 'o', 0xFA, 'u', 'N', 0xC7, 0xAA, 0xDF, 'I', 0x00,
|
||||
0xE2, 0xE4, 'e', 0xEB, 0xEE, 'i', 0xF4, 0xF6, 'u', 0xFC, 'n', 0xE7, 0xBA, 0x00, 'i', 0x00,
|
||||
@@ -58,6 +59,13 @@ static const unsigned char EBU[127] = {
|
||||
0x00, 0x00, 0x00, 0xFD, 0x00, 0x00, 0x00, 0x00, 0xE0, 0xE6, 0x9C, 0x9F, 0x00
|
||||
};
|
||||
|
||||
static unsigned int console_mode = 0;
|
||||
|
||||
const char* int_to_string(int value) {
|
||||
static char buffer[16];
|
||||
snprintf(buffer, sizeof(buffer), "%d", value);
|
||||
return buffer;
|
||||
}
|
||||
|
||||
unsigned char CharConv(unsigned char Ch) {
|
||||
if (Ch >= 128 && Ch < 255) {
|
||||
@@ -67,6 +75,105 @@ unsigned char CharConv(unsigned char Ch) {
|
||||
return Ch;
|
||||
}
|
||||
|
||||
LRESULT CALLBACK WndProc(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam)
|
||||
{
|
||||
switch (msg)
|
||||
{
|
||||
case WM_CLOSE:
|
||||
ShowWindow(hwnd, SW_HIDE);
|
||||
return 0;
|
||||
case WM_DESTROY:
|
||||
hWnd = NULL;
|
||||
return 0;
|
||||
}
|
||||
return DefWindowProc(hwnd, msg, wParam, lParam);
|
||||
}
|
||||
|
||||
void CreatePluginWindow(HWND hOwner) {
|
||||
WNDCLASS wc = {0};
|
||||
wc.lpfnWndProc = WndProc;
|
||||
wc.hInstance = hInst;
|
||||
wc.lpszClassName = "LuaHostPlugin";
|
||||
wc.hCursor = LoadCursor(NULL, IDC_ARROW);
|
||||
wc.hbrBackground = (HBRUSH)(COLOR_WINDOW + 1);
|
||||
RegisterClass(&wc);
|
||||
|
||||
hWnd = CreateWindowEx(
|
||||
0,
|
||||
"LuaHostPlugin",
|
||||
"Lua Host Console",
|
||||
WS_OVERLAPPED | WS_CAPTION | WS_SYSMENU,
|
||||
CW_USEDEFAULT, CW_USEDEFAULT,
|
||||
480, 320,
|
||||
hOwner,
|
||||
NULL,
|
||||
hInst,
|
||||
NULL
|
||||
);
|
||||
|
||||
hEditControl = CreateWindowEx(
|
||||
WS_EX_CLIENTEDGE, "EDIT", "",
|
||||
WS_CHILD | WS_VISIBLE | WS_VSCROLL |
|
||||
ES_LEFT | ES_MULTILINE | ES_AUTOVSCROLL | ES_READONLY,
|
||||
10, 10, 480-30, 320-50,
|
||||
hWnd, NULL, hInst, NULL
|
||||
);
|
||||
|
||||
HFONT hFont = CreateFont(18, 0, 0, 0, FW_NORMAL, FALSE, FALSE, FALSE, DEFAULT_CHARSET, OUT_DEFAULT_PRECIS, CLIP_DEFAULT_PRECIS, DEFAULT_QUALITY, DEFAULT_PITCH | FF_DONTCARE, "Segoe UI");
|
||||
SendMessage(hEditControl, WM_SETFONT, (WPARAM)hFont, TRUE);
|
||||
|
||||
HICON hIconBig = (HICON)SendMessage(hOwner, WM_GETICON, ICON_BIG, 0);
|
||||
HICON hIconSmall = (HICON)SendMessage(hOwner, WM_GETICON, ICON_SMALL, 0);
|
||||
if (!hIconBig) hIconBig = (HICON)GetClassLongPtr(hOwner, GCLP_HICON);
|
||||
if (!hIconSmall) hIconSmall = (HICON)GetClassLongPtr(hOwner, GCLP_HICONSM);
|
||||
SendMessage(hWnd, WM_SETICON, ICON_BIG, (LPARAM)hIconBig);
|
||||
SendMessage(hWnd, WM_SETICON, ICON_SMALL, (LPARAM)hIconSmall);
|
||||
|
||||
UpdateWindow(hWnd);
|
||||
}
|
||||
|
||||
void AppendText(const char* text) {
|
||||
if (hEditControl != NULL) {
|
||||
int len = GetWindowTextLength(hEditControl);
|
||||
SendMessage(hEditControl, EM_SETSEL, len, len);
|
||||
SendMessageA(hEditControl, EM_REPLACESEL, FALSE, (LPARAM)text);
|
||||
}
|
||||
}
|
||||
|
||||
void SetText(const char* text) {
|
||||
if (hEditControl != NULL) SetWindowTextA(hEditControl, text);
|
||||
}
|
||||
|
||||
int lua_log(lua_State* localL) {
|
||||
if(console_mode != 0) return luaL_error(localL, "Invalid log");
|
||||
const char* data = luaL_checkstring(localL, 1);
|
||||
AppendText(data);
|
||||
AppendText("\r\n");
|
||||
return 0;
|
||||
}
|
||||
|
||||
int lua_set_console(lua_State* localL) {
|
||||
if(console_mode != 1) return luaL_error(localL, "Invalid log");
|
||||
const char* data = luaL_checkstring(localL, 1);
|
||||
SetText(data);
|
||||
return 0;
|
||||
}
|
||||
|
||||
int lua_set_console_mode(lua_State* localL) {
|
||||
if (!lua_isboolean(localL, 1)) return luaL_error(localL, "boolean expected, got %s", luaL_typename(localL, 1));
|
||||
int mode = lua_toboolean(localL, 1);
|
||||
SetText("");
|
||||
console_mode = mode;
|
||||
return 0;
|
||||
}
|
||||
|
||||
int lua_MessageBox(lua_State* localL) {
|
||||
const char* data = luaL_checkstring(localL, 1);
|
||||
const char* title = luaL_checkstring(localL, 2);
|
||||
MessageBoxA(NULL, data, title, MB_OK | MB_TOPMOST);
|
||||
return 0;
|
||||
}
|
||||
|
||||
int lua_ReadValue(lua_State* localL) {
|
||||
if (g_DBPointer == NULL) {
|
||||
lua_pushnil(localL);
|
||||
@@ -116,15 +223,15 @@ int lua_ReadRecord(lua_State* localL) {
|
||||
|
||||
int lua_AddValue(lua_State* localL) {
|
||||
if (g_DBPointer == NULL) return 0;
|
||||
|
||||
|
||||
const char* key = luaL_checkstring(localL, 1);
|
||||
const char* value = luaL_checkstring(localL, 2);
|
||||
|
||||
|
||||
ShortString skey, svalue;
|
||||
skey.len = strlen(key);
|
||||
if (skey.len > 255) skey.len = 255;
|
||||
memcpy(skey.data, key, skey.len);
|
||||
|
||||
|
||||
svalue.len = strlen(value);
|
||||
if (svalue.len > 252) {
|
||||
svalue.len = 252;
|
||||
@@ -132,10 +239,10 @@ int lua_AddValue(lua_State* localL) {
|
||||
memcpy(svalue.data + 252, "...", 3);
|
||||
svalue.len = 255;
|
||||
} else memcpy(svalue.data, value, svalue.len);
|
||||
|
||||
|
||||
int count = g_DBPointer->Count;
|
||||
if (count > 255) count = 255;
|
||||
|
||||
|
||||
for (int i = 0; i < count; i++) {
|
||||
if (g_DBPointer->Records[i].Key.len == skey.len &&
|
||||
memcmp(g_DBPointer->Records[i].Key.data, skey.data, skey.len) == 0) {
|
||||
@@ -143,7 +250,7 @@ int lua_AddValue(lua_State* localL) {
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
if (count < 254) {
|
||||
g_DBPointer->Records[count].Key = skey;
|
||||
g_DBPointer->Records[count].Value = svalue;
|
||||
@@ -152,7 +259,7 @@ int lua_AddValue(lua_State* localL) {
|
||||
g_DBPointer->Records[254].Key = skey;
|
||||
g_DBPointer->Records[254].Value = svalue;
|
||||
}
|
||||
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
@@ -167,7 +274,7 @@ int lua_CountRecords(lua_State* localL) {
|
||||
lua_pushinteger(localL, 0);
|
||||
return 1;
|
||||
}
|
||||
|
||||
|
||||
int count = g_DBPointer->Count;
|
||||
if (count > 255) count = 255;
|
||||
lua_pushinteger(localL, count);
|
||||
@@ -185,7 +292,7 @@ int lua_SaveString(lua_State* localL) {
|
||||
const char* section = luaL_checkstring(localL, 2);
|
||||
const char* key = luaL_checkstring(localL, 3);
|
||||
const char* value = luaL_checkstring(localL, 4);
|
||||
|
||||
|
||||
char path[MAX_PATH];
|
||||
if (SUCCEEDED(SHGetFolderPathA(NULL, CSIDL_LOCAL_APPDATA, NULL, 0, path))) {
|
||||
char fullPath[MAX_PATH];
|
||||
@@ -200,10 +307,10 @@ int lua_SaveInteger(lua_State* localL) {
|
||||
const char* section = luaL_checkstring(localL, 2);
|
||||
const char* key = luaL_checkstring(localL, 3);
|
||||
int value = luaL_checkinteger(localL, 4);
|
||||
|
||||
|
||||
char valueStr[32];
|
||||
snprintf(valueStr, 32, "%d", value);
|
||||
|
||||
|
||||
char path[MAX_PATH];
|
||||
if (SUCCEEDED(SHGetFolderPathA(NULL, CSIDL_LOCAL_APPDATA, NULL, 0, path))) {
|
||||
char fullPath[MAX_PATH];
|
||||
@@ -218,7 +325,7 @@ int lua_SaveBoolean(lua_State* localL) {
|
||||
const char* section = luaL_checkstring(localL, 2);
|
||||
const char* key = luaL_checkstring(localL, 3);
|
||||
int value = lua_toboolean(localL, 4);
|
||||
|
||||
|
||||
char path[MAX_PATH];
|
||||
if (SUCCEEDED(SHGetFolderPathA(NULL, CSIDL_LOCAL_APPDATA, NULL, 0, path))) {
|
||||
char fullPath[MAX_PATH];
|
||||
@@ -233,10 +340,10 @@ int lua_LoadString(lua_State* localL) {
|
||||
const char* section = luaL_checkstring(localL, 2);
|
||||
const char* key = luaL_checkstring(localL, 3);
|
||||
const char* defaultValue = luaL_optstring(localL, 4, "");
|
||||
|
||||
|
||||
char buffer[1024];
|
||||
char path[MAX_PATH];
|
||||
|
||||
|
||||
if (SUCCEEDED(SHGetFolderPathA(NULL, CSIDL_LOCAL_APPDATA, NULL, 0, path))) {
|
||||
char fullPath[MAX_PATH];
|
||||
snprintf(fullPath, MAX_PATH, "%s\\RDS Spy\\%s", path, filename);
|
||||
@@ -251,7 +358,7 @@ int lua_LoadInteger(lua_State* localL) {
|
||||
const char* section = luaL_checkstring(localL, 2);
|
||||
const char* key = luaL_checkstring(localL, 3);
|
||||
int defaultValue = luaL_optinteger(localL, 4, 0);
|
||||
|
||||
|
||||
char path[MAX_PATH];
|
||||
if (SUCCEEDED(SHGetFolderPathA(NULL, CSIDL_LOCAL_APPDATA, NULL, 0, path))) {
|
||||
char fullPath[MAX_PATH];
|
||||
@@ -267,10 +374,10 @@ int lua_LoadBoolean(lua_State* localL) {
|
||||
const char* section = luaL_checkstring(localL, 2);
|
||||
const char* key = luaL_checkstring(localL, 3);
|
||||
int defaultValue = lua_toboolean(localL, 4);
|
||||
|
||||
|
||||
char buffer[16];
|
||||
char path[MAX_PATH];
|
||||
|
||||
|
||||
if (SUCCEEDED(SHGetFolderPathA(NULL, CSIDL_LOCAL_APPDATA, NULL, 0, path))) {
|
||||
char fullPath[MAX_PATH];
|
||||
snprintf(fullPath, MAX_PATH, "%s\\RDS Spy\\%s", path, filename);
|
||||
@@ -280,82 +387,6 @@ int lua_LoadBoolean(lua_State* localL) {
|
||||
return 1;
|
||||
}
|
||||
|
||||
LRESULT CALLBACK WndProc(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam)
|
||||
{
|
||||
switch (msg)
|
||||
{
|
||||
case WM_CLOSE:
|
||||
ShowWindow(hwnd, SW_HIDE);
|
||||
return 0;
|
||||
case WM_DESTROY:
|
||||
hWnd = NULL;
|
||||
return 0;
|
||||
}
|
||||
return DefWindowProc(hwnd, msg, wParam, lParam);
|
||||
}
|
||||
|
||||
void CreatePluginWindow(HWND hOwner)
|
||||
{
|
||||
WNDCLASS wc = {0};
|
||||
wc.lpfnWndProc = WndProc;
|
||||
wc.hInstance = hInst;
|
||||
wc.lpszClassName = "RDSPluginWindow";
|
||||
wc.hCursor = LoadCursor(NULL, IDC_ARROW);
|
||||
wc.hbrBackground = (HBRUSH)(COLOR_WINDOW + 1);
|
||||
RegisterClass(&wc);
|
||||
|
||||
hWnd = CreateWindowEx(
|
||||
0,
|
||||
"RDSPluginWindow",
|
||||
"RDS Plugin",
|
||||
WS_OVERLAPPED | WS_CAPTION | WS_SYSMENU,
|
||||
CW_USEDEFAULT, CW_USEDEFAULT,
|
||||
400, 300,
|
||||
hOwner,
|
||||
NULL,
|
||||
hInst,
|
||||
NULL
|
||||
);
|
||||
|
||||
hEditControl = CreateWindowEx(
|
||||
WS_EX_CLIENTEDGE, "EDIT", "",
|
||||
WS_CHILD | WS_VISIBLE | WS_VSCROLL |
|
||||
ES_LEFT | ES_MULTILINE | ES_AUTOVSCROLL | ES_READONLY,
|
||||
10, 10, 370, 250,
|
||||
hWnd, NULL, hInst, NULL
|
||||
);
|
||||
|
||||
HFONT hFont = CreateFont(16, 0, 0, 0, FW_NORMAL, FALSE, FALSE, FALSE, DEFAULT_CHARSET, OUT_DEFAULT_PRECIS, CLIP_DEFAULT_PRECIS, DEFAULT_QUALITY, DEFAULT_PITCH | FF_DONTCARE, "Segoe UI");
|
||||
SendMessage(hEditControl, WM_SETFONT, (WPARAM)hFont, TRUE);
|
||||
UpdateWindow(hWnd);
|
||||
}
|
||||
|
||||
void AppendText(const char* text) {
|
||||
if (hEditControl != NULL) {
|
||||
int len = GetWindowTextLength(hEditControl);
|
||||
SendMessage(hEditControl, EM_SETSEL, len, len);
|
||||
SendMessageA(hEditControl, EM_REPLACESEL, FALSE, (LPARAM)text);
|
||||
}
|
||||
}
|
||||
|
||||
void SetText(const char* text) {
|
||||
if (hEditControl != NULL) SetWindowTextA(hEditControl, text);
|
||||
}
|
||||
|
||||
int lua_log(lua_State* localL) {
|
||||
const char* data = luaL_checkstring(localL, 1);
|
||||
AppendText(data);
|
||||
AppendText("\r\n");
|
||||
return 0;
|
||||
}
|
||||
|
||||
int lua_MessageBox(lua_State* localL) {
|
||||
const char* data = luaL_checkstring(localL, 1);
|
||||
const char* title = luaL_checkstring(localL, 2);
|
||||
MessageBoxA(NULL, data, title, MB_OK | MB_TOPMOST);
|
||||
return 0;
|
||||
}
|
||||
|
||||
void lua_call_command(const char* Cmd, const char* Param) {
|
||||
lua_getglobal(L, "command");
|
||||
|
||||
@@ -412,50 +443,83 @@ __declspec(dllexport) void __stdcall Command(const char* Cmd, const char* Param)
|
||||
else if (_stricmp(Cmd, "SHOW") == 0) ShowWindow(hWnd, SW_SHOW);
|
||||
else if (_stricmp(Cmd, "MINIMIZE") == 0) ShowWindow(hWnd, SW_MINIMIZE);
|
||||
else if (_stricmp(Cmd, "RESTORE") == 0) ShowWindow(hWnd, SW_RESTORE);
|
||||
else lua_call_command(Cmd, Param);
|
||||
else if (_stricmp(Cmd, "OPENWORKSPACE") == 0) {
|
||||
if(hWnd != NULL) {
|
||||
int value = GetPrivateProfileIntA("luahost", "Visible", 0, Param);
|
||||
if(value == 1) ShowWindow(hWnd, SW_SHOW);
|
||||
else if(value == 0) ShowWindow(hWnd, SW_HIDE);
|
||||
int x = GetPrivateProfileIntA("luahost", "Left", 320, Param);
|
||||
int y = GetPrivateProfileIntA("luahost", "Top", 240, Param);
|
||||
SetWindowPos(hWnd, NULL, x, y, 0, 0, SWP_NOSIZE);
|
||||
}
|
||||
lua_call_command(Cmd, Param); // still call
|
||||
} else if (_stricmp(Cmd, "SAVEWORKSPACE") == 0) {
|
||||
if(hWnd != NULL) {
|
||||
RECT rect; // get rect
|
||||
if (GetWindowRect(hWnd, &rect)) {
|
||||
WritePrivateProfileStringA("luahost", "Left", int_to_string(rect.left), Param);
|
||||
WritePrivateProfileStringA("luahost", "Top", int_to_string(rect.top), Param);
|
||||
}
|
||||
WritePrivateProfileStringA("luahost", "Visible", IsWindowVisible(hWnd) ? "1" : "0", Param);
|
||||
}
|
||||
lua_call_command(Cmd, Param); // still call
|
||||
} else if (_stricmp(Cmd, "LUASCRIPT") == 0) { // custom
|
||||
char msg_buffer[255];
|
||||
if (luaL_loadfile(L, Param) != LUA_OK) {
|
||||
sprintf(msg_buffer, "Lua error loading file: %s\r\n", lua_tostring(L, -1));
|
||||
AppendText(msg_buffer);
|
||||
lua_pop(L, 1);
|
||||
} else {
|
||||
if (lua_pcall(L, 0, 0, 0) != LUA_OK) {
|
||||
sprintf(msg_buffer, "Init error: %s\r\n", lua_tostring(L, -1));
|
||||
AppendText(msg_buffer);
|
||||
lua_pop(L, 1);
|
||||
}
|
||||
}
|
||||
} else lua_call_command(Cmd, Param);
|
||||
}
|
||||
|
||||
__declspec(dllexport) const char* __stdcall PluginName(void) { return "Lua Host"; }
|
||||
|
||||
void RegisterDBFunctions(lua_State* localL) {
|
||||
lua_newtable(localL);
|
||||
|
||||
|
||||
lua_pushcfunction(localL, lua_ReadValue);
|
||||
lua_setfield(localL, -2, "read_value");
|
||||
|
||||
|
||||
lua_pushcfunction(localL, lua_ReadRecord);
|
||||
lua_setfield(localL, -2, "read_record");
|
||||
|
||||
|
||||
lua_pushcfunction(localL, lua_AddValue);
|
||||
lua_setfield(localL, -2, "add_value");
|
||||
|
||||
|
||||
lua_pushcfunction(localL, lua_ResetValues);
|
||||
lua_setfield(localL, -2, "reset_values");
|
||||
|
||||
|
||||
lua_pushcfunction(localL, lua_CountRecords);
|
||||
lua_setfield(localL, -2, "count_records");
|
||||
|
||||
|
||||
lua_pushcfunction(localL, lua_CharConv);
|
||||
lua_setfield(localL, -2, "char_conv");
|
||||
|
||||
|
||||
lua_pushcfunction(localL, lua_SaveString);
|
||||
lua_setfield(localL, -2, "save_string");
|
||||
|
||||
|
||||
lua_pushcfunction(localL, lua_SaveInteger);
|
||||
lua_setfield(localL, -2, "save_integer");
|
||||
|
||||
|
||||
lua_pushcfunction(localL, lua_SaveBoolean);
|
||||
lua_setfield(localL, -2, "save_boolean");
|
||||
|
||||
|
||||
lua_pushcfunction(localL, lua_LoadString);
|
||||
lua_setfield(localL, -2, "load_string");
|
||||
|
||||
|
||||
lua_pushcfunction(localL, lua_LoadInteger);
|
||||
lua_setfield(localL, -2, "load_integer");
|
||||
|
||||
|
||||
lua_pushcfunction(localL, lua_LoadBoolean);
|
||||
lua_setfield(localL, -2, "load_boolean");
|
||||
|
||||
|
||||
lua_setglobal(localL, "db");
|
||||
}
|
||||
|
||||
@@ -467,6 +531,8 @@ __declspec(dllexport) int __stdcall Initialize(HANDLE hHandle, TDB* DBPointer) {
|
||||
luaL_openlibs(L);
|
||||
lua_register(L, "message_box", lua_MessageBox);
|
||||
lua_register(L, "log", lua_log);
|
||||
lua_register(L, "set_console", lua_set_console);
|
||||
lua_register(L, "set_console_mode", lua_set_console_mode);
|
||||
g_DBPointer = DBPointer;
|
||||
RegisterDBFunctions(L);
|
||||
|
||||
|
||||
@@ -20,10 +20,17 @@ function group(stream, block_b_correction, a, b, c, d) end
|
||||
---@param title string
|
||||
function message_box(body, title) end
|
||||
|
||||
---Logs a string inside the host console
|
||||
---Logs a string inside the host console. Requires console mode to be false.
|
||||
---@param data string
|
||||
function log(data) end
|
||||
|
||||
---Sets the whole text of the console for display. Requires console mode to be true.
|
||||
---@param data string
|
||||
function set_console(data) end
|
||||
|
||||
---@param mode boolean
|
||||
function set_console_mode(mode) end
|
||||
|
||||
db = {}
|
||||
|
||||
---@param key string
|
||||
|
||||
Reference in New Issue
Block a user