diff --git a/Deltinteger/Deltinteger/Lobby/Extensions.cs b/Deltinteger/Deltinteger/Lobby/Extensions.cs new file mode 100644 index 000000000..29d76995c --- /dev/null +++ b/Deltinteger/Deltinteger/Lobby/Extensions.cs @@ -0,0 +1,43 @@ +namespace Deltin.Deltinteger.Lobby +{ + class ExtensionInfo + { + public static readonly ExtensionInfo[] Extensions = new ExtensionInfo[] { + new ExtensionInfo("Beam Effects", 2), + new ExtensionInfo("Beam Sounds", 1), + new ExtensionInfo("Buff Status Effects", 2), + new ExtensionInfo("Debuff Status Effects", 2), + new ExtensionInfo("Buff and Debuff Sounds", 2), + new ExtensionInfo("Energy Explosion Effects", 4), + new ExtensionInfo("Kinetic Explosion Effects", 4), + new ExtensionInfo("Explosion Sounds", 2), + new ExtensionInfo("Play More Effects", 1), + new ExtensionInfo("Spawn More Dummy Bots", 2) + }; + + public string Name { get; } + public int Cost { get; } + public ExtensionInfo(string name, int cost) + { + Name = name; + Cost = cost; + } + + public static RootSchema GetSchema() + { + RootSchema schema = new RootSchema().InitProperties(); + schema.AdditionalProperties = false; + + foreach (var extension in ExtensionInfo.Extensions) + { + schema.Properties.Add(extension.Name, new RootSchema() { + Type = SchemaObjectType.Boolean, + Default = false, + Description = "The '" + extension.Name + "' extension costs " + extension.Cost + " extension points." + }); + } + + return schema; + } + } +} \ No newline at end of file diff --git a/Deltinteger/Deltinteger/Lobby/Ruleset.cs b/Deltinteger/Deltinteger/Lobby/Ruleset.cs index 82a59ac09..7983dd936 100644 --- a/Deltinteger/Deltinteger/Lobby/Ruleset.cs +++ b/Deltinteger/Deltinteger/Lobby/Ruleset.cs @@ -34,6 +34,7 @@ public class Ruleset public HeroesRoot Heroes { get; set; } public string Description { get; set; } public WorkshopValuePair Workshop { get; set; } + public WorkshopValuePair Extensions { get; set; } public void ToWorkshop(WorkshopBuilder builder) { @@ -82,6 +83,21 @@ public void ToWorkshop(WorkshopBuilder builder) builder.AppendLine("}"); } + // Get extensions. + if (Extensions != null) + { + builder.AppendKeywordLine("extensions"); + builder.AppendLine("{"); + builder.Indent(); + + foreach (var ext in Extensions) + if ((bool)ext.Value) + builder.AppendKeywordLine(ext.Key); + + builder.Outdent(); + builder.AppendLine("}"); + } + builder.Outdent(); builder.AppendLine("}"); } @@ -138,6 +154,9 @@ public static void GenerateSchema() // Add 'Workshop' property. root.Properties.Add("Workshop", GetCustomSettingsSchema(generate)); + // Add 'Extensions' property. + root.Properties.Add("Extensions", ExtensionInfo.GetSchema()); + // Get the result. string result = JsonConvert.SerializeObject(root, new JsonSerializerSettings() { @@ -277,7 +296,7 @@ public static bool Validate(JObject jobject, FileDiagnostics diagnostics, DocRan // Check for invalid properties. foreach (JProperty setting in jobject.Properties()) - if (!new string[] { "Lobby", "Modes", "Heroes", "Description", "Workshop" }.Contains(setting.Name)) + if (!new string[] { "Lobby", "Modes", "Heroes", "Description", "Workshop", "Extensions" }.Contains(setting.Name)) validation.InvalidSetting(setting.Name); // Check lobby settings. @@ -295,6 +314,19 @@ public static bool Validate(JObject jobject, FileDiagnostics diagnostics, DocRan // Check description. if (jobject.TryGetValue("Description", out JToken description) && description.Type != JTokenType.String) validation.IncorrectType("Description", "string"); + + // Check extensions. + if (jobject.TryGetValue("Extensions", out JToken extensionsToken) + // Make sure the extension group's value is an object. + && validation.TryGetObject("Extensions", extensionsToken, out var extensions)) + // Check each extension. + foreach (var prop in extensions) + // The extension name does not exist. + if (!ExtensionInfo.Extensions.Any(e => e.Name == prop.Key)) + validation.Error($"The extension '{prop.Key}' does not exist."); + // The extension value is not a boolean. + else if (prop.Value.Type != JTokenType.Boolean) + validation.Error($"The value of the extension '{prop.Key}' must be a boolean."); validation.Dump(diagnostics, range); return !validation.HasErrors(); @@ -528,19 +560,20 @@ public class SettingValidation public SettingValidation() { } - public void Error(string error) - { - _errors.Add(error); - } - - public void InvalidSetting(string propertyName) + public void Error(string error) => _errors.Add(error); + public void InvalidSetting(string propertyName) => _errors.Add($"The setting '{propertyName}' is not valid."); + public void IncorrectType(string propertyName, string expectedType) => _errors.Add($"The setting '{propertyName}' requires a value of type " + expectedType + "."); + public bool TryGetObject(string propertyName, JToken token, out JObject obj) { - _errors.Add($"The setting '{propertyName}' is not valid."); - } + if (token is JObject tokenAsObject) + { + obj = tokenAsObject; + return true; + } - public void IncorrectType(string propertyName, string expectedType) - { - _errors.Add($"The setting '{propertyName}' requires a value of type " + expectedType + "."); + Error($"The setting '{propertyName}' must be an object."); + obj = null; + return false; } public bool HasErrors() => _errors.Count > 0; diff --git a/overwatch-script-to-workshop/json-schemas/LobbySettingValidation.json b/overwatch-script-to-workshop/json-schemas/LobbySettingValidation.json index 77315d134..fbeb891db 100644 --- a/overwatch-script-to-workshop/json-schemas/LobbySettingValidation.json +++ b/overwatch-script-to-workshop/json-schemas/LobbySettingValidation.json @@ -867,7 +867,7 @@ "Projectile Speed": { "default": 100.0, "type": "number", - "maximum": 300.0 + "maximum": 500.0 }, "Projectile Gravity": { "default": 100.0, @@ -6361,6 +6361,61 @@ "properties": {}, "type": "object", "additionalProperties": true + }, + "Extensions": { + "properties": { + "Beam Effects": { + "description": "The 'Beam Effects' extension costs 2 extension points.", + "default": false, + "type": "boolean" + }, + "Beam Sounds": { + "description": "The 'Beam Sounds' extension costs 1 extension points.", + "default": false, + "type": "boolean" + }, + "Buff Status Effects": { + "description": "The 'Buff Status Effects' extension costs 2 extension points.", + "default": false, + "type": "boolean" + }, + "Debuff Status Effects": { + "description": "The 'Debuff Status Effects' extension costs 2 extension points.", + "default": false, + "type": "boolean" + }, + "Buff and Debuff Sounds": { + "description": "The 'Buff and Debuff Sounds' extension costs 2 extension points.", + "default": false, + "type": "boolean" + }, + "Energy Explosion Effects": { + "description": "The 'Energy Explosion Effects' extension costs 4 extension points.", + "default": false, + "type": "boolean" + }, + "Kinetic Explosion Effects": { + "description": "The 'Kinetic Explosion Effects' extension costs 4 extension points.", + "default": false, + "type": "boolean" + }, + "Explosion Sounds": { + "description": "The 'Explosion Sounds' extension costs 2 extension points.", + "default": false, + "type": "boolean" + }, + "Play More Effects": { + "description": "The 'Play More Effects' extension costs 1 extension points.", + "default": false, + "type": "boolean" + }, + "Spawn More Dummy Bots": { + "description": "The 'Spawn More Dummy Bots' extension costs 2 extension points.", + "default": false, + "type": "boolean" + } + }, + "additionalProperties": false } }, "type": "object",