RunUO Community

This is a sample guest message. Register a free account today to become a member! Once signed in, you'll be able to participate on this site by adding your own topics and posts, as well as connect with other members through your own private inbox!

Load scripts from a library

Arya

Wanderer
Load scripts from a library

This isn't very consequential for server performance (except a slightly faster boot up). However it's very handy if your server is on a remote machine. Here's how it works:

The server should be installed as usual, but the Scripts folder should be deleted (well it can be left where it is, it doesn't really matter). This mod will load all scripts from a file called Scripts.dll that the server expects to find in the executable directory. (I didn't add support for VB scripts since it seems no one uses those).

Whenever you wish to update the scripts, place the new Scripts.dll you wish to use in a folder called "Update" within the server directory. Here's an example structure:

(1) C:\RunUO\Server.exe
(2) C:\RunUO\Scripts.dll
(3) C:\RunUO\Update\Scripts.dll

When the server starts it will first look for the file (3) and if present it will delete (2) and then move (3) inside the base directory. And then load it up.

The mod is very simple and takes place in the Compile( bool debug ) method in the file \ScriptCompiler.cs. Here's the new method:

Code:
public static bool Compile( bool debug )
     {
     	/* Mod by Arya: We no longer compile scripts on the fly, instead we load an assembly.
     		* The assembly is called Scripts.dll and is located in Core.BaseDirectory.
     		* 
     		* There is also a check for updates BEFORE loading the assembly. Look in
 		* Core.BaseDirectory\Updates for a new Scripts.dll. If present copy it over the old
     		* one.
     		*/
     
     	string path = Path.Combine( Core.BaseDirectory, "Scripts.dll" );
     	string updatePath = Path.Combine( Core.BaseDirectory, @"Update\Scripts.dll" );
     
     	if ( File.Exists( updatePath ) )
     	{
     		// We have a scripts update
     		Console.Write( "Scripts update found... " );
     
     		if ( File.Exists( path ) )
     		{
     			// Delete the old scripts.dll
     			try
     			{
     				File.Delete( path );
     			}
     			catch ( Exception err )
     			{
 		 	 Console.WriteLine( "update failed. Could not delete scripts.dll: {0}", err.ToString() );
     				return false;
     			}
     		}
     
     		try
     		{
     			File.Move( updatePath, path );
     		}
     		catch ( Exception err )
     		{
 		 Console.WriteLine( "update failed. Couldn't move scripts.dll: {0}", err.ToString() );
     			return false;
     		}
     
     		Console.WriteLine( "update succesful." );
     	}
     	
     	if ( ! File.Exists( path ) )
     	{
     		Console.WriteLine( "Scripts.dll not found. Startup aborted." );
     		return false;
     	}
     
     	Assembly scripts = null;
     	
     	try
     	{
     		scripts = Assembly.LoadFile( path );
     	}
     	catch ( Exception err )
     	{
 		Console.WriteLine( "Impossible to load Scripts.dll. Error: {0}", err.ToString() );
     		return false;
     	}
     
     	m_Assemblies = new Assembly[] { scripts };
     	Console.WriteLine( "Scripts.dll loaded" );
     
     	Console.Write( "Scripts: Verifying..." );
     	Core.VerifySerialization();
     	Console.WriteLine( "done ({0} items, {1} mobiles)", Core.ScriptItems, Core.ScriptMobiles );
     
     	ArrayList invoke = new ArrayList();
     
     	Type[] types = scripts.GetTypes();
     
     	for ( int i = 0; i < types.Length; ++i )
     	{
 		MethodInfo m = types[i].GetMethod( "Configure", BindingFlags.Static | BindingFlags.Public );
     
     		if ( m != null )
     			invoke.Add( m );
     	}
     
     	invoke.Sort( new CallPriorityComparer() );
     
     	for ( int i = 0; i < invoke.Count; ++i )
     		((MethodInfo)invoke[i]).Invoke( null, null );
     
     	invoke.Clear();
     
     	World.Load();
     
     	for ( int i = 0; i < types.Length; ++i )
     	{
 		MethodInfo m = types[i].GetMethod( "Initialize", BindingFlags.Static | BindingFlags.Public );
     
     		if ( m != null )
     			invoke.Add( m );
     	}
     
     	invoke.Sort( new CallPriorityComparer() );
     
     	for ( int i = 0; i < invoke.Count; ++i )
     		((MethodInfo)invoke[i]).Invoke( null, null );
     
     	return true;
     }

Note on debug mode: I'm exepcting no one will run the server in debug mode on a production shard. For local testing purposes you can just have your IDE output Scripts.dll and Scripts.pdb into the Server.exe folder, which will automatically enable debug mode.

When you need to perform a scripts update, simply recompile Scripts.dll on your machine, then upload the file into the Update directory and reboot. The mod will automatically update.
 

Arya

Wanderer
-=Magic=- said:
Its can be done without any core modification.

Edit: nevermind. Yes you can do that by using a script that loads up the assmebly in Configure, calls all Configure methods and then all Initialize methods in Initialize. Still placing it in the core makes more sense to me, perhaps not worth if it's the only mod you make, but if you plan on modifying more than this why not?
 

brodock

Sorceror
Arya said:
Edit: nevermind. Yes you can do that by using a script that loads up the assmebly in Configure, calls all Configure methods and then all Initialize methods in Initialize. Still placing it in the core makes more sense to me, perhaps not worth if it's the only mod you make, but if you plan on modifying more than this why not?

i did the same thing some time ago loading the output dll files with the assembly.cfg
 

Arya

Wanderer
brodockbr said:
i did the same thing some time ago loading the output dll files with the assembly.cfg

Does this actually call the Configure and Initialize methods? It looks like those are invoked only on the compiled assemblies, not on the referenced libraries...
 

brodock

Sorceror
Arya said:
Does this actually call the Configure and Initialize methods? It looks like those are invoked only on the compiled assemblies, not on the referenced libraries...

thre process was something like this: you let scripts folder empty (i think only output folder needs to be inside)
then you get your scripts.CS.dll you created before and insert a line in data/assemblies.cfg to where your scripts.CS.dll is...
it will compile but will not find any scripts then it will load all of the from the dll (i tested this with beta 36... it's an "old method" lol.
 
Top