Add projectile bans and the commands needed to set them up.

This commit is contained in:
Zack Piispanen 2014-04-11 13:44:47 -04:00
parent 61d05ffdc6
commit 84d8049ac6
6 changed files with 456 additions and 4 deletions

View file

@ -235,6 +235,10 @@ namespace TShockAPI
{
HelpText = "Manages item bans."
});
add(new Command(Permissions.manageprojectile, ProjectileBan, "projban")
{
HelpText = "Manages item bans."
});
add(new Command(Permissions.manageregion, Region, "region")
{
HelpText = "Manages regions."
@ -2769,9 +2773,187 @@ namespace TShockAPI
}
#endregion Item Management
#region Server Config Commands
#region Projectile Management
private static void SetSpawn(CommandArgs args)
private static void ProjectileBan(CommandArgs args)
{
if (args.Parameters.Count == 0)
{
args.Player.SendInfoMessage("Invalid syntax! Proper syntax: /projban <command> [arguments]");
args.Player.SendInfoMessage("Commands: add, allow, del, disallow, list");
args.Player.SendInfoMessage("Arguments: add <proj id>, allow <proj id> <group name>");
args.Player.SendInfoMessage("Arguments: del <proj id>, disallow <proj id> <group name>, list [page]");
return;
}
switch (args.Parameters[0].ToLower())
{
case "add":
#region Add projectile
{
if (args.Parameters.Count != 2)
{
args.Player.SendErrorMessage("Invalid syntax! Proper syntax: /projban add <proj id>");
return;
}
short id;
if (Int16.TryParse(args.Parameters[1], out id))
{
TShock.ProjectileBans.AddNewBan(id);
args.Player.SendSuccessMessage("Banned Projectile: " + id + ".");
return;
}
else
{
args.Player.SendErrorMessage("Invalid syntax! Projectile Id must be a number.");
return;
}
}
#endregion
return;
case "allow":
#region Allow group to projectile
{
if (args.Parameters.Count != 3)
{
args.Player.SendErrorMessage("Invalid syntax! Proper syntax: /projban allow <id> <group name>");
return;
}
short id;
if (Int16.TryParse(args.Parameters[1], out id))
{
if (!TShock.Groups.GroupExists(args.Parameters[2]))
{
args.Player.SendErrorMessage("Invalid group.");
return;
}
ProjectileBan ban = TShock.ProjectileBans.GetBanById(id);
if (ban == null)
{
args.Player.SendErrorMessage("Projectile " + id + " is not banned.");
return;
}
if (!ban.AllowedGroups.Contains(args.Parameters[2]))
{
TShock.ProjectileBans.AllowGroup(id, args.Parameters[2]);
args.Player.SendSuccessMessage(String.Format("{0} has been allowed to use projectile {1}.", args.Parameters[2], id));
return;
}
else
{
args.Player.SendWarningMessage(String.Format("{0} is already allowed to use projectile {1}.", args.Parameters[2], id));
return;
}
}
else
{
args.Player.SendErrorMessage("Invalid syntax! Projectile Id must be a number.");
return;
}
}
#endregion
case "del":
#region Delete item
{
if (args.Parameters.Count != 2)
{
args.Player.SendErrorMessage("Invalid syntax! Proper syntax: /projban del <id>");
return;
}
short id;
if (Int16.TryParse(args.Parameters[1], out id))
{
TShock.ProjectileBans.RemoveBan(id);
args.Player.SendSuccessMessage("Unbanned Projectile: " + id + ".");
return;
}
else
{
args.Player.SendErrorMessage("Invalid syntax! Projectile Id must be a number.");
return;
}
}
#endregion
return;
case "disallow":
#region Allow group to item
{
if (args.Parameters.Count != 3)
{
args.Player.SendErrorMessage("Invalid syntax! Proper syntax: /projban disallow <id> <group name>");
return;
}
short id;
if (Int16.TryParse(args.Parameters[1], out id))
{
if (!TShock.Groups.GroupExists(args.Parameters[2]))
{
args.Player.SendErrorMessage("Invalid group.");
return;
}
ProjectileBan ban = TShock.ProjectileBans.GetBanById(id);
if (ban == null)
{
args.Player.SendErrorMessage("Projectile " + id + " is not banned.");
return;
}
if (ban.AllowedGroups.Contains(args.Parameters[2]))
{
TShock.ProjectileBans.RemoveGroup(id, args.Parameters[2]);
args.Player.SendSuccessMessage(String.Format("{0} has been disallowed from using projectile {1}.", args.Parameters[2], id));
return;
}
else
{
args.Player.SendWarningMessage(String.Format("{0} is already prevented from using projectile {1}.", args.Parameters[2], id));
return;
}
}
else
{
args.Player.SendErrorMessage("Invalid syntax! Projectile Id must be a number.");
return;
}
}
#endregion
return;
case "help":
args.Player.SendInfoMessage("Syntax: /projban <command> [arguments]");
args.Player.SendInfoMessage("Commands: add, allow, del, disallow, list");
args.Player.SendInfoMessage("Arguments: add <id>, allow <id> <group name>");
args.Player.SendInfoMessage("Arguments: del <id>, disallow <id> <group name>, list [page]");
return;
case "list":
#region List items
int pageNumber;
if (!PaginationTools.TryParsePageNumber(args.Parameters, 1, args.Player, out pageNumber))
return;
IEnumerable<Int16> projectileIds = from projectileBan in TShock.ProjectileBans.ProjectileBans
select projectileBan.ID;
PaginationTools.SendPage(args.Player, pageNumber, PaginationTools.BuildLinesFromTerms(projectileIds),
new PaginationTools.Settings
{
HeaderFormat = "Projectile bans ({0}/{1}):",
FooterFormat = "Type /Projectile list {0} for more.",
NothingToDisplayString = "There are currently no banned projectiles."
});
#endregion
return;
}
}
#endregion Projectile Management
#region Server Config Commands
private static void SetSpawn(CommandArgs args)
{
Main.spawnTileX = args.Player.TileX + 1;
Main.spawnTileY = args.Player.TileY + 3;

View file

@ -0,0 +1,253 @@
/*
TShock, a server mod for Terraria
Copyright (C) 2011-2013 Nyx Studios (fka. The TShock Team)
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
using System;
using System.Collections.Generic;
using System.Data;
using System.Linq;
using MySql.Data.MySqlClient;
namespace TShockAPI.DB
{
public class ProjectileManagager
{
private IDbConnection database;
public List<ProjectileBan> ProjectileBans = new List<ProjectileBan>();
public ProjectileManagager(IDbConnection db)
{
database = db;
var table = new SqlTable("ProjectileBans",
new SqlColumn("ProjectileID", MySqlDbType.Int32) { Primary = true },
new SqlColumn("AllowedGroups", MySqlDbType.Text)
);
var creator = new SqlTableCreator(db,
db.GetSqlType() == SqlType.Sqlite
? (IQueryBuilder)new SqliteQueryCreator()
: new MysqlQueryCreator());
creator.EnsureExists(table);
UpdateBans();
}
public void UpdateBans()
{
ProjectileBans.Clear();
using (var reader = database.QueryReader("SELECT * FROM ProjectileBans"))
{
while (reader != null && reader.Read())
{
ProjectileBan ban = new ProjectileBan((short)reader.Get<Int32>("ProjectileID"));
ban.SetAllowedGroups(reader.Get<string>("AllowedGroups"));
ProjectileBans.Add(ban);
}
}
}
public void AddNewBan(short id = 0)
{
try
{
database.Query("INSERT INTO ProjectileBans (ProjectileID, AllowedGroups) VALUES (@0, @1);",
id, "");
if (!ProjectileIsBanned(id, null))
ProjectileBans.Add(new ProjectileBan(id));
}
catch (Exception ex)
{
Log.Error(ex.ToString());
}
}
public void RemoveBan(short id)
{
if (!ProjectileIsBanned(id, null))
return;
try
{
database.Query("DELETE FROM ProjectileBans WHERE ProjectileId=@0;", id);
ProjectileBans.Remove(new ProjectileBan(id));
}
catch (Exception ex)
{
Log.Error(ex.ToString());
}
}
public bool ProjectileIsBanned(short id)
{
if (ProjectileBans.Contains(new ProjectileBan(id)))
{
return true;
}
return false;
}
public bool ProjectileIsBanned(short id, TSPlayer ply)
{
if (ProjectileBans.Contains(new ProjectileBan(id)))
{
ProjectileBan b = GetBanById(id);
return !b.HasPermissionToCreateProjectile(ply);
}
return false;
}
public bool AllowGroup(short id, string name)
{
string groupsNew = "";
ProjectileBan b = GetBanById(id);
if (b != null)
{
try
{
groupsNew = String.Join(",", b.AllowedGroups);
if (groupsNew.Length > 0)
groupsNew += ",";
groupsNew += name;
b.SetAllowedGroups(groupsNew);
int q = database.Query("UPDATE ProjectileBans SET AllowedGroups=@0 WHERE ProjectileId=@1", groupsNew,
id);
return q > 0;
}
catch (Exception ex)
{
Log.Error(ex.ToString());
}
}
return false;
}
public bool RemoveGroup(short id, string group)
{
ProjectileBan b = GetBanById(id);
if (b != null)
{
try
{
b.RemoveGroup(group);
string groups = string.Join(",", b.AllowedGroups);
int q = database.Query("UPDATE ProjectileBans SET AllowedGroups=@0 WHERE ProjectileId=@1", groups,
id);
if (q > 0)
return true;
}
catch (Exception ex)
{
Log.Error(ex.ToString());
}
}
return false;
}
public ProjectileBan GetBanById(short id)
{
foreach (ProjectileBan b in ProjectileBans)
{
if (b.ID == id)
{
return b;
}
}
return null;
}
}
public class ProjectileBan : IEquatable<ProjectileBan>
{
public short ID { get; set; }
public List<string> AllowedGroups { get; set; }
public ProjectileBan(short id)
: this()
{
ID = id;
AllowedGroups = new List<string>();
}
public ProjectileBan()
{
ID = 0;
AllowedGroups = new List<string>();
}
public bool Equals(ProjectileBan other)
{
return ID == other.ID;
}
public bool HasPermissionToCreateProjectile(TSPlayer ply)
{
if (ply == null)
return false;
if (ply.Group.HasPermission(Permissions.canusebannedprojectiles))
return true;
var cur = ply.Group;
var traversed = new List<Group>();
while (cur != null)
{
if (AllowedGroups.Contains(cur.Name))
{
return true;
}
if (traversed.Contains(cur))
{
throw new InvalidOperationException("Infinite group parenting ({0})".SFormat(cur.Name));
}
traversed.Add(cur);
cur = cur.Parent;
}
return false;
// could add in the other permissions in this class instead of a giant if switch.
}
public void SetAllowedGroups(String groups)
{
// prevent null pointer exceptions
if (!string.IsNullOrEmpty(groups))
{
List<String> groupArr = groups.Split(',').ToList();
for (int i = 0; i < groupArr.Count; i++)
{
groupArr[i] = groupArr[i].Trim();
//Console.WriteLine(groupArr[i]);
}
AllowedGroups = groupArr;
}
}
public bool RemoveGroup(string groupName)
{
return AllowedGroups.Remove(groupName);
}
public override string ToString()
{
return ID + (AllowedGroups.Count > 0 ? " (" + String.Join(",", AllowedGroups) + ")" : "");
}
}
}

View file

@ -2393,9 +2393,17 @@ namespace TShockAPI
if (index > Main.maxProjectiles || index < 0)
{
return false;
args.Player.RemoveProjectile(ident, owner);
return true;
}
if (TShock.ProjectileBans.ProjectileIsBanned(type, args.Player))
{
args.Player.Disable("Player does not have permission to create that projectile.", true);
args.Player.SendErrorMessage("You do not have permission to create that projectile.");
args.Player.RemoveProjectile(ident, owner);
return false;
}
// Server now checks owner + ident, if owner is different, server will create new projectile.
/*if (args.Player.Index != owner)
{

View file

@ -64,6 +64,9 @@ namespace TShockAPI
[Description("User can manage item bans.")]
public static readonly string manageitem = "tshock.admin.itemban";
[Description("User can manage projectile bans.")]
public static readonly string manageprojectile = "tshock.admin.projectileban";
[Description("User can manage groups.")]
public static readonly string managegroup = "tshock.admin.group";
@ -322,6 +325,9 @@ namespace TShockAPI
[Description("Player can chat")]
public static readonly string canchat = "tshock.canchat";
[Description("Player can use banned projectiles.")]
public static readonly string canusebannedprojectiles = "tshock.projectiles.usebanned";
/// <summary>
/// Lists all commands associated with a given permission
/// </summary>

View file

@ -62,6 +62,7 @@ namespace TShockAPI
public static GroupManager Groups;
public static UserManager Users;
public static ItemManager Itembans;
public static ProjectileManagager ProjectileBans;
public static RememberedPosManager RememberedPos;
public static CharacterManager CharacterDB;
public static ConfigFile Config { get; set; }
@ -223,6 +224,7 @@ namespace TShockAPI
Users = new UserManager(DB);
Groups = new GroupManager(DB);
Itembans = new ItemManager(DB);
ProjectileBans = new ProjectileManagager(DB);
RememberedPos = new RememberedPosManager(DB);
CharacterDB = new CharacterManager(DB);
RestApi = new SecureRest(Netplay.serverListenIP, Config.RestApiPort);

View file

@ -72,6 +72,7 @@
</ItemGroup>
<ItemGroup>
<Compile Include="BackupManager.cs" />
<Compile Include="DB\ProjectileManager.cs" />
<Compile Include="DB\RegionManager.cs" />
<Compile Include="Hooks\GeneralHooks.cs" />
<Compile Include="Hooks\PlayerHooks.cs" />
@ -179,7 +180,7 @@
</PropertyGroup>
<ProjectExtensions>
<VisualStudio>
<UserProperties BuildVersion_IncrementBeforeBuild="False" BuildVersion_StartDate="2011/6/17" BuildVersion_BuildVersioningStyle="None.None.None.MonthAndDayStamp" BuildVersion_BuildAction="Both" BuildVersion_UpdateFileVersion="True" BuildVersion_UpdateAssemblyVersion="True" />
<UserProperties BuildVersion_UpdateAssemblyVersion="True" BuildVersion_UpdateFileVersion="True" BuildVersion_BuildAction="Both" BuildVersion_BuildVersioningStyle="None.None.None.MonthAndDayStamp" BuildVersion_StartDate="2011/6/17" BuildVersion_IncrementBeforeBuild="False" />
</VisualStudio>
</ProjectExtensions>
<!-- To modify your build process, add your task inside one of the targets below and uncomment it.