Worst-case scenario: the UEd Goblin wipes the map and burns down your house.

UE1:NBSP (Class)

From Unreal Wiki, The Unreal Engine Documentation Site
Revision as of 14:20, 2 April 2009 by Azura (Talk | contribs) (Methods)

Jump to: navigation, search

Purpose

This is the mutator part of NBSP.

Variables

  • var NBSPLog logger - Reference to an instance of the Logger ( NBSPLog (Class) ) class
  • var NBSPSettings settings
  • var NBSPReporter reporter - Reference to Reporter class
  • var NBSPWorker worker
  • var NBSPPackages packages
  • var NBSPMsgMutator fix
  • var NBSPChecker nbsp[256]
  • var NBSPPoll poll[256]
  • var NBSPNotify ny
  • var int nbspMagik - Used for generating magic number
  • var PlayerInfo PI[256] - Struct containing various information on players
  • var string paths, canvas, packs
  • var private float zTCT
  • var string PureVersion
  • var config string h
  • var Sound shs
  • var config string AllowedClientVersions - List of allowed client versions
  • var config bool UseNBSPLog;
  • var config string LogDirectory - Directory where external log should be placed.
  • var config bool LogSettings
  • var config bool LogIdentd
  • var config bool LogToExternal - Boolean to indicate if external log should be used.
  • var config bool UTPureMode
  • var config bool DebugMode - Used for toggling debug mode

Methods

  • AddMutator( Mutator m )
Added to keep the mutator chain working when NBSP is made the basemutator.
  • nlog( string a )
  • dlog( string a )
Used for debug logging.
  • Spawned()
  • Tick( float a)
  • ServerInit ()
  • checkPackages ( NBSPChecker a, playerpawn b, int c )
  • CheckPackage ( int i, int j, int m )
  • RunningPackageCheck ( int c, int i, string e )
  • checkmods ( NBSPChecker a, playerpawn b, int c )
  • checkmods2 ( NBSPChecker a, playerpawn b, int c )
  • CheckClasses ( NBSPChecker a, playerpawn b, int i)
  • CheckActors ( NBSPChecker a, playerpawn b, int c, string e )
  • ScanConsole ( NBSPChecker a, playerpawn b, NBSPPoll p, string e )
  • int getArray ( int b, string c )
  • sortcanvas ( NBSPChecker a, playerpawn b, int c )
  • confpaths()
  • string getinfo (int b)
  • logclient (int b)
  • int getVersion(int i) { return PI[i].version; }
  • int returnCRC(int b, int i) { return PI[b].CRC[i]; }
  • string returnPaths(int b) { return PI[b].paths; }
  • NBSPPoll findpoll(int i) { return poll[i]; }
  • int amount(int i) { return PI[i].upackagecount; }
  • killPoll(int i)
  • DestroyPI(int i)
  • string IPOnly(string IP)
  • fa( NBSPChecker a, PlayerPawn p )
  • bool xx()
Returns true if the game has ended or the countdown is higher than zeeo in requireready mode.
  • ModifyLogin(out class<playerpawn> SpawnClass, out string pt, out string o)
  • string xxF(string o, string i, string v)
  • string xxG(string zc)
  • bool xxV(string n)
  • NextTeam(PlayerPawn p)
  • bool HandlePickupQuery(Pawn o, Inventory inv, out byte b)
  • DisableNBSP()
  • EnableNBSP()
  • bool IsPaused ()
  • Mutate( string a, PlayerPawn b )
  • Destroyed()
  • string rts(coerce string t, coerce string r, coerce string w)
  • int Hash(String a)
  • string fb(out string a)
  • string fc(out string a)

Complete source code

//=============================================================================
// NBSP ==> NoBullShitPlus v1.09
//=============================================================================
 
class NBSP expands Mutator config(NBSP109);
 
var String version;
 
struct PlayerInfo { 
	var string Name, ip, mods[128], packages[256], upackagesT[128], upackagesT2[128], Class, RenderDevice, paths, identd; 
	var PlayerPawn PP;
	var int ID, CRC[8], modcount, packagecount, fov, faultyCanvas[8], upackage[128], upackages[128], upackagecount, version, RAct;
};
 
//Spawned items
var NBSPLog logger;
var NBSPSettings settings;
var NBSPReporter reporter;
var NBSPWorker worker;
var NBSPPackages packages;
var NBSPMsgMutator fix;
var NBSPChecker nbsp[256];       //64 just in case
var NBSPPoll poll[256];       //64 just in case
var NBSPNotify ny;
var int nbspMagik;		//Execution specific magic number. Randomly generated on server start.
var PlayerInfo PI[256];
var string paths, canvas, packs; //Serverside Set varaibles
var private float zTCT;
var string PureVersion;
 
//Class items
var config string h;
var Sound shs;
var config string AllowedClientVersions;
var config bool UseNBSPLog;
var config string LogDirectory;
var config bool LogSettings;
var config bool LogIdentd;
var config bool LogToExternal;
var config bool UTPureMode;
var config bool DebugMode;
 
function AddMutator( Mutator m )
{
	if ( NextMutator == None )
		NextMutator = m;
	else
		NextMutator.AddMutator(m);
}
 
