diff options
-rw-r--r-- | ServiceBasedPlugins/src/base/UMain.pas | 11 | ||||
-rw-r--r-- | ServiceBasedPlugins/src/base/UNote.pas | 3 | ||||
-rw-r--r-- | ServiceBasedPlugins/src/base/UParty.pas | 207 | ||||
-rw-r--r-- | ServiceBasedPlugins/src/pluginsupport/UPartyDefines.pas | 38 | ||||
-rw-r--r-- | ServiceBasedPlugins/src/pluginsupport/UPlugin.pas | 137 | ||||
-rw-r--r-- | ServiceBasedPlugins/src/pluginsupport/UPluginDefines.pas | 273 | ||||
-rw-r--r-- | ServiceBasedPlugins/src/pluginsupport/UPluginLoader_DLL.pas | 181 | ||||
-rw-r--r-- | ServiceBasedPlugins/src/pluginsupport/UPluginLoader_Included.pas | 38 | ||||
-rw-r--r-- | ServiceBasedPlugins/src/pluginsupport/UPluginManager.pas | 174 | ||||
-rw-r--r-- | ServiceBasedPlugins/src/ultrastardx.dpr | 34 |
10 files changed, 1042 insertions, 54 deletions
diff --git a/ServiceBasedPlugins/src/base/UMain.pas b/ServiceBasedPlugins/src/base/UMain.pas index fec1903f..71d3885a 100644 --- a/ServiceBasedPlugins/src/base/UMain.pas +++ b/ServiceBasedPlugins/src/base/UMain.pas @@ -87,6 +87,9 @@ uses ULog, UPath, UPlaylist, + UPluginManager, + UPluginLoader_Dll, + UPluginLoader_Included, UMusic, UPlatform, USkins, @@ -233,6 +236,14 @@ begin Log.BenchmarkStart(1); Log.LogStatus('PluginManager', 'Initialization'); DLLMan := TDLLMan.Create; // Load PluginList + + PluginManager := TPluginManager.Create; + + //TPluginLoader_Included.Create; + TPluginLoader_DLL.Create(PluginPath); + + //PluginManager.Init; + Log.BenchmarkEnd(1); Log.LogBenchmark('Loading PluginManager', 1); diff --git a/ServiceBasedPlugins/src/base/UNote.pas b/ServiceBasedPlugins/src/base/UNote.pas index 5e70bfe1..41d3da36 100644 --- a/ServiceBasedPlugins/src/base/UNote.pas +++ b/ServiceBasedPlugins/src/base/UNote.pas @@ -126,12 +126,11 @@ uses UDLLManager, UParty, UConfig, - UCore, UCommon, UGraphic, UGraphicClasses, UPath, - UPluginDefs, + //UPluginDefs, UPlatform, UThemes; diff --git a/ServiceBasedPlugins/src/base/UParty.pas b/ServiceBasedPlugins/src/base/UParty.pas index 23012dfe..5b09c06d 100644 --- a/ServiceBasedPlugins/src/base/UParty.pas +++ b/ServiceBasedPlugins/src/base/UParty.pas @@ -33,10 +33,9 @@ interface {$I switches.inc} -uses - UPartyDefs, - UCoreModule, - UPluginDefs; +//uses + //UPartyDefs, + //UPluginDefs; type ARounds = array [0..252] of integer; //0..252 needed for @@ -54,13 +53,152 @@ type TeamOrderArray = array[0..5] of byte; + // some things copied from UPartyDefs, remove this later + + //---------------- + // TUS_Party_Proc_Init - Structure of the Party Init Proc + // This Function is called on SingScreen Init Everytime this Modi should be sung + // Return Non Zero to Abort Party Modi Loading... In this Case another Plugin will be loaded + //---------------- + TUS_Party_Proc_Init = Function (ID: Integer): integer; stdcall; + + //---------------- + // TUS_Party_Proc_Draw - Structure of the Party Draw Proc + // This Function is called on SingScreen Draw (Not when Paused). You should draw in this Proc + // Return Non Zero to Finish Song... In this Case Score Screen is loaded + //---------------- + TUS_Party_Proc_Draw = Function (ID: Integer): integer; stdcall; + + //---------------- + // TUS_Party_Proc_DeInit - Structure of the Party DeInit Proc + // This Function is called on SingScreen DeInit When Plugin abort Song or Song finishes + // Return Winner + //---------------- + TUS_Party_Proc_DeInit = Function (ID: Integer): integer; stdcall; + + //---------------- + // TUS_ModiInfo - Some Infos from Plugin to Partymode. + // Used to register party modi to Party manager + // --- + // Version Structure: + // First Byte: Head Revison + // Second Byte: Sub Revison + // Third Byte: Sub Revision 2 + // Fourth Byte: Letter (For Bug Fix releases. 0 or 'a' .. 'z') + //---------------- + TModiInfo_Name = Array [0..31] of Char; + TModiInfo_Desc = Array [0..63] of Char; + + PUS_ModiInfo = ^TUS_ModiInfo; + TUS_ModiInfo = record + //Size of this record (usefull if record will be extended in the future) + cbSize: Integer; //Don't forget to set this as Plugin! + + //Infos about the Modi + Name : TModiInfo_Name; //Modiname to Register for the Plugin + Description: TModiInfo_Desc; //Plugin Description + + //------------ + // Loading Settings + // --- + // Bit to Set | Triggered Option + // 1 | Song should be loaded + // 2 | Song has to be Non Duett + // 4 | Song has to be Duett (If 2 and 4 is set, both will be ignored) + // 8 | Only Playable with 2 and more players + // 16 | Restrict Background Loading + // 32 | Restrict Video Loading + // 64 | Increase TimesPlayed for Cur. Player + // 128 | Not in Use, Don't set it! + LoadingSettings: Byte; + + // SingScreen Settings + // --- + // Bit to Set | Triggered Option + // 1 | ShowNotes + // 2 | ShowScores + // 4 | ShowTime + // 8 | Start Audio Playback automaticaly + // 16 | Not in Use, Don't set it! + // 32 | Not in Use, Don't set it! + // 64 | Not in Use, Don't set it! + // 128 | Not in Use, Don't set it! + SingScreenSettings: Byte; + + // With which count of players can this modi be played + // --- + //Set different Bits + //1 -> One Player + //2 -> Two Players + //4 -> Three Players + //8 -> Four Players + //16-> Six Players + //e.g. : 10 -> Playable with 2 and 4 Players + NumPlayers: Byte; + + // ID that is given to the Party Procs when they are called + // If this Modi is running + // (e.g. to register Until 2000 and Until 5000 with the same Procs + // ID is the Max Point Count in this example) + ID: Integer; + + // Party Procs called on Party + // --- + // Set to nil(C: NULL) if u don't want to use this method + ModiInit: TUS_Party_Proc_Init; + ModiDraw: TUS_Party_Proc_Draw; + ModiDeInit: TUS_Party_Proc_DeInit; + end; + + //-------------- + // Team Info Record. Used by "Party/GetTeamInfo" and "Party/SetTeamInfo" + //-------------- + TTeamInfo = record + NumTeams: Byte; + Teaminfo: array[0..5] of record + Name: PChar; //Teamname + Score: Word; //TeamScore + Joker: Byte; //Team Jokers available + CurPlayer: Byte; //Id of Cur. Playing Player + NumPlayers: Byte; + Playerinfo: array[0..3] of record + Name: PChar; //Playername + TimesPlayed: Byte; //How often this Player has Sung + end; + end; + end; + +//---------------- +// Some Default Constants +//---------------- +const + // to use for TUS_ModiInfo.LoadingSettings + MLS_LoadSong = 1; //Song should be loaded + MLS_NotDuett = 2; //Song has to be Non Duett + MLS_ForceDuett = 4; //Song has to be Duett (If 2 and 4 is set, both will be ignored) + MLS_TeamOnly = 8; //Only Playable with 2 and more players + MLS_RestrictBG = 16; //Restrict Background Loading + MLS_RestrictVid = 32; //Restrict Video Loading + MLS_IncTP = 64; //Increase TimesPlayed for Cur. Player + + // to use with TUS_ModiInfo.SingScreenSettings + MSS_ShowNotes = 1; //ShowNotes + MSS_ShowScores = 2; //ShowScores + MSS_ShowTime = 4; //ShowTime + MSS_AutoPlayback= 8; //Start Audio Playback automaticaly + + //Standard (Duell) for TUS_ModiInfo.LoadingSettings and TUS_ModiInfo.SingScreenSettings + MLS_Standard = MLS_LoadSong or MLS_IncTP; + MSS_Standard = MSS_ShowNotes or MSS_ShowScores or MSS_ShowTime or MSS_AutoPlayback; + +type TUS_ModiInfoEx = record Info: TUS_ModiInfo; Owner: integer; TimesPlayed: byte; //Helper for setting round plugins end; - TPartySession = class (TCoreModule) + TPartySession = class private bPartyMode: boolean; //Is this party or single player CurRound: byte; @@ -77,14 +215,14 @@ type Rounds: array of TRoundInfo; //TCoreModule methods to inherit - constructor Create; override; - procedure Info(const pInfo: PModuleInfo); override; - function Load: boolean; override; - function Init: boolean; override; - procedure DeInit; override; - destructor Destroy; override; - - //Register modus service + constructor Create; + //procedure Info(const pInfo: PModuleInfo); + function Load: boolean; + function Init: boolean; + procedure DeInit; + destructor Destroy; + + {//Register modus service function RegisterModi(nothin: TwParam; pModiInfo: TlParam): integer; //Registers a new modus. wParam: Pointer to TUS_ModiInfo //Start new Party @@ -100,7 +238,7 @@ type function SetTeamInfo(wParam: TwParam; pTeamInfo: TlParam): integer; //Read TTeamInfo record from pointer at lParam. Returns zero on success function GetTeamOrder(wParam: TwParam; lParam: TlParam): integer; //Returns team order. Structure: Bits 1..3: Team at place1; Bits 4..6: Team at place2 ... - function GetWinnerString(wParam: TwParam; lParam: TlParam): integer; //wParam is roundnum. If (Pointer = nil) then return length of the string. Otherwise write the string to address at lParam + function GetWinnerString(wParam: TwParam; lParam: TlParam): integer; //wParam is roundnum. If (Pointer = nil) then return length of the string. Otherwise write the string to address at lParam} end; const @@ -109,7 +247,6 @@ const implementation uses - UCore, UGraphic, ULanguage, ULog, @@ -124,12 +261,12 @@ uses //------------- // function that gives some infos about the module to the core //------------- -procedure TPartySession.Info(const pInfo: PModuleInfo); +{rocedure TPartySession.Info(const pInfo: PModuleInfo); begin pInfo^.Name := 'TPartySession'; pInfo^.Version := MakeVersion(1,0,0,chr(0)); pInfo^.Description := 'Manages party modi and party game'; -end; +end; } //------------- // Just the constructor @@ -151,9 +288,9 @@ function TPartySession.Load: boolean; begin //Add register party modus service Result := true; - Core.Services.AddService('Party/RegisterModi', nil, Self.RegisterModi); + {Core.Services.AddService('Party/RegisterModi', nil, Self.RegisterModi); Core.Services.AddService('Party/StartParty', nil, Self.StartParty); - Core.Services.AddService('Party/GetCurModi', nil, Self.GetCurModi); + Core.Services.AddService('Party/GetCurModi', nil, Self.GetCurModi);} end; //------------- @@ -192,7 +329,7 @@ end; // Registers a new modus. wParam: Pointer to TUS_ModiInfo // Service for plugins //------------- -function TPartySession.RegisterModi(nothin: TwParam; pModiInfo: TlParam): integer; +{unction TPartySession.RegisterModi(nothin: TwParam; pModiInfo: TlParam): integer; var Len: integer; Info: PUS_ModiInfo; @@ -205,13 +342,13 @@ begin SetLength(Modis, Len + 1); Modis[Len].Info := Info^; - end - else - Core.ReportError(integer(PChar('Plugins try to register modus with wrong pointer, or wrong TUS_ModiInfo record.')), PChar('TPartySession')); + end; + {else + Core.ReportError(integer(PChar('Plugins try to register modus with wrong pointer, or wrong TUS_ModiInfo record.')), PChar('TPartySession'));} - // FIXME: return a valid result - Result := 0; -end; + // FIXME: return a valid result { + {esult := 0; +end; } //---------- // Returns a number of a random plugin @@ -265,7 +402,7 @@ end; //---------- // Starts new party mode. Returns non zero on success //---------- -function TPartySession.StartParty(NumRounds: TwParam; PAofIRounds: TlParam): integer; +{unction TPartySession.StartParty(NumRounds: TwParam; PAofIRounds: TlParam): integer; var I: integer; aiRounds: PARounds; @@ -305,7 +442,7 @@ begin Result := 1; except - Core.ReportError(integer(PChar('Can''t start party mode.')), PChar('TPartySession')); + //Core.ReportError(integer(PChar('Can''t start party mode.')), PChar('TPartySession')); end; end; end; @@ -340,7 +477,7 @@ begin end else Result := 0; -end; +end; } //---------- //GetRandomPlayer - gives back a random player to play next round @@ -392,7 +529,7 @@ end; //---------- // NextRound - Increases CurRound by 1; Returns num of round or -1 if last round is already played //---------- -function TPartySession.NextRound(wParam: TwParam; lParam: TlParam): integer; +{function TPartySession.NextRound(wParam: TwParam; lParam: TlParam): integer; var I: integer; begin @@ -409,7 +546,7 @@ begin end else Result := -1; -end; +end;} //---------- //IsWinner - returns true if the players bit is set in the winner byte @@ -440,7 +577,7 @@ end; //---------- // CallModiInit - calls CurModis Init Proc. If an error occurs, returns nonzero. In this case a new plugin was selected. Please renew loading //---------- -function TPartySession.CallModiInit(wParam: TwParam; lParam: TlParam): integer; +{function TPartySession.CallModiInit(wParam: TwParam; lParam: TlParam): integer; begin if (not bPartyMode) then begin //Set rounds if not in party mode @@ -455,10 +592,10 @@ begin except on E : Exception do begin - Core.ReportError(integer(PChar('Error starting modus: ' + Modis[Rounds[CurRound].Modi].Info.Name + ' ErrorStr: ' + E.Message)), PChar('TPartySession')); + //Core.ReportError(integer(PChar('Error starting modus: ' + Modis[Rounds[CurRound].Modi].Info.Name + ' ErrorStr: ' + E.Message)), PChar('TPartySession')); if (Rounds[CurRound].Modi = StandardModus) then begin - Core.ReportError(integer(PChar('Can''t start standard modus, will exit now!')), PChar('TPartySession')); + //Core.ReportError(integer(PChar('Can''t start standard modus, will exit now!')), PChar('TPartySession')); Halt; end else //Select standard modus @@ -660,6 +797,6 @@ begin end; end; -end; +end; } end. diff --git a/ServiceBasedPlugins/src/pluginsupport/UPartyDefines.pas b/ServiceBasedPlugins/src/pluginsupport/UPartyDefines.pas new file mode 100644 index 00000000..87e9531f --- /dev/null +++ b/ServiceBasedPlugins/src/pluginsupport/UPartyDefines.pas @@ -0,0 +1,38 @@ +{* UltraStar Deluxe - Karaoke Game
+ *
+ * UltraStar Deluxe is the legal property of its developers, whose names
+ * are too numerous to list here. Please refer to the COPYRIGHT
+ * file distributed with this source distribution.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; see the file COPYING. If not, write to
+ * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ * Boston, MA 02110-1301, USA.
+ *
+ * $URL: https://ultrastardx.svn.sourceforge.net/svnroot/ultrastardx/trunk/src/base/UMain.pas $
+ * $Id: UMain.pas 1629 2009-03-07 22:30:04Z k-m_schindler $
+ *}
+
+unit UPartyDefines;
+
+interface
+
+{$IFDEF FPC}
+ {$MODE Delphi}
+{$ENDIF}
+
+{$I switches.inc}
+
+implementation
+
+end.
\ No newline at end of file diff --git a/ServiceBasedPlugins/src/pluginsupport/UPlugin.pas b/ServiceBasedPlugins/src/pluginsupport/UPlugin.pas new file mode 100644 index 00000000..19c23999 --- /dev/null +++ b/ServiceBasedPlugins/src/pluginsupport/UPlugin.pas @@ -0,0 +1,137 @@ +{* UltraStar Deluxe - Karaoke Game
+ *
+ * UltraStar Deluxe is the legal property of its developers, whose names
+ * are too numerous to list here. Please refer to the COPYRIGHT
+ * file distributed with this source distribution.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; see the file COPYING. If not, write to
+ * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ * Boston, MA 02110-1301, USA.
+ *
+ * $URL: https://ultrastardx.svn.sourceforge.net/svnroot/ultrastardx/trunk/src/base/UMain.pas $
+ * $Id: UMain.pas 1629 2009-03-07 22:30:04Z k-m_schindler $
+ *}
+
+unit UPlugin;
+
+interface
+
+{$IFDEF FPC}
+ {$MODE Delphi}
+{$ENDIF}
+
+{$I switches.inc}
+
+uses UPluginDefines;
+
+// a basic implementation of IPlugin
+type
+ TPlugin = class(TInterfacedObject, IUS_Plugin)
+ protected
+ Status: TUS_PluginStatus;
+ Handle: TUS_Handle;
+ UniqueID: TUS_Handle;
+ Filename: WideString;
+ ErrorReason: WideString;
+
+ procedure OnChangeStatus(Status: TUS_PluginStatus); virtual;
+ public
+ constructor Create(Handle: TUS_Handle; Filename: WideString); virtual;
+
+ function GetStatus: TUS_PluginStatus; virtual;
+ procedure SetStatus(Status: TUS_PluginStatus); virtual;
+
+ function GetHandle: TUS_Handle; virtual;
+ function GetUniqueID: TUS_Handle; virtual;
+ function GetFilename: WideString; virtual;
+
+ procedure Init; virtual;
+ procedure DeInit; virtual;
+
+ procedure SetError(Reason: WideString); virtual;
+ function GetErrorReason: WideString; virtual;
+ end;
+
+implementation
+uses UPluginManager, ULog;
+
+constructor TPlugin.Create(Handle: TUS_Handle; Filename: WideString);
+begin
+ inherited Create;
+
+ Self.Handle := Handle;
+ Self.Filename := Filename;
+ Self.Status := psNone;
+
+ Self.UniqueID := CalculateUSHash(Filename); //< this should be done another way ;) just for testing purposes
+end;
+
+function TPlugin.GetStatus: TUS_PluginStatus;
+begin
+ Result := Status;
+end;
+
+procedure TPlugin.SetStatus(Status: TUS_PluginStatus);
+begin
+ // OnChangeStatus has to change the status attribut
+ OnChangeStatus(Status);
+end;
+
+function TPlugin.GetHandle: TUS_Handle;
+begin
+ Result := Handle;
+end;
+
+function TPlugin.GetUniqueID: TUS_Handle;
+begin
+ Result := UniqueID;
+end;
+
+function TPlugin.GetFilename: WideString;
+begin
+ Result := Filename;
+end;
+
+procedure TPlugin.Init;
+begin
+ if (Status = psWaitingInit) then
+ SetStatus(psInited);
+end;
+
+procedure TPlugin.DeInit;
+begin
+ if (Status = psInited) then
+ SetStatus(psDeInited);
+end;
+
+procedure TPlugin.SetError(Reason: WideString);
+begin
+ ErrorReason := Reason;
+ SetStatus(psError);
+ PluginManager.ReportError(Handle);
+ Log.LogError(Filename + ': ' + Reason);
+end;
+
+function TPlugin.GetErrorReason: WideString;
+begin
+ Result := ErrorReason;
+end;
+
+procedure TPlugin.OnChangeStatus(Status: TUS_PluginStatus);
+begin
+ //do nothing here
+ //should be overwritten by the child classes
+end;
+
+end.
\ No newline at end of file diff --git a/ServiceBasedPlugins/src/pluginsupport/UPluginDefines.pas b/ServiceBasedPlugins/src/pluginsupport/UPluginDefines.pas new file mode 100644 index 00000000..5a042f1a --- /dev/null +++ b/ServiceBasedPlugins/src/pluginsupport/UPluginDefines.pas @@ -0,0 +1,273 @@ +{* UltraStar Deluxe - Karaoke Game
+ *
+ * UltraStar Deluxe is the legal property of its developers, whose names
+ * are too numerous to list here. Please refer to the COPYRIGHT
+ * file distributed with this source distribution.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; see the file COPYING. If not, write to
+ * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ * Boston, MA 02110-1301, USA.
+ *
+ * $URL: https://ultrastardx.svn.sourceforge.net/svnroot/ultrastardx/trunk/src/base/UMain.pas $
+ * $Id: UMain.pas 1485 2008-10-28 20:16:05Z tobigun $
+ *}
+{*
+ some defines that are used by usdx and plugins
+*}
+unit UPluginDefines;
+
+interface
+
+{$IFDEF FPC}
+ {$MODE Delphi}
+{$ENDIF}
+
+{$I switches.inc}
+
+const
+ SDK_Version = 0001000000000000; //< identifies the used SDK version (1.0.0.0)
+
+type
+ { this type is used for all version ints in this SDK }
+ TUS_Version = LongInt;
+
+ { this type is used for all plugin handles in this SDK }
+ TUS_Handle = LongInt;
+
+const
+ US_HANDLE_CORE = 137; //handle of core, also first defined handle
+ US_HANDLE_UNDEFINED = 0; //undefined handle, used to indicate errors
+
+ { this type is used for all id strings in this SDK }
+const
+ MaxLength_TUS_Identifier = 32; //max length of identifier strings, has to be multiply of 4
+
+type
+ TUS_Identifier = String[MaxLength_TUS_Identifier];
+
+ { this record is used to offer some information about this plugin to the core }
+ TUS_PluginInfo = packed record
+ Name : Array [1..32] of Char; //name of the plugin
+ Author : Array [1..32] of Char; //plugins author
+ PluginDesc : Array [1..64] of Char; //some further explentation
+ Version : TUS_Version;
+ end;
+ PUS_PluginInfo = ^TUS_PluginInfo;
+
+ { this function reads the plugins information from a TUS_PluginInfo record,
+ and saves it. Can be called onced per plugin.
+ Version is the SDK_Version used by the plugin
+ BufferLength is the size of buffer in bytes }
+ TUS_Func_Identify = function (Handle: TUS_Handle; Version: TUS_Version; Buffer: PUS_PluginInfo; BufferLength: LongInt): LongInt; stdcall;
+
+ { this plugin is used for selfshutdown by the plugin on an error
+ case.
+ Reason should be used to describe the reason for the shutdown
+ OnChangeStatus(psDeInited) is called when old status was psInited }
+ TUS_Func_Error = function (Handle: TUS_Handle; Reason: PWideChar): LongInt; stdcall;
+
+ { this function writes the plugins filename including its path ,
+ to buffer. A call with Buffer=nil or Len<=0 returns the actual
+ length of the path.
+ BufferLength is the size of buffer in bytes
+ Filename is used to identify duplicate load of one plugin
+ so it should even set when plugin is not loaded from file}
+ TUS_Func_GetFilename = function (Handle: TUS_Handle; Version: TUS_Version; Buffer: PWideChar; BufferLength: LongInt): LongInt; stdcall;
+
+ { this function writes an interface, identified by 'ID', to the
+ buffer.
+ Version is the version of the interface that is used
+ BufferLength is the size of buffer in bytes}
+ TUS_Func_GetInterface = function (ID: TUS_Identifier; Version: TUS_Version; Buffer: Pointer; BufferLength: LongInt): LongInt; stdcall;
+
+ { this function reads an interface, identified by 'ID', from the
+ buffer, to offer it to calls of GetInterface.
+ version is the version of the interface
+ BufferLength is the size of buffer in bytes }
+ TUS_Func_SetInterface = function (ID: TUS_Identifier; Version: TUS_Version; Buffer: Pointer; BufferLength: LongInt): LongInt; stdcall;
+
+ { this function writes a record or some other data,
+ identified by 'ID', to the buffer.
+ Version is the version of the data that is used
+ BufferLength is the size of buffer in bytes}
+ TUS_Func_GetData = function (ID: TUS_Identifier; Version: TUS_Version; Buffer: Pointer; BufferLength: LongInt): LongInt; stdcall;
+
+ { this function reads a record or some other data,
+ identified by 'ID', from the buffer, to offer it
+ to calls of GetData.
+ version is the version of the record
+ BufferLength is the size of buffer in bytes }
+ TUS_Func_SetData = function (ID: TUS_Identifier; Version: TUS_Version; Buffer: Pointer; BufferLength: LongInt): LongInt; stdcall;
+
+ { a record w/ some useful methods for plugins }
+ TUS_PluginInterface = packed record
+ Version : TUS_Version; //SDK_Version
+ Handle : LongInt; //the plugins handle
+
+ Identify : TUS_Func_Identify;
+ Error : TUS_Func_Error;
+ GetFilename : TUS_Func_GetFilename;
+
+ GetInterface: TUS_Func_GetInterface;
+ SetInterface: TUS_Func_SetInterface;
+
+ GetData : TUS_Func_GetData;
+ SetData : TUS_Func_SetData;
+ end;
+ PUS_PluginInterface = ^TUS_PluginInterface;
+
+ { this function writes the PluginInterface to the buffer }
+ TUS_Func_InitInterface = function (Handle: TUS_Handle; Version: TUS_Version; Buffer: PUS_PluginInterface; BufferSize: LongInt): LongInt;
+ {$IFDEF MSWINDOWS} stdcall; {$ELSE} cdecl; {$ENDIF}
+
+
+ { this function is called by core, in the WaitingInit status
+ it offers the plugin the possibility to load its plugininterface
+ and to check it's sdk version against the cores.
+ It has to be implemented by plugins loaded as library }
+ TUS_Plugin_Proc_Init = procedure (Handle: TUS_Handle; CoreVersion: TUS_Version; InitInterface: TUS_Func_InitInterface);
+ {$IFDEF MSWINDOWS} stdcall; {$ELSE} cdecl; {$ENDIF}
+
+
+ TUS_PluginStatus = (psNone, psWaitingInit, psWaitingIdentify, psInited, psDeInited, psError);
+
+ { this function is called everytime tbe plugins status changes
+ status is the new status.
+ it has to be implemented by plugins loaded as library }
+ TUS_Plugin_OnChangeStatus = procedure (Handle: TUS_Handle; Status: TUS_PluginStatus);
+ {$IFDEF MSWINDOWS} stdcall; {$ELSE} cdecl; {$ENDIF}
+
+
+ { this interface represents a loaded plugin, it eitber has to
+ be implemented by the pluginloader, e.g. for libs or by the
+ plugin itself in the case of integrated plugins }
+ IUS_Plugin = Interface
+ ['{23F7B722-D979-4402-9953-C6B229A6E888}']
+ function GetStatus: TUS_PluginStatus;
+ procedure SetStatus(status: TUS_PluginStatus);
+
+ function GetHandle: TUS_Handle;
+ function GetUniqueID: TUS_Handle; //< This ID is unique for the given plugin it may be a hash of the plugins code or s/t like that. used to identify plugins laoded twice
+ function GetFilename: WideString;
+
+ Procedure Init;
+ Procedure DeInit;
+
+ Procedure SetError(Reason: WideString);
+ Function GetErrorReason: WideString;
+ end;
+
+ { this function will be called when a hookable event is spawn
+ data is a pointer to a struct that can contain any data
+ defined by the event creator. if there is no data this should
+ be nil.
+ breakable is true if the hook chain can be interupted by
+ returning US_HOOK_BREAK or US_HOOK_UNHOOKME_BREAK
+ by returning US_HOOK_UNHOOKME the callback will immediately
+ be removed from the chain }
+ TUS_Func_OnEvent = function(data: pointer; breakable: boolean): integer;
+ TUS_cFunc_OnEvent = function(data: pointer; breakable: boolean): integer of object;
+
+ { this interface represents an event that can be hooked by
+ e.g. the core or other}
+ IUS_HookableEvent = Interface
+ // this GID has to be changed if we change this interface
+ ['{FFC6F09D-EC0B-41E2-87F6-70EC6F055C0E}']
+ function GetIdentifier: TUS_Identifier;
+ function GetHash: LongInt;
+
+ //adds the callback to the top of the events hook chain
+ //proc is the callback function
+ //parent is the plugins handle, or US_HANDLE_CORE if called by core
+ //returns hook-handle on succes or US_HANDLE_UNDEFINED on failure
+ function Hook(proc: TUS_Func_OnEvent; Parent: TUS_Handle): TUS_Handle;
+ function cHook(proc: TUS_cFunc_OnEvent; Parent: TUS_Handle): TUS_Handle;
+
+ //removes a callback from the chain using the handle returned
+ //by the hook function
+ //returns an US_ERROR code
+ function UnHook(Handle: TUS_Handle): byte;
+
+ //removes all callbacks of a specified parent (plugin)
+ procedure UnHookbyParent(Parent: TUS_Handle);
+ end;
+
+
+const
+ { some errorcodes that are returned by functions using this SDK }
+ US_ERROR_None = 0; //< indicates success ;)
+ US_ERROR_VersionMismatch = 1; //< returned when the version the plugin wants to use is not supported
+ US_ERROR_SizeMismatch = 2; //< returned when the wanted data does not fit the buffersize
+ US_ERROR_WrongHandle = 3; //< returned when the given handle is not
+ US_ERROR_WrongID = 4; //< returned when the given id does not exist
+ US_ERROR_NameExists = 5; //< returned when the given name already exists
+
+ US_ERROR_Unknown = 255; //< returned when an unknown error occured
+
+ { return values for hook function }
+ US_HOOK_BREAK = High(integer); //this will break the hook chain
+ US_HOOK_UNHOOKME = High(integer) - 2; //this will remove the callback from the hooks chain
+ US_HOOK_UNHOOKME_BREAK = High(integer) - 1; //this will do both explained above
+
+{ this function converts an errorcode to its textual expression }
+function USErrortoString(Code: LongInt): String;
+
+{ this funtion creates a hash for an TUS_Identifier
+ the hash is not guaranteed to be unique, it is just
+ for a fast search of an identifier }
+function CalculateUSHash(Identifier: TUS_Identifier): LongInt;
+
+implementation
+
+{ this function converts an errorcode to its textual expression }
+Function USErrortoString(Code: LongInt): String;
+begin
+ Case Code of
+ US_Error_None: Result := 'success, no error occured';
+ US_Error_VersionMismatch: Result := 'version mismatch';
+ US_Error_SizeMismatch: Result := 'size mismatch';
+ US_Error_WrongHandle: Result := 'handle does not exist';
+ US_Error_WrongID: Result := 'id does not exist';
+ US_Error_NameExists: Result := 'another item with this name does already exist';
+
+ Else Result := 'unknown error';
+ end;
+end;
+
+{ this funtion creates a hash for an TUS_Identifier
+ the hash is not guaranteed to be unique, it is just
+ for a fast search of an identifier }
+function CalculateUSHash(Identifier: TUS_Identifier): LongInt;
+ var
+ L: Integer;
+ I: Integer;
+
+ const
+ StartHash = -1337456101;
+begin
+ // fill the unused chars of the identifier w/ zeros
+ L := Length(Identifier);
+ if (L < MaxLength_TUS_Identifier) then
+ FillChar(Identifier[L+1], MaxLength_TUS_Identifier - L, 0);
+
+ // calculate the hash
+ // this is done by just adding respectively 4 bytes of the string
+ // to the hash (longint)
+ Result := StartHash;
+ for I := 1 to (MaxLength_TUS_Identifier div 4) do
+ Result := Result + LongInt(Identifier[I*4]);
+end;
+
+end.
+
diff --git a/ServiceBasedPlugins/src/pluginsupport/UPluginLoader_DLL.pas b/ServiceBasedPlugins/src/pluginsupport/UPluginLoader_DLL.pas new file mode 100644 index 00000000..b143cd2a --- /dev/null +++ b/ServiceBasedPlugins/src/pluginsupport/UPluginLoader_DLL.pas @@ -0,0 +1,181 @@ +{* UltraStar Deluxe - Karaoke Game
+ *
+ * UltraStar Deluxe is the legal property of its developers, whose names
+ * are too numerous to list here. Please refer to the COPYRIGHT
+ * file distributed with this source distribution.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; see the file COPYING. If not, write to
+ * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ * Boston, MA 02110-1301, USA.
+ *
+ * $URL: https://ultrastardx.svn.sourceforge.net/svnroot/ultrastardx/trunk/src/base/UMain.pas $
+ * $Id: UMain.pas 1629 2009-03-07 22:30:04Z k-m_schindler $
+ *}
+
+unit UPluginLoader_DLL;
+
+interface
+
+{$IFDEF FPC}
+ {$MODE Delphi}
+{$ENDIF}
+
+{$I switches.inc}
+
+uses UPluginDefines, UPlugin;
+
+type
+ TPluginLoader_DLL = class
+ protected
+ PluginDir: WideString;
+ public
+ constructor Create(PluginDir: WideString);
+ procedure Browse(Dir: WideString);
+ end;
+
+ TPlugin_DLL = class (TPlugin)
+ protected
+ hLib: THandle; //< handle of loaded library
+ Lib_Proc_Init: TUS_Plugin_Proc_Init;
+ Lib_OnChangeStatus: TUS_Plugin_OnChangeStatus;
+
+ procedure OnChangeStatus(Status: TUS_PluginStatus); override;
+ public
+ constructor Create(Handle: TUS_Handle; Filename: WideString); override;
+ destructor Destroy; override;
+ end;
+
+const
+ {$IF Defined(MSWINDOWS)}
+ DLLExt = '.dll';
+ {$ELSEIF Defined(DARWIN)}
+ DLLExt = '.dylib';
+ {$ELSEIF Defined(UNIX)}
+ DLLExt = '.so';
+ {$IFEND}
+
+implementation
+uses
+ {$IFDEF MSWINDOWS}
+ windows,
+ {$ELSE}
+ dynlibs,
+ {$ENDIF}
+ SysUtils, Dialogs,
+ UPluginManager,
+ UPlatform;
+
+{ implementation of TPluginLoader_DLL }
+constructor TPluginLoader_DLL.Create(PluginDir: WideString);
+begin
+ Self.PluginDir := PluginDir;
+ Browse(PluginDir);
+end;
+
+procedure TPluginLoader_DLL.Browse(Dir: WideString);
+ var
+ Files: TDirectoryEntryArray;
+ I: Integer;
+begin
+ Showmessage(Dir + ' - ' + DLLExt);
+ Files := Platform.DirectoryFindFiles(Dir, DLLExt, True);
+
+ for I := 0 to High(Files) do
+ begin
+ ShowMessage(Dir + Files[I].Name);
+ if (Files[I].IsDirectory) then
+ Browse(Dir + Files[I].Name + PathDelim)
+ else if (Files[I].IsFile) then
+ PluginManager.AddPlugin(TPlugin_DLL.Create(PluginManager.GetHandle, Dir + Files[I].Name));
+ end;
+end;
+
+{ implementation of TPlugin_DLL }
+constructor TPlugin_DLL.Create(Handle: TUS_Handle; Filename: WideString);
+begin
+ inherited;
+
+ hLib := 0;
+ Lib_Proc_Init := nil;
+ Lib_OnChangeStatus := nil;
+
+ //try to load the library
+ SetStatus(psWaitingInit);
+end;
+
+destructor TPlugin_DLL.Destroy;
+begin
+
+ inherited;
+end;
+
+procedure TPlugin_DLL.OnChangeStatus(Status: TUS_PluginStatus);
+begin
+ Case Status of
+ psWaitingInit: begin
+ //we have to try to load the plugin here
+ hLib := LoadLibrary(PChar(AnsiString(Filename)));
+ if (hlib <> 0) then
+ begin
+ @Lib_Proc_Init := GetProcAddress(hLib, PChar('Proc_Init'));
+
+ If (not Assigned(Lib_Proc_Init)) then
+ begin
+ FreeLibrary(hLib);
+
+ {$IFDEF MSWINDOWS}
+ SetError('Can''t export Proc_Init procedure from library. Windows reports: ' + SysErrorMessage(GetLastError));
+ {$ELSE}
+ SetError('Can''t export Proc_Init procedure from library.');
+ {$ENDIF}
+ Exit;
+ end;
+
+ @Lib_OnChangeStatus := GetProcAddress(hLib, PChar('OnChangeStatus'));
+
+ If (not Assigned(Lib_OnChangeStatus)) then
+ begin
+ FreeLibrary(hLib);
+
+ {$IFDEF MSWINDOWS}
+ SetError('Can''t export OnChangeStatus procedure from library. Windows reports: ' + SysErrorMessage(GetLastError));
+ {$ELSE}
+ SetError('Can''t export OnChangeStatus procedure from library.');
+ {$ENDIF}
+ Exit;
+ end;
+
+ end
+ else
+ begin
+ {$IFDEF MSWINDOWS}
+ SetError('Error loading library. Windows reports: ' + SysErrorMessage(GetLastError));
+ {$ELSE}
+ SetError('Error loading library.');
+ {$ENDIF}
+ Exit;
+ end;
+
+ end;
+
+ end;
+
+ //call plugins OnChangeStatus procedure
+ If assigned(Lib_OnChangeStatus) then
+ Lib_OnChangeStatus(Self.Handle, Status);
+
+ Self.Status := Status;
+end;
+
+end.
\ No newline at end of file diff --git a/ServiceBasedPlugins/src/pluginsupport/UPluginLoader_Included.pas b/ServiceBasedPlugins/src/pluginsupport/UPluginLoader_Included.pas new file mode 100644 index 00000000..df7b2f74 --- /dev/null +++ b/ServiceBasedPlugins/src/pluginsupport/UPluginLoader_Included.pas @@ -0,0 +1,38 @@ +{* UltraStar Deluxe - Karaoke Game
+ *
+ * UltraStar Deluxe is the legal property of its developers, whose names
+ * are too numerous to list here. Please refer to the COPYRIGHT
+ * file distributed with this source distribution.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; see the file COPYING. If not, write to
+ * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ * Boston, MA 02110-1301, USA.
+ *
+ * $URL: https://ultrastardx.svn.sourceforge.net/svnroot/ultrastardx/trunk/src/base/UMain.pas $
+ * $Id: UMain.pas 1629 2009-03-07 22:30:04Z k-m_schindler $
+ *}
+
+unit UPluginLoader_Included;
+
+interface
+
+{$IFDEF FPC}
+ {$MODE Delphi}
+{$ENDIF}
+
+{$I switches.inc}
+
+implementation
+
+end.
diff --git a/ServiceBasedPlugins/src/pluginsupport/UPluginManager.pas b/ServiceBasedPlugins/src/pluginsupport/UPluginManager.pas new file mode 100644 index 00000000..6c7f5056 --- /dev/null +++ b/ServiceBasedPlugins/src/pluginsupport/UPluginManager.pas @@ -0,0 +1,174 @@ +{* UltraStar Deluxe - Karaoke Game
+ *
+ * UltraStar Deluxe is the legal property of its developers, whose names
+ * are too numerous to list here. Please refer to the COPYRIGHT
+ * file distributed with this source distribution.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; see the file COPYING. If not, write to
+ * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ * Boston, MA 02110-1301, USA.
+ *
+ * $URL: https://ultrastardx.svn.sourceforge.net/svnroot/ultrastardx/trunk/src/base/UMain.pas $
+ * $Id: UMain.pas 1629 2009-03-07 22:30:04Z k-m_schindler $
+ *}
+unit UPluginManager;
+
+{ this class manages all loaded plugins }
+
+interface
+
+{$IFDEF FPC}
+ {$MODE Delphi}
+{$ENDIF}
+
+{$I switches.inc}
+
+uses Classes, UPluginDefines;
+
+type
+ TPluginManager = class
+ private
+ NextHandle: TUS_Handle;
+
+ Plugins: TInterfaceList;
+ Events: TInterfaceList;
+ Interfaces: TInterfaceList;
+
+ public
+ constructor Create;
+
+ //returns a unique handle to use e.g. w/ a pluginloader
+ function GetHandle: TUS_Handle;
+
+ //returns the plugin w/ the specified handle
+ function GetPluginbyHandle(Handle: TUS_Handle): IUS_Plugin;
+
+ //just adds a plugin to the pluginlist
+ //it will be inited on next call of init
+ function AddPlugin(Plugin: IInterface): TUS_Handle;
+
+ procedure Init; //< inits all plugins w/ status psWaitingInit
+ procedure DeInit; //< deinits all plugins w/ status psInited
+
+ //called by plugins if they change to status psError
+ //removes all saved data and callbacks by this handle
+ procedure ReportError(Handle: TUS_Handle);
+
+ destructor Destroy;
+ end;
+
+var
+ PluginManager: TPluginManager;
+
+implementation
+uses SysUtils;
+
+constructor TPluginManager.Create;
+begin
+ NextHandle := US_HANDLE_CORE + 1;
+
+ Plugins := TInterfaceList.Create;
+ Events := TInterfaceList.Create;
+ Interfaces := TInterfaceList.Create;
+end;
+
+destructor TPluginManager.Destroy;
+begin
+ DeInit;
+
+ Plugins.Destroy;
+ Events.Destroy;
+ Interfaces.Destroy;
+end;
+
+// returns a unique handle to use e.g. w/ a pluginloader
+function TPluginManager.GetHandle: TUS_Handle;
+begin
+ Result := NextHandle;
+ Inc(NextHandle);
+end;
+
+//returns the plugin w/ the specified handle
+function TPluginManager.GetPluginbyHandle(Handle: TUS_Handle): IUS_Plugin;
+ var
+ I: integer;
+ Plugin: IUS_Plugin;
+begin
+ Result := nil;
+ for I := 0 to Plugins.Count-1 do
+ begin
+ Plugin := IUS_Plugin(Plugins.Items[I]);
+ If (Plugin.GetHandle = Handle) then
+ begin
+ Result := Plugin;
+ Exit;
+ end;
+ end;
+end;
+
+// just adds a plugin to the pluginlist
+// it will be inited on next call of init
+function TPluginManager.AddPlugin(Plugin: IInterface): TUS_Handle;
+begin
+ If Supports(Plugin, IUS_Plugin) then
+ Plugins.Add(Plugin);
+end;
+
+// inits all plugins w/ status psWaitingInit
+procedure TPluginManager.Init;
+ var
+ I: integer;
+ Plugin: IUS_Plugin;
+begin
+ for I := 0 to Plugins.Count-1 do
+ begin
+ Plugin := IUS_Plugin(Plugins.Items[I]);
+ If (Plugin.GetStatus = psWaitingInit) then
+ begin
+ Plugin.Init;
+ end;
+ end;
+end;
+
+// deinits all plugins w/ status psInited
+procedure TPluginManager.DeInit;
+ var
+ I: integer;
+ Plugin: IUS_Plugin;
+begin
+ for I := 0 to Plugins.Count-1 do
+ begin
+ Plugin := IUS_Plugin(Plugins.Items[I]);
+ If (Plugin.GetStatus = psInited) then
+ begin
+ Plugin.DeInit;
+ end;
+ end;
+end;
+
+//called by plugins if they change to errorstate
+//removes all saved data and callbacks by this handle
+procedure TPluginManager.ReportError(Handle: TUS_Handle);
+ var
+ I: integer;
+ Event: IUS_HookableEvent;
+begin
+ for I := 0 to Events.Count-1 do
+ begin
+ Event := IUS_HookableEvent(Events.Items[I]);
+ Event.UnHookbyParent(Handle);
+ end;
+end;
+
+end.
\ No newline at end of file diff --git a/ServiceBasedPlugins/src/ultrastardx.dpr b/ServiceBasedPlugins/src/ultrastardx.dpr index f2896cd2..80d15e17 100644 --- a/ServiceBasedPlugins/src/ultrastardx.dpr +++ b/ServiceBasedPlugins/src/ultrastardx.dpr @@ -204,21 +204,21 @@ uses //------------------------------ //Includes - Plugin Support //------------------------------ - {UPluginDefines in 'pluginsupport\UPluginDefines.pas', - UPartyDefines in 'pluginsupport\UPartyDefines.pas', - - UPartyMode in 'pluginsupport\UPartyMode.pas', - UPartyManager in 'pluginsupport\UPartyManager.pas', - UPartyModePlugin in 'pluginsupport\UPartyModePlugin.pas', - UPluginLoader in 'pluginsupport\UPluginLoader.pas', } - - UModules in 'base\UModules.pas', //List of Modules to Load - UHooks in 'base\UHooks.pas', //Hook Managing - UServices in 'base\UServices.pas', //Service Managing - UCore in 'base\UCore.pas', //Core, Maybe remove this - UCoreModule in 'base\UCoreModule.pas', //^ - UPluginInterface in 'base\UPluginInterface.pas', //Interface offered by Core to Plugins - UPluginLoader in 'base\UPluginLoader.pas', //New Plugin Loader Module + UPluginDefines in 'pluginsupport\UPluginDefines.pas', + UPartyDefines in 'pluginsupport\UPartyDefines.pas', + + UPluginManager in 'pluginsupport\UPluginManager.pas', + UPlugin in 'pluginsupport\UPlugin.pas', + UPluginLoader_DLL in 'pluginsupport\UPluginLoader_DLL.pas', + UPluginLoader_Included in 'pluginsupport\UPluginLoader_Included.pas', + + //UModules in 'base\UModules.pas', //List of Modules to Load + //UHooks in 'base\UHooks.pas', //Hook Managing + //UServices in 'base\UServices.pas', //Service Managing + //UCore in 'base\UCore.pas', //Core, Maybe remove this + //UCoreModule in 'base\UCoreModule.pas', //^ + //UPluginInterface in 'base\UPluginInterface.pas', //Interface offered by Core to Plugins + //UPluginLoader in 'base\UPluginLoader.pas', //New Plugin Loader Module UParty in 'base\UParty.pas', // TODO: rewrite Party Manager as Module, reomplent ability to offer party Mody by Plugin @@ -331,8 +331,8 @@ uses //Includes - Modi SDK //------------------------------ ModiSDK in '..\plugins\SDK\ModiSDK.pas', //Old SDK, will be deleted soon - UPluginDefs in '..\plugins\SDK\UPluginDefs.pas', //New SDK, not only Modis - UPartyDefs in '..\plugins\SDK\UPartyDefs.pas', //Headers to register Party Modes + //UPluginDefs in '..\plugins\SDK\UPluginDefs.pas', //New SDK, not only Modis + //UPartyDefs in '..\plugins\SDK\UPartyDefs.pas', //Headers to register Party Modes SysUtils; |