Index: /trunk/nv/core/handle.hh
===================================================================
--- /trunk/nv/core/handle.hh	(revision 332)
+++ /trunk/nv/core/handle.hh	(revision 333)
@@ -29,4 +29,5 @@
 	public:
 		typedef T value_type;
+		typedef TAG tag_type;
 		static const int INDEX_BITS   = IBITS;
 		static const int COUNTER_BITS = IBITS;
@@ -48,8 +49,21 @@
 
 		handle( T a_index, T a_counter ) : m_index( a_index ), m_counter( a_counter ) {}
-		template < typename H, typename I >
-		friend class index_store;
-	};
-
+		template < typename H >
+		friend class handle_operator;
+	};
+
+	template < typename HANDLE >
+	class handle_operator
+	{
+	public:
+		typedef typename HANDLE::value_type value_type;
+
+		static HANDLE create( value_type index, value_type counter )
+		{
+			return HANDLE( index, counter );
+		}
+		static value_type get_counter( const HANDLE& h ) { return h.m_counter; }
+		static value_type get_index( const HANDLE& h ) { return h.m_index; }
+	};
 
 
@@ -66,31 +80,33 @@
 		handle create_handle( index_type index )
 		{
+			typedef handle_operator<HANDLE> hop; 
 			value_type i       = get_free_entry();
 			m_entries[i].index = index;
 			m_entries[i].counter++;
-			return handle( i, m_entries[i].counter );
+			return hop::create( i, m_entries[i].counter );
 		}
 
 		void free_handle( handle h )
 		{
-			m_entries[ h.m_index ].index     = -1;
-			m_entries[ h.m_index ].next_free = -1;
+			m_entries[ h.index() ].index     = -1;
+			m_entries[ h.index() ].next_free = -1;
 			if ( m_last_free == -1 )
 			{
-				m_first_free = m_last_free = h.m_index;
+				m_first_free = m_last_free = h.index();
 				return;
 			}
-			m_entries[ (unsigned)m_last_free ].next_free = h.m_index;
-			m_last_free = h.m_index;
+			m_entries[ (unsigned)m_last_free ].next_free = h.index();
+			m_last_free = h.index();
 		}
 
 		void swap_indices( handle h1, handle h2 )
 		{
-			std::swap( m_entries[ h1.m_index ].index, m_entries[ h2.m_index ].index );
+			std::swap( m_entries[ h1.index() ].index, m_entries[ h2.index() ].index );
 		}
 
 		sint32 get_index( handle h ) const
 		{
-			return m_entries[ h.m_index ].counter == h.m_counter ? m_entries[ h.m_index ].index : -1;
+			typedef handle_operator<HANDLE> hop; 
+			return m_entries[ h.index() ].counter == hop::get_counter(h) ? m_entries[ h.index() ].index : -1;
 		}
 	private:
Index: /trunk/nv/lua/lua_handle.hh
===================================================================
--- /trunk/nv/lua/lua_handle.hh	(revision 333)
+++ /trunk/nv/lua/lua_handle.hh	(revision 333)
@@ -0,0 +1,107 @@
+// Copyright (C) 2014 ChaosForge Ltd
+// http://chaosforge.org/
+//
+// This file is part of NV Libraries.
+// For conditions of distribution and use, see copyright notice in nv.hh
+#ifndef NV_LUA_HANDLE_HH
+#define NV_LUA_HANDLE_HH
+
+#include <nv/core/common.hh>
+#include <nv/core/handle.hh>
+#include <nv/lua/lua_values.hh>
+
+namespace nv
+{
+	namespace lua
+	{
+		//void register_handle( lua_State* L );
+
+		template < typename T >
+		struct handle_tag_table
+		{
+
+		};
+
+		template <>
+		struct handle_tag_table< void >
+		{
+			static const int REGISTRYINDEX = 1;
+		};
+
+		namespace detail
+		{
+			struct handle_struct
+			{
+				uint32 index;
+				uint32 counter;
+			};
+
+			union handle_conversion
+			{
+				handle_struct h;
+				double        d;
+			};
+
+			void push_handle_impl( lua_State* L, int pseudoindex, uint32 index );
+			handle_struct to_handle_impl( lua_State* L, int i, uint32 dindex, uint32 dcounter );
+			void register_handle_impl( lua_State* L, int pseudoindex, uint32 index, uint32 counter, bool empty );
+			void unregister_handle_impl( lua_State* L, int pseudoindex, uint32 index );
+		}
+
+		template < typename H >
+		void push_handle( lua_State* L, const H& handle )
+		{
+			typedef handle_operator<H> hop; 
+			detail::push_handle_impl( L, handle_tag_table< typename H::tag_type >::REGISTRYINDEX, hop::get_index( handle ) );
+		};
+
+		template < typename H >
+		H to_handle( lua_State* L, int index )
+		{
+			typedef handle_operator<H> hop; 
+			detail::handle_struct h = detail::to_handle_impl( L, index, 0, 0 );
+			return hop::create( h.index, h.counter );
+		};
+
+		template < typename H >
+		H to_handle( lua_State* L, int index, const H& def )
+		{
+			typedef handle_operator<H> hop; 
+			detail::handle_struct h = detail::to_handle_impl( L, index, hop::get_index( handle ), hop::get_counter( handle ) );
+			return hop::create( h.index, h.counter );
+		};
+
+
+		template < 
+			typename T, 
+			unsigned IBITS,
+			unsigned CBITS,
+			typename TAG 
+		>
+		struct pass_traits< handle< T, IBITS, CBITS, TAG > >
+		{
+			typedef handle< T, IBITS, CBITS, TAG > value_type;
+			static void push( lua_State *L, const value_type& p ) { push_handle< value_type >( L, p ); }
+			static value_type to( lua_State *L, int index ) { return to_handle< value_type >( L, index ); }
+			static value_type to( lua_State *L, int index, const value_type& def ) { return to_handle< value_type >( L, index, def ); }
+		};
+
+		template < typename H >
+		void register_handle( lua_State *L, const H& handle, bool empty = true )
+		{
+			typedef handle_operator<H> hop; 
+			detail::register_handle_impl( L, handle_tag_table< typename H::tag_type >::REGISTRYINDEX, hop::get_index( handle ), hop::get_counter( handle ), empty );
+		}
+
+		template < typename H >
+		void unregister_handle( lua_State *L, const H& handle )
+		{
+			typedef handle_operator<H> hop; 
+			detail::unregister_handle_impl( L, handle_tag_table< typename H::tag_type >::REGISTRYINDEX, hop::get_index( handle ) );
+		}
+
+	}
+
+}
+
+#endif // NV_LUA_GLM_HH
Index: /trunk/nv/lua/lua_state.hh
===================================================================
--- /trunk/nv/lua/lua_state.hh	(revision 332)
+++ /trunk/nv/lua/lua_state.hh	(revision 333)
@@ -14,4 +14,5 @@
 #include <nv/core/common.hh>
 #include <nv/core/flags.hh>