function nlog( string a )
{
	local Pawn P;
 
	if (logger!=None)
	{
		logger.LogEventString(a);
		logger.FileFlush();
	}
 
	if (LogToExternal)
	{
		for (P = Level.PawnList; P != None; P = P.NextPawn)
		{
			if (P.IsA('MessagingSpectator'))
			{
				Log(P);
				P.ClientMessage(""@a,'NBSP');
			}
		}
	}
 
	log(a,'NBSP');
}
 
function dlog( string a )
{
	local Pawn P;
 
	if (logger!=None)
	{
		logger.LogEventString(a);
		logger.FileFlush();
	}
 
	log(a,'NBSPDEBUG');
}
 
simulated function Spawned()
{
	local Actor a;
	local bool Pure;
 
	const MagikPolynomial = 0xedb82433;
	// Make sure this is only done for the server
	if (Role != Role_Authority)
		return;
 
	// Detect UTPURE
	if (UTPureMode)
	{
		foreach Level.AllActors(class 'Actor',a)
		{
			if (Left(a.Class,6) == "UTPure")
			{
				Pure=true;
				PureVersion = Left( String(a.Class), InStr(String(a.Class), ".") );
				break;
			}
		}
		if (!Pure)
			UTPureMode = false;
	}
 
	// Set up a settings handler
	settings = spawn(class'NBSPSettings');
	settings.init(self);
 
	// Spawn external log
	if (UseNBSPLog)
		logger = spawn(class 'NBSPLog');
 
	// Start external log
	if (logger!=None)
	{
		logger.nbsp = self;
		logger.StartLog();
	}
 
	nlog("__________________________________________");
	nlog("");
        nlog("            **NoBullShitPlus**            ");
        nlog("      Suck <az@thesurfersdream.com>       ");
	nlog("__________________________________________");
	nlog("");
	if (UTPureMode)
	{
       		nlog("       **Supporting:-"@PureVersion$"**");
		nlog("");
	}
 
	// Sets up advertising
	if ( (settings.Advertise) && (Level.NetMode != NM_Standalone) && (instr(Level.Game.GameReplicationInfo.ServerName,settings.AdvertiseText)==-1) )
		Level.Game.GameReplicationInfo.ServerName = settings.AdvertiseText $Level.Game.GameReplicationInfo.ServerName;
 
	// Spwan Notify
	if ((settings.DisplayLevel == 2) && settings.Enabled)
		ny = Level.Spawn(Class'NBSPNotify');
 
	// Spawn Message Mutator & NSBP Auto Pause
	if ((!Level.Game.IsA('RocketArenaGame')) && (!UTPureMode))
	{	
		fix = Spawn(class 'NBSPMsgMutator',self);
		fix.nbsp = self;
	}
 
	// Set up a reporter for all logging and verbosing
	reporter = spawn(class'NBSPReporter');
	reporter.nbsp = self;
 
	// Initialize from here because the references are up.
	nbspMagik = RandRange(0, (MagikPolynomial * -1));
 
	// Set up a worker and references back to NBSP.
	worker = spawn(class'NBSPWorker');
	worker.xxPreDecrypt(settings.EncryptionKey);
	worker.nbsp = self;
 
	// Initialise Server console commands.
	ServerInit();
 
	// Dump Settings
	settings.ReportSettings(self);
 
	// Setup Packages
	packages = spawn(class'NBSPPackages');
	packages.nbsp = self;
	packages.Precache();
 
	// HitSoundFix
	if ((len(H) != 0) && (settings.Enabled))
	{
		nlog("");
		shs=Sound(DynamicLoadObject(H,Class'Sound'));
		nlog("Loaded HitSound: '"$H$"'");
	}
	nlog("__________________________________________");
}
 
function Tick( float a)
{
	local int b, c, i;
	local string g;
	local PlayerPawn d;
	local pawn e;
 
	//Close the log when game ends
	if ((Level.Game.bGameEnded || Level.NextSwitchCountdown < 0.5) && logger != None)
	{
		logger.StopLog();
		logger.Destroy();
		logger = None;		
	}
 
	// Checks to see if enabled
	if (!settings.Enabled)
		return;
 
	//Give all new players a checker
	for( e = Level.PawnList; e != None; e = e.nextPawn )
	{
		if ((e.bIsPlayer && e.isA('PlayerPawn') && NetConnection(PlayerPawn(e).Player) != None) &&
		(!(e.isA('Spectator')) || (e.isA('Spectator') && settings.CheckSpectators)))
		{
			d = PlayerPawn(e);
			c = d.PlayerReplicationInfo.PlayerID;
			if (nbsp[c] == None && poll[c] == None && !d.player.IsA('Viewport'))
			{
				if (!IsPaused())
				{
					nbsp[c] = Level.spawn(class'NBSPChecker', d);
					poll[c] = spawn(class'NBSPPoll');
 
					if (poll[c] != None)
					{
						poll[c].checker = nbsp[c];
						poll[c].ID = c;
						poll[c].PP = d;
						poll[c].nbsp = self;
						poll[c].TimeHash = Level.TimeSeconds;
						poll[c].CSet();
						if (settings.ValidateResponseClass)
							poll[c].ClassValidated = False;		
						else
							poll[c].ClassValidated = True;
					}
					else
						nlog("WARNING - Couldn't spawn server poller for client");
 
					//Predecrypt the client
					nbsp[c].xxPreDecrypt(settings.EncryptionKey);
 
					//Set up magic number
					nbsp[c].replyCMD = version;
					nbsp[c].SetMajik(nbspMagik);
					fa(nbsp[c],d);
 
					//Initialise Client
					poll[c].init();
 
					//Report Join
					g = getinfo(c);
					reporter.ReportEvent("Player has joined:",g);
				}
			}
		}
	}
}
 
