.NET Modules

Well, I finally finished the wrappers. I’m sure there will be several bugs. The code isn’t exactly clean. But it works.

Download: http://cdbarrett.com/dump/GarrysmodNET.zip
Source: http://cdbarrett.com/dump/GarrysmodNET_src.zip

Installation:
[ul]
[li]Copy Garrysmod.Modules.dll into the garrysmod folder. The one with hl2.exe in it.
[/li][li]Copy gm_GarrysmodDotNet.dll into the garrysmod/lua/includes/modules/ folder
[/li][li]Place .NET Modules inside garrysmod/lua/includes/modules/DotNet/
[/li][/ul]

All things must derive from GMModule, this includes Modules and MetaTables.
Each module/metatable should contain the proper attribute.
You need to add Garrysmod.Modules.dll as a reference to your project.

Example:


/*------------------------------------
	Types
------------------------------------*/
public class XmlTypes
{

	public const int XmlDocument = 15000;
	public const int XmlNode = 15001;

}

/*------------------------------------
	MetaXmlDocument
------------------------------------*/
[LuaMetaTable( "XmlDocument", XmlTypes.XmlDocument )]
public class MetaXmlDocument : GMModule
{

	// -------- GC
	[LuaFunction( "__gc", Function.Meta )]
	[LuaTypeCheck( 1, XmlTypes.XmlDocument )]
	public int GarbageCollect( )
	{

		Lua.Msg( "Collected XmlDocument
" );

		// Free
		Lua.FreeManagedObject( 1 );

		return 0;

	}

	// -------- DocumentElement
	[LuaFunction( "DocumentElement", Function.Normal )]
	[LuaTypeCheck( 1, XmlTypes.XmlDocument )]
	public int DocumentElement( )
	{

		// get document
		XmlDocument doc = (XmlDocument)Lua.GetManagedObject( 1 );

		// push the document element
		LuaObject metatable = Lua.GetMetaTable( "XmlNode", XmlTypes.XmlNode );
		Lua.PushManagedObject( metatable, doc.DocumentElement );

		return 1;

	}

	// -------- SelectNodes
	[LuaFunction( "SelectNodes", Function.Normal )]
	[LuaTypeCheck( 1, XmlTypes.XmlDocument )]
	[LuaTypeCheck( 2, Types.String )]
	public int SelectNodes( )
	{

		// get document
		XmlDocument doc = (XmlDocument)Lua.GetManagedObject( 1 );

		// get the path
		string path = Lua.GetString( 2 );

		// get the namespace manager
		XmlNamespaceManager namespacemanager = new XmlNamespaceManager( doc.NameTable );
		namespacemanager.AddNamespace( String.Empty, doc.NamespaceURI );

		// select nodes
		XmlNodeList list = doc.SelectNodes( path, namespacemanager );

		// node metatable
		LuaObject meta = Lua.GetMetaTable( "XmlNode", XmlTypes.XmlNode );

		// populate a lua table with the nodes
		LuaObject table = Lua.GetNewTable();
		float count = 1.0f;
		foreach( XmlNode node in list )
		{

			// create a new temporary object
			LuaObject temp = Lua.NewTemporaryObject();
			Lua.PushManagedObject( meta, node );
			temp.SetFromStack( -1 );

			// add
			table.SetMember( count++, temp );

		}

		// push the table
		Lua.Push( table );

		return 1;

	}

	// -------- SelectSingleNode
	[LuaFunction( "SelectSingleNode", Function.Normal )]
	[LuaTypeCheck( 1, XmlTypes.XmlDocument )]
	[LuaTypeCheck( 2, Types.String )]
	public int SelectSingleNode( )
	{

		// get document
		XmlDocument doc = (XmlDocument)Lua.GetManagedObject( 1 );

		// get the path
		string path = Lua.GetString( 2 );

		// get the namespace manager
		XmlNamespaceManager namespacemanager = new XmlNamespaceManager( doc.NameTable );
		namespacemanager.AddNamespace( String.Empty, doc.NamespaceURI );

		// select nodes
		XmlNode node = doc.SelectSingleNode( path, namespacemanager );

		// valid node?
		if( node != null )
		{

			// push node
			LuaObject meta = Lua.GetMetaTable( "XmlNode", XmlTypes.XmlNode );
			Lua.PushManagedObject( meta, node );

			return 1;

		}

		return 0;

	}

}

/*------------------------------------
	MetaXmlNode
------------------------------------*/
[LuaMetaTable( "XmlNode", XmlTypes.XmlNode )]
public class MetaXmlNode : GMModule
{

