mirror of
https://github.com/alliedmodders/metamod-source.git
synced 2025-02-26 19:54:14 +01:00
Merged sourcemm-1.4.x back into default
This commit is contained in:
commit
2ea6e744bb
@ -31,8 +31,8 @@
|
|||||||
-M
|
-M
|
||||||
-$M16384,1048576
|
-$M16384,1048576
|
||||||
-K$00400000
|
-K$00400000
|
||||||
-LE"c:\programme\borland\delphi7\Projects\Bpl"
|
-LE"c:\program files\borland\delphi7\Projects\Bpl"
|
||||||
-LN"c:\programme\borland\delphi7\Projects\Bpl"
|
-LN"c:\program files\borland\delphi7\Projects\Bpl"
|
||||||
-w-UNSAFE_TYPE
|
-w-UNSAFE_TYPE
|
||||||
-w-UNSAFE_CODE
|
-w-UNSAFE_CODE
|
||||||
-w-UNSAFE_CAST
|
-w-UNSAFE_CAST
|
||||||
|
@ -14,24 +14,31 @@ begin
|
|||||||
WriteLn('');
|
WriteLn('');
|
||||||
WriteLn('// Looking up files...');
|
WriteLn('// Looking up files...');
|
||||||
{ Check files }
|
{ Check files }
|
||||||
if FileExists(ExtractFilePath(ParamStr(0)) + 'files\hl2launch.exe') then
|
if FileExists(ExtractFilePath(ParamStr(0)) + 'files\server.dll.source') then
|
||||||
WriteLn('// Found files\hl2launch.exe')
|
WriteLn('// Found files\server.dll.source')
|
||||||
else begin
|
else begin
|
||||||
WriteLn('// Error: Couldn''t find files\hl2launch.exe!');
|
WriteLn('// Error: Couldn''t find files\server.dll.source!');
|
||||||
ReadLn;
|
ReadLn;
|
||||||
exit;
|
exit;
|
||||||
end;
|
end;
|
||||||
if FileExists(ExtractFilePath(ParamStr(0)) + 'files\server.dll') then
|
if FileExists(ExtractFilePath(ParamStr(0)) + 'files\server_i486.so.source') then
|
||||||
WriteLn('// Found files\server.dll')
|
WriteLn('// Found files\server_i486.so.source')
|
||||||
else begin
|
else begin
|
||||||
WriteLn('// Error: Couldn''t find files\server.dll!');
|
WriteLn('// Error: Couldn''t find files\server_i486.so.source!');
|
||||||
ReadLn;
|
ReadLn;
|
||||||
exit;
|
exit;
|
||||||
end;
|
end;
|
||||||
if FileExists(ExtractFilePath(ParamStr(0)) + 'files\server_i486.so') then
|
if FileExists(ExtractFilePath(ParamStr(0)) + 'files\server.dll.orangebox') then
|
||||||
WriteLn('// Found files\server_i486.so')
|
WriteLn('// Found files\server.dll.orangebox')
|
||||||
else begin
|
else begin
|
||||||
WriteLn('// Error: Couldn''t find files\server_i486.so!');
|
WriteLn('// Error: Couldn''t find files\server.dll.orangebox!');
|
||||||
|
ReadLn;
|
||||||
|
exit;
|
||||||
|
end;
|
||||||
|
if FileExists(ExtractFilePath(ParamStr(0)) + 'files\server_i486.so.orangebox') then
|
||||||
|
WriteLn('// Found files\server_i486.so.orangebox')
|
||||||
|
else begin
|
||||||
|
WriteLn('// Error: Couldn''t find files\server_i486.so.orangebox!');
|
||||||
ReadLn;
|
ReadLn;
|
||||||
exit;
|
exit;
|
||||||
end;
|
end;
|
||||||
@ -53,9 +60,10 @@ begin
|
|||||||
{ Compress files }
|
{ Compress files }
|
||||||
WriteLn('// Compressing files...');
|
WriteLn('// Compressing files...');
|
||||||
eFiles := TStringList.Create;
|
eFiles := TStringList.Create;
|
||||||
eFiles.Add(ExtractFilePath(ParamStr(0)) + 'files\hl2launch.exe');
|
eFiles.Add(ExtractFilePath(ParamStr(0)) + 'files\server.dll.source');
|
||||||
eFiles.Add(ExtractFilePath(ParamStr(0)) + 'files\server.dll');
|
eFiles.Add(ExtractFilePath(ParamStr(0)) + 'files\server_i486.so.source');
|
||||||
eFiles.Add(ExtractFilePath(ParamStr(0)) + 'files\server_i486.so');
|
eFiles.Add(ExtractFilePath(ParamStr(0)) + 'files\server.dll.orangebox');
|
||||||
|
eFiles.Add(ExtractFilePath(ParamStr(0)) + 'files\server_i486.so.orangebox');
|
||||||
eStream := TMemoryStream.Create;
|
eStream := TMemoryStream.Create;
|
||||||
CompressFiles(eFiles, ExtractFilePath(ParamStr(0)) + 'temp.zip');
|
CompressFiles(eFiles, ExtractFilePath(ParamStr(0)) + 'temp.zip');
|
||||||
eStream.LoadFromFile(ExtractFilePath(ParamStr(0)) + 'temp.zip');
|
eStream.LoadFromFile(ExtractFilePath(ParamStr(0)) + 'temp.zip');
|
||||||
@ -63,6 +71,7 @@ begin
|
|||||||
AttachToFile(ExtractFilePath(ParamStr(0)) + 'MMS_Installer.exe', eStream, Version);
|
AttachToFile(ExtractFilePath(ParamStr(0)) + 'MMS_Installer.exe', eStream, Version);
|
||||||
DeleteFile(ExtractFilePath(ParamStr(0)) + 'temp.zip');
|
DeleteFile(ExtractFilePath(ParamStr(0)) + 'temp.zip');
|
||||||
eStream.Free;
|
eStream.Free;
|
||||||
|
eFiles.Free;
|
||||||
WriteLn('// Done.');
|
WriteLn('// Done.');
|
||||||
ReadLn;
|
ReadLn;
|
||||||
end.
|
end.
|
||||||
|
Binary file not shown.
@ -1,38 +0,0 @@
|
|||||||
-$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;DbiProcs=BDE;DbiErrs=BDE;
|
|
||||||
-H+
|
|
||||||
-W+
|
|
||||||
-M
|
|
||||||
-$M16384,1048576
|
|
||||||
-K$00400000
|
|
||||||
-LE"c:\programme\borland\delphi7\Projects\Bpl"
|
|
||||||
-LN"c:\programme\borland\delphi7\Projects\Bpl"
|
|
||||||
-w-UNSAFE_TYPE
|
|
||||||
-w-UNSAFE_CODE
|
|
||||||
-w-UNSAFE_CAST
|
|
@ -1,189 +0,0 @@
|
|||||||
program HL2Launch;
|
|
||||||
|
|
||||||
{$APPTYPE CONSOLE}
|
|
||||||
|
|
||||||
uses
|
|
||||||
SysUtils,
|
|
||||||
ShellApi,
|
|
||||||
Windows,
|
|
||||||
Classes;
|
|
||||||
|
|
||||||
procedure LaunchFile(eFile, eStartDir, eParams: String);
|
|
||||||
var eStartInfo: TStartupInfo;
|
|
||||||
eProcInfo: TProcessInformation;
|
|
||||||
begin
|
|
||||||
FillChar(eStartInfo, SizeOf(TStartupInfo), 0);
|
|
||||||
with eStartInfo do begin
|
|
||||||
cb := SizeOf(eStartInfo);
|
|
||||||
dwFlags := STARTF_USESHOWWINDOW;
|
|
||||||
end;
|
|
||||||
|
|
||||||
if (CreateProcess(nil, PChar(eFile + #32 + eParams), nil, nil, False, NORMAL_PRIORITY_CLASS, nil, PChar(eStartDir), eStartInfo, eProcInfo)) then begin
|
|
||||||
try
|
|
||||||
WaitForSingleObject(eProcInfo.hProcess, INFINITE);
|
|
||||||
finally
|
|
||||||
CloseHandle(eProcInfo.hProcess);
|
|
||||||
CloseHandle(eProcInfo.hThread);
|
|
||||||
end;
|
|
||||||
SetConsoleTextAttribute(GetStdHandle(STD_OUTPUT_HANDLE), 2);
|
|
||||||
Write(' Done.' + #13#10);
|
|
||||||
end
|
|
||||||
else begin
|
|
||||||
SetConsoleTextAttribute(GetStdHandle(STD_OUTPUT_HANDLE), 12);
|
|
||||||
Write(' Couldn''t start hl2.exe!' + #13#10);
|
|
||||||
end;
|
|
||||||
end;
|
|
||||||
|
|
||||||
function GetFileSize(eFile: String): Int64;
|
|
||||||
var eFindHandle: THandle;
|
|
||||||
eFindData: TWIN32FINDDATA;
|
|
||||||
begin
|
|
||||||
Result := 0;
|
|
||||||
if not FileExists(eFile) then exit;
|
|
||||||
eFindHandle := FindFirstFile(PChar(eFile), eFindData);
|
|
||||||
if eFindHandle = INVALID_HANDLE_VALUE then exit;
|
|
||||||
Result := (eFindData.nFileSizeHigh * (Int64(MAXDWORD) + 1)) + eFindData.nFileSizeLow;
|
|
||||||
FindClose(eFindHandle);
|
|
||||||
end;
|
|
||||||
|
|
||||||
var eStream: TFileStream;
|
|
||||||
ePath, eParams: String;
|
|
||||||
eModDir: String;
|
|
||||||
eSearchRec: TSearchRec;
|
|
||||||
eStr: TStringList;
|
|
||||||
i: integer;
|
|
||||||
CheckSuccessful: Boolean;
|
|
||||||
StartTime: Cardinal;
|
|
||||||
begin
|
|
||||||
ePath := ExtractFilePath(ParamStr(0));
|
|
||||||
for i := 1 to ParamCount do
|
|
||||||
eParams := eParams + #32 + ParamStr(i);
|
|
||||||
Delete(eParams, 1, 1);
|
|
||||||
if Pos('console', LowerCase(eParams)) = 0 then
|
|
||||||
eParams := eParams + ' -console';
|
|
||||||
eStream := nil;
|
|
||||||
eModDir := '';
|
|
||||||
|
|
||||||
SetConsoleTitle('HL2 Launcher');
|
|
||||||
Sleep(200); // wait a few ms until the launch program is closed
|
|
||||||
|
|
||||||
SetConsoleTextAttribute(GetStdHandle(STD_OUTPUT_HANDLE), 2);
|
|
||||||
WriteLn(' _ _ _ ____ _ _ ');
|
|
||||||
WriteLn('| | | | | |___ \ | | __ _ _ _ _ __ ___| |__ ___ _ __ ');
|
|
||||||
WriteLn('| |_| | | __) | | | / _` | | | | ''_ \ / __| ''_ \ / _ \ ''__|');
|
|
||||||
WriteLn('| _ | |___ / __/ | |__| (_| | |_| | | | | (__| | | | __/ | ');
|
|
||||||
WriteLn('|_| |_|_____|_____| |_____\__,_|\__,_|_| |_|\___|_| |_|\___|_| ');
|
|
||||||
WriteLn(' for listen servers using Metamod:Source');
|
|
||||||
WriteLn('');
|
|
||||||
SetConsoleTextAttribute(GetStdHandle(STD_OUTPUT_HANDLE), 7);
|
|
||||||
{ Check files }
|
|
||||||
WriteLn('Checking files...');
|
|
||||||
if not FileExists(ePath + 'hl2.exe') then begin
|
|
||||||
SetConsoleTextAttribute(GetStdHandle(STD_OUTPUT_HANDLE), 12);
|
|
||||||
WriteLn('Error: hl2.exe is missing! Maybe wrong directory? If not, start your HL2 Mod again via Steam and try again.');
|
|
||||||
ReadLn;
|
|
||||||
exit;
|
|
||||||
end;
|
|
||||||
if not FileExists(Copy(ePath, 1, Pos('\steamapps\', LowerCase(ePath))) + 'steam.exe') then begin
|
|
||||||
SetConsoleTextAttribute(GetStdHandle(STD_OUTPUT_HANDLE), 12);
|
|
||||||
WriteLn('Error: Cannot find steam.exe! Make sure this application is located in your listen server''s directory.');
|
|
||||||
ReadLn;
|
|
||||||
exit;
|
|
||||||
end;
|
|
||||||
{ Verify GameInfo.txt ... }
|
|
||||||
Write('Verifying GameInfo.txt...');
|
|
||||||
if (FindFirst(ePath + '*.*', faDirectory, eSearchRec) = 0) then begin
|
|
||||||
repeat
|
|
||||||
if (FileExists(ePath + eSearchRec.Name + '\GameInfo.txt')) then begin
|
|
||||||
eModDir := eSearchRec.Name;
|
|
||||||
break;
|
|
||||||
end;
|
|
||||||
until (FindNext(eSearchRec) <> 0);
|
|
||||||
end;
|
|
||||||
FindClose(eSearchRec.FindHandle);
|
|
||||||
if eModDir = '' then begin
|
|
||||||
SetConsoleTextAttribute(GetStdHandle(STD_OUTPUT_HANDLE), 12);
|
|
||||||
WriteLn('');
|
|
||||||
WriteLn('Error: Couldn''t find GameInfo.txt!');
|
|
||||||
ReadLn;
|
|
||||||
exit;
|
|
||||||
end
|
|
||||||
else begin
|
|
||||||
if Pos('game', LowerCase(eParams)) = 0 then // a small test which isn't worth a notice
|
|
||||||
eParams := '-game ' + eSearchRec.Name + #32 + eParams;
|
|
||||||
|
|
||||||
eStr := TStringList.Create;
|
|
||||||
eStr.LoadFromFile(ePath + eModDir + '\GameInfo.txt');
|
|
||||||
if Pos('|gameinfo_path|addons/metamod/bin', LowerCase(eStr.Text)) = 0 then begin
|
|
||||||
CheckSuccessful := False;
|
|
||||||
for i := 0 to eStr.Count -1 do begin
|
|
||||||
if Pos('searchpaths', LowerCase(Trim(eStr[i]))) = 1 then begin
|
|
||||||
if i+3 >= eStr.Count then
|
|
||||||
break;
|
|
||||||
eStr.Insert(i+2, ' GameBin |gameinfo_path|addons/metamod/bin');
|
|
||||||
CheckSuccessful := True;
|
|
||||||
break;
|
|
||||||
end;
|
|
||||||
end;
|
|
||||||
|
|
||||||
if CheckSuccessful then begin
|
|
||||||
SetConsoleTextAttribute(GetStdHandle(STD_OUTPUT_HANDLE), 2);
|
|
||||||
SetFileAttributes(PChar(ePath + eModDir + '\GameInfo.txt'), 0);
|
|
||||||
eStr.SaveToFile(ePath + eModDir + '\GameInfo.txt');
|
|
||||||
SetFileAttributes(PChar(ePath + eModDir + '\GameInfo.txt'), faReadOnly);
|
|
||||||
Write(' Registered MM:S sucessfully' + #13#10);
|
|
||||||
end
|
|
||||||
else begin
|
|
||||||
SetConsoleTextAttribute(GetStdHandle(STD_OUTPUT_HANDLE), 4);
|
|
||||||
Write(' Unexpected EOF, your GameInfo.txt seems to be corrupt' + #13#10);
|
|
||||||
end;
|
|
||||||
end
|
|
||||||
else begin
|
|
||||||
SetConsoleTextAttribute(GetStdHandle(STD_OUTPUT_HANDLE), 2);
|
|
||||||
Write(' Done' + #13#10);
|
|
||||||
end;
|
|
||||||
eStr.Free;
|
|
||||||
end;
|
|
||||||
{ ... and set it to write-protected }
|
|
||||||
SetConsoleTextAttribute(GetStdHandle(STD_OUTPUT_HANDLE), 7);
|
|
||||||
Write('Setting GameInfo.txt to write-protected...');
|
|
||||||
try
|
|
||||||
eStream := TFileStream.Create(ePath + eModDir + '\GameInfo.txt', fmShareDenyWrite);
|
|
||||||
SetConsoleTextAttribute(GetStdHandle(STD_OUTPUT_HANDLE), 2);
|
|
||||||
Write(' Done.' + #13#10);
|
|
||||||
except
|
|
||||||
SetConsoleTextAttribute(GetStdHandle(STD_OUTPUT_HANDLE), 14);
|
|
||||||
WriteLn('');
|
|
||||||
WriteLn('Warning: Couldn''t set GameInfo.txt to write-protected!');
|
|
||||||
eStream := nil;
|
|
||||||
end;
|
|
||||||
{ Launch Steam if not opened }
|
|
||||||
ShellExecute(0, 'open', PChar(Copy(ePath, 1, Pos('\steamapps\', LowerCase(ePath))) + 'steam.exe'), nil, PChar(Copy(ePath, 1, Pos('\steamapps\', LowerCase(ePath)))), SW_SHOW);
|
|
||||||
{ Launch game }
|
|
||||||
SetConsoleTextAttribute(GetStdHandle(STD_OUTPUT_HANDLE), 7);
|
|
||||||
Write('Starting HL2...');
|
|
||||||
StartTime := GetTickCount;
|
|
||||||
LaunchFile(ePath + 'hl2.exe', Copy(ePath, 1, Pos('Steam', ePath)+5), eParams);
|
|
||||||
if (GetTickCount - StartTime < 10000) then begin
|
|
||||||
SetConsoleTextAttribute(GetStdHandle(STD_OUTPUT_HANDLE), 14);
|
|
||||||
WriteLn('Important: If you experience any problems starting HL2 using this program, please start it once via Steam and try again.');
|
|
||||||
ReadLn;
|
|
||||||
end;
|
|
||||||
SetConsoleTextAttribute(GetStdHandle(STD_OUTPUT_HANDLE), 7);
|
|
||||||
{ Free GameInfo.txt }
|
|
||||||
Write('Removing read-only again from GameInfo.txt...');
|
|
||||||
if Assigned(eStream) then begin
|
|
||||||
eStream.Free;
|
|
||||||
SetConsoleTextAttribute(GetStdHandle(STD_OUTPUT_HANDLE), 2);
|
|
||||||
Write(' Done' + #13#10);
|
|
||||||
end
|
|
||||||
else begin
|
|
||||||
SetConsoleTextAttribute(GetStdHandle(STD_OUTPUT_HANDLE), 4);
|
|
||||||
Write(' Skipped' + #13#10);
|
|
||||||
end;
|
|
||||||
{ End message }
|
|
||||||
SetConsoleTextAttribute(GetStdHandle(STD_OUTPUT_HANDLE), 7);
|
|
||||||
WriteLn('');
|
|
||||||
WriteLn('Thanks for using Metamod:Source! Visit http://www.sourcemm.net/');
|
|
||||||
Sleep(2500);
|
|
||||||
end.
|
|
Binary file not shown.
@ -31,8 +31,8 @@
|
|||||||
-M
|
-M
|
||||||
-$M16384,1048576
|
-$M16384,1048576
|
||||||
-K$00400000
|
-K$00400000
|
||||||
-LE"c:\program files (x86)\borland\delphi7\Projects\Bpl"
|
-LE"c:\program files\borland\delphi7\Projects\Bpl"
|
||||||
-LN"c:\program files (x86)\borland\delphi7\Projects\Bpl"
|
-LN"c:\program files\borland\delphi7\Projects\Bpl"
|
||||||
-w-UNSAFE_TYPE
|
-w-UNSAFE_TYPE
|
||||||
-w-UNSAFE_CODE
|
-w-UNSAFE_CODE
|
||||||
-w-UNSAFE_CAST
|
-w-UNSAFE_CAST
|
||||||
|
Binary file not shown.
@ -10,6 +10,8 @@ function GetAllFiles(Mask: String; Attr: Integer; Recursive: Boolean; ShowDirs:
|
|||||||
// ftp
|
// ftp
|
||||||
function GetAllDirs: TStringList;
|
function GetAllDirs: TStringList;
|
||||||
|
|
||||||
|
function GetModName(const Path: String): String;
|
||||||
|
|
||||||
implementation
|
implementation
|
||||||
|
|
||||||
uses UnitfrmMain;
|
uses UnitfrmMain;
|
||||||
@ -121,6 +123,20 @@ begin
|
|||||||
Result := eList;
|
Result := eList;
|
||||||
end; }
|
end; }
|
||||||
|
|
||||||
|
function GetModName(const Path: String): String;
|
||||||
|
var i: integer;
|
||||||
|
begin
|
||||||
|
Result := '';
|
||||||
|
for i := Length(Path) -1 downto 1 do begin
|
||||||
|
if (Path[i] = '\') or (Path[i] = '/') then begin
|
||||||
|
Result := Copy(Path, i +1, Length(Path) -i);
|
||||||
|
break;
|
||||||
|
end;
|
||||||
|
end;
|
||||||
|
if (Copy(Result, Length(Result), 1) = '\') or (Copy(Result, Length(Result), 1) = '/') then
|
||||||
|
Result := Copy(Result, 1, Length(Result) -1);
|
||||||
|
end;
|
||||||
|
|
||||||
end.
|
end.
|
||||||
|
|
||||||
|
|
||||||
|
@ -13,11 +13,11 @@ procedure AddSkipped;
|
|||||||
procedure AddNotFound;
|
procedure AddNotFound;
|
||||||
procedure DownloadFile(eFile: String; eDestination: String);
|
procedure DownloadFile(eFile: String; eDestination: String);
|
||||||
|
|
||||||
procedure BasicInstallation(ePath: String; SteamInstall, ListenInstall: Boolean; OS: TOS);
|
procedure BasicInstallation(ePath: String; SteamInstall, ListenInstall: Boolean; OS: TOS; const Source: Boolean);
|
||||||
procedure InstallDedicated(eModPath: String; UseSteam: Boolean);
|
procedure InstallDedicated(eModPath: String; const UseSteam, Source: Boolean);
|
||||||
procedure InstallListen(ePath: String);
|
procedure InstallListen(ePath: String; const Source: Boolean);
|
||||||
procedure InstallCustom(ePath: String; eOS: TOS);
|
procedure InstallCustom(ePath: String; eOS: TOS; const Source: Boolean);
|
||||||
procedure InstallFTP(OS: TOS);
|
procedure InstallFTP(OS: TOS; const Source: Boolean; const ModDir: String);
|
||||||
|
|
||||||
var StartTime: TDateTime;
|
var StartTime: TDateTime;
|
||||||
SteamPath: String;
|
SteamPath: String;
|
||||||
@ -32,7 +32,7 @@ uses UnitfrmMain, UnitfrmProxy, UnitFunctions, UnitPackSystem;
|
|||||||
|
|
||||||
function InstallTime: String;
|
function InstallTime: String;
|
||||||
begin
|
begin
|
||||||
Result := FormatDateTime('HH:MM:SS', Now - StartTime);
|
Result := Copy(FormatDateTime('HH:MM:SS', Now - StartTime), 4, 5);
|
||||||
end;
|
end;
|
||||||
|
|
||||||
procedure AddStatus(Text: String; Color: TColor; ShowTime: Boolean = True);
|
procedure AddStatus(Text: String; Color: TColor; ShowTime: Boolean = True);
|
||||||
@ -218,18 +218,16 @@ end;
|
|||||||
|
|
||||||
{ Basic Installation }
|
{ Basic Installation }
|
||||||
|
|
||||||
procedure BasicInstallation(ePath: String; SteamInstall, ListenInstall: Boolean; OS: TOS);
|
procedure BasicInstallation(ePath: String; SteamInstall, ListenInstall: Boolean; OS: TOS; const Source: Boolean);
|
||||||
var eStr: TStringList;
|
var eStr: TStringList;
|
||||||
i: integer;
|
|
||||||
CopyConfig: Boolean;
|
CopyConfig: Boolean;
|
||||||
eFound: Boolean;
|
|
||||||
begin
|
begin
|
||||||
frmMain.ggeAll.MaxValue := 8;
|
frmMain.ggeAll.MaxValue := 8;
|
||||||
frmMain.ggeAll.Progress := 0;
|
frmMain.ggeAll.Progress := 0;
|
||||||
frmMain.ggeItem.MaxValue := 1;
|
frmMain.ggeItem.MaxValue := 1;
|
||||||
frmMain.ggeItem.Progress := 0;
|
frmMain.ggeItem.Progress := 0;
|
||||||
|
|
||||||
if (GetProcessID('Steam.exe') <> -1) and (SteamInstall) then begin
|
{if (GetProcessID('Steam.exe') <> -1) and (SteamInstall) then begin
|
||||||
if MessageBox(frmMain.Handle, 'Steam is still running. It is necersarry to shut it down before you install Metamod:Source. Shut it down now?', PChar(frmMain.Caption), MB_ICONQUESTION + MB_YESNO) = mrYes then begin
|
if MessageBox(frmMain.Handle, 'Steam is still running. It is necersarry to shut it down before you install Metamod:Source. Shut it down now?', PChar(frmMain.Caption), MB_ICONQUESTION + MB_YESNO) = mrYes then begin
|
||||||
AddStatus('Shutting down Steam...', clBlack, False);
|
AddStatus('Shutting down Steam...', clBlack, False);
|
||||||
if GetProcessID('Steam.exe') = -1 then
|
if GetProcessID('Steam.exe') = -1 then
|
||||||
@ -247,13 +245,13 @@ begin
|
|||||||
Application.Terminate;
|
Application.Terminate;
|
||||||
exit;
|
exit;
|
||||||
end;
|
end;
|
||||||
end;
|
end;}
|
||||||
frmMain.ggeAll.Progress := 1;
|
frmMain.ggeAll.Progress := 1;
|
||||||
frmMain.ggeItem.Progress := 1;
|
frmMain.ggeItem.Progress := 1;
|
||||||
{ Unpack }
|
{ Unpack }
|
||||||
frmMain.ggeItem.Progress := 0;
|
frmMain.ggeItem.Progress := 0;
|
||||||
AddStatus('Unpacking files...', clBlack);
|
AddStatus('Unpacking files...', clBlack);
|
||||||
if not Unpack() then begin
|
if not Unpack(Source) then begin
|
||||||
AddStatus('No files attached!', clRed);
|
AddStatus('No files attached!', clRed);
|
||||||
Screen.Cursor := crDefault;
|
Screen.Cursor := crDefault;
|
||||||
exit;
|
exit;
|
||||||
@ -265,8 +263,8 @@ begin
|
|||||||
CopyConfig := True;
|
CopyConfig := True;
|
||||||
AddStatus('Creating directories...', clBlack);
|
AddStatus('Creating directories...', clBlack);
|
||||||
if DirectoryExists(ePath + 'addons\metamod\bin') then begin
|
if DirectoryExists(ePath + 'addons\metamod\bin') then begin
|
||||||
case MessageBox(frmMain.Handle, 'A Metamod:Source installation was already detected. If you choose to reinstall, your configuration files will be erased. Click Yes to continue, No to Upgrade, or Cancel to abort the install.', PChar(frmMain.Caption), MB_ICONQUESTION + MB_YESNOCANCEL) of
|
case MessageBox(frmMain.Handle, 'A Metamod:Source installation was already detected. If you choose to reinstall, your configuration files will be erased. Click Yes to upgrade, No to reinstall, or Cancel to abort the installation.', PChar(frmMain.Caption), MB_ICONQUESTION + MB_YESNOCANCEL) of
|
||||||
mrNo: CopyConfig := False;
|
mrYes: CopyConfig := False;
|
||||||
mrCancel: begin
|
mrCancel: begin
|
||||||
Application.Terminate;
|
Application.Terminate;
|
||||||
exit;
|
exit;
|
||||||
@ -282,7 +280,7 @@ begin
|
|||||||
frmMain.ggeItem.Progress := 1;
|
frmMain.ggeItem.Progress := 1;
|
||||||
frmMain.ggeAll.Progress := 3;
|
frmMain.ggeAll.Progress := 3;
|
||||||
|
|
||||||
{ gameinfo.txt }
|
{ gameinfo.txt for check / create VDF file }
|
||||||
if not FileExists(ePath + 'gameinfo.txt') then begin
|
if not FileExists(ePath + 'gameinfo.txt') then begin
|
||||||
if MessageBox(frmMain.Handle, 'The file "gameinfo.txt" couldn''t be found. Continue installation?', PChar(frmMain.Caption), MB_ICONQUESTION + MB_YESNO) = mrNo then begin
|
if MessageBox(frmMain.Handle, 'The file "gameinfo.txt" couldn''t be found. Continue installation?', PChar(frmMain.Caption), MB_ICONQUESTION + MB_YESNO) = mrNo then begin
|
||||||
AddStatus('Installation canceled by user!', clRed, False);
|
AddStatus('Installation canceled by user!', clRed, False);
|
||||||
@ -304,33 +302,32 @@ begin
|
|||||||
AddSkipped;
|
AddSkipped;
|
||||||
frmMain.ggeItem.Progress := 1;
|
frmMain.ggeItem.Progress := 1;
|
||||||
frmMain.ggeAll.Progress := 4;
|
frmMain.ggeAll.Progress := 4;
|
||||||
{ Gameinfo.txt }
|
{ CDF Plugin }
|
||||||
frmMain.ggeItem.Progress := 0;
|
frmMain.ggeItem.Progress := 0;
|
||||||
eFound := False;
|
AddStatus('Creating VDF Plugin...', clBlack);
|
||||||
AddStatus('Editing gameinfo.txt...', clBlack);
|
if (FileExists(ePath + 'addons\metamod.vdf')) then begin
|
||||||
eStr.LoadFromFile(ePath + 'gameinfo.txt');
|
eStr.LoadFromFile(ePath + 'addons\metamod.vdf');
|
||||||
for i := 0 to eStr.Count -1 do begin
|
if (Pos('server.dll', eStr.Text) <> 0) then
|
||||||
if Trim(LowerCase(eStr[i])) = 'gamebin |gameinfo_path|addons/metamod/bin' then begin
|
AddSkipped
|
||||||
eFound := True;
|
else begin
|
||||||
break;
|
eStr.Add('');
|
||||||
|
eStr.Add('"Plugin"');
|
||||||
|
eStr.Add('{');
|
||||||
|
eStr.Add(' "file" "..\' + GetModName(ePath) + '\addons\metamod\bin\server.dll"');
|
||||||
|
eStr.Add('}');
|
||||||
|
eStr.SaveToFile(ePath + 'addons\metamod.vdf');
|
||||||
|
AddDone;
|
||||||
end;
|
end;
|
||||||
end;
|
|
||||||
|
|
||||||
if not eFound then begin
|
|
||||||
for i := 0 to eStr.Count -1 do begin
|
|
||||||
if Trim(eStr[i]) = 'SearchPaths' then begin
|
|
||||||
eStr.Insert(i +2, ' GameBin |gameinfo_path|addons/metamod/bin');
|
|
||||||
AddDone;
|
|
||||||
break;
|
|
||||||
end;
|
|
||||||
end;
|
|
||||||
SetFileAttributes(PChar(ePath + 'gameinfo.txt'), 0);
|
|
||||||
eStr.SaveToFile(ePath + 'gameinfo.txt');
|
|
||||||
SetFileAttributes(PChar(ePath + 'gameinfo.txt'), faReadOnly); // important for listen servers
|
|
||||||
AddDone;
|
|
||||||
end
|
end
|
||||||
else
|
else begin
|
||||||
AddSkipped;
|
eStr.Add('');
|
||||||
|
eStr.Add('"Plugin"');
|
||||||
|
eStr.Add('{');
|
||||||
|
eStr.Add(' "file" "..\' + GetModName(ePath) + '\addons\metamod\bin\server.dll"');
|
||||||
|
eStr.Add('}');
|
||||||
|
eStr.SaveToFile(ePath + 'addons\metamod.vdf');
|
||||||
|
AddDone;
|
||||||
|
end;
|
||||||
eStr.Free;
|
eStr.Free;
|
||||||
frmMain.ggeItem.Progress := 1;
|
frmMain.ggeItem.Progress := 1;
|
||||||
frmMain.ggeAll.Progress := 5;
|
frmMain.ggeAll.Progress := 5;
|
||||||
@ -342,16 +339,9 @@ begin
|
|||||||
AddDone;
|
AddDone;
|
||||||
frmMain.ggeItem.Progress := 1;
|
frmMain.ggeItem.Progress := 1;
|
||||||
frmMain.ggeAll.Progress := 6;
|
frmMain.ggeAll.Progress := 6;
|
||||||
if ListenInstall then begin
|
|
||||||
ePath := ExtractFilePath(Copy(ePath, 1, Length(ePath)-1));
|
|
||||||
AddStatus('Copying hl2launch.exe...', clBlack);
|
|
||||||
CopyFile(PChar(ExtractFilePath(ParamStr(0)) + 'hl2launch.exe'), PChar(ePath + 'hl2launch.exe'), False);
|
|
||||||
AddDone;
|
|
||||||
end;
|
|
||||||
{ Remove files }
|
{ Remove files }
|
||||||
frmMain.ggeItem.Progress := 0;
|
frmMain.ggeItem.Progress := 0;
|
||||||
AddStatus('Removing temporary files...', clBlack);
|
AddStatus('Removing temporary files...', clBlack);
|
||||||
DeleteFile(PChar(ExtractFilePath(ParamStr(0)) + 'hl2launch.exe'));
|
|
||||||
DeleteFile(PChar(ExtractFilePath(ParamStr(0)) + 'server.dll'));
|
DeleteFile(PChar(ExtractFilePath(ParamStr(0)) + 'server.dll'));
|
||||||
DeleteFile(PChar(ExtractFilePath(ParamStr(0)) + 'server_i486.so'));
|
DeleteFile(PChar(ExtractFilePath(ParamStr(0)) + 'server_i486.so'));
|
||||||
AddDone;
|
AddDone;
|
||||||
@ -363,44 +353,41 @@ begin
|
|||||||
frmMain.cmdNext.Enabled := True;
|
frmMain.cmdNext.Enabled := True;
|
||||||
frmMain.cmdCancel.Hide;
|
frmMain.cmdCancel.Hide;
|
||||||
Screen.Cursor := crDefault;
|
Screen.Cursor := crDefault;
|
||||||
|
|
||||||
if ListenInstall then
|
|
||||||
MessageBox(frmMain.Handle, PChar('hl2launch.exe has been copied to ' + ePath + '. You can use it if you want to start your Source game with Metamod:Source enabled.'), PChar(Application.Title), MB_ICONINFORMATION);
|
|
||||||
end;
|
end;
|
||||||
|
|
||||||
{ Dedicated Server }
|
{ Dedicated Server }
|
||||||
|
|
||||||
procedure InstallDedicated(eModPath: String; UseSteam: Boolean);
|
procedure InstallDedicated(eModPath: String; const UseSteam, Source: Boolean);
|
||||||
begin
|
begin
|
||||||
StartTime := Now;
|
StartTime := Now;
|
||||||
Screen.Cursor := crHourGlass;
|
Screen.Cursor := crHourGlass;
|
||||||
AddStatus('Starting Metamod:Source installation on dedicated server...', clBlack, False);
|
AddStatus('Starting Metamod:Source installation on dedicated server...', clBlack, False);
|
||||||
BasicInstallation(eModPath, UseSteam, False, osWindows);
|
BasicInstallation(eModPath, UseSteam, False, osWindows, Source);
|
||||||
end;
|
end;
|
||||||
|
|
||||||
{ Listen Server }
|
{ Listen Server }
|
||||||
|
|
||||||
procedure InstallListen(ePath: String);
|
procedure InstallListen(ePath: String; const Source: Boolean);
|
||||||
begin
|
begin
|
||||||
StartTime := Now;
|
StartTime := Now;
|
||||||
Screen.Cursor := crHourGlass;
|
Screen.Cursor := crHourGlass;
|
||||||
AddStatus('Starting Metamod:Source installation on the listen server...', clBlack);
|
AddStatus('Starting Metamod:Source installation on the listen server...', clBlack);
|
||||||
BasicInstallation(ePath, True, True, osWindows);
|
BasicInstallation(ePath, True, True, osWindows, Source);
|
||||||
end;
|
end;
|
||||||
|
|
||||||
{ Custom mod }
|
{ Custom mod }
|
||||||
|
|
||||||
procedure InstallCustom(ePath: String; eOS: TOS);
|
procedure InstallCustom(ePath: String; eOS: TOS; const Source: Boolean);
|
||||||
begin
|
begin
|
||||||
StartTime := Now;
|
StartTime := Now;
|
||||||
Screen.Cursor := crHourGlass;
|
Screen.Cursor := crHourGlass;
|
||||||
AddStatus('Starting Metamod:Source installation...', clBlack);
|
AddStatus('Starting Metamod:Source installation...', clBlack);
|
||||||
BasicInstallation(ePath, False, False, eOS);
|
BasicInstallation(ePath, False, False, eOS, Source);
|
||||||
end;
|
end;
|
||||||
|
|
||||||
{ FTP }
|
{ FTP }
|
||||||
|
|
||||||
procedure InstallFTP(OS: TOS);
|
procedure InstallFTP(OS: TOS; const Source: Boolean; const ModDir: String);
|
||||||
function DoReconnect: Boolean;
|
function DoReconnect: Boolean;
|
||||||
begin
|
begin
|
||||||
Result := False;
|
Result := False;
|
||||||
@ -414,11 +401,13 @@ begin
|
|||||||
end;
|
end;
|
||||||
end;
|
end;
|
||||||
|
|
||||||
|
|
||||||
label CreateAgain;
|
label CreateAgain;
|
||||||
label UploadAgain;
|
label UploadAgain;
|
||||||
|
|
||||||
var eStr: TStringList;
|
var eStr: TStringList;
|
||||||
i: integer;
|
CopyConfig, CommentFound: Boolean;
|
||||||
CopyConfig, eFound: Boolean;
|
i: Integer;
|
||||||
begin
|
begin
|
||||||
frmMain.cmdCancel.Show;
|
frmMain.cmdCancel.Show;
|
||||||
frmMain.cmdNext.Hide;
|
frmMain.cmdNext.Hide;
|
||||||
@ -426,72 +415,27 @@ begin
|
|||||||
|
|
||||||
frmMain.ggeAll.MaxValue := 6;
|
frmMain.ggeAll.MaxValue := 6;
|
||||||
frmMain.ggeAll.Progress := 0;
|
frmMain.ggeAll.Progress := 0;
|
||||||
frmMain.ggeItem.MaxValue := 1;
|
frmMain.ggeItem.MaxValue := 3;
|
||||||
frmMain.ggeItem.Progress := 0;
|
frmMain.ggeItem.Progress := 0;
|
||||||
|
|
||||||
|
StartTime := Now;
|
||||||
{ Unpack }
|
{ Unpack }
|
||||||
frmMain.ggeItem.Progress := 0;
|
|
||||||
AddStatus('Unpacking files...', clBlack);
|
AddStatus('Unpacking files...', clBlack);
|
||||||
if not Unpack() then begin
|
if not Unpack(Source) then begin
|
||||||
AddStatus('No files attached!', clRed);
|
AddStatus('No files attached!', clRed);
|
||||||
Screen.Cursor := crDefault;
|
Screen.Cursor := crDefault;
|
||||||
exit;
|
exit;
|
||||||
end;
|
end;
|
||||||
AddDone;
|
AddDone;
|
||||||
frmMain.ggeAll.Progress := 2;
|
frmMain.ggeAll.Progress := 1;
|
||||||
frmMain.ggeItem.Progress := 1;
|
frmMain.ggeItem.Progress := 1;
|
||||||
{ Check for installation }
|
Sleep(250);
|
||||||
AddStatus('Editing gameinfo.txt...', clBlack);
|
|
||||||
eStr := TStringList.Create;
|
|
||||||
DownloadFile('gameinfo.txt', ExtractFilePath(ParamStr(0)) + 'gameinfo.txt');
|
|
||||||
eStr.LoadFromFile(ExtractFilePath(ParamStr(0)) + 'gameinfo.txt');
|
|
||||||
|
|
||||||
CopyConfig := True;
|
|
||||||
eFound := False;
|
|
||||||
for i := 0 to eStr.Count -1 do begin
|
|
||||||
if Trim(LowerCase(eStr[i])) = 'gamebin |gameinfo_path|addons/metamod/bin' then begin
|
|
||||||
eFound := True;
|
|
||||||
case MessageBox(frmMain.Handle, 'A Metamod:Source installation was already detected. If you choose to reinstall, your configuration files will be erased. Click Yes to continue, No to Upgrade, or Cancel to abort the install.', PChar(frmMain.Caption), MB_ICONQUESTION + MB_YESNOCANCEL) of
|
|
||||||
mrNo: CopyConfig := False;
|
|
||||||
mrCancel: begin
|
|
||||||
Application.Terminate;
|
|
||||||
eStr.Free;
|
|
||||||
exit;
|
|
||||||
end;
|
|
||||||
end;
|
|
||||||
break;
|
|
||||||
end;
|
|
||||||
end;
|
|
||||||
|
|
||||||
if not eFound then begin
|
|
||||||
for i := 0 to eStr.Count -1 do begin
|
|
||||||
if Trim(eStr[i]) = 'SearchPaths' then begin
|
|
||||||
eStr.Insert(i +2, ' GameBin |gameinfo_path|addons/metamod/bin');
|
|
||||||
AddDone;
|
|
||||||
break;
|
|
||||||
end;
|
|
||||||
end;
|
|
||||||
eStr.SaveToFile(ExtractFilePath(ParamStr(0)) + 'gameinfo.txt');
|
|
||||||
UploadFile(ExtractFilePath(ParamStr(0)) + 'gameinfo.txt', 'gameinfo.txt');
|
|
||||||
try
|
|
||||||
AddStatus('Trying to set gameinfo.txt to read-only...', clBlack);
|
|
||||||
frmMain.IdFTP.Site('CHMOD 744 gameinfo.txt');
|
|
||||||
AddDone;
|
|
||||||
except
|
|
||||||
AddStatus('Warning: CHMOD not supported.', clMaroon);
|
|
||||||
end;
|
|
||||||
DeleteFile(PChar(ExtractFilePath(ParamStr(0)) + 'gameinfo.txt'));
|
|
||||||
end
|
|
||||||
else
|
|
||||||
AddSkipped;
|
|
||||||
frmMain.ggeAll.Progress := 3;
|
|
||||||
frmMain.ggeItem.Progress := 1;
|
|
||||||
|
|
||||||
{ Create directories }
|
{ Create directories }
|
||||||
|
frmMain.ggeAll.Progress := 2;
|
||||||
frmMain.ggeItem.Progress := 0;
|
frmMain.ggeItem.Progress := 0;
|
||||||
frmMain.ggeItem.MaxValue := 3;
|
|
||||||
AddStatus('Creating directories...', clBlack);
|
AddStatus('Creating directories...', clBlack);
|
||||||
if not eFound then begin
|
try
|
||||||
FTPMakeDir('addons');
|
FTPMakeDir('addons');
|
||||||
frmMain.IdFTP.ChangeDir('addons');
|
frmMain.IdFTP.ChangeDir('addons');
|
||||||
frmMain.ggeItem.Progress := 1;
|
frmMain.ggeItem.Progress := 1;
|
||||||
@ -501,24 +445,108 @@ begin
|
|||||||
FTPMakeDir('bin');
|
FTPMakeDir('bin');
|
||||||
frmMain.ggeItem.Progress := 3;
|
frmMain.ggeItem.Progress := 3;
|
||||||
AddDone;
|
AddDone;
|
||||||
end
|
except
|
||||||
else
|
|
||||||
AddSkipped;
|
AddSkipped;
|
||||||
frmMain.ggeAll.Progress := 4;
|
end;
|
||||||
|
{ Check VDF Plugin }
|
||||||
|
CopyConfig := True;
|
||||||
|
|
||||||
|
frmMain.ggeAll.Progress := 3;
|
||||||
|
frmMain.ggeItem.Progress := 0;
|
||||||
|
|
||||||
|
AddStatus('Creating VDF Plugin...', clBlack);
|
||||||
|
eStr := TStringList.Create;
|
||||||
|
try
|
||||||
|
frmMain.IdFTP.ChangeDirUp;
|
||||||
|
|
||||||
|
frmMain.ggeItem.Progress := 1;
|
||||||
|
DownloadFile('metamod.vdf', ExtractFilePath(ParamStr(0)) + 'metamod.vdf');
|
||||||
|
eStr.LoadFromFile(ExtractFilePath(ParamStr(0)) + 'metamod.vdf');
|
||||||
|
frmMain.ggeItem.Progress := 2;
|
||||||
|
if (((Pos('server.dll', eStr.Text) <> 0) and (OS = osWindows)) or ((Pos('server_i486.so', eStr.Text) <> 0) and (OS = osLinux))) then begin
|
||||||
|
case MessageBox(frmMain.Handle, 'A Metamod:Source installation was already detected. If you choose to reinstall, your configuration files will be erased. Click Yes to upgrade, No to reinstall, or Cancel to abort the installation.', PChar(frmMain.Caption), MB_ICONQUESTION + MB_YESNOCANCEL) of
|
||||||
|
mrYes: CopyConfig := False;
|
||||||
|
mrCancel: begin
|
||||||
|
Application.Terminate;
|
||||||
|
eStr.Free;
|
||||||
|
exit;
|
||||||
|
end;
|
||||||
|
end;
|
||||||
|
end;
|
||||||
|
except
|
||||||
|
// bacon
|
||||||
|
end;
|
||||||
|
{ Create and Upload plugin here }
|
||||||
|
frmMain.ggeItem.Progress := 2;
|
||||||
|
eStr.Clear;
|
||||||
|
eStr.Add('"Plugin"');
|
||||||
|
eStr.Add('{');
|
||||||
|
if (OS = osWindows) then
|
||||||
|
eStr.Add(' "file" "..\' + ModDir + '\addons\metamod\bin\server.dll"')
|
||||||
|
else
|
||||||
|
eStr.Add(' "file" "../' + ModDir + '/addons/metamod/bin/server_i486.so"');
|
||||||
|
eStr.Add('}');
|
||||||
|
eStr.SaveToFile(ExtractFilePath(ParamStr(0)) + 'metamod.vdf');
|
||||||
|
UploadFile(ExtractFilePath(ParamStr(0)) + 'metamod.vdf', 'metamod.vdf');
|
||||||
frmMain.ggeItem.Progress := 3;
|
frmMain.ggeItem.Progress := 3;
|
||||||
{ Upload metaplugins.ini }
|
{ Upload metaplugins.ini }
|
||||||
frmMain.ggeAll.Progress := 4;
|
frmMain.ggeAll.Progress := 4;
|
||||||
frmMain.ggeItem.MaxValue := 1;
|
frmMain.ggeItem.MaxValue := 1;
|
||||||
frmMain.ggeItem.Progress := 0;
|
frmMain.ggeItem.Progress := 0;
|
||||||
AddStatus('Uploading metaplugins.ini...', clBlack);
|
AddStatus('Uploading metaplugins.ini...', clBlack);
|
||||||
if CopyConfig then begin
|
frmMain.IdFTP.ChangeDir('metamod');
|
||||||
|
if (CopyConfig) then begin
|
||||||
eStr.Clear;
|
eStr.Clear;
|
||||||
|
// see http://svn.alliedmods.net/viewvc.cgi/metamodsource/orangebox/addons/metamod/metaplugins.ini?revision=1099&root=Packages
|
||||||
|
eStr.Add(';List one plugin per line. Each line should contain the path to the plugin''s binary.');
|
||||||
|
eStr.Add(';Any line starting with a '';'' character is a comment line, and is ignored.');
|
||||||
|
eStr.Add(';');
|
||||||
|
eStr.Add(';You do not need to include the _i486.so or .dll part of the file name. Example:');
|
||||||
|
eStr.Add('; addons/sourcemod/bin/sourcemod_mm');
|
||||||
|
eStr.Add(';You may also put an alias in front of the file, for example:');
|
||||||
|
eStr.Add('; sm addons/sourcemod/bin/sourcemod_mm');
|
||||||
|
eStr.Add(';Will allow you to use "meta load sm" from the console.');
|
||||||
|
eStr.Add(';');
|
||||||
|
eStr.Add(';********* LIST PLUGINS BELOW ***********');
|
||||||
|
// end
|
||||||
eStr.SaveToFile(ExtractFilePath(ParamStr(0)) + 'metaplugins.ini');
|
eStr.SaveToFile(ExtractFilePath(ParamStr(0)) + 'metaplugins.ini');
|
||||||
UploadFile(ExtractFilePath(ParamStr(0)) + 'metaplugins.ini', 'metaplugins.ini');
|
UploadFile(ExtractFilePath(ParamStr(0)) + 'metaplugins.ini', 'metaplugins.ini');
|
||||||
DeleteFile(PChar(ExtractFilePath(ParamStr(0)) + 'metaplugins.ini'));
|
|
||||||
end
|
end
|
||||||
else
|
else if (frmMain.IdFTP.Size('metaplugins.ini') <> -1) then begin
|
||||||
AddSkipped;
|
DownloadFile('metaplugins.ini', ExtractFilePath(ParamStr(0)) + 'metaplugins.ini');
|
||||||
|
eStr.LoadFromFile(ExtractFilePath(ParamStr(0)) + 'metaplugins.ini');
|
||||||
|
CommentFound := False;
|
||||||
|
for i := 0 to eStr.Count -1 do begin
|
||||||
|
if (Pos(';', eStr[i]) = 1) then begin
|
||||||
|
CommentFound := True;
|
||||||
|
break;
|
||||||
|
end;
|
||||||
|
end;
|
||||||
|
|
||||||
|
if (CommentFound) then
|
||||||
|
AddSkipped
|
||||||
|
else begin
|
||||||
|
// delete empty lines first
|
||||||
|
for i := eStr.Count -1 downto 0 do begin
|
||||||
|
if (Trim(eStr[i]) = '') then
|
||||||
|
eStr.Delete(i);
|
||||||
|
end;
|
||||||
|
// see http://svn.alliedmods.net/viewvc.cgi/metamodsource/orangebox/addons/metamod/metaplugins.ini?revision=1099&root=Packages
|
||||||
|
eStr.Insert(0, ';List one plugin per line. Each line should contain the path to the plugin''s binary.');
|
||||||
|
eStr.Insert(1, ';Any line starting with a '';'' character is a comment line, and is ignored.');
|
||||||
|
eStr.Insert(2, ';');
|
||||||
|
eStr.Insert(3, ';You do not need to include the _i486.so or .dll part of the file name. Example:');
|
||||||
|
eStr.Insert(4, '; addons/sourcemod/bin/sourcemod_mm');
|
||||||
|
eStr.Insert(5, ';You may also put an alias in front of the file, for example:');
|
||||||
|
eStr.Insert(6, '; sm addons/sourcemod/bin/sourcemod_mm');
|
||||||
|
eStr.Insert(7, ';Will allow you to use "meta load sm" from the console.');
|
||||||
|
eStr.Insert(8, ';');
|
||||||
|
eStr.Insert(9, ';********* LIST PLUGINS BELOW ***********');
|
||||||
|
// end
|
||||||
|
eStr.SaveToFile(ExtractFilePath(ParamStr(0)) + 'metaplugins.ini');
|
||||||
|
UploadFile(ExtractFilePath(ParamStr(0)) + 'metaplugins.ini', 'metaplugins.ini');
|
||||||
|
end;
|
||||||
|
end;
|
||||||
frmMain.ggeAll.Progress := 5;
|
frmMain.ggeAll.Progress := 5;
|
||||||
frmMain.ggeItem.Progress := 1;
|
frmMain.ggeItem.Progress := 1;
|
||||||
{ Upload server.dll / server_i486.so }
|
{ Upload server.dll / server_i486.so }
|
||||||
@ -537,9 +565,10 @@ begin
|
|||||||
end;
|
end;
|
||||||
{ Remove created files }
|
{ Remove created files }
|
||||||
AddStatus('Removing temporary files...', clBlack);
|
AddStatus('Removing temporary files...', clBlack);
|
||||||
DeleteFile(PChar(ExtractFilePath(ParamStr(0)) + 'hl2launch.exe'));
|
|
||||||
DeleteFile(PChar(ExtractFilePath(ParamStr(0)) + 'server.dll'));
|
DeleteFile(PChar(ExtractFilePath(ParamStr(0)) + 'server.dll'));
|
||||||
DeleteFile(PChar(ExtractFilePath(ParamStr(0)) + 'server_i486.so'));
|
DeleteFile(PChar(ExtractFilePath(ParamStr(0)) + 'server_i486.so'));
|
||||||
|
DeleteFile(PChar(ExtractFilePath(ParamStr(0)) + 'metamod.vdf'));
|
||||||
|
DeleteFile(PChar(ExtractFilePath(ParamStr(0)) + 'metaplugins.ini'));
|
||||||
AddDone;
|
AddDone;
|
||||||
{ End }
|
{ End }
|
||||||
frmMain.IdFTP.Disconnect;
|
frmMain.IdFTP.Disconnect;
|
||||||
|
@ -4,11 +4,11 @@ interface
|
|||||||
|
|
||||||
uses SysUtils, Classes, Zlib;
|
uses SysUtils, Classes, Zlib;
|
||||||
|
|
||||||
procedure CompressFiles(Files : TStrings; const Filename : String);
|
procedure CompressFiles(Files: TStrings; const Filename: String);
|
||||||
function DecompressStream(Stream : TMemoryStream; DestDirectory : String): Boolean;
|
function DecompressStream(Stream: TMemoryStream; DestDirectory: String; const Source: Boolean): Boolean;
|
||||||
function AttachToFile(const AFileName: string; MemoryStream: TMemoryStream; Version: String): Boolean;
|
function AttachToFile(const AFileName: string; MemoryStream: TMemoryStream; Version: String): Boolean;
|
||||||
function LoadFromFile(const AFileName: string; MemoryStream: TMemoryStream): Boolean;
|
function LoadFromFile(const AFileName: string; MemoryStream: TMemoryStream): Boolean;
|
||||||
function Unpack: Boolean;
|
function Unpack(const Source: Boolean): Boolean;
|
||||||
function GetVersion: String;
|
function GetVersion: String;
|
||||||
|
|
||||||
implementation
|
implementation
|
||||||
@ -54,6 +54,8 @@ begin
|
|||||||
{ append the compressed file to the destination file }
|
{ append the compressed file to the destination file }
|
||||||
tmpFile := TFileStream.Create('tmp',fmOpenRead);
|
tmpFile := TFileStream.Create('tmp',fmOpenRead);
|
||||||
try
|
try
|
||||||
|
l := tmpFile.Size;
|
||||||
|
outfile.WriteBuffer(l, SizeOf(l));
|
||||||
outfile.CopyFrom(tmpFile,0);
|
outfile.CopyFrom(tmpFile,0);
|
||||||
finally
|
finally
|
||||||
tmpFile.Free;
|
tmpFile.Free;
|
||||||
@ -68,12 +70,13 @@ begin
|
|||||||
DeleteFile('tmp');
|
DeleteFile('tmp');
|
||||||
end;
|
end;
|
||||||
end;
|
end;
|
||||||
function DecompressStream(Stream : TMemoryStream; DestDirectory : String): Boolean;
|
|
||||||
|
function DecompressStream(Stream : TMemoryStream; DestDirectory : String; const Source: Boolean): Boolean;
|
||||||
var
|
var
|
||||||
dest,s : String;
|
dest,s : String;
|
||||||
decompr : TDecompressionStream;
|
decompr : TDecompressionStream;
|
||||||
outfile : TFilestream;
|
outfile : TFilestream;
|
||||||
i,l,c : Integer;
|
i,l,lr,c : Integer;
|
||||||
begin
|
begin
|
||||||
// IncludeTrailingPathDelimiter (D6/D7 only)
|
// IncludeTrailingPathDelimiter (D6/D7 only)
|
||||||
dest := IncludeTrailingPathDelimiter(DestDirectory);
|
dest := IncludeTrailingPathDelimiter(DestDirectory);
|
||||||
@ -82,24 +85,30 @@ begin
|
|||||||
try
|
try
|
||||||
{ number of files }
|
{ number of files }
|
||||||
Stream.Read(c,SizeOf(c));
|
Stream.Read(c,SizeOf(c));
|
||||||
for i := 1 to c do
|
for i := 1 to c do begin
|
||||||
begin
|
|
||||||
{ read filename }
|
{ read filename }
|
||||||
Stream.Read(l,SizeOf(l));
|
Stream.Read(l,SizeOf(l));
|
||||||
SetLength(s,l);
|
SetLength(s,l);
|
||||||
Stream.Read(s[1],l);
|
Stream.Read(s[1],l);
|
||||||
{ read filesize }
|
|
||||||
Stream.Read(l,SizeOf(l));
|
Stream.Read(l,SizeOf(l));
|
||||||
{ decompress the files and store it }
|
Stream.Read(lr,SizeOf(lr));
|
||||||
s := dest+s; //include the path
|
{ check if this is the right file }
|
||||||
outfile := TFileStream.Create(s,fmCreate);
|
if ((Pos('.source', s) <> 0) and (Source)) or ((Pos('.orangebox', s) <> 0) and (not Source)) then begin
|
||||||
decompr := TDecompressionStream.Create(Stream);
|
{ remove extension and read filesize }
|
||||||
try
|
s := ChangeFileExt(s, '');
|
||||||
outfile.CopyFrom(decompr,l);
|
{ decompress the files and store it }
|
||||||
finally
|
s := dest+s; //include the path
|
||||||
outfile.Free;
|
outfile := TFileStream.Create(s,fmCreate);
|
||||||
decompr.Free;
|
decompr := TDecompressionStream.Create(Stream);
|
||||||
end;
|
try
|
||||||
|
outfile.CopyFrom(decompr,l);
|
||||||
|
finally
|
||||||
|
outfile.Free;
|
||||||
|
decompr.Free;
|
||||||
|
end;
|
||||||
|
end
|
||||||
|
else
|
||||||
|
Stream.Position := Stream.Position + lr;
|
||||||
end;
|
end;
|
||||||
finally
|
finally
|
||||||
Result := True;
|
Result := True;
|
||||||
@ -114,6 +123,7 @@ begin
|
|||||||
Result := False;
|
Result := False;
|
||||||
if not FileExists(AFileName) then
|
if not FileExists(AFileName) then
|
||||||
Exit;
|
Exit;
|
||||||
|
|
||||||
try
|
try
|
||||||
aStream := TFileStream.Create(AFileName, fmOpenWrite or fmShareDenyWrite);
|
aStream := TFileStream.Create(AFileName, fmOpenWrite or fmShareDenyWrite);
|
||||||
MemoryStream.Seek(0, soFromBeginning);
|
MemoryStream.Seek(0, soFromBeginning);
|
||||||
@ -177,14 +187,14 @@ end;
|
|||||||
|
|
||||||
{ Unpack function }
|
{ Unpack function }
|
||||||
|
|
||||||
function Unpack: Boolean;
|
function Unpack(const Source: Boolean): Boolean;
|
||||||
var eStream: TMemoryStream;
|
var eStream: TMemoryStream;
|
||||||
begin
|
begin
|
||||||
eStream := TMemoryStream.Create;
|
eStream := TMemoryStream.Create;
|
||||||
try
|
try
|
||||||
// Get ZIP
|
// Get ZIP
|
||||||
LoadFromFile(ParamStr(0), eStream);
|
LoadFromFile(ParamStr(0), eStream);
|
||||||
DecompressStream(eStream, ExtractFilePath(ParamStr(0))); // Unpack files
|
DecompressStream(eStream, ExtractFilePath(ParamStr(0)), Source); // Unpack files
|
||||||
|
|
||||||
Result := True;
|
Result := True;
|
||||||
except
|
except
|
||||||
|
Binary file not shown.
@ -5,7 +5,7 @@ interface
|
|||||||
uses
|
uses
|
||||||
SysUtils, Windows, Messages, Classes, Graphics, Controls,
|
SysUtils, Windows, Messages, Classes, Graphics, Controls,
|
||||||
StdCtrls, ExtCtrls, Forms, FileCtrl, ComCtrls, ShellCtrls,
|
StdCtrls, ExtCtrls, Forms, FileCtrl, ComCtrls, ShellCtrls,
|
||||||
TFlatComboBoxUnit, TFlatButtonUnit;
|
TFlatComboBoxUnit, TFlatButtonUnit, TFlatCheckBoxUnit;
|
||||||
|
|
||||||
type
|
type
|
||||||
TfrmSelectModPath = class(TForm)
|
TfrmSelectModPath = class(TForm)
|
||||||
@ -14,6 +14,8 @@ type
|
|||||||
trvDirectory: TShellTreeView;
|
trvDirectory: TShellTreeView;
|
||||||
cmdOK: TFlatButton;
|
cmdOK: TFlatButton;
|
||||||
cmdCancel: TFlatButton;
|
cmdCancel: TFlatButton;
|
||||||
|
chkUsesOrangebox: TFlatCheckBox;
|
||||||
|
procedure trvDirectoryClick(Sender: TObject);
|
||||||
end;
|
end;
|
||||||
|
|
||||||
var
|
var
|
||||||
@ -23,4 +25,11 @@ implementation
|
|||||||
|
|
||||||
{$R *.DFM}
|
{$R *.DFM}
|
||||||
|
|
||||||
|
procedure TfrmSelectModPath.trvDirectoryClick(Sender: TObject);
|
||||||
|
begin
|
||||||
|
// !! OrangeBox Check !!
|
||||||
|
if (trvDirectory.Selected <> nil) then
|
||||||
|
chkUsesOrangebox.Checked := (chkUsesOrangebox.Checked) or (trvDirectory.Selected.Text = 'tf');
|
||||||
|
end;
|
||||||
|
|
||||||
end.
|
end.
|
||||||
|
@ -10407,7 +10407,7 @@ object frmMain: TfrmMain
|
|||||||
Lines.Strings = (
|
Lines.Strings = (
|
||||||
'The zlib/libpng License'
|
'The zlib/libpng License'
|
||||||
''
|
''
|
||||||
'Copyright (c) 2006, AlliedModders'
|
'Copyright (c) 2006-2008, AlliedModders'
|
||||||
''
|
''
|
||||||
|
|
||||||
'This software is provided '#39'as-is'#39', without any express or implie' +
|
'This software is provided '#39'as-is'#39', without any express or implie' +
|
||||||
@ -10838,12 +10838,12 @@ object frmMain: TfrmMain
|
|||||||
Height = 13
|
Height = 13
|
||||||
Caption = '2. Connect to server and select the mod directory:'
|
Caption = '2. Connect to server and select the mod directory:'
|
||||||
end
|
end
|
||||||
object lblStep4: TLabel
|
object lblStep5: TLabel
|
||||||
Left = 44
|
Left = 44
|
||||||
Top = 296
|
Top = 338
|
||||||
Width = 64
|
Width = 64
|
||||||
Height = 13
|
Height = 13
|
||||||
Caption = '4. Click Next.'
|
Caption = '5. Click Next.'
|
||||||
end
|
end
|
||||||
object lblStep3: TLabel
|
object lblStep3: TLabel
|
||||||
Left = 44
|
Left = 44
|
||||||
@ -10852,6 +10852,13 @@ object frmMain: TfrmMain
|
|||||||
Height = 13
|
Height = 13
|
||||||
Caption = '3. Select the operating system of your server:'
|
Caption = '3. Select the operating system of your server:'
|
||||||
end
|
end
|
||||||
|
object lblStep4: TLabel
|
||||||
|
Left = 44
|
||||||
|
Top = 296
|
||||||
|
Width = 125
|
||||||
|
Height = 13
|
||||||
|
Caption = '4. Select the engine type:'
|
||||||
|
end
|
||||||
object pnlHeader3: TPanel
|
object pnlHeader3: TPanel
|
||||||
Left = 0
|
Left = 0
|
||||||
Top = 0
|
Top = 0
|
||||||
@ -11130,7 +11137,7 @@ object frmMain: TfrmMain
|
|||||||
TabStop = True
|
TabStop = True
|
||||||
end
|
end
|
||||||
object optLinux: TFlatRadioButton
|
object optLinux: TFlatRadioButton
|
||||||
Left = 173
|
Left = 183
|
||||||
Top = 3
|
Top = 3
|
||||||
Width = 82
|
Width = 82
|
||||||
Height = 14
|
Height = 14
|
||||||
@ -11138,7 +11145,7 @@ object frmMain: TfrmMain
|
|||||||
TabOrder = 1
|
TabOrder = 1
|
||||||
end
|
end
|
||||||
object FlatRadioButton1: TFlatRadioButton
|
object FlatRadioButton1: TFlatRadioButton
|
||||||
Left = 353
|
Left = 319
|
||||||
Top = 3
|
Top = 3
|
||||||
Width = 82
|
Width = 82
|
||||||
Height = 14
|
Height = 14
|
||||||
@ -11147,6 +11154,40 @@ object frmMain: TfrmMain
|
|||||||
TabOrder = 2
|
TabOrder = 2
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
object pnlEngineType: TPanel
|
||||||
|
Left = 44
|
||||||
|
Top = 312
|
||||||
|
Width = 441
|
||||||
|
Height = 21
|
||||||
|
BevelOuter = bvLowered
|
||||||
|
TabOrder = 5
|
||||||
|
object optAutoDetect: TFlatRadioButton
|
||||||
|
Left = 1
|
||||||
|
Top = 3
|
||||||
|
Width = 154
|
||||||
|
Height = 14
|
||||||
|
Caption = 'Auto-Detect (recommended)'
|
||||||
|
Checked = True
|
||||||
|
TabOrder = 0
|
||||||
|
TabStop = True
|
||||||
|
end
|
||||||
|
object optSource: TFlatRadioButton
|
||||||
|
Left = 183
|
||||||
|
Top = 3
|
||||||
|
Width = 96
|
||||||
|
Height = 15
|
||||||
|
Caption = 'Source'#8482' Engine'
|
||||||
|
TabOrder = 1
|
||||||
|
end
|
||||||
|
object optOrangeBox: TFlatRadioButton
|
||||||
|
Left = 319
|
||||||
|
Top = 3
|
||||||
|
Width = 118
|
||||||
|
Height = 15
|
||||||
|
Caption = 'OrangeBox'#8482' Engine'
|
||||||
|
TabOrder = 2
|
||||||
|
end
|
||||||
|
end
|
||||||
end
|
end
|
||||||
object jspInstallProgress: TJvStandardPage
|
object jspInstallProgress: TJvStandardPage
|
||||||
Left = 0
|
Left = 0
|
||||||
@ -11404,8 +11445,8 @@ object frmMain: TfrmMain
|
|||||||
end
|
end
|
||||||
end
|
end
|
||||||
object ilImages: TImageList
|
object ilImages: TImageList
|
||||||
Left = 154
|
Left = 334
|
||||||
Top = 324
|
Top = 8
|
||||||
Bitmap = {
|
Bitmap = {
|
||||||
494C010102000400040010001000FFFFFFFFFF10FFFFFFFFFFFFFFFF424D3600
|
494C010102000400040010001000FFFFFFFFFF10FFFFFFFFFFFFFFFF424D3600
|
||||||
0000000000003600000028000000400000001000000001002000000000000010
|
0000000000003600000028000000400000001000000001002000000000000010
|
||||||
@ -11555,23 +11596,23 @@ object frmMain: TfrmMain
|
|||||||
OnWork = IdFTPWork
|
OnWork = IdFTPWork
|
||||||
ProxySettings.ProxyType = fpcmNone
|
ProxySettings.ProxyType = fpcmNone
|
||||||
ProxySettings.Port = 0
|
ProxySettings.Port = 0
|
||||||
Left = 274
|
Left = 454
|
||||||
Top = 324
|
Top = 8
|
||||||
end
|
end
|
||||||
object IdAntiFreeze: TIdAntiFreeze
|
object IdAntiFreeze: TIdAntiFreeze
|
||||||
IdleTimeOut = 150
|
IdleTimeOut = 150
|
||||||
Left = 244
|
Left = 424
|
||||||
Top = 324
|
Top = 8
|
||||||
end
|
end
|
||||||
object tmrSpeed: TTimer
|
object tmrSpeed: TTimer
|
||||||
Enabled = False
|
Enabled = False
|
||||||
OnTimer = tmrSpeedTimer
|
OnTimer = tmrSpeedTimer
|
||||||
Left = 214
|
Left = 394
|
||||||
Top = 324
|
Top = 8
|
||||||
end
|
end
|
||||||
object IdLogFile: TIdLogFile
|
object IdLogFile: TIdLogFile
|
||||||
LogTime = False
|
LogTime = False
|
||||||
Left = 184
|
Left = 364
|
||||||
Top = 324
|
Top = 8
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
@ -63,7 +63,7 @@ type
|
|||||||
cmdConnect: TFlatButton;
|
cmdConnect: TFlatButton;
|
||||||
pnlDirectory: TPanel;
|
pnlDirectory: TPanel;
|
||||||
trvDirectories: TTreeView;
|
trvDirectories: TTreeView;
|
||||||
lblStep4: TLabel;
|
lblStep5: TLabel;
|
||||||
jspInstallProgress: TJvStandardPage;
|
jspInstallProgress: TJvStandardPage;
|
||||||
pnlHeader5: TPanel;
|
pnlHeader5: TPanel;
|
||||||
imgIcon4: TImage;
|
imgIcon4: TImage;
|
||||||
@ -101,6 +101,11 @@ type
|
|||||||
shpMods: TShape;
|
shpMods: TShape;
|
||||||
trvMods: TTreeView;
|
trvMods: TTreeView;
|
||||||
FlatRadioButton1: TFlatRadioButton;
|
FlatRadioButton1: TFlatRadioButton;
|
||||||
|
pnlEngineType: TPanel;
|
||||||
|
optAutoDetect: TFlatRadioButton;
|
||||||
|
optSource: TFlatRadioButton;
|
||||||
|
optOrangeBox: TFlatRadioButton;
|
||||||
|
lblStep4: TLabel;
|
||||||
procedure jvwStepsCancelButtonClick(Sender: TObject);
|
procedure jvwStepsCancelButtonClick(Sender: TObject);
|
||||||
procedure cmdCancelClick(Sender: TObject);
|
procedure cmdCancelClick(Sender: TObject);
|
||||||
procedure cmdNextClick(Sender: TObject);
|
procedure cmdNextClick(Sender: TObject);
|
||||||
@ -136,6 +141,9 @@ var
|
|||||||
|
|
||||||
var VERSION: String = '<none>';
|
var VERSION: String = '<none>';
|
||||||
|
|
||||||
|
const NormalHeight = 382;
|
||||||
|
FTPHeight = 422;
|
||||||
|
|
||||||
implementation
|
implementation
|
||||||
|
|
||||||
uses UnitFunctions, UnitfrmProxy, UnitInstall, UnitSelectModPath;
|
uses UnitFunctions, UnitfrmProxy, UnitInstall, UnitSelectModPath;
|
||||||
@ -159,10 +167,11 @@ var ePath: String;
|
|||||||
CurNode: TTreeNode;
|
CurNode: TTreeNode;
|
||||||
eOS: TOS;
|
eOS: TOS;
|
||||||
i: integer;
|
i: integer;
|
||||||
|
Source: Boolean;
|
||||||
begin
|
begin
|
||||||
{ FTP }
|
{ FTP }
|
||||||
if jplWizard.ActivePage = jspFTP then begin
|
if (jplWizard.ActivePage = jspFTP) then begin
|
||||||
if not IdFTP.Connected then
|
if (not IdFTP.Connected) then
|
||||||
IdFTP.Connect;
|
IdFTP.Connect;
|
||||||
eStr := TStringList.Create;
|
eStr := TStringList.Create;
|
||||||
ePath := '/';
|
ePath := '/';
|
||||||
@ -175,14 +184,22 @@ begin
|
|||||||
end;
|
end;
|
||||||
IdFTP.ChangeDir(ePath);
|
IdFTP.ChangeDir(ePath);
|
||||||
IdFTP.List(eStr, '', False);
|
IdFTP.List(eStr, '', False);
|
||||||
if eStr.IndexOf('gameinfo.txt') = -1 then begin
|
eStr.CaseSensitive := False;
|
||||||
|
// check if gameinfo.txt is in the directory -> valid installation
|
||||||
|
if (eStr.IndexOf('gameinfo.txt') = -1) then begin
|
||||||
MessageBox(Handle, 'Invalid directory. Please select your mod directory and try again.', PChar(Application.Title), MB_ICONWARNING);
|
MessageBox(Handle, 'Invalid directory. Please select your mod directory and try again.', PChar(Application.Title), MB_ICONWARNING);
|
||||||
eStr.Free;
|
eStr.Free;
|
||||||
exit;
|
exit;
|
||||||
end
|
end
|
||||||
else
|
else
|
||||||
eStr.Free;
|
eStr.Free;
|
||||||
|
// check for orangebox directory (!! OrangeBox Check !!)
|
||||||
|
if (optAutoDetect.Checked) then
|
||||||
|
Source := not ((AnsiSameText(trvDirectories.Selected.Text, 'tf')) or (Pos('orangebox', LowerCase(ePath)) <> 0))
|
||||||
|
else if (optSource.Checked) then
|
||||||
|
Source := True
|
||||||
|
else
|
||||||
|
Source := False;
|
||||||
// design stuff
|
// design stuff
|
||||||
trvDirectories.Enabled := False;
|
trvDirectories.Enabled := False;
|
||||||
cmdConnect.Enabled := False;
|
cmdConnect.Enabled := False;
|
||||||
@ -190,81 +207,131 @@ begin
|
|||||||
optLinux.Enabled := False;
|
optLinux.Enabled := False;
|
||||||
Screen.Cursor := crHourGlass;
|
Screen.Cursor := crHourGlass;
|
||||||
|
|
||||||
if optWindows.Checked then
|
if (optWindows.Checked) then begin
|
||||||
eOS := osWindows
|
eOS := osWindows;
|
||||||
else
|
if (Source) then
|
||||||
|
rtfDetails.Lines.Text := '* Installing Source binaries for Windows' + #13#10 + #13#10
|
||||||
|
else
|
||||||
|
rtfDetails.Lines.Text := '* Installing OrangeBox binaries for Windows' + #13#10 + #13#10
|
||||||
|
end
|
||||||
|
else begin
|
||||||
eOS := osLinux;
|
eOS := osLinux;
|
||||||
|
if (Source) then
|
||||||
|
rtfDetails.Lines.Text := '* Installing Source binaries for Linux' + #13#10 + #13#10
|
||||||
|
else
|
||||||
|
rtfDetails.Lines.Text := '* Installing OrangeBox binaries for Linux' + #13#10 + #13#10
|
||||||
|
end;
|
||||||
jspInstallProgress.Show;
|
jspInstallProgress.Show;
|
||||||
// installation
|
// installation
|
||||||
Screen.Cursor := crAppStart;
|
Screen.Cursor := crAppStart;
|
||||||
InstallFTP(eOS);
|
InstallFTP(eOS, Source, trvDirectories.Selected.Text);
|
||||||
end
|
end
|
||||||
else if jplWizard.ActivePage = jspInstallProgress then
|
else if (jplWizard.ActivePage = jspInstallProgress) then
|
||||||
Close
|
Close
|
||||||
else if jplWizard.ActivePage = jspSelectMod then begin
|
else if (jplWizard.ActivePage = jspSelectMod) then begin
|
||||||
{ Dedicated Server }
|
{ Dedicated Server }
|
||||||
if (frbDedicatedServer.Checked) or (frbStandaloneServer.Checked) then begin
|
if frbDedicatedServer.Checked then begin
|
||||||
|
Source := True;
|
||||||
|
ePath := trvMods.Selected.Text;
|
||||||
|
if (ePath = 'Counter-Strike:Source') then
|
||||||
|
ePath := trvMods.Selected.Parent.Text + '\source dedicated server\cstrike'
|
||||||
|
else if (ePath = 'Day of Defeat:Source') then
|
||||||
|
ePath := trvMods.Selected.Parent.Text + '\source dedicated server\dod'
|
||||||
|
else if (ePath = 'Half-Life 2 Deathmatch') then
|
||||||
|
ePath := trvMods.Selected.Parent.Text + '\source dedicated server\hl2mp'
|
||||||
|
else begin
|
||||||
|
{ get games }
|
||||||
|
if (ePath = 'Team Fortress 2') then
|
||||||
|
ePath := trvMods.Selected.Parent.Text + '\source 2007 dedicated server\tf';
|
||||||
|
{ ask user, just in case }
|
||||||
|
case MessageBox(Handle, 'It looks like your server is using the OrangeBox engine. Would you like to install the appropriate binaries for it?', PChar(Application.Title), MB_ICONQUESTION + MB_YESNOCANCEL) of
|
||||||
|
mrYes: Source := False;
|
||||||
|
mrNo: Source := True;
|
||||||
|
mrCancel: exit;
|
||||||
|
end;
|
||||||
|
end;
|
||||||
|
SteamPath := IncludeTrailingPathDelimiter(SteamPath) + 'steamapps\';
|
||||||
|
// install it
|
||||||
|
if (DirectoryExists(SteamPath + ePath)) then begin
|
||||||
|
jspInstallProgress.Show;
|
||||||
|
InstallDedicated(IncludeTrailingPathDelimiter(SteamPath + ePath), True, Source);
|
||||||
|
end
|
||||||
|
else begin
|
||||||
|
MessageBox(Handle, 'Error: The directory of the mod you selected doesn''t exist any more. Run Dedicated Server with the chosen mod and try again.', PChar(Application.Title), MB_ICONERROR);
|
||||||
|
jspSelectMod.Show;
|
||||||
|
exit;
|
||||||
|
end;
|
||||||
|
end;
|
||||||
|
{ Standalone Server }
|
||||||
|
if (frbStandaloneServer.Checked) then begin
|
||||||
|
Source := True;
|
||||||
ePath := trvMods.Selected.Text;
|
ePath := trvMods.Selected.Text;
|
||||||
if ePath = 'Counter-Strike:Source' then
|
if ePath = 'Counter-Strike:Source' then
|
||||||
ePath := 'cstrike'
|
ePath := 'cstrike'
|
||||||
else if ePath = 'Day of Defeat:Source' then
|
else if ePath = 'Day of Defeat:Source' then
|
||||||
ePath := 'dod'
|
ePath := 'dod'
|
||||||
else
|
else if ePath = 'Half-Life 2 Deathmatch' then
|
||||||
ePath := 'hl2mp';
|
ePath := 'hl2mp'
|
||||||
ePath := 'SteamApps\' + trvMods.Selected.Parent.Text + '\source dedicated server\' + ePath;
|
else begin
|
||||||
// install it
|
{ get games }
|
||||||
if frbDedicatedServer.Checked then begin
|
if (ePath = 'Team Fortress 2') then
|
||||||
if DirectoryExists(SteamPath + ePath) then begin
|
ePath := 'orangebox\tf';
|
||||||
jspInstallProgress.Show;
|
{ ask user, just in case }
|
||||||
InstallDedicated(IncludeTrailingPathDelimiter(SteamPath + ePath), True);
|
case MessageBox(Handle, 'It looks like your server is using the OrangeBox engine. Would you like to install the appropriate binaries for it?', PChar(Application.Title), MB_ICONQUESTION + MB_YESNOCANCEL) of
|
||||||
end
|
mrYes: Source := False;
|
||||||
else begin
|
mrNo: Source := True;
|
||||||
MessageBox(Handle, 'Error: The directory of the mod you selected doesn''t exist any more. Run Dedicated Server with the chosen mod and try again.', PChar(Application.Title), MB_ICONERROR);
|
mrCancel: exit;
|
||||||
jspSelectMod.Show;
|
|
||||||
exit;
|
|
||||||
end;
|
end;
|
||||||
|
end;
|
||||||
|
// install it
|
||||||
|
if (DirectoryExists(StandaloneServer + ePath)) then begin
|
||||||
|
jspInstallProgress.Show;
|
||||||
|
InstallDedicated(IncludeTrailingPathDelimiter(StandaloneServer + ePath), False, Source)
|
||||||
end
|
end
|
||||||
else begin
|
else begin
|
||||||
if DirectoryExists(StandaloneServer + ePath) then begin
|
MessageBox(Handle, 'Error: The directory of the mod you selected doesn''t exist (any more). Run Half-Life Dedicated Server with the chosen mod again and restart.', PChar(Application.Title), MB_ICONERROR);
|
||||||
jspInstallProgress.Show;
|
jspSelectMod.Show;
|
||||||
InstallDedicated(IncludeTrailingPathDelimiter(StandaloneServer + ePath), False)
|
exit;
|
||||||
end
|
|
||||||
else begin
|
|
||||||
MessageBox(Handle, 'Error: The directory of the mod you selected doesn''t exist (any more). Run Half-Life Dedicated Server with the chosen mod again and restart.', PChar(Application.Title), MB_ICONERROR);
|
|
||||||
jspSelectMod.Show;
|
|
||||||
exit;
|
|
||||||
end;
|
|
||||||
end;
|
end;
|
||||||
end;
|
end;
|
||||||
{ Listen Server }
|
{ Listen Server }
|
||||||
if frbListenServer.Checked then begin
|
if (frbListenServer.Checked) then begin
|
||||||
|
Source := True;
|
||||||
ePath := trvMods.Selected.Text;
|
ePath := trvMods.Selected.Text;
|
||||||
if ePath = 'Counter-Strike:Source' then
|
if (ePath = 'Counter-Strike:Source') then
|
||||||
ePath := SteamPath + 'SteamApps\' + trvMods.Selected.Parent.Text + '\counter-strike source\cstrike'
|
ePath := SteamPath + 'SteamApps\' + trvMods.Selected.Parent.Text + '\counter-strike source\cstrike'
|
||||||
else if ePath = 'Half-Life 2 Deathmatch' then
|
else if (ePath = 'Half-Life 2 Deathmatch') then
|
||||||
ePath := SteamPath + 'SteamApps\' + trvMods.Selected.Parent.Text + '\half-life 2 deathmatch\hl2mp'
|
ePath := SteamPath + 'SteamApps\' + trvMods.Selected.Parent.Text + '\half-life 2 deathmatch\hl2mp'
|
||||||
else
|
else if ePath = 'Day of Defeat:Source' then
|
||||||
ePath := SteamPath + 'SteamApps\' + trvMods.Selected.Parent.Text + '\day of defeat source\dod';
|
ePath := SteamPath + 'SteamApps\' + trvMods.Selected.Parent.Text + '\day of defeat source\dod'
|
||||||
|
else begin
|
||||||
|
{ get games }
|
||||||
|
if (ePath = 'Team Fortress 2') then
|
||||||
|
ePath := SteamPath + 'SteamApps\' + trvMods.Selected.Parent.Text + '\team fortress 2\tf';
|
||||||
|
{ ask user, just in case }
|
||||||
|
case MessageBox(Handle, 'It looks like your server is using the OrangeBox engine. Would you like to install the appropriate binaries for it?', PChar(Application.Title), MB_ICONQUESTION + MB_YESNOCANCEL) of
|
||||||
|
mrYes: Source := False;
|
||||||
|
mrNo: Source := True;
|
||||||
|
mrCancel: exit;
|
||||||
|
end;
|
||||||
|
end;
|
||||||
|
|
||||||
if Pos(SteamPath, ePath) = 0 then
|
if (Pos(SteamPath, ePath) = 0) then
|
||||||
MessageBox(Handle, 'An error occured. Please report this bug to the Metamod:Source team and post a new thread on the forums of www.amxmodx.org.', PChar(Application.Title), MB_ICONSTOP)
|
MessageBox(Handle, 'An error occured. Please report this bug to the Metamod:Source team and post a new thread on the forums of www.amxmodx.org.', PChar(Application.Title), MB_ICONSTOP)
|
||||||
else begin
|
else begin
|
||||||
if not FileExists(ePath + '\gameinfo.txt') then begin
|
if (not FileExists(ePath + '\gameinfo.txt')) then begin
|
||||||
MessageBox(Handle, 'You have to play this game once before installing Metamod:Source. Do that and try again.', PChar(Application.Title), MB_ICONWARNING);
|
MessageBox(Handle, 'You have to play this game once before installing Metamod:Source. Do that and try again.', PChar(Application.Title), MB_ICONWARNING);
|
||||||
exit;
|
exit;
|
||||||
end;
|
end;
|
||||||
|
|
||||||
jspInstallProgress.Show;
|
jspInstallProgress.Show;
|
||||||
InstallListen(IncludeTrailingPathDelimiter(ePath));
|
InstallListen(IncludeTrailingPathDelimiter(ePath), Source);
|
||||||
end;
|
end;
|
||||||
end;
|
end;
|
||||||
{ Custom mod below }
|
{ Custom mod below }
|
||||||
end
|
end
|
||||||
else if jplWizard.ActivePage <> jspInstallMethod then
|
else if (jplWizard.ActivePage = jspInstallMethod) then begin
|
||||||
jplWizard.NextPage
|
if (frbDedicatedServer.Checked) then begin // Dedicated Server
|
||||||
else begin
|
|
||||||
if frbDedicatedServer.Checked then begin // Dedicated Server
|
|
||||||
eRegistry := TRegistry.Create(KEY_READ);
|
eRegistry := TRegistry.Create(KEY_READ);
|
||||||
try
|
try
|
||||||
eRegistry.RootKey := HKEY_CURRENT_USER;
|
eRegistry.RootKey := HKEY_CURRENT_USER;
|
||||||
@ -274,19 +341,21 @@ begin
|
|||||||
SteamPath := ePath;
|
SteamPath := ePath;
|
||||||
|
|
||||||
ePath := ePath + 'SteamApps\';
|
ePath := ePath + 'SteamApps\';
|
||||||
if DirectoryExists(ePath) then begin
|
if (DirectoryExists(ePath)) then begin
|
||||||
trvMods.Items.Clear;
|
trvMods.Items.Clear;
|
||||||
// Check Mods
|
// Check Mods
|
||||||
eStr := GetAllFiles(ePath + '*.*', faDirectory, False, True, False);
|
eStr := GetAllFiles(ePath + '*.*', faDirectory, False, True, False);
|
||||||
for i := 0 to eStr.Count -1 do begin
|
for i := 0 to eStr.Count -1 do begin
|
||||||
CurNode := trvMods.Items.Add(nil, eStr[i]);
|
CurNode := trvMods.Items.Add(nil, eStr[i]);
|
||||||
|
|
||||||
if DirectoryExists(ePath + eStr[i] + '\source dedicated server\cstrike') then
|
if (DirectoryExists(ePath + eStr[i] + '\source dedicated server\cstrike')) then
|
||||||
trvMods.Items.AddChild(CurNode, 'Counter-Strike:Source');
|
trvMods.Items.AddChild(CurNode, 'Counter-Strike:Source');
|
||||||
if DirectoryExists(ePath + eStr[i] + '\source dedicated server\dod') then
|
if (DirectoryExists(ePath + eStr[i] + '\source dedicated server\dod')) then
|
||||||
trvMods.Items.AddChild(CurNode, 'Day of Defeat:Source');
|
trvMods.Items.AddChild(CurNode, 'Day of Defeat:Source');
|
||||||
if DirectoryExists(ePath + eStr[i] + '\source dedicated server\hl2mp') then
|
if (DirectoryExists(ePath + eStr[i] + '\source dedicated server\hl2mp')) then
|
||||||
trvMods.Items.AddChild(CurNode, 'Half-Life 2 Deatmatch');
|
trvMods.Items.AddChild(CurNode, 'Half-Life 2 Deatmatch');
|
||||||
|
if (DirectoryExists(ePath + eStr[i] + '\source 2007 dedicated server\tf')) then
|
||||||
|
trvMods.Items.AddChild(CurNode, 'Team Fortress 2');
|
||||||
|
|
||||||
if CurNode.Count = 0 then
|
if CurNode.Count = 0 then
|
||||||
CurNode.Free
|
CurNode.Free
|
||||||
@ -307,11 +376,11 @@ begin
|
|||||||
eRegistry.Free;
|
eRegistry.Free;
|
||||||
end;
|
end;
|
||||||
end
|
end
|
||||||
else if frbListenServer.Checked then begin // Listen Server
|
else if (frbListenServer.Checked) then begin // Listen Server
|
||||||
eRegistry := TRegistry.Create(KEY_READ);
|
eRegistry := TRegistry.Create(KEY_READ);
|
||||||
try
|
try
|
||||||
eRegistry.RootKey := HKEY_CURRENT_USER;
|
eRegistry.RootKey := HKEY_CURRENT_USER;
|
||||||
if eRegistry.OpenKey('Software\Valve\Steam', False) then begin
|
if (eRegistry.OpenKey('Software\Valve\Steam', False)) then begin
|
||||||
ePath := eRegistry.ReadString('SteamPath');
|
ePath := eRegistry.ReadString('SteamPath');
|
||||||
ePath := IncludeTrailingPathDelimiter(StringReplace(ePath, '/', '\', [rfReplaceAll]));
|
ePath := IncludeTrailingPathDelimiter(StringReplace(ePath, '/', '\', [rfReplaceAll]));
|
||||||
SteamPath := ePath;
|
SteamPath := ePath;
|
||||||
@ -330,6 +399,8 @@ begin
|
|||||||
trvMods.Items.AddChild(CurNode, 'Day of Defeat:Source');
|
trvMods.Items.AddChild(CurNode, 'Day of Defeat:Source');
|
||||||
if DirectoryExists(ePath + eStr[i] + '\half-life 2 deathmatch') then
|
if DirectoryExists(ePath + eStr[i] + '\half-life 2 deathmatch') then
|
||||||
trvMods.Items.AddChild(CurNode, 'Half-Life 2 Deatmatch');
|
trvMods.Items.AddChild(CurNode, 'Half-Life 2 Deatmatch');
|
||||||
|
if DirectoryExists(ePath + eStr[i] + '\team fortress 2') then
|
||||||
|
trvMods.Items.AddChild(CurNode, 'Team Fortress 2');
|
||||||
|
|
||||||
if CurNode.Count = 0 then
|
if CurNode.Count = 0 then
|
||||||
CurNode.Free
|
CurNode.Free
|
||||||
@ -350,7 +421,7 @@ begin
|
|||||||
eRegistry.Free;
|
eRegistry.Free;
|
||||||
end;
|
end;
|
||||||
end
|
end
|
||||||
else if frbStandaloneServer.Checked then begin // Standalone Server
|
else if (frbStandaloneServer.Checked) then begin // Standalone Server
|
||||||
eRegistry := TRegistry.Create;
|
eRegistry := TRegistry.Create;
|
||||||
try
|
try
|
||||||
eRegistry.RootKey := HKEY_CURRENT_USER;
|
eRegistry.RootKey := HKEY_CURRENT_USER;
|
||||||
@ -362,6 +433,8 @@ begin
|
|||||||
trvMods.Items.Add(nil, 'Day of Defeat:Source');
|
trvMods.Items.Add(nil, 'Day of Defeat:Source');
|
||||||
if DirectoryExists(StandaloneServer + 'hl2mp') then
|
if DirectoryExists(StandaloneServer + 'hl2mp') then
|
||||||
trvMods.Items.Add(nil, 'Half-Life 2 Deatmatch');
|
trvMods.Items.Add(nil, 'Half-Life 2 Deatmatch');
|
||||||
|
if DirectoryExists(StandaloneServer + 'orangebox\tf') then
|
||||||
|
trvMods.Items.Add(nil, 'Team Fortress 2');
|
||||||
jspSelectMod.Show;
|
jspSelectMod.Show;
|
||||||
cmdNext.Enabled := False;
|
cmdNext.Enabled := False;
|
||||||
end
|
end
|
||||||
@ -371,16 +444,22 @@ begin
|
|||||||
eRegistry.Free;
|
eRegistry.Free;
|
||||||
end;
|
end;
|
||||||
end
|
end
|
||||||
else if frbSelectMod.Checked then begin
|
else if (frbSelectMod.Checked) then begin
|
||||||
{ Custom mod }
|
{ Custom mod }
|
||||||
if frmSelectModPath.ShowModal = mrOk then begin
|
if frmSelectModPath.ShowModal = mrOk then begin
|
||||||
|
ePath := frmSelectModPath.trvDirectory.SelectedFolder.PathName;
|
||||||
|
{ install now }
|
||||||
jspInstallProgress.Show;
|
jspInstallProgress.Show;
|
||||||
InstallCustom(IncludeTrailingPathDelimiter(frmSelectModPath.trvDirectory.SelectedFolder.PathName), osWindows);
|
InstallCustom(IncludeTrailingPathDelimiter(ePath), osWindows, not frmSelectModPath.chkUsesOrangebox.Checked);
|
||||||
end;
|
end;
|
||||||
end
|
end
|
||||||
else if frbFTP.Checked then // FTP
|
else if (frbFTP.Checked) then begin // FTP
|
||||||
|
Height := FTPHeight;
|
||||||
jspFTP.Show;
|
jspFTP.Show;
|
||||||
end;
|
end;
|
||||||
|
end
|
||||||
|
else
|
||||||
|
jplWizard.NextPage
|
||||||
end;
|
end;
|
||||||
|
|
||||||
procedure TfrmMain.CheckNext(Sender: TObject);
|
procedure TfrmMain.CheckNext(Sender: TObject);
|
||||||
@ -390,8 +469,10 @@ end;
|
|||||||
|
|
||||||
procedure TfrmMain.cmdBackClick(Sender: TObject);
|
procedure TfrmMain.cmdBackClick(Sender: TObject);
|
||||||
begin
|
begin
|
||||||
if jplWizard.ActivePage = jspFTP then
|
if jplWizard.ActivePage = jspFTP then begin
|
||||||
jspInstallMethod.Show
|
Height := NormalHeight;
|
||||||
|
jspInstallMethod.Show;
|
||||||
|
end
|
||||||
else begin
|
else begin
|
||||||
jplWizard.PrevPage;
|
jplWizard.PrevPage;
|
||||||
cmdBack.Visible := jplWizard.ActivePageIndex <> 0;
|
cmdBack.Visible := jplWizard.ActivePageIndex <> 0;
|
||||||
@ -399,9 +480,9 @@ begin
|
|||||||
end;
|
end;
|
||||||
|
|
||||||
procedure TfrmMain.cmdConnectClick(Sender: TObject);
|
procedure TfrmMain.cmdConnectClick(Sender: TObject);
|
||||||
var i: integer;
|
var i, k: integer;
|
||||||
eStr: TStringList;
|
eStr: TStringList;
|
||||||
CurNode: TTreeNode;
|
CurNode, CurNode2: TTreeNode;
|
||||||
Path: String;
|
Path: String;
|
||||||
begin
|
begin
|
||||||
if (Trim(txtHost.Text) = '') or (Trim(txtUsername.Text) = '') then
|
if (Trim(txtHost.Text) = '') or (Trim(txtUsername.Text) = '') then
|
||||||
@ -432,7 +513,7 @@ begin
|
|||||||
eStr := TStringList.Create;
|
eStr := TStringList.Create;
|
||||||
eStr.Text := StringReplace(Path, '/', #13, [rfReplaceAll]);
|
eStr.Text := StringReplace(Path, '/', #13, [rfReplaceAll]);
|
||||||
for i := eStr.Count -1 downto 0 do begin
|
for i := eStr.Count -1 downto 0 do begin
|
||||||
if eStr[i] = '' then
|
if (eStr[i] = '') then
|
||||||
eStr.Delete(i);
|
eStr.Delete(i);
|
||||||
end;
|
end;
|
||||||
if (Copy(Path, Length(Path) -1, 1) <> '/') then
|
if (Copy(Path, Length(Path) -1, 1) <> '/') then
|
||||||
@ -441,47 +522,39 @@ begin
|
|||||||
trvDirectories.Enabled := True;
|
trvDirectories.Enabled := True;
|
||||||
cmdConnect.Enabled := True;
|
cmdConnect.Enabled := True;
|
||||||
cmdConnect.Caption := 'Disconnect';
|
cmdConnect.Caption := 'Disconnect';
|
||||||
// ... change to / and create all the directories ...
|
|
||||||
CurNode := nil;
|
|
||||||
if (Path <> '/') then begin
|
|
||||||
try
|
|
||||||
IdFTP.ChangeDir('/');
|
|
||||||
with GetAllDirs do begin
|
|
||||||
for i := 0 to Count -1 do begin
|
|
||||||
if (Assigned(CurNode)) then
|
|
||||||
trvDirectories.Items.AddChild(trvDirectories.Items.Add(nil, Strings[i]), 'Scanning...')
|
|
||||||
else begin
|
|
||||||
CurNode := trvDirectories.Items.Add(nil, Strings[i]);
|
|
||||||
trvDirectories.Items.AddChild(CurNode, 'Scanning...');
|
|
||||||
if (Pos('/' + CurNode.Text + '/', Path) = 0) then
|
|
||||||
CurNode := nil;
|
|
||||||
end
|
|
||||||
end;
|
|
||||||
Free;
|
|
||||||
end;
|
|
||||||
IdFTP.ChangeDir(Path);
|
|
||||||
except
|
|
||||||
if (IdFTP.Connected) then
|
|
||||||
IdFTP.ChangeDir(Path)
|
|
||||||
else
|
|
||||||
IdFTP.Connect;
|
|
||||||
end;
|
|
||||||
end;
|
|
||||||
// ... find directories in start path ...
|
// ... find directories in start path ...
|
||||||
if eStr.Count <> 0 then begin
|
CurNode := nil;
|
||||||
for i := 0 to eStr.Count -1 do begin
|
CurNode2 := nil;
|
||||||
if (not ((i = 0) and (Assigned(CurNode)))) then
|
if (eStr.Count <> 0) then begin
|
||||||
CurNode := trvDirectories.Items.AddChild(CurNode, eStr[i]);
|
IdFTP.ChangeDir('/');
|
||||||
|
for i := 0 to eStr.Count do begin
|
||||||
|
try
|
||||||
|
with GetAllDirs do begin
|
||||||
|
for k := 0 to Count -1 do begin
|
||||||
|
if (i = eStr.Count) or (Strings[k] <> eStr[i]) then
|
||||||
|
trvDirectories.Items.AddChild(trvDirectories.Items.AddChild(CurNode, Strings[k]), 'Scanning...')
|
||||||
|
else
|
||||||
|
CurNode2 := trvDirectories.Items.AddChild(CurNode, Strings[k]);
|
||||||
|
end;
|
||||||
|
Free;
|
||||||
|
|
||||||
|
CurNode := CurNode2;
|
||||||
|
trvDirectories.Selected := CurNode;
|
||||||
|
Repaint;
|
||||||
|
Application.ProcessMessages;
|
||||||
|
end;
|
||||||
|
|
||||||
|
if (i <> eStr.Count) then
|
||||||
|
IdFTP.ChangeDir(eStr[i]);
|
||||||
|
except
|
||||||
|
IdFTP.CheckForDisconnect(False);
|
||||||
|
if (not IdFTP.Connected) then
|
||||||
|
IdFTP.Disconnect;
|
||||||
|
CurNode := trvDirectories.Items.AddChild(CurNode, eStr.Strings[i])
|
||||||
|
end;
|
||||||
end;
|
end;
|
||||||
end;
|
end;
|
||||||
trvDirectories.Selected := CurNode;
|
|
||||||
eStr.Free;
|
eStr.Free;
|
||||||
// ... scan for directories ...
|
|
||||||
with GetAllDirs do begin
|
|
||||||
for i := 0 to Count -1 do
|
|
||||||
trvDirectories.Items.AddChild(trvDirectories.Items.AddChild(CurNode, Strings[i]), 'Scanning...');
|
|
||||||
Free;
|
|
||||||
end;
|
|
||||||
|
|
||||||
if Assigned(CurNode) then
|
if Assigned(CurNode) then
|
||||||
CurNode.Expand(False);
|
CurNode.Expand(False);
|
||||||
|
@ -1,7 +1,8 @@
|
|||||||
In this folder should be server.dll and server_i486.so.
|
Every MM:S library should be located in this directory.
|
||||||
|
|
||||||
How you prepare a release:
|
How to prepare a release:
|
||||||
1) Copy the latest MM:S dlls and hl2launch.exe into this folder
|
1) Copy the latest MM:S dlls into this folder
|
||||||
2) Run Attach.exe
|
2) Append .source to the Source binaries and .orangebox to the OrangeBox binaries
|
||||||
3) Test MMS_Installer.exe once (should work but nobody wants bug releases, especially not in the installer)
|
3) Run Attach.exe
|
||||||
4) If everything worked fine, release it, otherwise pm me (Basic-Master)
|
4) Test MMS_Installer.exe once (recommended)
|
||||||
|
5) Release it or e-Mail me if you find a bug
|
@ -1,7 +1,7 @@
|
|||||||
[PRODUCT]
|
[PRODUCT]
|
||||||
major = 1
|
major = 1
|
||||||
minor = 4
|
minor = 4
|
||||||
revision = 0
|
revision = 4
|
||||||
|
|
||||||
[sourcemm]
|
[sourcemm]
|
||||||
folder = sourcemm
|
folder = sourcemm
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
/* ======== SourceHook ========
|
/* ======== SourceHook ========
|
||||||
* Copyright (C) 2004-2007 Metamod:Source Development Team
|
* Copyright (C) 2004-2008 Metamod:Source Development Team
|
||||||
* No warranties of any kind
|
* No warranties of any kind
|
||||||
*
|
*
|
||||||
* License: zlib/libpng
|
* License: zlib/libpng
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
/* ======== SourceHook ========
|
/* ======== SourceHook ========
|
||||||
* Copyright (C) 2004-2007 Metamod:Source Development Team
|
* Copyright (C) 2004-2008 Metamod:Source Development Team
|
||||||
* No warranties of any kind
|
* No warranties of any kind
|
||||||
*
|
*
|
||||||
* License: zlib/libpng
|
* License: zlib/libpng
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
/* ======== SourceHook ========
|
/* ======== SourceHook ========
|
||||||
* Copyright (C) 2004-2007 Metamod:Source Development Team
|
* Copyright (C) 2004-2008 Metamod:Source Development Team
|
||||||
* No warranties of any kind
|
* No warranties of any kind
|
||||||
*
|
*
|
||||||
* License: zlib/libpng
|
* License: zlib/libpng
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
/* ======== SourceHook ========
|
/* ======== SourceHook ========
|
||||||
* Copyright (C) 2004-2007 Metamod:Source Development Team
|
* Copyright (C) 2004-2008 Metamod:Source Development Team
|
||||||
* No warranties of any kind
|
* No warranties of any kind
|
||||||
*
|
*
|
||||||
* License: zlib/libpng
|
* License: zlib/libpng
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
/* ======== SourceMM ========
|
/* ======== SourceMM ========
|
||||||
* Copyright (C) 2004-2007 Metamod:Source Development Team
|
* Copyright (C) 2004-2008 Metamod:Source Development Team
|
||||||
* No warranties of any kind
|
* No warranties of any kind
|
||||||
*
|
*
|
||||||
* License: zlib/libpng
|
* License: zlib/libpng
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
/* ======== SourceHook ========
|
/* ======== SourceHook ========
|
||||||
* Copyright (C) 2004-2007 Metamod:Source Development Team
|
* Copyright (C) 2004-2008 Metamod:Source Development Team
|
||||||
* No warranties of any kind
|
* No warranties of any kind
|
||||||
*
|
*
|
||||||
* License: zlib/libpng
|
* License: zlib/libpng
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
/* ======== SourceHook ========
|
/* ======== SourceHook ========
|
||||||
* Copyright (C) 2004-2007 Metamod:Source Development Team
|
* Copyright (C) 2004-2008 Metamod:Source Development Team
|
||||||
* No warranties of any kind
|
* No warranties of any kind
|
||||||
*
|
*
|
||||||
* License: zlib/libpng
|
* License: zlib/libpng
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
/* ======== SourceMM ========
|
/* ======== SourceMM ========
|
||||||
* Copyright (C) 2004-2007 Metamod:Source Development Team
|
* Copyright (C) 2004-2008 Metamod:Source Development Team
|
||||||
* No warranties of any kind
|
* No warranties of any kind
|
||||||
*
|
*
|
||||||
* License: zlib/libpng
|
* License: zlib/libpng
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
/* ======== SourceMM ========
|
/* ======== SourceMM ========
|
||||||
* Copyright (C) 2004-2007 Metamod:Source Development Team
|
* Copyright (C) 2004-2008 Metamod:Source Development Team
|
||||||
* No warranties of any kind
|
* No warranties of any kind
|
||||||
*
|
*
|
||||||
* License: zlib/libpng
|
* License: zlib/libpng
|
||||||
@ -153,6 +153,30 @@ public:
|
|||||||
return npos;
|
return npos;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
int find_last_of(const char c, int index = npos) const
|
||||||
|
{
|
||||||
|
int len = static_cast<int>(size());
|
||||||
|
if (len < 1)
|
||||||
|
return npos;
|
||||||
|
if (index >= len || index < npos)
|
||||||
|
return npos;
|
||||||
|
int i;
|
||||||
|
if (index == npos)
|
||||||
|
i = len - 1;
|
||||||
|
else
|
||||||
|
i = index;
|
||||||
|
|
||||||
|
for (; i>=0; i--)
|
||||||
|
{
|
||||||
|
if (v[i] == c)
|
||||||
|
{
|
||||||
|
return i;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return npos;
|
||||||
|
}
|
||||||
|
|
||||||
bool is_space(int c) const
|
bool is_space(int c) const
|
||||||
{
|
{
|
||||||
if (c == '\f' || c == '\n' ||
|
if (c == '\f' || c == '\n' ||
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
/* ======== SourceMM ========
|
/* ======== SourceMM ========
|
||||||
* Copyright (C) 2004-2007 Metamod:Source Development Team
|
* Copyright (C) 2004-2008 Metamod:Source Development Team
|
||||||
* No warranties of any kind
|
* No warranties of any kind
|
||||||
*
|
*
|
||||||
* License: zlib/libpng
|
* License: zlib/libpng
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
/* ======== SourceMM ========
|
/* ======== SourceMM ========
|
||||||
* Copyright (C) 2004-2007 Metamod:Source Development Team
|
* Copyright (C) 2004-2008 Metamod:Source Development Team
|
||||||
* No warranties of any kind
|
* No warranties of any kind
|
||||||
*
|
*
|
||||||
* License: zlib/libpng
|
* License: zlib/libpng
|
||||||
@ -19,39 +19,58 @@ namespace SourceHook
|
|||||||
// Vector
|
// Vector
|
||||||
template <class T> class CVector
|
template <class T> class CVector
|
||||||
{
|
{
|
||||||
bool Grow()
|
bool Grow(size_t amount)
|
||||||
{
|
{
|
||||||
// automatic grow
|
// automatic grow
|
||||||
size_t newSize = m_Size * 2;
|
size_t newSize = m_Size * 2;
|
||||||
|
|
||||||
if (newSize == 0)
|
if (newSize == 0)
|
||||||
newSize = 8; // a good init value
|
{
|
||||||
|
newSize = 8;
|
||||||
|
}
|
||||||
|
|
||||||
|
while (m_CurrentUsedSize + amount > newSize)
|
||||||
|
{
|
||||||
|
newSize *= 2;
|
||||||
|
}
|
||||||
|
|
||||||
T *newData = new T[newSize];
|
T *newData = new T[newSize];
|
||||||
if (!newData)
|
|
||||||
return false;
|
|
||||||
if (m_Data)
|
if (m_Data)
|
||||||
{
|
{
|
||||||
for (size_t i=0; i<m_CurrentUsedSize; i++)
|
for (size_t i=0; i<m_CurrentUsedSize; i++)
|
||||||
|
{
|
||||||
newData[i] = m_Data[i];
|
newData[i] = m_Data[i];
|
||||||
|
}
|
||||||
|
|
||||||
delete [] m_Data;
|
delete [] m_Data;
|
||||||
}
|
}
|
||||||
|
|
||||||
m_Data = newData;
|
m_Data = newData;
|
||||||
m_Size = newSize;
|
m_Size = newSize;
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool GrowIfNeeded()
|
bool GrowIfNeeded(size_t amount)
|
||||||
{
|
{
|
||||||
if (m_CurrentUsedSize >= m_Size)
|
if (m_CurrentUsedSize + amount >= m_Size)
|
||||||
return Grow();
|
{
|
||||||
|
return Grow(amount);
|
||||||
|
}
|
||||||
else
|
else
|
||||||
|
{
|
||||||
return true;
|
return true;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
bool ChangeSize(size_t size)
|
bool ChangeSize(size_t size)
|
||||||
{
|
{
|
||||||
// change size
|
// change size
|
||||||
if (size == m_Size)
|
if (size == m_Size)
|
||||||
|
{
|
||||||
return true;
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
if (!size)
|
if (!size)
|
||||||
{
|
{
|
||||||
@ -65,19 +84,24 @@ template <class T> class CVector
|
|||||||
}
|
}
|
||||||
|
|
||||||
T *newData = new T[size];
|
T *newData = new T[size];
|
||||||
if (!newData)
|
|
||||||
return false;
|
|
||||||
if (m_Data)
|
if (m_Data)
|
||||||
{
|
{
|
||||||
size_t end = (m_CurrentUsedSize < size) ? (m_CurrentUsedSize) : size;
|
size_t end = (m_CurrentUsedSize < size) ? (m_CurrentUsedSize) : size;
|
||||||
for (size_t i=0; i<end; i++)
|
for (size_t i=0; i<end; i++)
|
||||||
|
{
|
||||||
newData[i] = m_Data[i];
|
newData[i] = m_Data[i];
|
||||||
|
}
|
||||||
|
|
||||||
delete [] m_Data;
|
delete [] m_Data;
|
||||||
}
|
}
|
||||||
m_Data = newData;
|
m_Data = newData;
|
||||||
m_Size = size;
|
m_Size = size;
|
||||||
|
|
||||||
if (m_CurrentUsedSize > m_Size)
|
if (m_CurrentUsedSize > m_Size)
|
||||||
|
{
|
||||||
m_CurrentUsedSize = m_Size;
|
m_CurrentUsedSize = m_Size;
|
||||||
|
}
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
@ -85,7 +109,9 @@ template <class T> class CVector
|
|||||||
void FreeMemIfPossible()
|
void FreeMemIfPossible()
|
||||||
{
|
{
|
||||||
if (!m_Data)
|
if (!m_Data)
|
||||||
|
{
|
||||||
return;
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
if (!m_CurrentUsedSize)
|
if (!m_CurrentUsedSize)
|
||||||
{
|
{
|
||||||
@ -95,10 +121,14 @@ template <class T> class CVector
|
|||||||
|
|
||||||
size_t newSize = m_Size;
|
size_t newSize = m_Size;
|
||||||
while (m_CurrentUsedSize <= newSize / 2)
|
while (m_CurrentUsedSize <= newSize / 2)
|
||||||
|
{
|
||||||
newSize /= 2;
|
newSize /= 2;
|
||||||
|
}
|
||||||
|
|
||||||
if (newSize != m_Size)
|
if (newSize != m_Size)
|
||||||
|
{
|
||||||
ChangeSize(newSize);
|
ChangeSize(newSize);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
protected:
|
protected:
|
||||||
T *m_Data;
|
T *m_Data;
|
||||||
@ -321,14 +351,13 @@ public:
|
|||||||
|
|
||||||
bool push_back(const T & elem)
|
bool push_back(const T & elem)
|
||||||
{
|
{
|
||||||
++m_CurrentUsedSize;
|
if (!GrowIfNeeded(1))
|
||||||
if (!GrowIfNeeded())
|
|
||||||
{
|
{
|
||||||
--m_CurrentUsedSize;
|
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
m_Data[m_CurrentUsedSize - 1] = elem;
|
m_Data[m_CurrentUsedSize++] = elem;
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -433,13 +462,13 @@ public:
|
|||||||
|
|
||||||
size_t ofs = where - begin();
|
size_t ofs = where - begin();
|
||||||
|
|
||||||
++m_CurrentUsedSize;
|
if (!GrowIfNeeded(1))
|
||||||
if (!GrowIfNeeded())
|
|
||||||
{
|
{
|
||||||
--m_CurrentUsedSize;
|
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
++m_CurrentUsedSize;
|
||||||
|
|
||||||
where = begin() + ofs;
|
where = begin() + ofs;
|
||||||
|
|
||||||
// Move subsequent entries
|
// Move subsequent entries
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
/* ======== SourceHook ========
|
/* ======== SourceHook ========
|
||||||
* Copyright (C) 2004-2007 Metamod:Source Development Team
|
* Copyright (C) 2004-2008 Metamod:Source Development Team
|
||||||
* No warranties of any kind
|
* No warranties of any kind
|
||||||
*
|
*
|
||||||
* License: zlib/libpng
|
* License: zlib/libpng
|
||||||
@ -752,11 +752,6 @@ namespace SourceHook
|
|||||||
|
|
||||||
bool CSourceHookImpl::ShouldContinue()
|
bool CSourceHookImpl::ShouldContinue()
|
||||||
{
|
{
|
||||||
// If recall is true, we shall not continue either.
|
|
||||||
// This is because, if it's true and ShouldContinue is called, it suggests that the
|
|
||||||
// actual recall is done and that we are back in the original handler which shall return
|
|
||||||
// immediately.
|
|
||||||
|
|
||||||
// Post-recalls:
|
// Post-recalls:
|
||||||
// The second element on the stack has recall set to Recall_Post1.
|
// The second element on the stack has recall set to Recall_Post1.
|
||||||
// This means that we want to skip this part and the original function calling thing, so
|
// This means that we want to skip this part and the original function calling thing, so
|
||||||
@ -778,7 +773,21 @@ namespace SourceHook
|
|||||||
return m_HLIStack.front().shouldContinue;
|
return m_HLIStack.front().shouldContinue;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return m_HLIStack.front().shouldContinue && !m_HLIStack.front().recall;
|
|
||||||
|
// 16.01.2008: We used to return false for recalls here.
|
||||||
|
// This caused the hook funcs to think that the whole iface has been destroyed
|
||||||
|
// (the original purpose of shouldcontinue was to notify the hookfuncs that everything has been
|
||||||
|
// invalidated by RemoveHook) so they did not release their iterator. -> Leaks
|
||||||
|
// Now, GetIter sets the iterator to END so it still gets released but the hooks don't continue.
|
||||||
|
|
||||||
|
// But: we have to return false in the post phase of pre recalls (ie. a pre hook made a recall).
|
||||||
|
if (m_HLIStack.front().recall == HookLoopInfo::Recall_Pre &&
|
||||||
|
static_cast<CIface*>(m_HLIStack.front().pCurIface)->m_PreHooks.RelFlagGet())
|
||||||
|
{
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
return m_HLIStack.front().shouldContinue;
|
||||||
}
|
}
|
||||||
|
|
||||||
void CSourceHookImpl::DoRecall()
|
void CSourceHookImpl::DoRecall()
|
||||||
@ -994,6 +1003,9 @@ namespace SourceHook
|
|||||||
ret->Set(m_UsedIters); // m_UsedIters is the last returned and not released iterator
|
ret->Set(m_UsedIters); // m_UsedIters is the last returned and not released iterator
|
||||||
ret->Next(); // Use next instead of directly incrementing its m_Iter:
|
ret->Next(); // Use next instead of directly incrementing its m_Iter:
|
||||||
// skips paused plugins
|
// skips paused plugins
|
||||||
|
|
||||||
|
// Set the last iterator to END!
|
||||||
|
m_UsedIters->GoToEnd();
|
||||||
}
|
}
|
||||||
|
|
||||||
ret->m_pNext = m_UsedIters;
|
ret->m_pNext = m_UsedIters;
|
||||||
@ -1008,6 +1020,8 @@ namespace SourceHook
|
|||||||
}
|
}
|
||||||
void CSourceHookImpl::CHookList::ReleaseIter(IIter *pIter)
|
void CSourceHookImpl::CHookList::ReleaseIter(IIter *pIter)
|
||||||
{
|
{
|
||||||
|
m_RelFlag = true;
|
||||||
|
|
||||||
CIter *pIter2 = static_cast<CIter*>(pIter);
|
CIter *pIter2 = static_cast<CIter*>(pIter);
|
||||||
|
|
||||||
// Unlink from m_UsedIters
|
// Unlink from m_UsedIters
|
||||||
@ -1017,7 +1031,7 @@ namespace SourceHook
|
|||||||
if (pIter2->m_pPrev)
|
if (pIter2->m_pPrev)
|
||||||
pIter2->m_pPrev->m_pNext = pIter2->m_pNext;
|
pIter2->m_pPrev->m_pNext = pIter2->m_pNext;
|
||||||
if (pIter2 == m_UsedIters)
|
if (pIter2 == m_UsedIters)
|
||||||
m_UsedIters = NULL;
|
m_UsedIters = m_UsedIters->m_pNext;
|
||||||
|
|
||||||
// Link to m_FreeIters
|
// Link to m_FreeIters
|
||||||
|
|
||||||
@ -1048,6 +1062,11 @@ namespace SourceHook
|
|||||||
SkipPaused();
|
SkipPaused();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void CSourceHookImpl::CHookList::CIter::GoToEnd()
|
||||||
|
{
|
||||||
|
m_Iter = m_pList->m_List.end();
|
||||||
|
}
|
||||||
|
|
||||||
bool CSourceHookImpl::CHookList::CIter::End()
|
bool CSourceHookImpl::CHookList::CIter::End()
|
||||||
{
|
{
|
||||||
if (!m_pList)
|
if (!m_pList)
|
||||||
@ -1056,7 +1075,7 @@ namespace SourceHook
|
|||||||
}
|
}
|
||||||
void CSourceHookImpl::CHookList::CIter::Next()
|
void CSourceHookImpl::CHookList::CIter::Next()
|
||||||
{
|
{
|
||||||
if (!m_pList)
|
if (!m_pList || m_Iter == m_pList->m_List.end())
|
||||||
return;
|
return;
|
||||||
++m_Iter;
|
++m_Iter;
|
||||||
SkipPaused();
|
SkipPaused();
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
/* ======== SourceHook ========
|
/* ======== SourceHook ========
|
||||||
* Copyright (C) 2004-2007 Metamod:Source Development Team
|
* Copyright (C) 2004-2008 Metamod:Source Development Team
|
||||||
* No warranties of any kind
|
* No warranties of any kind
|
||||||
*
|
*
|
||||||
* License: zlib/libpng
|
* License: zlib/libpng
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
/* ======== SourceHook ========
|
/* ======== SourceHook ========
|
||||||
* Copyright (C) 2004-2007 Metamod:Source Development Team
|
* Copyright (C) 2004-2008 Metamod:Source Development Team
|
||||||
* No warranties of any kind
|
* No warranties of any kind
|
||||||
*
|
*
|
||||||
* License: zlib/libpng
|
* License: zlib/libpng
|
||||||
@ -257,6 +257,7 @@ namespace SourceHook
|
|||||||
virtual ~CIter();
|
virtual ~CIter();
|
||||||
|
|
||||||
void GoToBegin();
|
void GoToBegin();
|
||||||
|
void GoToEnd();
|
||||||
void Set(CIter *pOther);
|
void Set(CIter *pOther);
|
||||||
|
|
||||||
bool End();
|
bool End();
|
||||||
@ -276,6 +277,7 @@ namespace SourceHook
|
|||||||
// For recalls
|
// For recalls
|
||||||
bool m_Recall;
|
bool m_Recall;
|
||||||
bool m_RQFlag;
|
bool m_RQFlag;
|
||||||
|
bool m_RelFlag;
|
||||||
|
|
||||||
void SetRecallState(); // Sets the list into a state where the next returned
|
void SetRecallState(); // Sets the list into a state where the next returned
|
||||||
// iterator (from GetIter) will be a copy of the last
|
// iterator (from GetIter) will be a copy of the last
|
||||||
@ -283,8 +285,9 @@ namespace SourceHook
|
|||||||
// The hook resets this state automatically on:
|
// The hook resets this state automatically on:
|
||||||
// GetIter, ReleaseIter
|
// GetIter, ReleaseIter
|
||||||
|
|
||||||
void RQFlagReset() { m_RQFlag = false; }
|
void RQFlagReset() { m_RQFlag = false; m_RelFlag = false; }
|
||||||
bool RQFlagGet() { return m_RQFlag; }
|
bool RQFlagGet() { return m_RQFlag; }
|
||||||
|
bool RelFlagGet() { return m_RelFlag; }
|
||||||
CHookList();
|
CHookList();
|
||||||
CHookList(const CHookList &other);
|
CHookList(const CHookList &other);
|
||||||
virtual ~CHookList();
|
virtual ~CHookList();
|
||||||
|
@ -1,4 +1,4 @@
|
|||||||
#(C)2004-2007 SourceMM Development Team
|
#(C)2004-2008 SourceMM Development Team
|
||||||
# Makefile written by David "BAILOPAN" Anderson and Pavol Marko
|
# Makefile written by David "BAILOPAN" Anderson and Pavol Marko
|
||||||
|
|
||||||
OPT_FLAGS = -O3 -funroll-loops -s -pipe
|
OPT_FLAGS = -O3 -funroll-loops -s -pipe
|
||||||
|
@ -289,6 +289,9 @@
|
|||||||
<File
|
<File
|
||||||
RelativePath="..\testref.cpp">
|
RelativePath="..\testref.cpp">
|
||||||
</File>
|
</File>
|
||||||
|
<File
|
||||||
|
RelativePath="..\testrefret.cpp">
|
||||||
|
</File>
|
||||||
</Filter>
|
</Filter>
|
||||||
<Filter
|
<Filter
|
||||||
Name="Header Files"
|
Name="Header Files"
|
||||||
|
@ -109,6 +109,10 @@ bool TestBail(std::string &error)
|
|||||||
new State_EatYams_Return(6),
|
new State_EatYams_Return(6),
|
||||||
NULL), "Part 6");
|
NULL), "Part 6");
|
||||||
|
|
||||||
|
SH_REMOVE_HOOK_STATICFUNC(IGaben, EatYams, g_Gabgab, EatYams_Handler1, false);
|
||||||
|
|
||||||
|
UntestBail2();
|
||||||
|
|
||||||
delete g_Gabgab;
|
delete g_Gabgab;
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
|
@ -28,6 +28,7 @@ namespace N_TestBail
|
|||||||
extern IGaben *g_Gabgab;
|
extern IGaben *g_Gabgab;
|
||||||
|
|
||||||
bool TestBail2(std::string &error);
|
bool TestBail2(std::string &error);
|
||||||
|
void UntestBail2();
|
||||||
}
|
}
|
||||||
|
|
||||||
using namespace N_TestBail;
|
using namespace N_TestBail;
|
||||||
|
@ -5,6 +5,7 @@
|
|||||||
#include "sourcehook_test.h"
|
#include "sourcehook_test.h"
|
||||||
#include "testbail.h"
|
#include "testbail.h"
|
||||||
|
|
||||||
|
static unsigned int n_calls = 0;
|
||||||
|
|
||||||
int EatYams_Handler2(int a)
|
int EatYams_Handler2(int a)
|
||||||
{
|
{
|
||||||
@ -31,6 +32,18 @@ namespace N_TestBail
|
|||||||
|
|
||||||
CHECK_COND(ret == 6, "Part 2.1");
|
CHECK_COND(ret == 6, "Part 2.1");
|
||||||
|
|
||||||
|
n_calls++;
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void UntestBail2()
|
||||||
|
{
|
||||||
|
while (n_calls)
|
||||||
|
{
|
||||||
|
SH_REMOVE_HOOK_STATICFUNC(IGaben, EatYams, g_Gabgab, EatYams_Handler3, false);
|
||||||
|
SH_REMOVE_HOOK_STATICFUNC(IGaben, EatYams, g_Gabgab, EatYams_Handler2, false);
|
||||||
|
n_calls--;
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
/* ======== SourceHook ========
|
/* ======== SourceHook ========
|
||||||
* Copyright (C) 2004-2007 Metamod:Source Development Team
|
* Copyright (C) 2004-2008 Metamod:Source Development Team
|
||||||
* No warranties of any kind
|
* No warranties of any kind
|
||||||
*
|
*
|
||||||
* License: zlib/libpng
|
* License: zlib/libpng
|
||||||
|
@ -94,9 +94,9 @@ bool TestMulti(std::string &error)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
for (unsigned int i=1; i<10; i++)
|
for (unsigned int i=0; i<10; i++)
|
||||||
{
|
{
|
||||||
SH_REMOVE_HOOK_STATICFUNC(VMultiTest, HookTarget, pv[1], HookFunction, false);
|
SH_REMOVE_HOOK_STATICFUNC(VMultiTest, HookTarget, pv[i], HookFunction, false);
|
||||||
delete pv[i];
|
delete pv[i];
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -104,3 +104,4 @@ bool TestMulti(std::string &error)
|
|||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -222,5 +222,11 @@ bool TestRecall(std::string &error)
|
|||||||
|
|
||||||
CHECK_COND(a == 0xDEADFC, "Part 5.1");
|
CHECK_COND(a == 0xDEADFC, "Part 5.1");
|
||||||
|
|
||||||
|
SH_REMOVE_HOOK_STATICFUNC(Test, Func2, ptr, HandlerPost_Func2, true);
|
||||||
|
SH_REMOVE_HOOK_STATICFUNC(Test, Func2, ptr, Handler2_Func2, false);
|
||||||
|
SH_REMOVE_HOOK_STATICFUNC(Test, Func2, ptr, Handler1_Func22, false);
|
||||||
|
SH_REMOVE_HOOK_STATICFUNC(Test, Func2, ptr, HandlerPost1_Func22, true);
|
||||||
|
SH_REMOVE_HOOK_STATICFUNC(Test, Func2, ptr, HandlerPost2_Func22, true);
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
@ -159,5 +159,7 @@ bool TestRef(std::string &error)
|
|||||||
new State_Result(12),
|
new State_Result(12),
|
||||||
NULL), "Part 4");
|
NULL), "Part 4");
|
||||||
|
|
||||||
|
SH_REMOVE_HOOK_MEMFUNC(CHello, Func, &hello, &hook, &CHook::Func, false);
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
@ -196,5 +196,13 @@ bool TestRefRet(std::string &error)
|
|||||||
new State_Func2_Ret(&hook.m_Var), // really returned hook.m_Var
|
new State_Func2_Ret(&hook.m_Var), // really returned hook.m_Var
|
||||||
NULL), "Part 7");
|
NULL), "Part 7");
|
||||||
|
|
||||||
|
SH_REMOVE_HOOK_MEMFUNC(Test, Func2, &test, &hook, &CHook::Func2_Post1, true);
|
||||||
|
SH_REMOVE_HOOK_MEMFUNC(Test, Func2, &test, &hook, &CHook::Func2_Pre1, false);
|
||||||
|
SH_REMOVE_HOOK_MEMFUNC(Test, Func1, &test, &hook, &CHook::Func1_Pre1, false);
|
||||||
|
SH_REMOVE_HOOK_MEMFUNC(Test, Func1, &test, &hook, &CHook::Func1_Post1, true);
|
||||||
|
SH_REMOVE_HOOK_MEMFUNC(Test, Func1, &test, &hook, &CHook::Func1_Pre2, false);
|
||||||
|
SH_REMOVE_HOOK_MEMFUNC(Test, Func1, &test, &hook, &CHook::Func1_Post2, true);
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
/* ======== SourceMM ========
|
/* ======== SourceMM ========
|
||||||
* Copyright (C) 2004-2007 Metamod:Source Development Team
|
* Copyright (C) 2004-2008 Metamod:Source Development Team
|
||||||
* No warranties of any kind
|
* No warranties of any kind
|
||||||
*
|
*
|
||||||
* License: zlib/libpng
|
* License: zlib/libpng
|
||||||
@ -12,6 +12,7 @@
|
|||||||
#include "CSmmAPI.h"
|
#include "CSmmAPI.h"
|
||||||
#include "sourcemm.h"
|
#include "sourcemm.h"
|
||||||
#include "concommands.h"
|
#include "concommands.h"
|
||||||
|
#include "vsp_listener.h"
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief Implements functions from CPlugin.h
|
* @brief Implements functions from CPlugin.h
|
||||||
@ -22,14 +23,14 @@ using namespace SourceMM;
|
|||||||
|
|
||||||
#define ITER_PLEVENT(evn, plid) \
|
#define ITER_PLEVENT(evn, plid) \
|
||||||
CPluginManager::CPlugin *_Xpl; \
|
CPluginManager::CPlugin *_Xpl; \
|
||||||
SourceHook::List<IMetamodListener *>::iterator event; \
|
SourceHook::List<CPluginEventHandler>::iterator event; \
|
||||||
IMetamodListener *api; \
|
IMetamodListener *api; \
|
||||||
for (PluginIter iter = g_PluginMngr._begin(); iter != g_PluginMngr._end(); iter++) { \
|
for (PluginIter iter = g_PluginMngr._begin(); iter != g_PluginMngr._end(); iter++) { \
|
||||||
_Xpl = (*iter); \
|
_Xpl = (*iter); \
|
||||||
if (_Xpl->m_Id == plid) \
|
if (_Xpl->m_Id == plid) \
|
||||||
continue; \
|
continue; \
|
||||||
for (event=_Xpl->m_Events.begin(); event!=_Xpl->m_Events.end(); event++) { \
|
for (event=_Xpl->m_Events.begin(); event!=_Xpl->m_Events.end(); event++) { \
|
||||||
api = (*event); \
|
api = (*event).event; \
|
||||||
api->evn(plid); \
|
api->evn(plid); \
|
||||||
} \
|
} \
|
||||||
}
|
}
|
||||||
@ -182,6 +183,38 @@ void CPluginManager::SetAllLoaded()
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void CPluginManager::SetVSPAsLoaded()
|
||||||
|
{
|
||||||
|
PluginIter i;
|
||||||
|
CPlugin *pPlugin;
|
||||||
|
SourceHook::List<CPluginEventHandler>::iterator event;
|
||||||
|
|
||||||
|
for (i = m_Plugins.begin(); i != m_Plugins.end(); i++)
|
||||||
|
{
|
||||||
|
pPlugin = (*i);
|
||||||
|
if (pPlugin->m_Status < Pl_Paused)
|
||||||
|
{
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
/* Only valid for plugins >= 10 (v1:5, SourceMM 1.4) */
|
||||||
|
if (pPlugin->m_API->GetApiVersion() < 10)
|
||||||
|
{
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
for (event = pPlugin->m_Events.begin();
|
||||||
|
event != pPlugin->m_Events.end();
|
||||||
|
event++)
|
||||||
|
{
|
||||||
|
if ((*event).got_vsp)
|
||||||
|
{
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
(*event).got_vsp = true;
|
||||||
|
(*event).event->OnVSPListening(&g_VspListener);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
bool CPluginManager::Pause(PluginId id, char *error, size_t maxlen)
|
bool CPluginManager::Pause(PluginId id, char *error, size_t maxlen)
|
||||||
{
|
{
|
||||||
CPlugin *pl = FindById(id);
|
CPlugin *pl = FindById(id);
|
||||||
@ -335,7 +368,7 @@ CPluginManager::CPlugin *CPluginManager::_Load(const char *file, PluginId source
|
|||||||
if (!pl->m_Lib)
|
if (!pl->m_Lib)
|
||||||
{
|
{
|
||||||
if (error)
|
if (error)
|
||||||
UTIL_Format(error, maxlen, "%s", dlerror());
|
UTIL_Format(error, maxlen, "[%d]", GetLastError());
|
||||||
pl->m_Status = Pl_Error;
|
pl->m_Status = Pl_Error;
|
||||||
} else {
|
} else {
|
||||||
CreateInterfaceFn pfn = (CreateInterfaceFn)(dlsym(pl->m_Lib, PL_EXPOSURE_C));
|
CreateInterfaceFn pfn = (CreateInterfaceFn)(dlsym(pl->m_Lib, PL_EXPOSURE_C));
|
||||||
@ -373,6 +406,22 @@ CPluginManager::CPlugin *CPluginManager::_Load(const char *file, PluginId source
|
|||||||
//if (pl->m_API->GetApiVersion() >= 4)
|
//if (pl->m_API->GetApiVersion() >= 4)
|
||||||
pl->m_API->AllPluginsLoaded();
|
pl->m_API->AllPluginsLoaded();
|
||||||
}
|
}
|
||||||
|
if (g_VspListener.IsRootLoadMethod()
|
||||||
|
|| (g_VspListener.IsLoaded() && g_SmmAPI.VSPEnabled()))
|
||||||
|
{
|
||||||
|
SourceHook::List<CPluginEventHandler>::iterator event;
|
||||||
|
for (event = pl->m_Events.begin();
|
||||||
|
event != pl->m_Events.end();
|
||||||
|
event++)
|
||||||
|
{
|
||||||
|
if (pl->m_API->GetApiVersion() < 10 || (*event).got_vsp)
|
||||||
|
{
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
(*event).got_vsp = true;
|
||||||
|
(*event).event->OnVSPListening(&g_VspListener);
|
||||||
|
}
|
||||||
|
}
|
||||||
} else {
|
} else {
|
||||||
pl->m_Status = Pl_Refused;
|
pl->m_Status = Pl_Refused;
|
||||||
}
|
}
|
||||||
@ -496,23 +545,17 @@ bool CPluginManager::UnloadAll()
|
|||||||
{
|
{
|
||||||
PluginIter i;
|
PluginIter i;
|
||||||
|
|
||||||
SourceHook::List<SourceMM::CPluginManager::CPlugin *> remqueue;
|
|
||||||
|
|
||||||
for (i=m_Plugins.begin(); i!=m_Plugins.end(); i++)
|
|
||||||
remqueue.push_back( (*i) );
|
|
||||||
|
|
||||||
char error[128];
|
char error[128];
|
||||||
bool status = true;
|
bool status = true;
|
||||||
|
|
||||||
for (i=remqueue.begin(); i!=remqueue.end(); i++)
|
while ((i = m_Plugins.begin()) != m_Plugins.end())
|
||||||
{
|
{
|
||||||
if ( !_Unload( (*i), true, error, sizeof(error)) )
|
if ( !_Unload( (*i), true, error, sizeof(error)) )
|
||||||
|
{
|
||||||
status = false;
|
status = false;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
m_Plugins.clear();
|
|
||||||
remqueue.clear();
|
|
||||||
|
|
||||||
return status;
|
return status;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -622,3 +665,34 @@ void CPluginManager::UnregAllConCmds(CPlugin *pl)
|
|||||||
|
|
||||||
pl->m_Cmds.clear();
|
pl->m_Cmds.clear();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const char *CPluginManager::GetStatusText(CPlugin *pl)
|
||||||
|
{
|
||||||
|
switch (pl->m_Status)
|
||||||
|
{
|
||||||
|
case Pl_NotFound:
|
||||||
|
return "NOFILE";
|
||||||
|
case Pl_Error:
|
||||||
|
return "ERROR";
|
||||||
|
case Pl_Refused:
|
||||||
|
return "FAILED";
|
||||||
|
case Pl_Paused:
|
||||||
|
return "PAUSED";
|
||||||
|
case Pl_Running:
|
||||||
|
{
|
||||||
|
if (pl->m_API && pl->m_API->QueryRunning(NULL, 0))
|
||||||
|
{
|
||||||
|
return "STOPPED";
|
||||||
|
} else {
|
||||||
|
return "RUNNING";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
default:
|
||||||
|
return "-";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
unsigned int CPluginManager::GetPluginCount()
|
||||||
|
{
|
||||||
|
return (unsigned int)m_Plugins.size();
|
||||||
|
}
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
/* ======== SourceMM ========
|
/* ======== SourceMM ========
|
||||||
* Copyright (C) 2004-2007 Metamod:Source Development Team
|
* Copyright (C) 2004-2008 Metamod:Source Development Team
|
||||||
* No warranties of any kind
|
* No warranties of any kind
|
||||||
*
|
*
|
||||||
* License: zlib/libpng
|
* License: zlib/libpng
|
||||||
@ -50,6 +50,13 @@ namespace SourceMM
|
|||||||
SourceHook::String alias;
|
SourceHook::String alias;
|
||||||
SourceHook::String value;
|
SourceHook::String value;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
struct CPluginEventHandler
|
||||||
|
{
|
||||||
|
bool got_vsp;
|
||||||
|
IMetamodListener *event;
|
||||||
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief Implements Plugin Manager API
|
* @brief Implements Plugin Manager API
|
||||||
*/
|
*/
|
||||||
@ -72,7 +79,7 @@ namespace SourceMM
|
|||||||
HINSTANCE m_Lib;
|
HINSTANCE m_Lib;
|
||||||
SourceHook::List<ConCommandBase *> m_Cvars;
|
SourceHook::List<ConCommandBase *> m_Cvars;
|
||||||
SourceHook::List<ConCommandBase *> m_Cmds;
|
SourceHook::List<ConCommandBase *> m_Cmds;
|
||||||
SourceHook::List<IMetamodListener *> m_Events;
|
SourceHook::List<CPluginEventHandler> m_Events;
|
||||||
};
|
};
|
||||||
public:
|
public:
|
||||||
CPluginManager();
|
CPluginManager();
|
||||||
@ -123,6 +130,10 @@ namespace SourceMM
|
|||||||
//Internal iterators
|
//Internal iterators
|
||||||
SourceHook::List<SourceMM::CPluginManager::CPlugin *>::iterator _begin();
|
SourceHook::List<SourceMM::CPluginManager::CPlugin *>::iterator _begin();
|
||||||
SourceHook::List<SourceMM::CPluginManager::CPlugin *>::iterator _end();
|
SourceHook::List<SourceMM::CPluginManager::CPlugin *>::iterator _end();
|
||||||
|
|
||||||
|
void SetVSPAsLoaded();
|
||||||
|
unsigned int GetPluginCount();
|
||||||
|
const char *GetStatusText(CPlugin *pl);
|
||||||
private:
|
private:
|
||||||
//These are identical internal functions for the wrappers above.
|
//These are identical internal functions for the wrappers above.
|
||||||
CPlugin *_Load(const char *file, PluginId source, char *error, size_t maxlen);
|
CPlugin *_Load(const char *file, PluginId source, char *error, size_t maxlen);
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
/* ======== SourceMM ========
|
/* ======== SourceMM ========
|
||||||
* Copyright (C) 2004-2007 Metamod:Source Development Team
|
* Copyright (C) 2004-2008 Metamod:Source Development Team
|
||||||
* No warranties of any kind
|
* No warranties of any kind
|
||||||
*
|
*
|
||||||
* License: zlib/libpng
|
* License: zlib/libpng
|
||||||
@ -141,8 +141,12 @@ void CSmmAPI::ConPrintf(const char *fmt, ...)
|
|||||||
void CSmmAPI::AddListener(ISmmPlugin *plugin, IMetamodListener *pListener)
|
void CSmmAPI::AddListener(ISmmPlugin *plugin, IMetamodListener *pListener)
|
||||||
{
|
{
|
||||||
CPluginManager::CPlugin *pl = g_PluginMngr.FindByAPI(plugin);
|
CPluginManager::CPlugin *pl = g_PluginMngr.FindByAPI(plugin);
|
||||||
|
CPluginEventHandler cpeh;
|
||||||
|
|
||||||
pl->m_Events.push_back(pListener);
|
cpeh.event = pListener;
|
||||||
|
cpeh.got_vsp = false;
|
||||||
|
|
||||||
|
pl->m_Events.push_back(cpeh);
|
||||||
}
|
}
|
||||||
|
|
||||||
void *CSmmAPI::MetaFactory(const char *iface, int *_ret, PluginId *id)
|
void *CSmmAPI::MetaFactory(const char *iface, int *_ret, PluginId *id)
|
||||||
@ -174,7 +178,7 @@ void *CSmmAPI::MetaFactory(const char *iface, int *_ret, PluginId *id)
|
|||||||
}
|
}
|
||||||
|
|
||||||
CPluginManager::CPlugin *pl;
|
CPluginManager::CPlugin *pl;
|
||||||
SourceHook::List<IMetamodListener *>::iterator event;
|
SourceHook::List<CPluginEventHandler>::iterator event;
|
||||||
IMetamodListener *api;
|
IMetamodListener *api;
|
||||||
int ret = 0;
|
int ret = 0;
|
||||||
void *val = NULL;
|
void *val = NULL;
|
||||||
@ -184,7 +188,7 @@ void *CSmmAPI::MetaFactory(const char *iface, int *_ret, PluginId *id)
|
|||||||
pl = (*iter);
|
pl = (*iter);
|
||||||
for (event=pl->m_Events.begin(); event!=pl->m_Events.end(); event++)
|
for (event=pl->m_Events.begin(); event!=pl->m_Events.end(); event++)
|
||||||
{
|
{
|
||||||
api = (*event);
|
api = (*event).event;
|
||||||
ret = IFACE_FAILED;
|
ret = IFACE_FAILED;
|
||||||
if ( (val=api->OnMetamodQuery(iface, &ret)) != NULL )
|
if ( (val=api->OnMetamodQuery(iface, &ret)) != NULL )
|
||||||
{
|
{
|
||||||
@ -221,22 +225,6 @@ void *CSmmAPI::MetaFactory(const char *iface, int *_ret, PluginId *id)
|
|||||||
#define ENGINEW32_OFFS 38
|
#define ENGINEW32_OFFS 38
|
||||||
#define IA32_CALL 0xE8
|
#define IA32_CALL 0xE8
|
||||||
|
|
||||||
bool vcmp(const void *_addr1, const void *_addr2, size_t len)
|
|
||||||
{
|
|
||||||
unsigned char *addr1 = (unsigned char *)_addr1;
|
|
||||||
unsigned char *addr2 = (unsigned char *)_addr2;
|
|
||||||
|
|
||||||
for (size_t i=0; i<len; i++)
|
|
||||||
{
|
|
||||||
if (addr2[i] == '*')
|
|
||||||
continue;
|
|
||||||
if (addr1[i] != addr2[i])
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
//Thanks to fysh for the idea of extracting info from "echo" and for
|
//Thanks to fysh for the idea of extracting info from "echo" and for
|
||||||
// having the original offsets at hand!
|
// having the original offsets at hand!
|
||||||
bool CSmmAPI::CacheCmds()
|
bool CSmmAPI::CacheCmds()
|
||||||
@ -256,20 +244,20 @@ bool CSmmAPI::CacheCmds()
|
|||||||
callback = ((ConCommand *)pBase)->GetCallback();
|
callback = ((ConCommand *)pBase)->GetCallback();
|
||||||
ptr = (unsigned char *)callback;
|
ptr = (unsigned char *)callback;
|
||||||
#ifdef OS_LINUX
|
#ifdef OS_LINUX
|
||||||
if (vcmp(ptr, ENGINE486_SIG, SIGLEN))
|
if (UTIL_VerifySignature(ptr, ENGINE486_SIG, SIGLEN))
|
||||||
{
|
{
|
||||||
offs = ENGINE486_OFFS;
|
offs = ENGINE486_OFFS;
|
||||||
}
|
}
|
||||||
else if (vcmp(ptr, ENGINE686_SIG, SIGLEN))
|
else if (UTIL_VerifySignature(ptr, ENGINE686_SIG, SIGLEN))
|
||||||
{
|
{
|
||||||
offs = ENGINE686_OFFS;
|
offs = ENGINE686_OFFS;
|
||||||
}
|
}
|
||||||
else if (vcmp(ptr, ENGINEAMD_SIG, SIGLEN))
|
else if (UTIL_VerifySignature(ptr, ENGINEAMD_SIG, SIGLEN))
|
||||||
{
|
{
|
||||||
offs = ENGINEAMD_OFFS;
|
offs = ENGINEAMD_OFFS;
|
||||||
}
|
}
|
||||||
#elif defined OS_WIN32 // Only one Windows engine binary so far...
|
#elif defined OS_WIN32 // Only one Windows engine binary so far...
|
||||||
if (vcmp(ptr, ENGINEW32_SIG, SIGLEN))
|
if (UTIL_VerifySignature(ptr, ENGINEW32_SIG, SIGLEN))
|
||||||
{
|
{
|
||||||
offs = ENGINEW32_OFFS;
|
offs = ENGINEW32_OFFS;
|
||||||
}
|
}
|
||||||
@ -454,16 +442,40 @@ void CSmmAPI::ClientConPrintf(edict_t *client, const char *fmt, ...)
|
|||||||
|
|
||||||
void CSmmAPI::LoadAsVSP()
|
void CSmmAPI::LoadAsVSP()
|
||||||
{
|
{
|
||||||
char command[350];
|
size_t len;
|
||||||
|
char engine_file[PATH_SIZE];
|
||||||
|
char rel_path[PATH_SIZE * 2];
|
||||||
|
|
||||||
|
GetFileOfAddress(g_Engine.engine, engine_file, sizeof(engine_file));
|
||||||
|
|
||||||
|
/* Chop off the "engine" file part */
|
||||||
|
len = strlen(engine_file);
|
||||||
|
for (size_t i = len - 1; i >= 0 && i < len; i--)
|
||||||
|
{
|
||||||
|
if (engine_file[i] == '/'
|
||||||
|
|| engine_file[i] == '\\')
|
||||||
|
{
|
||||||
|
engine_file[i] = '\0';
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
const char *usepath = g_SmmPath.c_str();
|
||||||
|
if (UTIL_Relatize(rel_path, sizeof(rel_path), engine_file, g_SmmPath.c_str()))
|
||||||
|
{
|
||||||
|
usepath = rel_path;
|
||||||
|
}
|
||||||
|
|
||||||
|
char command[PATH_SIZE * 2];
|
||||||
g_VspListener.SetLoadable(true);
|
g_VspListener.SetLoadable(true);
|
||||||
UTIL_Format(command, sizeof(command), "plugin_load \"%s\"\n", g_SmmPath.c_str());
|
UTIL_Format(command, sizeof(command), "plugin_load \"%s\"\n", usepath);
|
||||||
g_Engine.engine->ServerCommand(command);
|
g_Engine.engine->ServerCommand(command);
|
||||||
}
|
}
|
||||||
|
|
||||||
void CSmmAPI::EnableVSPListener()
|
void CSmmAPI::EnableVSPListener()
|
||||||
{
|
{
|
||||||
/* If GameInit already passed and we're not already enabled or loaded, go ahead and LoadAsVSP load */
|
/* If GameInit already passed and we're not already enabled or loaded, go ahead and LoadAsVSP load */
|
||||||
if (bGameInit && !m_VSP && !g_VspListener.IsLoaded())
|
if (bGameInit && !m_VSP && !g_VspListener.IsLoaded() && !g_VspListener.IsRootLoadMethod())
|
||||||
{
|
{
|
||||||
LoadAsVSP();
|
LoadAsVSP();
|
||||||
}
|
}
|
||||||
@ -492,6 +504,11 @@ int CSmmAPI::GetGameDLLVersion()
|
|||||||
#define MSGCLASS2_SIGLEN 16
|
#define MSGCLASS2_SIGLEN 16
|
||||||
#define MSGCLASS2_SIG "\x56\x8B\x74\x24\x2A\x85\xF6\x7C\x2A\x3B\x35\x2A\x2A\x2A\x2A\x7D"
|
#define MSGCLASS2_SIG "\x56\x8B\x74\x24\x2A\x85\xF6\x7C\x2A\x3B\x35\x2A\x2A\x2A\x2A\x7D"
|
||||||
#define MSGCLASS2_OFFS 11
|
#define MSGCLASS2_OFFS 11
|
||||||
|
|
||||||
|
/* Windows frame pointer sig */
|
||||||
|
#define MSGCLASS3_SIGLEN 18
|
||||||
|
#define MSGCLASS3_SIG "\x55\x8B\xEC\x51\x89\x2A\x2A\x8B\x2A\x2A\x50\x8B\x0D\x2A\x2A\x2A\x2A\xE8"
|
||||||
|
#define MSGCLASS3_OFFS 13
|
||||||
#elif defined OS_LINUX
|
#elif defined OS_LINUX
|
||||||
/* No frame pointer sig */
|
/* No frame pointer sig */
|
||||||
#define MSGCLASS_SIGLEN 14
|
#define MSGCLASS_SIGLEN 14
|
||||||
@ -508,45 +525,22 @@ int CSmmAPI::GetGameDLLVersion()
|
|||||||
/* :TODO: Make this prettier */
|
/* :TODO: Make this prettier */
|
||||||
bool CSmmAPI::CacheUserMessages()
|
bool CSmmAPI::CacheUserMessages()
|
||||||
{
|
{
|
||||||
SourceHook::MemFuncInfo info = {true, -1, 0, 0};
|
|
||||||
SourceHook::GetFuncInfo(&IServerGameDLL::GetUserMessageInfo, info);
|
|
||||||
|
|
||||||
/* Get address of original GetUserMessageInfo() */
|
|
||||||
char *vfunc = reinterpret_cast<char *>(g_GameDllPatch->GetOrigFunc(info.vtbloffs, info.vtblindex));
|
|
||||||
|
|
||||||
/* If we can't get original function, that means there's no hook */
|
|
||||||
if (vfunc == NULL)
|
|
||||||
{
|
|
||||||
/* Get virtual function address 'manually' then */
|
|
||||||
char *adjustedptr = reinterpret_cast<char *>(g_GameDll.pGameDLL) + info.thisptroffs + info.vtbloffs;
|
|
||||||
char **vtable = *reinterpret_cast<char ***>(adjustedptr);
|
|
||||||
|
|
||||||
vfunc = vtable[info.vtblindex];
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Oh dear, we have a relative jump on our hands
|
|
||||||
* PVK II on Windows made me do this, but I suppose it doesn't hurt to check this on Linux too...
|
|
||||||
*/
|
|
||||||
if (*vfunc == '\xE9')
|
|
||||||
{
|
|
||||||
/* Get address from displacement...
|
|
||||||
*
|
|
||||||
* Add 5 because it's relative to next instruction:
|
|
||||||
* Opcode <1 byte> + 32-bit displacement <4 bytes>
|
|
||||||
*/
|
|
||||||
vfunc = vfunc + *reinterpret_cast<int *>(vfunc + 1) + 5;
|
|
||||||
}
|
|
||||||
|
|
||||||
UserMsgDict *dict = NULL;
|
UserMsgDict *dict = NULL;
|
||||||
|
char *vfunc = UTIL_GetOrigFunction(&IServerGameDLL::GetUserMessageInfo, g_GameDll.pGameDLL, g_GameDllPatch);
|
||||||
|
|
||||||
if (vcmp(vfunc, MSGCLASS_SIG, MSGCLASS_SIGLEN))
|
if (!vfunc)
|
||||||
|
{
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (UTIL_VerifySignature(vfunc, MSGCLASS_SIG, MSGCLASS_SIGLEN))
|
||||||
{
|
{
|
||||||
/* Get address of CUserMessages instance */
|
/* Get address of CUserMessages instance */
|
||||||
char **userMsgClass = *reinterpret_cast<char ***>(vfunc + MSGCLASS_OFFS);
|
char **userMsgClass = *reinterpret_cast<char ***>(vfunc + MSGCLASS_OFFS);
|
||||||
|
|
||||||
/* Get address of CUserMessages::m_UserMessages */
|
/* Get address of CUserMessages::m_UserMessages */
|
||||||
dict = reinterpret_cast<UserMsgDict *>(*userMsgClass);
|
dict = reinterpret_cast<UserMsgDict *>(*userMsgClass);
|
||||||
} else if (vcmp(vfunc, MSGCLASS2_SIG, MSGCLASS2_SIGLEN)) {
|
} else if (UTIL_VerifySignature(vfunc, MSGCLASS2_SIG, MSGCLASS2_SIGLEN)) {
|
||||||
#ifdef OS_WIN32
|
#ifdef OS_WIN32
|
||||||
/* If we get here, the code is possibly inlined like in Dystopia */
|
/* If we get here, the code is possibly inlined like in Dystopia */
|
||||||
|
|
||||||
@ -562,6 +556,14 @@ bool CSmmAPI::CacheUserMessages()
|
|||||||
/* Get address of CUserMessages::m_UserMessages */
|
/* Get address of CUserMessages::m_UserMessages */
|
||||||
dict = reinterpret_cast<UserMsgDict *>(*userMsgClass);
|
dict = reinterpret_cast<UserMsgDict *>(*userMsgClass);
|
||||||
#endif
|
#endif
|
||||||
|
#ifdef OS_WIN32
|
||||||
|
} else if (UTIL_VerifySignature(vfunc, MSGCLASS3_SIG, MSGCLASS3_SIGLEN)) {
|
||||||
|
/* Get address of CUserMessages instance */
|
||||||
|
char **userMsgClass = *reinterpret_cast<char ***>(vfunc + MSGCLASS3_OFFS);
|
||||||
|
|
||||||
|
/* Get address of CUserMessages::m_UserMessages */
|
||||||
|
dict = reinterpret_cast<UserMsgDict *>(*userMsgClass);
|
||||||
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
if (dict)
|
if (dict)
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
/* ======== SourceMM ========
|
/* ======== SourceMM ========
|
||||||
* Copyright (C) 2004-2007 Metamod:Source Development Team
|
* Copyright (C) 2004-2008 Metamod:Source Development Team
|
||||||
* No warranties of any kind
|
* No warranties of any kind
|
||||||
*
|
*
|
||||||
* License: zlib/libpng
|
* License: zlib/libpng
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
/* ======== SourceMM ========
|
/* ======== SourceMM ========
|
||||||
* Copyright (C) 2004-2007 Metamod:Source Development Team
|
* Copyright (C) 2004-2008 Metamod:Source Development Team
|
||||||
* No warranties of any kind
|
* No warranties of any kind
|
||||||
*
|
*
|
||||||
* License: zlib/libpng
|
* License: zlib/libpng
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
/* ======== SourceMM ========
|
/* ======== SourceMM ========
|
||||||
* Copyright (C) 2004-2007 Metamod:Source Development Team
|
* Copyright (C) 2004-2008 Metamod:Source Development Team
|
||||||
* No warranties of any kind
|
* No warranties of any kind
|
||||||
*
|
*
|
||||||
* License: zlib/libpng
|
* License: zlib/libpng
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
/* ======== SourceMM ========
|
/* ======== SourceMM ========
|
||||||
* Copyright (C) 2004-2007 Metamod:Source Development Team
|
* Copyright (C) 2004-2008 Metamod:Source Development Team
|
||||||
* No warranties of any kind
|
* No warranties of any kind
|
||||||
*
|
*
|
||||||
* License: zlib/libpng
|
* License: zlib/libpng
|
||||||
|
@ -1,4 +1,4 @@
|
|||||||
The software is Copyright (C) 2004-2007, Metamod:Source Development Team.
|
The software is Copyright (C) 2004-2008, Metamod:Source Development Team.
|
||||||
|
|
||||||
Metamod:Source is distributed under the "zLib/libpng" license, which is reproduced
|
Metamod:Source is distributed under the "zLib/libpng" license, which is reproduced
|
||||||
below:
|
below:
|
||||||
|
@ -1,4 +1,4 @@
|
|||||||
#(C)2004-2007 SourceMM Development Team
|
#(C)2004-2008 SourceMM Development Team
|
||||||
# Makefile written by David "BAILOPAN" Anderson
|
# Makefile written by David "BAILOPAN" Anderson
|
||||||
|
|
||||||
HL2SDK = ../../hl2sdk
|
HL2SDK = ../../hl2sdk
|
||||||
@ -34,7 +34,10 @@ endif
|
|||||||
|
|
||||||
GCC_VERSION := $(shell $(CPP) -dumpversion >&1 | cut -b1)
|
GCC_VERSION := $(shell $(CPP) -dumpversion >&1 | cut -b1)
|
||||||
|
|
||||||
CFLAGS += -D_LINUX -DNDEBUG -Dstricmp=strcasecmp -D_stricmp=strcasecmp -D_strnicmp=strncasecmp -Dstrnicmp=strncasecmp -D_snprintf=snprintf -D_vsnprintf=vsnprintf -D_alloca=alloca -Dstrcmpi=strcasecmp -Wall -Wno-non-virtual-dtor -Werror -fPIC -fno-exceptions -fno-rtti -msse
|
CFLAGS += -D_LINUX -DNDEBUG -Dstricmp=strcasecmp -D_stricmp=strcasecmp -D_strnicmp=strncasecmp \
|
||||||
|
-Dstrnicmp=strncasecmp -D_snprintf=snprintf -D_vsnprintf=vsnprintf -D_alloca=alloca \
|
||||||
|
-Dstrcmpi=strcasecmp -Wall -Wno-non-virtual-dtor -Wno-uninitialized -Werror -fPIC \
|
||||||
|
-fno-exceptions -fno-rtti -msse -m32
|
||||||
|
|
||||||
ifeq "$(GCC_VERSION)" "4"
|
ifeq "$(GCC_VERSION)" "4"
|
||||||
CFLAGS += $(GCC4_FLAGS)
|
CFLAGS += $(GCC4_FLAGS)
|
||||||
@ -55,7 +58,7 @@ all:
|
|||||||
ln -sf $(BIN_DIR)/$(BINARY) $(BINARY)
|
ln -sf $(BIN_DIR)/$(BINARY) $(BINARY)
|
||||||
|
|
||||||
sourcemm: $(OBJ_LINUX)
|
sourcemm: $(OBJ_LINUX)
|
||||||
$(CPP) $(INCLUDE) $(CFLAGS) $(OBJ_LINUX) $(LINK) -shared -ldl -lm -o$(BIN_DIR)/$(BINARY)
|
$(CPP) $(INCLUDE) -m32 $(CFLAGS) $(OBJ_LINUX) $(LINK) -shared -ldl -lm -o$(BIN_DIR)/$(BINARY)
|
||||||
|
|
||||||
debug:
|
debug:
|
||||||
$(MAKE) all DEBUG=true
|
$(MAKE) all DEBUG=true
|
||||||
|
@ -1,3 +1,35 @@
|
|||||||
|
2008/??/?? 1.4.5:
|
||||||
|
- Fixed amb1952: Crash when first plugin listed in metaplugins.ini had an alias
|
||||||
|
and was not on the first line of the file.
|
||||||
|
|
||||||
|
2008/07/26 1.4.4:
|
||||||
|
- Fixed a bug where loading plugins built for MM:S 1.3 or older (API ver <= 9)
|
||||||
|
would cause a crash.
|
||||||
|
- Fixed a bug where loading plugins using VDF files caused Metamod:Source
|
||||||
|
to crash on The Ship. (bug 1523)
|
||||||
|
- Fixed a class of crashes caused by improper cvar removal handling. (bug 1416)
|
||||||
|
- Fixed a bug where VDF files were opened by MM:S even if the .vdf extension
|
||||||
|
was not at the very end of the filename. For example, "plugin.vdf.disabled"
|
||||||
|
would have been opened in previous versions. (bug 1534)
|
||||||
|
- Removed FCVAR_REPLICATED from MM:S convars. (bug 1479)
|
||||||
|
|
||||||
|
2008/01/23 1.4.3:
|
||||||
|
- Metamod:Source can now be loaded via a .vdf instead of gameinfo.txt.
|
||||||
|
- Added new plugin loading mechanism via .vdf files in the metamod folder.
|
||||||
|
- Changed "meta list" output to look similar to Metamod:Source 1.6.
|
||||||
|
- Plugins which need a VSP pointer can now receive it on late load.
|
||||||
|
- Fixed a small memory leak when using recalls (RETURN_META_NEWPARAMS).
|
||||||
|
- Fixed a rare memory corruption bug in the CVector class.
|
||||||
|
|
||||||
|
2007/06/26 1.4.2:
|
||||||
|
- Fixed a bug where unloading all plugins could crash if one plugin had child plugins.
|
||||||
|
|
||||||
|
2007/05/16 1.4.1:
|
||||||
|
- The client version of the "meta" command should now work with games using the latest
|
||||||
|
Source beta (srcds0407).
|
||||||
|
- Fixed amb233 (VSP listener didn't work with Steam dedicated version).
|
||||||
|
- Fixed amb277 (failed to get user message list in Kreedz Climbing).
|
||||||
|
|
||||||
2007/04/05 1.4.0:
|
2007/04/05 1.4.0:
|
||||||
- Added API functions for retrieving User Message info without potentially crashing.
|
- Added API functions for retrieving User Message info without potentially crashing.
|
||||||
- Added API functions for letting SourceMM plugins use Valve Server Plugin callbacks.
|
- Added API functions for letting SourceMM plugins use Valve Server Plugin callbacks.
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
/* ======== SourceMM ========
|
/* ======== SourceMM ========
|
||||||
* Copyright (C) 2004-2007 Metamod:Source Development Team
|
* Copyright (C) 2004-2008 Metamod:Source Development Team
|
||||||
* No warranties of any kind
|
* No warranties of any kind
|
||||||
*
|
*
|
||||||
* License: zlib/libpng
|
* License: zlib/libpng
|
||||||
@ -9,31 +9,38 @@
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
#include <ctype.h>
|
#include <ctype.h>
|
||||||
|
#include "convar_smm.h"
|
||||||
#include "CSmmAPI.h"
|
#include "CSmmAPI.h"
|
||||||
#include "concommands.h"
|
#include "concommands.h"
|
||||||
#include "CPlugin.h"
|
#include "CPlugin.h"
|
||||||
#include "sh_string.h"
|
#include "sh_string.h"
|
||||||
#include "sh_list.h"
|
#include "sh_list.h"
|
||||||
|
#include "vsp_listener.h"
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief Console Command Implementations
|
* @brief Console Command Implementations
|
||||||
* @file concommands.cpp
|
* @file concommands.cpp
|
||||||
*/
|
*/
|
||||||
|
|
||||||
CAlwaysRegisterableCommand g_EternalCommand;
|
|
||||||
SMConVarAccessor g_SMConVarAccessor;
|
SMConVarAccessor g_SMConVarAccessor;
|
||||||
|
|
||||||
|
SMConVarAccessor::SMConVarAccessor()
|
||||||
|
{
|
||||||
|
m_TopConCommandBase = NULL;
|
||||||
|
}
|
||||||
|
|
||||||
bool SMConVarAccessor::RegisterConCommandBase(ConCommandBase *pCommand)
|
bool SMConVarAccessor::RegisterConCommandBase(ConCommandBase *pCommand)
|
||||||
{
|
{
|
||||||
// Add the FCVAR_GAMEDLL flag
|
/* Add the FCVAR_GAMEDLL flag
|
||||||
// => No crash on exit!
|
* => No crash on exit!
|
||||||
// UPDATE: Do _not_ add the FCVAR_GAMEDLL flag here, as it
|
* UPDATE: Do _not_ add the FCVAR_GAMEDLL flag here, as it
|
||||||
// causes the command to be unusable on listenservers until you load a map
|
* causes the command to be unusable on listen servers until you load a map
|
||||||
// We will set the FCVAR_GAMEDLL flag on all commands we have registered once we are being unloaded
|
* We will set the FCVAR_GAMEDLL flag on all commands we have registered once we are being unloaded
|
||||||
//pCommand->AddFlags(FCVAR_GAMEDLL);
|
*/
|
||||||
|
// pCommand->AddFlags(FCVAR_GAMEDLL);
|
||||||
m_RegisteredCommands.push_back(pCommand);
|
m_RegisteredCommands.push_back(pCommand);
|
||||||
|
|
||||||
pCommand->SetNext( NULL );
|
pCommand->SetNext(NULL);
|
||||||
g_Engine.icvar->RegisterConCommandBase(pCommand);
|
g_Engine.icvar->RegisterConCommandBase(pCommand);
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
@ -41,8 +48,8 @@ bool SMConVarAccessor::RegisterConCommandBase(ConCommandBase *pCommand)
|
|||||||
|
|
||||||
bool SMConVarAccessor::Register(ConCommandBase *pCommand)
|
bool SMConVarAccessor::Register(ConCommandBase *pCommand)
|
||||||
{
|
{
|
||||||
//simple, don't mark as part of sourcemm!
|
/* Simple, don't mark as part of sourcemm! */
|
||||||
pCommand->SetNext( NULL );
|
pCommand->SetNext(NULL);
|
||||||
g_Engine.icvar->RegisterConCommandBase(pCommand);
|
g_Engine.icvar->RegisterConCommandBase(pCommand);
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
@ -59,67 +66,52 @@ void SMConVarAccessor::MarkCommandsAsGameDLL()
|
|||||||
|
|
||||||
void SMConVarAccessor::Unregister(ConCommandBase *pCommand)
|
void SMConVarAccessor::Unregister(ConCommandBase *pCommand)
|
||||||
{
|
{
|
||||||
ICvar *cv = g_Engine.icvar;
|
ConCommandBase *pCur = NULL;
|
||||||
ConCommandBase *ptr = cv->GetCommands();
|
ConCommandBase *pPrev = NULL;
|
||||||
|
|
||||||
if (ptr == pCommand)
|
if (!pCommand || !pCommand->IsRegistered())
|
||||||
{
|
{
|
||||||
//first in list
|
return;
|
||||||
g_EternalCommand.BringToFront();
|
}
|
||||||
g_EternalCommand.SetNext(const_cast<ConCommandBase *>(pCommand->GetNext()));
|
|
||||||
} else {
|
pCur = g_Engine.icvar->GetCommands();
|
||||||
//find us and unregister us
|
pCommand->SetRegistered(false);
|
||||||
ConCommandBase *pPrev = NULL;
|
|
||||||
while (ptr)
|
if (!m_TopConCommandBase || !pCur)
|
||||||
{
|
{
|
||||||
if (ptr == pCommand)
|
return;
|
||||||
break;
|
}
|
||||||
pPrev = ptr;
|
|
||||||
ptr = const_cast<ConCommandBase *>(ptr->GetNext());
|
if (pCur == pCommand)
|
||||||
}
|
{
|
||||||
if (pPrev && ptr == pCommand)
|
*m_TopConCommandBase = const_cast<ConCommandBase *>(pCommand->GetNext());
|
||||||
|
pCommand->SetNext(NULL);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
pPrev = pCur;
|
||||||
|
pCur = const_cast<ConCommandBase *>(pCur->GetNext());
|
||||||
|
|
||||||
|
while (pCur)
|
||||||
|
{
|
||||||
|
if (pCur == pCommand)
|
||||||
{
|
{
|
||||||
pPrev->SetNext(const_cast<ConCommandBase *>(pCommand->GetNext()));
|
pPrev->SetNext(const_cast<ConCommandBase *>(pCommand->GetNext()));
|
||||||
|
pCommand->SetNext(NULL);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pPrev = pCur;
|
||||||
|
pCur = const_cast<ConCommandBase *>(pCur->GetNext());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void SMConVarAccessor::UnregisterGameDLLCommands()
|
ConVar metamod_version("metamod_version", SOURCEMM_VERSION, FCVAR_SPONLY | FCVAR_NOTIFY, "Metamod:Source Version");
|
||||||
{
|
#ifdef OS_WIN32
|
||||||
ConCommandBase *begin = g_Engine.icvar->GetCommands();
|
|
||||||
ConCommandBase *iter = begin;
|
|
||||||
ConCommandBase *prev = NULL;
|
|
||||||
while (iter)
|
|
||||||
{
|
|
||||||
// watch out for the ETERNAL COMMAND!
|
|
||||||
if (iter != &g_EternalCommand && iter->IsBitSet(FCVAR_GAMEDLL))
|
|
||||||
{
|
|
||||||
// Remove it!
|
|
||||||
if (iter == begin)
|
|
||||||
{
|
|
||||||
g_EternalCommand.BringToFront();
|
|
||||||
iter = const_cast<ConCommandBase*>(iter->GetNext());
|
|
||||||
g_EternalCommand.SetNext(iter);
|
|
||||||
prev = &g_EternalCommand;
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
iter = const_cast<ConCommandBase*>(iter->GetNext());
|
|
||||||
prev->SetNext(iter);
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
prev = iter;
|
|
||||||
iter = const_cast<ConCommandBase*>(iter->GetNext());
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
ConVar metamod_version("metamod_version", SOURCEMM_VERSION, FCVAR_REPLICATED | FCVAR_SPONLY | FCVAR_NOTIFY, "Metamod:Source Version");
|
|
||||||
#if defined WIN32 || defined _WIN32
|
|
||||||
ConVar mm_pluginsfile("mm_pluginsfile", "addons\\metamod\\metaplugins.ini", FCVAR_SPONLY, "Metamod:Source Plugins File");
|
ConVar mm_pluginsfile("mm_pluginsfile", "addons\\metamod\\metaplugins.ini", FCVAR_SPONLY, "Metamod:Source Plugins File");
|
||||||
|
ConVar mm_basedir("mm_basedir", "addons\\metamod", FCVAR_SPONLY, "Metamod:Source base folder");
|
||||||
#else
|
#else
|
||||||
ConVar mm_pluginsfile("mm_pluginsfile", "addons/metamod/metaplugins.ini", FCVAR_SPONLY, "Metamod:Source Plugins File");
|
ConVar mm_pluginsfile("mm_pluginsfile", "addons/metamod/metaplugins.ini", FCVAR_SPONLY, "Metamod:Source Plugins File");
|
||||||
|
ConVar mm_basedir("mm_basedir", "addons/metamod", FCVAR_SPONLY, "Metamod:Source base folder");
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
CON_COMMAND(meta, "Metamod:Source Menu")
|
CON_COMMAND(meta, "Metamod:Source Menu")
|
||||||
@ -128,6 +120,12 @@ CON_COMMAND(meta, "Metamod:Source Menu")
|
|||||||
|
|
||||||
int args = e->Cmd_Argc();
|
int args = e->Cmd_Argc();
|
||||||
|
|
||||||
|
if (g_VspListener.IsRootLoadMethod() && !g_bLevelChanged)
|
||||||
|
{
|
||||||
|
CONMSG("WARNING: You must change the map to activate Metamod:Source.\n");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
if (args >= 2)
|
if (args >= 2)
|
||||||
{
|
{
|
||||||
const char *command = e->Cmd_Argv(1);
|
const char *command = e->Cmd_Argv(1);
|
||||||
@ -138,15 +136,23 @@ CON_COMMAND(meta, "Metamod:Source Menu")
|
|||||||
CONMSG(" GameDLL/Plugins: David \"BAILOPAN\" Anderson\n");
|
CONMSG(" GameDLL/Plugins: David \"BAILOPAN\" Anderson\n");
|
||||||
CONMSG(" GameDLL: Scott \"Damaged Soul\" Ehlert\n");
|
CONMSG(" GameDLL: Scott \"Damaged Soul\" Ehlert\n");
|
||||||
CONMSG("For more information, see the official website\n");
|
CONMSG("For more information, see the official website\n");
|
||||||
CONMSG("http://www.sourcemm.net/\n");
|
CONMSG("http://www.metamodsource.net/\n");
|
||||||
|
|
||||||
return;
|
return;
|
||||||
} else if (strcmp(command, "version") == 0) {
|
} else if (strcmp(command, "version") == 0) {
|
||||||
CONMSG("Metamod:Source version %s\n", SOURCEMM_VERSION);
|
CONMSG("Metamod:Source version %s\n", SOURCEMM_VERSION);
|
||||||
|
if (g_VspListener.IsRootLoadMethod())
|
||||||
|
{
|
||||||
|
CONMSG("Loaded As: Valve Server Plugin\n");
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
CONMSG("Loaded As: GameDLL (gameinfo.txt)\n");
|
||||||
|
}
|
||||||
CONMSG("Compiled on: %s\n", SOURCEMM_DATE);
|
CONMSG("Compiled on: %s\n", SOURCEMM_DATE);
|
||||||
CONMSG("Plugin interface version: %d:%d\n", PLAPI_VERSION, PLAPI_MIN_VERSION);
|
CONMSG("Plugin interface version: %d:%d\n", PLAPI_VERSION, PLAPI_MIN_VERSION);
|
||||||
CONMSG("SourceHook version: %d:%d\n", g_SourceHook.GetIfaceVersion(), g_SourceHook.GetImplVersion());
|
CONMSG("SourceHook version: %d:%d\n", g_SourceHook.GetIfaceVersion(), g_SourceHook.GetImplVersion());
|
||||||
CONMSG("http://www.sourcemm.net/\n");
|
CONMSG("http://www.metamodsource.net/\n");
|
||||||
|
|
||||||
return;
|
return;
|
||||||
} else if (strcmp(command, "game") == 0) {
|
} else if (strcmp(command, "game") == 0) {
|
||||||
@ -191,59 +197,63 @@ CON_COMMAND(meta, "Metamod:Source Menu")
|
|||||||
|
|
||||||
return;
|
return;
|
||||||
} else if (strcmp(command, "list") == 0) {
|
} else if (strcmp(command, "list") == 0) {
|
||||||
SourceMM::CPluginManager::CPlugin *pl;
|
size_t len;
|
||||||
PluginIter i;
|
PluginIter i;
|
||||||
const char *status="";
|
char buffer[255];
|
||||||
const char *version=NULL;
|
ISmmPlugin *plapi;
|
||||||
const char *name=NULL;
|
const char *plname;
|
||||||
const char *author=NULL;
|
SourceMM::CPluginManager::CPlugin *pl;
|
||||||
|
unsigned int plnum = g_PluginMngr.GetPluginCount();
|
||||||
|
|
||||||
|
#define IS_STR_FILLED(var) (var != NULL && var[0] != '\0')
|
||||||
|
|
||||||
|
if (!plnum)
|
||||||
|
{
|
||||||
|
CONMSG("No plugins loaded.\n");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
CONMSG("Listing %d plugin%s:\n", plnum, (plnum > 1) ? "s" : "");
|
||||||
|
}
|
||||||
|
|
||||||
CONMSG("-Id- %-20.19s %-10.9s %-20.19s %-8.7s\n", "Name", "Version", "Author", "Status");
|
|
||||||
for (i=g_PluginMngr._begin(); i!=g_PluginMngr._end(); i++)
|
for (i=g_PluginMngr._begin(); i!=g_PluginMngr._end(); i++)
|
||||||
{
|
{
|
||||||
pl = (*i);
|
pl = (*i);
|
||||||
if (!pl)
|
if (!pl)
|
||||||
|
{
|
||||||
break;
|
break;
|
||||||
if (pl->m_Status == Pl_Paused)
|
|
||||||
{
|
|
||||||
status = "PAUSE";
|
|
||||||
} else if (pl->m_Status == Pl_Running) {
|
|
||||||
if (pl->m_API && pl->m_API->QueryRunning(NULL, 0))
|
|
||||||
status = "RUN";
|
|
||||||
else
|
|
||||||
status = "STOPPED";
|
|
||||||
} else if (pl->m_Status == Pl_Refused) {
|
|
||||||
status = "FAIL";
|
|
||||||
} else if (pl->m_Status == Pl_Error) {
|
|
||||||
status = "ERROR";
|
|
||||||
} else if (pl->m_Status == Pl_NotFound) {
|
|
||||||
status = "NOFILE";
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (pl->m_API)
|
len = 0;
|
||||||
|
|
||||||
|
if (pl->m_Status != Pl_Running)
|
||||||
{
|
{
|
||||||
version = pl->m_API->GetVersion();
|
len += UTIL_Format(buffer, sizeof(buffer), " [%02d] <%s>", pl->m_Id, g_PluginMngr.GetStatusText(pl));
|
||||||
author = pl->m_API->GetAuthor();
|
}
|
||||||
name = pl->m_API->GetName();
|
else
|
||||||
} else {
|
{
|
||||||
version = "-";
|
len += UTIL_Format(buffer, sizeof(buffer), " [%02d]", pl->m_Id);
|
||||||
author = "-";
|
|
||||||
name = "-";
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!version)
|
if ((plapi = pl->m_API))
|
||||||
version = "-";
|
{
|
||||||
if (!author)
|
plname = IS_STR_FILLED(plapi->GetName()) ? plapi->GetName() : pl->m_File.c_str();
|
||||||
author = "-";
|
len += UTIL_Format(&buffer[len], sizeof(buffer)-len, " %s", plname);
|
||||||
if (!name)
|
|
||||||
name = pl->m_File.c_str();
|
|
||||||
|
|
||||||
|
if (IS_STR_FILLED(plapi->GetVersion()))
|
||||||
|
{
|
||||||
|
len += UTIL_Format(&buffer[len], sizeof(buffer)-len, " (%s)", plapi->GetVersion());
|
||||||
|
}
|
||||||
|
if (IS_STR_FILLED(plapi->GetAuthor()))
|
||||||
|
{
|
||||||
|
UTIL_Format(&buffer[len], sizeof(buffer)-len, " by %s", plapi->GetAuthor());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
CONMSG("[%02d] %-20.19s %-10.9s %-20.19s %-8.7s\n", pl->m_Id, name, version, author, status);
|
CONMSG("%s\n", buffer);
|
||||||
}
|
}
|
||||||
|
|
||||||
//CONMSG("\n");
|
|
||||||
|
|
||||||
return;
|
return;
|
||||||
} else if (strcmp(command, "cmds") == 0) {
|
} else if (strcmp(command, "cmds") == 0) {
|
||||||
if (args >= 3)
|
if (args >= 3)
|
||||||
@ -625,53 +635,6 @@ CON_COMMAND(meta, "Metamod:Source Menu")
|
|||||||
CONMSG(" version - Version information\n");
|
CONMSG(" version - Version information\n");
|
||||||
}
|
}
|
||||||
|
|
||||||
CAlwaysRegisterableCommand::CAlwaysRegisterableCommand()
|
|
||||||
{
|
|
||||||
Create("", NULL, FCVAR_UNREGISTERED|FCVAR_GAMEDLL);
|
|
||||||
m_pICvar = NULL;
|
|
||||||
}
|
|
||||||
|
|
||||||
bool CAlwaysRegisterableCommand::IsRegistered( void ) const
|
|
||||||
{
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
void CAlwaysRegisterableCommand::BringToFront()
|
|
||||||
{
|
|
||||||
if (!m_pICvar)
|
|
||||||
m_pICvar = g_Engine.icvar;
|
|
||||||
|
|
||||||
// First, let's try to find us!
|
|
||||||
ConCommandBase *pPtr = m_pICvar->GetCommands();
|
|
||||||
|
|
||||||
if (pPtr == this)
|
|
||||||
{
|
|
||||||
// We are already at the beginning; Nothing to do
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
while (pPtr)
|
|
||||||
{
|
|
||||||
if (pPtr == this && pPtr->IsCommand() && stricmp(GetName(), pPtr->GetName()) == 0)
|
|
||||||
break;
|
|
||||||
ConCommandBase *pPrev = NULL;
|
|
||||||
while (pPtr)
|
|
||||||
{
|
|
||||||
if (pPtr == this)
|
|
||||||
break;
|
|
||||||
pPrev = pPtr;
|
|
||||||
pPtr = const_cast<ConCommandBase*>(pPtr->GetNext());
|
|
||||||
}
|
|
||||||
if (pPrev && pPtr == this)
|
|
||||||
{
|
|
||||||
pPrev->SetNext(m_pNext); // Remove us from the list
|
|
||||||
}
|
|
||||||
// Now, register us
|
|
||||||
SetNext(NULL);
|
|
||||||
m_pICvar->RegisterConCommandBase(this);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void ClientCommand_handler(edict_t *client)
|
void ClientCommand_handler(edict_t *client)
|
||||||
{
|
{
|
||||||
IVEngineServer *e = g_Engine.engine;
|
IVEngineServer *e = g_Engine.engine;
|
||||||
@ -688,10 +651,10 @@ void ClientCommand_handler(edict_t *client)
|
|||||||
{
|
{
|
||||||
CLIENT_CONMSG(client, "Metamod:Source was developed by:\n");
|
CLIENT_CONMSG(client, "Metamod:Source was developed by:\n");
|
||||||
CLIENT_CONMSG(client, " SourceHook: Pavol \"PM OnoTo\" Marko\n");
|
CLIENT_CONMSG(client, " SourceHook: Pavol \"PM OnoTo\" Marko\n");
|
||||||
CLIENT_CONMSG(client, " GameDLL/Plugins: David \"BAILOPAN\" Anderson\n");
|
CLIENT_CONMSG(client, " Core: David \"BAILOPAN\" Anderson\n");
|
||||||
CLIENT_CONMSG(client, " GameDLL: Scott \"Damaged Soul\" Ehlert\n");
|
CLIENT_CONMSG(client, " Core: Scott \"Damaged Soul\" Ehlert\n");
|
||||||
CLIENT_CONMSG(client, "For more information, see the official website\n");
|
CLIENT_CONMSG(client, "For more information, see the official website\n");
|
||||||
CLIENT_CONMSG(client, "http://www.sourcemm.net/\n");
|
CLIENT_CONMSG(client, "http://www.metamodsource.net/\n");
|
||||||
|
|
||||||
RETURN_META(MRES_SUPERCEDE);
|
RETURN_META(MRES_SUPERCEDE);
|
||||||
} else if(strcmp(subcmd, "version") == 0) {
|
} else if(strcmp(subcmd, "version") == 0) {
|
||||||
@ -699,49 +662,53 @@ void ClientCommand_handler(edict_t *client)
|
|||||||
CLIENT_CONMSG(client, "Compiled on: %s\n", SOURCEMM_DATE);
|
CLIENT_CONMSG(client, "Compiled on: %s\n", SOURCEMM_DATE);
|
||||||
CLIENT_CONMSG(client, "Plugin interface version: %d:%d\n", PLAPI_VERSION, PLAPI_MIN_VERSION);
|
CLIENT_CONMSG(client, "Plugin interface version: %d:%d\n", PLAPI_VERSION, PLAPI_MIN_VERSION);
|
||||||
CLIENT_CONMSG(client, "SourceHook version: %d:%d\n", g_SourceHook.GetIfaceVersion(), g_SourceHook.GetImplVersion());
|
CLIENT_CONMSG(client, "SourceHook version: %d:%d\n", g_SourceHook.GetIfaceVersion(), g_SourceHook.GetImplVersion());
|
||||||
CLIENT_CONMSG(client, "http://www.sourcemm.net/\n");
|
CLIENT_CONMSG(client, "http://www.metamodsource.net/\n");
|
||||||
|
|
||||||
RETURN_META(MRES_SUPERCEDE);
|
RETURN_META(MRES_SUPERCEDE);
|
||||||
} else if(strcmp(subcmd, "list") == 0) {
|
} else if(strcmp(subcmd, "list") == 0) {
|
||||||
SourceMM::CPluginManager::CPlugin *pl;
|
SourceMM::CPluginManager::CPlugin *pl;
|
||||||
Pl_Status st;
|
ISmmPlugin *plapi;
|
||||||
|
const char *plname;
|
||||||
PluginIter i;
|
PluginIter i;
|
||||||
const char *version = NULL;
|
char buffer[256];
|
||||||
const char *name = NULL;
|
int len = 0;
|
||||||
const char *author = NULL;
|
int plnum = 0;
|
||||||
const char *status = NULL;
|
|
||||||
|
|
||||||
CLIENT_CONMSG(client, "-Id- %-20.19s %-10.9s %-20.19s %6s\n", "Name", "Version", "Author", "Status");
|
for (i = g_PluginMngr._begin(); i != g_PluginMngr._end(); i++, len=0)
|
||||||
|
|
||||||
for (i=g_PluginMngr._begin(); i!=g_PluginMngr._end(); i++)
|
|
||||||
{
|
{
|
||||||
pl = (*i);
|
pl = (*i);
|
||||||
if (!pl)
|
if (pl && pl->m_Status == Pl_Running)
|
||||||
break;
|
|
||||||
|
|
||||||
st = pl->m_Status;
|
|
||||||
|
|
||||||
/* Only show plugins that are running or paused */
|
|
||||||
if (pl->m_API && (st == Pl_Running || st == Pl_Paused))
|
|
||||||
{
|
{
|
||||||
version = pl->m_API->GetVersion();
|
plapi = pl->m_API;
|
||||||
author = pl->m_API->GetAuthor();
|
if (!plapi || !plapi->QueryRunning(NULL, 0))
|
||||||
name = pl->m_API->GetName();
|
|
||||||
|
|
||||||
if (st == Pl_Running && pl->m_API->QueryRunning(NULL, 0))
|
|
||||||
{
|
{
|
||||||
status = "RUN";
|
continue;
|
||||||
} else {
|
}
|
||||||
status = "PAUSE";
|
plnum++;
|
||||||
|
|
||||||
|
len += UTIL_Format(buffer, sizeof(buffer), " [%02d]", plnum);
|
||||||
|
|
||||||
|
plname = IS_STR_FILLED(plapi->GetName()) ? plapi->GetName() : pl->m_File.c_str();
|
||||||
|
len += UTIL_Format(&buffer[len], sizeof(buffer)-len, " %s", plname);
|
||||||
|
|
||||||
|
if (IS_STR_FILLED(plapi->GetVersion()))
|
||||||
|
{
|
||||||
|
len += UTIL_Format(&buffer[len], sizeof(buffer)-len, " (%s)", plapi->GetVersion());
|
||||||
|
}
|
||||||
|
if (IS_STR_FILLED(plapi->GetAuthor()))
|
||||||
|
{
|
||||||
|
UTIL_Format(&buffer[len], sizeof(buffer)-len, " by %s", plapi->GetAuthor());
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!version || !author || !name)
|
CLIENT_CONMSG(client, "%s\n", buffer);
|
||||||
break;
|
|
||||||
|
|
||||||
CLIENT_CONMSG(client, "[%02d] %-20.19s %-10.9s %-20.19s %6s\n", pl->m_Id, name, version, author, status);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (!plnum)
|
||||||
|
{
|
||||||
|
CLIENT_CONMSG(client, "No active plugins loaded.\n");
|
||||||
|
}
|
||||||
|
|
||||||
RETURN_META(MRES_SUPERCEDE);
|
RETURN_META(MRES_SUPERCEDE);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -758,7 +725,79 @@ void ClientCommand_handler(edict_t *client)
|
|||||||
RETURN_META(MRES_IGNORED);
|
RETURN_META(MRES_IGNORED);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void SMConVarAccessor::UnloadMetamodCommands()
|
||||||
|
{
|
||||||
|
Unregister(&metamod_version);
|
||||||
|
Unregister(&mm_pluginsfile);
|
||||||
|
Unregister(&mm_basedir);
|
||||||
|
Unregister(&meta_command);
|
||||||
|
}
|
||||||
|
|
||||||
const char *GetPluginsFile()
|
const char *GetPluginsFile()
|
||||||
{
|
{
|
||||||
return mm_pluginsfile.GetString();
|
return mm_pluginsfile.GetString();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const char *GetMetamodBaseDir()
|
||||||
|
{
|
||||||
|
return mm_basedir.GetString();
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Signature for ICvar::GetCommands() in vstdlib for Win32 and Linux.
|
||||||
|
*
|
||||||
|
* 20226EE0 A1 50 5C 5A 20 mov eax,dword ptr ds:[205A5C50h] <-- What we want
|
||||||
|
* 20226EE5 C3 ret
|
||||||
|
*/
|
||||||
|
#define CMDLIST_SIG "\xA1\x2A\x2A\x2A\x2A\xC3"
|
||||||
|
#define CMDLIST_SIGLEN 6
|
||||||
|
|
||||||
|
/* Linux symbol name of ConCommandBase list in vstdlib */
|
||||||
|
#define CMDLIST_SYMBOL "_ZN14ConCommandBase18s_pConCommandBasesE"
|
||||||
|
|
||||||
|
/* This function retrieves the address of the var that holds the top of the ConCommandBase list.
|
||||||
|
* Having this allows us to change the beginning of this list with ease.
|
||||||
|
*
|
||||||
|
* This craziness eliminates the need for the eternal command/cvar used previously which
|
||||||
|
* could have caused a crash as a result of registering commands/cvars more than once.
|
||||||
|
*/
|
||||||
|
bool SMConVarAccessor::InitConCommandBaseList()
|
||||||
|
{
|
||||||
|
char *vfunc = UTIL_GetOrigFunction(&ICvar::GetCommands, g_Engine.icvar, g_CvarPatch);
|
||||||
|
|
||||||
|
if (!vfunc)
|
||||||
|
{
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
#ifdef OS_WIN32
|
||||||
|
if (UTIL_VerifySignature(vfunc, CMDLIST_SIG, CMDLIST_SIGLEN))
|
||||||
|
{
|
||||||
|
/* Skip past 0xA1 and get addr of ConCommandBase list var */
|
||||||
|
m_TopConCommandBase = *reinterpret_cast<ConCommandBase ***>(vfunc + 1);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
#elif defined OS_LINUX
|
||||||
|
/* Try dlsym first */
|
||||||
|
char path[PATH_SIZE];
|
||||||
|
if (GetFileOfAddress((void *)g_Engine.icvar, path, sizeof(path)))
|
||||||
|
{
|
||||||
|
void *handle = dlopen(path, RTLD_NOW);
|
||||||
|
if (handle)
|
||||||
|
{
|
||||||
|
m_TopConCommandBase = reinterpret_cast<ConCommandBase **>(dlsym(handle, CMDLIST_SYMBOL));
|
||||||
|
dlclose(handle);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/* If dlsym failed, then verify signature of function */
|
||||||
|
if (!m_TopConCommandBase && UTIL_VerifySignature(vfunc, CMDLIST_SIG, CMDLIST_SIGLEN))
|
||||||
|
{
|
||||||
|
/* Skip past 0xA1 and get addr of ConCommandBase list var */
|
||||||
|
m_TopConCommandBase = *reinterpret_cast<ConCommandBase ***>(vfunc + 1);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
/* ======== SourceMM ========
|
/* ======== SourceMM ========
|
||||||
* Copyright (C) 2004-2007 Metamod:Source Development Team
|
* Copyright (C) 2004-2008 Metamod:Source Development Team
|
||||||
* No warranties of any kind
|
* No warranties of any kind
|
||||||
*
|
*
|
||||||
* License: zlib/libpng
|
* License: zlib/libpng
|
||||||
@ -16,37 +16,28 @@
|
|||||||
* @file concommands.h
|
* @file concommands.h
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#include <interface.h>
|
|
||||||
#include <eiface.h>
|
|
||||||
#include "sourcemm.h"
|
|
||||||
#include "convar_smm.h"
|
#include "convar_smm.h"
|
||||||
|
#include "sourcemm.h"
|
||||||
#include "sh_list.h"
|
#include "sh_list.h"
|
||||||
|
|
||||||
class SMConVarAccessor : public IConCommandBaseAccessor
|
class SMConVarAccessor : public IConCommandBaseAccessor
|
||||||
{
|
{
|
||||||
SourceHook::List<ConCommandBase*> m_RegisteredCommands;
|
SourceHook::List<ConCommandBase*> m_RegisteredCommands;
|
||||||
|
ConCommandBase **m_TopConCommandBase;
|
||||||
public:
|
public:
|
||||||
|
SMConVarAccessor();
|
||||||
virtual bool RegisterConCommandBase(ConCommandBase *pCommand);
|
virtual bool RegisterConCommandBase(ConCommandBase *pCommand);
|
||||||
bool Register(ConCommandBase *pCommand);
|
bool Register(ConCommandBase *pCommand);
|
||||||
void MarkCommandsAsGameDLL();
|
void MarkCommandsAsGameDLL();
|
||||||
|
bool InitConCommandBaseList();
|
||||||
void Unregister(ConCommandBase *pCommand);
|
void Unregister(ConCommandBase *pCommand);
|
||||||
void UnregisterGameDLLCommands();
|
void UnloadMetamodCommands();
|
||||||
};
|
|
||||||
|
|
||||||
class CAlwaysRegisterableCommand : public ConCommandBase
|
|
||||||
{
|
|
||||||
ICvar *m_pICvar;
|
|
||||||
public:
|
|
||||||
CAlwaysRegisterableCommand();
|
|
||||||
bool IsRegistered( void ) const;
|
|
||||||
// If already registered, removes us
|
|
||||||
// Then it registers us again
|
|
||||||
void BringToFront();
|
|
||||||
};
|
};
|
||||||
|
|
||||||
void ClientCommand_handler(edict_t *client);
|
void ClientCommand_handler(edict_t *client);
|
||||||
|
|
||||||
const char *GetPluginsFile();
|
const char *GetPluginsFile();
|
||||||
|
const char *GetMetamodBaseDir();
|
||||||
|
|
||||||
extern SMConVarAccessor g_SMConVarAccessor;
|
extern SMConVarAccessor g_SMConVarAccessor;
|
||||||
|
|
||||||
|
@ -198,6 +198,11 @@ protected:
|
|||||||
|
|
||||||
// ConVars in this executable use this 'global' to access values.
|
// ConVars in this executable use this 'global' to access values.
|
||||||
static IConCommandBaseAccessor *s_pAccessor;
|
static IConCommandBaseAccessor *s_pAccessor;
|
||||||
|
public:
|
||||||
|
inline void SetRegistered(bool registered)
|
||||||
|
{
|
||||||
|
m_bRegistered = registered;
|
||||||
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
//-----------------------------------------------------------------------------
|
//-----------------------------------------------------------------------------
|
||||||
@ -242,7 +247,7 @@ private:
|
|||||||
FnCommandCompletionCallback m_fnCompletionCallback;
|
FnCommandCompletionCallback m_fnCompletionCallback;
|
||||||
bool m_bHasCompletionCallback;
|
bool m_bHasCompletionCallback;
|
||||||
public:
|
public:
|
||||||
FnCommandCallback GetCallback() { return m_fnCommandCallback; }
|
inline FnCommandCallback GetCallback() { return m_fnCommandCallback; }
|
||||||
};
|
};
|
||||||
|
|
||||||
//-----------------------------------------------------------------------------
|
//-----------------------------------------------------------------------------
|
||||||
|
@ -41,6 +41,7 @@
|
|||||||
<Tool
|
<Tool
|
||||||
Name="VCCLCompilerTool"
|
Name="VCCLCompilerTool"
|
||||||
Optimization="0"
|
Optimization="0"
|
||||||
|
AdditionalIncludeDirectories=""$(HL2SDK)\public";"$(HL2SDK)\public\dlls";"$(HL2SDK)\public\engine";"$(HL2SDK)\public\tier0";"$(HL2SDK)\public\tier1";"$(HL2SDK)\public\vstdlib";..\..;..\..\sourcehook"
|
||||||
PreprocessorDefinitions="WIN32;_DEBUG;_WINDOWS;_USRDLL;SOURCEMM_EXPORTS;_CRT_SECURE_NO_DEPRECATE"
|
PreprocessorDefinitions="WIN32;_DEBUG;_WINDOWS;_USRDLL;SOURCEMM_EXPORTS;_CRT_SECURE_NO_DEPRECATE"
|
||||||
MinimalRebuild="true"
|
MinimalRebuild="true"
|
||||||
BasicRuntimeChecks="3"
|
BasicRuntimeChecks="3"
|
||||||
@ -62,7 +63,7 @@
|
|||||||
/>
|
/>
|
||||||
<Tool
|
<Tool
|
||||||
Name="VCLinkerTool"
|
Name="VCLinkerTool"
|
||||||
AdditionalDependencies="tier0.lib tier1.lib vstdlib.lib"
|
AdditionalDependencies=""$(HL2SDK)\lib\public\tier0.lib" "$(HL2SDK)\lib\public\tier1.lib" "$(HL2SDK)\lib\public\vstdlib.lib""
|
||||||
OutputFile="$(OutDir)/server.dll"
|
OutputFile="$(OutDir)/server.dll"
|
||||||
LinkIncremental="2"
|
LinkIncremental="2"
|
||||||
IgnoreDefaultLibraryNames="libc.lib;libcd.lib;libcmt.lib"
|
IgnoreDefaultLibraryNames="libc.lib;libcd.lib;libcmt.lib"
|
||||||
@ -126,6 +127,7 @@
|
|||||||
Optimization="3"
|
Optimization="3"
|
||||||
FavorSizeOrSpeed="1"
|
FavorSizeOrSpeed="1"
|
||||||
OmitFramePointers="true"
|
OmitFramePointers="true"
|
||||||
|
AdditionalIncludeDirectories=""$(HL2SDK)\public";"$(HL2SDK)\public\dlls";"$(HL2SDK)\public\engine";"$(HL2SDK)\public\tier0";"$(HL2SDK)\public\tier1";"$(HL2SDK)\public\vstdlib";..\..;..\..\sourcehook"
|
||||||
PreprocessorDefinitions="WIN32;NDEBUG;_WINDOWS;_USRDLL;SOURCEMM_EXPORTS;_CRT_SECURE_NO_DEPRECATE"
|
PreprocessorDefinitions="WIN32;NDEBUG;_WINDOWS;_USRDLL;SOURCEMM_EXPORTS;_CRT_SECURE_NO_DEPRECATE"
|
||||||
StringPooling="true"
|
StringPooling="true"
|
||||||
ExceptionHandling="1"
|
ExceptionHandling="1"
|
||||||
@ -148,7 +150,7 @@
|
|||||||
/>
|
/>
|
||||||
<Tool
|
<Tool
|
||||||
Name="VCLinkerTool"
|
Name="VCLinkerTool"
|
||||||
AdditionalDependencies="tier0.lib tier1.lib vstdlib.lib"
|
AdditionalDependencies=""$(HL2SDK)\lib\public\tier0.lib" "$(HL2SDK)\lib\public\tier1.lib" "$(HL2SDK)\lib\public\vstdlib.lib""
|
||||||
OutputFile="$(OutDir)/server.dll"
|
OutputFile="$(OutDir)/server.dll"
|
||||||
LinkIncremental="1"
|
LinkIncremental="1"
|
||||||
IgnoreDefaultLibraryNames="libc.lib;libcd.lib;libcmtd.lib"
|
IgnoreDefaultLibraryNames="libc.lib;libcd.lib;libcmtd.lib"
|
||||||
@ -273,6 +275,10 @@
|
|||||||
Filter="rc;ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe;resx"
|
Filter="rc;ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe;resx"
|
||||||
UniqueIdentifier="{67DA6AB6-F800-4c08-8B7A-83BB121AAD01}"
|
UniqueIdentifier="{67DA6AB6-F800-4c08-8B7A-83BB121AAD01}"
|
||||||
>
|
>
|
||||||
|
<File
|
||||||
|
RelativePath="..\svn_version.tpl"
|
||||||
|
>
|
||||||
|
</File>
|
||||||
<File
|
<File
|
||||||
RelativePath="..\version.rc"
|
RelativePath="..\version.rc"
|
||||||
>
|
>
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
/* ======== SourceMM ========
|
/* ======== SourceMM ========
|
||||||
* Copyright (C) 2004-2007 Metamod:Source Development Team
|
* Copyright (C) 2004-2008 Metamod:Source Development Team
|
||||||
* No warranties of any kind
|
* No warranties of any kind
|
||||||
*
|
*
|
||||||
* License: zlib/libpng
|
* License: zlib/libpng
|
||||||
@ -16,17 +16,29 @@
|
|||||||
#include "oslink.h"
|
#include "oslink.h"
|
||||||
#ifdef __linux
|
#ifdef __linux
|
||||||
#include <errno.h>
|
#include <errno.h>
|
||||||
#include <stdio.h>
|
|
||||||
#endif
|
#endif
|
||||||
|
#include <stdio.h>
|
||||||
|
|
||||||
#if defined __WIN32__ || defined _WIN32 || defined WIN32
|
#if defined __WIN32__ || defined _WIN32 || defined WIN32
|
||||||
const char *dlerror()
|
const char *dlerror()
|
||||||
{
|
{
|
||||||
static char buf[1024];
|
static char buf[1024];
|
||||||
FormatMessage(FORMAT_MESSAGE_FROM_SYSTEM | FORMAT_MESSAGE_IGNORE_INSERTS,
|
DWORD num;
|
||||||
NULL, GetLastError(),
|
|
||||||
MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT),
|
num = GetLastError();
|
||||||
(LPTSTR) &buf, 0, NULL);
|
|
||||||
|
if (FormatMessage(FORMAT_MESSAGE_FROM_SYSTEM | FORMAT_MESSAGE_IGNORE_INSERTS,
|
||||||
|
NULL,
|
||||||
|
num,
|
||||||
|
MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT),
|
||||||
|
buf,
|
||||||
|
sizeof(buf),
|
||||||
|
NULL)
|
||||||
|
== 0)
|
||||||
|
{
|
||||||
|
_snprintf(buf, sizeof(buf), "unknown error %x", num);
|
||||||
|
}
|
||||||
|
|
||||||
return buf;
|
return buf;
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
/* ======== SourceMM ========
|
/* ======== SourceMM ========
|
||||||
* Copyright (C) 2004-2007 Metamod:Source Development Team
|
* Copyright (C) 2004-2008 Metamod:Source Development Team
|
||||||
* No warranties of any kind
|
* No warranties of any kind
|
||||||
*
|
*
|
||||||
* License: zlib/libpng
|
* License: zlib/libpng
|
||||||
@ -56,7 +56,7 @@
|
|||||||
#endif
|
#endif
|
||||||
|
|
||||||
#if defined __linux__
|
#if defined __linux__
|
||||||
extern int errno;
|
#include <errno.h>
|
||||||
int GetLastError();
|
int GetLastError();
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
@ -1,4 +1,4 @@
|
|||||||
The software is Copyright (C) 2004-2007, Metamod:Source Development Team.
|
The software is Copyright (C) 2004-2008, Metamod:Source Development Team.
|
||||||
|
|
||||||
Metamod:Source is distributed under the "zLib/libpng" license, which is reproduced
|
Metamod:Source is distributed under the "zLib/libpng" license, which is reproduced
|
||||||
below:
|
below:
|
||||||
|
@ -1,4 +1,4 @@
|
|||||||
#(C)2004-2007 SourceMM Development Team
|
#(C)2004-2008 SourceMM Development Team
|
||||||
# Makefile written by David "BAILOPAN" Anderson
|
# Makefile written by David "BAILOPAN" Anderson
|
||||||
|
|
||||||
HL2SDK = ../../../hl2sdk
|
HL2SDK = ../../../hl2sdk
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
/* ======== sample_mm ========
|
/* ======== sample_mm ========
|
||||||
* Copyright (C) 2004-2007 Metamod:Source Development Team
|
* Copyright (C) 2004-2008 Metamod:Source Development Team
|
||||||
* No warranties of any kind
|
* No warranties of any kind
|
||||||
*
|
*
|
||||||
* License: zlib/libpng
|
* License: zlib/libpng
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
/* ======== sample_mm ========
|
/* ======== sample_mm ========
|
||||||
* Copyright (C) 2004-2007 Metamod:Source Development Team
|
* Copyright (C) 2004-2008 Metamod:Source Development Team
|
||||||
* No warranties of any kind
|
* No warranties of any kind
|
||||||
*
|
*
|
||||||
* License: zlib/libpng
|
* License: zlib/libpng
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
/* ======== sample_mm ========
|
/* ======== sample_mm ========
|
||||||
* Copyright (C) 2004-2007 Metamod:Source Development Team
|
* Copyright (C) 2004-2008 Metamod:Source Development Team
|
||||||
* No warranties of any kind
|
* No warranties of any kind
|
||||||
*
|
*
|
||||||
* License: zlib/libpng
|
* License: zlib/libpng
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
/* ======== sample_mm ========
|
/* ======== sample_mm ========
|
||||||
* Copyright (C) 2004-2007 Metamod:Source Development Team
|
* Copyright (C) 2004-2008 Metamod:Source Development Team
|
||||||
* No warranties of any kind
|
* No warranties of any kind
|
||||||
*
|
*
|
||||||
* License: zlib/libpng
|
* License: zlib/libpng
|
||||||
|
@ -41,6 +41,7 @@
|
|||||||
<Tool
|
<Tool
|
||||||
Name="VCCLCompilerTool"
|
Name="VCCLCompilerTool"
|
||||||
Optimization="0"
|
Optimization="0"
|
||||||
|
AdditionalIncludeDirectories=""$(SOURCEMM14)";"$(SOURCEMM14)\sourcemm";"$(SOURCEMM14)\sourcehook";"$(HL2SDK)\public";"$(HL2SDK)\public\dlls";"$(HL2SDK)\public\engine";"$(HL2SDK)\public\tier0";"$(HL2SDK)\public\tier1";"$(HL2SDK)\public\vstdlib""
|
||||||
PreprocessorDefinitions="WIN32;_DEBUG;_WINDOWS;_USRDLL;SAMPLE_MM_EXPORTS"
|
PreprocessorDefinitions="WIN32;_DEBUG;_WINDOWS;_USRDLL;SAMPLE_MM_EXPORTS"
|
||||||
MinimalRebuild="true"
|
MinimalRebuild="true"
|
||||||
BasicRuntimeChecks="3"
|
BasicRuntimeChecks="3"
|
||||||
@ -62,7 +63,7 @@
|
|||||||
/>
|
/>
|
||||||
<Tool
|
<Tool
|
||||||
Name="VCLinkerTool"
|
Name="VCLinkerTool"
|
||||||
AdditionalDependencies="tier0.lib tier1.lib vstdlib.lib"
|
AdditionalDependencies=""$(HL2SDK)\lib\public\tier0.lib" "$(HL2SDK)\lib\public\tier1.lib" "$(HL2SDK)\lib\public\vstdlib.lib""
|
||||||
OutputFile="$(OutDir)/sample_mm.dll"
|
OutputFile="$(OutDir)/sample_mm.dll"
|
||||||
LinkIncremental="2"
|
LinkIncremental="2"
|
||||||
IgnoreDefaultLibraryNames="libc.lib;libcd.lib;libcmt.lib"
|
IgnoreDefaultLibraryNames="libc.lib;libcd.lib;libcmt.lib"
|
||||||
@ -122,6 +123,7 @@
|
|||||||
/>
|
/>
|
||||||
<Tool
|
<Tool
|
||||||
Name="VCCLCompilerTool"
|
Name="VCCLCompilerTool"
|
||||||
|
AdditionalIncludeDirectories=""$(SOURCEMM14)";"$(SOURCEMM14)\sourcemm";"$(SOURCEMM14)\sourcehook";"$(HL2SDK)\public";"$(HL2SDK)\public\dlls";"$(HL2SDK)\public\engine";"$(HL2SDK)\public\tier0";"$(HL2SDK)\public\tier1";"$(HL2SDK)\public\vstdlib""
|
||||||
PreprocessorDefinitions="WIN32;NDEBUG;_WINDOWS;_USRDLL;SAMPLE_MM_EXPORTS"
|
PreprocessorDefinitions="WIN32;NDEBUG;_WINDOWS;_USRDLL;SAMPLE_MM_EXPORTS"
|
||||||
RuntimeLibrary="0"
|
RuntimeLibrary="0"
|
||||||
RuntimeTypeInfo="false"
|
RuntimeTypeInfo="false"
|
||||||
@ -142,7 +144,7 @@
|
|||||||
/>
|
/>
|
||||||
<Tool
|
<Tool
|
||||||
Name="VCLinkerTool"
|
Name="VCLinkerTool"
|
||||||
AdditionalDependencies="tier0.lib tier1.lib vstdlib.lib"
|
AdditionalDependencies=""$(HL2SDK)\lib\public\tier0.lib" "$(HL2SDK)\lib\public\tier1.lib" "$(HL2SDK)\lib\public\vstdlib.lib""
|
||||||
OutputFile="$(OutDir)/sample_mm.dll"
|
OutputFile="$(OutDir)/sample_mm.dll"
|
||||||
LinkIncremental="1"
|
LinkIncremental="1"
|
||||||
IgnoreDefaultLibraryNames="libc.lib;libcd.lib;libcmtd.lib"
|
IgnoreDefaultLibraryNames="libc.lib;libcd.lib;libcmtd.lib"
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
/* ======== SourceMM ========
|
/* ======== SourceMM ========
|
||||||
* Copyright (C) 2004-2007 Metamod:Source Development Team
|
* Copyright (C) 2004-2008 Metamod:Source Development Team
|
||||||
* No warranties of any kind
|
* No warranties of any kind
|
||||||
*
|
*
|
||||||
* License: zlib/libpng
|
* License: zlib/libpng
|
||||||
@ -19,6 +19,8 @@
|
|||||||
#include "CPlugin.h"
|
#include "CPlugin.h"
|
||||||
#include "util.h"
|
#include "util.h"
|
||||||
#include "vsp_listener.h"
|
#include "vsp_listener.h"
|
||||||
|
#include "iplayerinfo.h"
|
||||||
|
#include <filesystem.h>
|
||||||
|
|
||||||
using namespace SourceMM;
|
using namespace SourceMM;
|
||||||
|
|
||||||
@ -43,6 +45,8 @@ void DLLShutdown_handler();
|
|||||||
void LevelShutdown_handler();
|
void LevelShutdown_handler();
|
||||||
bool LevelInit_handler(char const *pMapName, char const *pMapEntities, char const *pOldLevel, char const *pLandmarkName, bool loadGame, bool background);
|
bool LevelInit_handler(char const *pMapName, char const *pMapEntities, char const *pOldLevel, char const *pLandmarkName, bool loadGame, bool background);
|
||||||
bool GameInit_handler();
|
bool GameInit_handler();
|
||||||
|
void LookForVDFs(const char *dir);
|
||||||
|
bool KVLoadFromFile(KeyValues *kv, IBaseFileSystem *filesystem, const char *resourceName, const char *pathID = NULL);
|
||||||
|
|
||||||
GameDllInfo g_GameDll = {false, NULL, NULL, NULL, NULL};
|
GameDllInfo g_GameDll = {false, NULL, NULL, NULL, NULL};
|
||||||
EngineInfo g_Engine;
|
EngineInfo g_Engine;
|
||||||
@ -57,24 +61,28 @@ bool gParsedGameInfo = false;
|
|||||||
bool bGameInit = false;
|
bool bGameInit = false;
|
||||||
SourceHook::List<GameDllInfo *> gamedll_list;
|
SourceHook::List<GameDllInfo *> gamedll_list;
|
||||||
SourceHook::CallClass<IServerGameDLL> *g_GameDllPatch;
|
SourceHook::CallClass<IServerGameDLL> *g_GameDllPatch;
|
||||||
|
SourceHook::CallClass<ICvar> *g_CvarPatch;
|
||||||
int g_GameDllVersion = 0;
|
int g_GameDllVersion = 0;
|
||||||
const char VSPIFACE_001[] = "ISERVERPLUGINCALLBACKS001";
|
const char VSPIFACE_001[] = "ISERVERPLUGINCALLBACKS001";
|
||||||
const char VSPIFACE_002[] = "ISERVERPLUGINCALLBACKS002";
|
const char VSPIFACE_002[] = "ISERVERPLUGINCALLBACKS002";
|
||||||
const char GAMEINFO_PATH[] = "|gameinfo_path|";
|
const char GAMEINFO_PATH[] = "|gameinfo_path|";
|
||||||
|
IFileSystem *baseFs = NULL;
|
||||||
|
bool g_bLevelChanged = false;
|
||||||
|
|
||||||
|
|
||||||
void ClearGamedllList();
|
void ClearGamedllList();
|
||||||
|
|
||||||
/* Helper Macro */
|
/* Helper Macro */
|
||||||
#define IFACE_MACRO(orig,nam) \
|
#define IFACE_MACRO(orig,nam) \
|
||||||
CPluginManager::CPlugin *pl; \
|
CPluginManager::CPlugin *pl; \
|
||||||
SourceHook::List<IMetamodListener *>::iterator event; \
|
SourceHook::List<CPluginEventHandler>::iterator event; \
|
||||||
IMetamodListener *api; \
|
IMetamodListener *api; \
|
||||||
int mret = 0; \
|
int mret = 0; \
|
||||||
void *val = NULL; \
|
void *val = NULL; \
|
||||||
for (PluginIter iter = g_PluginMngr._begin(); iter != g_PluginMngr._end(); iter++) { \
|
for (PluginIter iter = g_PluginMngr._begin(); iter != g_PluginMngr._end(); iter++) { \
|
||||||
pl = (*iter); \
|
pl = (*iter); \
|
||||||
for (event=pl->m_Events.begin(); event!=pl->m_Events.end(); event++) { \
|
for (event=pl->m_Events.begin(); event!=pl->m_Events.end(); event++) { \
|
||||||
api = (*event); \
|
api = (*event).event; \
|
||||||
mret = IFACE_FAILED; \
|
mret = IFACE_FAILED; \
|
||||||
if ( (val=api->On##nam##Query(iface, &mret)) != NULL ) { \
|
if ( (val=api->On##nam##Query(iface, &mret)) != NULL ) { \
|
||||||
if (ret) *ret = mret; \
|
if (ret) *ret = mret; \
|
||||||
@ -86,12 +94,12 @@ void ClearGamedllList();
|
|||||||
|
|
||||||
#define ITER_EVENT(evn, args) \
|
#define ITER_EVENT(evn, args) \
|
||||||
CPluginManager::CPlugin *pl; \
|
CPluginManager::CPlugin *pl; \
|
||||||
SourceHook::List<IMetamodListener *>::iterator event; \
|
SourceHook::List<CPluginEventHandler>::iterator event; \
|
||||||
IMetamodListener *api; \
|
IMetamodListener *api; \
|
||||||
for (PluginIter iter = g_PluginMngr._begin(); iter != g_PluginMngr._end(); iter++) { \
|
for (PluginIter iter = g_PluginMngr._begin(); iter != g_PluginMngr._end(); iter++) { \
|
||||||
pl = (*iter); \
|
pl = (*iter); \
|
||||||
for (event=pl->m_Events.begin(); event!=pl->m_Events.end(); event++) { \
|
for (event=pl->m_Events.begin(); event!=pl->m_Events.end(); event++) { \
|
||||||
api = (*event); \
|
api = (*event).event; \
|
||||||
api->evn args; \
|
api->evn args; \
|
||||||
} \
|
} \
|
||||||
}
|
}
|
||||||
@ -119,25 +127,34 @@ void InitMainStates()
|
|||||||
SH_ADD_HOOK_STATICFUNC(IServerGameDLL, LevelShutdown, g_GameDll.pGameDLL, LevelShutdown_handler, true);
|
SH_ADD_HOOK_STATICFUNC(IServerGameDLL, LevelShutdown, g_GameDll.pGameDLL, LevelShutdown_handler, true);
|
||||||
SH_ADD_HOOK_STATICFUNC(IServerGameDLL, LevelInit, g_GameDll.pGameDLL, LevelInit_handler, true);
|
SH_ADD_HOOK_STATICFUNC(IServerGameDLL, LevelInit, g_GameDll.pGameDLL, LevelInit_handler, true);
|
||||||
SH_ADD_HOOK_STATICFUNC(IServerGameDLL, GameInit, g_GameDll.pGameDLL, GameInit_handler, false);
|
SH_ADD_HOOK_STATICFUNC(IServerGameDLL, GameInit, g_GameDll.pGameDLL, GameInit_handler, false);
|
||||||
|
|
||||||
if (g_GameDll.pGameClients)
|
|
||||||
{
|
|
||||||
SH_ADD_HOOK_STATICFUNC(IServerGameClients, ClientCommand, g_GameDll.pGameClients, ClientCommand_handler, false);
|
|
||||||
} else {
|
|
||||||
/* If IServerGameClients isn't found, this really isn't a fatal error so... */
|
|
||||||
LogMessage("[META] Warning: Could not find IServerGameClients!");
|
|
||||||
LogMessage("[META] Warning: The 'meta' command will not be available to clients.");
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
bool DLLInit(CreateInterfaceFn engineFactory, CreateInterfaceFn physicsFactory, CreateInterfaceFn filesystemFactory, CGlobalVars *pGlobals)
|
void DoInitialPluginLoads()
|
||||||
{
|
{
|
||||||
g_Engine.engineFactory = engineFactory;
|
const char *pluginFile = g_Engine.icvar->GetCommandLineValue("mm_pluginsfile");
|
||||||
g_Engine.fileSystemFactory = filesystemFactory;
|
const char *mmBaseDir = g_Engine.icvar->GetCommandLineValue("mm_basedir");
|
||||||
g_Engine.physicsFactory = physicsFactory;
|
|
||||||
g_Engine.pGlobals = pGlobals;
|
|
||||||
|
|
||||||
|
if (!pluginFile)
|
||||||
|
{
|
||||||
|
pluginFile = GetPluginsFile();
|
||||||
|
}
|
||||||
|
if (!mmBaseDir)
|
||||||
|
{
|
||||||
|
mmBaseDir = GetMetamodBaseDir();
|
||||||
|
}
|
||||||
|
|
||||||
|
char full_path[260];
|
||||||
|
|
||||||
|
g_SmmAPI.PathFormat(full_path, sizeof(full_path), "%s/%s", g_ModPath.c_str(), pluginFile);
|
||||||
|
LoadPluginsFromFile(full_path);
|
||||||
|
g_SmmAPI.PathFormat(full_path, sizeof(full_path), "%s/%s", g_ModPath.c_str(), mmBaseDir);
|
||||||
|
LookForVDFs(full_path);
|
||||||
|
}
|
||||||
|
|
||||||
|
bool StartupMetamod(CreateInterfaceFn engineFactory, bool bWaitForGameInit)
|
||||||
|
{
|
||||||
g_Engine.engine = (IVEngineServer *)((engineFactory)(INTERFACEVERSION_VENGINESERVER, NULL));
|
g_Engine.engine = (IVEngineServer *)((engineFactory)(INTERFACEVERSION_VENGINESERVER, NULL));
|
||||||
|
|
||||||
if (!g_Engine.engine)
|
if (!g_Engine.engine)
|
||||||
{
|
{
|
||||||
Error("Could not find IVEngineServer! Metamod cannot load.");
|
Error("Could not find IVEngineServer! Metamod cannot load.");
|
||||||
@ -152,10 +169,24 @@ bool DLLInit(CreateInterfaceFn engineFactory, CreateInterfaceFn physicsFactory,
|
|||||||
|
|
||||||
g_Engine.loaded = true;
|
g_Engine.loaded = true;
|
||||||
|
|
||||||
/* Initialize our console hooks */
|
/* The Ship is the only game known at this time that uses the pre-Episode One engine */
|
||||||
|
g_Engine.original = strcmp(CommandLine()->ParmValue("-game", "hl2"), "ship") == 0;
|
||||||
|
|
||||||
ConCommandBaseMgr::OneTimeInit(static_cast<IConCommandBaseAccessor *>(&g_SMConVarAccessor));
|
ConCommandBaseMgr::OneTimeInit(static_cast<IConCommandBaseAccessor *>(&g_SMConVarAccessor));
|
||||||
|
|
||||||
g_GameDllPatch = SH_GET_CALLCLASS(g_GameDll.pGameDLL);
|
g_GameDllPatch = SH_GET_CALLCLASS(g_GameDll.pGameDLL);
|
||||||
|
g_CvarPatch = SH_GET_CALLCLASS(g_Engine.icvar);
|
||||||
|
|
||||||
|
if (g_GameDll.pGameClients)
|
||||||
|
{
|
||||||
|
SH_ADD_HOOK_STATICFUNC(IServerGameClients, ClientCommand, g_GameDll.pGameClients, ClientCommand_handler, false);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
/* If IServerGameClients isn't found, this really isn't a fatal error so... */
|
||||||
|
LogMessage("[META] Warning: Could not find IServerGameClients!");
|
||||||
|
LogMessage("[META] Warning: The 'meta' command will not be available to clients.");
|
||||||
|
}
|
||||||
|
|
||||||
if (!g_SmmAPI.CacheCmds())
|
if (!g_SmmAPI.CacheCmds())
|
||||||
{
|
{
|
||||||
@ -172,34 +203,127 @@ bool DLLInit(CreateInterfaceFn engineFactory, CreateInterfaceFn physicsFactory,
|
|||||||
LogMessage("[META] Warning: The 'meta game' command will not display user messages.");
|
LogMessage("[META] Warning: The 'meta game' command will not display user messages.");
|
||||||
}
|
}
|
||||||
|
|
||||||
const char *pluginFile = g_Engine.icvar->GetCommandLineValue("mm_pluginsfile");
|
baseFs = (IFileSystem *)((engineFactory)(FILESYSTEM_INTERFACE_VERSION, NULL));
|
||||||
if (!pluginFile)
|
if (baseFs == NULL)
|
||||||
{
|
{
|
||||||
pluginFile = GetPluginsFile();
|
LogMessage("[META] Failed to find filesystem interface, .vdf files will not be parsed.");
|
||||||
}
|
}
|
||||||
|
|
||||||
char full_path[260];
|
if (!g_SMConVarAccessor.InitConCommandBaseList())
|
||||||
g_SmmAPI.PathFormat(full_path, sizeof(full_path), "%s/%s", g_ModPath.c_str(), pluginFile);
|
{
|
||||||
|
/* This is very unlikely considering it's old engine */
|
||||||
|
LogMessage("[META] Warning: Failed to find ConCommandBase list!");
|
||||||
|
LogMessage("[META] Warning: ConVars and ConCommands cannot be unregistered properly! Please file a bug report.");
|
||||||
|
}
|
||||||
|
|
||||||
LoadPluginsFromFile(full_path);
|
if (!bWaitForGameInit)
|
||||||
|
{
|
||||||
|
DoInitialPluginLoads();
|
||||||
|
bInFirstLevel = true;
|
||||||
|
}
|
||||||
|
|
||||||
bInFirstLevel = true;
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool DLLInit(CreateInterfaceFn engineFactory, CreateInterfaceFn physicsFactory, CreateInterfaceFn filesystemFactory, CGlobalVars *pGlobals)
|
||||||
|
{
|
||||||
|
g_Engine.engineFactory = engineFactory;
|
||||||
|
g_Engine.fileSystemFactory = filesystemFactory;
|
||||||
|
g_Engine.physicsFactory = physicsFactory;
|
||||||
|
g_Engine.pGlobals = pGlobals;
|
||||||
|
|
||||||
|
StartupMetamod(engineFactory, false);
|
||||||
|
|
||||||
RETURN_META_VALUE(MRES_IGNORED, true);
|
RETURN_META_VALUE(MRES_IGNORED, true);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool AlternatelyLoadMetamod(CreateInterfaceFn ifaceFactory, CreateInterfaceFn serverFactory)
|
||||||
|
{
|
||||||
|
g_Engine.engineFactory = ifaceFactory;
|
||||||
|
g_Engine.fileSystemFactory = ifaceFactory;
|
||||||
|
g_Engine.physicsFactory = ifaceFactory;
|
||||||
|
|
||||||
|
IPlayerInfoManager *playerInfoManager = (IPlayerInfoManager *)serverFactory("PlayerInfoManager002", NULL);
|
||||||
|
if (playerInfoManager == NULL)
|
||||||
|
{
|
||||||
|
Error("Metamod:Source requires gameinfo.txt modification to load on this game.");
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
g_Engine.pGlobals = playerInfoManager->GetGlobalVars();
|
||||||
|
|
||||||
|
/* Now find the server */
|
||||||
|
g_GameDll.factory = serverFactory;
|
||||||
|
g_GameDll.lib = NULL;
|
||||||
|
|
||||||
|
char gamedll_iface[] = "ServerGameDLL000";
|
||||||
|
for (unsigned int i = 3; i <= 50; i++)
|
||||||
|
{
|
||||||
|
gamedll_iface[15] = '0' + i;
|
||||||
|
g_GameDll.pGameDLL = (IServerGameDLL *)serverFactory(gamedll_iface, NULL);
|
||||||
|
if (g_GameDll.pGameDLL != NULL)
|
||||||
|
{
|
||||||
|
g_GameDllVersion = i;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (g_GameDll.pGameDLL == NULL)
|
||||||
|
{
|
||||||
|
Error("Metamod:Source requires gameinfo.txt modification to load on this game.");
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
char gameclients_iface[] = "ServerGameClients000";
|
||||||
|
for (unsigned int i = 3; i <= 4; i++)
|
||||||
|
{
|
||||||
|
gameclients_iface[19] = '0' + i;
|
||||||
|
g_GameDll.pGameClients = (IServerGameClients *)serverFactory(gameclients_iface, NULL);
|
||||||
|
if (g_GameDll.pGameClients != NULL)
|
||||||
|
{
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
char smm_path[PATH_SIZE];
|
||||||
|
const char *game_dir;
|
||||||
|
GetFileOfAddress((void *)AlternatelyLoadMetamod, smm_path, sizeof(smm_path));
|
||||||
|
g_SmmPath.assign(smm_path);
|
||||||
|
|
||||||
|
game_dir = CommandLine()->ParmValue("-game", "hl2");
|
||||||
|
abspath(smm_path, game_dir);
|
||||||
|
g_ModPath.assign(smm_path);
|
||||||
|
|
||||||
|
InitMainStates();
|
||||||
|
|
||||||
|
if (!StartupMetamod(ifaceFactory, true))
|
||||||
|
{
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
g_PluginMngr.SetAllLoaded();
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
bool GameInit_handler()
|
bool GameInit_handler()
|
||||||
{
|
{
|
||||||
if (bGameInit)
|
if (bGameInit)
|
||||||
{
|
{
|
||||||
return true;
|
RETURN_META_VALUE(MRES_IGNORED, true);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (g_SmmAPI.VSPEnabled())
|
if (g_SmmAPI.VSPEnabled() && !g_VspListener.IsRootLoadMethod())
|
||||||
{
|
{
|
||||||
g_SmmAPI.LoadAsVSP();
|
g_SmmAPI.LoadAsVSP();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (g_VspListener.IsRootLoadMethod())
|
||||||
|
{
|
||||||
|
DoInitialPluginLoads();
|
||||||
|
//gaben
|
||||||
|
}
|
||||||
|
|
||||||
bGameInit = true;
|
bGameInit = true;
|
||||||
|
|
||||||
RETURN_META_VALUE(MRES_IGNORED, true);
|
RETURN_META_VALUE(MRES_IGNORED, true);
|
||||||
@ -217,7 +341,7 @@ SMM_API void *CreateInterface(const char *iface, int *ret)
|
|||||||
/* Prevent loading of self as a SourceMM plugin or Valve server plugin :x */
|
/* Prevent loading of self as a SourceMM plugin or Valve server plugin :x */
|
||||||
if (strcmp(iface, PLAPI_NAME) == 0)
|
if (strcmp(iface, PLAPI_NAME) == 0)
|
||||||
{
|
{
|
||||||
Warning("Do not try loading Metamod:Source as a SourceMM or Valve server plugin.\n");
|
Warning("Do not try loading Metamod:Source as a Metamod:Source plugin");
|
||||||
|
|
||||||
if (ret)
|
if (ret)
|
||||||
{
|
{
|
||||||
@ -240,6 +364,12 @@ SMM_API void *CreateInterface(const char *iface, int *ret)
|
|||||||
return &g_VspListener;
|
return &g_VspListener;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* If we're a VSP, bypass this by default */
|
||||||
|
if (g_VspListener.IsRootLoadMethod())
|
||||||
|
{
|
||||||
|
IFACE_MACRO(g_GameDll.factory, GameDLL);
|
||||||
|
}
|
||||||
|
|
||||||
if (!gParsedGameInfo)
|
if (!gParsedGameInfo)
|
||||||
{
|
{
|
||||||
gParsedGameInfo = true;
|
gParsedGameInfo = true;
|
||||||
@ -373,7 +503,6 @@ SMM_API void *CreateInterface(const char *iface, int *ret)
|
|||||||
pInfo->lib = gamedll;
|
pInfo->lib = gamedll;
|
||||||
pInfo->loaded = true;
|
pInfo->loaded = true;
|
||||||
pInfo->pGameDLL = NULL;
|
pInfo->pGameDLL = NULL;
|
||||||
pInfo->pGameClients = (IServerGameClients *)((fn)(INTERFACEVERSION_SERVERGAMECLIENTS, NULL));
|
|
||||||
gamedll_list.push_back(pInfo);
|
gamedll_list.push_back(pInfo);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
@ -446,6 +575,15 @@ SMM_API void *CreateInterface(const char *iface, int *ret)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* We use this interface for responding to the meta client command */
|
||||||
|
if (strncmp(iface, "ServerGameClients", 17) == 0)
|
||||||
|
{
|
||||||
|
void *ptr = (g_GameDll.factory)(iface, ret);
|
||||||
|
g_GameDll.pGameClients = static_cast<IServerGameClients *>(ptr);
|
||||||
|
|
||||||
|
return ptr;
|
||||||
|
}
|
||||||
|
|
||||||
/* If we got here, there's definitely a GameDLL */
|
/* If we got here, there's definitely a GameDLL */
|
||||||
IFACE_MACRO(g_GameDll.factory, GameDLL);
|
IFACE_MACRO(g_GameDll.factory, GameDLL);
|
||||||
}
|
}
|
||||||
@ -465,29 +603,212 @@ void ClearGamedllList()
|
|||||||
gamedll_list.clear();
|
gamedll_list.clear();
|
||||||
}
|
}
|
||||||
|
|
||||||
void DLLShutdown_handler()
|
void UnloadMetamod(bool shutting_down)
|
||||||
{
|
{
|
||||||
/* Unload plugins */
|
/* Unload plugins */
|
||||||
g_PluginMngr.UnloadAll();
|
g_PluginMngr.UnloadAll();
|
||||||
|
|
||||||
/* Add the FCVAR_GAMEDLL flag to our cvars so the engine removes them properly */
|
if (shutting_down)
|
||||||
g_SMConVarAccessor.MarkCommandsAsGameDLL();
|
{
|
||||||
g_SMConVarAccessor.UnregisterGameDLLCommands();
|
/* Add the FCVAR_GAMEDLL flag to our cvars so the engine removes them properly */
|
||||||
|
g_SMConVarAccessor.MarkCommandsAsGameDLL();
|
||||||
|
g_Engine.icvar->UnlinkVariables(FCVAR_GAMEDLL);
|
||||||
|
|
||||||
SH_CALL(g_GameDllPatch, &IServerGameDLL::DLLShutdown)();
|
SH_CALL(g_GameDllPatch, &IServerGameDLL::DLLShutdown)();
|
||||||
|
}
|
||||||
|
|
||||||
SH_RELEASE_CALLCLASS(g_GameDllPatch);
|
SH_RELEASE_CALLCLASS(g_GameDllPatch);
|
||||||
|
SH_RELEASE_CALLCLASS(g_CvarPatch);
|
||||||
g_GameDllPatch = NULL;
|
g_GameDllPatch = NULL;
|
||||||
|
g_CvarPatch = NULL;
|
||||||
|
|
||||||
g_SourceHook.CompleteShutdown();
|
g_SourceHook.CompleteShutdown();
|
||||||
|
|
||||||
if (g_GameDll.lib && g_GameDll.loaded)
|
if (g_GameDll.lib && g_GameDll.loaded)
|
||||||
|
{
|
||||||
dlclose(g_GameDll.lib);
|
dlclose(g_GameDll.lib);
|
||||||
|
}
|
||||||
memset(&g_GameDll, 0, sizeof(GameDllInfo));
|
memset(&g_GameDll, 0, sizeof(GameDllInfo));
|
||||||
|
}
|
||||||
|
|
||||||
|
void DLLShutdown_handler()
|
||||||
|
{
|
||||||
|
UnloadMetamod(true);
|
||||||
RETURN_META(MRES_SUPERCEDE);
|
RETURN_META(MRES_SUPERCEDE);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void LoadFromVDF(const char *file)
|
||||||
|
{
|
||||||
|
PluginId id;
|
||||||
|
bool already, kvfileLoaded;
|
||||||
|
KeyValues *pValues;
|
||||||
|
const char *plugin_file, *alias;
|
||||||
|
char full_path[256], error[256];
|
||||||
|
|
||||||
|
pValues = new KeyValues("Metamod Plugin");
|
||||||
|
|
||||||
|
if (g_Engine.original)
|
||||||
|
{
|
||||||
|
/* The Ship must use a special version of this function */
|
||||||
|
kvfileLoaded = KVLoadFromFile(pValues, baseFs, file);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
kvfileLoaded = pValues->LoadFromFile(baseFs, file);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!kvfileLoaded)
|
||||||
|
{
|
||||||
|
pValues->deleteThis();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if ((plugin_file = pValues->GetString("file", NULL)) == NULL)
|
||||||
|
{
|
||||||
|
pValues->deleteThis();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if ((alias = pValues->GetString("alias", NULL)) != NULL)
|
||||||
|
{
|
||||||
|
g_PluginMngr.SetAlias(alias, plugin_file);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Attempt to find a file extension */
|
||||||
|
if (UTIL_GetExtension(plugin_file) == NULL)
|
||||||
|
{
|
||||||
|
g_SmmAPI.PathFormat(full_path,
|
||||||
|
sizeof(full_path),
|
||||||
|
"%s/%s%s",
|
||||||
|
g_ModPath.c_str(),
|
||||||
|
plugin_file,
|
||||||
|
#if defined WIN32 || defined _WIN32
|
||||||
|
".dll"
|
||||||
|
#else
|
||||||
|
"_i486.so"
|
||||||
|
#endif
|
||||||
|
);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
g_SmmAPI.PathFormat(full_path,
|
||||||
|
sizeof(full_path),
|
||||||
|
"%s/%s",
|
||||||
|
g_ModPath.c_str(),
|
||||||
|
plugin_file);
|
||||||
|
}
|
||||||
|
|
||||||
|
id = g_PluginMngr.Load(full_path, Pl_File, already, error, sizeof(error));
|
||||||
|
if (id < Pl_MinId || g_PluginMngr.FindById(id)->m_Status < Pl_Paused)
|
||||||
|
{
|
||||||
|
LogMessage("[META] Failed to load plugin %s: %s", plugin_file, error);
|
||||||
|
}
|
||||||
|
|
||||||
|
pValues->deleteThis();
|
||||||
|
}
|
||||||
|
|
||||||
|
void LookForVDFs(const char *dir)
|
||||||
|
{
|
||||||
|
char path[MAX_PATH];
|
||||||
|
int extidx;
|
||||||
|
|
||||||
|
#if defined _MSC_VER
|
||||||
|
HANDLE hFind;
|
||||||
|
WIN32_FIND_DATA fd;
|
||||||
|
char error[255];
|
||||||
|
|
||||||
|
g_SmmAPI.PathFormat(path, sizeof(path), "%s\\*.*", dir);
|
||||||
|
if ((hFind = FindFirstFile(path, &fd)) == INVALID_HANDLE_VALUE)
|
||||||
|
{
|
||||||
|
DWORD dw = GetLastError();
|
||||||
|
FormatMessage(FORMAT_MESSAGE_FROM_SYSTEM|FORMAT_MESSAGE_IGNORE_INSERTS,
|
||||||
|
NULL,
|
||||||
|
dw,
|
||||||
|
MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT),
|
||||||
|
error,
|
||||||
|
sizeof(error),
|
||||||
|
NULL);
|
||||||
|
LogMessage("[META] Could not open folder \"%s\" (%s)", dir, error);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
do
|
||||||
|
{
|
||||||
|
if (strcmp(fd.cFileName, ".") == 0
|
||||||
|
|| strcmp(fd.cFileName, "..") == 0)
|
||||||
|
{
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
extidx = strlen(fd.cFileName) - 4;
|
||||||
|
if (extidx < 0 || stricmp(&fd.cFileName[extidx], ".vdf"))
|
||||||
|
{
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
g_SmmAPI.PathFormat(path, sizeof(path), "%s\\%s", dir, fd.cFileName);
|
||||||
|
LoadFromVDF(path);
|
||||||
|
} while (FindNextFile(hFind, &fd));
|
||||||
|
|
||||||
|
FindClose(hFind);
|
||||||
|
#else
|
||||||
|
DIR *pDir;
|
||||||
|
struct dirent *pEnt;
|
||||||
|
|
||||||
|
if ((pDir = opendir(dir)) == NULL)
|
||||||
|
{
|
||||||
|
LogMessage("[META] Could not open folder \"%s\" (%s)", dir, strerror(errno));
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
while ((pEnt = readdir(pDir)) != NULL)
|
||||||
|
{
|
||||||
|
if (strcmp(pEnt->d_name, ".") == 0
|
||||||
|
|| strcmp(pEnt->d_name, "..") == 0)
|
||||||
|
{
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
extidx = strlen(pEnt->d_name) - 4;
|
||||||
|
if (extidx < 0 || stricmp(&pEnt->d_name[extidx], ".vdf"))
|
||||||
|
{
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
g_SmmAPI.PathFormat(path, sizeof(path), "%s/%s", dir, pEnt->d_name);
|
||||||
|
LoadFromVDF(path);
|
||||||
|
}
|
||||||
|
|
||||||
|
closedir(pDir);
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
|
bool KVLoadFromFile(KeyValues *kv, IBaseFileSystem *filesystem, const char *resourceName, const char *pathID)
|
||||||
|
{
|
||||||
|
Assert(filesystem);
|
||||||
|
#ifdef _MSC_VER
|
||||||
|
Assert(_heapchk() == _HEAPOK);
|
||||||
|
#endif
|
||||||
|
|
||||||
|
FileHandle_t f = filesystem->Open(resourceName, "rb", pathID);
|
||||||
|
if (!f)
|
||||||
|
return false;
|
||||||
|
|
||||||
|
// load file into a null-terminated buffer
|
||||||
|
int fileSize = filesystem->Size(f);
|
||||||
|
char *buffer = (char *)MemAllocScratch(fileSize + 1);
|
||||||
|
|
||||||
|
Assert(buffer);
|
||||||
|
|
||||||
|
filesystem->Read(buffer, fileSize, f); // read into local buffer
|
||||||
|
|
||||||
|
buffer[fileSize] = 0; // null terminate file as EOF
|
||||||
|
|
||||||
|
filesystem->Close( f ); // close file after reading
|
||||||
|
|
||||||
|
bool retOK = kv->LoadFromBuffer( resourceName, buffer, filesystem );
|
||||||
|
|
||||||
|
MemFreeScratch();
|
||||||
|
|
||||||
|
return retOK;
|
||||||
|
}
|
||||||
|
|
||||||
int LoadPluginsFromFile(const char *_file)
|
int LoadPluginsFromFile(const char *_file)
|
||||||
{
|
{
|
||||||
FILE *fp;
|
FILE *fp;
|
||||||
@ -505,21 +826,22 @@ int LoadPluginsFromFile(const char *_file)
|
|||||||
char buffer[255], error[255], full_path[255];
|
char buffer[255], error[255], full_path[255];
|
||||||
const char *ptr, *ext, *file;
|
const char *ptr, *ext, *file;
|
||||||
size_t length;
|
size_t length;
|
||||||
while (!feof(fp))
|
while (!feof(fp) && fgets(buffer, sizeof(buffer), fp) != NULL)
|
||||||
{
|
{
|
||||||
buffer[0] = '\0';
|
|
||||||
fgets(buffer, sizeof(buffer), fp);
|
|
||||||
length = strlen(buffer);
|
|
||||||
if (!length)
|
|
||||||
continue;
|
|
||||||
if (buffer[length-1] == '\n')
|
|
||||||
buffer[--length] = '\0';
|
|
||||||
|
|
||||||
UTIL_TrimLeft(buffer);
|
UTIL_TrimLeft(buffer);
|
||||||
UTIL_TrimRight(buffer);
|
UTIL_TrimRight(buffer);
|
||||||
|
|
||||||
if (buffer[0] == '\0' || buffer[0] == ';' || strncmp(buffer, "//", 2) == 0)
|
length = strlen(buffer);
|
||||||
|
if (!length)
|
||||||
|
{
|
||||||
continue;
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (buffer[0] == '\0' || buffer[0] == ';' || strncmp(buffer, "//", 2) == 0)
|
||||||
|
{
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
file = buffer;
|
file = buffer;
|
||||||
if (buffer[0] == '"')
|
if (buffer[0] == '"')
|
||||||
{
|
{
|
||||||
@ -535,7 +857,9 @@ int LoadPluginsFromFile(const char *_file)
|
|||||||
}
|
}
|
||||||
cptr++;
|
cptr++;
|
||||||
}
|
}
|
||||||
} else {
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
char *cptr = buffer;
|
char *cptr = buffer;
|
||||||
while (*cptr)
|
while (*cptr)
|
||||||
{
|
{
|
||||||
@ -543,7 +867,9 @@ int LoadPluginsFromFile(const char *_file)
|
|||||||
{
|
{
|
||||||
char *optr = cptr;
|
char *optr = cptr;
|
||||||
while (*cptr && isspace(*cptr))
|
while (*cptr && isspace(*cptr))
|
||||||
|
{
|
||||||
cptr++;
|
cptr++;
|
||||||
|
}
|
||||||
*optr = '\0';
|
*optr = '\0';
|
||||||
UTIL_TrimRight(cptr);
|
UTIL_TrimRight(cptr);
|
||||||
if (*cptr && isalpha(*cptr))
|
if (*cptr && isalpha(*cptr))
|
||||||
@ -568,13 +894,21 @@ int LoadPluginsFromFile(const char *_file)
|
|||||||
if (id < Pl_MinId || g_PluginMngr.FindById(id)->m_Status < Pl_Paused)
|
if (id < Pl_MinId || g_PluginMngr.FindById(id)->m_Status < Pl_Paused)
|
||||||
{
|
{
|
||||||
LogMessage("[META] Failed to load plugin %s. %s", buffer, error);
|
LogMessage("[META] Failed to load plugin %s. %s", buffer, error);
|
||||||
} else {
|
|
||||||
if (already)
|
|
||||||
skipped++;
|
|
||||||
else
|
|
||||||
total++;
|
|
||||||
}
|
}
|
||||||
} else {
|
else
|
||||||
|
{
|
||||||
|
if (already)
|
||||||
|
{
|
||||||
|
skipped++;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
total++;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
/* Attempt to find a file extension */
|
/* Attempt to find a file extension */
|
||||||
ptr = UTIL_GetExtension(file);
|
ptr = UTIL_GetExtension(file);
|
||||||
/* Add an extension if there's none there */
|
/* Add an extension if there's none there */
|
||||||
@ -585,7 +919,9 @@ int LoadPluginsFromFile(const char *_file)
|
|||||||
#else
|
#else
|
||||||
ext = "_i486.so";
|
ext = "_i486.so";
|
||||||
#endif
|
#endif
|
||||||
} else {
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
ext = "";
|
ext = "";
|
||||||
}
|
}
|
||||||
/* Format the new path */
|
/* Format the new path */
|
||||||
@ -594,11 +930,17 @@ int LoadPluginsFromFile(const char *_file)
|
|||||||
if (id < Pl_MinId || g_PluginMngr.FindById(id)->m_Status < Pl_Paused)
|
if (id < Pl_MinId || g_PluginMngr.FindById(id)->m_Status < Pl_Paused)
|
||||||
{
|
{
|
||||||
LogMessage("[META] Failed to load plugin %s. %s", buffer, error);
|
LogMessage("[META] Failed to load plugin %s. %s", buffer, error);
|
||||||
} else {
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
if (already)
|
if (already)
|
||||||
|
{
|
||||||
skipped++;
|
skipped++;
|
||||||
|
}
|
||||||
else
|
else
|
||||||
|
{
|
||||||
total++;
|
total++;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -607,13 +949,16 @@ int LoadPluginsFromFile(const char *_file)
|
|||||||
if (skipped)
|
if (skipped)
|
||||||
{
|
{
|
||||||
LogMessage("[META] Loaded %d plugins from file (%d already loaded)", total, skipped);
|
LogMessage("[META] Loaded %d plugins from file (%d already loaded)", total, skipped);
|
||||||
} else {
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
LogMessage("[META] Loaded %d plugins from file.", total);
|
LogMessage("[META] Loaded %d plugins from file.", total);
|
||||||
}
|
}
|
||||||
|
|
||||||
return total;
|
return total;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/* Wrapper function. This is called when the GameDLL thinks it's using
|
/* Wrapper function. This is called when the GameDLL thinks it's using
|
||||||
* the engine's real engineFactory.
|
* the engine's real engineFactory.
|
||||||
*/
|
*/
|
||||||
@ -663,13 +1008,20 @@ void LevelShutdown_handler(void)
|
|||||||
if (!bInFirstLevel)
|
if (!bInFirstLevel)
|
||||||
{
|
{
|
||||||
char full_path[255];
|
char full_path[255];
|
||||||
g_SmmAPI.PathFormat(full_path, sizeof(full_path), "%s/%s", g_ModPath.c_str(), GetPluginsFile());
|
|
||||||
|
|
||||||
|
g_SmmAPI.PathFormat(full_path, sizeof(full_path), "%s/%s", g_ModPath.c_str(), GetPluginsFile());
|
||||||
LoadPluginsFromFile(full_path);
|
LoadPluginsFromFile(full_path);
|
||||||
} else {
|
|
||||||
|
g_SmmAPI.PathFormat(full_path, sizeof(full_path), "%s/%s", g_ModPath.c_str(), GetMetamodBaseDir());
|
||||||
|
LookForVDFs(full_path);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
bInFirstLevel = false;
|
bInFirstLevel = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
g_bLevelChanged = true;
|
||||||
|
|
||||||
ITER_EVENT(OnLevelShutdown, ());
|
ITER_EVENT(OnLevelShutdown, ());
|
||||||
|
|
||||||
RETURN_META(MRES_IGNORED);
|
RETURN_META(MRES_IGNORED);
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
/* ======== SourceMM ========
|
/* ======== SourceMM ========
|
||||||
* Copyright (C) 2004-2007 Metamod:Source Development Team
|
* Copyright (C) 2004-2008 Metamod:Source Development Team
|
||||||
* No warranties of any kind
|
* No warranties of any kind
|
||||||
*
|
*
|
||||||
* License: zlib/libpng
|
* License: zlib/libpng
|
||||||
@ -74,11 +74,12 @@ struct GameDllInfo
|
|||||||
/** @brief Stores information about the HL2 Engine pointers */
|
/** @brief Stores information about the HL2 Engine pointers */
|
||||||
struct EngineInfo
|
struct EngineInfo
|
||||||
{
|
{
|
||||||
EngineInfo() : loaded(false),
|
EngineInfo() : loaded(false), original(false),
|
||||||
engineFactory(NULL), physicsFactory(NULL), fileSystemFactory(NULL),
|
engineFactory(NULL), physicsFactory(NULL), fileSystemFactory(NULL),
|
||||||
pGlobals(NULL), icvar(NULL), engine(NULL)
|
pGlobals(NULL), icvar(NULL), engine(NULL)
|
||||||
{ };
|
{ };
|
||||||
bool loaded;
|
bool loaded;
|
||||||
|
bool original;
|
||||||
CreateInterfaceFn engineFactory;
|
CreateInterfaceFn engineFactory;
|
||||||
CreateInterfaceFn physicsFactory;
|
CreateInterfaceFn physicsFactory;
|
||||||
CreateInterfaceFn fileSystemFactory;
|
CreateInterfaceFn fileSystemFactory;
|
||||||
@ -87,6 +88,8 @@ struct EngineInfo
|
|||||||
IVEngineServer *engine;
|
IVEngineServer *engine;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
bool AlternatelyLoadMetamod(CreateInterfaceFn ifaceFactory, CreateInterfaceFn serverFactory);
|
||||||
|
|
||||||
/** @brief Global variable for GameDLL info */
|
/** @brief Global variable for GameDLL info */
|
||||||
extern GameDllInfo g_GameDll;
|
extern GameDllInfo g_GameDll;
|
||||||
|
|
||||||
@ -115,8 +118,14 @@ extern PluginId g_PLID;
|
|||||||
extern int g_GameDllVersion;
|
extern int g_GameDllVersion;
|
||||||
|
|
||||||
extern bool bGameInit;
|
extern bool bGameInit;
|
||||||
|
extern bool g_bLevelChanged;
|
||||||
|
|
||||||
|
void UnloadMetamod(bool shutting_down);
|
||||||
|
|
||||||
/** @brief Global CallClass for IServerGameDLL */
|
/** @brief Global CallClass for IServerGameDLL */
|
||||||
extern SourceHook::CallClass<IServerGameDLL> *g_GameDllPatch;
|
extern SourceHook::CallClass<IServerGameDLL> *g_GameDllPatch;
|
||||||
|
|
||||||
|
/** @brief Global CallClass for ICvar */
|
||||||
|
extern SourceHook::CallClass<ICvar> *g_CvarPatch;
|
||||||
|
|
||||||
#endif //_INCLUDE_SOURCEMM_H
|
#endif //_INCLUDE_SOURCEMM_H
|
||||||
|
@ -1,4 +1,4 @@
|
|||||||
The software is Copyright (C) 2004-2007, Metamod:Source Development Team.
|
The software is Copyright (C) 2004-2008, Metamod:Source Development Team.
|
||||||
|
|
||||||
Metamod:Source is distributed under the "zLib/libpng" license, which is reproduced
|
Metamod:Source is distributed under the "zLib/libpng" license, which is reproduced
|
||||||
below:
|
below:
|
||||||
|
@ -1,4 +1,4 @@
|
|||||||
#(C)2004-2007 SourceMM Development Team
|
#(C)2004-2008 SourceMM Development Team
|
||||||
# Makefile written by David "BAILOPAN" Anderson
|
# Makefile written by David "BAILOPAN" Anderson
|
||||||
|
|
||||||
HL2SDK = ../../../hl2sdk
|
HL2SDK = ../../../hl2sdk
|
||||||
|
@ -41,6 +41,7 @@
|
|||||||
<Tool
|
<Tool
|
||||||
Name="VCCLCompilerTool"
|
Name="VCCLCompilerTool"
|
||||||
Optimization="0"
|
Optimization="0"
|
||||||
|
AdditionalIncludeDirectories=""$(SOURCEMM14)";"$(SOURCEMM14)\sourcemm";"$(SOURCEMM14)\sourcehook";"$(HL2SDK)\public";"$(HL2SDK)\public\dlls";"$(HL2SDK)\public\engine";"$(HL2SDK)\public\tier0";"$(HL2SDK)\public\tier1";"$(HL2SDK)\public\vstdlib""
|
||||||
PreprocessorDefinitions="WIN32;_DEBUG;_WINDOWS;_USRDLL;STUB_MM_EXPORTS"
|
PreprocessorDefinitions="WIN32;_DEBUG;_WINDOWS;_USRDLL;STUB_MM_EXPORTS"
|
||||||
MinimalRebuild="true"
|
MinimalRebuild="true"
|
||||||
BasicRuntimeChecks="3"
|
BasicRuntimeChecks="3"
|
||||||
@ -62,7 +63,7 @@
|
|||||||
/>
|
/>
|
||||||
<Tool
|
<Tool
|
||||||
Name="VCLinkerTool"
|
Name="VCLinkerTool"
|
||||||
AdditionalDependencies="tier0.lib"
|
AdditionalDependencies=""$(HL2SDK)\lib\public\tier0.lib""
|
||||||
ShowProgress="0"
|
ShowProgress="0"
|
||||||
OutputFile="$(OutDir)/stub_mm.dll"
|
OutputFile="$(OutDir)/stub_mm.dll"
|
||||||
LinkIncremental="2"
|
LinkIncremental="2"
|
||||||
@ -123,6 +124,7 @@
|
|||||||
/>
|
/>
|
||||||
<Tool
|
<Tool
|
||||||
Name="VCCLCompilerTool"
|
Name="VCCLCompilerTool"
|
||||||
|
AdditionalIncludeDirectories=""$(SOURCEMM14)";"$(SOURCEMM14)\sourcemm";"$(SOURCEMM14)\sourcehook";"$(HL2SDK)\public";"$(HL2SDK)\public\dlls";"$(HL2SDK)\public\engine";"$(HL2SDK)\public\tier0";"$(HL2SDK)\public\tier1";"$(HL2SDK)\public\vstdlib""
|
||||||
PreprocessorDefinitions="WIN32;NDEBUG;_WINDOWS;_USRDLL;STUB_MM_EXPORTS"
|
PreprocessorDefinitions="WIN32;NDEBUG;_WINDOWS;_USRDLL;STUB_MM_EXPORTS"
|
||||||
RuntimeLibrary="0"
|
RuntimeLibrary="0"
|
||||||
RuntimeTypeInfo="false"
|
RuntimeTypeInfo="false"
|
||||||
@ -142,7 +144,7 @@
|
|||||||
/>
|
/>
|
||||||
<Tool
|
<Tool
|
||||||
Name="VCLinkerTool"
|
Name="VCLinkerTool"
|
||||||
AdditionalDependencies="tier0.lib"
|
AdditionalDependencies=""$(HL2SDK)\lib\public\tier0.lib""
|
||||||
OutputFile="$(OutDir)/stub_mm.dll"
|
OutputFile="$(OutDir)/stub_mm.dll"
|
||||||
LinkIncremental="1"
|
LinkIncremental="1"
|
||||||
IgnoreDefaultLibraryNames="libc.lib;libcd.lib;libcmtd.lib"
|
IgnoreDefaultLibraryNames="libc.lib;libcd.lib;libcmtd.lib"
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
/* ======== stub_mm ========
|
/* ======== stub_mm ========
|
||||||
* Copyright (C) 2004-2007 Metamod:Source Development Team
|
* Copyright (C) 2004-2008 Metamod:Source Development Team
|
||||||
* No warranties of any kind
|
* No warranties of any kind
|
||||||
*
|
*
|
||||||
* License: zlib/libpng
|
* License: zlib/libpng
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
/* ======== stub_mm ========
|
/* ======== stub_mm ========
|
||||||
* Copyright (C) 2004-2007 Metamod:Source Development Team
|
* Copyright (C) 2004-2008 Metamod:Source Development Team
|
||||||
* No warranties of any kind
|
* No warranties of any kind
|
||||||
*
|
*
|
||||||
* License: zlib/libpng
|
* License: zlib/libpng
|
||||||
|
@ -3,11 +3,11 @@
|
|||||||
#ifndef _INCLUDE_SVN_VERSION_H_
|
#ifndef _INCLUDE_SVN_VERSION_H_
|
||||||
#define _INCLUDE_SVN_VERSION_H_
|
#define _INCLUDE_SVN_VERSION_H_
|
||||||
|
|
||||||
#define SVN_PRODUCT_VERSION "1.4.0"
|
#define SVN_PRODUCT_VERSION "1.4.4"
|
||||||
|
|
||||||
#define SVN_REVISION 346
|
#define SVN_REVISION 705
|
||||||
#define SVN_REVISION_STRING "346"
|
#define SVN_REVISION_STRING "705"
|
||||||
#define SVN_FILE_VERSION 1,4,0,346
|
#define SVN_FILE_VERSION 1,4,4,705
|
||||||
#define SVN_FILE_VERSION_STRING "1.4.0.346"
|
#define SVN_FILE_VERSION_STRING "1.4.4.705"
|
||||||
|
|
||||||
#endif //_INCLUDE_SVN_VERSION_H_
|
#endif //_INCLUDE_SVN_VERSION_H_
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
/* ======== SourceMM ========
|
/* ======== SourceMM ========
|
||||||
* Copyright (C) 2004-2007 Metamod:Source Development Team
|
* Copyright (C) 2004-2008 Metamod:Source Development Team
|
||||||
* No warranties of any kind
|
* No warranties of any kind
|
||||||
*
|
*
|
||||||
* License: zlib/libpng
|
* License: zlib/libpng
|
||||||
@ -239,3 +239,186 @@ size_t UTIL_Format(char *buffer, size_t maxlength, const char *fmt, ...)
|
|||||||
|
|
||||||
return len;
|
return len;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
inline bool pathchar_isalpha(char a)
|
||||||
|
{
|
||||||
|
return (((a & 1<<7) == 0) && isalpha(a));
|
||||||
|
}
|
||||||
|
|
||||||
|
inline bool pathchar_sep(char a)
|
||||||
|
{
|
||||||
|
#if defined WIN32
|
||||||
|
return (a == '/' || a == '\\');
|
||||||
|
#elif defined __linux__
|
||||||
|
return (a == '/');
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
|
inline bool pathstr_isabsolute(const char *str)
|
||||||
|
{
|
||||||
|
#if defined WIN32
|
||||||
|
return (pathchar_isalpha(str[0])
|
||||||
|
&& str[1] == ':'
|
||||||
|
&& pathchar_sep(str[2]));
|
||||||
|
#elif defined __linux__
|
||||||
|
return (str[0] == '/');
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
|
inline bool pathchar_cmp(char a, char b)
|
||||||
|
{
|
||||||
|
#if defined WIN32
|
||||||
|
if (pathchar_isalpha(a) && pathchar_isalpha(b))
|
||||||
|
{
|
||||||
|
return (tolower(a) == tolower(b));
|
||||||
|
}
|
||||||
|
/* Either path separator is acceptable */
|
||||||
|
if (pathchar_sep(a))
|
||||||
|
{
|
||||||
|
return pathchar_sep(b);
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
return (a == b);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Forms a relative path given two absolute paths.
|
||||||
|
*
|
||||||
|
* @param buffer Buffer to store relative path in.
|
||||||
|
* @param maxlength Maximum length of the output buffer.
|
||||||
|
* @param relTo Destination folder to use as a working directory.
|
||||||
|
* Final folder name should not be pathchar-terminated.
|
||||||
|
* @param relFrom Source file or folder to use as a target.
|
||||||
|
* @return True on success, false on failure.
|
||||||
|
*/
|
||||||
|
bool UTIL_Relatize(char buffer[],
|
||||||
|
size_t maxlength,
|
||||||
|
const char *relTo,
|
||||||
|
const char *relFrom)
|
||||||
|
{
|
||||||
|
/* We don't allow relative paths in here, force
|
||||||
|
* the user to resolve these himself!
|
||||||
|
*/
|
||||||
|
if (!pathstr_isabsolute(relTo)
|
||||||
|
|| !pathstr_isabsolute(relFrom))
|
||||||
|
{
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
#if defined WIN32
|
||||||
|
/* Relative paths across drives are not possible */
|
||||||
|
if (!pathchar_cmp(relTo[0], relFrom[0]))
|
||||||
|
{
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
/* Get rid of the drive and semicolon part */
|
||||||
|
relTo = &relTo[2];
|
||||||
|
relFrom = &relFrom[2];
|
||||||
|
#endif
|
||||||
|
|
||||||
|
/* Eliminate the common root between the paths */
|
||||||
|
const char *rootTo = NULL;
|
||||||
|
const char *rootFrom = NULL;
|
||||||
|
while (*relTo != '\0' && *relFrom != '\0')
|
||||||
|
{
|
||||||
|
/* If we get to a new path sequence, start over */
|
||||||
|
if (pathchar_sep(*relTo)
|
||||||
|
&& pathchar_sep(*relFrom))
|
||||||
|
{
|
||||||
|
rootTo = relTo;
|
||||||
|
rootFrom = relFrom;
|
||||||
|
/* If the paths don't compare, stop looking for a common root */
|
||||||
|
} else if (!pathchar_cmp(*relTo, *relFrom)) {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
relTo++;
|
||||||
|
relFrom++;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* NULLs shouldn't happen! */
|
||||||
|
if (rootTo == NULL
|
||||||
|
|| rootFrom == NULL)
|
||||||
|
{
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
size_t numLevels = 0;
|
||||||
|
|
||||||
|
/* The root case is special!
|
||||||
|
* Don't count anything from it.
|
||||||
|
*/
|
||||||
|
if (*(rootTo + 1) != '\0')
|
||||||
|
{
|
||||||
|
/* Search for how many levels we need to go up.
|
||||||
|
* Since the root pointer points to a '/', we increment
|
||||||
|
* the initial pointer by one.
|
||||||
|
*/
|
||||||
|
while (*rootTo != '\0')
|
||||||
|
{
|
||||||
|
if (pathchar_sep(*rootTo))
|
||||||
|
{
|
||||||
|
/* Check for an improper trailing slash,
|
||||||
|
* just to be nice even though the user
|
||||||
|
* should NOT have done this!
|
||||||
|
*/
|
||||||
|
if (*(rootTo + 1) == '\0')
|
||||||
|
{
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
numLevels++;
|
||||||
|
}
|
||||||
|
rootTo++;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Now build the new relative path. */
|
||||||
|
size_t len, total = 0;
|
||||||
|
while (numLevels--)
|
||||||
|
{
|
||||||
|
len = _snprintf(&buffer[total], maxlength - total, ".." PATH_SEP_STR);
|
||||||
|
if (len >= maxlength - total)
|
||||||
|
{
|
||||||
|
/* Not enough space in the buffer */
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
total += len;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Add the absolute path. */
|
||||||
|
len = _snprintf(&buffer[total], maxlength - total, "%s", &rootFrom[1]);
|
||||||
|
if (len >= maxlength - total)
|
||||||
|
{
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
size_t UTIL_FormatArgs(char *buffer, size_t maxlength, const char *fmt, va_list params)
|
||||||
|
{
|
||||||
|
size_t len = vsnprintf(buffer, maxlength, fmt, params);
|
||||||
|
|
||||||
|
if (len >= maxlength)
|
||||||
|
{
|
||||||
|
len = maxlength - 1;
|
||||||
|
buffer[len] = '\0';
|
||||||
|
}
|
||||||
|
|
||||||
|
return len;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool UTIL_VerifySignature(const void *addr, const char *sig, size_t len)
|
||||||
|
{
|
||||||
|
unsigned char *addr1 = (unsigned char *) addr;
|
||||||
|
unsigned char *addr2 = (unsigned char *) sig;
|
||||||
|
|
||||||
|
for (size_t i = 0; i < len; i++)
|
||||||
|
{
|
||||||
|
if (addr2[i] == '*')
|
||||||
|
continue;
|
||||||
|
if (addr1[i] != addr2[i])
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
/* ======== SourceMM ========
|
/* ======== SourceMM ========
|
||||||
* Copyright (C) 2004-2007 Metamod:Source Development Team
|
* Copyright (C) 2004-2008 Metamod:Source Development Team
|
||||||
* No warranties of any kind
|
* No warranties of any kind
|
||||||
*
|
*
|
||||||
* License: zlib/libpng
|
* License: zlib/libpng
|
||||||
@ -12,12 +12,15 @@
|
|||||||
#define _INCLUDE_UTIL_H
|
#define _INCLUDE_UTIL_H
|
||||||
|
|
||||||
#include <stdarg.h>
|
#include <stdarg.h>
|
||||||
|
#include <sourcehook/sourcehook.h>
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief Utility functions
|
* @brief Utility functions
|
||||||
* @file util.h
|
* @file util.h
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
#define IA32_JMP_IMM32 '\xE9'
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief Returns a pointer to the extension in a file name.
|
* @brief Returns a pointer to the extension in a file name.
|
||||||
*/
|
*/
|
||||||
@ -56,17 +59,72 @@ size_t UTIL_Format(char *buffer, size_t maxlength, const char *fmt, ...);
|
|||||||
/**
|
/**
|
||||||
* @brief Same as vsnprintf except that it ensures the string buffer is null terminated.
|
* @brief Same as vsnprintf except that it ensures the string buffer is null terminated.
|
||||||
*/
|
*/
|
||||||
inline size_t UTIL_FormatArgs(char *buffer, size_t maxlength, const char *fmt, va_list params)
|
size_t UTIL_FormatArgs(char *buffer, size_t maxlength, const char *fmt, va_list params);
|
||||||
{
|
|
||||||
size_t len = vsnprintf(buffer, maxlength, fmt, params);
|
|
||||||
|
|
||||||
if (len >= maxlength)
|
/**
|
||||||
|
* @brief Forms a relative path given two absolute paths.
|
||||||
|
*
|
||||||
|
* @param buffer Buffer to store relative path in.
|
||||||
|
* @param maxlength Maximum length of the output buffer.
|
||||||
|
* @param relTo Destination folder to use as a working directory.
|
||||||
|
* Final folder name should not be pathchar-terminated.
|
||||||
|
* @param relFrom Source file or folder to use as a target.
|
||||||
|
* @return True on success, false on failure.
|
||||||
|
*/
|
||||||
|
bool UTIL_Relatize(char buffer[],
|
||||||
|
size_t maxlength,
|
||||||
|
const char *relTo,
|
||||||
|
const char *relFrom);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Compares memory address against a signature.
|
||||||
|
*
|
||||||
|
* @param addr Memory address to check.
|
||||||
|
* @param sig Signature used to check against memory address. Accept 0x2A as wildcard.
|
||||||
|
* @param len Length of signature.
|
||||||
|
* @return True if signature was verified, false otherwise.
|
||||||
|
*/
|
||||||
|
bool UTIL_VerifySignature(const void *addr, const char *sig, size_t len);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Returns the original function address of a given virtual function.
|
||||||
|
*
|
||||||
|
* @param mfp Member function pointer to virtual function.
|
||||||
|
* @param ptr Pointer to interface in which the virtual function belongs.
|
||||||
|
* @param cls A CallClass for the interface in which the virtual function belongs.
|
||||||
|
* @return Address of function originally pointed to by the virtual function.
|
||||||
|
*/
|
||||||
|
template <class MFP, class Iface>
|
||||||
|
char *UTIL_GetOrigFunction(MFP vfunc, Iface *ptr, SourceHook::CallClass<Iface> *cls)
|
||||||
|
{
|
||||||
|
SourceHook::MemFuncInfo info = {true, -1, 0, 0};
|
||||||
|
SourceHook::GetFuncInfo(vfunc, info);
|
||||||
|
|
||||||
|
/* Get address of original GetUserMessageInfo() */
|
||||||
|
char *func = reinterpret_cast<char *>(cls->GetOrigFunc(info.vtbloffs, info.vtblindex));
|
||||||
|
|
||||||
|
/* If we can't get original function, that means there's no hook */
|
||||||
|
if (func == NULL)
|
||||||
{
|
{
|
||||||
len = maxlength - 1;
|
/* Get virtual function address 'manually' then */
|
||||||
buffer[len] = '\0';
|
char *adjustedptr = reinterpret_cast<char *>(ptr) + info.vtbloffs + info.vtbloffs;
|
||||||
|
char **vtable = *reinterpret_cast<char ***>(adjustedptr);
|
||||||
|
|
||||||
|
func = vtable[info.vtblindex];
|
||||||
}
|
}
|
||||||
|
|
||||||
return len;
|
/* Check for relative jumps */
|
||||||
|
if (func[0] == IA32_JMP_IMM32)
|
||||||
|
{
|
||||||
|
/* Get address from displacement...
|
||||||
|
*
|
||||||
|
* Add 5 because it's relative to next instruction:
|
||||||
|
* Opcode <1 byte> + 32-bit displacement <4 bytes>
|
||||||
|
*/
|
||||||
|
func += *reinterpret_cast<unsigned long *>(func + 1) + 5;
|
||||||
|
}
|
||||||
|
|
||||||
|
return func;
|
||||||
}
|
}
|
||||||
|
|
||||||
#endif //_INCLUDE_UTIL_H
|
#endif //_INCLUDE_UTIL_H
|
||||||
|
@ -47,7 +47,7 @@ BEGIN
|
|||||||
VALUE "FileDescription", "Metamod: Source"
|
VALUE "FileDescription", "Metamod: Source"
|
||||||
VALUE "FileVersion", SVN_FILE_VERSION_STRING
|
VALUE "FileVersion", SVN_FILE_VERSION_STRING
|
||||||
VALUE "InternalName", "sourcemm"
|
VALUE "InternalName", "sourcemm"
|
||||||
VALUE "LegalCopyright", "Copyright (c) 2004-2007, Metamod: Source Development Team"
|
VALUE "LegalCopyright", "Copyright (c) 2004-2008, Metamod: Source Development Team"
|
||||||
VALUE "OriginalFilename", "server.dll"
|
VALUE "OriginalFilename", "server.dll"
|
||||||
VALUE "ProductName", "Metamod: Source"
|
VALUE "ProductName", "Metamod: Source"
|
||||||
VALUE "ProductVersion", SVN_PRODUCT_VERSION
|
VALUE "ProductVersion", SVN_PRODUCT_VERSION
|
||||||
@ -99,3 +99,4 @@ END
|
|||||||
|
|
||||||
/////////////////////////////////////////////////////////////////////////////
|
/////////////////////////////////////////////////////////////////////////////
|
||||||
#endif // not APSTUDIO_INVOKED
|
#endif // not APSTUDIO_INVOKED
|
||||||
|
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
/* ======== SourceMM ========
|
/* ======== SourceMM ========
|
||||||
* Copyright (C) 2004-2007 Metamod:Source Development Team
|
* Copyright (C) 2004-2008 Metamod:Source Development Team
|
||||||
* No warranties of any kind
|
* No warranties of any kind
|
||||||
*
|
*
|
||||||
* License: zlib/libpng
|
* License: zlib/libpng
|
||||||
@ -10,15 +10,31 @@
|
|||||||
|
|
||||||
#include "vsp_listener.h"
|
#include "vsp_listener.h"
|
||||||
#include "CPlugin.h"
|
#include "CPlugin.h"
|
||||||
|
#include "concommands.h"
|
||||||
|
|
||||||
|
SH_DECL_HOOK0_void(ConCommand, Dispatch, SH_NOATTRIB, false);
|
||||||
|
|
||||||
using namespace SourceMM;
|
using namespace SourceMM;
|
||||||
|
|
||||||
VSPListener g_VspListener;
|
VSPListener g_VspListener;
|
||||||
|
ConCommand *g_plugin_unload = NULL;
|
||||||
|
bool g_bIsTryingToUnload;
|
||||||
|
|
||||||
|
void InterceptPluginUnloads()
|
||||||
|
{
|
||||||
|
g_bIsTryingToUnload = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
void InterceptPluginUnloads_Post()
|
||||||
|
{
|
||||||
|
g_bIsTryingToUnload = false;
|
||||||
|
}
|
||||||
|
|
||||||
VSPListener::VSPListener()
|
VSPListener::VSPListener()
|
||||||
{
|
{
|
||||||
m_Loaded = false;
|
m_Loaded = false;
|
||||||
m_Loadable = false;
|
m_Loadable = false;
|
||||||
|
m_bIsRootLoadMethod = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
void VSPListener::ClientActive(edict_t *pEntity)
|
void VSPListener::ClientActive(edict_t *pEntity)
|
||||||
@ -92,6 +108,25 @@ void VSPListener::ServerActivate(edict_t *pEdictList, int edictCount, int client
|
|||||||
|
|
||||||
void VSPListener::Unload()
|
void VSPListener::Unload()
|
||||||
{
|
{
|
||||||
|
if (g_bIsTryingToUnload)
|
||||||
|
{
|
||||||
|
Error("Metamod:Source cannot be unloaded from VSP mode. Use \"meta unload\" to unload specific plugins.\n");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
if (IsRootLoadMethod())
|
||||||
|
{
|
||||||
|
if (g_plugin_unload != NULL)
|
||||||
|
{
|
||||||
|
SH_REMOVE_HOOK_STATICFUNC(ConCommand, Dispatch, g_plugin_unload, InterceptPluginUnloads, false);
|
||||||
|
SH_REMOVE_HOOK_STATICFUNC(ConCommand, Dispatch, g_plugin_unload, InterceptPluginUnloads_Post, true);
|
||||||
|
g_plugin_unload = NULL;
|
||||||
|
}
|
||||||
|
g_SMConVarAccessor.UnloadMetamodCommands();
|
||||||
|
UnloadMetamod(false);
|
||||||
|
}
|
||||||
|
m_Loadable = true;
|
||||||
|
m_Loaded = false;
|
||||||
|
m_bIsRootLoadMethod = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
void VSPListener::SetLoadable(bool set)
|
void VSPListener::SetLoadable(bool set)
|
||||||
@ -99,53 +134,60 @@ void VSPListener::SetLoadable(bool set)
|
|||||||
m_Loadable = set;
|
m_Loadable = set;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool VSPListener::IsRootLoadMethod()
|
||||||
|
{
|
||||||
|
return m_bIsRootLoadMethod;
|
||||||
|
}
|
||||||
|
|
||||||
bool VSPListener::Load(CreateInterfaceFn interfaceFactory, CreateInterfaceFn gameServerFactory)
|
bool VSPListener::Load(CreateInterfaceFn interfaceFactory, CreateInterfaceFn gameServerFactory)
|
||||||
{
|
{
|
||||||
if (!g_GameDll.loaded)
|
|
||||||
{
|
|
||||||
Error("Metamod:Source is not a Valve Server Plugin\n");
|
|
||||||
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!m_Loadable)
|
|
||||||
{
|
|
||||||
Warning("Do not manually load Metamod:Source as a Valve Server Plugin\n");
|
|
||||||
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (m_Loaded)
|
if (m_Loaded)
|
||||||
{
|
{
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (!m_Loadable && !g_GameDll.loaded)
|
||||||
|
{
|
||||||
|
/* New loading mechanism, do a bunch o' stuff! */
|
||||||
|
m_bIsRootLoadMethod = true;
|
||||||
|
m_Loaded = true;
|
||||||
|
SetLoadable(false);
|
||||||
|
if (!AlternatelyLoadMetamod(interfaceFactory, gameServerFactory))
|
||||||
|
{
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
ConCommandBase *pBase = g_Engine.icvar->GetCommands();
|
||||||
|
while (pBase != NULL)
|
||||||
|
{
|
||||||
|
if (pBase->IsCommand() && strcmp(pBase->GetName(), "plugin_unload") == 0)
|
||||||
|
{
|
||||||
|
g_plugin_unload = (ConCommand *)pBase;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
pBase = const_cast<ConCommandBase *>(pBase->GetNext());
|
||||||
|
}
|
||||||
|
|
||||||
|
if (g_plugin_unload != NULL)
|
||||||
|
{
|
||||||
|
SH_ADD_HOOK_STATICFUNC(ConCommand, Dispatch, g_plugin_unload, InterceptPluginUnloads, false);
|
||||||
|
SH_ADD_HOOK_STATICFUNC(ConCommand, Dispatch, g_plugin_unload, InterceptPluginUnloads_Post, true);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Ho ho ho... if we get here, set a new cvar version. */
|
||||||
|
extern ConVar metamod_version;
|
||||||
|
char buffer[255];
|
||||||
|
|
||||||
|
UTIL_Format(buffer, sizeof(buffer), "%sV", metamod_version.GetString());
|
||||||
|
metamod_version.SetValue(buffer);
|
||||||
|
}
|
||||||
|
|
||||||
m_Loaded = true;
|
m_Loaded = true;
|
||||||
SetLoadable(false);
|
SetLoadable(false);
|
||||||
|
|
||||||
PluginIter iter;
|
if (!m_bIsRootLoadMethod)
|
||||||
CPluginManager::CPlugin *pPlugin;
|
|
||||||
SourceHook::List<IMetamodListener *>::iterator event;
|
|
||||||
IMetamodListener *pML;
|
|
||||||
for (iter=g_PluginMngr._begin(); iter!=g_PluginMngr._end(); iter++)
|
|
||||||
{
|
{
|
||||||
pPlugin = (*iter);
|
g_PluginMngr.SetVSPAsLoaded();
|
||||||
if (pPlugin->m_Status < Pl_Paused)
|
|
||||||
{
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
/* Only valid for plugins >= 10 (v1:5, SourceMM 1.4) */
|
|
||||||
if (pPlugin->m_API->GetApiVersion() < 10)
|
|
||||||
{
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
for (event=pPlugin->m_Events.begin();
|
|
||||||
event!=pPlugin->m_Events.end();
|
|
||||||
event++)
|
|
||||||
{
|
|
||||||
pML = (*event);
|
|
||||||
pML->OnVSPListening(this);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
/* ======== SourceMM ========
|
/* ======== SourceMM ========
|
||||||
* Copyright (C) 2004-2007 Metamod:Source Development Team
|
* Copyright (C) 2004-2008 Metamod:Source Development Team
|
||||||
* No warranties of any kind
|
* No warranties of any kind
|
||||||
*
|
*
|
||||||
* License: zlib/libpng
|
* License: zlib/libpng
|
||||||
@ -39,9 +39,11 @@ public:
|
|||||||
public:
|
public:
|
||||||
bool IsLoaded();
|
bool IsLoaded();
|
||||||
void SetLoadable(bool loadable);
|
void SetLoadable(bool loadable);
|
||||||
|
bool IsRootLoadMethod();
|
||||||
private:
|
private:
|
||||||
bool m_Loaded;
|
bool m_Loaded;
|
||||||
bool m_Loadable;
|
bool m_Loadable;
|
||||||
|
bool m_bIsRootLoadMethod;
|
||||||
};
|
};
|
||||||
|
|
||||||
extern VSPListener g_VspListener;
|
extern VSPListener g_VspListener;
|
||||||
|
@ -1,68 +0,0 @@
|
|||||||
#(C)2004-2007 SourceMM Development Team
|
|
||||||
# Makefile written by David "BAILOPAN" Anderson
|
|
||||||
|
|
||||||
HL2SDK = ../../hl2sdk
|
|
||||||
SMM_ROOT = ..
|
|
||||||
SRCDS = ~/srcds
|
|
||||||
|
|
||||||
### EDIT BELOW FOR OTHER PROJECTS ###
|
|
||||||
|
|
||||||
OPT_FLAGS = -O2 -funroll-loops -s -pipe
|
|
||||||
GCC4_FLAGS = -fvisibility=hidden -fvisibility-inlines-hidden
|
|
||||||
DEBUG_FLAGS = -g -ggdb3
|
|
||||||
CPP = gcc-4.1
|
|
||||||
BINARY = sourcemm_update_tool_i486.so
|
|
||||||
|
|
||||||
HL2PUB = $(HL2SDK)/public
|
|
||||||
HL2LIB = $(HL2SDK)/linux_sdk
|
|
||||||
|
|
||||||
OBJECTS = update_tool.cpp
|
|
||||||
|
|
||||||
LINK = vstdlib_i486.so tier0_i486.so -static-libgcc
|
|
||||||
|
|
||||||
INCLUDE = -I. -I$(HL2PUB) -I$(HL2PUB)/dlls -I$(HL2PUB)/engine -I$(HL2PUB)/tier0 -I$(HL2PUB)/tier1 \
|
|
||||||
-I$(HL2PUB)/vstdlib -I$(HL2SDK)/tier1 -I$(SMM_ROOT) -I$(SMM_ROOT)/sourcehook
|
|
||||||
|
|
||||||
ifeq "$(DEBUG)" "true"
|
|
||||||
BIN_DIR = Debug
|
|
||||||
CFLAGS = $(DEBUG_FLAGS)
|
|
||||||
else
|
|
||||||
BIN_DIR = Release
|
|
||||||
CFLAGS = $(OPT_FLAGS)
|
|
||||||
endif
|
|
||||||
|
|
||||||
GCC_VERSION := $(shell $(CPP) -dumpversion >&1 | cut -b1)
|
|
||||||
|
|
||||||
CFLAGS += -D_LINUX -DNDEBUG -Dstricmp=strcasecmp -D_stricmp=strcasecmp -D_strnicmp=strncasecmp -Dstrnicmp=strncasecmp -D_snprintf=snprintf -D_vsnprintf=vsnprintf -D_alloca=alloca -Dstrcmpi=strcasecmp -Wall -Wno-non-virtual-dtor -Werror -fPIC -fno-exceptions -fno-rtti -msse
|
|
||||||
|
|
||||||
ifeq "$(GCC_VERSION)" "4"
|
|
||||||
CFLAGS += $(GCC4_FLAGS)
|
|
||||||
endif
|
|
||||||
|
|
||||||
OBJ_LINUX := $(OBJECTS:%.cpp=$(BIN_DIR)/%.o)
|
|
||||||
|
|
||||||
$(BIN_DIR)/%.o: %.cpp
|
|
||||||
$(CPP) $(INCLUDE) $(CFLAGS) -o $@ -c $<
|
|
||||||
|
|
||||||
all:
|
|
||||||
mkdir -p $(BIN_DIR)
|
|
||||||
ln -sf $(SRCDS)/bin/tier0_i486.so tier0_i486.so
|
|
||||||
ln -sf $(SRCDS)/bin/vstdlib_i486.so vstdlib_i486.so
|
|
||||||
nasm api_link.asm -f elf -o $(BIN_DIR)/api_link.o -DLINUX
|
|
||||||
$(MAKE) sourcemm
|
|
||||||
rm -rf $(BINARY)
|
|
||||||
ln -sf $(BIN_DIR)/$(BINARY) $(BINARY)
|
|
||||||
|
|
||||||
sourcemm: $(OBJ_LINUX)
|
|
||||||
$(CPP) $(INCLUDE) $(CFLAGS) $(OBJ_LINUX) $(BIN_DIR)/api_link.o $(LINK) -shared -ldl -lm -o$(BIN_DIR)/$(BINARY)
|
|
||||||
|
|
||||||
debug:
|
|
||||||
$(MAKE) all DEBUG=true
|
|
||||||
|
|
||||||
default: all
|
|
||||||
|
|
||||||
clean:
|
|
||||||
rm -rf Release/*.o
|
|
||||||
rm -rf Release/$(BINARY)
|
|
||||||
rm -rf Debug/*.o
|
|
||||||
rm -rf Debug/$(BINARY)
|
|
@ -1,90 +0,0 @@
|
|||||||
This is the README file for sourcemm_update_tool.
|
|
||||||
|
|
||||||
This tool will automatically correct gameinfo.txt when your server gets updated, and Valve's updater overwrites Metamod:Source's changes. This tool is experimental, and is thus a separate download for now.
|
|
||||||
|
|
||||||
1. INSTALLATION
|
|
||||||
|
|
||||||
a. Extract the entire package to your mod folder. The structure should look like:
|
|
||||||
|
|
||||||
<mod>/addons/metamod/bin/sourcemm_update_tool.dll
|
|
||||||
<mod>/addons/metamod/bin/sourcemm_update_tool_i486.so
|
|
||||||
<mod>/addons/metamod/README.txt
|
|
||||||
<mod>/addons/sourcemm_update_tool.vdf
|
|
||||||
<mod>/sourcemm_updater.conf
|
|
||||||
|
|
||||||
b. Open <mod>/sourcemm_updater.conf with your favorite text editor. Change the
|
|
||||||
"cstrike" folder to match your mod folder.
|
|
||||||
|
|
||||||
2. CONFIGURATION
|
|
||||||
|
|
||||||
The sourcemm_updater.conf file has two configuration options.
|
|
||||||
|
|
||||||
mmpath - Set this to the path Metamod:Source is located in.
|
|
||||||
This defaults to addons/metamod/bin
|
|
||||||
restart - Set this to how the server should be restarted when
|
|
||||||
gameinfo.txt is patched. There are three options:
|
|
||||||
|
|
||||||
quit - Execute "quit" in the console. Currently does not work.
|
|
||||||
never - Do not restart.
|
|
||||||
error - Generate an error message. Because of a bug in SourceDS,
|
|
||||||
this will generate a crash dump on Windows, but the server
|
|
||||||
will successfully quit.
|
|
||||||
|
|
||||||
3. USAGE
|
|
||||||
|
|
||||||
You do not need to do anything to use the updater tool. When your server starts,
|
|
||||||
it silently checks to see if Metamod:Source is loaded. If not, it will make sure
|
|
||||||
gameinfo.txt is correctly set. Then, depending on how it's configured, it will
|
|
||||||
kill the server. Most game server provides have auto-restart functionality on their
|
|
||||||
servers; if not, you will need to manually restart the server.
|
|
||||||
|
|
||||||
The update tool unloads itself immediately after the server starts, so it will not
|
|
||||||
use any resources, and will not display when you type 'plugin_print'.
|
|
||||||
|
|
||||||
4. TROUBLESHOOTING
|
|
||||||
|
|
||||||
This tool is currently experimental. There are two possible problems. For
|
|
||||||
any issue you encounter, you should post a report here:
|
|
||||||
|
|
||||||
http://bugs.alliedmods.net/index.php?project=4
|
|
||||||
|
|
||||||
a. The updater tool does not patch gameinfo.txt
|
|
||||||
|
|
||||||
Verify that the tool is loading. You can do this by opening up the
|
|
||||||
sourcemm_update_tool.vdf file and copying its file path. Then, enter
|
|
||||||
the following command in your server console:
|
|
||||||
|
|
||||||
plugin_load <path>
|
|
||||||
|
|
||||||
Example:
|
|
||||||
|
|
||||||
plugin_load cstrike\addons\metamod\bin\sourcemm_update_tool
|
|
||||||
|
|
||||||
If you get the following reply:
|
|
||||||
|
|
||||||
Failed to load plugin "cstrike\addons\sourcemm_update_tool"
|
|
||||||
Unable to load plugin "cstrike\addons\sourcemm_update_tool"
|
|
||||||
|
|
||||||
Then the tool is working, and you should post a bug report. If instead,
|
|
||||||
you get:
|
|
||||||
|
|
||||||
Unable to load plugin "cstrike\addons\sourcemm_update_tool"
|
|
||||||
Unable to load plugin "cstrike\addons\sourcemm_update_tool"
|
|
||||||
|
|
||||||
Then the tool is not loading properly, and the path you are trying to use
|
|
||||||
is not correct.
|
|
||||||
|
|
||||||
b. The server always dies, and you can't start it at all
|
|
||||||
|
|
||||||
The updater tool is either crashing or not repairing Metamod:Source
|
|
||||||
correctly. First, try changing the 'restart' line in sourcemm_updater.conf
|
|
||||||
to the following line:
|
|
||||||
|
|
||||||
restart = never
|
|
||||||
|
|
||||||
If that does not fix the problem, remove the .vdf file so the updater tool
|
|
||||||
will not be loaded.
|
|
||||||
|
|
||||||
In either case, you should post a bug report containing your mod name and
|
|
||||||
your gameinfo.txt as an attachment.
|
|
||||||
|
|
@ -1,138 +0,0 @@
|
|||||||
;;;;
|
|
||||||
;; (C)2005-2007 AlliedModders LLC
|
|
||||||
;; By the Metamod:Source Development Team
|
|
||||||
;; This software is licensed under the zlib/libpng free software license.
|
|
||||||
;;
|
|
||||||
;; This assembly file is a short thunk wrapper to let us load as a VSP and exit quietly,
|
|
||||||
;; without any overhead of the rest of the interface, and also to prevent linking against
|
|
||||||
;; tierX or vstdlib
|
|
||||||
;;;;
|
|
||||||
|
|
||||||
;;Exports:
|
|
||||||
;; void GetBaseDir(char *buffer, maxlength);
|
|
||||||
;; void *GetThisPointer();
|
|
||||||
;;Imports:
|
|
||||||
;; void LoadFunction();
|
|
||||||
|
|
||||||
section .text
|
|
||||||
|
|
||||||
global GetThisPointer, GetGameDir, ServerCommand
|
|
||||||
global _GetThisPointer, _GetGameDir, _ServerCommand
|
|
||||||
global _GetICvar, GetICvar
|
|
||||||
extern _LoadFunction
|
|
||||||
|
|
||||||
GetICvar:
|
|
||||||
_GetICvar:
|
|
||||||
mov eax, [icvar]
|
|
||||||
ret
|
|
||||||
|
|
||||||
GetThisPointer:
|
|
||||||
_GetThisPointer:
|
|
||||||
mov eax, GLOBAL_POINTER
|
|
||||||
ret
|
|
||||||
|
|
||||||
GetGameDir:
|
|
||||||
_GetGameDir:
|
|
||||||
push ebp
|
|
||||||
mov ebp, esp
|
|
||||||
|
|
||||||
mov ecx, [engine] ;get this pointer
|
|
||||||
mov edx, [ecx] ;get the vtable
|
|
||||||
push dword [ebp+12] ;push maxlenth
|
|
||||||
push dword [ebp+8] ;push buffer
|
|
||||||
%ifdef LINUX
|
|
||||||
push ecx ;push this pointer
|
|
||||||
%endif
|
|
||||||
call dword [edx+216] ;call IVEngineServer::GetGameDir
|
|
||||||
%ifdef LINUX
|
|
||||||
add esp, 12 ;correct stack
|
|
||||||
%endif
|
|
||||||
|
|
||||||
pop ebp
|
|
||||||
ret
|
|
||||||
|
|
||||||
ServerCommand
|
|
||||||
_ServerCommand:
|
|
||||||
push ebp
|
|
||||||
mov ebp, esp
|
|
||||||
|
|
||||||
mov ecx, [engine] ;get this pointer
|
|
||||||
mov edx, [ecx] ;get the vtable
|
|
||||||
push dword [ebp+8] ;push string
|
|
||||||
%ifdef LINUX
|
|
||||||
push ecx ;push this pointer
|
|
||||||
%endif
|
|
||||||
call dword [edx+144] ;call IVEngineServer::ServerCommand
|
|
||||||
%ifdef LINUX
|
|
||||||
add esp, 8 ;correct stack
|
|
||||||
%endif
|
|
||||||
|
|
||||||
pop ebp
|
|
||||||
ret
|
|
||||||
|
|
||||||
thisLoadFunction:
|
|
||||||
push ebp
|
|
||||||
mov ebp, esp
|
|
||||||
|
|
||||||
push edi
|
|
||||||
|
|
||||||
;get factory
|
|
||||||
%ifdef LINUX
|
|
||||||
mov edi, [ebp+12]
|
|
||||||
%else
|
|
||||||
mov edi, [ebp+8]
|
|
||||||
%endif
|
|
||||||
|
|
||||||
push dword 0 ;NULL
|
|
||||||
push dword VENGINESERVER ;iface name
|
|
||||||
call edi ;call factory
|
|
||||||
add esp, 8 ;correct stack
|
|
||||||
|
|
||||||
test eax, eax ;do we have a valid pointer?
|
|
||||||
jz .end ;no, bail out
|
|
||||||
|
|
||||||
mov [engine], eax ;store the engine pointer
|
|
||||||
|
|
||||||
push dword 0 ;NULL
|
|
||||||
push dword VENGINECVAR ;iface name
|
|
||||||
call edi ;call factory
|
|
||||||
add esp, 8 ;correct stack
|
|
||||||
|
|
||||||
test eax, eax ;do we have a valid pointer?
|
|
||||||
jz .end ;no, bail out
|
|
||||||
|
|
||||||
mov [icvar], eax ;store the icvar pointer
|
|
||||||
|
|
||||||
call _LoadFunction
|
|
||||||
|
|
||||||
.end:
|
|
||||||
;We never load, never ever ever!
|
|
||||||
xor eax, eax
|
|
||||||
|
|
||||||
pop edi
|
|
||||||
|
|
||||||
pop ebp
|
|
||||||
%ifdef LINUX
|
|
||||||
ret
|
|
||||||
%else
|
|
||||||
retn 8
|
|
||||||
%endif
|
|
||||||
|
|
||||||
thisUnloadFunction:
|
|
||||||
ret
|
|
||||||
|
|
||||||
section .data
|
|
||||||
INTERFACE_NAME DB "ISERVERPLUGINCALLBACKS001", 0
|
|
||||||
VENGINESERVER DB "VEngineServer021", 0
|
|
||||||
VENGINECVAR DB "VEngineCvar003", 0
|
|
||||||
|
|
||||||
VIRTUAL_TABLE DD thisLoadFunction
|
|
||||||
DD thisUnloadFunction
|
|
||||||
;We don't need any more of the vtable here
|
|
||||||
|
|
||||||
GLOBAL_POINTER DD VIRTUAL_TABLE
|
|
||||||
|
|
||||||
temp_ret DD 0
|
|
||||||
temp_ptr DD temp_ret
|
|
||||||
engine DD 0
|
|
||||||
icvar DD 0
|
|
@ -1,20 +0,0 @@
|
|||||||
|
|
||||||
Microsoft Visual Studio Solution File, Format Version 9.00
|
|
||||||
# Visual Studio 2005
|
|
||||||
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "update_tool", "update_tool.vcproj", "{DDD1563F-7EE2-4E76-BE57-ED84A2664A51}"
|
|
||||||
EndProject
|
|
||||||
Global
|
|
||||||
GlobalSection(SolutionConfigurationPlatforms) = preSolution
|
|
||||||
Debug|Win32 = Debug|Win32
|
|
||||||
Release|Win32 = Release|Win32
|
|
||||||
EndGlobalSection
|
|
||||||
GlobalSection(ProjectConfigurationPlatforms) = postSolution
|
|
||||||
{DDD1563F-7EE2-4E76-BE57-ED84A2664A51}.Debug|Win32.ActiveCfg = Debug|Win32
|
|
||||||
{DDD1563F-7EE2-4E76-BE57-ED84A2664A51}.Debug|Win32.Build.0 = Debug|Win32
|
|
||||||
{DDD1563F-7EE2-4E76-BE57-ED84A2664A51}.Release|Win32.ActiveCfg = Release|Win32
|
|
||||||
{DDD1563F-7EE2-4E76-BE57-ED84A2664A51}.Release|Win32.Build.0 = Release|Win32
|
|
||||||
EndGlobalSection
|
|
||||||
GlobalSection(SolutionProperties) = preSolution
|
|
||||||
HideSolutionNode = FALSE
|
|
||||||
EndGlobalSection
|
|
||||||
EndGlobal
|
|
@ -1,203 +0,0 @@
|
|||||||
<?xml version="1.0" encoding="Windows-1252"?>
|
|
||||||
<VisualStudioProject
|
|
||||||
ProjectType="Visual C++"
|
|
||||||
Version="8.00"
|
|
||||||
Name="update_tool"
|
|
||||||
ProjectGUID="{DDD1563F-7EE2-4E76-BE57-ED84A2664A51}"
|
|
||||||
RootNamespace="update_tool"
|
|
||||||
Keyword="Win32Proj"
|
|
||||||
>
|
|
||||||
<Platforms>
|
|
||||||
<Platform
|
|
||||||
Name="Win32"
|
|
||||||
/>
|
|
||||||
</Platforms>
|
|
||||||
<ToolFiles>
|
|
||||||
</ToolFiles>
|
|
||||||
<Configurations>
|
|
||||||
<Configuration
|
|
||||||
Name="Debug|Win32"
|
|
||||||
OutputDirectory="$(SolutionDir)$(ConfigurationName)"
|
|
||||||
IntermediateDirectory="$(ConfigurationName)"
|
|
||||||
ConfigurationType="2"
|
|
||||||
CharacterSet="2"
|
|
||||||
>
|
|
||||||
<Tool
|
|
||||||
Name="VCPreBuildEventTool"
|
|
||||||
CommandLine="nasmw ..\api_link.asm -f win32 -oDebug\api_link.obj -DWIN32"
|
|
||||||
/>
|
|
||||||
<Tool
|
|
||||||
Name="VCCustomBuildTool"
|
|
||||||
/>
|
|
||||||
<Tool
|
|
||||||
Name="VCXMLDataGeneratorTool"
|
|
||||||
/>
|
|
||||||
<Tool
|
|
||||||
Name="VCWebServiceProxyGeneratorTool"
|
|
||||||
/>
|
|
||||||
<Tool
|
|
||||||
Name="VCMIDLTool"
|
|
||||||
/>
|
|
||||||
<Tool
|
|
||||||
Name="VCCLCompilerTool"
|
|
||||||
Optimization="0"
|
|
||||||
PreprocessorDefinitions="WIN32;_DEBUG;_WINDOWS;_USRDLL;UPDATE_TOOL_EXPORTS;_CRT_SECURE_NO_DEPRECATE;_CRT_STD_NO_DEPRECATE"
|
|
||||||
MinimalRebuild="true"
|
|
||||||
BasicRuntimeChecks="3"
|
|
||||||
RuntimeLibrary="1"
|
|
||||||
UsePrecompiledHeader="0"
|
|
||||||
WarningLevel="3"
|
|
||||||
Detect64BitPortabilityProblems="true"
|
|
||||||
DebugInformationFormat="4"
|
|
||||||
/>
|
|
||||||
<Tool
|
|
||||||
Name="VCManagedResourceCompilerTool"
|
|
||||||
/>
|
|
||||||
<Tool
|
|
||||||
Name="VCResourceCompilerTool"
|
|
||||||
/>
|
|
||||||
<Tool
|
|
||||||
Name="VCPreLinkEventTool"
|
|
||||||
/>
|
|
||||||
<Tool
|
|
||||||
Name="VCLinkerTool"
|
|
||||||
AdditionalDependencies="Debug\api_link.obj tier0.lib"
|
|
||||||
OutputFile="$(OutDir)\sourcemm_update_tool.dll"
|
|
||||||
LinkIncremental="2"
|
|
||||||
GenerateDebugInformation="true"
|
|
||||||
SubSystem="2"
|
|
||||||
TargetMachine="1"
|
|
||||||
/>
|
|
||||||
<Tool
|
|
||||||
Name="VCALinkTool"
|
|
||||||
/>
|
|
||||||
<Tool
|
|
||||||
Name="VCManifestTool"
|
|
||||||
/>
|
|
||||||
<Tool
|
|
||||||
Name="VCXDCMakeTool"
|
|
||||||
/>
|
|
||||||
<Tool
|
|
||||||
Name="VCBscMakeTool"
|
|
||||||
/>
|
|
||||||
<Tool
|
|
||||||
Name="VCFxCopTool"
|
|
||||||
/>
|
|
||||||
<Tool
|
|
||||||
Name="VCAppVerifierTool"
|
|
||||||
/>
|
|
||||||
<Tool
|
|
||||||
Name="VCWebDeploymentTool"
|
|
||||||
/>
|
|
||||||
<Tool
|
|
||||||
Name="VCPostBuildEventTool"
|
|
||||||
/>
|
|
||||||
</Configuration>
|
|
||||||
<Configuration
|
|
||||||
Name="Release|Win32"
|
|
||||||
OutputDirectory="$(SolutionDir)$(ConfigurationName)"
|
|
||||||
IntermediateDirectory="$(ConfigurationName)"
|
|
||||||
ConfigurationType="2"
|
|
||||||
CharacterSet="2"
|
|
||||||
WholeProgramOptimization="1"
|
|
||||||
>
|
|
||||||
<Tool
|
|
||||||
Name="VCPreBuildEventTool"
|
|
||||||
CommandLine="nasmw ..\api_link.asm -f win32 -oRelease\api_link.obj -DWIN32"
|
|
||||||
/>
|
|
||||||
<Tool
|
|
||||||
Name="VCCustomBuildTool"
|
|
||||||
/>
|
|
||||||
<Tool
|
|
||||||
Name="VCXMLDataGeneratorTool"
|
|
||||||
/>
|
|
||||||
<Tool
|
|
||||||
Name="VCWebServiceProxyGeneratorTool"
|
|
||||||
/>
|
|
||||||
<Tool
|
|
||||||
Name="VCMIDLTool"
|
|
||||||
/>
|
|
||||||
<Tool
|
|
||||||
Name="VCCLCompilerTool"
|
|
||||||
PreprocessorDefinitions="WIN32;NDEBUG;_WINDOWS;_USRDLL;UPDATE_TOOL_EXPORTS;_CRT_SECURE_NO_DEPRECATE"
|
|
||||||
RuntimeLibrary="0"
|
|
||||||
UsePrecompiledHeader="0"
|
|
||||||
WarningLevel="3"
|
|
||||||
Detect64BitPortabilityProblems="true"
|
|
||||||
DebugInformationFormat="3"
|
|
||||||
/>
|
|
||||||
<Tool
|
|
||||||
Name="VCManagedResourceCompilerTool"
|
|
||||||
/>
|
|
||||||
<Tool
|
|
||||||
Name="VCResourceCompilerTool"
|
|
||||||
/>
|
|
||||||
<Tool
|
|
||||||
Name="VCPreLinkEventTool"
|
|
||||||
/>
|
|
||||||
<Tool
|
|
||||||
Name="VCLinkerTool"
|
|
||||||
AdditionalDependencies="Release\api_link.obj tier0.lib"
|
|
||||||
OutputFile="$(OutDir)\sourcemm_update_tool.dll"
|
|
||||||
LinkIncremental="1"
|
|
||||||
GenerateDebugInformation="true"
|
|
||||||
SubSystem="2"
|
|
||||||
OptimizeReferences="2"
|
|
||||||
EnableCOMDATFolding="2"
|
|
||||||
TargetMachine="1"
|
|
||||||
/>
|
|
||||||
<Tool
|
|
||||||
Name="VCALinkTool"
|
|
||||||
/>
|
|
||||||
<Tool
|
|
||||||
Name="VCManifestTool"
|
|
||||||
/>
|
|
||||||
<Tool
|
|
||||||
Name="VCXDCMakeTool"
|
|
||||||
/>
|
|
||||||
<Tool
|
|
||||||
Name="VCBscMakeTool"
|
|
||||||
/>
|
|
||||||
<Tool
|
|
||||||
Name="VCFxCopTool"
|
|
||||||
/>
|
|
||||||
<Tool
|
|
||||||
Name="VCAppVerifierTool"
|
|
||||||
/>
|
|
||||||
<Tool
|
|
||||||
Name="VCWebDeploymentTool"
|
|
||||||
/>
|
|
||||||
<Tool
|
|
||||||
Name="VCPostBuildEventTool"
|
|
||||||
/>
|
|
||||||
</Configuration>
|
|
||||||
</Configurations>
|
|
||||||
<References>
|
|
||||||
</References>
|
|
||||||
<Files>
|
|
||||||
<Filter
|
|
||||||
Name="Source Files"
|
|
||||||
Filter="cpp;c;cc;cxx;def;odl;idl;hpj;bat;asm;asmx"
|
|
||||||
UniqueIdentifier="{4FC737F1-C7A5-4376-A066-2A32D752A2FF}"
|
|
||||||
>
|
|
||||||
<File
|
|
||||||
RelativePath="..\update_tool.cpp"
|
|
||||||
>
|
|
||||||
</File>
|
|
||||||
</Filter>
|
|
||||||
<Filter
|
|
||||||
Name="Header Files"
|
|
||||||
Filter="h;hpp;hxx;hm;inl;inc;xsd"
|
|
||||||
UniqueIdentifier="{93995380-89BD-4b04-88EB-625FBE52EBFB}"
|
|
||||||
>
|
|
||||||
</Filter>
|
|
||||||
<Filter
|
|
||||||
Name="Resource Files"
|
|
||||||
Filter="rc;ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe;resx;tiff;tif;png;wav"
|
|
||||||
UniqueIdentifier="{67DA6AB6-F800-4c08-8B7A-83BB121AAD01}"
|
|
||||||
>
|
|
||||||
</Filter>
|
|
||||||
</Files>
|
|
||||||
<Globals>
|
|
||||||
</Globals>
|
|
||||||
</VisualStudioProject>
|
|
@ -1,6 +0,0 @@
|
|||||||
//This is a sample VDF file. You need to edit "cstrike" to point to the mod you use.
|
|
||||||
|
|
||||||
"Plugin"
|
|
||||||
{
|
|
||||||
"file" "cstrike/addons/metamod/bin/sourcemm_update_tool"
|
|
||||||
}
|
|
@ -1,9 +0,0 @@
|
|||||||
;Use this to configure where Metamod resides, if you have
|
|
||||||
;changed its location
|
|
||||||
;mmpath = addons/metamod/bin
|
|
||||||
|
|
||||||
;Use this to specify how the updater tool restarts SourceDS
|
|
||||||
; never - don't restart
|
|
||||||
; error - restart by generating a fatal error message
|
|
||||||
; quit - restart by issuing a "quit" server command
|
|
||||||
restart = error
|
|
@ -1,366 +0,0 @@
|
|||||||
#include <stdio.h>
|
|
||||||
#include <stdarg.h>
|
|
||||||
#include <string.h>
|
|
||||||
#include <ctype.h>
|
|
||||||
|
|
||||||
#if defined _MSC_VER
|
|
||||||
#define SEPCHAR "\\"
|
|
||||||
#define MMPATH "addons\\metamod\\bin"
|
|
||||||
#define WINDOWS_LEAN_AND_MEAN
|
|
||||||
#include <windows.h>
|
|
||||||
#elif defined __linux__
|
|
||||||
#define SEPCHAR "/"
|
|
||||||
#define MMPATH "addons/metamod/bin"
|
|
||||||
#include <unistd.h>
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#include <icvar.h>
|
|
||||||
|
|
||||||
extern "C" void GetGameDir(char *buffer, int maxlength);
|
|
||||||
extern "C" void *GetThisPointer();
|
|
||||||
extern "C" void ServerCommand(const char *command);
|
|
||||||
extern "C" ICvar *GetICvar();
|
|
||||||
|
|
||||||
size_t UTIL_Format(char *buffer, size_t maxlength, const char *fmt, ...);
|
|
||||||
bool s_isspace(char c);
|
|
||||||
bool RenameFile(const char *old, const char *newf);
|
|
||||||
bool RemoveFile(const char *file);
|
|
||||||
|
|
||||||
/* This will be called by the thunk */
|
|
||||||
#if defined _MSC_VER
|
|
||||||
extern "C" void LoadFunction()
|
|
||||||
#elif defined __linux__
|
|
||||||
extern "C" void _LoadFunction()
|
|
||||||
#endif
|
|
||||||
{
|
|
||||||
ICvar *pCvar = GetICvar();
|
|
||||||
if (pCvar->FindVar("metamod_version") != NULL)
|
|
||||||
{
|
|
||||||
/* Already exists, bail out */
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
char gamedir[260];
|
|
||||||
char mmpath[260];
|
|
||||||
|
|
||||||
enum RestartMode
|
|
||||||
{
|
|
||||||
Restart_Never,
|
|
||||||
Restart_Error,
|
|
||||||
Restart_Quit,
|
|
||||||
};
|
|
||||||
|
|
||||||
RestartMode mode = Restart_Error;
|
|
||||||
|
|
||||||
GetGameDir(gamedir, sizeof(gamedir));
|
|
||||||
|
|
||||||
/* Defaults */
|
|
||||||
UTIL_Format(mmpath, sizeof(mmpath), "|gameinfo_path|%s", MMPATH);
|
|
||||||
|
|
||||||
/* Read config */
|
|
||||||
char config[260];
|
|
||||||
UTIL_Format(config, sizeof(config), "%s" SEPCHAR "sourcemm_updater.conf", gamedir);
|
|
||||||
FILE *fpCfg = fopen(config, "rt");
|
|
||||||
if (fpCfg)
|
|
||||||
{
|
|
||||||
char cfgLine[512];
|
|
||||||
while (!feof(fpCfg) && fgets(cfgLine, sizeof(cfgLine), fpCfg) != NULL)
|
|
||||||
{
|
|
||||||
char key[255];
|
|
||||||
|
|
||||||
size_t keyLen = 0;
|
|
||||||
|
|
||||||
/* Strip whitespace */
|
|
||||||
char *input = cfgLine;
|
|
||||||
while (*input != '\0' && s_isspace(*input))
|
|
||||||
{
|
|
||||||
input++;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Strip ending whitespace */
|
|
||||||
size_t len = strlen(input);
|
|
||||||
for (size_t i = len - 1;
|
|
||||||
i >= 0 && i < len;
|
|
||||||
i--)
|
|
||||||
{
|
|
||||||
if (s_isspace(input[i]))
|
|
||||||
{
|
|
||||||
input[i] = '\0';
|
|
||||||
len--;
|
|
||||||
} else {
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Eat stuff until we find a key */
|
|
||||||
while (*input != '\0' && !s_isspace(*input))
|
|
||||||
{
|
|
||||||
if (keyLen < sizeof(key))
|
|
||||||
{
|
|
||||||
key[keyLen++] = *input;
|
|
||||||
}
|
|
||||||
input++;
|
|
||||||
}
|
|
||||||
key[keyLen] = '\0';
|
|
||||||
|
|
||||||
/* Eat spaces until we hit an = sign */
|
|
||||||
while (*input != '\0' && *input != '=')
|
|
||||||
{
|
|
||||||
input++;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (*input == '=')
|
|
||||||
{
|
|
||||||
input++;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Eat spaces again */
|
|
||||||
while (*input != '\0' && s_isspace(*input))
|
|
||||||
{
|
|
||||||
input++;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Ignore comments */
|
|
||||||
if (key[0] == ';')
|
|
||||||
{
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* The rest is our key */
|
|
||||||
if (strcmp(key, "mmpath") == 0)
|
|
||||||
{
|
|
||||||
UTIL_Format(mmpath, sizeof(mmpath), "%s", input);
|
|
||||||
} else if (strcmp(key, "restart") == 0) {
|
|
||||||
if (strcmp(input, "never") == 0)
|
|
||||||
{
|
|
||||||
mode = Restart_Never;
|
|
||||||
} else if (strcmp(input, "error") == 0) {
|
|
||||||
mode = Restart_Error;
|
|
||||||
} else if (strcmp(input, "quit") == 0) {
|
|
||||||
mode = Restart_Quit;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
fclose(fpCfg);
|
|
||||||
}
|
|
||||||
|
|
||||||
char old_path[260];
|
|
||||||
char new_path[260];
|
|
||||||
|
|
||||||
UTIL_Format(old_path, sizeof(old_path), "%s" SEPCHAR "gameinfo.txt", gamedir);
|
|
||||||
UTIL_Format(new_path, sizeof(new_path), "%s" SEPCHAR "gameinfo.new.txt", gamedir);
|
|
||||||
|
|
||||||
FILE *fp = fopen(old_path, "rt");
|
|
||||||
|
|
||||||
if (!fp)
|
|
||||||
{
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
FILE *op = fopen(new_path, "wt");
|
|
||||||
if (!op)
|
|
||||||
{
|
|
||||||
fclose(fp);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
enum ParseState
|
|
||||||
{
|
|
||||||
Parse_None,
|
|
||||||
Parse_Root,
|
|
||||||
Parse_GameInfo,
|
|
||||||
Parse_FileSystem,
|
|
||||||
Parse_SearchPaths,
|
|
||||||
};
|
|
||||||
|
|
||||||
ParseState ps = Parse_Root;
|
|
||||||
|
|
||||||
char input[1024];
|
|
||||||
char backup[1024];
|
|
||||||
|
|
||||||
bool bWroteOutput = false;
|
|
||||||
|
|
||||||
while (!feof(fp) && fgets(input, sizeof(input), fp) != NULL)
|
|
||||||
{
|
|
||||||
UTIL_Format(backup, sizeof(backup), "%s", input);
|
|
||||||
|
|
||||||
if (ps != Parse_None)
|
|
||||||
{
|
|
||||||
char *inbuf = input;
|
|
||||||
|
|
||||||
/* Strip beginning whitespace */
|
|
||||||
while (*inbuf != '\0' && s_isspace(*inbuf))
|
|
||||||
{
|
|
||||||
inbuf++;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Strip ending whitespace */
|
|
||||||
size_t len = strlen(inbuf);
|
|
||||||
for (size_t i = len - 1;
|
|
||||||
i >= 0 && i < len;
|
|
||||||
i--)
|
|
||||||
{
|
|
||||||
if (s_isspace(inbuf[i]))
|
|
||||||
{
|
|
||||||
inbuf[i] = '\0';
|
|
||||||
len--;
|
|
||||||
} else {
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Strip quotation marks */
|
|
||||||
if (inbuf[0] == '"'
|
|
||||||
&& inbuf[len-1] == '"')
|
|
||||||
{
|
|
||||||
inbuf[len - 1] = '\0';
|
|
||||||
inbuf = &inbuf[1];
|
|
||||||
len -= 2;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Do tests */
|
|
||||||
if (ps == Parse_Root && strcmp(inbuf, "GameInfo") == 0)
|
|
||||||
{
|
|
||||||
ps = Parse_GameInfo;
|
|
||||||
} else if (ps == Parse_GameInfo && strcmp(inbuf, "FileSystem") == 0) {
|
|
||||||
ps = Parse_FileSystem;
|
|
||||||
} else if (ps == Parse_FileSystem && strcmp(inbuf, "SearchPaths") == 0) {
|
|
||||||
ps = Parse_SearchPaths;
|
|
||||||
} else if (ps == Parse_SearchPaths) {
|
|
||||||
const char *game = strstr(inbuf, "Game");
|
|
||||||
if (game)
|
|
||||||
{
|
|
||||||
if (strstr(game, "GameBin") != NULL
|
|
||||||
&& strstr(game, mmpath) != NULL)
|
|
||||||
{
|
|
||||||
fclose(op);
|
|
||||||
op = NULL;
|
|
||||||
break; /* Nothing more to do! */
|
|
||||||
} else {
|
|
||||||
fputs("\t\t\tGameBin\t\t\t", op);
|
|
||||||
fputs(mmpath, op);
|
|
||||||
fputs("\n", op);
|
|
||||||
ps = Parse_None;
|
|
||||||
bWroteOutput = true;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
fputs(backup, op);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!op)
|
|
||||||
{
|
|
||||||
/* Well, we can't really do anything else. Give up. */
|
|
||||||
fclose(fp);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Close all streams */
|
|
||||||
fclose(op);
|
|
||||||
fclose(fp);
|
|
||||||
|
|
||||||
/* If we didn't change anything, abort here */
|
|
||||||
if (!bWroteOutput)
|
|
||||||
{
|
|
||||||
RemoveFile(new_path);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Move the old file to a backup name */
|
|
||||||
char backup_name[260];
|
|
||||||
UTIL_Format(backup_name, sizeof(backup_name), "%s" SEPCHAR "gameinfo.backup.txt", gamedir);
|
|
||||||
|
|
||||||
if (!RenameFile(old_path, backup_name))
|
|
||||||
{
|
|
||||||
/* If we can't rename, just bail out.
|
|
||||||
* We don't want to overwrite the client's default
|
|
||||||
* without backing it up first!
|
|
||||||
*/
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
if (!RenameFile(new_path, old_path))
|
|
||||||
{
|
|
||||||
/* Since this failed, we really have no choice.
|
|
||||||
* Try and rename the old back.
|
|
||||||
*/
|
|
||||||
RenameFile(backup_name, old_path);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
RemoveFile(new_path);
|
|
||||||
|
|
||||||
if (mode == Restart_Error)
|
|
||||||
{
|
|
||||||
Error("Server is restarting to load Metamod:Source");
|
|
||||||
} else if (mode == Restart_Quit) {
|
|
||||||
ServerCommand("quit\n");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
bool RemoveFile(const char *file)
|
|
||||||
{
|
|
||||||
#if defined _MSC_VER
|
|
||||||
return (_unlink(file) == 0);
|
|
||||||
#else
|
|
||||||
return (unlink(file) == 0);
|
|
||||||
#endif
|
|
||||||
}
|
|
||||||
|
|
||||||
bool s_isspace(char c)
|
|
||||||
{
|
|
||||||
if ((unsigned)c & 0x80)
|
|
||||||
{
|
|
||||||
return false;
|
|
||||||
} else {
|
|
||||||
return isspace(c) ? true : false;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
size_t UTIL_Format(char *buffer, size_t maxlength, const char *fmt, ...)
|
|
||||||
{
|
|
||||||
va_list ap;
|
|
||||||
|
|
||||||
va_start(ap, fmt);
|
|
||||||
size_t len = vsnprintf(buffer, maxlength, fmt, ap);
|
|
||||||
va_end(ap);
|
|
||||||
|
|
||||||
if (len >= maxlength)
|
|
||||||
{
|
|
||||||
len = maxlength - 1;
|
|
||||||
buffer[len] = '\0';
|
|
||||||
}
|
|
||||||
|
|
||||||
return len;
|
|
||||||
}
|
|
||||||
|
|
||||||
bool RenameFile(const char *old, const char *newf)
|
|
||||||
{
|
|
||||||
#if defined __linux__
|
|
||||||
return (rename(old, newf) == 0);
|
|
||||||
#elif defined WIN32
|
|
||||||
return (MoveFileA(old, newf) != 0);
|
|
||||||
#endif
|
|
||||||
}
|
|
||||||
|
|
||||||
#if defined _MSC_VER
|
|
||||||
extern "C" __declspec(dllexport) void *CreateInterface(const char *iface, int *ret)
|
|
||||||
#elif defined __linux__
|
|
||||||
extern "C" __attribute__((visibility("default"))) void *CreateInterface(const char *iface, int *ret)
|
|
||||||
#endif
|
|
||||||
{
|
|
||||||
if (strcmp(iface, "ISERVERPLUGINCALLBACKS001") == 0)
|
|
||||||
{
|
|
||||||
if (ret)
|
|
||||||
{
|
|
||||||
*ret = 0;
|
|
||||||
}
|
|
||||||
return GetThisPointer();
|
|
||||||
}
|
|
||||||
|
|
||||||
if (ret)
|
|
||||||
{
|
|
||||||
*ret = 1;
|
|
||||||
}
|
|
||||||
return NULL;
|
|
||||||
}
|
|
Loading…
x
Reference in New Issue
Block a user