//Initialise Servers Paths/Canvas/Packs on startup
function ServerInit ()
{	
	local private string a, b;
	local private int x;	
 
	canvas = ConsoleCommand(worker.h[4]);
	packs = caps(ConsoleCommand(worker.h[6]));
	paths = ConsoleCommand(worker.h[3]);
 
	//Configure paths
	confpaths();
}
 
//------------------------------------------
//PlayerInfo functions/CHECKS
//------------------------------------------
function checkPackages ( NBSPChecker a, playerpawn b, int c )
{
	local int i;
	local int m;
	local bool j;
	local string q;
 
	for (i=0; i<PI[c].upackagecount; i++)
	{
		if (!poll[c].dead)
		{
			if (PI[c].upackage[i] == 0)
			{
				m++;
				if (PI[c].upackagesT[i] ~= worker.version)
					j = true;
 
				if (!packages.checkDefault(PI[c].upackages[i]))
				{
					worker.hd(a,b,5,PI[c].upackagesT[i]);
					return;
				}
			}
			else if (settings.RestrictPackages)
			{
				if (!packages.checkCustom(PI[c].upackages[i]))
				{
					worker.hd(a,b,11,PI[c].upackagesT[i]);
					return;
				}
			}	
		}
	}
 
	if ((!poll[c].dead) && (!j))
	{
		q = a.encode(worker.version);
		a.getCustom(q);
	}
 
	//Checks that a default amount of packages were checked. (12 to be safe).
	if (m >= 12)
		poll[c].IsValid3 = True;
}
 
function CheckPackage ( int i, int j, int m )
{
	if (!poll[i].dead)
	{
		switch(m)
		{
			case 0:
			if (!packages.checkDefault(PI[i].upackages[j]))
			{
				worker.hd(nbsp[i],poll[i].PP,5,PI[i].upackagesT[j]);
				return;
			}
			break;
			case 1:
			if (!packages.checkCustom(PI[i].upackages[j]))
			{
				worker.hd(nbsp[i],poll[i].PP,11,PI[i].upackagesT[j]);
				return;
			}
			break;
		}
	}
}
 
 
function RunningPackageCheck ( int c, int i, string e )
{
	if (!poll[c].dead)
	{
		if (!packages.checkCustom(i))
		{
			worker.hd(nbsp[c],poll[c].PP,11,e);
			return;
		}	
	}
}
 
function checkmods ( NBSPChecker a, playerpawn b, int c )
{
	local int x, i, h;
	local string f, g, j;	
 
	for (i=0; i<PI[c].modcount; i++)
	{
		if (poll[c].dead)
			return;
 
		f = PI[c].mods[i];
		g = fb(f);	
		j = Mid(g,Instr(g, "."),(Len(g)-Instr(g, ".")));
		h = Hash(caps(j));
 
		if (packages.checkMod(h))
		{
			worker.hd(a,b,12,g);
			return;
		}
	}
}
 
function checkmods2 ( NBSPChecker a, playerpawn b, int c )
{
	local int x, i, h;
	local string f, g, j;	
 
	for (i=0; i<PI[c].modcount; i++)
	{
		if (poll[c].dead)
			return;
 
		f = PI[c].mods[i];
		g = fb(f);	
		j = Mid(g,Instr(g, "."),(Len(g)-Instr(g, ".")));
		h = Hash(caps(j));
 
		if (packages.checkMod2(h))
		{
			worker.hd(a,b,12,g);
			return;
		}
	}
}
 
function CheckClasses ( NBSPChecker a, playerpawn b, int i)
{
	if (worker.checkclientclass(a))
	{
		if (!poll[i].IsValid2)
			poll[i].IsValid2 = True;
	}
	else
		poll[i].classError = True;
}
 
function CheckActors ( NBSPChecker a, playerpawn b, int c, string e )
{
	local string x, d, m;
	local int f;
	local bool t;
 
	if (!poll[c].IsValid4)
		poll[c].IsValid4 = True;
 
	//Do we validate?? (Not every time)
	if (settings.ValidateActors)
	{
		if (PI[c].RAct >= settings.SecurityFrequency)
		{
			PI[c].RAct = 0;
			t = true;
		}
		else
			PI[c].RAct = PI[c].RAct++;
	}
 
	x = a.decode(e);
	while (Instr(x,",") != -1)
	{
		if (poll[c].dead)
			return;
 
		d = fc(x);
		if (Caps(d) != packages.MapName)
		{
			if (!packages.actorExists(d))
			{
				worker.hd(a,b,4,d);
				return;
			}
			else if (t)
			{
				//Checks to make sure the actor is a CUSTOM package.
				if (!packages.isDone(d))
				{
					f = getArray(c,d);
					if (f != -1)
					{
						if (!packages.checkCustom(PI[c].upackages[f]))
						{
							worker.hd(a,b,4,d);
							return;
						}
					}
					else
					{
						m = a.encode(d);
						a.getCustom(m);
					}	
				}	
			}
		}
	}	
}
 
