Skip to content
Open
Show file tree
Hide file tree
Changes from 4 commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Binary file removed .vs/SmartRegions/v14/.suo
Binary file not shown.
Binary file removed .vs/Template/v14/.suo
Binary file not shown.
Binary file added Build/SmartRegions.dll
Binary file not shown.
170 changes: 116 additions & 54 deletions Plugin.cs
Original file line number Diff line number Diff line change
Expand Up @@ -13,33 +13,42 @@ namespace SmartRegions
[ApiVersion(2, 1)]
public class Plugin : TerrariaPlugin
{
public Plugin(Main game) : base(game) { }
public override Version Version => new Version("1.3.2");
public override string Name => "Smart Regions";
public override string Author => "GameRoom";
public override string Description => "Runs commands when players enter a region.";

private DBConnection DBConnection;
List<SmartRegion> regions;
PlayerData[] players = new PlayerData[255];
private static FileSystemWatcher SmartRegionFileWatcher;

private static List<SmartRegion> regions;
private static Dictionary<string, string[]> regionCommands;
private static PlayerData[] players = new PlayerData[255];

struct PlayerData
{
public Dictionary<SmartRegion, DateTime> cooldowns;
public Dictionary<string, DateTime> cooldown;
public SmartRegion regionToReplace;
public void Reset()
{
cooldowns = new Dictionary<SmartRegion, DateTime>();
cooldown = new Dictionary<string, DateTime>();
regionToReplace = null;
}
}

public Plugin(Main game) : base(game) { }
public override void Initialize()
{
Commands.ChatCommands.Add(new Command("SmartRegions.manage", regionCommand, "smartregion"));
Commands.ChatCommands.Add(new Command("SmartRegions.manage", replaceRegion, "replace"));
Commands.ChatCommands.Add(new Command("SmartRegions.manage", RegionCommand, "smartregion"));
Commands.ChatCommands.Add(new Command("SmartRegions.manage", ReplaceRegion, "replace"));

ServerApi.Hooks.NetGreetPlayer.Register(this, OnGreetPlayer);
ServerApi.Hooks.GameUpdate.Register(this, OnUpdate);

DBConnection = new DBConnection();
DBConnection.Initialize();
string folder = Path.Combine(TShock.SavePath, "SmartRegions");
if(!Directory.Exists(folder))
if (!Directory.Exists(folder))
{
Directory.CreateDirectory(folder);
}
Expand All @@ -49,90 +58,138 @@ public override void Initialize()
}
regions = DBConnection.GetRegions();

SmartRegionFileWatcher = new FileSystemWatcher(folder);
SmartRegionFileWatcher.NotifyFilter = NotifyFilters.Attributes | NotifyFilters.CreationTime |
NotifyFilters.DirectoryName | NotifyFilters.FileName |
NotifyFilters.LastAccess | NotifyFilters.LastWrite |
NotifyFilters.Security | NotifyFilters.Size;
SmartRegionFileWatcher.Changed += OnChanged;
SmartRegionFileWatcher.Created += OnCreated;
SmartRegionFileWatcher.Deleted += OnDeleted;
SmartRegionFileWatcher.Renamed += OnRenamed;
SmartRegionFileWatcher.Error += OnError;
}

protected override void Dispose(bool Disposing)
{
if(Disposing)
{
ServerApi.Hooks.NetGreetPlayer.Deregister(this, OnGreetPlayer);
ServerApi.Hooks.GameUpdate.Deregister(this, OnUpdate);
DBConnection?.Close();
SmartRegionFileWatcher.Dispose();
}
base.Dispose(Disposing);
}
public override Version Version

#region FileWatcher
private static void OnChanged(object sender, FileSystemEventArgs e)
{
if (e.ChangeType != WatcherChangeTypes.Changed)
return;
if (Path.GetExtension(e.FullPath) != ".txt")
return;
string fileName = Path.GetFileNameWithoutExtension(e.FullPath);
if (!regionCommands.ContainsKey(fileName))
regionCommands.Add(fileName, File.ReadAllLines(e.FullPath));
else
regionCommands[fileName] = File.ReadAllLines(e.FullPath);
}

private static void OnCreated(object sender, FileSystemEventArgs e)
{
get { return new Version("1.3.1"); }
if (Path.GetExtension(e.FullPath) != ".txt")
return;
string fileName = Path.GetFileNameWithoutExtension(e.FullPath);
regionCommands.Add(fileName, File.ReadAllLines(e.FullPath));
}
public override string Name

private static void OnDeleted(object sender, FileSystemEventArgs e)
{
get { return "Smart Regions"; }
if (Path.GetExtension(e.FullPath) != ".txt")
return;
string fileName = Path.GetFileNameWithoutExtension(e.FullPath);
if (regionCommands.ContainsKey(fileName))
regionCommands.Remove(fileName);
}
public override string Author

