summaryrefslogtreecommitdiff
path: root/gamemode/server/pon.lua
diff options
context:
space:
mode:
authorAlexander Pickering <alexandermpickering@gmail.com>2016-05-21 19:29:52 -0400
committerAlexander Pickering <alexandermpickering@gmail.com>2016-05-21 19:29:52 -0400
commit6f25e16528f9f035c784055304b9f07c59f6782d (patch)
tree1d3bc0a7959a185b82dc01dd24b800850cc11783 /gamemode/server/pon.lua
parentdc64170e1c5fe08513ca46afa8224d4e9d95753b (diff)
downloadgmstranded-6f25e16528f9f035c784055304b9f07c59f6782d.tar.gz
gmstranded-6f25e16528f9f035c784055304b9f07c59f6782d.tar.bz2
gmstranded-6f25e16528f9f035c784055304b9f07c59f6782d.zip
First pass at createing a databaseing system
Diffstat (limited to 'gamemode/server/pon.lua')
-rw-r--r--gamemode/server/pon.lua361
1 files changed, 361 insertions, 0 deletions
diff --git a/gamemode/server/pon.lua b/gamemode/server/pon.lua
new file mode 100644
index 0000000..3c48a90
--- /dev/null
+++ b/gamemode/server/pon.lua
@@ -0,0 +1,361 @@
+--[[
+RECOMMENDED VERSION
+VERSION 1.2.1
+Copyright thelastpenguin™
+ You may use this for any purpose as long as:
+ - You don't remove this copyright notice.
+ - You don't claim this to be your own.
+ - You properly credit the author, thelastpenguin™, if you publish your work based on (and/or using) this.
+
+ If you modify the code for any purpose, the above still applies to the modified code.
+
+ The author is not held responsible for any d amages incured from the use of pON, you use it at your own risk.
+DATA TYPES SUPPORTED:
+ - tables - k,v - pointers
+ - strings - k,v - pointers
+ - numbers - k,v
+ - booleans- k,v
+ - Vectors - k,v
+ - Angles - k,v
+ - Entities- k,v
+ - Players - k,v
+
+CHANGE LOG
+V 1.1.0
+ - Added Vehicle, NPC, NextBot, Player, Weapon
+V 1.2.0
+ - Added custom handling for k,v tables without any array component.
+V 1.2.1
+ - fixed deserialization bug.
+V 1.3.0
+ - added custom handling of strings without any escaped characters.
+V 1.4.0
+ - added detection of numbers without requiring 'n' datatype. (10 datatypes one for each num it could start with)
+
+THANKS TO...
+ - VERCAS for the inspiration.
+]]
+
+
+local pon = {};
+_G.pon = pon;
+
+local type, count = type, table.Count ;
+local tonumber = tonumber ;
+
+do
+ local encode = {};
+
+ local tryCache ;
+
+ local cacheSize = 0;
+
+ encode['table'] = function( self, tbl, output, cache )
+
+ if( cache[ tbl ] )then
+ output[ #output + 1 ] = '('..cache[tbl]..')';
+ return ;
+ else
+ cacheSize = cacheSize + 1;
+ cache[ tbl ] = cacheSize;
+ end
+ -- CALCULATE COMPONENT SIZES
+ local nSize = #tbl;
+ local kvSize = count( tbl ) - nSize;
+
+ if( nSize == 0 and kvSize > 0 )then
+ output[ #output + 1 ] = '[';
+ else
+ output[ #output + 1 ] = '{';
+
+ if nSize > 0 then
+ for i = 1, nSize do
+ local v = tbl[ i ];
+ if v == nil then continue end
+ local tv = type( v );
+ -- HANDLE POINTERS
+ if( tv == 'string' )then
+ local pid = cache[ v ];
+ if( pid )then
+ output[ #output + 1 ] = '('..pid..')';
+ else
+ cacheSize = cacheSize + 1;
+ cache[ v ] = cacheSize;
+
+ self.string( self, v, output, cache );
+ end
+ else
+ self[ tv ]( self, v, output, cache );
+ end
+ end
+ end
+ end
+
+ if( kvSize > 0 )then
+ if( nSize > 0 )then
+ output[ #output + 1 ] = '~';
+ end
+ for k,v in next, tbl do
+ if( type( k ) ~= 'number' or k < 1 or k > nSize )then
+ local tk, tv = type( k ), type( v );
+
+ -- THE KEY
+ if( tk == 'string' )then
+ local pid = cache[ k ];
+ if( pid )then
+ output[ #output + 1 ] = '('..pid..')';
+ else
+ cacheSize = cacheSize + 1;
+ cache[ k ] = cacheSize;
+
+ self.string( self, k, output, cache );
+ end
+ else
+ self[ tk ]( self, k, output, cache );
+ end
+
+ -- THE VALUE
+ if( tv == 'string' )then
+ local pid = cache[ v ];
+ if( pid )then
+ output[ #output + 1 ] = '('..pid..')';
+ else
+ cacheSize = cacheSize + 1;
+ cache[ v ] = cacheSize;
+
+ self.string( self, v, output, cache );
+ end
+ else
+ self[ tv ]( self, v, output, cache );
+ end
+
+ end
+ end
+ end
+ output[ #output + 1 ] = '}';
+ end
+ -- ENCODE STRING
+ local gsub = string.gsub ;
+ encode['string'] = function( self, str, output )
+ --if tryCache( str, output ) then return end
+ local estr, count = gsub( str, ";", "\\;");
+ if( count == 0 )then
+ output[ #output + 1 ] = '\''..str..';';
+ else
+ output[ #output + 1 ] = '"'..estr..'";';
+ end
+ end
+ -- ENCODE NUMBER
+ encode['number'] = function( self, num, output )
+ output[ #output + 1 ] = tonumber( num )..';';
+ end
+ -- ENCODE BOOLEAN
+ encode['boolean'] = function( self, val, output )
+ output[ #output + 1 ] = val and 't' or 'f'
+ end
+ -- ENCODE VECTOR
+ encode['Vector'] = function( self, val, output )
+ output[ #output + 1 ] = ('v'..val.x..','..val.y)..(','..val.z..';');
+ end
+ -- ENCODE ANGLE
+ encode['Angle'] = function( self, val, output )
+ output[ #output + 1 ] = ('a'..val.p..','..val.y)..(','..val.r..';');
+ end
+ encode['Entity'] = function( self, val, output )
+ output[ #output + 1] = 'E'..(IsValid( val ) and (val:EntIndex( )..';') or '#');
+ end
+ encode['Player'] = encode['Entity'];
+ encode['Vehicle'] = encode['Entity'];
+ encode['Weapon'] = encode['Entity'];
+ encode['NPC'] = encode['Entity'];
+ encode['NextBot'] = encode['Entity'];
+
+ do
+ local empty, concat = table.Empty, table.concat ;
+ function pon.encode( tbl )
+ local output = {};
+ cacheSize = 0;
+ encode[ 'table' ]( encode, tbl, output, {} );
+ local res = concat( output );
+
+ return res;
+ end
+ end
+end
+
+do
+ local tonumber = tonumber ;
+ local find, sub, gsub, Explode = string.find, string.sub, string.gsub, string.Explode ;
+ local Vector, Angle, Entity = Vector, Angle, Entity ;
+
+ local decode = {};
+ decode['{'] = function( self, index, str, cache )
+
+ local cur = {};
+ cache[ #cache + 1 ] = cur;
+
+ local k, v, tk, tv = 1, nil, nil, nil;
+ while( true )do
+ tv = sub( str, index, index );
+ if( not tv or tv == '~' )then
+ index = index + 1;
+ break ;
+ end
+ if( tv == '}' )then
+ return index + 1, cur;
+ end
+
+ -- READ THE VALUE
+ index = index + 1;
+ index, v = self[ tv ]( self, index, str, cache );
+ cur[ k ] = v;
+
+ k = k + 1;
+ end
+
+ while( true )do
+ tk = sub( str, index, index );
+ if( not tk or tk == '}' )then
+ index = index + 1;
+ break ;
+ end
+
+ -- READ THE KEY
+
+ index = index + 1;
+ index, k = self[ tk ]( self, index, str, cache );
+
+ -- READ THE VALUE
+ tv = sub( str, index, index );
+ index = index + 1;
+ index, v = self[ tv ]( self, index, str, cache );
+
+ cur[ k ] = v;
+ end
+
+ return index, cur;
+ end
+ decode['['] = function( self, index, str, cache )
+
+ local cur = {};
+ cache[ #cache + 1 ] = cur;
+
+ local k, v, tk, tv = 1, nil, nil, nil;
+ while( true )do
+ tk = sub( str, index, index );
+ if( not tk or tk == '}' )then
+ index = index + 1;
+ break ;
+ end
+
+ -- READ THE KEY
+
+ index = index + 1;
+ index, k = self[ tk ]( self, index, str, cache );
+ -- READ THE VALUE
+ tv = sub( str, index, index );
+ index = index + 1;
+ index, v = self[ tv ]( self, index, str, cache );
+
+ cur[ k ] = v;
+ end
+
+ return index, cur;
+ end
+
+ -- STRING
+ decode['"'] = function( self, index, str, cache )
+ local finish = find( str, '";', index, true );
+ local res = gsub( sub( str, index, finish - 1 ), '\\;', ';' );
+ index = finish + 2;
+
+ cache[ #cache + 1 ] = res;
+ return index, res;
+ end
+ -- STRING NO ESCAPING NEEDED
+ decode['\''] = function( self, index, str, cache )
+ local finish = find( str, ';', index, true );
+ local res = sub( str, index, finish - 1 )
+ index = finish + 1;
+
+ cache[ #cache + 1 ] = res;
+ return index, res;
+ end
+
+ -- NUMBER
+ decode['n'] = function( self, index, str, cache )
+ index = index - 1;
+ local finish = find( str, ';', index, true );
+ local num = tonumber( sub( str, index, finish - 1 ) );
+ index = finish + 1;
+ return index, num;
+ end
+ decode['0'] = decode['n'];
+ decode['1'] = decode['n'];
+ decode['2'] = decode['n'];
+ decode['3'] = decode['n'];
+ decode['4'] = decode['n'];
+ decode['5'] = decode['n'];
+ decode['6'] = decode['n'];
+ decode['7'] = decode['n'];
+ decode['8'] = decode['n'];
+ decode['9'] = decode['n'];
+ decode['-'] = decode['n'];
+
+ -- POINTER
+ decode['('] = function( self, index, str, cache )
+ local finish = find( str, ')', index, true );
+ local num = tonumber( sub( str, index, finish - 1 ) );
+ index = finish + 1;
+ return index, cache[ num ];
+ end
+
+ -- BOOLEAN. ONE DATA TYPE FOR YES, ANOTHER FOR NO.
+ decode[ 't' ] = function( self, index )
+ return index, true;
+ end
+ decode[ 'f' ] = function( self, index )
+ return index, false;
+ end
+
+ -- VECTOR
+ decode[ 'v' ] = function( self, index, str, cache )
+ local finish = find( str, ';', index, true );
+ local vecStr = sub( str, index, finish - 1 );
+ index = finish + 1; -- update the index.
+ local segs = Explode( ',', vecStr, false );
+ return index, Vector( tonumber( segs[1] ), tonumber( segs[2] ), tonumber( segs[3] ) );
+ end
+ -- ANGLE
+ decode[ 'a' ] = function( self, index, str, cache )
+ local finish = find( str, ';', index, true );
+ local angStr = sub( str, index, finish - 1 );
+ index = finish + 1; -- update the index.
+ local segs = Explode( ',', angStr, false );
+ return index, Angle( tonumber( segs[1] ), tonumber( segs[2] ), tonumber( segs[3] ) );
+ end
+ -- ENTITY
+ decode[ 'E' ] = function( self, index, str, cache )
+ if( str[index] == '#' )then
+ index = index + 1;
+ return NULL ;
+ else
+ local finish = find( str, ';', index, true );
+ local num = tonumber( sub( str, index, finish - 1 ) );
+ index = finish + 1;
+ return index, Entity( num );
+ end
+ end
+ -- PLAYER
+ decode[ 'P' ] = function( self, index, str, cache )
+ local finish = find( str, ';', index, true );
+ local num = tonumber( sub( str, index, finish - 1 ) );
+ index = finish + 1;
+ return index, Entity( num ) or NULL;
+ end
+
+ function pon.decode( data )
+ local _, res = decode[sub(data,1,1)]( decode, 2, data, {});
+ return res;
+ end
+end