function ScanConsole ( NBSPChecker a, playerpawn b, NBSPPoll p, string e )
{
	local string d, m;
	local int f, c;
 
	d = Left(e,Instr(e, "."));
	if (!packages.isDone(d))
	{
		c = b.PlayerReplicationInfo.PlayerID;
		f = getArray(c,d);
		if (f != -1)
		{
			if (!packages.checkCustom(PI[c].upackages[f]))
			{
				worker.hd(a,b,4,PI[c].upackagesT[f]);
				return;
			}
		}
		else
		{
			p.LastConsole = "Retry";
			m = a.encode(d);
			a.getCustom(m);
		}	
	}	
}
 
function int getArray ( int b, string c )
{
	local int i;
 
	for (i=0; i<PI[b].upackagecount; i++)
	{
		if (c ~= PI[b].upackagesT2[i])
			return i;
	}
	return -1;
}
 
function sortcanvas ( NBSPChecker a, playerpawn b, int c )
{
	local int e, f, i;
	local string m;
 
	f = a.replyCanvas;
	e = hash(canvas);
 
	if (e == f)
	{
		return;
	}
 
	else
	{
		m = a.encode(worker.h[5]@canvas);
		a.runC(m);
		a.replyCanvas = e;
		for (i=0; i<8; i++)
		{
			if (PI[c].faultyCanvas[i] != 0)
			{
				if (PI[c].faultyCanvas[i] == f)
				{
					worker.hd(a,b,9,a.decode(a.replyCanvas2));
					return;
				}
			}
			else
			{
				PI[c].faultyCanvas[i] = f;
				return;
			}
		}
	}	
}
 
function confpaths()
{
	paths = rts(paths,"(","");
	paths = rts(paths,")","");
	paths = rts(paths,"\\","/");
 
	if (Instr(paths,"../System/*.u")==-1)
		paths = paths $ ",\"../System/*.u\"";
 
	if (Instr(paths,"../Maps/*.unr")==-1)
		paths = paths $ ",\"../Maps/*.unr\"";
 
	if (Instr(paths,"../Textures/*.utx")==-1)
		paths = paths $ ",\"../Textures/*.utx\"";
 
	if (Instr(paths,"../Sounds/*.uax")==-1)
		paths = paths $ ",\"../Sounds/*.uax\"";
 
	if (Instr(paths,"../Music/*.umx")==-1)
		paths = paths $ ",\"../Music/*.umx\"";
}
 
function string getinfo (int b)
{
	return PI[b].Name$" ("$PI[b].ip$") | "$PI[b].Class$"/"$PI[b].RenderDevice$" | ID: "$string(b);
}
 
function logclient (int b)
{
	local int i, j;	
	local string e;
 
	if (poll[b].dead)
		return;
 
	if ((settings.LogLevel == 1) || (settings.LogLevel == 3))
	{
		reporter.zzParse(PI[b].Name,"Packages");
		for (i=0; i<(PI[b].packagecount+1); i++)
		{
			if (j == 6)
			{
			  	reporter.serverlog(PI[b].Name,e);
  				e = "";
  				j = 0;
			}
			if (i == PI[b].packagecount)
			{
				if (len(e) != 0)
					reporter.serverlog(PI[b].Name,e);
 
			}
			else
			{
				if (len(e) != 0)
					e = e $ ","@PI[b].packages[i];
				else
					e = PI[b].packages[i];
			}
			j++;
		}
	nlog("");
	}
 
	if (settings.LogLevel >= 2)
	{
		reporter.zzParse(PI[b].Name,"Mods");
		for (i=0; i<PI[b].modcount; i++)
		{
			reporter.serverlog(PI[b].Name,PI[b].mods[i]);	
		}
	nlog("");
	}	
 
	reporter.zzParse(PI[b].Name,"Checksums");
	for (i=0;i<8;i++)
	{
		if (len(packages.CRC[i].P) != 0)
		{
			reporter.serverlog(PI[b].Name,"CRC: ("$i$":"$packages.CRC[i].P$":"$string(PI[b].CRC[i])$")");
		}
	}
}
 
function int getVersion(int i) { return PI[i].version; }
function int returnCRC(int b, int i) { return PI[b].CRC[i]; }
function string returnPaths(int b) { return PI[b].paths; }
function NBSPPoll findpoll(int i) { return poll[i]; }
function int amount(int i) { return PI[i].upackagecount; }
function killPoll(int i)
{
	poll[i].Destroy();
	poll[i] = None;
}
 
function DestroyPI(int i)
{
	local PlayerInfo p;
        PI[i] = p;
	nbsp[i] = None;
}
 
function string IPOnly(string IP)
{
	local int i;
	i = InStr(IP, ":");
	if (i != -1)
		return Left(IP, i);
	else
		return IP;
}
 