	// -------- GC
	[LuaFunction( "__gc", Function.Meta )]
	[LuaTypeCheck( 1, XmlTypes.XmlNode )]
	public int GarbageCollect( )
	{

		Lua.Msg( "Collected XmlNode
" );

		// free
		Lua.FreeManagedObject( 1 );

		return 0;

	}

	// -------- NextSibling
	[LuaFunction( "NextSibling", Function.Normal )]
	[LuaTypeCheck( 1, XmlTypes.XmlNode )]
	public int NextSibling( )
	{

		// get document
		XmlNode node = (XmlNode)Lua.GetManagedObject( 1 );

		// have a sibling?
		if( node.NextSibling != null )
		{

			// push the document element
			LuaObject metatable = Lua.GetMetaTable( "XmlNode", XmlTypes.XmlNode );
			Lua.PushManagedObject( metatable, node.NextSibling );

			return 1;

		}

		return 0;

	}

	// -------- FirstChild
	[LuaFunction( "FirstChild", Function.Normal )]
	[LuaTypeCheck( 1, XmlTypes.XmlNode )]
	public int FirstChild( )
	{

		// get document
		XmlNode node = (XmlNode)Lua.GetManagedObject( 1 );

		// have a child?
		if( node.FirstChild != null )
		{

			// push the document element
			LuaObject metatable = Lua.GetMetaTable( "XmlNode", XmlTypes.XmlNode );
			Lua.PushManagedObject( metatable, node.FirstChild );

			return 1;

		}

		return 0;

	}


	// -------- InnerText
	[LuaFunction( "InnerText", Function.Normal )]
	[LuaTypeCheck( 1, XmlTypes.XmlNode )]
	public int InnerText( )
	{

		// get document
		XmlNode node = (XmlNode)Lua.GetManagedObject( 1 );

		// push the text
		Lua.Push( node.InnerText );

		return 1;

	}

	// -------- InnerXml
	[LuaFunction( "InnerXml", Function.Normal )]
	[LuaTypeCheck( 1, XmlTypes.XmlNode )]
	public int InnerXml( )
	{

		// get document
		XmlNode node = (XmlNode)Lua.GetManagedObject( 1 );

		// push the text
		Lua.Push( node.InnerXml );

		return 1;

	}

	// -------- OuterXml
	[LuaFunction( "OuterXml", Function.Normal )]
	[LuaTypeCheck( 1, XmlTypes.XmlNode )]
	public int OuterXml( )
	{

		// get document
		XmlNode node = (XmlNode)Lua.GetManagedObject( 1 );

		// push the text
		Lua.Push( node.OuterXml );

		return 1;

	}

}

/*------------------------------------
	XmlModule
------------------------------------*/
[LuaModule( "Xml" )]
public class XmlModule : GMModule
{

	// -------- NewDocument
	[LuaFunction( "LoadDocument", Function.Normal )]
	[LuaTypeCheck( 1, Types.String )]
	public int LoadDocument( )
	{

		// create a document
		XmlDocument doc = new XmlDocument();
		doc.Load( Lua.GetString( 1 ) );

		// push it
		LuaObject metatable = Lua.GetMetaTable( "XmlDocument", XmlTypes.XmlDocument );
		Lua.PushManagedObject( metatable, doc );

		return 1;

	}

}

And now I have to learn .Net. (C#/VB I know, don’t rip my balls off.)

Yay, you released it :smiley:

Ummmm… What does it do?

Awesome!

This is great, thanks a lot for this Jinto.

What exactly is this ?

It lets you make LUA DLL’s for GMODE using .NET (Microsoft’s Java-like software). Only interesting to developers using that, of course.

I tried recompiling your binary (the C++.net one) with debug but it spammed a shit load of errors, apparently you’re calling functions which are not in ILuaInterface (I checked, their not), am I using the wrong version of that header or is the one from google code’s svn correct? Or am I a moron?

You’re most likely using an older version, the latest version of the interface headers are in the SQLite module over at googlecode. You also need to mark ILuaInterface as public and compile with /clr.

Ah, thanks, I was using the old original module base (the one with the Msg function in it).

Edit:

Wait a sec… Tier1/utlvector.h!? Isn’t that part of the source engine code? You mean I’ll have to completely install the source code for source?

exact

Yes I succeeded in compiling but VS is still complaining about the link missing the Lua symbols. I’m unsure if this will affect the build so I’ll leave it at that before getting mad at the wrong problem, till Chad fixes the bugs in the table get all members I’ll just use a work around.

Yes, I know what’s wrong with that method. I’ll be fixing it soon. Just need to find the time.

Sorry to bump this but what is the XmlTypes class used for?

For example:


Lua.GetMetaTable( "XmlNode", XmlTypes.XmlNode );

What is it doing?

It’s my way of using globals. I could just as easily have placed those constants within each of the meta tables, which on second thought would have been a better idea.

But… what do the numbers actually do/represent?

They are a unique number that represents that metatable.

Basically everything in the C++ GML interface is represented in type by a unique enumerator.

This works great so far! But I have a question… Why does the Lua.PushLong take integers? Shouldn’t it be a long?