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