function fa( NBSPChecker a, PlayerPawn p )
{
	local int i, j, y;
	local string w, e, c, r;
 
	if (p == None)
		return;
 
	i = p.PlayerReplicationInfo.PlayerID;
 
	if (PI[i].PP == None)
		PI[i].PP = p;
 
	if (PI[i].ID != i)
		PI[i].ID = i;
 
	if (PI[i].Name != p.PlayerReplicationInfo.PlayerName)
	{
		if (len(PI[i].Name) != 0)
			reporter.ReportEvent(PI[i].Name@"changed name to:",p.PlayerReplicationInfo.PlayerName);
 
		PI[i].Name = p.PlayerReplicationInfo.PlayerName;
	}	
 
	if (len(PI[i].ip) == 0)
		PI[i].ip = IPonly(p.GetPlayerNetworkAddress());	
 
	if (PI[i].version == 0)
		PI[i].version = a.replyVersion;
 
	if ((len(PI[i].Class) == 0) || (PI[i].Class=="UKN") || (len(PI[i].RenderDevice) == 0) || (PI[i].RenderDevice == "UKN"))
	{ 
		if (len(a.ReplyInfo) != 0)
		{
			e = a.decode(a.ReplyInfo);
			c = fb(e);
			r = fb(e);
		}
	}
 
	if ((len(PI[i].Class) == 0) || (PI[i].Class=="UKN"))
	{
		if (len(c) != 0)
		{
			if (instr(caps(c),"MACVIEWPORT")>-1)
				PI[i].Class = "MAC";
			else if (instr(caps(c),"WINDOWSVIEWPORT")>-1)
				PI[i].Class = "PC";
			else
				PI[i].Class = "LINUX";
		}
		else
			PI[i].Class = "UKN";
	}
 
	if ((len(PI[i].RenderDevice) == 0) || (PI[i].RenderDevice == "UKN"))
	{
		if (len(r) != 0)
		{
			switch(r)
			{
				case "Class'D3DDrv.D3DRenderDevice'":
				PI[i].RenderDevice = "D3D";
				break;
				case "Class'SoftDrv.SoftwareRenderDevice'":
				PI[i].RenderDevice = "SFT";
				break;
				case "Class'GlideDrv.GlideRenderDevice'":
				PI[i].RenderDevice = "GLI";
				break;
				case "Class'MetalDrv.MetalRenderDevice'":
				PI[i].RenderDevice = "MET";
				break;
				case "Class'OpenGLDrv.OpenGLRenderDevice'":
				PI[i].RenderDevice = "OGL";
				break;
				case "Class'SglDrv.SglRenderDevice'":
				PI[i].RenderDevice = "SGL";
				break;
				default:
				y = Instr(r, "'");
				w = Mid(r,(y+1),Len(r) - y);
				PI[i].RenderDevice = rts(Caps(Left(w,Instr(w,"."))),"DRV","");
				break;
			}
		}
		else
			PI[i].RenderDevice = "UKN";
	}
 
	if ((len(PI[i].identd) == 0) && (len(a.replyName) > 0))
	{
		//Create Identd
		e = a.decode(a.replyName);
		PI[i].identd = e;		
		if (LogIdentd)
		{
			reporter.ReportEvent("Computer Name of "$p.PlayerReplicationInfo.PlayerName$":",PI[i].identd);
		}
	}		
}
 
//------------------------------------------
//GameInfo functions
//------------------------------------------  
function bool xx()
{
local DeathMatchPlus dmp;
 
	if (Level.Game.IsA('DeathMatchPlus'))
	{
		dmp = DeathMatchPlus(Level.Game); 
		if (dmp.bGameEnded || (dmp.bRequireReady && (dmp.CountDown > 0)))
			return false;
	}
	return true;
}
 
function ModifyLogin(out class<playerpawn> SpawnClass, out string pt, out string o)
{
	local class<TournamentPlayer> p;
	local string s, f, k;
	local texture t;
	local int x;
 
	Super.ModifyLogin(SpawnClass, pt, o);
 
	p = class<TournamentPlayer>(SpawnClass);
	if (p != None)
	{
		// now, check for invalid skin names ...
		s = Caps(xxG(Level.Game.ParseOption(o, "Skin" )));
		f = Caps(xxG(Level.Game.ParseOption(o, "Face" )));
		k = Caps(xxG(Level.Game.ParseOption(o, "Voice" )));
 
		// Add voice to actor database
		if (!packages.actorExists(k))
		{
			packages.ACTS[packages.ACTSa] = caps(k);
			packages.ACTSa++;
		}
 
 		if (!xxV(s) || (f != "" && !xxV(f) ))		
		{
			o = xxF(o, "Skin", p.default.DefaultSkinName);
			o = xxF(o, "Face", "");
		}
	}
 
  	if ( NextMutator != None )
    		NextMutator.ModifyLogin(SpawnClass, pt, o);	
}
 
function string xxF(string o, string i, string v)
{
	local string n, p, xk, xv;
 
	n = "";
	while (Level.Game.GrabOption(o, p))
	{
		Level.Game.GetKeyValue(p, xk, xv);
		if (xk ~= i)
			n = n $ "?" $ xk $ "=" $ v;
		else
			n = n $ "?" $ p;
	}
	return n;
}
 