+#include <nv/core/handle.hh>
 #include <istream>
 #include <map>
Index: /trunk/src/lua/lua_handle.cc
===================================================================
--- /trunk/src/lua/lua_handle.cc	(revision 333)
+++ /trunk/src/lua/lua_handle.cc	(revision 333)
@@ -0,0 +1,66 @@
+// Copyright (C) 2014 ChaosForge Ltd
+// http://chaosforge.org/
+//
+// This file is part of Nova libraries.
+// For conditions of distribution and use, see copyright notice in nv.hh
+
+#include "nv/lua/lua_handle.hh"
+
+#include "nv/lua/lua_raw.hh"
+
+// pseudoindex must be valid
+void nv::lua::detail::push_handle_impl( lua_State* L, int pseudoindex, uint32 index )
+{
+	int stack = lua_gettop(L);
+	lua_rawgeti( L, LUA_REGISTRYINDEX, pseudoindex ); // table
+	lua_rawgeti( L, -1, index );                      // table, entry
+	if ( lua_isnil( L, -1 ) )
+	{
+		NV_LOG( nv::LOG_ERROR, "NIL" );
+	}
+	lua_replace( L, stack + 1 );
+	lua_settop( L, stack + 1 );
+}
+
+nv::lua::detail::handle_struct nv::lua::detail::to_handle_impl( lua_State* L, int i, uint32 dindex, uint32 dcounter )
+{
+	handle_conversion hc;
+	hc.h.index   = dindex;
+	hc.h.counter = dcounter;
+	if ( lua_istable( L, i ) )
+	{
+		lua_rawgeti( L, i, 1 ); // handle as double
+		hc.d = lua_tonumber( L, -1 );
+		lua_pop( L, 1 );
+	}
+	return hc.h;
+}
+
+void nv::lua::detail::register_handle_impl( lua_State* L, int pseudoindex, uint32 index, uint32 counter, bool empty )
+{
+	if ( empty )
+	{
+		lua_newtable( L );
+	}
+	if ( !lua_istable( L, -1 ) ) return;
+
+	handle_conversion hc;
+	hc.h.index   = index;
+	hc.h.counter = counter;
+	lua_pushnumber( L, hc.d );
+	lua_rawseti( L, -2, 1 );
+
+	lua_rawgeti( L, LUA_REGISTRYINDEX, pseudoindex );
+	lua_insert( L, -2 );
+	lua_rawseti( L, -2, index );
+	lua_pop( L, 1 );
+}
+
+void nv::lua::detail::unregister_handle_impl( lua_State* L, int pseudoindex, uint32 index )
+{
+	int stack = lua_gettop(L);
+	lua_rawgeti( L, LUA_REGISTRYINDEX, pseudoindex ); // table
+	lua_pushinteger( L, 0 );
+	lua_rawseti( L, -2, index );
+	lua_settop( L, stack );
+}
Index: /trunk/src/lua/lua_state.cc
===================================================================
--- /trunk/src/lua/lua_state.cc	(revision 332)
+++ /trunk/src/lua/lua_state.cc	(revision 333)
@@ -261,4 +261,15 @@
 	lua_pushliteral(m_state, LUA_TABLIBNAME);
 	lua_call(m_state, 1, 0);
+
+	{
+		// Preregister 8 references for Handle registry
+		lua_newtable(m_state);
+		NV_ASSERT( luaL_ref( m_state, LUA_REGISTRYINDEX ) == 1, "First reference not 1!" );
+		for ( uint32 i = 1; i < 8; ++i )
+		{
+			lua_newtable(m_state);
+			luaL_ref( m_state, LUA_REGISTRYINDEX );
+		}
+	}
 
 	if ( load_libs )
