diff --git a/SequentialScript.Test/CustomData/Resources.Designer.cs b/SequentialScript.Test/CustomData/Resources.Designer.cs
index 53b2844..3045bbe 100644
--- a/SequentialScript.Test/CustomData/Resources.Designer.cs
+++ b/SequentialScript.Test/CustomData/Resources.Designer.cs
@@ -1,214 +1,237 @@
-//------------------------------------------------------------------------------
-//
-// This code was generated by a tool.
-// Runtime Version:4.0.30319.42000
-//
-// Changes to this file may cause incorrect behavior and will be lost if
-// the code is regenerated.
-//
-//------------------------------------------------------------------------------
-
-namespace SequentialScript.Test.CustomData {
- using System;
-
-
- ///
- /// A strongly-typed resource class, for looking up localized strings, etc.
- ///
- // This class was auto-generated by the StronglyTypedResourceBuilder
- // class via a tool like ResGen or Visual Studio.
- // To add or remove a member, edit your .ResX file then rerun ResGen
- // with the /str option, or rebuild your VS project.
- [global::System.CodeDom.Compiler.GeneratedCodeAttribute("System.Resources.Tools.StronglyTypedResourceBuilder", "17.0.0.0")]
- [global::System.Diagnostics.DebuggerNonUserCodeAttribute()]
- [global::System.Runtime.CompilerServices.CompilerGeneratedAttribute()]
- internal class Resources {
-
- private static global::System.Resources.ResourceManager resourceMan;
-
- private static global::System.Globalization.CultureInfo resourceCulture;
-
- [global::System.Diagnostics.CodeAnalysis.SuppressMessageAttribute("Microsoft.Performance", "CA1811:AvoidUncalledPrivateCode")]
- internal Resources() {
- }
-
- ///
- /// Returns the cached ResourceManager instance used by this class.
- ///
- [global::System.ComponentModel.EditorBrowsableAttribute(global::System.ComponentModel.EditorBrowsableState.Advanced)]
- internal static global::System.Resources.ResourceManager ResourceManager {
- get {
- if (object.ReferenceEquals(resourceMan, null)) {
- global::System.Resources.ResourceManager temp = new global::System.Resources.ResourceManager("SequentialScript.Test.CustomData.Resources", typeof(Resources).Assembly);
- resourceMan = temp;
- }
- return resourceMan;
- }
- }
-
- ///
- /// Overrides the current thread's CurrentUICulture property for all
- /// resource lookups using this strongly typed resource class.
- ///
- [global::System.ComponentModel.EditorBrowsableAttribute(global::System.ComponentModel.EditorBrowsableState.Advanced)]
- internal static global::System.Globalization.CultureInfo Culture {
- get {
- return resourceCulture;
- }
- set {
- resourceCulture = value;
- }
- }
-
- ///
- /// Looks up a localized string similar to [OPEN]
- ///run
- /// Block -> Some Action /NoCheck /Key1:Value /Key2:"Value with spaces" /Key3:"Value with special characters :/"
- ///as @action.
- ///
- internal static string TestArguments {
- get {
- return ResourceManager.GetString("TestArguments", resourceCulture);
- }
- }
-
- ///
- /// Looks up a localized string similar to [OPEN]
- ///
- ///// Comment over block
- ///run // Comment in block
- ///
- /// // Comment over instruction
- /// Door -> Open // Comment in instruction
- ///
- ///as @open_door // Comment at the end of the block.
- ///
- internal static string TestComments {
- get {
- return ResourceManager.GetString("TestComments", resourceCulture);
- }
- }
-
- ///
- /// Looks up a localized string similar to [OPEN]
- ///run
- /// Door Light -> Enable
- ///as @open_door_1
- ///
- ///when @open_door_1
- ///run
- /// Door -> Open
- ///as @open_door_2
- ///
- ///when @open_door_1, @open_door_2
- ///run
- /// Door Light -> Disable
- ///as @open_door_3.
- ///
- internal static string TestDependences {
- get {
- return ResourceManager.GetString("TestDependences", resourceCulture);
- }
- }
-
- ///
- /// Looks up a localized string similar to [OPEN]
- ///run
- /// Door Light -> Enable
- ///as @open_door_1
- ///
- ///when @open_door_1, @open_door_3
- ///run
- /// Door -> Open
- ///as @open_door_2
- ///
- ///when @open_door_1, @open_door_2
- ///run
- /// Door Light -> Disable
- ///as @open_door_3.
- ///
- internal static string TestDependences_Recursivity {
- get {
- return ResourceManager.GetString("TestDependences_Recursivity", resourceCulture);
- }
- }
-
- ///
- /// Looks up a localized string similar to [HYDROGEN_STOCKPILE]
- ///run
- /// Hydrogen Example (Thruster) -> Disable
- ///as @thrusters_disabled
- ///
- ///run
- /// Hydrogen Example (Status LCD) -> Set /Index:-1 /Background:YELLOW /Text:Connecting...
- /// Hydrogen Example (Piston) -> Extend
- ///as piston_extended
- ///
- ///when @piston_extended
- ///run
- /// Hydrogen Example (Connector) -> Connect
- ///as @connector_locked
- ///
- ///when @connector_locked
- ///run
- /// Hydrogen Example (Status LCD) -> Set /Index:-1 /Background:BLUE /Text:Recharging...
- /// Hydrogen Example (Tank) -> Stockpile
- ///as @tank_full
- ///
- /// [rest of string was truncated]";.
- ///
- internal static string TestHydrogen {
- get {
- return ResourceManager.GetString("TestHydrogen", resourceCulture);
- }
- }
-
- ///
- /// Looks up a localized string similar to [OPEN]
- ///run
- /// Door -> Open
- ///as @open_door.
- ///
- internal static string TestSimple {
- get {
- return ResourceManager.GetString("TestSimple", resourceCulture);
- }
- }
-
- ///
- /// Looks up a localized string similar to .
- ///
- internal static string TestSyntaxAliasDuplicated {
- get {
- return ResourceManager.GetString("TestSyntaxAliasDuplicated", resourceCulture);
- }
- }
-
- ///
- /// Looks up a localized string similar to [TEST]
- ///run
- /// Air Vent -> Depressurize
- ///as @room_depressurized
- ///
- ///when @room_depressurized
- ///run
- /// Door 1 -> Enable
- /// Door 1 -> Open
- ///as door_opened.
- ///
- internal static string TestSyntaxAliasInvalid {
- get {
- return ResourceManager.GetString("TestSyntaxAliasInvalid", resourceCulture);
- }
- }
-
- ///
- /// Looks up a localized string similar to .
- ///
- internal static string TestSyntaxInstructionInvalid {
- get {
- return ResourceManager.GetString("TestSyntaxInstructionInvalid", resourceCulture);
- }
- }
- }
-}
+//------------------------------------------------------------------------------
+//
+// This code was generated by a tool.
+// Runtime Version:4.0.30319.42000
+//
+// Changes to this file may cause incorrect behavior and will be lost if
+// the code is regenerated.
+//
+//------------------------------------------------------------------------------
+
+namespace SequentialScript.Test.CustomData {
+ using System;
+
+
+ ///
+ /// A strongly-typed resource class, for looking up localized strings, etc.
+ ///
+ // This class was auto-generated by the StronglyTypedResourceBuilder
+ // class via a tool like ResGen or Visual Studio.
+ // To add or remove a member, edit your .ResX file then rerun ResGen
+ // with the /str option, or rebuild your VS project.
+ [global::System.CodeDom.Compiler.GeneratedCodeAttribute("System.Resources.Tools.StronglyTypedResourceBuilder", "17.0.0.0")]
+ [global::System.Diagnostics.DebuggerNonUserCodeAttribute()]
+ [global::System.Runtime.CompilerServices.CompilerGeneratedAttribute()]
+ internal class Resources {
+
+ private static global::System.Resources.ResourceManager resourceMan;
+
+ private static global::System.Globalization.CultureInfo resourceCulture;
+
+ [global::System.Diagnostics.CodeAnalysis.SuppressMessageAttribute("Microsoft.Performance", "CA1811:AvoidUncalledPrivateCode")]
+ internal Resources() {
+ }
+
+ ///
+ /// Returns the cached ResourceManager instance used by this class.
+ ///
+ [global::System.ComponentModel.EditorBrowsableAttribute(global::System.ComponentModel.EditorBrowsableState.Advanced)]
+ internal static global::System.Resources.ResourceManager ResourceManager {
+ get {
+ if (object.ReferenceEquals(resourceMan, null)) {
+ global::System.Resources.ResourceManager temp = new global::System.Resources.ResourceManager("SequentialScript.Test.CustomData.Resources", typeof(Resources).Assembly);
+ resourceMan = temp;
+ }
+ return resourceMan;
+ }
+ }
+
+ ///
+ /// Overrides the current thread's CurrentUICulture property for all
+ /// resource lookups using this strongly typed resource class.
+ ///
+ [global::System.ComponentModel.EditorBrowsableAttribute(global::System.ComponentModel.EditorBrowsableState.Advanced)]
+ internal static global::System.Globalization.CultureInfo Culture {
+ get {
+ return resourceCulture;
+ }
+ set {
+ resourceCulture = value;
+ }
+ }
+
+ ///
+ /// Looks up a localized string similar to [OPEN]
+ ///run
+ /// Block -> Some Action /NoCheck /Key1:Value /Key2:"Value with spaces" /Key3:"Value with special characters :/"
+ ///as @action.
+ ///
+ internal static string TestArguments {
+ get {
+ return ResourceManager.GetString("TestArguments", resourceCulture);
+ }
+ }
+
+ ///
+ /// Looks up a localized string similar to [OPEN]
+ ///
+ ///// Comment over block
+ ///run // Comment in block
+ ///
+ /// // Comment over instruction
+ /// Door -> Open // Comment in instruction
+ ///
+ ///as @open_door // Comment at the end of the block.
+ ///
+ internal static string TestComments {
+ get {
+ return ResourceManager.GetString("TestComments", resourceCulture);
+ }
+ }
+
+ ///
+ /// Looks up a localized string similar to [OPEN]
+ ///run
+ /// Block -> Some Action /NoCheck /Key1:Value /Key2:"Value with spaces" /Key3:"Value with special characters :/"
+ /// Delay 3000
+ ///as @action.
+ ///
+ internal static string TestDelay {
+ get {
+ return ResourceManager.GetString("TestDelay", resourceCulture);
+ }
+ }
+
+ ///
+ /// Looks up a localized string similar to [OPEN]
+ ///run
+ /// Door Light -> Enable
+ ///as @open_door_1
+ ///
+ ///when @open_door_1
+ ///run
+ /// Door -> Open
+ ///as @open_door_2
+ ///
+ ///when @open_door_1, @open_door_2
+ ///run
+ /// Door Light -> Disable
+ ///as @open_door_3.
+ ///
+ internal static string TestDependences {
+ get {
+ return ResourceManager.GetString("TestDependences", resourceCulture);
+ }
+ }
+
+ ///
+ /// Looks up a localized string similar to [OPEN]
+ ///run
+ /// Door Light -> Enable
+ ///as @open_door_1
+ ///
+ ///when @open_door_1, @open_door_3
+ ///run
+ /// Door -> Open
+ ///as @open_door_2
+ ///
+ ///when @open_door_1, @open_door_2
+ ///run
+ /// Door Light -> Disable
+ ///as @open_door_3.
+ ///
+ internal static string TestDependences_Recursivity {
+ get {
+ return ResourceManager.GetString("TestDependences_Recursivity", resourceCulture);
+ }
+ }
+
+ ///
+ /// Looks up a localized string similar to [HYDROGEN_STOCKPILE]
+ ///run
+ /// Hydrogen Example (Thruster) -> Disable
+ ///as @thrusters_disabled
+ ///
+ ///run
+ /// Hydrogen Example (Status LCD) -> Set /Index:-1 /Background:YELLOW /Text:Connecting...
+ /// Hydrogen Example (Piston) -> Extend
+ ///as @piston_extended
+ ///
+ ///when @piston_extended
+ ///run
+ /// Hydrogen Example (Connector) -> Connect
+ ///as @connector_locked
+ ///
+ ///when @connector_locked
+ ///run
+ /// Hydrogen Example (Status LCD) -> Set /Index:-1 /Background:BLUE /Text:Recharging...
+ /// Hydrogen Example (Tank) -> Stockpile
+ ///as @tank_full
+ ///
/// [rest of string was truncated]";.
+ ///
+ internal static string TestHydrogen {
+ get {
+ return ResourceManager.GetString("TestHydrogen", resourceCulture);
+ }
+ }
+
+ ///
+ /// Looks up a localized string similar to [OPEN]
+ ///run
+ /// Door -> Open
+ ///as @open_door.
+ ///
+ internal static string TestSimple {
+ get {
+ return ResourceManager.GetString("TestSimple", resourceCulture);
+ }
+ }
+
+ ///
+ /// Looks up a localized string similar to [TEST]
+ ///run
+ /// Block 1 -> Enabled
+ /// Block 2 -> Enabled
+ ///as @block_name
+ ///
+ ///run
+ /// Block 3 -> Enabled
+ /// Block 4 -> Enabled
+ /// Block 5 -> Enabled
+ ///as @block_name
+ ///.
+ ///
+ internal static string TestSyntaxAliasDuplicated {
+ get {
+ return ResourceManager.GetString("TestSyntaxAliasDuplicated", resourceCulture);
+ }
+ }
+
+ ///
+ /// Looks up a localized string similar to [TEST]
+ ///run
+ /// Air Vent -> Depressurize
+ ///as @room_depressurized
+ ///
+ ///when @room_depressurized
+ ///run
+ /// Door 1 -> Enable
+ /// Door 1 -> Open
+ ///as door_opened.
+ ///
+ internal static string TestSyntaxAliasInvalid {
+ get {
+ return ResourceManager.GetString("TestSyntaxAliasInvalid", resourceCulture);
+ }
+ }
+
+ ///
+ /// Looks up a localized string similar to .
+ ///
+ internal static string TestSyntaxInstructionInvalid {
+ get {
+ return ResourceManager.GetString("TestSyntaxInstructionInvalid", resourceCulture);
+ }
+ }
+ }
+}
diff --git a/SequentialScript.Test/CustomData/Resources.resx b/SequentialScript.Test/CustomData/Resources.resx
index 52bc585..d5829f7 100644
--- a/SequentialScript.Test/CustomData/Resources.resx
+++ b/SequentialScript.Test/CustomData/Resources.resx
@@ -124,6 +124,9 @@
TestComments.txt;System.String, mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089;utf-8
+
+ TestDelay.txt;System.String, mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089;utf-8
+
TestDependences.txt;System.String, mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089;utf-8
diff --git a/SequentialScript.Test/CustomData/TestDelay.txt b/SequentialScript.Test/CustomData/TestDelay.txt
new file mode 100644
index 0000000..d602e50
--- /dev/null
+++ b/SequentialScript.Test/CustomData/TestDelay.txt
@@ -0,0 +1,5 @@
+[OPEN]
+run
+ Block -> Some Action /NoCheck /Key1:Value /Key2:"Value with spaces" /Key3:"Value with special characters :/"
+ Delay 3000
+as @action
\ No newline at end of file
diff --git a/SequentialScript.Test/CustomData/TestHydrogen.txt b/SequentialScript.Test/CustomData/TestHydrogen.txt
index 14e4c30..988fce2 100644
--- a/SequentialScript.Test/CustomData/TestHydrogen.txt
+++ b/SequentialScript.Test/CustomData/TestHydrogen.txt
@@ -6,7 +6,7 @@ as @thrusters_disabled
run
Hydrogen Example (Status LCD) -> Set /Index:-1 /Background:YELLOW /Text:Connecting...
Hydrogen Example (Piston) -> Extend
-as piston_extended
+as @piston_extended
when @piston_extended
run
diff --git a/SequentialScript.Test/InstructionParserTest.cs b/SequentialScript.Test/InstructionParserTest.cs
index 26fb342..e732990 100644
--- a/SequentialScript.Test/InstructionParserTest.cs
+++ b/SequentialScript.Test/InstructionParserTest.cs
@@ -192,5 +192,43 @@ public void TestHydrogen()
commands = IngameScript.InstructionParser.Parse(CustomData.Resources.TestHydrogen);
commands.ToString();
}
+
+ [TestMethod]
+ public void TestDelay()
+ {
+ IDictionary commands;
+ var expected = new Dictionary()
+ {
+ { "OPEN", new IngameScript.InstructionCommand {
+ CommandName = "OPEN",
+ Body = new Dictionary {
+ { "@action", new IngameScript.InstructionBlock {
+ Alias = "@action",
+ PreviousAlias = new string[] { },
+ Instructions = new []{ new IngameScript.Instruction {
+ BlockName = "Block",
+ ActionName = "Some Action",
+ Arguments = new Dictionary {
+ { "NoCheck", "" },
+ { "Key1", "Value" },
+ { "Key2", "Value with spaces" },
+ { "Key3", "Value with special characters :/" }
+ },
+ IsValid = true,
+ }, new IngameScript.Instruction {
+ BlockName = null,
+ ActionName = "DELAY",
+ Arguments = new Dictionary { { "TIME", "3000" } },
+ IsValid = true,
+ }},
+ } }
+ }.Values
+ }}
+ };
+
+ commands = IngameScript.InstructionParser.Parse(CustomData.Resources.TestDelay);
+ InstrucionAssert.AreEqual(expected, commands);
+ }
+
}
}
diff --git a/SequentialScript.Test/SequentialScript.Test.csproj b/SequentialScript.Test/SequentialScript.Test.csproj
index 5e55882..d29288c 100644
--- a/SequentialScript.Test/SequentialScript.Test.csproj
+++ b/SequentialScript.Test/SequentialScript.Test.csproj
@@ -71,6 +71,7 @@
+
diff --git a/SequentialScript/Instructions.readme b/SequentialScript/Instructions.readme
index aa44956..b4389e7 100644
--- a/SequentialScript/Instructions.readme
+++ b/SequentialScript/Instructions.readme
@@ -1,6 +1,6 @@
R e a d m e
-----------
-V1.1-alpha.6
+V1.2-alpha
See more information in the following link:
https://github.com/space-engineers-hf/SequentialScript
\ No newline at end of file
diff --git a/SequentialScript/Instructions/InstructionParser.cs b/SequentialScript/Instructions/InstructionParser.cs
index c0f00eb..144f772 100644
--- a/SequentialScript/Instructions/InstructionParser.cs
+++ b/SequentialScript/Instructions/InstructionParser.cs
@@ -125,40 +125,52 @@ private static InstructionCommand CreateCommand(System.Text.RegularExpressions.M
.Where(line => !string.IsNullOrWhiteSpace(line) && !line.StartsWith("//")) // Ignore empty lines and comments.
.Select((line, index) =>
{
+ Instruction instruction = null;
+
// Remove comments
var lineComments = line.Split(new[] { "//" }, StringSplitOptions.None);
- var lineWithoutComments = lineComments.First();
-
- // Take BlockName and ActionName
- var lineItems = lineWithoutComments.Trim().Split(new[] { "->" }, StringSplitOptions.RemoveEmptyEntries);
- string blockName = null, actionName = null;
- bool isValid;
+ var lineWithoutComments = lineComments.First().Trim();
- if (lineItems.Length > 0)
+ // Create instruction.
+ if (lineWithoutComments.Contains("->"))
{
- blockName = lineItems[0].Trim();
+ // Instruction of IMyTerminalBlock -> Action
+ instruction = CreateInstruction(lineWithoutComments);
}
- if (lineItems.Length > 1)
+ else
{
- actionName = lineItems[1].Trim();
- }
- isValid = lineItems.Length == 2;
-
- // Arguments
- var arguments = GetArguments(actionName);
+ // Script reserved instructions.
+ var lineItems = lineWithoutComments.Split(new[] { ' ' }, StringSplitOptions.RemoveEmptyEntries);
+ var command = lineItems.FirstOrDefault();
+ if (command == null)
+ {
+ instruction = null;
+ }
+ else if (command.Equals("DELAY", StringComparison.OrdinalIgnoreCase))
+ {
+ instruction = CreateInstructionDelay(lineItems);
+ }
+ if (instruction == null)
+ {
+ instruction = new Instruction
+ {
+ BlockName = null,
+ ActionName = null,
+ Arguments = null,
+ IsValid = false
+ };
+ }
+ }
return new
{
Line = index + 1,
- BlockName = blockName,
- ActionName = arguments[""].Trim(),
- Arguments = arguments.Where(x => !string.IsNullOrEmpty(x.Key)).ToDictionary(x => x.Key, x => x.Value, StringComparer.OrdinalIgnoreCase),
- IsValid = isValid
+ Instruction = instruction,
};
})
;
- var invalid = actions.Where(x => !x.IsValid);
+ var invalid = actions.Where(x => !x.Instruction.IsValid);
if (invalid.Any())
{
throw new SyntaxException(
@@ -197,13 +209,7 @@ private static InstructionCommand CreateCommand(System.Text.RegularExpressions.M
{
Alias = alias,
PreviousAlias = previousActionsMatch.Select(x => x.Alias),
- Instructions = actions.Select(x => new Instruction
- {
- BlockName = x.BlockName,
- ActionName = x.ActionName,
- Arguments = x.Arguments,
- IsValid = x.IsValid
- })
+ Instructions = actions.Select(x => x.Instruction)
});
}
}
@@ -237,6 +243,55 @@ private static InstructionCommand CreateCommand(System.Text.RegularExpressions.M
return result;
}
+ private static Instruction CreateInstruction(string lineWithoutComments)
+ {
+ // Take BlockName and ActionName
+ var lineItems = lineWithoutComments.Split(new[] { "->" }, StringSplitOptions.RemoveEmptyEntries);
+ string blockName = null, actionName = null;
+ bool isValid;
+
+ if (lineItems.Length > 0)
+ {
+ blockName = lineItems[0].Trim();
+ }
+ if (lineItems.Length > 1)
+ {
+ actionName = lineItems[1].Trim();
+ }
+ isValid = lineItems.Length == 2;
+
+ // Arguments
+ var arguments = GetArguments(actionName);
+
+ // Return
+ return new Instruction
+ {
+ BlockName = blockName,
+ ActionName = arguments[""].Trim(),
+ Arguments = arguments.Where(x => !string.IsNullOrEmpty(x.Key)).ToDictionary(x => x.Key, x => x.Value, StringComparer.OrdinalIgnoreCase),
+ IsValid = isValid
+ };
+ }
+
+ private static Instruction CreateInstructionDelay(string[] lineItems)
+ {
+ string timeString = null;
+
+ if (lineItems.Length >= 1)
+ {
+ timeString = lineItems[1];
+ }
+ return new Instruction
+ {
+ BlockName = null,
+ ActionName = "DELAY",
+ Arguments = new Dictionary() {
+ { "TIME", timeString }
+ },
+ IsValid = true
+ };
+ }
+
private static ConditionCommandInstruction CreateConditionCommand(System.Text.RegularExpressions.Match commandMatch)
{
ConditionCommandInstruction result = null;
diff --git a/SequentialScript/MDK/MDK.options.props b/SequentialScript/MDK/MDK.options.props
index 2dab6fa..1d8bd19 100644
--- a/SequentialScript/MDK/MDK.options.props
+++ b/SequentialScript/MDK/MDK.options.props
@@ -6,10 +6,10 @@
-->
1.4.14
- no
+ yes
- StripComments
+ Lite
mdk
diff --git a/SequentialScript/Program.cs b/SequentialScript/Program.cs
index a0176d2..cb92548 100644
--- a/SequentialScript/Program.cs
+++ b/SequentialScript/Program.cs
@@ -30,6 +30,11 @@ partial class Program : MyGridProgram
static readonly UpdateFrequency UPDATE_FREQUENCY = UpdateFrequency.Update10; // Update1, Update10, Update100
static readonly int UPDATE_TICKS = 0; // Very slow mode multiplier (for debug)
+
+ /* ----------------------------------------------------------------------------------- */
+ /* --- ¡¡¡IMPORTANT!!! Do not change anything below this line. --- */
+ /* ----------------------------------------------------------------------------------- */
+
#endregion
DateTime _momento;
@@ -76,7 +81,9 @@ public void Main(string argument, UpdateType updateSource)
.OfType()
.SelectMany(cmd => cmd.Body)
.SelectMany(body => body.Instructions)
- .Select(instruction => instruction.BlockName);
+ .Where(instruction => instruction.BlockName != null)
+ .Select(instruction => instruction.BlockName)
+ .Distinct();
AdvancedEcho($"Building dictionary", append: true);
_blocksDictionary = Helper.CreateBlockDictionary(blockNames, _terminalBlocks, _terminalGroups);
@@ -283,7 +290,7 @@ void EndCycle()
void AdvancedEchoReset()
{
- _momento = DateTime.Now;
+ _momento = DateTime.UtcNow;
}
void AdvancedEcho(string message, bool append = false)
@@ -297,7 +304,7 @@ void AdvancedEcho(string message, bool append = false)
builder.Append(value);
message = builder.ToString();
}
- message = $"| Elapsed {(DateTime.Now - _momento).TotalMilliseconds:00}ms |\n{message}";
+ message = $"| Elapsed {(DateTime.UtcNow - _momento).TotalMilliseconds:00}ms |\n{message}";
Echo(message);
if (DEBUG_IN_SCREEN)
diff --git a/SequentialScript/SequentialScript.csproj b/SequentialScript/SequentialScript.csproj
index 3084c30..85ace97 100644
--- a/SequentialScript/SequentialScript.csproj
+++ b/SequentialScript/SequentialScript.csproj
@@ -99,8 +99,11 @@
+
+
+
diff --git a/SequentialScript/Tasks/ITaskAction.cs b/SequentialScript/Tasks/ITaskAction.cs
new file mode 100644
index 0000000..d68d997
--- /dev/null
+++ b/SequentialScript/Tasks/ITaskAction.cs
@@ -0,0 +1,52 @@
+using Sandbox.Game.EntityComponents;
+using Sandbox.ModAPI.Ingame;
+using Sandbox.ModAPI.Interfaces;
+using SpaceEngineers.Game.ModAPI.Ingame;
+using System;
+using System.Collections;
+using System.Collections.Generic;
+using System.Collections.Immutable;
+using System.Linq;
+using System.Text;
+using VRage;
+using VRage.Collections;
+using VRage.Game;
+using VRage.Game.Components;
+using VRage.Game.GUI.TextPanel;
+using VRage.Game.ModAPI.Ingame;
+using VRage.Game.ModAPI.Ingame.Utilities;
+using VRage.Game.ObjectBuilders.Definitions;
+using VRageMath;
+
+namespace IngameScript
+{
+ interface ITaskAction
+ {
+
+ string ActionKey { get; }
+
+ ///
+ /// Gets or sets if this task action must be checked during "" validation.
+ ///
+ bool IsCommandCondition { get; set; }
+
+ ///
+ /// Gets or sets when this task started or null if it has not started yet.
+ ///
+ DateTime? StartTime { get; set; }
+
+ ///
+ /// Starts the task.
+ ///
+ void Execute();
+
+ ///
+ /// Checks if this task has been ended.
+ ///
+ ///
+ ///
+ ///
+ bool Check(TaskStatusMode mode, DateTime? momento = null, StringBuilder debug = null);
+
+ }
+}
diff --git a/SequentialScript/Tasks/Task.cs b/SequentialScript/Tasks/Task.cs
index a91f679..7120f3d 100644
--- a/SequentialScript/Tasks/Task.cs
+++ b/SequentialScript/Tasks/Task.cs
@@ -25,7 +25,7 @@ class Task
public string Alias { get; set; }
public IEnumerable PreviousTasks { get; set; }
- public IEnumerable Actions { get; set; }
+ public IEnumerable Actions { get; set; }
public bool IsRunning { get; set; }
public bool IsDone { get; set; }
diff --git a/SequentialScript/Tasks/TaskAction.cs b/SequentialScript/Tasks/TaskAction.cs
index 7b6cf9c..814f9de 100644
--- a/SequentialScript/Tasks/TaskAction.cs
+++ b/SequentialScript/Tasks/TaskAction.cs
@@ -6,6 +6,7 @@
using System.Collections;
using System.Collections.Generic;
using System.Collections.Immutable;
+using System.Diagnostics;
using System.Linq;
using System.Text;
using VRage;
@@ -20,20 +21,25 @@
namespace IngameScript
{
- class TaskAction
+ class TaskAction : ITaskAction
{
+ public string ActionKey
+ {
+ get { return $"{this.Block.EntityId}\t{this.ActionProfile.GroupName}"; }
+ }
+
public IMyTerminalBlock Block { get; set; }
public IActionProfile ActionProfile { get; set; }
public IDictionary Arguments { get; set; }
-
+
public DateTime? StartTime { get; set; }
///
/// Gets or sets if this task action must be checked during "" validation.
///
- public bool Check { get; set; }
-
+ public bool IsCommandCondition { get; set; }
+
///
/// Gets or sets the number of milliseconds to wait before assume this task finished.
/// can finish before if returns true.
@@ -44,5 +50,62 @@ class TaskAction
///
public int Wait { get; set; }
+
+ public void Execute()
+ {
+ this.ActionProfile.OnActionCallback(this.Block, this.Arguments);
+ }
+
+ public bool Check(TaskStatusMode mode, DateTime? momento = null, StringBuilder debug = null)
+ {
+ var action = this;
+ bool isCompleted = false;
+ bool printDebug = false;
+ string sufixDebug = null;
+
+ switch (mode)
+ {
+ case TaskStatusMode.Condition:
+ // Condition wait is ignored.
+ if (action.Wait > -1)
+ {
+ sufixDebug = $"(wait:{action.Wait})";
+ isCompleted = true;
+ printDebug = false;
+ }
+ break;
+
+ case TaskStatusMode.Run:
+ if (action.Wait == 0) // No wait.
+ {
+ isCompleted = true;
+ }
+ else if (action.Wait > -1) // -1 wait until done
+ {
+ isCompleted = (action.StartTime != null && (((momento ?? DateTime.UtcNow) - action.StartTime.Value).TotalMilliseconds >= action.Wait)); // Wait for maximun...
+ }
+ sufixDebug = $"(wait:{action.Wait})";
+ printDebug = true;
+ break;
+
+ default:
+ break;
+ }
+ isCompleted |= action.ActionProfile.IsCompleteCallback(action.Block, action.Arguments);
+ if (printDebug && !isCompleted)
+ {
+ var isCompletedText = (isCompleted ? "Done" : "Pending");
+ var actionDebug = action.ActionProfile.GetCompletionDetails(action.Block, action.Arguments);
+
+ if (!string.IsNullOrWhiteSpace(actionDebug))
+ {
+ sufixDebug += $" ({actionDebug})";
+ }
+ debug?.AppendLine($" - {action.Block.DisplayNameText}.{action.ActionProfile.ActionNames.First()} ({isCompletedText})");
+ debug?.AppendLine($" {sufixDebug?.Trim()} {action.StartTime?.ToString("HH:mm:ss")}");
+ }
+ return isCompleted;
+ }
+
}
}
diff --git a/SequentialScript/Tasks/TaskActionDelay.cs b/SequentialScript/Tasks/TaskActionDelay.cs
new file mode 100644
index 0000000..2056844
--- /dev/null
+++ b/SequentialScript/Tasks/TaskActionDelay.cs
@@ -0,0 +1,58 @@
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+using System.Threading.Tasks;
+
+namespace IngameScript
+{
+ class TaskActionDelay : ITaskAction
+ {
+
+ private string _name => $"delay_{DateTime.Now.Ticks}";
+ private DateTime? _internalStartTime;
+
+ ///
+ /// Time in miliseconds before this task is done.
+ ///
+ public int Delay { get; set; }
+
+ public string ActionKey => _name;
+ public DateTime? StartTime { get; set; }
+
+ public bool IsCommandCondition
+ {
+ get { return false; }
+ set { throw new NotImplementedException(); }
+ }
+
+ public void Execute()
+ {
+ _internalStartTime = DateTime.UtcNow;
+ }
+
+ public bool Check(TaskStatusMode mode, DateTime? momento = null, StringBuilder debug = null)
+ {
+ bool isCompleted;
+ string isCompletedText;
+
+ if (_internalStartTime.HasValue)
+ {
+ var elapsedTimeSpan = (momento ?? DateTime.UtcNow) - _internalStartTime.Value;
+ var remainingTimeSpan = TimeSpan.FromMilliseconds(this.Delay) - elapsedTimeSpan;
+
+ debug?.Append($"Delay: {remainingTimeSpan:hh\\:mm\\:ss}");
+ isCompleted = (remainingTimeSpan <= TimeSpan.Zero);
+ }
+ else
+ {
+ debug?.Append($"Delay: not started");
+ isCompleted = false; //not started yet.
+ }
+ isCompletedText = (isCompleted ? "Done" : "Pending");
+ debug?.Append($" ({isCompletedText})");
+ return isCompleted;
+ }
+
+ }
+}
diff --git a/SequentialScript/Tasks/TaskEnums.cs b/SequentialScript/Tasks/TaskEnums.cs
new file mode 100644
index 0000000..cede0d0
--- /dev/null
+++ b/SequentialScript/Tasks/TaskEnums.cs
@@ -0,0 +1,44 @@
+using Sandbox.Game.EntityComponents;
+using Sandbox.Game.GameSystems;
+using Sandbox.ModAPI.Ingame;
+using Sandbox.ModAPI.Interfaces;
+using SpaceEngineers.Game.ModAPI.Ingame;
+using System;
+using System.Collections;
+using System.Collections.Generic;
+using System.Collections.Immutable;
+using System.Linq;
+using System.Text;
+using VRage;
+using VRage.Collections;
+using VRage.Game;
+using VRage.Game.Components;
+using VRage.Game.GUI.TextPanel;
+using VRage.Game.ModAPI.Ingame;
+using VRage.Game.ModAPI.Ingame.Utilities;
+using VRage.Game.ObjectBuilders.Definitions;
+using VRageMath;
+
+namespace IngameScript
+{
+
+ enum TaskStatus
+ {
+ Pending,
+ Running,
+ Completed
+ }
+
+ enum TaskStatusMode
+ {
+ ///
+ /// Checks if task is already done.
+ ///
+ Condition,
+ ///
+ /// Checks if every actions in the task have run and finished.
+ ///
+ Run
+ }
+
+}
diff --git a/SequentialScript/Tasks/Tasks.cs b/SequentialScript/Tasks/Tasks.cs
index 9590e9b..39c68cc 100644
--- a/SequentialScript/Tasks/Tasks.cs
+++ b/SequentialScript/Tasks/Tasks.cs
@@ -24,24 +24,6 @@ namespace IngameScript
static class Tasks
{
- enum TaskStatus
- {
- Pending,
- Running,
- Completed
- }
-
- enum TaskStatusMode
- {
- ///
- /// Checks if task is already done.
- ///
- Condition,
- ///
- /// Checks if every actions in the task have run and finished.
- ///
- Run
- }
///
/// Creates a list of tasks from a list of .
@@ -56,60 +38,26 @@ public static IEnumerable CreateTasks(IEnumerable instru
foreach (var instructionBlock in instructions)
{
- var actions = new List();
+ var actions = new List();
foreach (var instruction in instructionBlock.Instructions)
{
- IEnumerable blocks = null;
-
- // Try get blocks.
- if (blockDictionary.TryGetValue(instruction.BlockName, out blocks))
+ if (instruction.BlockName == null)
{
- foreach (var block in blocks)
+ // Script actions.
+ switch (instruction.ActionName)
{
- string argumentValue;
- bool check;
- int wait;
-
- // Check parameters
- check = instruction.Arguments.TryGetValue("CHECK", out argumentValue) && (string.IsNullOrWhiteSpace(argumentValue) || argumentValue.Equals("true", StringComparison.OrdinalIgnoreCase));
- if (instruction.Arguments.TryGetValue("MAXWAIT", out argumentValue))
- {
- if (string.IsNullOrWhiteSpace(argumentValue) || !int.TryParse(argumentValue, out wait))
- {
- throw new FormatException($"'/MAXWAIT' must have a numeric value.");
- }
- }
- else if (instruction.Arguments.TryGetValue("WAIT", out argumentValue))
- {
- if (string.IsNullOrWhiteSpace(argumentValue) || !int.TryParse(argumentValue, out wait))
- {
- throw new FormatException($"'/WAIT' must have a numeric value.");
- }
- }
- else if (instruction.Arguments.TryGetValue("NOWAIT", out argumentValue) && (string.IsNullOrWhiteSpace(argumentValue) || argumentValue.Equals("true", StringComparison.OrdinalIgnoreCase)))
- {
- wait = 0;
- }
- else
- {
- wait = -1;
- }
-
- // Add action.
- actions.Add(new TaskAction
- {
- Block = block,
- ActionProfile = ActionProfiles.GetActionProfile(block, instruction.ActionName),
- Arguments = instruction.Arguments,
- Check = check,
- Wait = wait
- });
+ case "DELAY":
+ actions.Add(CreateTaskDelay(instruction));
+ break;
+ default:
+ throw new Exception($"Action name: '{instruction.ActionName}'.");
}
}
else
{
- throw new KeyNotFoundException($"No blocks found with name '{instruction.BlockName}'.");
+ // Block actions.
+ actions.AddRange(CreateTaskAction(instruction, blockDictionary));
}
}
result.Add(new Task
@@ -127,6 +75,93 @@ public static IEnumerable CreateTasks(IEnumerable instru
return result;
}
+ private static IEnumerable CreateTaskAction(Instruction instruction, IDictionary> blockDictionary)
+ {
+ var list = new List();
+ IEnumerable blocks = null;
+
+ // Try get blocks.
+ if (blockDictionary.TryGetValue(instruction.BlockName, out blocks))
+ {
+ string argumentValue;
+ bool check;
+ int wait;
+
+ // Check parameters
+ check = instruction.Arguments.TryGetValue("CHECK", out argumentValue) && (string.IsNullOrWhiteSpace(argumentValue) || argumentValue.Equals("true", StringComparison.OrdinalIgnoreCase));
+ if (instruction.Arguments.TryGetValue("MAXWAIT", out argumentValue))
+ {
+ if (string.IsNullOrWhiteSpace(argumentValue) || !int.TryParse(argumentValue, out wait))
+ {
+ throw new FormatException($"'/MAXWAIT' must have a numeric value.");
+ }
+ }
+ else if (instruction.Arguments.TryGetValue("WAIT", out argumentValue))
+ {
+ if (string.IsNullOrWhiteSpace(argumentValue) || !int.TryParse(argumentValue, out wait))
+ {
+ throw new FormatException($"'/WAIT' must have a numeric value.");
+ }
+ }
+ else if (instruction.Arguments.TryGetValue("NOWAIT", out argumentValue) && (string.IsNullOrWhiteSpace(argumentValue) || argumentValue.Equals("true", StringComparison.OrdinalIgnoreCase)))
+ {
+ wait = 0;
+ }
+ else
+ {
+ wait = -1;
+ }
+
+ foreach (var block in blocks)
+ {
+
+ // Add action.
+ list.Add(new TaskAction
+ {
+ Block = block,
+ ActionProfile = ActionProfiles.GetActionProfile(block, instruction.ActionName),
+ Arguments = instruction.Arguments,
+ IsCommandCondition = check,
+ Wait = wait
+ });
+ }
+ }
+ else
+ {
+ throw new KeyNotFoundException($"No blocks found with name '{instruction.BlockName}'.");
+ }
+ return list;
+ }
+
+ private static TaskActionDelay CreateTaskDelay(Instruction instruction)
+ {
+ string argumentValue;
+ int milliseconds;
+
+ if (instruction.Arguments.TryGetValue("TIME", out argumentValue))
+ {
+ if (string.IsNullOrWhiteSpace(argumentValue) || !int.TryParse(argumentValue, out milliseconds))
+ {
+ throw new FormatException($"Delay time must be numeric.");
+ }
+ }
+ else
+ {
+ throw new FormatException($"No time defined for delay.");
+ }
+
+ return new TaskActionDelay
+ {
+ Delay = milliseconds
+ };
+ }
+
+ ///
+ /// Starts task.
+ ///
+ ///
+ ///
+ ///
public static IEnumerable Run(this IEnumerable tasks, StringBuilder debug = null)
{
var momento = DateTime.UtcNow;
@@ -152,7 +187,7 @@ public static IEnumerable Run(this IEnumerable tasks, StringBuilder
{
foreach (var action in task.Actions)
{
- action.ActionProfile.OnActionCallback(action.Block, action.Arguments);
+ action.Execute();
action.StartTime = momento;
}
task.IsRunning = true;
@@ -180,7 +215,7 @@ public static void Cancel(this IEnumerable tasks)
public static bool IsCompleted(this IEnumerable tasks, StringBuilder debug = null)
{
bool result;
- var checkActions = tasks.SelectMany(x => x.Actions).Where(x => x.Check);
+ var checkActions = tasks.SelectMany(x => x.Actions).Where(x => x.IsCommandCondition);
debug?.AppendLine("Checking:");
if (!checkActions.Any())
@@ -239,67 +274,18 @@ private static bool IsDone(Task task, TaskStatusMode mode, DateTime? momento = n
///
/// Checks if all have been completed.
///
- private static bool IsDone(IEnumerable actions, TaskStatusMode mode, DateTime? momento = null, StringBuilder debug = null)
+ private static bool IsDone(IEnumerable actions, TaskStatusMode mode, DateTime? momento = null, StringBuilder debug = null)
{
- return actions.All(action =>
- {
- bool isCompleted = false;
- bool printDebug = false;
- string sufixDebug = null;
-
- switch (mode)
- {
- case TaskStatusMode.Condition:
- // Condition wait is ignored.
- if (action.Wait > -1)
- {
- sufixDebug = $"(wait:{action.Wait})";
- isCompleted = true;
- printDebug = false;
- }
- break;
-
- case TaskStatusMode.Run:
- if (action.Wait == 0) // No wait.
- {
- isCompleted = true;
- sufixDebug = $"(wait:{action.Wait})";
- }
- else if (action.Wait > -1) // -1 wait until done
- {
- isCompleted = (action.StartTime != null && (((momento ?? DateTime.UtcNow) - action.StartTime.Value).TotalMilliseconds > action.Wait)); // Wait for maximun...
- }
- sufixDebug = $"(wait:{action.Wait})";
- printDebug = true;
- break;
-
- default:
- break;
- }
- isCompleted |= action.ActionProfile.IsCompleteCallback(action.Block, action.Arguments);
- if (printDebug && !isCompleted)
- {
- var isCompletedText = (isCompleted ? "Done" : "Pending");
- var actionDebug = action.ActionProfile.GetCompletionDetails(action.Block, action.Arguments);
-
- if (!string.IsNullOrWhiteSpace(actionDebug))
- {
- sufixDebug += $" ({actionDebug})";
- }
- debug?.AppendLine($" - {action.Block.DisplayNameText}.{action.ActionProfile.ActionNames.First()} ({isCompletedText})");
- debug?.AppendLine($" {sufixDebug?.Trim()} {action.StartTime?.ToString("HH:mm:ss")}");
- }
- return isCompleted;
- });
+ return actions.All(action => action.Check(mode, momento, debug));
}
///
/// Returns the last action for each block taking in mind the running sequence.
///
/// List of instruction blocks.
- public static IEnumerable GetLastActions(this IEnumerable tasks)
+ public static IEnumerable GetLastActions(this IEnumerable tasks)
{
- var actionDictionary = new Dictionary(StringComparer.OrdinalIgnoreCase);
+ var actionDictionary = new Dictionary(StringComparer.OrdinalIgnoreCase);
var validatedTasks = new List(); // All tasks already validated.
IEnumerable validationTasks; // Tasks to validate for each iteration.
var i = 0;
@@ -312,7 +298,7 @@ public static IEnumerable GetLastActions(this IEnumerable task
{
foreach (var action in task.Actions)
{
- actionDictionary[$"{action.Block.EntityId}\t{action.ActionProfile.GroupName}"] = action;
+ actionDictionary[action.ActionKey] = action;
}
validatedTasks.Add(task);
}
diff --git a/docs/README.md b/docs/README.md
index 16d3f8d..eb6eea9 100644
--- a/docs/README.md
+++ b/docs/README.md
@@ -5,6 +5,7 @@
- [Blocks](#blocks)
- [Sequence](#sequence)
- [Argumens](#arguments)
+ - [Delay](#delay)
- [Comments](#comments)
- [Action list](#action-list)
- [Known issues](#known-issues)
@@ -199,6 +200,22 @@ as @done
#### Custom-defined arguments by action
Some actions have their own arguments. Those arguments are defined in the [action list](#action-list).
+### Delay
+Include "DELAY" instruction (in milliseconds) when it is necessary to wait for a specific time before a sequence block is done.
+
+The following example waits for 3 seconds before switchs on the second light.
+```
+[COMMAND_NAME]
+run
+ Interior Light 1 -> Enable
+ delay 3000 // Waits for 3 seconds.
+as @light1_on
+
+when @light1_on
+run
+ Interior Light 2 -> Enable
+as @light2_on
+```
### Comments