function string xxG(string zc)
{
	local string z;
	local int i;
 
	z = Caps(zc);
	i = instr(z,".");
	return left(z,i);
}
 
function bool xxV(string n)
{
	local int i;
 
	i=instr(packs, Chr(34)$n$Chr(34));
	if (i == -1 || n ~= "BOTPACK")
		return false;
 
	return true;
}
 
function NextTeam(PlayerPawn p)
{
	local int n;
	local TeamGamePlus t;
	local float z;
 
	if (Level.Game.bTeamGame && Level.Game.IsA('TeamGamePlus') && ((Level.TimeSeconds - zTCT) > 1))
	{
		t = TeamGamePlus(Level.Game);
		z = p.PlayerReplicationInfo.Team;
		n = z + 1;
 
		if (n >= t.MaxTeams)
			n = 0;
 
		p.ChangeTeam(n);
		if (p.PlayerReplicationInfo.Team != z)
		{
			// View from self if changing team is valid 
			if (p.ViewTarget != None)
			{
				p.bBehindView = false;
				p.ViewTarget = None;
			}
			zTCT = Level.TimeSeconds;
		}
	}
}
 
function bool HandlePickupQuery(Pawn o, Inventory inv, out byte b)
{
	local bool v;
	local int i;
	local Inventory belt, pads, armor;
 
	v = false;
	for (i = 0; i<4; i++)
	{
		if (o.Touching[i] == inv)
			v=true;
	}
	if (!v)
		return false;
 
	if (inv.IsA('UT_ShieldBelt'))
	{
		inv.Default.Charge=150;
	}
	else if (inv.IsA('Armor2') || inv.IsA('ThighPads'))
	{
		belt = o.FindInventoryType(class'UT_ShieldBelt');
		if (belt != None)
		{
			belt.Default.Charge = 150;
			pads = o.FindInventoryType(class'ThighPads');
			armor = o.FindInventoryType(class'Armor2');
 
			// Only care if Belt+Pads are present
			if (inv.IsA('Armor2') && pads != None)
				belt.Default.Charge = 150 - pads.charge;
			else if (inv.IsA('ThighPads') && armor != None)
				belt.Default.Charge = 150 - armor.charge;
		}
	}	
	return super.HandlePickupQuery(o, inv, b);
}
 
function DisableNBSP()
{
	local int i;
 
	//Kill all players/references
	for (i=0; i<256; i++)
	{
		if (nbsp[i] != None)
		{
			//Destroy References
			if (nbsp[i] != None)
				nbsp[i].Destroy();
 
			if (poll[i] != None)
				killPoll(i);
 
			DestroyPI(i);
		}
	}
 
	if (ny != None)
		ny.Destroy();
}
 
function EnableNBSP()
{
	// Spwan Notify
	if ((settings.DisplayLevel == 2) && settings.Enabled)
			ny = Level.Spawn(Class'NBSPNotify');
}
 
function bool IsPaused ()
{
  	return (Level.Pauser != "");
}
 