private static void OnRenamed(object sender, RenamedEventArgs e)
{
get { return "GameRoom"; }
OnDeleted(sender, new FileSystemEventArgs(WatcherChangeTypes.Deleted, e.OldFullPath, e.Name));
OnCreated(sender, new FileSystemEventArgs(WatcherChangeTypes.Created, e.FullPath, e.Name));
}
public override string Description

private static void OnError(object sender, ErrorEventArgs e) =>
PrintException(e.GetException());

private static void PrintException(Exception ex)
{
get { return "Runs commands when players enter a region."; }
if (ex != null)
{
Console.WriteLine($"Message: {ex.Message}");
Console.WriteLine("Stacktrace:");
Console.WriteLine(ex.StackTrace);
Console.WriteLine();
PrintException(ex.InnerException);
}
}
#endregion

private void OnGreetPlayer(GreetPlayerEventArgs args)
{
players[args.Who].Reset();
}

void OnUpdate(EventArgs args)
public void OnUpdate(EventArgs args)
{
foreach(TSPlayer player in TShock.Players)
if(player != null && NetMessage.buffer[player.Index].broadcast)
foreach (TSPlayer player in TShock.Players)
{
if (player != null && NetMessage.buffer[player.Index].broadcast)
{
var inRegion = TShock.Regions.InAreaRegionName((int)(player.X / 16), (int)(player.Y / 16));
var hs = new HashSet<string>(inRegion);
var inSmartRegion = regions.Where(x => hs.Contains(x.name)).OrderByDescending(x => x.region.Z);

int regionCounter = 0;
foreach(var region in inSmartRegion)
{
if((regionCounter++ == 0 || !region.region.Name.EndsWith("--"))
&& (!players[player.Index].cooldowns.ContainsKey(region)
|| DateTime.UtcNow > players[player.Index].cooldowns[region]))
List<SmartRegion> inSmartRegion = new List<SmartRegion>();
for (int i = 0; i < regions.Count; i++)
{
if (!regions[i].region.InArea(player.TileX, player.TileY)) continue;
//If region is prefixed with "--" only run it if its the top Z level,
//Hot path unsure how to optimize.
if (regions[i].region.Name.StartsWith("--", StringComparison.Ordinal))
{
string file = Path.Combine(TShock.SavePath, "SmartRegions", region.command);
if(File.Exists(file))
{
foreach(string command in File.ReadAllLines(file))
{
Commands.HandleCommand(TSPlayer.Server, replaceWithName(command, player));
}
}
else
foreach (var region in TShock.Regions.Regions)
{
Commands.HandleCommand(TSPlayer.Server, replaceWithName(region.command, player));
if (!region.InArea(player.TileX, player.TileY)) continue;
if (region.Z > regions[i].region.Z)
goto CONTINUE_MAIN_LOOP_AND_DONT_ADD;
}
if(players[player.Index].cooldowns.ContainsKey(region))
{
players[player.Index].cooldowns[region] = DateTime.UtcNow.AddSeconds(region.cooldown);
}
else
}
inSmartRegion.Add(regions[i]);
CONTINUE_MAIN_LOOP_AND_DONT_ADD: continue;
}
foreach (var region in inSmartRegion)
{
if(DateTime.UtcNow > players[player.Index].cooldown[region.name])
{
foreach (var command in regionCommands[region.name])
{
players[player.Index].cooldowns.Add(region, DateTime.UtcNow.AddSeconds(region.cooldown));
Commands.HandleCommand(TSPlayer.Server, ReplaceWithName(command, player));
}
players[player.Index].cooldown[region.name] =
DateTime.UtcNow.AddSeconds(region.cooldown);
}
}
}
}
}

string replaceWithName(string cmd, TSPlayer player)
private static string ReplaceWithName(string cmd, TSPlayer player)
{
return cmd.Replace("[PLAYERNAME]", $"\"tsn:{player.Name}\"");
}

public async void regionCommand(CommandArgs args)
public async void RegionCommand(CommandArgs args)
{
try
{
await regionCommandInner(args);
await RegionCommandInner(args);
}
catch (Exception e)
{
Expand All @@ -141,7 +198,7 @@ public async void regionCommand(CommandArgs args)
}
}

public async Task regionCommandInner(CommandArgs args)
public async Task RegionCommandInner(CommandArgs args)
{
switch(args.Parameters.ElementAtOrDefault(0))
{
Expand Down Expand Up @@ -208,6 +265,7 @@ public async Task regionCommandInner(CommandArgs args)
else
{
regions.Add(newRegion);
regionCommands.Add(newRegion.name, new string[] { newRegion.command });
await DBConnection.SaveRegion(newRegion);
args.Player.SendSuccessMessage("Smart region added!");
}
Expand Down Expand Up @@ -317,7 +375,7 @@ public async Task regionCommandInner(CommandArgs args)
}
}

void ReplaceLegacyRegionStorage()
private void ReplaceLegacyRegionStorage()
{
string path = Path.Combine(TShock.SavePath, "SmartRegions", "config.txt");
if(File.Exists(path))
Expand Down Expand Up @@ -346,7 +404,7 @@ void ReplaceLegacyRegionStorage()
}
}

