I really need to get back into updating this more often..
Backend Update..
Updated the blog again to the latest version of WordPress. This time being 3.0, although it looks exactly the same. Yay I guess. Nothing really much changed, just some random updates and fixes for the software. Still, the best blogging software on the net.
patchLib v3?
So I’ve been working on a side project that involves some things that patchLib does. (Rendering a Gui via GDI / UpdateLayeredWindow.) This turned into a bug fix experience. By this I mean I found the reason to a few bugs in patchLib v2, as well as finally figured out how to fully draw Win32 controls ontop of a layered window. Sadly there are still some issues that I can’t fully figure out yet, but I am working on it slowly and when I’m bored. But I am unsure if this will spark me to write patchLib v3, so we’ll see.
Garrys Mod
I got into Garrys Mod for a while, mainly because of the Lua programming. For those that don’t know, Garrys Mod is entirely ran using Lua. While the main core of the game is done using the Orange Box engine from Valve, the game is powered by Lua in the end. All the events and such are done based on Lua scripts and so on. In my opinion, GMod is the best example of how powerful Lua can be as an embedded language in an application.
I mainly got into GMod because of a few friends playing a private gamemode. I got my hands on this gamemode and started my own server for a few months. It never really exploded with popularity but we did have some regulars which was fun for the time being. Overall I spent majority of my time not playing but fixing bugs in the Lua scripts from the original author. Which really got me interested in Lua again.
Two major things in GMod that really got me into Lua again was their implementation of timers and hooks. My first time around with Lua I tried to get something similar working but failed. However this time around I’ve finally figured it out. Granted I have no idea if I’m doing it “correctly” or the same as GMod but I did get my timer and hook modules working. They are based on GMods scripts, but his scripts are based on old Lua stuff that’s been done before as well.
I’ve also modded my Lua install to include bitwise operations and logical operators. (Using a community patch, and with the help of a Lua forum user.) Which allows users to use things such as:
!, !=, &&, ||, &, |, ^^, <>, ~,
For testing my Lua stuff I use the following script:
–[[
Lua Demonstration Script
(c) 2010 atom0s
This script is used to test a personal installation
and modification of Lua. This script will not work
on stock Lua installs!
]]–
print( string.format( "test.lua – Script started at: %d", os.time() ) );
— Require hooking package.
require( ‘hook’ );
local hook = hook;
— Require timer package.
require( ‘timer’ );
local timer = timer;
— Logical operation tests.
local bTest1 = false;
local nTest2 = 1234;
local nTest3 = 4321;
print( string.format(
"Logical test #1: %snLogical test #2: %snLogical test #3: %s",
tostring( !bTest1 && bTest1 != true ),
tostring( nTest2 == 1234 && nTest3 == 4321 ),
tostring( nTest2 == 9999 || nTest3 == 4321 )
) );
— Lua config table tests.
local config = config;
config[ "test1" ] = 1234;
config[ "test2" ] = "Hello world!";
— LuaBind exposure test.
local pObject = CTest();
local nReturn = pObject:HelloWorld( 10, 90 );
print( string.format( "[LuaBind Test] HelloWorld returned: %d", nReturn ) );
— Lua call from C++ test.
function SomeFunction ( )
print( string.format( "Test function was called from C++!" ) );
return 0;
end
— Create a test timer to tick every 5 seconds.
timer.Create( ‘TestTimer’, 5, 0,
function ( )
print( "[Tick!] Test timer was pulsed! " .. tostring( os.time() ) );
end
);
— Hook module test #1 – Event callback.
function ExampleHook_Callback ( name, health, armor )
print( string.format(
"[Hooked] ExampleHook event was called: %s – %d – %d",
name, health, armor
) );
return 0;
end
hook.Add( "ExampleHook", "ExampleHook_Test", ExampleHook_Callback );
— Hook module test #2 — WindowProc.
function LuaWindowProc ( hWnd, uMsg, wParam, lParam )
— WM_CHAR
if( uMsg == 0x0101 ) then
— User pressed F1.
if( ( wParam & 0xFFFF ) == 0x70 ) then
print( "[LuaWindowProc] User pressed F1!" );
end
end
return 0;
end
hook.Add( "WindowProc", "WindowProcLua", LuaWindowProc );
print( string.format( "test.lua – Script finished at: %d", os.time() ) );
I personally don’t suggest handling the window procedure through Lua as it can get laggy depending on how indepth your application is. This was personally just for testing events and stuff though on my part.
I wrote a wrapper for Lua to handle a more functional method of calling things in Lua, handling the hook module, and to easily integrate Lua with a full-scale project. I’m sure it has it’s flaws and I’m not a professional coder so I’m sure things could be done differently. I’m not one to do templated coding as well so I know parts of this could be templated too. Here’s the header of what I got done so far:
/**
* ScriptManager.h
* (c) atom0s 2010 [atom0s@live.com]
*
* This is a simple singleton wrapper for Lua to easily embed Lua into projects.
* This class is not finalized and is subject to change without notice!
*
* This class makes use of:
* - boost : http://www.boost.org/
* - Lua : http://www.lua.org/
* - Luabind : http://www.rasterbar.com/products/luabind.html
*
*/
#pragma once
#ifndef __SCRIPTMANAGER_H_INCLUDED__
#define __SCRIPTMANAGER_H_INCLUDED__
#define STRICT
#define WIN32_LEAN_AND_MEAN
#include <Windows.h>
#include <string>
#include <boost/smart_ptr.hpp>
#pragma comment( lib, "lua5.1.lib" )
extern "C"
{
#include <lua.h>
#include <lualib.h>
#include <lauxlib.h>
}
#pragma comment( lib, "luabindd.lib" )
#include <luabind/luabind.hpp>
#include "Logger.h"
/**
* Validates the given Lua state is initialized.
*
* @param s Current Lua state.
* @param r Return value if state is not valid.
*/
#define STATE_CHECK( s, r ) if( !s ) return r;
/**
* Checks the Lua stack for stray items.
*
* @param pState Current Lua state.
* @noreturn
*/
inline void __CheckLuaStack( lua_State* pState )
{
// Obtain stack count.
int nStack = lua_gettop( pState );
if( nStack > 0 )
{
Logger::instance()->Log( "[LUA:WARNING] Lua stack was not properly cleared!" );
for( int x = 1; x <= nStack; x++ )
{
int nType = lua_type( pState, -1 );
Logger::instance()->Log( "[LUA:STACK] (%d) %s", x, lua_typename( pState, nType ) );
}
lua_pop( pState, nStack );
Logger::instance()->Log( "-------------------------------------------------" );
}
}
/**
* Cleans the Lua stack.
*
* @param pState Current Lua state.
* @noreturn
*/
inline void __CleanLuaStack( lua_State* pState )
{
int nStack = lua_gettop( pState );
if( nStack > 0 ) lua_pop( pState, nStack );
}
/**
* Prints the current error on the stack.
*
* @param pState Current Lua state.
* @noreturn
*/
inline void __PrintStackError( lua_State* pState )
{
int nStack = lua_gettop( pState );
if( nStack == 1 && ( lua_type( pState, -1 ) == LUA_TSTRING ) )
{
const char* pMessage = lua_tostring( pState, -1 );
if( pMessage != NULL )
Logger::instance()->Log( "[LUA:ERROR] %s", pMessage );
lua_pop( pState, 1 );
}
}
/**
* ScriptManager
*
* Lua script manager class.
*/
class ScriptManager
{
static boost::shared_ptr< ScriptManager > m_vInstance;
lua_State* m_vState;
public:
static boost::shared_ptr< ScriptManager > instance( void );
public:
ScriptManager ( void );
~ScriptManager ( void );
public:
HRESULT Initialize ( void );
HRESULT Release ( bool bCollect = false );
public:
HRESULT RunScript ( const std::string& strFile );
HRESULT RunString ( const std::string& strScript );
public:
bool FunctionExists ( const std::string& strFunction );
bool TableExists ( const std::string& strTable );
bool TableMemberExists ( const std::string& strTable, const std::string& strMember );
bool VariableExists ( const std::string& strVariable );
public:
bool CallFunction ( const std::string& strFunction );
bool CallFunction ( int nArgCount = 0 );
public:
bool PushFunction ( const std::string& strFunction );
bool PushTable ( const std::string& strTable );
bool PushField ( const std::string& strField );
bool PushString ( const std::string& strParam );
bool PushNumber ( int nParam );
bool PushBoolean ( bool bParam );
bool PushPointer ( void* lpParam ); // LUA_TLIGHTUSERDATA
bool PopStack ( int nCount );
public:
HRESULT SetGlobal ( const std::string& strKey, std::string& strValue );
HRESULT SetGlobal ( const std::string& strKey, int nValue );
HRESULT SetGlobal ( const std::string& strKey, bool bValue );
HRESULT SetGlobal ( const std::string& strKey, void* lpValue ); // LUA_TLIGHTUSERDATA
public:
HRESULT GetConfigValue ( const std::string& strKey, std::string& strResult );
HRESULT SetConfigValue ( const std::string& strKey, const std::string& strValue );
HRESULT GetConfigValue ( const std::string& strKey, int& nResult );
HRESULT SetConfigValue ( const std::string& strKey, int nValue );
HRESULT GetConfigValue ( const std::string& strKey, bool& bResult );
HRESULT SetConfigValue ( const std::string& strKey, bool bValue );
HRESULT GetConfigValue ( const std::string& strKey, void** lpResult );
HRESULT SetConfigValue ( const std::string& strKey, void* lpValue );
public:
lua_State* GetState ( void ) { return this->m_vState; }
};
class CTest
{
public:
CTest( void ) { }
~CTest( void ) { }
int HelloWorld( int nArg1, int nArg2 )
{
return ( nArg1 + nArg2 );
}
};
#endif // __SCRIPTMANAGER_H_INCLUDED__
So basically at the moment I’ve just fixated myself with Lua stuff, learning as much about it as I can, while looking for some usages I may have for it later down the line with coding.