New IEntity properties: Coordinates (set), Identifier. Loadable entities should...
[chaz/carfire] / CarFire / CarFire / CarFire / Script.cs
1 ´╗┐using System;
2 using System.Collections.Generic;
3 using System.Linq;
4 using System.Text;
5 using System.Reflection;
6 using System.Diagnostics;
7
8 namespace CarFire
9 {
10 /// <summary>
11 /// The Script class handles the parsing and execution of lists
12 /// of functions. Scripts are closely related to triggers.
13 /// </summary>
14 public class Script
15 {
16 #region Public Properties
17
18 /// <summary>
19 /// Determine if the script is in the process of being run.
20 /// </summary>
21 public bool IsRunning { get { return mIsRunning; } }
22
23 #endregion
24
25
26 #region Public Methods
27
28 /// <summary>
29 /// Construct a script object with code and a game reference.
30 /// </summary>
31 /// <param name="code">The script code.</param>
32 /// <param name="game">A game reference.</param>
33 public Script(string code, object bindings)
34 {
35 mBindings = bindings;
36
37 string[] functions = Parse.List(code);
38 if (functions != null)
39 {
40 foreach (string function in functions)
41 {
42 string[] parts = Parse.Function(function);
43 if (parts != null)
44 {
45 string[] args = Parse.List(parts[1]);
46 if (args != null)
47 {
48 Function func = new Function(parts[0], args);
49 mFunctions.Add(func);
50 }
51 else throw new Exception("Arguments could not be parsed: " + parts[1]);
52 }
53 else throw new Exception("Function could not be parsed: " + function);
54 }
55 }
56 else throw new Exception("Script could not be parsed: " + code);
57 }
58
59 /// <summary>
60 /// Start execution of the script. If there is no need to break
61 /// execution before the script ends, it will finish before this method
62 /// call ends. Otherwise, execution will be delayed and will finish sometime
63 /// in the future. This will execute each function in sequence as long
64 /// as each function evaluates to true. If a function does not evaluate to true,
65 /// this method will return and execution will be delayed. In either case,
66 /// the evaluation of the last function is returned by this method.
67 /// </summary>
68 /// <param name="player">The player associated with this script.</param>
69 /// <returns>Evaluation of the last function call.</returns>
70 public bool Run(Player player)
71 {
72 bool result = false;
73
74 if (!mIsRunning)
75 {
76 mIsRunning = true;
77 mRunningIndex = 0;
78 }
79
80 for (; mRunningIndex < mFunctions.Count; mRunningIndex++)
81 {
82 result = Call(mRunningIndex, player);
83 if (!result) break;
84 }
85
86 if (mRunningIndex >= mFunctions.Count - 1) mIsRunning = false;
87 return result;
88 }
89
90 public void Reset()
91 {
92 mIsRunning = false;
93
94 }
95
96 #endregion
97
98
99 #region Private Methods
100
101 /// <summary>
102 /// Call a function in the last at a certain index.
103 /// </summary>
104 /// <param name="index">The function index.</param>
105 /// <param name="player">The associated player object.</param>
106 /// <returns>The evaluation of the function.</returns>
107 bool Call(int index, Player player)
108 {
109 Debug.Assert(0 <= index && index < mFunctions.Count);
110 try
111 {
112 object[] args = new object[2];
113 args[0] = player;
114 args[1] = mFunctions[index].Arguments;
115 return (bool)mBindings.GetType().InvokeMember(mFunctions[index].Name, BindingFlags.InvokeMethod, null, mBindings, args);
116 }
117 #pragma warning disable 0168
118 catch (System.MissingMethodException ex)
119 #pragma warning restore 0168
120 {
121 throw new Exception("Function could not be found: " + mFunctions[index].Name);
122 }
123 }
124
125 #endregion
126
127
128 #region Private Types
129
130 class Function
131 {
132 public string Name { get { return mName; } }
133 public string[] Arguments { get { return mArgs; } }
134
135 public Function(string name, string[] args)
136 {
137 mName = name;
138 mArgs = args;
139 }
140
141 string mName;
142 string[] mArgs;
143 }
144
145 #endregion
146
147
148 #region Private Variables
149
150 object mBindings;
151 List<Function> mFunctions = new List<Function>();
152 bool mIsRunning;
153 int mRunningIndex;
154
155 #endregion
156 }
157 }
This page took 0.047971 seconds and 4 git commands to generate.