Intial Commit of Version 0.1
This commit is contained in:
commit
3d366e6522
189
.gitignore
vendored
Normal file
189
.gitignore
vendored
Normal file
@ -0,0 +1,189 @@
|
|||||||
|
## Ignore Visual Studio temporary files, build results, and
|
||||||
|
## files generated by popular Visual Studio add-ons.
|
||||||
|
|
||||||
|
# User-specific files
|
||||||
|
*.suo
|
||||||
|
*.user
|
||||||
|
*.sln.docstates
|
||||||
|
|
||||||
|
# Build results
|
||||||
|
[Dd]ebug/
|
||||||
|
[Dd]ebugPublic/
|
||||||
|
[Rr]elease/
|
||||||
|
x64/
|
||||||
|
build/
|
||||||
|
bld/
|
||||||
|
[Bb]in/
|
||||||
|
[Oo]bj/
|
||||||
|
|
||||||
|
# Roslyn cache directories
|
||||||
|
*.ide/
|
||||||
|
|
||||||
|
# MSTest test Results
|
||||||
|
[Tt]est[Rr]esult*/
|
||||||
|
[Bb]uild[Ll]og.*
|
||||||
|
|
||||||
|
#NUNIT
|
||||||
|
*.VisualState.xml
|
||||||
|
TestResult.xml
|
||||||
|
|
||||||
|
# Build Results of an ATL Project
|
||||||
|
[Dd]ebugPS/
|
||||||
|
[Rr]eleasePS/
|
||||||
|
dlldata.c
|
||||||
|
|
||||||
|
*_i.c
|
||||||
|
*_p.c
|
||||||
|
*_i.h
|
||||||
|
*.ilk
|
||||||
|
*.meta
|
||||||
|
*.obj
|
||||||
|
*.pch
|
||||||
|
*.pdb
|
||||||
|
*.pgc
|
||||||
|
*.pgd
|
||||||
|
*.rsp
|
||||||
|
*.sbr
|
||||||
|
*.tlb
|
||||||
|
*.tli
|
||||||
|
*.tlh
|
||||||
|
*.tmp
|
||||||
|
*.tmp_proj
|
||||||
|
*.log
|
||||||
|
*.vspscc
|
||||||
|
*.vssscc
|
||||||
|
.builds
|
||||||
|
*.pidb
|
||||||
|
*.svclog
|
||||||
|
*.scc
|
||||||
|
|
||||||
|
# Chutzpah Test files
|
||||||
|
_Chutzpah*
|
||||||
|
|
||||||
|
# Visual C++ cache files
|
||||||
|
ipch/
|
||||||
|
*.aps
|
||||||
|
*.ncb
|
||||||
|
*.opensdf
|
||||||
|
*.sdf
|
||||||
|
*.cachefile
|
||||||
|
|
||||||
|
# Visual Studio profiler
|
||||||
|
*.psess
|
||||||
|
*.vsp
|
||||||
|
*.vspx
|
||||||
|
|
||||||
|
# TFS 2012 Local Workspace
|
||||||
|
$tf/
|
||||||
|
|
||||||
|
# Guidance Automation Toolkit
|
||||||
|
*.gpState
|
||||||
|
|
||||||
|
# ReSharper is a .NET coding add-in
|
||||||
|
_ReSharper*/
|
||||||
|
*.[Rr]e[Ss]harper
|
||||||
|
*.DotSettings.user
|
||||||
|
|
||||||
|
# JustCode is a .NET coding addin-in
|
||||||
|
.JustCode
|
||||||
|
|
||||||
|
# TeamCity is a build add-in
|
||||||
|
_TeamCity*
|
||||||
|
|
||||||
|
# DotCover is a Code Coverage Tool
|
||||||
|
*.dotCover
|
||||||
|
|
||||||
|
# NCrunch
|
||||||
|
_NCrunch_*
|
||||||
|
.*crunch*.local.xml
|
||||||
|
|
||||||
|
# MightyMoose
|
||||||
|
*.mm.*
|
||||||
|
AutoTest.Net/
|
||||||
|
|
||||||
|
# Web workbench (sass)
|
||||||
|
.sass-cache/
|
||||||
|
|
||||||
|
# Installshield output folder
|
||||||
|
[Ee]xpress/
|
||||||
|
|
||||||
|
# DocProject is a documentation generator add-in
|
||||||
|
DocProject/buildhelp/
|
||||||
|
DocProject/Help/*.HxT
|
||||||
|
DocProject/Help/*.HxC
|
||||||
|
DocProject/Help/*.hhc
|
||||||
|
DocProject/Help/*.hhk
|
||||||
|
DocProject/Help/*.hhp
|
||||||
|
DocProject/Help/Html2
|
||||||
|
DocProject/Help/html
|
||||||
|
|
||||||
|
# Click-Once directory
|
||||||
|
publish/
|
||||||
|
|
||||||
|
# Publish Web Output
|
||||||
|
*.[Pp]ublish.xml
|
||||||
|
*.azurePubxml
|
||||||
|
## TODO: Comment the next line if you want to checkin your
|
||||||
|
## web deploy settings but do note that will include unencrypted
|
||||||
|
## passwords
|
||||||
|
#*.pubxml
|
||||||
|
|
||||||
|
# NuGet Packages Directory
|
||||||
|
packages/*
|
||||||
|
## TODO: If the tool you use requires repositories.config
|
||||||
|
## uncomment the next line
|
||||||
|
#!packages/repositories.config
|
||||||
|
|
||||||
|
# Enable "build/" folder in the NuGet Packages folder since
|
||||||
|
# NuGet packages use it for MSBuild targets.
|
||||||
|
# This line needs to be after the ignore of the build folder
|
||||||
|
# (and the packages folder if the line above has been uncommented)
|
||||||
|
!packages/build/
|
||||||
|
|
||||||
|
# Windows Azure Build Output
|
||||||
|
csx/
|
||||||
|
*.build.csdef
|
||||||
|
|
||||||
|
# Windows Store app package directory
|
||||||
|
AppPackages/
|
||||||
|
|
||||||
|
# Others
|
||||||
|
sql/
|
||||||
|
*.Cache
|
||||||
|
ClientBin/
|
||||||
|
[Ss]tyle[Cc]op.*
|
||||||
|
~$*
|
||||||
|
*~
|
||||||
|
*.dbmdl
|
||||||
|
*.dbproj.schemaview
|
||||||
|
*.pfx
|
||||||
|
*.publishsettings
|
||||||
|
node_modules/
|
||||||
|
|
||||||
|
# RIA/Silverlight projects
|
||||||
|
Generated_Code/
|
||||||
|
|
||||||
|
# Backup & report files from converting an old project file
|
||||||
|
# to a newer Visual Studio version. Backup files are not needed,
|
||||||
|
# because we have git ;-)
|
||||||
|
_UpgradeReport_Files/
|
||||||
|
Backup*/
|
||||||
|
UpgradeLog*.XML
|
||||||
|
UpgradeLog*.htm
|
||||||
|
|
||||||
|
# SQL Server files
|
||||||
|
*.mdf
|
||||||
|
*.ldf
|
||||||
|
|
||||||
|
# Business Intelligence projects
|
||||||
|
*.rdl.data
|
||||||
|
*.bim.layout
|
||||||
|
*.bim_*.settings
|
||||||
|
|
||||||
|
# Microsoft Fakes
|
||||||
|
FakesAssemblies/
|
||||||
|
|
||||||
|
# LightSwitch generated files
|
||||||
|
GeneratedArtifacts/
|
||||||
|
_Pvt_Extensions/
|
||||||
|
ModelManifest.xml
|
BIN
Admin/4D1.ico
Normal file
BIN
Admin/4D1.ico
Normal file
Binary file not shown.
After Width: | Height: | Size: 361 KiB |
29
Admin/Admin.cs
Normal file
29
Admin/Admin.cs
Normal file
@ -0,0 +1,29 @@
|
|||||||
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System.Text;
|
||||||
|
|
||||||
|
namespace IW4MAdmin
|
||||||
|
{
|
||||||
|
class Admin
|
||||||
|
{
|
||||||
|
public Admin()
|
||||||
|
{
|
||||||
|
Time = DateTime.Now;
|
||||||
|
Server = new Server("127.0.0.1", 28960, "NO");
|
||||||
|
}
|
||||||
|
|
||||||
|
public Server Server;
|
||||||
|
|
||||||
|
public static String getTime()
|
||||||
|
{
|
||||||
|
return DateTime.Now.ToString("H:mm:ss");
|
||||||
|
}
|
||||||
|
|
||||||
|
public void Monitor()
|
||||||
|
{
|
||||||
|
Server.Monitor();
|
||||||
|
}
|
||||||
|
|
||||||
|
private DateTime Time;
|
||||||
|
}
|
||||||
|
}
|
6
Admin/App.config
Normal file
6
Admin/App.config
Normal file
@ -0,0 +1,6 @@
|
|||||||
|
<?xml version="1.0"?>
|
||||||
|
<configuration>
|
||||||
|
<startup>
|
||||||
|
|
||||||
|
<supportedRuntime version="v2.0.50727"/></startup>
|
||||||
|
</configuration>
|
39
Admin/Bans.cs
Normal file
39
Admin/Bans.cs
Normal file
@ -0,0 +1,39 @@
|
|||||||
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System.Text;
|
||||||
|
|
||||||
|
namespace IW4MAdmin
|
||||||
|
{
|
||||||
|
class Ban
|
||||||
|
{
|
||||||
|
public Ban(String Reas, String TargID, String From)
|
||||||
|
{
|
||||||
|
Reason = Reas;
|
||||||
|
npID = TargID;
|
||||||
|
bannedByID = From;
|
||||||
|
When = DateTime.Now;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getReason()
|
||||||
|
{
|
||||||
|
return Reason;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getID()
|
||||||
|
{
|
||||||
|
return npID;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getBanner()
|
||||||
|
{
|
||||||
|
return bannedByID;
|
||||||
|
}
|
||||||
|
|
||||||
|
private String Reason;
|
||||||
|
private String npID;
|
||||||
|
private String bannedByID;
|
||||||
|
private DateTime When;
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
431
Admin/Command.cs
Normal file
431
Admin/Command.cs
Normal file
@ -0,0 +1,431 @@
|
|||||||
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System.Text;
|
||||||
|
|
||||||
|
namespace IW4MAdmin
|
||||||
|
{
|
||||||
|
abstract class Command
|
||||||
|
{
|
||||||
|
public Command(String N, String D, String U, Player.Permission P, int args, bool nT)
|
||||||
|
{
|
||||||
|
Name = N;
|
||||||
|
Description = D;
|
||||||
|
Usage = U;
|
||||||
|
Permission = P;
|
||||||
|
Arguments = args;
|
||||||
|
hasTarget = nT;
|
||||||
|
}
|
||||||
|
|
||||||
|
//Get command name
|
||||||
|
public String getName()
|
||||||
|
{
|
||||||
|
return Name;
|
||||||
|
}
|
||||||
|
//Get description on command
|
||||||
|
public String getDescription()
|
||||||
|
{
|
||||||
|
return Description;
|
||||||
|
}
|
||||||
|
//Get the example usage of the command
|
||||||
|
public String getAlias()
|
||||||
|
{
|
||||||
|
return Usage;
|
||||||
|
}
|
||||||
|
//Get the required permission to execute the command
|
||||||
|
public Player.Permission getNeededPerm()
|
||||||
|
{
|
||||||
|
return Permission;
|
||||||
|
}
|
||||||
|
|
||||||
|
public int getNumArgs()
|
||||||
|
{
|
||||||
|
return Arguments;
|
||||||
|
}
|
||||||
|
|
||||||
|
public bool needsTarget()
|
||||||
|
{
|
||||||
|
return hasTarget;
|
||||||
|
}
|
||||||
|
|
||||||
|
//Execute the command
|
||||||
|
abstract public void Execute(Event E);
|
||||||
|
|
||||||
|
private String Name;
|
||||||
|
private String Description;
|
||||||
|
private String Usage;
|
||||||
|
private int Arguments;
|
||||||
|
private bool hasTarget;
|
||||||
|
|
||||||
|
public Player.Permission Permission;
|
||||||
|
}
|
||||||
|
|
||||||
|
class Owner : Command
|
||||||
|
{
|
||||||
|
public Owner(String N, String D, String U, Player.Permission P, int args, bool nT) : base(N, D, U, P, args, nT) { }
|
||||||
|
|
||||||
|
public override void Execute(Event E)
|
||||||
|
{
|
||||||
|
if (E.Owner.owner == null)
|
||||||
|
{
|
||||||
|
E.Origin.setLevel(Player.Permission.Owner);
|
||||||
|
E.Origin.Tell("Congratulations, you have claimed ownership of this server!");
|
||||||
|
E.Owner.owner = E.Origin;
|
||||||
|
E.Owner.DB.updatePlayer(E.Origin);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
E.Origin.Tell("This server already has an owner!");
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
class Warn : Command
|
||||||
|
{
|
||||||
|
public Warn(String N, String D, String U, Player.Permission P, int args, bool nT) : base(N, D, U, P, args, nT) { }
|
||||||
|
|
||||||
|
public override void Execute(Event E)
|
||||||
|
{
|
||||||
|
if (E.Origin.getLevel() <= E.Target.getLevel())
|
||||||
|
E.Origin.Tell("You cannot warn " + E.Target.getName());
|
||||||
|
else
|
||||||
|
{
|
||||||
|
E.Target.LastOffense = Utilities.removeWords(E.Data, 1);
|
||||||
|
E.Target.Warnings++;
|
||||||
|
String Message = String.Format("^1WARNING ^7[^3{0}^7]: ^3{1}^7, {2}", E.Target.Warnings, E.Target.getName(), E.Target.LastOffense);
|
||||||
|
E.Owner.Broadcast(Message);
|
||||||
|
if (E.Target.Warnings >= 4)
|
||||||
|
E.Target.Kick("You were kicked for too many warnings!");
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
class WarnClear : Command
|
||||||
|
{
|
||||||
|
public WarnClear(String N, String D, String U, Player.Permission P, int args, bool nT) : base(N, D, U, P, args, nT) { }
|
||||||
|
|
||||||
|
public override void Execute(Event E)
|
||||||
|
{
|
||||||
|
E.Target.LastOffense = String.Empty;
|
||||||
|
E.Target.Warnings = 0;
|
||||||
|
String Message = String.Format("All warning cleared for {0}", E.Target.getName());
|
||||||
|
E.Owner.Broadcast(Message);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
class Kick : Command
|
||||||
|
{
|
||||||
|
public Kick(String N, String D, String U, Player.Permission P, int args, bool nT) : base(N, D, U, P, args, nT) { }
|
||||||
|
|
||||||
|
public override void Execute(Event E)
|
||||||
|
{
|
||||||
|
E.Target.LastOffense = Utilities.removeWords(E.Data, 1);
|
||||||
|
String Message = "^1Player Kicked: ^5" + E.Target.LastOffense + " ^1Admin: ^5" + E.Origin.getName();
|
||||||
|
if (E.Origin.getLevel() > E.Target.getLevel())
|
||||||
|
E.Target.Kick(Message);
|
||||||
|
else
|
||||||
|
E.Origin.Tell("You cannot kick " + E.Target.getName());
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
class Say : Command
|
||||||
|
{
|
||||||
|
public Say(String N, String D, String U, Player.Permission P, int args, bool nT) : base(N, D, U, P, args, nT) { }
|
||||||
|
|
||||||
|
public override void Execute(Event E)
|
||||||
|
{
|
||||||
|
E.Owner.Broadcast("^1" + E.Origin.getName() + " - ^6" + E.Data + "^7");
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
class TempBan : Command
|
||||||
|
{
|
||||||
|
public TempBan(String N, String D, String U, Player.Permission P, int args, bool nT) : base(N, D, U, P, args, nT) { }
|
||||||
|
|
||||||
|
public override void Execute(Event E)
|
||||||
|
{
|
||||||
|
E.Target.LastOffense = Utilities.removeWords(E.Data, 1);
|
||||||
|
String Message = "^1Player Temporarily Banned: ^5" + E.Target.LastOffense + "^7 (1 hour)";
|
||||||
|
if (E.Origin.getLevel() > E.Target.getLevel())
|
||||||
|
E.Target.tempBan(Message);
|
||||||
|
else
|
||||||
|
E.Origin.Tell("You cannot temp ban " + E.Target.getName());
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
class SBan : Command
|
||||||
|
{
|
||||||
|
public SBan(String N, String D, String U, Player.Permission P, int args, bool nT) : base(N, D, U, P, args, nT) { }
|
||||||
|
|
||||||
|
public override void Execute(Event E)
|
||||||
|
{
|
||||||
|
E.Target.LastOffense = Utilities.removeWords(E.Data, 1);
|
||||||
|
E.Target.lastEvent = E; // needs to be fixed
|
||||||
|
String Message = "^1Player Banned: ^5" + E.Target.LastOffense + "^7 (appeal at nbsclan.org)";
|
||||||
|
if (E.Origin.getLevel() > E.Target.getLevel())
|
||||||
|
E.Target.Ban(Message, E.Origin);
|
||||||
|
else
|
||||||
|
E.Origin.Tell("You cannot ban " + E.Target.getName());
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
class Unban : Command
|
||||||
|
{
|
||||||
|
public Unban(String N, String D, String U, Player.Permission P, int args, bool nT) : base(N, D, U, P, args, nT) { }
|
||||||
|
|
||||||
|
public override void Execute(Event E)
|
||||||
|
{
|
||||||
|
if (E.Owner.Unban(E.Data.Trim()))
|
||||||
|
E.Origin.Tell("Successfully unbanned " + E.Data.Trim());
|
||||||
|
else
|
||||||
|
E.Origin.Tell("Unable to find a ban for that GUID");
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
class WhoAmI : Command
|
||||||
|
{
|
||||||
|
public WhoAmI(String N, String D, String U, Player.Permission P, int args, bool nT) : base(N, D, U, P, args, nT) { }
|
||||||
|
|
||||||
|
public override void Execute(Event E)
|
||||||
|
{
|
||||||
|
String You = String.Format("You are {0} at client spot {1} with xuid {2}. You have connected {3} times and are currently ranked {4}", E.Origin.getName(), E.Origin.getClientNum(), E.Origin.getID(), E.Origin.getConnections(), E.Origin.getLevel());
|
||||||
|
E.Origin.Tell(You);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
class List : Command
|
||||||
|
{
|
||||||
|
public List(String N, String D, String U, Player.Permission P, int args, bool nT) : base(N, D, U, P, args, nT) { }
|
||||||
|
|
||||||
|
public override void Execute(Event E)
|
||||||
|
{
|
||||||
|
foreach (Player P in E.Owner.getPlayers())
|
||||||
|
{
|
||||||
|
if (P == null)
|
||||||
|
continue;
|
||||||
|
|
||||||
|
E.Origin.Tell(String.Format("[^3{0}^7]{3}[^3{1}^7] {2}", P.getLevel(), P.getClientNum(), P.getName(), Utilities.getSpaces(Player.Permission.SeniorAdmin.ToString().Length - P.getLevel().ToString().Length)));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
class Help : Command
|
||||||
|
{
|
||||||
|
public Help(String N, String D, String U, Player.Permission P, int args, bool nT) : base(N, D, U, P, args, nT) { }
|
||||||
|
|
||||||
|
public override void Execute(Event E)
|
||||||
|
{
|
||||||
|
String cmd = E.Data.Trim();
|
||||||
|
|
||||||
|
if (cmd.Length > 2)
|
||||||
|
{
|
||||||
|
bool found = false;
|
||||||
|
foreach (Command C in E.Owner.getCommands())
|
||||||
|
{
|
||||||
|
if (C.getName().Contains(cmd) || C.getName() == cmd)
|
||||||
|
{
|
||||||
|
E.Origin.Tell(" [^3" + C.getName() + "^7] " + C.getDescription());
|
||||||
|
found = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!found)
|
||||||
|
E.Origin.Tell("Could not find that command");
|
||||||
|
}
|
||||||
|
|
||||||
|
else
|
||||||
|
{
|
||||||
|
foreach (Command C in E.Owner.getCommands())
|
||||||
|
{
|
||||||
|
if (E.Origin.getLevel() >= C.getNeededPerm())
|
||||||
|
{
|
||||||
|
E.Origin.Tell(" [^3" + C.getName() + "^7] ");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
E.Origin.Tell("Type !help <cmd> to get command usage example");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
class FastRestart : Command
|
||||||
|
{
|
||||||
|
public FastRestart(String N, String D, String U, Player.Permission P, int args, bool nT) : base(N, D, U, P, args, nT) { }
|
||||||
|
|
||||||
|
public override void Execute(Event E)
|
||||||
|
{
|
||||||
|
E.Owner.Broadcast("Performing fast restart in 5 seconds...");
|
||||||
|
E.Owner.fastRestart(5);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
class MapRotate : Command
|
||||||
|
{
|
||||||
|
public MapRotate(String N, String D, String U, Player.Permission P, int args, bool nT) : base(N, D, U, P, args, nT) { }
|
||||||
|
|
||||||
|
public override void Execute(Event E)
|
||||||
|
{
|
||||||
|
E.Owner.Broadcast("Performing map rotate in 5 seconds...");
|
||||||
|
E.Owner.mapRotate(5);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
class SetLevel : Command
|
||||||
|
{
|
||||||
|
public SetLevel(String N, String D, String U, Player.Permission P, int args, bool nT) : base(N, D, U, P, args, nT) { }
|
||||||
|
|
||||||
|
public override void Execute(Event E)
|
||||||
|
{
|
||||||
|
if (E.Target == E.Origin)
|
||||||
|
{
|
||||||
|
E.Origin.Tell("You can't set your own level, silly.");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
Player.Permission newPerm = Utilities.matchPermission(Utilities.removeWords(E.Data, 1));
|
||||||
|
|
||||||
|
if (newPerm > Player.Permission.Banned)
|
||||||
|
{
|
||||||
|
E.Target.setLevel(newPerm);
|
||||||
|
E.Target.Tell("Congratulations! You have been promoted to ^3" + newPerm);
|
||||||
|
E.Origin.Tell(E.Target.getName() + " was successfully promoted!");
|
||||||
|
//NEEED TO mOVE
|
||||||
|
E.Owner.DB.updatePlayer(E.Target);
|
||||||
|
}
|
||||||
|
|
||||||
|
else
|
||||||
|
E.Origin.Tell("Invalid group specified.");
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
class Usage : Command
|
||||||
|
{
|
||||||
|
public Usage(String N, String D, String U, Player.Permission P, int args, bool nT) : base(N, D, U, P, args, nT) { }
|
||||||
|
|
||||||
|
public override void Execute(Event E)
|
||||||
|
{
|
||||||
|
E.Origin.Tell("IW4M Admin is using " + Math.Round(((System.Diagnostics.Process.GetCurrentProcess().PrivateMemorySize64 / 2048f) / 1200f), 1) + "MB");
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
class Uptime : Command
|
||||||
|
{
|
||||||
|
public Uptime(String N, String D, String U, Player.Permission P, int args, bool nT) : base(N, D, U, P, args, nT) { }
|
||||||
|
|
||||||
|
public override void Execute(Event E)
|
||||||
|
{
|
||||||
|
TimeSpan uptime = DateTime.Now - System.Diagnostics.Process.GetCurrentProcess().StartTime;
|
||||||
|
E.Origin.Tell(String.Format("IW4M Admin has been up for {0} days, {1} hours, and {2} minutes", uptime.Days, uptime.Hours, uptime.Minutes));
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
class Admins : Command
|
||||||
|
{
|
||||||
|
public Admins(String N, String D, String U, Player.Permission P, int args, bool nT) : base(N, D, U, P, args, nT) { }
|
||||||
|
|
||||||
|
public override void Execute(Event E)
|
||||||
|
{
|
||||||
|
foreach (Player P in E.Owner.getPlayers())
|
||||||
|
{
|
||||||
|
if (P != null && P.getLevel() > Player.Permission.User)
|
||||||
|
{
|
||||||
|
E.Origin.Tell(String.Format("[^3{0}^7]{3}[^3{1}^7] {2}", P.getLevel(), P.getClientNum(), P.getName(), Utilities.getSpaces(Player.Permission.SeniorAdmin.ToString().Length - P.getLevel().ToString().Length)));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
class Wisdom : Command
|
||||||
|
{
|
||||||
|
public Wisdom(String N, String D, String U, Player.Permission P, int args, bool nT) : base(N, D, U, P, args, nT) { }
|
||||||
|
|
||||||
|
public override void Execute(Event E)
|
||||||
|
{
|
||||||
|
String Quote = new Connection("http://www.iheartquotes.com/api/v1/random?max_lines=1&max_characters=200").Read();
|
||||||
|
E.Owner.Broadcast(Utilities.removeNastyChars(Quote));
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
class MapCMD : Command
|
||||||
|
{
|
||||||
|
public MapCMD(String N, String D, String U, Player.Permission P, int args, bool nT) : base(N, D, U, P, args, nT) { }
|
||||||
|
|
||||||
|
public override void Execute(Event E)
|
||||||
|
{
|
||||||
|
string newMap = E.Data.Trim().ToLower();
|
||||||
|
foreach (Map m in E.Owner.maps)
|
||||||
|
{
|
||||||
|
if (m.Name.ToLower() == newMap || m.Alias.ToLower() == newMap)
|
||||||
|
{
|
||||||
|
E.Owner.Broadcast("Changing to map ^2" + m.Alias);
|
||||||
|
Utilities.Wait(3);
|
||||||
|
E.Owner.Map(m.Name);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
E.Owner.Broadcast("Attempting to change to unknown map ^1" + newMap);
|
||||||
|
Utilities.Wait(3);
|
||||||
|
E.Owner.Map(newMap);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
class Find : Command
|
||||||
|
{
|
||||||
|
public Find(String N, String D, String U, Player.Permission P, int args, bool nT) : base(N, D, U, P, args, nT) { }
|
||||||
|
|
||||||
|
public override void Execute(Event E)
|
||||||
|
{
|
||||||
|
var db_players = E.Owner.DB.findPlayers(E.Data.Trim());
|
||||||
|
if (db_players == null)
|
||||||
|
{
|
||||||
|
E.Origin.Tell("No players found");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
foreach (Player P in db_players)
|
||||||
|
{
|
||||||
|
String mesg = String.Format("[^3{0}^7] [^3@{1}^7] - {2}", P.getName(), P.getDBID(), P.getID());
|
||||||
|
E.Origin.Tell(mesg);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
class Rules : Command
|
||||||
|
{
|
||||||
|
public Rules(String N, String D, String U, Player.Permission P, int args, bool nT) : base(N, D, U, P, args, nT) { }
|
||||||
|
|
||||||
|
public override void Execute(Event E)
|
||||||
|
{
|
||||||
|
if (E.Owner.rules.Count < 1)
|
||||||
|
E.Origin.Tell("This server has not set any rules.");
|
||||||
|
else
|
||||||
|
{
|
||||||
|
foreach (String r in E.Owner.rules)
|
||||||
|
E.Origin.Tell("- " + r);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
33
Admin/Connection.cs
Normal file
33
Admin/Connection.cs
Normal file
@ -0,0 +1,33 @@
|
|||||||
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System.Text;
|
||||||
|
using System.Net;
|
||||||
|
using System.IO;
|
||||||
|
|
||||||
|
namespace IW4MAdmin
|
||||||
|
{
|
||||||
|
class Connection
|
||||||
|
{
|
||||||
|
public Connection(String Loc)
|
||||||
|
{
|
||||||
|
Location = Loc;
|
||||||
|
ConnectionHandle = WebRequest.Create(Location);
|
||||||
|
ConnectionHandle.Proxy = null;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String Read()
|
||||||
|
{
|
||||||
|
WebResponse Resp = ConnectionHandle.GetResponse();
|
||||||
|
StreamReader data_in = new StreamReader(Resp.GetResponseStream());
|
||||||
|
String result = data_in.ReadToEnd();
|
||||||
|
|
||||||
|
data_in.Close();
|
||||||
|
Resp.Close();
|
||||||
|
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
private String Location;
|
||||||
|
private WebRequest ConnectionHandle;
|
||||||
|
}
|
||||||
|
}
|
244
Admin/Database.cs
Normal file
244
Admin/Database.cs
Normal file
@ -0,0 +1,244 @@
|
|||||||
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System.Text;
|
||||||
|
using System.Data.SQLite;
|
||||||
|
using System.Data;
|
||||||
|
using System.IO;
|
||||||
|
using System.Collections;
|
||||||
|
|
||||||
|
namespace IW4MAdmin
|
||||||
|
{
|
||||||
|
class Database
|
||||||
|
{
|
||||||
|
public Database(String FN)
|
||||||
|
{
|
||||||
|
FileName = FN;
|
||||||
|
DBCon = String.Format("Data Source={0}", FN);
|
||||||
|
Con = new SQLiteConnection(DBCon);
|
||||||
|
Init();
|
||||||
|
}
|
||||||
|
|
||||||
|
private void Init()
|
||||||
|
{
|
||||||
|
if(!File.Exists(FileName))
|
||||||
|
{
|
||||||
|
String query = "CREATE TABLE [CLIENTS] ( [Name] TEXT NULL, [npID] TEXT NULL, [Number] INTEGER PRIMARY KEY AUTOINCREMENT, [Level] INT DEFAULT 0 NULL, [LastOffense] TEXT NULL, [Connections] INT DEFAULT 1 NULL);";
|
||||||
|
ExecuteNonQuery(query);
|
||||||
|
query = "CREATE TABLE [BANS] ( [Reason] TEXT NULL, [npID] TEXT NULL, [bannedByID] Text NULL)";
|
||||||
|
ExecuteNonQuery(query);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public Player getPlayer(String ID, int cNum)
|
||||||
|
{
|
||||||
|
String Query = String.Format("SELECT * FROM CLIENTS WHERE npID = '{0}' LIMIT 1", ID);
|
||||||
|
DataTable Result = GetDataTable(Query);
|
||||||
|
|
||||||
|
if (Result != null && Result.Rows.Count > 0)
|
||||||
|
{
|
||||||
|
DataRow ResponseRow = Result.Rows[0];
|
||||||
|
return new Player(ResponseRow["Name"].ToString(), ResponseRow["npID"].ToString(), cNum, (Player.Permission)(ResponseRow["Level"]), Convert.ToInt32(ResponseRow["Number"]), ResponseRow["LastOffense"].ToString(), ((int)ResponseRow["Connections"] + 1));
|
||||||
|
}
|
||||||
|
|
||||||
|
else
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
public List<Player> findPlayers(String name)
|
||||||
|
{
|
||||||
|
String Query = String.Format("SELECT * FROM CLIENTS WHERE Name LIKE '%{0}%' LIMIT 10", name);
|
||||||
|
DataTable Result = GetDataTable(Query);
|
||||||
|
|
||||||
|
List<Player> Players = new List<Player>();
|
||||||
|
|
||||||
|
if (Result != null && Result.Rows.Count > 0)
|
||||||
|
{
|
||||||
|
foreach (DataRow p in Result.Rows)
|
||||||
|
{
|
||||||
|
Players.Add(new Player(p["Name"].ToString(), p["npID"].ToString(), -1, (Player.Permission)(p["Level"]), Convert.ToInt32(p["Number"]), p["LastOffense"].ToString(), ((int)p["Connections"])));
|
||||||
|
}
|
||||||
|
return Players;
|
||||||
|
}
|
||||||
|
|
||||||
|
else
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Player findPlayers(int dbIndex)
|
||||||
|
{
|
||||||
|
String Query = String.Format("SELECT * FROM CLIENTS WHERE Number = '{0}' LIMIT 1", dbIndex);
|
||||||
|
DataTable Result = GetDataTable(Query);
|
||||||
|
|
||||||
|
if (Result != null && Result.Rows.Count > 0)
|
||||||
|
{
|
||||||
|
foreach (DataRow p in Result.Rows)
|
||||||
|
return new Player(p["Name"].ToString(), p["npID"].ToString(), -1, (Player.Permission)(p["Level"]), Convert.ToInt32(p["Number"]), p["LastOffense"].ToString(), ((int)p["Connections"]));
|
||||||
|
}
|
||||||
|
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Player getOwner()
|
||||||
|
{
|
||||||
|
String Query = String.Format("SELECT * FROM CLIENTS WHERE Level = '{0}'", 4);
|
||||||
|
DataTable Result = GetDataTable(Query);
|
||||||
|
|
||||||
|
if (Result != null && Result.Rows.Count > 0)
|
||||||
|
{
|
||||||
|
DataRow ResponseRow = Result.Rows[0];
|
||||||
|
return new Player(ResponseRow["Name"].ToString(), ResponseRow["npID"].ToString(), -1, (Player.Permission)(ResponseRow["Level"]), Convert.ToInt32(ResponseRow["Number"]), null, 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
else
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
public List<Ban> getBans()
|
||||||
|
{
|
||||||
|
List<Ban> Bans = new List<Ban>();
|
||||||
|
DataTable Result = GetDataTable("SELECT * FROM BANS");
|
||||||
|
|
||||||
|
foreach (DataRow Row in Result.Rows)
|
||||||
|
Bans.Add(new Ban(Row["Reason"].ToString(), Row["npID"].ToString(), Row["bannedByID"].ToString()));
|
||||||
|
|
||||||
|
return Bans;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void removeBan(String GUID)
|
||||||
|
{
|
||||||
|
String Query = String.Format("DELETE FROM BANS WHERE npID = '{0}'", GUID);
|
||||||
|
ExecuteNonQuery(Query);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void addPlayer(Player P)
|
||||||
|
{
|
||||||
|
Dictionary<String, object> newPlayer = new Dictionary<String, object>();
|
||||||
|
|
||||||
|
newPlayer.Add("Name", Utilities.removeNastyChars(P.getName()));
|
||||||
|
newPlayer.Add("npID", P.getID());
|
||||||
|
newPlayer.Add("Level", (int)P.getLevel());
|
||||||
|
// newPlayer.Add("Number", P.getClientNum().ToString());
|
||||||
|
newPlayer.Add("LastOffense", "");
|
||||||
|
newPlayer.Add("Connections", 1);
|
||||||
|
|
||||||
|
Insert("CLIENTS", newPlayer);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void updatePlayer(Player P)
|
||||||
|
{
|
||||||
|
Dictionary<String, object> updatedPlayer = new Dictionary<String, object>();
|
||||||
|
|
||||||
|
updatedPlayer.Add("Name", P.getName());
|
||||||
|
updatedPlayer.Add("npID", P.getID());
|
||||||
|
updatedPlayer.Add("Level", (int)P.getLevel());
|
||||||
|
// updatedPlayer.Add("Number", P.getClientNum().ToString());
|
||||||
|
updatedPlayer.Add("LastOffense", P.getLastO());
|
||||||
|
updatedPlayer.Add("Connections", P.getConnections());
|
||||||
|
|
||||||
|
Update("CLIENTS", updatedPlayer, String.Format("npID = '{0}'", P.getID()));
|
||||||
|
}
|
||||||
|
|
||||||
|
public void addBan(Ban B)
|
||||||
|
{
|
||||||
|
Dictionary<String, object> newBan = new Dictionary<String, object>();
|
||||||
|
|
||||||
|
newBan.Add("Reason", B.getReason());
|
||||||
|
newBan.Add("npID", B.getID());
|
||||||
|
newBan.Add("bannedByID", B.getBanner());
|
||||||
|
|
||||||
|
Insert("BANS", newBan);
|
||||||
|
}
|
||||||
|
|
||||||
|
//HELPERS
|
||||||
|
|
||||||
|
public bool Insert(String tableName, Dictionary<String, object> data)
|
||||||
|
{
|
||||||
|
String columns = "";
|
||||||
|
String values = "";
|
||||||
|
Boolean returnCode = true;
|
||||||
|
foreach (KeyValuePair<String, object> val in data)
|
||||||
|
{
|
||||||
|
columns += String.Format(" {0},", val.Key);
|
||||||
|
values += String.Format(" '{0}',", val.Value);
|
||||||
|
}
|
||||||
|
columns = columns.Substring(0, columns.Length - 1);
|
||||||
|
values = values.Substring(0, values.Length - 1);
|
||||||
|
try
|
||||||
|
{
|
||||||
|
this.ExecuteNonQuery(String.Format("insert into {0}({1}) values({2});", tableName, columns, values));
|
||||||
|
}
|
||||||
|
catch (Exception fail)
|
||||||
|
{
|
||||||
|
Console.WriteLine(fail.Message);
|
||||||
|
returnCode = false;
|
||||||
|
}
|
||||||
|
return returnCode;
|
||||||
|
}
|
||||||
|
|
||||||
|
public bool Update(String tableName, Dictionary<String, object> data, String where)
|
||||||
|
{
|
||||||
|
String vals = "";
|
||||||
|
Boolean returnCode = true;
|
||||||
|
if (data.Count >= 1)
|
||||||
|
{
|
||||||
|
foreach (KeyValuePair<String, object> val in data)
|
||||||
|
{
|
||||||
|
vals += String.Format(" {0} = '{1}',", val.Key, val.Value);
|
||||||
|
}
|
||||||
|
vals = vals.Substring(0, vals.Length - 1);
|
||||||
|
}
|
||||||
|
try
|
||||||
|
{
|
||||||
|
this.ExecuteNonQuery(String.Format("update {0} set {1} where {2};", tableName, vals, where));
|
||||||
|
}
|
||||||
|
catch (Exception fail)
|
||||||
|
{
|
||||||
|
Console.WriteLine(fail.Message);
|
||||||
|
returnCode = false;
|
||||||
|
}
|
||||||
|
return returnCode;
|
||||||
|
}
|
||||||
|
|
||||||
|
public DataRow getDataRow(String Q)
|
||||||
|
{
|
||||||
|
DataRow Result = GetDataTable(Q).Rows[0];
|
||||||
|
return Result;
|
||||||
|
}
|
||||||
|
|
||||||
|
private int ExecuteNonQuery(String Request)
|
||||||
|
{
|
||||||
|
Con.Open();
|
||||||
|
SQLiteCommand CMD = new SQLiteCommand(Con);
|
||||||
|
CMD.CommandText = Request;
|
||||||
|
int rowsUpdated = CMD.ExecuteNonQuery();
|
||||||
|
Con.Close();
|
||||||
|
return rowsUpdated;
|
||||||
|
}
|
||||||
|
|
||||||
|
public DataTable GetDataTable(String sql)
|
||||||
|
{
|
||||||
|
DataTable dt = new DataTable();
|
||||||
|
try
|
||||||
|
{
|
||||||
|
Con.Open();
|
||||||
|
SQLiteCommand mycommand = new SQLiteCommand(Con);
|
||||||
|
mycommand.CommandText = sql;
|
||||||
|
SQLiteDataReader reader = mycommand.ExecuteReader();
|
||||||
|
dt.Load(reader);
|
||||||
|
reader.Close();
|
||||||
|
Con.Close();
|
||||||
|
}
|
||||||
|
catch (Exception e)
|
||||||
|
{
|
||||||
|
Console.WriteLine(e.Message);
|
||||||
|
throw new Exception(e.Message);
|
||||||
|
}
|
||||||
|
return dt;
|
||||||
|
}
|
||||||
|
//END
|
||||||
|
|
||||||
|
private String FileName;
|
||||||
|
private String DBCon;
|
||||||
|
private SQLiteConnection Con;
|
||||||
|
}
|
||||||
|
}
|
105
Admin/Event.cs
Normal file
105
Admin/Event.cs
Normal file
@ -0,0 +1,105 @@
|
|||||||
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System.Text;
|
||||||
|
using System.Text.RegularExpressions;
|
||||||
|
|
||||||
|
namespace IW4MAdmin
|
||||||
|
{
|
||||||
|
class Event
|
||||||
|
{
|
||||||
|
public enum GType
|
||||||
|
{
|
||||||
|
//FROM SERVER
|
||||||
|
Connect,
|
||||||
|
Disconnect,
|
||||||
|
Say,
|
||||||
|
Kill,
|
||||||
|
Death,
|
||||||
|
MapChange,
|
||||||
|
MapEnd,
|
||||||
|
|
||||||
|
//FROM ADMIN
|
||||||
|
Broadcast,
|
||||||
|
Tell,
|
||||||
|
Kick,
|
||||||
|
Ban,
|
||||||
|
|
||||||
|
Unknown,
|
||||||
|
}
|
||||||
|
|
||||||
|
public Event(GType t, string d, Player O, Player T, Server S)
|
||||||
|
{
|
||||||
|
Type = t;
|
||||||
|
Data = d;
|
||||||
|
Origin = O;
|
||||||
|
Target = T;
|
||||||
|
Owner = S;
|
||||||
|
}
|
||||||
|
|
||||||
|
//This needs to be here
|
||||||
|
public Command isValidCMD(List<Command> list)
|
||||||
|
{
|
||||||
|
if (this.Data.Substring(0, 1) == "!")
|
||||||
|
{
|
||||||
|
string[] cmd = this.Data.Substring(1, this.Data.Length - 1).Split(' ');
|
||||||
|
|
||||||
|
foreach (Command C in list)
|
||||||
|
{
|
||||||
|
if (C.getName() == cmd[0].ToLower() || C.getAlias() == cmd[0].ToLower())
|
||||||
|
return C;
|
||||||
|
}
|
||||||
|
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
else
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static Event requestEvent(String[] line, Server SV)
|
||||||
|
{
|
||||||
|
try
|
||||||
|
{
|
||||||
|
String eventType = line[0].Substring(line[0].Length - 1);
|
||||||
|
eventType = eventType.Trim();
|
||||||
|
|
||||||
|
if (eventType == "J")
|
||||||
|
return new Event(GType.Connect, null, SV.clientFromLine(line, 3, true), null, SV);
|
||||||
|
|
||||||
|
if (eventType == "Q")
|
||||||
|
return new Event(GType.Disconnect, null, SV.clientFromLine(line, 3, false), null, null);
|
||||||
|
|
||||||
|
if (line[0].Substring(line[0].Length - 3).Trim() == "say")
|
||||||
|
{
|
||||||
|
Regex rgx = new Regex("[^a-zA-Z0-9 -! -_]");
|
||||||
|
string message = rgx.Replace(line[4], "");
|
||||||
|
if (message.Length < 2)
|
||||||
|
message = " ";
|
||||||
|
return new Event(GType.Say, Utilities.removeNastyChars(message), SV.clientFromLine(line, 3, false), null, null);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (eventType == "d")
|
||||||
|
return new Event(GType.MapEnd, null, null, null, null);
|
||||||
|
|
||||||
|
if (line[0].Length > 400) // blaze it
|
||||||
|
return new Event(GType.MapChange, null, null, null, null);
|
||||||
|
|
||||||
|
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
catch (Exception E)
|
||||||
|
{
|
||||||
|
SV.Log.Write("Error requesting event " + E.Message, Log.Level.Debug);
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
public GType Type;
|
||||||
|
public string Data; // Data is usually the message sent by player
|
||||||
|
public Player Origin;
|
||||||
|
public Player Target;
|
||||||
|
public Server Owner;
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
161
Admin/File.cs
Normal file
161
Admin/File.cs
Normal file
@ -0,0 +1,161 @@
|
|||||||
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System.Text;
|
||||||
|
using System.IO;
|
||||||
|
|
||||||
|
namespace IW4MAdmin
|
||||||
|
{
|
||||||
|
class file
|
||||||
|
{
|
||||||
|
public file(String fileName)
|
||||||
|
{
|
||||||
|
//Not safe for directories with more than one folder but meh
|
||||||
|
_Directory = fileName.Split('\\')[0];
|
||||||
|
Name = (fileName.Split('\\'))[fileName.Split('\\').Length-1];
|
||||||
|
|
||||||
|
if (!Directory.Exists(_Directory))
|
||||||
|
Directory.CreateDirectory(_Directory);
|
||||||
|
|
||||||
|
if (!File.Exists(fileName))
|
||||||
|
{
|
||||||
|
FileStream penis = File.Create(fileName);
|
||||||
|
penis.Close();
|
||||||
|
}
|
||||||
|
Handle = new StreamReader(new FileStream(fileName, FileMode.Open, FileAccess.Read, FileShare.ReadWrite));
|
||||||
|
sze = Handle.BaseStream.Length;
|
||||||
|
}
|
||||||
|
|
||||||
|
public file(String file, bool write)
|
||||||
|
{
|
||||||
|
Name = file;
|
||||||
|
writeHandle = new StreamWriter(new FileStream(Name, FileMode.Create, FileAccess.Write, FileShare.ReadWrite));
|
||||||
|
sze = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
public long getSize()
|
||||||
|
{
|
||||||
|
sze = Handle.BaseStream.Length;
|
||||||
|
return sze;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void Write(String line)
|
||||||
|
{
|
||||||
|
writeHandle.WriteLine(line);
|
||||||
|
writeHandle.Flush();
|
||||||
|
}
|
||||||
|
|
||||||
|
public String[] getParameters(int num)
|
||||||
|
{
|
||||||
|
if (sze > 0)
|
||||||
|
{
|
||||||
|
String firstLine = Handle.ReadLine();
|
||||||
|
String[] Parms = firstLine.Split(':');
|
||||||
|
if (Parms.Length < num)
|
||||||
|
return null;
|
||||||
|
else
|
||||||
|
return Parms;
|
||||||
|
}
|
||||||
|
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
public int getNumLines()
|
||||||
|
{
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
//FROM http://stackoverflow.com/questions/398378/get-last-10-lines-of-very-large-text-file-10gb-c-sharp
|
||||||
|
public string ReadEndTokens()
|
||||||
|
{
|
||||||
|
Encoding encoding = Encoding.ASCII;
|
||||||
|
string tokenSeparator = "\n";
|
||||||
|
int numberOfTokens = 2;
|
||||||
|
|
||||||
|
int sizeOfChar = encoding.GetByteCount("\n");
|
||||||
|
byte[] buffer = encoding.GetBytes(tokenSeparator);
|
||||||
|
|
||||||
|
using (FileStream fs = new FileStream(this.Name, FileMode.Open, FileAccess.Read, FileShare.ReadWrite))
|
||||||
|
{
|
||||||
|
Int64 tokenCount = 0;
|
||||||
|
Int64 endPosition = fs.Length / sizeOfChar;
|
||||||
|
|
||||||
|
for (Int64 position = sizeOfChar; position < endPosition; position += sizeOfChar)
|
||||||
|
{
|
||||||
|
fs.Seek(-position, SeekOrigin.End);
|
||||||
|
fs.Read(buffer, 0, buffer.Length);
|
||||||
|
|
||||||
|
if (encoding.GetString(buffer) == tokenSeparator)
|
||||||
|
{
|
||||||
|
tokenCount++;
|
||||||
|
if (tokenCount == numberOfTokens)
|
||||||
|
{
|
||||||
|
byte[] returnBuffer = new byte[fs.Length - fs.Position];
|
||||||
|
fs.Read(returnBuffer, 0, returnBuffer.Length);
|
||||||
|
return encoding.GetString(returnBuffer);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// handle case where number of tokens in file is less than numberOfTokens
|
||||||
|
fs.Seek(0, SeekOrigin.Begin);
|
||||||
|
buffer = new byte[fs.Length];
|
||||||
|
fs.Read(buffer, 0, buffer.Length);
|
||||||
|
return encoding.GetString(buffer);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
public String[] readAll()
|
||||||
|
{
|
||||||
|
return Handle.ReadToEnd().Split('\n');
|
||||||
|
}
|
||||||
|
|
||||||
|
public String[] end(int neededLines)
|
||||||
|
{
|
||||||
|
var lines = new List<String>();
|
||||||
|
while (!Handle.EndOfStream)
|
||||||
|
{
|
||||||
|
String lins = Handle.ReadLine();
|
||||||
|
lines.Add(lins.ToString());
|
||||||
|
if (lines.Count > neededLines)
|
||||||
|
{
|
||||||
|
lines.RemoveAt(0);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return lines.ToArray();
|
||||||
|
}
|
||||||
|
|
||||||
|
public String[] Tail(int lineCount)
|
||||||
|
{
|
||||||
|
var buffer = new List<string>(lineCount);
|
||||||
|
string line;
|
||||||
|
for (int i = 0; i < lineCount; i++)
|
||||||
|
{
|
||||||
|
line = Handle.ReadLine();
|
||||||
|
if (line == null) return buffer.ToArray();
|
||||||
|
buffer.Add(line);
|
||||||
|
}
|
||||||
|
|
||||||
|
int lastLine = lineCount - 1; //The index of the last line read from the buffer. Everything > this index was read earlier than everything <= this indes
|
||||||
|
|
||||||
|
while (null != (line = Handle.ReadLine()))
|
||||||
|
{
|
||||||
|
lastLine++;
|
||||||
|
if (lastLine == lineCount) lastLine = 0;
|
||||||
|
buffer[lastLine] = line;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (lastLine == lineCount - 1) return buffer.ToArray();
|
||||||
|
var retVal = new string[lineCount];
|
||||||
|
buffer.CopyTo(lastLine + 1, retVal, 0, lineCount - lastLine - 1);
|
||||||
|
buffer.CopyTo(0, retVal, lineCount - lastLine - 1, lastLine + 1);
|
||||||
|
return retVal;
|
||||||
|
}
|
||||||
|
//END
|
||||||
|
|
||||||
|
private long sze;
|
||||||
|
private String Name;
|
||||||
|
private String _Directory;
|
||||||
|
StreamReader Handle;
|
||||||
|
StreamWriter writeHandle;
|
||||||
|
}
|
||||||
|
}
|
145
Admin/IW4M ADMIN.csproj
Normal file
145
Admin/IW4M ADMIN.csproj
Normal file
@ -0,0 +1,145 @@
|
|||||||
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
|
<Project ToolsVersion="4.0" DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
|
||||||
|
<Import Project="$(MSBuildExtensionsPath)\$(MSBuildToolsVersion)\Microsoft.Common.props" Condition="Exists('$(MSBuildExtensionsPath)\$(MSBuildToolsVersion)\Microsoft.Common.props')" />
|
||||||
|
<PropertyGroup>
|
||||||
|
<Configuration Condition=" '$(Configuration)' == '' ">Debug</Configuration>
|
||||||
|
<Platform Condition=" '$(Platform)' == '' ">AnyCPU</Platform>
|
||||||
|
<ProjectGuid>{DD5DCDA2-51DB-4B1A-922F-5705546E6115}</ProjectGuid>
|
||||||
|
<OutputType>Exe</OutputType>
|
||||||
|
<AppDesignerFolder>Properties</AppDesignerFolder>
|
||||||
|
<RootNamespace>IW4MAdmin</RootNamespace>
|
||||||
|
<AssemblyName>IW4MAdmin</AssemblyName>
|
||||||
|
<TargetFrameworkVersion>v2.0</TargetFrameworkVersion>
|
||||||
|
<FileAlignment>512</FileAlignment>
|
||||||
|
<TargetFrameworkProfile />
|
||||||
|
<IsWebBootstrapper>false</IsWebBootstrapper>
|
||||||
|
<PublishUrl>C:\Users\Michael\Desktop\IW4MAdmin\</PublishUrl>
|
||||||
|
<Install>true</Install>
|
||||||
|
<InstallFrom>Disk</InstallFrom>
|
||||||
|
<UpdateEnabled>false</UpdateEnabled>
|
||||||
|
<UpdateMode>Foreground</UpdateMode>
|
||||||
|
<UpdateInterval>7</UpdateInterval>
|
||||||
|
<UpdateIntervalUnits>Days</UpdateIntervalUnits>
|
||||||
|
<UpdatePeriodically>false</UpdatePeriodically>
|
||||||
|
<UpdateRequired>false</UpdateRequired>
|
||||||
|
<MapFileExtensions>true</MapFileExtensions>
|
||||||
|
<ProductName>IW4M Administration</ProductName>
|
||||||
|
<PublisherName>RaidMax LLC</PublisherName>
|
||||||
|
<WebPage>publish.htm</WebPage>
|
||||||
|
<AutorunEnabled>true</AutorunEnabled>
|
||||||
|
<ApplicationRevision>2</ApplicationRevision>
|
||||||
|
<ApplicationVersion>0.1.0.%2a</ApplicationVersion>
|
||||||
|
<UseApplicationTrust>false</UseApplicationTrust>
|
||||||
|
<PublishWizardCompleted>true</PublishWizardCompleted>
|
||||||
|
<BootstrapperEnabled>true</BootstrapperEnabled>
|
||||||
|
</PropertyGroup>
|
||||||
|
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|AnyCPU' ">
|
||||||
|
<PlatformTarget>AnyCPU</PlatformTarget>
|
||||||
|
<DebugSymbols>true</DebugSymbols>
|
||||||
|
<DebugType>full</DebugType>
|
||||||
|
<Optimize>false</Optimize>
|
||||||
|
<OutputPath>bin\Debug\</OutputPath>
|
||||||
|
<DefineConstants>DEBUG;TRACE</DefineConstants>
|
||||||
|
<ErrorReport>prompt</ErrorReport>
|
||||||
|
<WarningLevel>4</WarningLevel>
|
||||||
|
</PropertyGroup>
|
||||||
|
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release|AnyCPU' ">
|
||||||
|
<PlatformTarget>x86</PlatformTarget>
|
||||||
|
<DebugType>pdbonly</DebugType>
|
||||||
|
<Optimize>true</Optimize>
|
||||||
|
<OutputPath>bin\Release\</OutputPath>
|
||||||
|
<DefineConstants>TRACE</DefineConstants>
|
||||||
|
<ErrorReport>prompt</ErrorReport>
|
||||||
|
<WarningLevel>0</WarningLevel>
|
||||||
|
</PropertyGroup>
|
||||||
|
<PropertyGroup>
|
||||||
|
<ManifestCertificateThumbprint>0D02A7F5C6EA170625B5BF533E667AE6C3F93065</ManifestCertificateThumbprint>
|
||||||
|
</PropertyGroup>
|
||||||
|
<PropertyGroup>
|
||||||
|
<ManifestKeyFile>IW4M ADMIN_TemporaryKey.pfx</ManifestKeyFile>
|
||||||
|
</PropertyGroup>
|
||||||
|
<PropertyGroup>
|
||||||
|
<GenerateManifests>true</GenerateManifests>
|
||||||
|
</PropertyGroup>
|
||||||
|
<PropertyGroup>
|
||||||
|
<TargetZone>LocalIntranet</TargetZone>
|
||||||
|
</PropertyGroup>
|
||||||
|
<PropertyGroup>
|
||||||
|
<ApplicationManifest>Properties\app.manifest</ApplicationManifest>
|
||||||
|
</PropertyGroup>
|
||||||
|
<PropertyGroup>
|
||||||
|
<SignManifests>true</SignManifests>
|
||||||
|
</PropertyGroup>
|
||||||
|
<PropertyGroup>
|
||||||
|
<ApplicationIcon>4D1.ico</ApplicationIcon>
|
||||||
|
</PropertyGroup>
|
||||||
|
<PropertyGroup>
|
||||||
|
<StartupObject>IW4MAdmin.Program</StartupObject>
|
||||||
|
</PropertyGroup>
|
||||||
|
<ItemGroup>
|
||||||
|
<Reference Include="System" />
|
||||||
|
<Reference Include="System.Data" />
|
||||||
|
<Reference Include="System.Data.SQLite, Version=1.0.66.0, Culture=neutral, PublicKeyToken=db937bc2d44ff139, processorArchitecture=x86">
|
||||||
|
<SpecificVersion>False</SpecificVersion>
|
||||||
|
<HintPath>bin\Release\System.Data.SQLite.dll</HintPath>
|
||||||
|
</Reference>
|
||||||
|
<Reference Include="System.Web" />
|
||||||
|
<Reference Include="System.Xml" />
|
||||||
|
</ItemGroup>
|
||||||
|
<ItemGroup>
|
||||||
|
<Compile Include="Bans.cs" />
|
||||||
|
<Compile Include="Command.cs" />
|
||||||
|
<Compile Include="Connection.cs" />
|
||||||
|
<Compile Include="Database.cs" />
|
||||||
|
<Compile Include="Event.cs" />
|
||||||
|
<Compile Include="File.cs" />
|
||||||
|
<Compile Include="Log.cs" />
|
||||||
|
<Compile Include="Main.cs" />
|
||||||
|
<Compile Include="Maps.cs" />
|
||||||
|
<Compile Include="Player.cs" />
|
||||||
|
<Compile Include="Properties\AssemblyInfo.cs" />
|
||||||
|
<Compile Include="Properties\Settings.Designer.cs">
|
||||||
|
<AutoGen>True</AutoGen>
|
||||||
|
<DesignTimeSharedInput>True</DesignTimeSharedInput>
|
||||||
|
<DependentUpon>Settings.settings</DependentUpon>
|
||||||
|
</Compile>
|
||||||
|
<Compile Include="RCON.cs" />
|
||||||
|
<Compile Include="Server.cs" />
|
||||||
|
<Compile Include="Utilities.cs" />
|
||||||
|
</ItemGroup>
|
||||||
|
<ItemGroup>
|
||||||
|
<None Include="App.config" />
|
||||||
|
<None Include="IW4M ADMIN_TemporaryKey.pfx" />
|
||||||
|
<None Include="Properties\app.manifest" />
|
||||||
|
<None Include="Properties\Settings.settings">
|
||||||
|
<Generator>SettingsSingleFileGenerator</Generator>
|
||||||
|
<LastGenOutput>Settings.Designer.cs</LastGenOutput>
|
||||||
|
</None>
|
||||||
|
</ItemGroup>
|
||||||
|
<ItemGroup>
|
||||||
|
<BootstrapperPackage Include="Microsoft.Net.Client.3.5">
|
||||||
|
<Visible>False</Visible>
|
||||||
|
<ProductName>.NET Framework 3.5 SP1 Client Profile</ProductName>
|
||||||
|
<Install>false</Install>
|
||||||
|
</BootstrapperPackage>
|
||||||
|
<BootstrapperPackage Include="Microsoft.Net.Framework.3.5.SP1">
|
||||||
|
<Visible>False</Visible>
|
||||||
|
<ProductName>.NET Framework 3.5 SP1</ProductName>
|
||||||
|
<Install>true</Install>
|
||||||
|
</BootstrapperPackage>
|
||||||
|
</ItemGroup>
|
||||||
|
<ItemGroup>
|
||||||
|
<Content Include="4D1.ico" />
|
||||||
|
</ItemGroup>
|
||||||
|
<ItemGroup>
|
||||||
|
<Folder Include="Fakes\" />
|
||||||
|
</ItemGroup>
|
||||||
|
<Import Project="$(MSBuildToolsPath)\Microsoft.CSharp.targets" />
|
||||||
|
<!-- To modify your build process, add your task inside one of the targets below and uncomment it.
|
||||||
|
Other similar extension points exist, see Microsoft.Common.targets.
|
||||||
|
<Target Name="BeforeBuild">
|
||||||
|
</Target>
|
||||||
|
<Target Name="AfterBuild">
|
||||||
|
</Target>
|
||||||
|
-->
|
||||||
|
</Project>
|
54
Admin/Log.cs
Normal file
54
Admin/Log.cs
Normal file
@ -0,0 +1,54 @@
|
|||||||
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System.Text;
|
||||||
|
|
||||||
|
namespace IW4MAdmin
|
||||||
|
{
|
||||||
|
class Log
|
||||||
|
{
|
||||||
|
public enum Level
|
||||||
|
{
|
||||||
|
All,
|
||||||
|
Debug,
|
||||||
|
Production,
|
||||||
|
None,
|
||||||
|
}
|
||||||
|
|
||||||
|
public Log(file logf, Level mode)
|
||||||
|
{
|
||||||
|
logFile = logf;
|
||||||
|
logMode = mode;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
public void Write(String line, Level lv)
|
||||||
|
{
|
||||||
|
String Line = String.Format("{1} - [{0}]: {2}", lv, getTime(), line);
|
||||||
|
switch(logMode)
|
||||||
|
{
|
||||||
|
case Level.All:
|
||||||
|
if (lv == Level.All || lv == Level.Debug || lv == Level.Production)
|
||||||
|
Console.WriteLine(Line);
|
||||||
|
break;
|
||||||
|
case Level.Debug:
|
||||||
|
if (lv == Level.All || lv == Level.Debug)
|
||||||
|
Console.WriteLine(Line);
|
||||||
|
break;
|
||||||
|
case Level.Production:
|
||||||
|
if (lv == Level.Production)
|
||||||
|
Console.WriteLine(Line);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
logFile.Write(Line);
|
||||||
|
}
|
||||||
|
|
||||||
|
private string getTime()
|
||||||
|
{
|
||||||
|
return DateTime.Now.ToString("HH:mm:ss");
|
||||||
|
}
|
||||||
|
|
||||||
|
private file logFile;
|
||||||
|
private Level logMode;
|
||||||
|
}
|
||||||
|
}
|
36
Admin/Main.cs
Normal file
36
Admin/Main.cs
Normal file
@ -0,0 +1,36 @@
|
|||||||
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System.Text;
|
||||||
|
|
||||||
|
namespace IW4MAdmin
|
||||||
|
{
|
||||||
|
class Program
|
||||||
|
{
|
||||||
|
static void Main(string[] args)
|
||||||
|
{
|
||||||
|
|
||||||
|
file Config = new file("config\\servers.cfg");
|
||||||
|
String[] SV_CONF = Config.getParameters(3);
|
||||||
|
double Version = 0.1;
|
||||||
|
|
||||||
|
if (Config.getSize() > 0 && SV_CONF != null)
|
||||||
|
{
|
||||||
|
Console.WriteLine("=====================================================");
|
||||||
|
Console.WriteLine(" IW4M ADMIN v" + Version);
|
||||||
|
Console.WriteLine(" by RaidMax ");
|
||||||
|
Console.WriteLine("=====================================================");
|
||||||
|
Console.WriteLine("Starting admin on port " + SV_CONF[1]);
|
||||||
|
|
||||||
|
Server IW4M;
|
||||||
|
IW4M = new Server(SV_CONF[0], Convert.ToInt32(SV_CONF[1]), SV_CONF[2]);
|
||||||
|
IW4M.Monitor();
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
Console.WriteLine("[FATAL] CONFIG FILE DOES NOT EXIST OR IS INCORRECT!");
|
||||||
|
Utilities.Wait(5);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
18
Admin/Maps.cs
Normal file
18
Admin/Maps.cs
Normal file
@ -0,0 +1,18 @@
|
|||||||
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System.Text;
|
||||||
|
|
||||||
|
namespace IW4MAdmin
|
||||||
|
{
|
||||||
|
class Map
|
||||||
|
{
|
||||||
|
public Map(String N, String A)
|
||||||
|
{
|
||||||
|
Name = N;
|
||||||
|
Alias = A;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String Name;
|
||||||
|
public String Alias;
|
||||||
|
}
|
||||||
|
}
|
134
Admin/Player.cs
Normal file
134
Admin/Player.cs
Normal file
@ -0,0 +1,134 @@
|
|||||||
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System.Text;
|
||||||
|
|
||||||
|
namespace IW4MAdmin
|
||||||
|
{
|
||||||
|
class Player
|
||||||
|
{
|
||||||
|
public enum Permission
|
||||||
|
{
|
||||||
|
Banned = -1,
|
||||||
|
User = 0,
|
||||||
|
Moderator = 1,
|
||||||
|
Administrator = 2,
|
||||||
|
SeniorAdmin = 3,
|
||||||
|
Owner = 4,
|
||||||
|
Creator = 5,
|
||||||
|
}
|
||||||
|
|
||||||
|
public Player(string n, string id, int num, int l)
|
||||||
|
{
|
||||||
|
Name = n;
|
||||||
|
npID = id;
|
||||||
|
Number = num;
|
||||||
|
Level = (Player.Permission)l;
|
||||||
|
LastOffense = null;
|
||||||
|
Connections = 0;
|
||||||
|
Warnings = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Player(string n, string id, int num, Player.Permission l, int cind, String lo, int con)
|
||||||
|
{
|
||||||
|
Name = n;
|
||||||
|
npID = id;
|
||||||
|
Number = num;
|
||||||
|
Level = l;
|
||||||
|
dbID = cind;
|
||||||
|
LastOffense = lo;
|
||||||
|
Connections = con;
|
||||||
|
Warnings = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getName()
|
||||||
|
{
|
||||||
|
return Name;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getID()
|
||||||
|
{
|
||||||
|
return npID;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getDBID()
|
||||||
|
{
|
||||||
|
return Convert.ToString(dbID);
|
||||||
|
}
|
||||||
|
|
||||||
|
public int getClientNum()
|
||||||
|
{
|
||||||
|
return Number;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Player.Permission getLevel()
|
||||||
|
{
|
||||||
|
return Level;
|
||||||
|
}
|
||||||
|
|
||||||
|
public int getConnections()
|
||||||
|
{
|
||||||
|
return Connections;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getLastO()
|
||||||
|
{
|
||||||
|
return LastOffense;
|
||||||
|
}
|
||||||
|
|
||||||
|
// BECAUSE IT NEEDS TO BE CHANGED!
|
||||||
|
public void setLevel(Player.Permission Perm)
|
||||||
|
{
|
||||||
|
Level = Perm;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void Tell(String Message)
|
||||||
|
{
|
||||||
|
lastEvent.Owner.Tell(Message, this);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void Warn(String Message)
|
||||||
|
{
|
||||||
|
lastEvent.Owner.Broadcast(Message);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void Kick(String Message)
|
||||||
|
{
|
||||||
|
lastEvent.Owner.Kick(Message, this);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void tempBan(String Message)
|
||||||
|
{
|
||||||
|
lastEvent.Owner.tempBan(Message, this);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void Ban(String Message, Player Sender)
|
||||||
|
{
|
||||||
|
lastEvent.Owner.Ban(Message, this, Sender);
|
||||||
|
}
|
||||||
|
|
||||||
|
//should be moved to utils
|
||||||
|
public Player findPlayer(String Nme)
|
||||||
|
{
|
||||||
|
foreach (Player P in lastEvent.Owner.getPlayers())
|
||||||
|
{
|
||||||
|
if (P == null)
|
||||||
|
continue;
|
||||||
|
if (P.getName().ToLower().Contains(Name.ToLower()))
|
||||||
|
return P;
|
||||||
|
}
|
||||||
|
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
private string Name;
|
||||||
|
private string npID;
|
||||||
|
private int Number;
|
||||||
|
private Player.Permission Level;
|
||||||
|
private int dbID;
|
||||||
|
private int Connections;
|
||||||
|
|
||||||
|
public Event lastEvent;
|
||||||
|
public String LastOffense;
|
||||||
|
public int Warnings;
|
||||||
|
}
|
||||||
|
}
|
37
Admin/Properties/AssemblyInfo.cs
Normal file
37
Admin/Properties/AssemblyInfo.cs
Normal file
@ -0,0 +1,37 @@
|
|||||||
|
using System.Reflection;
|
||||||
|
using System.Runtime.CompilerServices;
|
||||||
|
using System.Runtime.InteropServices;
|
||||||
|
using System.Resources;
|
||||||
|
|
||||||
|
// General Information about an assembly is controlled through the following
|
||||||
|
// set of attributes. Change these attribute values to modify the information
|
||||||
|
// associated with an assembly.
|
||||||
|
[assembly: AssemblyTitle("IW4M Admin")]
|
||||||
|
[assembly: AssemblyDescription("Admin for IW4x projects")]
|
||||||
|
[assembly: AssemblyConfiguration("")]
|
||||||
|
[assembly: AssemblyCompany("RaidMax LLC")]
|
||||||
|
[assembly: AssemblyProduct("")]
|
||||||
|
[assembly: AssemblyCopyright("© 2015")]
|
||||||
|
[assembly: AssemblyTrademark("")]
|
||||||
|
[assembly: AssemblyCulture("")]
|
||||||
|
|
||||||
|
// Setting ComVisible to false makes the types in this assembly not visible
|
||||||
|
// to COM components. If you need to access a type in this assembly from
|
||||||
|
// COM, set the ComVisible attribute to true on that type.
|
||||||
|
[assembly: ComVisible(true)]
|
||||||
|
|
||||||
|
// The following GUID is for the ID of the typelib if this project is exposed to COM
|
||||||
|
[assembly: Guid("62f47df4-c8eb-4b5d-bdd8-9de0ca6b570f")]
|
||||||
|
|
||||||
|
// Version information for an assembly consists of the following four values:
|
||||||
|
//
|
||||||
|
// Major Version
|
||||||
|
// Minor Version
|
||||||
|
// Build Number
|
||||||
|
// Revision
|
||||||
|
//
|
||||||
|
// You can specify all the values or you can default the Build and Revision Numbers
|
||||||
|
// by using the '*' as shown below:
|
||||||
|
// [assembly: AssemblyVersion("1.0.*")]
|
||||||
|
[assembly: AssemblyVersion("1.1.*")]
|
||||||
|
[assembly: NeutralResourcesLanguageAttribute("en")]
|
6
Admin/Properties/Settings.settings
Normal file
6
Admin/Properties/Settings.settings
Normal file
@ -0,0 +1,6 @@
|
|||||||
|
<?xml version='1.0' encoding='utf-8'?>
|
||||||
|
<SettingsFile xmlns="http://schemas.microsoft.com/VisualStudio/2004/01/settings" CurrentProfile="(Default)">
|
||||||
|
<Profiles>
|
||||||
|
<Profile Name="(Default)" />
|
||||||
|
</Profiles>
|
||||||
|
</SettingsFile>
|
52
Admin/Properties/app.manifest
Normal file
52
Admin/Properties/app.manifest
Normal file
@ -0,0 +1,52 @@
|
|||||||
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
|
<asmv1:assembly manifestVersion="1.0" xmlns="urn:schemas-microsoft-com:asm.v1" xmlns:asmv1="urn:schemas-microsoft-com:asm.v1" xmlns:asmv2="urn:schemas-microsoft-com:asm.v2" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
|
||||||
|
<assemblyIdentity version="1.0.0.0" name="MyApplication.app" />
|
||||||
|
<trustInfo xmlns="urn:schemas-microsoft-com:asm.v2">
|
||||||
|
<security>
|
||||||
|
<requestedPrivileges xmlns="urn:schemas-microsoft-com:asm.v3">
|
||||||
|
<!-- UAC Manifest Options
|
||||||
|
If you want to change the Windows User Account Control level replace the
|
||||||
|
requestedExecutionLevel node with one of the following.
|
||||||
|
|
||||||
|
<requestedExecutionLevel level="asInvoker" uiAccess="false" />
|
||||||
|
<requestedExecutionLevel level="requireAdministrator" uiAccess="false" />
|
||||||
|
<requestedExecutionLevel level="highestAvailable" uiAccess="false" />
|
||||||
|
|
||||||
|
Specifying requestedExecutionLevel node will disable file and registry virtualization.
|
||||||
|
If you want to utilize File and Registry Virtualization for backward
|
||||||
|
compatibility then delete the requestedExecutionLevel node.
|
||||||
|
-->
|
||||||
|
<requestedExecutionLevel level="asInvoker" uiAccess="false" />
|
||||||
|
</requestedPrivileges>
|
||||||
|
<applicationRequestMinimum>
|
||||||
|
<defaultAssemblyRequest permissionSetReference="Custom" />
|
||||||
|
<PermissionSet class="System.Security.PermissionSet" version="1" ID="Custom" SameSite="site" Unrestricted="true" />
|
||||||
|
</applicationRequestMinimum>
|
||||||
|
</security>
|
||||||
|
</trustInfo>
|
||||||
|
<compatibility xmlns="urn:schemas-microsoft-com:compatibility.v1">
|
||||||
|
<application>
|
||||||
|
<!-- A list of all Windows versions that this application is designed to work with.
|
||||||
|
Windows will automatically select the most compatible environment.-->
|
||||||
|
<!-- If your application is designed to work with Windows Vista, uncomment the following supportedOS node-->
|
||||||
|
<!--<supportedOS Id="{e2011457-1546-43c5-a5fe-008deee3d3f0}"></supportedOS>-->
|
||||||
|
<!-- If your application is designed to work with Windows 7, uncomment the following supportedOS node-->
|
||||||
|
<!--<supportedOS Id="{35138b9a-5d96-4fbd-8e2d-a2440225f93a}"/>-->
|
||||||
|
<!-- If your application is designed to work with Windows 8, uncomment the following supportedOS node-->
|
||||||
|
<!--<supportedOS Id="{4a2f28e3-53b9-4441-ba9c-d69d4a4a6e38}"></supportedOS>-->
|
||||||
|
</application>
|
||||||
|
</compatibility>
|
||||||
|
<!-- Enable themes for Windows common controls and dialogs (Windows XP and later) -->
|
||||||
|
<!-- <dependency>
|
||||||
|
<dependentAssembly>
|
||||||
|
<assemblyIdentity
|
||||||
|
type="win32"
|
||||||
|
name="Microsoft.Windows.Common-Controls"
|
||||||
|
version="6.0.0.0"
|
||||||
|
processorArchitecture="*"
|
||||||
|
publicKeyToken="6595b64144ccf1df"
|
||||||
|
language="*"
|
||||||
|
/>
|
||||||
|
</dependentAssembly>
|
||||||
|
</dependency>-->
|
||||||
|
</asmv1:assembly>
|
129
Admin/RCON.cs
Normal file
129
Admin/RCON.cs
Normal file
@ -0,0 +1,129 @@
|
|||||||
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System.Text;
|
||||||
|
using System.Net;
|
||||||
|
using System.Net.Sockets;
|
||||||
|
using System.Threading;
|
||||||
|
|
||||||
|
//DILEMMA -- Seperate intance of RCON for each server or no?
|
||||||
|
namespace IW4MAdmin
|
||||||
|
{
|
||||||
|
class RCON
|
||||||
|
{
|
||||||
|
enum Type
|
||||||
|
{
|
||||||
|
Query,
|
||||||
|
Execute,
|
||||||
|
}
|
||||||
|
|
||||||
|
public RCON(Server I)
|
||||||
|
{
|
||||||
|
sv_connection = new UdpClient();
|
||||||
|
sv_connection.Client.SendTimeout = 1000;
|
||||||
|
sv_connection.Client.ReceiveTimeout = 1000;
|
||||||
|
Instance = I;
|
||||||
|
toSend = new Queue<String>();
|
||||||
|
}
|
||||||
|
//When we don't care about a response
|
||||||
|
public bool sendRCON(String message)
|
||||||
|
{
|
||||||
|
try
|
||||||
|
{
|
||||||
|
String STR_REQUEST = String.Format("ÿÿÿÿrcon {0} {1}", Instance.getPassword(), message);
|
||||||
|
|
||||||
|
Byte[] Request_ = Encoding.Unicode.GetBytes(STR_REQUEST);
|
||||||
|
Byte[] Request = new Byte[Request_.Length / 2];
|
||||||
|
|
||||||
|
int count = 0; //This is kinda hacky but Unicode -> ASCII doesn't seem to be working correctly for this.
|
||||||
|
foreach (Byte b in Request_)
|
||||||
|
{
|
||||||
|
if (b != 0)
|
||||||
|
Request[count / 2] = b;
|
||||||
|
count++;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
System.Net.IPAddress IP = System.Net.IPAddress.Parse(Instance.getIP());
|
||||||
|
IPEndPoint endPoint = new IPEndPoint(IP, Instance.getPort());
|
||||||
|
|
||||||
|
sv_connection.Connect(endPoint);
|
||||||
|
sv_connection.Send(Request, Request.Length);
|
||||||
|
}
|
||||||
|
|
||||||
|
catch (SocketException)
|
||||||
|
{
|
||||||
|
Instance.Log.Write("Unable to reach server for sending RCON", Log.Level.Debug);
|
||||||
|
sv_connection.Close();
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
//We want to read the reponse
|
||||||
|
public String[] responseSendRCON(String message)
|
||||||
|
{
|
||||||
|
try
|
||||||
|
{
|
||||||
|
String STR_REQUEST;
|
||||||
|
if (message != "getstatus")
|
||||||
|
STR_REQUEST = String.Format("ÿÿÿÿrcon {0} {1}", Instance.getPassword(), message);
|
||||||
|
else
|
||||||
|
STR_REQUEST = String.Format("ÿÿÿÿ getstatus");
|
||||||
|
|
||||||
|
Byte[] Request_ = Encoding.Unicode.GetBytes(STR_REQUEST);
|
||||||
|
Byte[] Request = new Byte[Request_.Length/2];
|
||||||
|
|
||||||
|
int count = 0; //This is kinda hacky but Unicode -> ASCII doesn't seem to be working correctly for this.
|
||||||
|
foreach (Byte b in Request_)
|
||||||
|
{
|
||||||
|
if (b != 0)
|
||||||
|
Request[count/2] = b;
|
||||||
|
count++;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
System.Net.IPAddress IP = System.Net.IPAddress.Parse(Instance.getIP());
|
||||||
|
IPEndPoint endPoint = new IPEndPoint(IP, Instance.getPort());
|
||||||
|
|
||||||
|
sv_connection.Connect(endPoint);
|
||||||
|
sv_connection.Send(Request, Request.Length);
|
||||||
|
|
||||||
|
|
||||||
|
Byte[] receive = sv_connection.Receive(ref endPoint);
|
||||||
|
int num = int.Parse("0a", System.Globalization.NumberStyles.AllowHexSpecifier);
|
||||||
|
|
||||||
|
return System.Text.Encoding.UTF8.GetString(receive).Split((char)num);
|
||||||
|
}
|
||||||
|
|
||||||
|
catch (SocketException)
|
||||||
|
{
|
||||||
|
Instance.Log.Write("Unable to reach server for sending RCON", Log.Level.Debug);
|
||||||
|
sv_connection.Close();
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public void addRCON(String Message, int delay)
|
||||||
|
{
|
||||||
|
toSend.Enqueue(Message);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void ManageRCONQueue()
|
||||||
|
{
|
||||||
|
while (true)
|
||||||
|
{
|
||||||
|
if (toSend.Count > 0)
|
||||||
|
{
|
||||||
|
sendRCON(toSend.Peek());
|
||||||
|
toSend.Dequeue();
|
||||||
|
}
|
||||||
|
Utilities.Wait(0.3);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private UdpClient sv_connection;
|
||||||
|
private Server Instance;
|
||||||
|
private DateTime lastCMD;
|
||||||
|
private Queue<String> toSend;
|
||||||
|
}
|
||||||
|
}
|
234
Admin/SQLiteDatabase.cs
Normal file
234
Admin/SQLiteDatabase.cs
Normal file
@ -0,0 +1,234 @@
|
|||||||
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System.Data;
|
||||||
|
using System.Data.SQLite;
|
||||||
|
|
||||||
|
namespace IW4MAdmin
|
||||||
|
{
|
||||||
|
|
||||||
|
|
||||||
|
public class SQLiteDatabase
|
||||||
|
{
|
||||||
|
String dbConnection;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Default Constructor for SQLiteDatabase Class.
|
||||||
|
/// </summary>
|
||||||
|
public SQLiteDatabase(String file)
|
||||||
|
{
|
||||||
|
dbConnection = "Data Source=" + file;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Single Param Constructor for specifying the DB file.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="inputFile">The File containing the DB</param>
|
||||||
|
public SQLiteDatabase(String inputFile)
|
||||||
|
{
|
||||||
|
dbConnection = String.Format("Data Source={0}", inputFile);
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Single Param Constructor for specifying advanced connection options.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="connectionOpts">A dictionary containing all desired options and their values</param>
|
||||||
|
public SQLiteDatabase(Dictionary<String, String> connectionOpts)
|
||||||
|
{
|
||||||
|
String str = "";
|
||||||
|
foreach (KeyValuePair<String, String> row in connectionOpts)
|
||||||
|
{
|
||||||
|
str += String.Format("{0}={1}; ", row.Key, row.Value);
|
||||||
|
}
|
||||||
|
str = str.Trim().Substring(0, str.Length - 1);
|
||||||
|
dbConnection = str;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Allows the programmer to run a query against the Database.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="sql">The SQL to run</param>
|
||||||
|
/// <returns>A DataTable containing the result set.</returns>
|
||||||
|
public DataTable GetDataTable(string sql)
|
||||||
|
{
|
||||||
|
DataTable dt = new DataTable();
|
||||||
|
try
|
||||||
|
{
|
||||||
|
SQLiteConnection cnn = new SQLiteConnection(dbConnection);
|
||||||
|
cnn.Open();
|
||||||
|
SQLiteCommand mycommand = new SQLiteCommand(cnn);
|
||||||
|
mycommand.CommandText = sql;
|
||||||
|
SQLiteDataReader reader = mycommand.ExecuteReader();
|
||||||
|
dt.Load(reader);
|
||||||
|
reader.Close();
|
||||||
|
cnn.Close();
|
||||||
|
}
|
||||||
|
catch (Exception e)
|
||||||
|
{
|
||||||
|
Console.WriteLine(e.Message);
|
||||||
|
throw new Exception(e.Message);
|
||||||
|
}
|
||||||
|
return dt;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Allows the programmer to interact with the database for purposes other than a query.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="sql">The SQL to be run.</param>
|
||||||
|
/// <returns>An Integer containing the number of rows updated.</returns>
|
||||||
|
public int ExecuteNonQuery(string sql)
|
||||||
|
{
|
||||||
|
SQLiteConnection cnn = new SQLiteConnection(dbConnection);
|
||||||
|
cnn.Open();
|
||||||
|
SQLiteCommand mycommand = new SQLiteCommand(cnn);
|
||||||
|
mycommand.CommandText = sql;
|
||||||
|
int rowsUpdated = mycommand.ExecuteNonQuery();
|
||||||
|
cnn.Close();
|
||||||
|
return rowsUpdated;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Allows the programmer to retrieve single items from the DB.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="sql">The query to run.</param>
|
||||||
|
/// <returns>A string.</returns>
|
||||||
|
public string ExecuteScalar(string sql)
|
||||||
|
{
|
||||||
|
SQLiteConnection cnn = new SQLiteConnection(dbConnection);
|
||||||
|
cnn.Open();
|
||||||
|
SQLiteCommand mycommand = new SQLiteCommand(cnn);
|
||||||
|
mycommand.CommandText = sql;
|
||||||
|
object value = mycommand.ExecuteScalar();
|
||||||
|
cnn.Close();
|
||||||
|
if (value != null)
|
||||||
|
{
|
||||||
|
return value.ToString();
|
||||||
|
}
|
||||||
|
return "";
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Allows the programmer to easily update rows in the DB.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="tableName">The table to update.</param>
|
||||||
|
/// <param name="data">A dictionary containing Column names and their new values.</param>
|
||||||
|
/// <param name="where">The where clause for the update statement.</param>
|
||||||
|
/// <returns>A boolean true or false to signify success or failure.</returns>
|
||||||
|
public bool Update(String tableName, Dictionary<String, String> data, String where)
|
||||||
|
{
|
||||||
|
String vals = "";
|
||||||
|
Boolean returnCode = true;
|
||||||
|
if (data.Count >= 1)
|
||||||
|
{
|
||||||
|
foreach (KeyValuePair<String, String> val in data)
|
||||||
|
{
|
||||||
|
vals += String.Format(" {0} = '{1}',", val.Key.ToString(), val.Value.ToString());
|
||||||
|
}
|
||||||
|
vals = vals.Substring(0, vals.Length - 1);
|
||||||
|
}
|
||||||
|
try
|
||||||
|
{
|
||||||
|
this.ExecuteNonQuery(String.Format("update {0} set {1} where {2};", tableName, vals, where));
|
||||||
|
}
|
||||||
|
catch( Exception fail)
|
||||||
|
{
|
||||||
|
Console.WriteLine(fail.Message);
|
||||||
|
returnCode = false;
|
||||||
|
}
|
||||||
|
return returnCode;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Allows the programmer to easily delete rows from the DB.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="tableName">The table from which to delete.</param>
|
||||||
|
/// <param name="where">The where clause for the delete.</param>
|
||||||
|
/// <returns>A boolean true or false to signify success or failure.</returns>
|
||||||
|
public bool Delete(String tableName, String where)
|
||||||
|
{
|
||||||
|
Boolean returnCode = true;
|
||||||
|
try
|
||||||
|
{
|
||||||
|
this.ExecuteNonQuery(String.Format("delete from {0} where {1};", tableName, where));
|
||||||
|
}
|
||||||
|
catch (Exception fail)
|
||||||
|
{
|
||||||
|
Console.WriteLine(fail.Message);
|
||||||
|
returnCode = false;
|
||||||
|
}
|
||||||
|
return returnCode;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Allows the programmer to easily insert into the DB
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="tableName">The table into which we insert the data.</param>
|
||||||
|
/// <param name="data">A dictionary containing the column names and data for the insert.</param>
|
||||||
|
/// <returns>A boolean true or false to signify success or failure.</returns>
|
||||||
|
public bool Insert(String tableName, Dictionary<String, String> data)
|
||||||
|
{
|
||||||
|
String columns = "";
|
||||||
|
String values = "";
|
||||||
|
Boolean returnCode = true;
|
||||||
|
foreach (KeyValuePair<String, String> val in data)
|
||||||
|
{
|
||||||
|
columns += String.Format(" {0},", val.Key.ToString());
|
||||||
|
values += String.Format(" '{0}',", val.Value);
|
||||||
|
}
|
||||||
|
columns = columns.Substring(0, columns.Length - 1);
|
||||||
|
values = values.Substring(0, values.Length - 1);
|
||||||
|
try
|
||||||
|
{
|
||||||
|
this.ExecuteNonQuery(String.Format("insert into {0}({1}) values({2});", tableName, columns, values));
|
||||||
|
}
|
||||||
|
catch (Exception fail)
|
||||||
|
{
|
||||||
|
Console.WriteLine(fail.Message);
|
||||||
|
returnCode = false;
|
||||||
|
}
|
||||||
|
return returnCode;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Allows the programmer to easily delete all data from the DB.
|
||||||
|
/// </summary>
|
||||||
|
/// <returns>A boolean true or false to signify success or failure.</returns>
|
||||||
|
public bool ClearDB()
|
||||||
|
{
|
||||||
|
DataTable tables;
|
||||||
|
try
|
||||||
|
{
|
||||||
|
tables = this.GetDataTable("select NAME from SQLITE_MASTER where type='table' order by NAME;");
|
||||||
|
foreach (DataRow table in tables.Rows)
|
||||||
|
{
|
||||||
|
this.ClearTable(table["NAME"].ToString());
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
catch
|
||||||
|
{
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Allows the user to easily clear all data from a specific table.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="table">The name of the table to clear.</param>
|
||||||
|
/// <returns>A boolean true or false to signify success or failure.</returns>
|
||||||
|
public bool ClearTable(String table)
|
||||||
|
{
|
||||||
|
try
|
||||||
|
{
|
||||||
|
|
||||||
|
this.ExecuteNonQuery(String.Format("delete from {0};", table));
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
catch
|
||||||
|
{
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
}
|
759
Admin/Server.cs
Normal file
759
Admin/Server.cs
Normal file
@ -0,0 +1,759 @@
|
|||||||
|
|
||||||
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System.Text;
|
||||||
|
using System.Threading; //SLEEP
|
||||||
|
using System.IO;
|
||||||
|
|
||||||
|
|
||||||
|
namespace IW4MAdmin
|
||||||
|
{
|
||||||
|
class Server
|
||||||
|
{
|
||||||
|
const int FLOOD_TIMEOUT = 300;
|
||||||
|
|
||||||
|
public Server(string address, int port, string password)
|
||||||
|
{
|
||||||
|
IP = address;
|
||||||
|
Port = port;
|
||||||
|
rcon_pass = password;
|
||||||
|
clientnum = 0;
|
||||||
|
RCON = new RCON(this);
|
||||||
|
logFile = new file("admin_" + address + "_" + port + ".log", true);
|
||||||
|
Log = new Log(logFile, Log.Level.Production);
|
||||||
|
players = new List<Player>(new Player[18]);
|
||||||
|
DB = new Database(port + ".db");
|
||||||
|
Bans = DB.getBans();
|
||||||
|
owner = DB.getOwner();
|
||||||
|
maps = new List<Map>();
|
||||||
|
rules = new List<String>();
|
||||||
|
messages = new List<String>();
|
||||||
|
events = new Queue<Event>();
|
||||||
|
nextMessage = 0;
|
||||||
|
initCommands();
|
||||||
|
initMessages();
|
||||||
|
initMaps();
|
||||||
|
initRules();
|
||||||
|
}
|
||||||
|
|
||||||
|
//Returns the current server name -- *STRING*
|
||||||
|
public String getName()
|
||||||
|
{
|
||||||
|
return hostname;
|
||||||
|
}
|
||||||
|
|
||||||
|
//Returns current server IP set by `net_ip` -- *STRING*
|
||||||
|
public String getIP()
|
||||||
|
{
|
||||||
|
return IP;
|
||||||
|
}
|
||||||
|
|
||||||
|
//Returns current server port set by `net_port` -- *INT*
|
||||||
|
public int getPort()
|
||||||
|
{
|
||||||
|
return Port;
|
||||||
|
}
|
||||||
|
|
||||||
|
//Returns number of active clients on server -- *INT*
|
||||||
|
public int getNumPlayers()
|
||||||
|
{
|
||||||
|
return clientnum;
|
||||||
|
}
|
||||||
|
|
||||||
|
//Returns the list of commands
|
||||||
|
public List<Command> getCommands()
|
||||||
|
{
|
||||||
|
return commands;
|
||||||
|
}
|
||||||
|
|
||||||
|
public List<Player> getPlayers()
|
||||||
|
{
|
||||||
|
return players;
|
||||||
|
}
|
||||||
|
|
||||||
|
public List<Ban> getBans()
|
||||||
|
{
|
||||||
|
return Bans;
|
||||||
|
}
|
||||||
|
|
||||||
|
//Performs update on server statistics read from log.
|
||||||
|
public void Update()
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
//Add player object p to `players` list
|
||||||
|
public bool addPlayer(Player P)
|
||||||
|
{
|
||||||
|
try
|
||||||
|
{
|
||||||
|
if (DB.getPlayer(P.getID(), P.getClientNum()) == null)
|
||||||
|
DB.addPlayer(P);
|
||||||
|
else
|
||||||
|
{
|
||||||
|
//messy way to prevent loss of last event
|
||||||
|
Player A;
|
||||||
|
A = DB.getPlayer(P.getID(), P.getClientNum());
|
||||||
|
A.lastEvent = P.lastEvent;
|
||||||
|
P = A;
|
||||||
|
}
|
||||||
|
|
||||||
|
players[P.getClientNum()] = null;
|
||||||
|
players[P.getClientNum()] = P;
|
||||||
|
|
||||||
|
clientnum++;
|
||||||
|
|
||||||
|
if (P.getLevel() == Player.Permission.Banned)
|
||||||
|
{
|
||||||
|
Log.Write("Banned client " + P.getName() + " trying to connect...", Log.Level.Production);
|
||||||
|
String Message = "^1Player Kicked: ^7Previously Banned for ^5" + isBanned(P).getReason();
|
||||||
|
P.Kick(Message);
|
||||||
|
}
|
||||||
|
|
||||||
|
else
|
||||||
|
Log.Write("Client " + P.getName() + " connecting...", Log.Level.Production);
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
catch (Exception E)
|
||||||
|
{
|
||||||
|
Log.Write("Unable to add player - " + E.Message, Log.Level.Debug);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
//Remove player by CLIENT NUMBER
|
||||||
|
public bool removePlayer(int cNum)
|
||||||
|
{
|
||||||
|
Log.Write("Client at " + cNum + " disconnecting...", Log.Level.Production);
|
||||||
|
players[cNum] = null;
|
||||||
|
clientnum--;
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Player clientFromLine(String[] line, int name_pos, bool create)
|
||||||
|
{
|
||||||
|
string Name = line[name_pos].ToString().Trim();
|
||||||
|
if (create)
|
||||||
|
{
|
||||||
|
Player C = new Player(Name, line[1].ToString(), Convert.ToInt16(line[2]), 0);
|
||||||
|
return C;
|
||||||
|
}
|
||||||
|
|
||||||
|
else
|
||||||
|
{
|
||||||
|
foreach (Player P in players)
|
||||||
|
{
|
||||||
|
if (P == null)
|
||||||
|
continue;
|
||||||
|
|
||||||
|
if (line[1].Trim() == P.getID())
|
||||||
|
return P;
|
||||||
|
}
|
||||||
|
|
||||||
|
Log.Write("Could not find player but player is in server. Lets try to manually add (looks like you didn't start me on an empty server)", Log.Level.All);
|
||||||
|
addPlayer(new Player(Name, line[1].ToString(), Convert.ToInt16(line[2]), 0));
|
||||||
|
return players[Convert.ToInt16(line[2])];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public Player clientFromLine(String Name)
|
||||||
|
{
|
||||||
|
foreach (Player P in players)
|
||||||
|
{
|
||||||
|
if (P == null)
|
||||||
|
continue;
|
||||||
|
if (P.getName().ToLower().Contains(Name.ToLower()))
|
||||||
|
return P;
|
||||||
|
}
|
||||||
|
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Ban isBanned(Player C)
|
||||||
|
{
|
||||||
|
if (C.getLevel() == Player.Permission.Banned)
|
||||||
|
{
|
||||||
|
foreach (Ban B in Bans)
|
||||||
|
{
|
||||||
|
if (B.getID() == C.getID())
|
||||||
|
return B;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Command processCommand(Event E, Command C)
|
||||||
|
{
|
||||||
|
E.Data = Utilities.removeWords(E.Data, 1);
|
||||||
|
String[] Args = E.Data.Trim().Split(' ');
|
||||||
|
|
||||||
|
if (Args.Length < (C.getNumArgs()))
|
||||||
|
{
|
||||||
|
E.Origin.Tell("Not enough arguments supplied!");
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
if(E.Origin.getLevel() < C.getNeededPerm())
|
||||||
|
{
|
||||||
|
E.Origin.Tell("You do not have access to that command!");
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (C.needsTarget())
|
||||||
|
{
|
||||||
|
int cNum = -1;
|
||||||
|
int.TryParse(Args[0], out cNum);
|
||||||
|
|
||||||
|
if (Args[0][0] == '@')
|
||||||
|
{
|
||||||
|
int dbID = -1;
|
||||||
|
int.TryParse(Args[0].Substring(1, Args[0].Length-1), out dbID);
|
||||||
|
Player found = E.Owner.DB.findPlayers(dbID);
|
||||||
|
if (found != null)
|
||||||
|
E.Target = found;
|
||||||
|
}
|
||||||
|
|
||||||
|
else if(Args[0].Length < 3 && cNum > -1 && cNum < 18)
|
||||||
|
{
|
||||||
|
if (players[cNum] != null)
|
||||||
|
E.Target = players[cNum];
|
||||||
|
}
|
||||||
|
|
||||||
|
else
|
||||||
|
E.Target = clientFromLine(Args[0]);
|
||||||
|
|
||||||
|
if (E.Target == null)
|
||||||
|
{
|
||||||
|
E.Origin.Tell("Unable to find specified player.");
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return C;
|
||||||
|
}
|
||||||
|
|
||||||
|
private void addEvent(Event E)
|
||||||
|
{
|
||||||
|
events.Enqueue(E);
|
||||||
|
}
|
||||||
|
|
||||||
|
private void manageEventQueue()
|
||||||
|
{
|
||||||
|
while (true)
|
||||||
|
{
|
||||||
|
if (events.Count > 0)
|
||||||
|
{
|
||||||
|
processEvent(events.Peek());
|
||||||
|
events.Dequeue();
|
||||||
|
}
|
||||||
|
Utilities.Wait(0.1);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
//Starts the monitoring process
|
||||||
|
public void Monitor()
|
||||||
|
{
|
||||||
|
if (!intializeBasics())
|
||||||
|
{
|
||||||
|
Log.Write("Shutting due to uncorrectable errors..." + logPath, Log.Level.Debug);
|
||||||
|
Utilities.Wait(10);
|
||||||
|
Environment.Exit(-1);
|
||||||
|
}
|
||||||
|
|
||||||
|
//Handles new rcon requests in a fashionable manner
|
||||||
|
Thread RCONQueue = new Thread(new ThreadStart(RCON.ManageRCONQueue));
|
||||||
|
RCONQueue.Start();
|
||||||
|
|
||||||
|
//Handles new events in a fashionable manner
|
||||||
|
Thread eventQueue = new Thread(new ThreadStart(manageEventQueue));
|
||||||
|
eventQueue.Start();
|
||||||
|
|
||||||
|
long l_size = -1;
|
||||||
|
String[] lines = new String[8];
|
||||||
|
String[] oldLines = new String[8];
|
||||||
|
DateTime start = DateTime.Now;
|
||||||
|
|
||||||
|
Utilities.Wait(1);
|
||||||
|
Broadcast("IW4M Admin is now ^2ONLINE");
|
||||||
|
|
||||||
|
while (errors <=5)
|
||||||
|
{
|
||||||
|
try
|
||||||
|
{
|
||||||
|
lastMessage = DateTime.Now - start;
|
||||||
|
if(lastMessage.TotalSeconds > messageTime && messages.Count > 0)
|
||||||
|
{
|
||||||
|
Broadcast(messages[nextMessage]);
|
||||||
|
if (nextMessage == (messages.Count - 1))
|
||||||
|
nextMessage = 0;
|
||||||
|
else
|
||||||
|
nextMessage++;
|
||||||
|
start = DateTime.Now;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (l_size != logFile.getSize())
|
||||||
|
{
|
||||||
|
lines = logFile.Tail(8);
|
||||||
|
if (lines != oldLines)
|
||||||
|
{
|
||||||
|
l_size = logFile.getSize();
|
||||||
|
int end;
|
||||||
|
if (lines.Length == oldLines.Length)
|
||||||
|
end = lines.Length - 1;
|
||||||
|
else
|
||||||
|
end = Math.Abs((lines.Length - oldLines.Length)) - 1;
|
||||||
|
|
||||||
|
for (int count = 0; count < lines.Length; count++)
|
||||||
|
{
|
||||||
|
if (lines.Length < 1 && oldLines.Length < 1)
|
||||||
|
continue;
|
||||||
|
|
||||||
|
if (lines[count] == oldLines[oldLines.Length - 1])
|
||||||
|
continue;
|
||||||
|
|
||||||
|
if (lines[count].Length < 10) //Not a needed line
|
||||||
|
continue;
|
||||||
|
|
||||||
|
else
|
||||||
|
{
|
||||||
|
string[] game_event = lines[count].Split(';');
|
||||||
|
Event event_ = Event.requestEvent(game_event, this);
|
||||||
|
if (event_ != null)
|
||||||
|
{
|
||||||
|
if (event_.Origin == null)
|
||||||
|
event_.Origin = new Player("WORLD", "-1", -1, 0);
|
||||||
|
|
||||||
|
event_.Origin.lastEvent = event_;
|
||||||
|
event_.Origin.lastEvent.Owner = this;
|
||||||
|
|
||||||
|
addEvent(event_);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
oldLines = lines;
|
||||||
|
l_size = logFile.getSize();
|
||||||
|
Thread.Sleep(1);
|
||||||
|
}
|
||||||
|
catch (Exception E)
|
||||||
|
{
|
||||||
|
Log.Write("Something unexpected occured. Hopefully we can ignore it - " + E.Message + " @" + Utilities.GetLineNumber(E), Log.Level.All);
|
||||||
|
errors++;
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
RCONQueue.Abort();
|
||||||
|
eventQueue.Abort();
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
private bool intializeBasics()
|
||||||
|
{
|
||||||
|
try
|
||||||
|
{
|
||||||
|
//GET fs_basepath
|
||||||
|
String[] p = RCON.responseSendRCON("fs_basepath");
|
||||||
|
|
||||||
|
if (p == null)
|
||||||
|
{
|
||||||
|
Log.Write("Could not obtain basepath!", Log.Level.All);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
p = p[1].Split('"');
|
||||||
|
Basepath = p[3].Substring(0, p[3].Length - 2).Trim();
|
||||||
|
p = null;
|
||||||
|
|
||||||
|
Thread.Sleep(FLOOD_TIMEOUT);
|
||||||
|
//END
|
||||||
|
|
||||||
|
//get fs_game
|
||||||
|
p = RCON.responseSendRCON("fs_game");
|
||||||
|
|
||||||
|
if (p == null)
|
||||||
|
{
|
||||||
|
Log.Write("Could not obtain mod path!", Log.Level.All);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
p = p[1].Split('"');
|
||||||
|
Mod = p[3].Substring(0, p[3].Length - 2).Trim().Replace('/', '\\');
|
||||||
|
p = null;
|
||||||
|
|
||||||
|
Thread.Sleep(FLOOD_TIMEOUT);
|
||||||
|
//END
|
||||||
|
|
||||||
|
//get g_log
|
||||||
|
p = RCON.responseSendRCON("g_log");
|
||||||
|
|
||||||
|
if (p == null)
|
||||||
|
{
|
||||||
|
Log.Write("Could not obtain log path!", Log.Level.All);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (p.Length < 4)
|
||||||
|
{
|
||||||
|
Thread.Sleep(FLOOD_TIMEOUT);
|
||||||
|
Log.Write("Server does not appear to have map loaded. Please map_rotate", Log.Level.All);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
p = p[1].Split('"');
|
||||||
|
string log = p[3].Substring(0, p[3].Length - 2).Trim();
|
||||||
|
p = null;
|
||||||
|
|
||||||
|
Thread.Sleep(FLOOD_TIMEOUT);
|
||||||
|
//END
|
||||||
|
|
||||||
|
//get g_logsync
|
||||||
|
p = RCON.responseSendRCON("g_logsync");
|
||||||
|
|
||||||
|
if (p == null)
|
||||||
|
{
|
||||||
|
Log.Write("Could not obtain log sync status!", Log.Level.All);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
p = p[1].Split('"');
|
||||||
|
int logsync = Convert.ToInt32(p[3].Substring(0, p[3].Length - 2).Trim());
|
||||||
|
p = null;
|
||||||
|
|
||||||
|
Thread.Sleep(FLOOD_TIMEOUT);
|
||||||
|
if (logsync != 1)
|
||||||
|
RCON.sendRCON("g_logsync 1");
|
||||||
|
|
||||||
|
Thread.Sleep(FLOOD_TIMEOUT);
|
||||||
|
//END
|
||||||
|
|
||||||
|
//get iw4m_onelog
|
||||||
|
p = RCON.responseSendRCON("iw4m_onelog");
|
||||||
|
|
||||||
|
if (p[0] == String.Empty || p[1].Length < 15)
|
||||||
|
{
|
||||||
|
Log.Write("Could not obtain iw4m_onelog value!", Log.Level.All);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
p = p[1].Split('"');
|
||||||
|
string onelog = p[3].Substring(0, p[3].Length - 2).Trim();
|
||||||
|
p = null;
|
||||||
|
//END
|
||||||
|
|
||||||
|
Thread.Sleep(FLOOD_TIMEOUT);
|
||||||
|
|
||||||
|
//get sv_hostname
|
||||||
|
p = RCON.responseSendRCON("sv_hostname");
|
||||||
|
|
||||||
|
if (p == null)
|
||||||
|
{
|
||||||
|
Log.Write("Could not obtain server name!", Log.Level.All);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
p = p[1].Split('"');
|
||||||
|
hostname = p[3].Substring(0, p[3].Length - 2).Trim();
|
||||||
|
p = null;
|
||||||
|
//END
|
||||||
|
|
||||||
|
if (Mod == String.Empty || onelog == "1")
|
||||||
|
logPath = Basepath + '\\' + "m2demo" + '\\' + log;
|
||||||
|
else
|
||||||
|
logPath = Basepath + '\\' + Mod + '\\' + log;
|
||||||
|
|
||||||
|
if (!File.Exists(logPath))
|
||||||
|
{
|
||||||
|
Log.Write("Gamelog does not exist!", Log.Level.All);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
logFile = new file(logPath);
|
||||||
|
Log.Write("Log file is " + logPath, Log.Level.Debug);
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
catch (Exception E)
|
||||||
|
{
|
||||||
|
Log.Write("Error during initialization - " + E.Message, Log.Level.All);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
//Process any server event
|
||||||
|
public bool processEvent(Event E)
|
||||||
|
{
|
||||||
|
if (E.Type == Event.GType.Connect)
|
||||||
|
{
|
||||||
|
this.addPlayer(E.Origin);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (E.Type == Event.GType.Disconnect)
|
||||||
|
{
|
||||||
|
if (getNumPlayers() > 0)
|
||||||
|
removePlayer(E.Origin.getClientNum());
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (E.Type == Event.GType.Say)
|
||||||
|
{
|
||||||
|
Log.Write("Message from " + E.Origin.getName() + ": " + E.Data, Log.Level.Debug);
|
||||||
|
|
||||||
|
if (E.Data.Substring(0, 1) != "!")
|
||||||
|
return true;
|
||||||
|
|
||||||
|
Command C = E.isValidCMD(commands);
|
||||||
|
if (C != null)
|
||||||
|
{
|
||||||
|
C = processCommand(E, C);
|
||||||
|
if (C != null)
|
||||||
|
{
|
||||||
|
C.Execute(E);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
Log.Write("Error processing command by " + E.Origin.getName(), Log.Level.Debug);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
else
|
||||||
|
E.Origin.Tell("You entered an invalid command!");
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (E.Type == Event.GType.MapChange)
|
||||||
|
{
|
||||||
|
Log.Write("Map change detected..", Log.Level.Production);
|
||||||
|
return true;
|
||||||
|
//TODO here
|
||||||
|
}
|
||||||
|
|
||||||
|
if (E.Type == Event.GType.MapEnd)
|
||||||
|
{
|
||||||
|
Log.Write("Game ending...", Log.Level.Production);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
//THESE MAY NEED TO BE MOVED
|
||||||
|
public void Broadcast(String Message)
|
||||||
|
{
|
||||||
|
RCON.addRCON("sayraw " + Message, 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void Tell(String Message, Player Target)
|
||||||
|
{
|
||||||
|
RCON.addRCON("tell " + Target.getClientNum() + " " + Message + "^7", 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void Kick(String Message, Player Target)
|
||||||
|
{
|
||||||
|
RCON.addRCON("clientkick " + Target.getClientNum() + " \"" + Message + "^7\"", 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void Ban(String Message, Player Target, Player Origin)
|
||||||
|
{
|
||||||
|
RCON.addRCON("tempbanclient " + Target.getClientNum() + " \"" + Message + "^7\"", 0);
|
||||||
|
if (Origin != null)
|
||||||
|
{
|
||||||
|
Target.setLevel(Player.Permission.Banned);
|
||||||
|
Ban newBan = new Ban(Target.getLastO(), Target.getID(), Origin.getID());
|
||||||
|
Bans.Add(newBan);
|
||||||
|
DB.addBan(newBan);
|
||||||
|
DB.updatePlayer(Target);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public bool Unban(String GUID)
|
||||||
|
{
|
||||||
|
foreach (Ban B in Bans)
|
||||||
|
{
|
||||||
|
if (B.getID() == GUID)
|
||||||
|
{
|
||||||
|
DB.removeBan(GUID);
|
||||||
|
Bans.Remove(B);
|
||||||
|
Player P = DB.getPlayer(GUID, 0);
|
||||||
|
P.setLevel(Player.Permission.User);
|
||||||
|
DB.updatePlayer(P);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
public void fastRestart(int delay)
|
||||||
|
{
|
||||||
|
Utilities.Wait(delay);
|
||||||
|
RCON.addRCON("fast_restart", 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void mapRotate(int delay)
|
||||||
|
{
|
||||||
|
Utilities.Wait(delay);
|
||||||
|
RCON.addRCON("map_rotate", 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void tempBan(String Message, Player Target)
|
||||||
|
{
|
||||||
|
RCON.addRCON("tempbanclient " + Target.getClientNum() + " \"" + Message + "\"", 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void mapRotate()
|
||||||
|
{
|
||||||
|
RCON.addRCON("map_rotate", 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void Map(String map)
|
||||||
|
{
|
||||||
|
RCON.addRCON("map " + map, 0);
|
||||||
|
}
|
||||||
|
//END
|
||||||
|
|
||||||
|
//THIS IS BAD BECAUSE WE DON"T WANT EVERYONE TO HAVE ACCESS :/
|
||||||
|
public String getPassword()
|
||||||
|
{
|
||||||
|
return rcon_pass;
|
||||||
|
}
|
||||||
|
|
||||||
|
private void initMaps()
|
||||||
|
{
|
||||||
|
file mapfile = new file("config\\maps.cfg");
|
||||||
|
String[] _maps = mapfile.readAll();
|
||||||
|
if (_maps.Length > 2) // readAll returns minimum one empty string
|
||||||
|
{
|
||||||
|
foreach (String m in _maps)
|
||||||
|
{
|
||||||
|
String[] m2 = m.Split(':');
|
||||||
|
if (m2.Length > 1)
|
||||||
|
{
|
||||||
|
Map map = new Map(m2[0].Trim(), m2[1].Trim());
|
||||||
|
maps.Add(map);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
Log.Write("Maps configuration appears to be empty - skipping...", Log.Level.All);
|
||||||
|
}
|
||||||
|
|
||||||
|
private void initMessages()
|
||||||
|
{
|
||||||
|
file messageCFG = new file("config\\messages.cfg");
|
||||||
|
String[] lines = messageCFG.readAll();
|
||||||
|
|
||||||
|
if (lines.Length < 2) //readAll returns minimum one empty string
|
||||||
|
{
|
||||||
|
Log.Write("Messages configuration appears empty - skipping...", Log.Level.All);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
int mTime = -1;
|
||||||
|
int.TryParse(lines[0], out mTime);
|
||||||
|
|
||||||
|
if (messageTime == -1)
|
||||||
|
messageTime = 60;
|
||||||
|
else
|
||||||
|
messageTime = mTime;
|
||||||
|
|
||||||
|
foreach (String l in lines)
|
||||||
|
{
|
||||||
|
if (lines[0] != l && l.Length > 1)
|
||||||
|
messages.Add(l);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private void initRules()
|
||||||
|
{
|
||||||
|
file ruleFile = new file("config\\rules.cfg");
|
||||||
|
String[] _rules = ruleFile.readAll();
|
||||||
|
if (_rules.Length > 2) // readAll returns minimum one empty string
|
||||||
|
{
|
||||||
|
foreach (String r in _rules)
|
||||||
|
{
|
||||||
|
if (r.Length > 1)
|
||||||
|
rules.Add(r);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
Log.Write("Rules configuration appears empty - skipping...", Log.Level.All);
|
||||||
|
}
|
||||||
|
|
||||||
|
private void initCommands()
|
||||||
|
{
|
||||||
|
// Something like *COMMAND* | NAME | HELP MSG | ALIAS | NEEDED PERMISSION | # OF REQUIRED ARGS | HAS TARGET |
|
||||||
|
|
||||||
|
commands = new List<Command>();
|
||||||
|
|
||||||
|
if(owner == null)
|
||||||
|
commands.Add(new Owner("owner", "claim ownership of the server", "owner", Player.Permission.User, 0, false));
|
||||||
|
|
||||||
|
commands.Add(new Kick("kick", "kick a player by name. syntax: !kick <player> <reason>.", "k", Player.Permission.Moderator, 2, true));
|
||||||
|
commands.Add(new Say("say", "broadcast message to all players. syntax: !say <message>.", "s", Player.Permission.Moderator, 1, false));
|
||||||
|
commands.Add(new TempBan("tempban", "temporarily ban a player for 1 hour. syntax: !tempban <player> <reason>.", "tb", Player.Permission.Moderator, 2, true));
|
||||||
|
commands.Add(new SBan("ban", "permanently ban a player from the server. syntax: !ban <player> <reason>", "b", Player.Permission.SeniorAdmin, 2, true));
|
||||||
|
commands.Add(new WhoAmI("whoami", "give information about yourself. syntax: !whoami.", "who", Player.Permission.User, 0, false));
|
||||||
|
commands.Add(new List("list", "list active clients syntax: !list.", "l", Player.Permission.Moderator, 0, false));
|
||||||
|
commands.Add(new Help("help", "list all available commands. syntax: !help.", "l", Player.Permission.User, 0, false));
|
||||||
|
commands.Add(new FastRestart("fastrestart", "fast restart current map. syntax: !fastrestart.", "fr", Player.Permission.Moderator, 0, false));
|
||||||
|
commands.Add(new MapRotate("maprotate", "cycle to the next map in rotation. syntax: !maprotate.", "mr", Player.Permission.Administrator, 0, false));
|
||||||
|
commands.Add(new SetLevel("setlevel", "set player to specified administration level. syntax: !setlevel <player> <level>.", "sl", Player.Permission.Owner, 2, true));
|
||||||
|
commands.Add(new Usage("usage", "get current application memory usage. syntax: !usage.", "u", Player.Permission.Moderator, 0, false));
|
||||||
|
commands.Add(new Uptime("uptime", "get current application running time. syntax: !uptime.", "up", Player.Permission.Moderator, 0, false));
|
||||||
|
commands.Add(new Warn("warn", "warn player for infringing rules syntax: !warn <player> <reason>.", "w", Player.Permission.Moderator, 2, true));
|
||||||
|
commands.Add(new WarnClear("warnclear", "remove all warning for a player syntax: !warnclear <player>.", "wc", Player.Permission.Administrator, 1, true));
|
||||||
|
commands.Add(new Unban("unban", "unban player by guid. syntax: !unban <guid>.", "ub", Player.Permission.Administrator, 1, false));
|
||||||
|
commands.Add(new Admins("admins", "list currently connected admins. syntax: !admins.", "a", Player.Permission.User, 0, false));
|
||||||
|
commands.Add(new Wisdom("wisdom", "get a random wisdom quote. syntax: !wisdom", "w", Player.Permission.Administrator, 0, false));
|
||||||
|
commands.Add(new MapCMD("map", "change to specified map. syntax: !map", "m", Player.Permission.Administrator, 1, false));
|
||||||
|
commands.Add(new Find("find", "find player in database. syntax: !find <player>", "f", Player.Permission.Administrator, 1, false));
|
||||||
|
commands.Add(new Rules("rules", "list server rules. syntax: !rules", "r", Player.Permission.User, 0, false));
|
||||||
|
|
||||||
|
/*
|
||||||
|
commands.Add(new commands { command = "stats", desc = "view your server stats.", requiredPer = 0 });
|
||||||
|
commands.Add(new commands { command = "speed", desc = "change player speed. syntax: !speed <number>", requiredPer = 3 });
|
||||||
|
commands.Add(new commands { command = "gravity", desc = "change game gravity. syntax: !gravity <number>", requiredPer = 3 });
|
||||||
|
|
||||||
|
commands.Add(new commands { command = "version", desc = "view current app version.", requiredPer = 0 });*/
|
||||||
|
}
|
||||||
|
|
||||||
|
//Objects
|
||||||
|
public Log Log;
|
||||||
|
public RCON RCON;
|
||||||
|
public Database DB;
|
||||||
|
public List<Ban> Bans;
|
||||||
|
public Player owner;
|
||||||
|
public List<Map> maps;
|
||||||
|
public List<String> rules;
|
||||||
|
public Queue<Event> events;
|
||||||
|
|
||||||
|
//Info
|
||||||
|
private String IP;
|
||||||
|
private int Port;
|
||||||
|
private String hostname;
|
||||||
|
private int clientnum;
|
||||||
|
private string rcon_pass;
|
||||||
|
private List<Player> players;
|
||||||
|
private List<Command> commands;
|
||||||
|
private List<String> messages;
|
||||||
|
private int messageTime;
|
||||||
|
private TimeSpan lastMessage;
|
||||||
|
private int nextMessage;
|
||||||
|
private int errors = 0;
|
||||||
|
|
||||||
|
//Log stuff
|
||||||
|
private String Basepath;
|
||||||
|
private String Mod;
|
||||||
|
private String logPath;
|
||||||
|
private file logFile;
|
||||||
|
}
|
||||||
|
}
|
77
Admin/Utilities.cs
Normal file
77
Admin/Utilities.cs
Normal file
@ -0,0 +1,77 @@
|
|||||||
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System.Text;
|
||||||
|
using System.Threading;
|
||||||
|
|
||||||
|
namespace IW4MAdmin
|
||||||
|
{
|
||||||
|
class Utilities
|
||||||
|
{
|
||||||
|
//Get string with specified number of spaces -- really only for visual output
|
||||||
|
public static String getSpaces(int Num)
|
||||||
|
{
|
||||||
|
String SpaceString = String.Empty;
|
||||||
|
while (Num > 0)
|
||||||
|
{
|
||||||
|
SpaceString += ' ';
|
||||||
|
Num--;
|
||||||
|
}
|
||||||
|
|
||||||
|
return SpaceString;
|
||||||
|
}
|
||||||
|
|
||||||
|
//Sleep for x amount of seconds
|
||||||
|
public static void Wait(double time)
|
||||||
|
{
|
||||||
|
Thread.Sleep((int)Math.Ceiling(time*1000));
|
||||||
|
}
|
||||||
|
|
||||||
|
//Remove words from a space delimited string
|
||||||
|
public static String removeWords(String str, int num)
|
||||||
|
{
|
||||||
|
String newStr = String.Empty;
|
||||||
|
String[] tmp = str.Split(' ');
|
||||||
|
|
||||||
|
for (int i = 0; i < tmp.Length; i++)
|
||||||
|
{
|
||||||
|
if (i >= num)
|
||||||
|
newStr += tmp[i] + ' ';
|
||||||
|
}
|
||||||
|
|
||||||
|
return newStr;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static Player.Permission matchPermission(String str)
|
||||||
|
{
|
||||||
|
String lookingFor = str.ToLower();
|
||||||
|
|
||||||
|
for (Player.Permission Perm = Player.Permission.User; Perm < Player.Permission.Owner; Perm++)
|
||||||
|
{
|
||||||
|
if (lookingFor.Contains(Perm.ToString().ToLower()))
|
||||||
|
return Perm;
|
||||||
|
}
|
||||||
|
|
||||||
|
return Player.Permission.Banned;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static String removeNastyChars(String str)
|
||||||
|
{
|
||||||
|
return str.Replace("`", "").Replace("'", "").Replace("\\", "").Replace("\"", "").Replace("^", "").Replace(""", "''");
|
||||||
|
}
|
||||||
|
|
||||||
|
public static int GetLineNumber(Exception ex)
|
||||||
|
{
|
||||||
|
var lineNumber = 0;
|
||||||
|
const string lineSearch = ":line ";
|
||||||
|
var index = ex.StackTrace.LastIndexOf(lineSearch);
|
||||||
|
if (index != -1)
|
||||||
|
{
|
||||||
|
var lineNumberText = ex.StackTrace.Substring(index + lineSearch.Length);
|
||||||
|
if (int.TryParse(lineNumberText, out lineNumber))
|
||||||
|
{
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return lineNumber;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
22
IW4M Admin.sln
Normal file
22
IW4M Admin.sln
Normal file
@ -0,0 +1,22 @@
|
|||||||
|
|
||||||
|
Microsoft Visual Studio Solution File, Format Version 12.00
|
||||||
|
# Visual Studio 2013
|
||||||
|
VisualStudioVersion = 12.0.31101.0
|
||||||
|
MinimumVisualStudioVersion = 10.0.40219.1
|
||||||
|
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "IW4M ADMIN", "Admin\IW4M ADMIN.csproj", "{DD5DCDA2-51DB-4B1A-922F-5705546E6115}"
|
||||||
|
EndProject
|
||||||
|
Global
|
||||||
|
GlobalSection(SolutionConfigurationPlatforms) = preSolution
|
||||||
|
Debug|Any CPU = Debug|Any CPU
|
||||||
|
Release|Any CPU = Release|Any CPU
|
||||||
|
EndGlobalSection
|
||||||
|
GlobalSection(ProjectConfigurationPlatforms) = postSolution
|
||||||
|
{DD5DCDA2-51DB-4B1A-922F-5705546E6115}.Debug|Any CPU.ActiveCfg = Release|Any CPU
|
||||||
|
{DD5DCDA2-51DB-4B1A-922F-5705546E6115}.Debug|Any CPU.Build.0 = Release|Any CPU
|
||||||
|
{DD5DCDA2-51DB-4B1A-922F-5705546E6115}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||||
|
{DD5DCDA2-51DB-4B1A-922F-5705546E6115}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||||
|
EndGlobalSection
|
||||||
|
GlobalSection(SolutionProperties) = preSolution
|
||||||
|
HideSolutionNode = FALSE
|
||||||
|
EndGlobalSection
|
||||||
|
EndGlobal
|
Loading…
Reference in New Issue
Block a user