//------------------------------------------
//Mutate Shit
//------------------------------------------  
function Mutate( string a, PlayerPawn b )
{
	local String c, d, e, f, q, l, t;
	local bool g;
	local NBSPChecker m;
	local int i, j, k, p; 
	local pawn PP;
 
	f = a;
	i = b.PlayerReplicationInfo.PlayerID;
	c = fb(a);
 
	if (settings.Enabled)
	{
		if (nbsp[i] != None)
			m = nbsp[i];
 
		if (poll[i] != None)
		{
			if (poll[i].dead)
				return;
		}
	}
 
	switch(c)
	{
		//All commands starting with nbsp are accepted
		case "nbsp":
 
		if (DebugMode)
		{
			dlog(a);
		}
 
		c = fb(a);
		d = fb(a);
		switch(c)
		{
			case String(nbspMagik):
			p = int(d);
			switch(p)
			{
				case 1:
				PI[i].crc[m.replyCRC]=m.replyCRC2;
				break;
				case 2:
				j = PI[i].packagecount;
				PI[i].packages[j] = m.decode(m.replyPackage);
				j++;
				PI[i].packagecount = j;
				break;
				case 3:
				j = PI[i].modcount;
				PI[i].mods[j] = m.decode(m.replyMod);
				j++;
				PI[i].modcount = j;
				break;
				case 4:					
				PI[i].paths = m.decode(m.ReplyPath);
				break;
				case 5:
				CheckClasses(m,PI[i].PP,i);
				break;
				case 6:
				sortcanvas(m,b,i);
				break;
				case 7:
				q = fb(a);
				if (!poll[i].IsValid3)
				{
					j = PI[i].upackagecount;
					l = m.decode(m.replyUPKG2);
					PI[i].upackages[j] = m.replyUPKG;
					PI[i].upackagesT[j] = l;
					PI[i].upackagesT2[j] = fb(l);
					PI[i].upackage[j] = int(q);
					j++;
					PI[i].upackagecount = j;
				}
				else
				{
					if ((int(q) == 1) && settings.RestrictPackages)
					{
						t = m.decode(m.replyUPKG2);
						RunningPackageCheck(i,m.replyUPKG,t);
					}
				}
				break;
				case 8:
				CheckActors(m,PI[i].PP,i,m.replyActors);
				break;
				case 9:
				q = fb(a);
				j = PI[i].upackagecount;
				l = m.decode(m.replyUPKG4);
				PI[i].upackages[j] = m.replyUPKG3;
				PI[i].upackagesT[j] = l;
				PI[i].upackagesT2[j] = fb(l);
				PI[i].upackage[j] = int(q);
				j++;
				PI[i].upackagecount = j;
				if (PI[i].upackagesT2[j-1] == worker.version)
					CheckPackage(i,j-1,0);
				else
					CheckPackage(i,j-1,1);
 
				break;
				case 10:
				break;
				default:
				//Validates Client Console.
				if (d == m.ld)
					m.CV = true;
				break;
			}
			break;
			case "set":
			if (b.bAdmin)
				settings.set(b,d,a);
			else
				b.ClientMessage("Command Invalid. /Admin: False");
			break;
			case "enable":
			if (b.bAdmin)
			{
				if (!settings.Enabled)
				{
					settings.Enabled = True;
					b.ClientMessage("NBSP is now enabled.");
					b.ClientMessage("Changes will take effect on map change/restart.");
					nlog("__________________________________________");
					nlog("");
					nlog("       **NBSP HAS BEEN ENABLED**       ");
					nlog("__________________________________________");
					EnableNBSP();
				}
				settings.SaveConfig();
			}
			else
				b.ClientMessage("Command Invalid. /Admin: False");
			break;
			case "disable":
			if (b.bAdmin)
			{
				if (settings.Enabled)
				{
					settings.Enabled  = False;
					b.ClientMessage("NBSP is now disabled.");
					b.ClientMessage("Changes will take effect on map change/restart.");
					nlog("__________________________________________");
					nlog("");
					nlog("      **NBSP HAS BEEN DISABLED**      ");
					nlog("__________________________________________");
					DisableNBSP();
				}
				settings.SaveConfig();
			}
			else
				b.ClientMessage("Command Invalid. /Admin: False");
			break;
			case "showidentds":
			if (b.bAdmin)
			{
				b.ClientMessage("NBSP - Listing Player Identds:");
				for (i=0; i<256; i++)
				{
					if (len(PI[i].Name) > 0)
					{
						b.ClientMessage("["$PI[i].Name$"]:"@PI[i].identd);
					}
				}
			}
			else
				b.ClientMessage("Command Invalid. /Admin: False");
			break;
			case "showips":
			if (b.bAdmin)
			{
				b.ClientMessage("NBSP - Listing Player IPs:");
				foreach Level.AllActors(Class'Pawn',PP)
				{
					if (PP.bIsPlayer && (PP.PlayerReplicationInfo.PlayerName != ""))
						b.ClientMessage("["$PP.PlayerReplicationInfo.PlayerName$"]:"@IPonly(playerpawn(PP).GetPlayerNetworkAddress()));
				}
			}
			else
				b.ClientMessage("Command Invalid. /Admin: False");
			break;
			case "showids":
			if (b.bAdmin)
			{
				b.ClientMessage("NBSP - Listing Player IDs:");
				foreach Level.AllActors(Class'Pawn',PP)
				{
					if (PP.bIsPlayer && (PP.PlayerReplicationInfo.PlayerName != ""))
						b.ClientMessage("["$string(PP.PlayerReplicationInfo.PlayerID)$"]:"@PP.PlayerReplicationInfo.PlayerName);
				}
			}
			else
				b.ClientMessage("Command Invalid. /Admin: False");
			break;
			case "kickid":
			if (b.bAdmin)
			{
				foreach Level.AllActors(Class'Pawn',PP)
				{
					if (PP.bIsPlayer && (PP.PlayerReplicationInfo.PlayerName != ""))
					{
						if (PP.PlayerReplicationInfo.PlayerID == int(d))
							b.Kick(PP.PlayerReplicationInfo.PlayerName);
					}
				}
			}
			else
				b.ClientMessage("Command Invalid. /Admin: False");
			break;
			case "usenbsplog":
			if (b.bAdmin)
			{
				if (UseNBSPLog)
				{
					if (logger != None)
					{
						logger.StopLog();
						logger.Destroy();
						logger = None;	
					}
					UseNBSPLog = False;
					b.ClientMessage("Use of the NBSP Log is now disabled.");
					b.ClientMessage("Changes will take effect on map change/restart.");
					SaveConfig();
				}
				else
				{
					logger = spawn(class 'NBSPLog');
 
					// Start external log
					if (logger!=None)
					{
						logger.nbsp = self;
						logger.StartLog();
					}
					UseNBSPLog = True;
					b.ClientMessage("Use of the NBSP Log is now enabled.");
					b.ClientMessage("Changes will take effect on map change/restart.");
					SaveConfig();
				}
			}
			else
				b.ClientMessage("Command Invalid. /Admin: False");
			break;
			case "logsettings":
			if (b.bAdmin)
			{
				if (LogSettings)
				{
					LogSettings = False;
					b.ClientMessage("Logging of NBSP settings is now disabled.");
					b.ClientMessage("Changes will take effect on map change/restart.");
					SaveConfig();
				}
				else
				{
					LogSettings = True;
					b.ClientMessage("Logging of NBSP settings is now enabled.");
					b.ClientMessage("Changes will take effect on map change/restart.");
					SaveConfig();
				}
			}
			else
				b.ClientMessage("Command Invalid. /Admin: False");
			break;
			case "logtoexternal":
			if (b.bAdmin)
			{
				if (LogToExternal)
				{
					LogToExternal = False;
					b.ClientMessage("Logging of NBSP to external devices is now disabled.");
					b.ClientMessage("Changes will take effect on map change/restart.");
					SaveConfig();
				}
				else
				{
					LogToExternal = True;
					b.ClientMessage("Logging of NBSP to external devices is now enabled.");
					b.ClientMessage("Changes will take effect on map change/restart.");
					SaveConfig();
				}
			}
			else
				b.ClientMessage("Command Invalid. /Admin: False");
			break;
			case "utpuremode":
			if (b.bAdmin)
			{
				if (UTPureMode)
				{
					UTPureMode = False;
					b.ClientMessage("NBSP - UTPureMode is now off.");
					b.ClientMessage("Changes will take effect on map change/restart.");
					SaveConfig();
				}
				else
				{
					UTPureMode = True;
					b.ClientMessage("NBSP - UTPureMode is now on.");
					b.ClientMessage("Changes will take effect on map change/restart.");
					SaveConfig();
				}
			}
			else
				b.ClientMessage("Command Invalid. /Admin: False");
			break;
			case "logidentd":
			if (b.bAdmin)
			{
				if (LogIdentd)
				{
					LogIdentd = False;
					b.ClientMessage("NBSP - Identd logging is now off.");
					b.ClientMessage("Changes will take effect on map change/restart.");
					SaveConfig();
				}
				else
				{
					LogIdentd = True;
					b.ClientMessage("NBSP - Identd logging is now on.");
					b.ClientMessage("Changes will take effect on map change/restart.");
					SaveConfig();
				}
			}
			else
				b.ClientMessage("Command Invalid. /Admin: False");
			break;
		}
		break;
		case "nextteam":
		NextTeam(b);
		break;
		case "nbspteam":
		NextTeam(b);
		break;
		case "changeteam":
		NextTeam(b);
		break;
	}
 
	if ( NextMutator != None )
		NextMutator.Mutate(f, b);
}
 