public async void replaceRegion(CommandArgs args)
public async void ReplaceRegion(CommandArgs args)
{
try
{
Expand All @@ -356,9 +414,13 @@ public async void replaceRegion(CommandArgs args)
}
else
{
regions.RemoveAll(x => x.name == players[args.Player.Index].regionToReplace.name);
regions.Add(players[args.Player.Index].regionToReplace);
await DBConnection.SaveRegion(players[args.Player.Index].regionToReplace);
SmartRegion regionToReplace = players[args.Player.Index].regionToReplace;
regions.RemoveAll(x => x.name == regionToReplace.name);
regions.Add(regionToReplace);
if (regionCommands.ContainsKey(regionToReplace.name))
regionCommands.Remove(regionToReplace.name);
regionCommands.Add(regionToReplace.name, new string[] { regionToReplace.command });
await DBConnection.SaveRegion(regionToReplace);
players[args.Player.Index].regionToReplace = null;
args.Player.SendSuccessMessage("Region successfully replaced!");
}
Expand Down
4 changes: 2 additions & 2 deletions Properties/AssemblyInfo.cs
Original file line number Diff line number Diff line change
Expand Up @@ -32,5 +32,5 @@
// 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.3.1.0")]
[assembly: AssemblyFileVersion("1.3.1.0")]
[assembly: AssemblyVersion("1.3.2.0")]
[assembly: AssemblyFileVersion("1.3.2.0")]
5 changes: 4 additions & 1 deletion SmartRegions.csproj
Original file line number Diff line number Diff line change
Expand Up @@ -30,7 +30,7 @@
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release|AnyCPU' ">
<DebugType>pdbonly</DebugType>
<Optimize>true</Optimize>
<OutputPath>C:\Users\Zak\Desktop\build\</OutputPath>
<OutputPath>bin\Release\</OutputPath>
<DefineConstants>TRACE</DefineConstants>
<ErrorReport>prompt</ErrorReport>
<WarningLevel>4</WarningLevel>
Expand Down Expand Up @@ -97,6 +97,9 @@
</Target>
<Import Project="packages\EntityFramework.6.3.0\build\EntityFramework.targets" Condition="Exists('packages\EntityFramework.6.3.0\build\EntityFramework.targets')" />
<Import Project="packages\Stub.System.Data.SQLite.Core.NetFramework.1.0.113.3\build\net46\Stub.System.Data.SQLite.Core.NetFramework.targets" Condition="Exists('packages\Stub.System.Data.SQLite.Core.NetFramework.1.0.113.3\build\net46\Stub.System.Data.SQLite.Core.NetFramework.targets')" />
<PropertyGroup>
<PostBuildEvent>copy /Y "$(TargetDir)$(ProjectName).dll" "$(SolutionDir)Build\$(ProjectName).dll"</PostBuildEvent>
</PropertyGroup>
<!-- 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">
Expand Down
3 changes: 0 additions & 3 deletions SmartRegions.csproj.user

This file was deleted.

Binary file removed SmartRegions.suo
Binary file not shown.
Binary file removed bin/Debug/BCrypt.Net.dll
Binary file not shown.
Binary file removed bin/Debug/HttpServer.dll
Binary file not shown.
Binary file removed bin/Debug/Mono.Data.Sqlite.dll
Binary file not shown.
Binary file removed bin/Debug/MySql.Data.dll
Binary file not shown.
Binary file removed bin/Debug/Newtonsoft.Json.dll
Binary file not shown.
Binary file removed bin/Debug/OTAPI.dll
Binary file not shown.
Binary file removed bin/Debug/SmartRegions.dll
Binary file not shown.
Binary file removed bin/Debug/SmartRegions.pdb
Binary file not shown.
Binary file removed bin/Debug/TShockAPI.dll
Binary file not shown.
Binary file removed bin/Debug/TerrariaServer.exe
Binary file not shown.
Binary file removed obj/Debug/DesignTimeResolveAssemblyReferences.cache
Binary file not shown.
Binary file not shown.
38 changes: 0 additions & 38 deletions obj/Debug/SmartRegions.csproj.FileListAbsolute.txt

This file was deleted.

Binary file not shown.
Binary file removed obj/Debug/SmartRegions.dll
Binary file not shown.
Binary file removed obj/Debug/SmartRegions.pdb
Binary file not shown.
Empty file.
Empty file.
Empty file.
Binary file removed obj/Release/DesignTimeResolveAssemblyReferences.cache
Binary file not shown.
Binary file not shown.
6 changes: 0 additions & 6 deletions obj/Release/Template.csproj.FileListAbsolute.txt

This file was deleted.

Binary file not shown.
Binary file removed obj/Release/Template.dll
Binary file not shown.
Binary file removed obj/Release/Template.pdb
Binary file not shown.
Empty file.
Empty file.
Empty file.