Skip to content

Commit

Permalink
Refactored plugin configuration
Browse files Browse the repository at this point in the history
Configuration loading is now separated from the actual configuration
data, which should make it easier to eventually reuse.

Also cleaned up some formatting in EntityAttachment.cs.
  • Loading branch information
brianide committed Jun 19, 2020
1 parent c7e593c commit 4e68043
Show file tree
Hide file tree
Showing 5 changed files with 80 additions and 46 deletions.
1 change: 1 addition & 0 deletions BloodTithe/BloodTithe.csproj
Original file line number Diff line number Diff line change
Expand Up @@ -56,6 +56,7 @@
<Compile Include="BloodTitheConfig.cs" />
<Compile Include="BloodTithePlugin.cs" />
<Compile Include="EntityAttachment.cs" />
<Compile Include="PluginConfiguration.cs" />
<Compile Include="Properties\AssemblyInfo.cs" />
<Compile Include="Util.cs" />
</ItemGroup>
Expand Down
40 changes: 3 additions & 37 deletions BloodTithe/BloodTitheConfig.cs
Original file line number Diff line number Diff line change
@@ -1,59 +1,25 @@
using Newtonsoft.Json;
using System.ComponentModel;
using System.ComponentModel;
using System.IO;
using Terraria.ID;
using TShockAPI;

namespace BloodTithe
{
class BloodTitheConfig
struct BloodTitheConfig : IPluginConfiguration
{
private static readonly string FilePath = Path.Combine(TShock.SavePath, "BloodTithe.json");
private static readonly BloodTitheConfig Default = JsonConvert.DeserializeObject<BloodTitheConfig>("{}");
public string FilePath => Path.Combine(TShock.SavePath, "BloodTithe.json");

[JsonProperty(DefaultValueHandling = DefaultValueHandling.Populate)]
[DefaultValue(ItemID.LifeCrystal)]
public int Item { get; private set; }

[JsonProperty(DefaultValueHandling = DefaultValueHandling.Populate)]
[DefaultValue(3)]
public int ItemsRequired { get; private set; }

[JsonProperty(DefaultValueHandling = DefaultValueHandling.Populate)]
[DefaultValue(false)]
public bool PreventCorruption { get; private set; }

[JsonProperty(DefaultValueHandling = DefaultValueHandling.Populate)]
[DefaultValue(true)]
public bool SpawnWarpFairy { get; private set; }

public static BloodTitheConfig Load()
{
TShock.Log.Info("Loading configuration from {0}", FilePath);

BloodTitheConfig config;

if (!File.Exists(FilePath))
{
config = Default;
}
else
{
try
{
config = JsonConvert.DeserializeObject<BloodTitheConfig>(File.ReadAllText(FilePath));
}
catch (JsonReaderException e)
{
TShock.Log.Error("Error loading {0}: {1}", FilePath, e.Message);
config = Default;
}
}

File.WriteAllText(FilePath, JsonConvert.SerializeObject(config, Formatting.Indented));
return config;
}

public override string ToString() => JsonConvert.SerializeObject(this);
}
}
4 changes: 2 additions & 2 deletions BloodTithe/BloodTithePlugin.cs
Original file line number Diff line number Diff line change
Expand Up @@ -28,14 +28,14 @@ public BloodTithePlugin(Main game) : base(game) { }

public override void Initialize()
{
Config = BloodTitheConfig.Load();
Config = PluginConfiguration.Load<BloodTitheConfig>();

RegisterCorruptionTracking();
RegisterAIHandling();

// Add debug commands
Util.RegisterChatCommands("bloodtithe.debug",
("bt_printconfig", args => args.Player.SendInfoMessage(Config.ToString())),
("bt_printconfig", args => args.Player.SendInfoMessage(PluginConfiguration.Stringify(Config))),
("bt_pending", args => PendingAltars.ForEach(kv => args.Player.SendInfoMessage("{0},{1}: {2}", kv.Key.x, kv.Key.y, kv.Value))),
("bt_needammo", args => Item.NewItem(args.Player.TPlayer.Top, Vector2.Zero, Config.Item, Stack: 30, noGrabDelay: true)));
}
Expand Down
14 changes: 7 additions & 7 deletions BloodTithe/EntityAttachment.cs
Original file line number Diff line number Diff line change
Expand Up @@ -7,17 +7,17 @@
namespace BloodTithe
{
abstract class EntityAttachment
{
{
private int timer;
public bool Update() => OnUpdate(timer++);
public bool Update() => OnUpdate(timer++);
protected abstract bool OnUpdate(int tick);
}

class FairyExtendedIdle : EntityAttachment
{
class FairyExtendedIdle : EntityAttachment
{
protected NPC Fairy { get; }
public Vector2 HomePoint { get; }
public Action<TSPlayer> OnCollision { get; }
public Action<TSPlayer> OnCollision { get; }

public FairyExtendedIdle(NPC entity, Vector2 homePoint, Action<TSPlayer> onCollision)
{
Expand All @@ -27,7 +27,7 @@ public FairyExtendedIdle(NPC entity, Vector2 homePoint, Action<TSPlayer> onColli
}

protected override bool OnUpdate(int tick)
{
{
// Detach special handling if the fairy's five-minute timer is up
if (Fairy.ai[2] == 7)
return false;
Expand Down Expand Up @@ -61,5 +61,5 @@ protected override bool OnUpdate(int tick)

return true;
}
}
}
}
67 changes: 67 additions & 0 deletions BloodTithe/PluginConfiguration.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,67 @@
using Newtonsoft.Json;
using Newtonsoft.Json.Serialization;
using System;
using System.IO;
using System.Reflection;
using TShockAPI;

namespace BloodTithe
{
interface IPluginConfiguration {
[JsonIgnore]
string FilePath { get; }
}

class DefaultValueContractResolver : DefaultContractResolver
{
protected override JsonProperty CreateProperty(MemberInfo member, MemberSerialization memberSerialization)
{
var prop = base.CreateProperty(member, memberSerialization);
bool tagged = member.GetCustomAttribute<System.ComponentModel.DefaultValueAttribute>() != null && (member as PropertyInfo)?.SetMethod != null;
prop.Writable = tagged;
prop.ShouldSerialize = _ => tagged;
prop.ShouldDeserialize = _ => tagged;
return prop;
}
}

static class PluginConfiguration
{
private readonly static JsonSerializerSettings settings = new JsonSerializerSettings() {
DefaultValueHandling = DefaultValueHandling.Populate,
ContractResolver = new DefaultValueContractResolver()
};

public static T LoadDefault<T>() => JsonConvert.DeserializeObject<T>("{}", settings);

public static T Load<T>() where T : IPluginConfiguration
{
string filePath = default(T).FilePath;
TShock.Log.Info("Loading configuration from {0}", filePath);

T config;
if (!File.Exists(filePath))
{
config = LoadDefault<T>();
}
else
{
try
{
config = JsonConvert.DeserializeObject<T>(File.ReadAllText(filePath), settings);
}
catch (JsonReaderException e)
{
TShock.Log.Error("Error loading {0}: {1}", filePath, e.Message);
config = LoadDefault<T>();
}
}

File.WriteAllText(filePath, JsonConvert.SerializeObject(config, Formatting.Indented));
return config;
}

public static string Stringify<T>(T config) where T : IPluginConfiguration => JsonConvert.SerializeObject(config);
}

}

0 comments on commit 4e68043

Please sign in to comment.