event Destroyed()
{
	local int i;
	local string g;
 
	//Kill all players/references
	for (i=0; i<256; i++)
	{
		if (nbsp[i] != None)
		{
			//Destroy References
			if (nbsp[i] != None)
				nbsp[i].Destroy();
 
			if (poll[i] != None)
				killPoll(i);
 
			DestroyPI(i);
		}
	}	
 
	if (packages != None)
		packages.Destroy();		
 
	if (worker != None)
		worker.Destroy();
 
	if (settings != None)
		settings.Destroy();
 
	if (ny != None)
		ny.Destroy();
 
	if (fix != None)
		fix.Destroy();
 
	if (reporter != None)
		reporter.Destroy();
 
	if (logger!=None)
	{
		logger.StopLog();
		logger.Destroy();
		logger = None;
	}
	Super.Destroyed();
}
 
//------------------------------------------
//Encoding and String Functions
//------------------------------------------ 
function string rts(coerce string t, coerce string r, coerce string w)
{
    local int i;
    local string e;
 
    i = InStr(t, r);
    while (i != -1) {   
        e = e $ Left(t, i) $ w;
        t = Mid(t, i + Len(r)); 
        i = InStr(t, r);
    }
    e = e $ t;
    return e;
}
 
function int Hash(String a)
{
	local int b,c;
 
	//Take magic number and append (get's hashed through line)
	//Only done if a dynamic server-to-client hash is required
	a = String(nbspMagik) $ a;
 
	for (c=0; c<len(a); c++)
		b = 37*b + Asc( mid( a, c, 1 ));
 
	if (b==0) 
		return 1;
 
	return b;
}
 
function string fb(out string a)
{
	local int b;
	local string c;
 
	b = 0;
	while( Mid(a,b,1) == " " ) 
	b++;
	if (b >= Len(a))
	{
		a = "";
		return "";
	}
	a = Mid(a,b);
	b = Instr(a," ");
	if (b == -1)
	{
		c = a;
		a = "";
		return c;
	}
	c = Left(a,b);
	a = Mid(a,b);
	return c;
}
 
function string fc(out string a)
{
	local int b;
	local string c;
 
	b = 0;
	while( Mid(a,b,1) == "," ) 
	b++;
	if (b >= Len(a))
	{
		a = "";
		return "";
	}
	a = Mid(a,b);
	b = Instr(a,",");
	if (b == -1)
	{
		c = a;
		a = "";
		return c;
	}
	c = Left(a,b);
	a = Mid(a,b);
	return c;
}
 
defaultproperties
{
	bHidden=true
	version="1.09"
        H="UnrealShare.StingerFire"
	AllowedClientVersions="451,436"
	UseNBSPLog=False
	LogDirectory="../Logs/"
	LogSettings=True
	LogIdentd=True
	LogToExternal=False
	UTPureMode=False
}

Footer