diff --git a/binaries/data/mods/_test.sim/simulation/components/addentity/test-addentity.js b/binaries/data/mods/_test.sim/simulation/components/addentity/test-addentity.js
new file mode 100644
index 0000000000..2d17760034
--- /dev/null
+++ b/binaries/data/mods/_test.sim/simulation/components/addentity/test-addentity.js
@@ -0,0 +1,11 @@
+function TestScript2A() {}
+
+TestScript2A.prototype.Init = function() {
+ this.x = eval(this.template.y);
+};
+
+TestScript2A.prototype.GetX = function() {
+ return this.x;
+};
+
+Engine.RegisterComponentType(IID_Test2, "TestScript2A", TestScript2A);
\ No newline at end of file
diff --git a/binaries/data/mods/_test.sim/simulation/components/error.js b/binaries/data/mods/_test.sim/simulation/components/error.js
new file mode 100644
index 0000000000..e79e828e40
--- /dev/null
+++ b/binaries/data/mods/_test.sim/simulation/components/error.js
@@ -0,0 +1,12 @@
+function TestScript1A() {}
+
+try {
+ Engine.RegisterComponentType(12345, "TestScript1A", TestScript1A);
+ Engine.TS_FAIL("Missed exception");
+} catch (e) {
+// print("Caught exception: " + e + "\n");
+}
+
+var n = Engine.QueryInterface(12345, IID_Test1);
+if (n !== null)
+ Engine.TS_FAIL("QueryInterface return "+n+", not null");
diff --git a/binaries/data/mods/_test.sim/simulation/components/test-entityid.js b/binaries/data/mods/_test.sim/simulation/components/test-entityid.js
new file mode 100644
index 0000000000..e0541699d9
--- /dev/null
+++ b/binaries/data/mods/_test.sim/simulation/components/test-entityid.js
@@ -0,0 +1,12 @@
+function TestScript1A() {}
+
+TestScript1A.prototype.GetX = function() {
+ // Test that .entity is readonly
+ delete this.entity;
+ this.entity = -1;
+
+ // and return the value
+ return this.entity;
+};
+
+Engine.RegisterComponentType(IID_Test1, "TestScript1A", TestScript1A);
diff --git a/binaries/data/mods/_test.sim/simulation/components/test-helper.js b/binaries/data/mods/_test.sim/simulation/components/test-helper.js
new file mode 100644
index 0000000000..ea491d4134
--- /dev/null
+++ b/binaries/data/mods/_test.sim/simulation/components/test-helper.js
@@ -0,0 +1,7 @@
+function TestScript1_Helper() {}
+
+TestScript1_Helper.prototype.GetX = function() {
+ return AdditionHelper(1, 2);
+};
+
+Engine.RegisterComponentType(IID_Test1, "TestScript1_Helper", TestScript1_Helper);
diff --git a/binaries/data/mods/_test.sim/simulation/components/test-hotload1.js b/binaries/data/mods/_test.sim/simulation/components/test-hotload1.js
new file mode 100644
index 0000000000..a94774fb7f
--- /dev/null
+++ b/binaries/data/mods/_test.sim/simulation/components/test-hotload1.js
@@ -0,0 +1,23 @@
+function HotloadA() {}
+
+HotloadA.prototype.Init = function() {
+ this.x = +this.template.x;
+};
+
+HotloadA.prototype.GetX = function() {
+ return this.x;
+};
+
+Engine.RegisterComponentType(IID_Test1, "HotloadA", HotloadA);
+
+function HotloadB() {}
+
+HotloadB.prototype.Init = function() {
+ this.x = +this.template.x;
+};
+
+HotloadB.prototype.GetX = function() {
+ return this.x*2;
+};
+
+Engine.RegisterComponentType(IID_Test1, "HotloadB", HotloadB);
\ No newline at end of file
diff --git a/binaries/data/mods/_test.sim/simulation/components/test-hotload2.js b/binaries/data/mods/_test.sim/simulation/components/test-hotload2.js
new file mode 100644
index 0000000000..8f4690093b
--- /dev/null
+++ b/binaries/data/mods/_test.sim/simulation/components/test-hotload2.js
@@ -0,0 +1,11 @@
+function HotloadA() {}
+
+HotloadA.prototype.Init = function() {
+ this.x = +this.template.x;
+};
+
+HotloadA.prototype.GetX = function() {
+ return this.x*10;
+};
+
+Engine.RegisterComponentType(IID_Test1, "HotloadA", HotloadA);
diff --git a/binaries/data/mods/_test.sim/simulation/components/test-msg.js b/binaries/data/mods/_test.sim/simulation/components/test-msg.js
new file mode 100644
index 0000000000..f00949c864
--- /dev/null
+++ b/binaries/data/mods/_test.sim/simulation/components/test-msg.js
@@ -0,0 +1,32 @@
+function TestScript1A() {}
+
+TestScript1A.prototype.Init = function() {
+ this.x = 100;
+};
+
+TestScript1A.prototype.GetX = function() {
+ return this.x;
+};
+
+TestScript1A.prototype.OnUpdate = function(msg) {
+ this.x += msg.turnLength;
+}
+
+Engine.RegisterComponentType(IID_Test1, "TestScript1A", TestScript1A);
+
+// -------- //
+
+function TestScript2A() {}
+
+TestScript2A.prototype.Init = function() {
+ this.x = 200;
+};
+
+TestScript2A.prototype.GetX = function() {
+ Engine.BroadcastMessage(MT_Update, { turnLength: 50 });
+ Engine.PostMessage(1, MT_Update, { turnLength: 500 });
+ Engine.PostMessage(2, MT_Update, { turnLength: 5000 });
+ return this.x;
+};
+
+Engine.RegisterComponentType(IID_Test2, "TestScript2A", TestScript2A);
diff --git a/binaries/data/mods/_test.sim/simulation/components/test-param.js b/binaries/data/mods/_test.sim/simulation/components/test-param.js
new file mode 100644
index 0000000000..de3bb1e2ca
--- /dev/null
+++ b/binaries/data/mods/_test.sim/simulation/components/test-param.js
@@ -0,0 +1,31 @@
+function TestScript1_Init() {}
+
+TestScript1_Init.prototype.Init = function() {
+ var param = this.template;
+// print("# ",uneval(param),"\n");
+ if (param)
+ this.x = (+param.x) + (+param.y._string) + (+param.y.z['@w']) + (+param.y.z.a);
+ else
+ this.x = 100;
+};
+
+TestScript1_Init.prototype.GetX = function() {
+ return this.x;
+};
+
+Engine.RegisterComponentType(IID_Test1, "TestScript1_Init", TestScript1_Init);
+
+// -------- //
+
+function TestScript1_readonly() {}
+
+TestScript1_readonly.prototype.GetX = function() {
+ this.template = null;
+ delete this.template;
+ try { this.template.x += 1000; } catch(e) { }
+ try { delete this.template.x; } catch(e) { }
+ try { this.template.y = 2000; } catch(e) { }
+ return +(this.template.x || 1) + +(this.template.y || 2);
+};
+
+Engine.RegisterComponentType(IID_Test1, "TestScript1_readonly", TestScript1_readonly);
diff --git a/binaries/data/mods/_test.sim/simulation/components/test-query.js b/binaries/data/mods/_test.sim/simulation/components/test-query.js
new file mode 100644
index 0000000000..c33be54e67
--- /dev/null
+++ b/binaries/data/mods/_test.sim/simulation/components/test-query.js
@@ -0,0 +1,26 @@
+function TestScript1A() {}
+
+TestScript1A.prototype.Init = function() {
+ this.x = 100;
+};
+
+TestScript1A.prototype.GetX = function() {
+ var test2 = Engine.QueryInterface(this.entity, IID_Test2);
+ return test2.GetX() + (test2.x || 0);
+};
+
+Engine.RegisterComponentType(IID_Test1, "TestScript1A", TestScript1A);
+
+// -------- //
+
+function TestScript2A() {}
+
+TestScript2A.prototype.Init = function() {
+ this.x = 200;
+};
+
+TestScript2A.prototype.GetX = function() {
+ return this.x;
+};
+
+Engine.RegisterComponentType(IID_Test2, "TestScript2A", TestScript2A);
diff --git a/binaries/data/mods/_test.sim/simulation/components/test-serialize.js b/binaries/data/mods/_test.sim/simulation/components/test-serialize.js
new file mode 100644
index 0000000000..64cbeb7ca6
--- /dev/null
+++ b/binaries/data/mods/_test.sim/simulation/components/test-serialize.js
@@ -0,0 +1,68 @@
+function TestScript1_values() {}
+
+TestScript1_values.prototype.Init = function() {
+ this.x = +this.template.x;
+ this.str = "this is a string";
+ this.things = { a: 1, b: "2", c: [3, "4", [5, []]] };
+};
+
+TestScript1_values.prototype.GetX = function() {
+// print(uneval(this));
+ return this.x;
+};
+
+Engine.RegisterComponentType(IID_Test1, "TestScript1_values", TestScript1_values);
+
+// -------- //
+
+function TestScript1_entity() {}
+
+TestScript1_entity.prototype.GetX = function() {
+ // Test that .entity is readonly
+ delete this.entity;
+ this.entity = -1;
+
+ // and return the value
+ return this.entity;
+};
+
+Engine.RegisterComponentType(IID_Test1, "TestScript1_entity", TestScript1_entity);
+
+// -------- //
+
+function TestScript1_nontree() {}
+
+TestScript1_nontree.prototype.Init = function() {
+ var n = [1];
+ this.x = [n, n, null, { y: n }];
+ this.x[2] = this.x;
+};
+
+TestScript1_nontree.prototype.GetX = function() {
+// print(uneval(this)+"\n");
+ this.x[0][0] += 1;
+ return this.x[0][0] + this.x[1][0] + this.x[2][0][0] + this.x[3].y[0];
+}
+
+Engine.RegisterComponentType(IID_Test1, "TestScript1_nontree", TestScript1_nontree);
+
+// -------- //
+
+function TestScript1_getter() {}
+
+TestScript1_getter.prototype.Init = function() {
+ this.x = 100;
+ this.__defineGetter__('x', function () { return 200; });
+};
+
+Engine.RegisterComponentType(IID_Test1, "TestScript1_getter", TestScript1_getter);
+
+// -------- //
+
+function TestScript1_consts() {}
+
+TestScript1_consts.prototype.GetX = function() {
+ return (+this.entity) + (+this.template.x);
+};
+
+Engine.RegisterComponentType(IID_Test1, "TestScript1_consts", TestScript1_consts);
diff --git a/binaries/data/mods/_test.sim/simulation/components/test.js b/binaries/data/mods/_test.sim/simulation/components/test.js
new file mode 100644
index 0000000000..479427a5ba
--- /dev/null
+++ b/binaries/data/mods/_test.sim/simulation/components/test.js
@@ -0,0 +1,45 @@
+function TestScript1A() {}
+
+TestScript1A.prototype.Init = function() {
+ this.x = 101000;
+};
+
+TestScript1A.prototype.GetX = function() {
+ return this.x;
+};
+
+TestScript1A.prototype.OnTurnStart = function(msg) {
+ this.x += 1;
+};
+
+Engine.RegisterComponentType(IID_Test1, "TestScript1A", TestScript1A);
+
+// -------- //
+
+function TestScript1B() {}
+
+TestScript1B.prototype = new TestScript1A();
+
+TestScript1B.prototype.Init = function() {
+ this.x = 102000;
+};
+
+Engine.RegisterComponentType(IID_Test1, "TestScript1B", TestScript1B);
+
+// -------- //
+
+function TestScript2A() {}
+
+TestScript2A.prototype.Init = function() {
+ this.x = 201000;
+};
+
+TestScript2A.prototype.GetX = function() {
+ return this.x;
+};
+
+TestScript2A.prototype.OnUpdate = function(msg) {
+ this.x += msg.turnLength;
+};
+
+Engine.RegisterComponentType(IID_Test2, "TestScript2A", TestScript2A);
diff --git a/binaries/data/mods/_test.sim/simulation/helpers/test-helper.js b/binaries/data/mods/_test.sim/simulation/helpers/test-helper.js
new file mode 100644
index 0000000000..2ce1940d13
--- /dev/null
+++ b/binaries/data/mods/_test.sim/simulation/helpers/test-helper.js
@@ -0,0 +1,5 @@
+function AdditionHelper(a, b) {
+ return a+b;
+}
+
+Engine.RegisterGlobal("AdditionHelper", AdditionHelper);
diff --git a/binaries/data/mods/_test.sim/simulation/templates/basic.xml b/binaries/data/mods/_test.sim/simulation/templates/basic.xml
new file mode 100644
index 0000000000..b876138c01
--- /dev/null
+++ b/binaries/data/mods/_test.sim/simulation/templates/basic.xml
@@ -0,0 +1,4 @@
+
+
+ 12345
+
diff --git a/binaries/data/mods/_test.sim/simulation/templates/hotload.xml b/binaries/data/mods/_test.sim/simulation/templates/hotload.xml
new file mode 100644
index 0000000000..3be131ca8b
--- /dev/null
+++ b/binaries/data/mods/_test.sim/simulation/templates/hotload.xml
@@ -0,0 +1,6 @@
+
+
+
+ 100
+
+
diff --git a/binaries/data/mods/_test.sim/simulation/templates/inherit-broken.xml b/binaries/data/mods/_test.sim/simulation/templates/inherit-broken.xml
new file mode 100644
index 0000000000..f3af209480
--- /dev/null
+++ b/binaries/data/mods/_test.sim/simulation/templates/inherit-broken.xml
@@ -0,0 +1,2 @@
+
+broken
diff --git a/binaries/data/mods/_test.sim/simulation/templates/inherit-loop-2.xml b/binaries/data/mods/_test.sim/simulation/templates/inherit-loop-2.xml
new file mode 100644
index 0000000000..960984546a
--- /dev/null
+++ b/binaries/data/mods/_test.sim/simulation/templates/inherit-loop-2.xml
@@ -0,0 +1,2 @@
+
+loop-2
diff --git a/binaries/data/mods/_test.sim/simulation/templates/inherit-loop.xml b/binaries/data/mods/_test.sim/simulation/templates/inherit-loop.xml
new file mode 100644
index 0000000000..85fc6ecc62
--- /dev/null
+++ b/binaries/data/mods/_test.sim/simulation/templates/inherit-loop.xml
@@ -0,0 +1,2 @@
+
+loop
diff --git a/binaries/data/mods/_test.sim/simulation/templates/inherit1.xml b/binaries/data/mods/_test.sim/simulation/templates/inherit1.xml
new file mode 100644
index 0000000000..c25d0b9a6a
--- /dev/null
+++ b/binaries/data/mods/_test.sim/simulation/templates/inherit1.xml
@@ -0,0 +1,8 @@
+
+
+
+ d1
+ e1
+ f1
+
+
diff --git a/binaries/data/mods/_test.sim/simulation/templates/inherit2.xml b/binaries/data/mods/_test.sim/simulation/templates/inherit2.xml
new file mode 100644
index 0000000000..a9b1f8375e
--- /dev/null
+++ b/binaries/data/mods/_test.sim/simulation/templates/inherit2.xml
@@ -0,0 +1,7 @@
+
+
+
+ d2
+ g2
+
+
diff --git a/binaries/data/mods/_test.sim/simulation/templates/template-serialize.xml b/binaries/data/mods/_test.sim/simulation/templates/template-serialize.xml
new file mode 100644
index 0000000000..d0861e0d6d
--- /dev/null
+++ b/binaries/data/mods/_test.sim/simulation/templates/template-serialize.xml
@@ -0,0 +1,4 @@
+
+
+ 12345
+
diff --git a/binaries/data/mods/_test.sim/simulation/templates/test1-inherit.xml b/binaries/data/mods/_test.sim/simulation/templates/test1-inherit.xml
new file mode 100644
index 0000000000..f2b142b171
--- /dev/null
+++ b/binaries/data/mods/_test.sim/simulation/templates/test1-inherit.xml
@@ -0,0 +1,6 @@
+
+
+
+ 1234
+
+
diff --git a/binaries/data/mods/_test.sim/simulation/templates/test1.xml b/binaries/data/mods/_test.sim/simulation/templates/test1.xml
new file mode 100644
index 0000000000..43a8b846f1
--- /dev/null
+++ b/binaries/data/mods/_test.sim/simulation/templates/test1.xml
@@ -0,0 +1,9 @@
+
+
+
+ 999
+
+
+ (600+17)*20+5
+
+
diff --git a/binaries/data/mods/public/gui/common/functions_global_object.js b/binaries/data/mods/public/gui/common/functions_global_object.js
index 85dc99956c..e7a4194e44 100644
--- a/binaries/data/mods/public/gui/common/functions_global_object.js
+++ b/binaries/data/mods/public/gui/common/functions_global_object.js
@@ -14,7 +14,7 @@
function messageBox (mbWidth, mbHeight, mbMessage, mbTitle, mbMode, mbButtonCaptions, mbButtonsCode)
{
- pushGuiPage("page_msgbox.xml", {
+ Engine.PushGuiPage("page_msgbox.xml", {
width: mbWidth,
height: mbHeight,
message: mbMessage,
diff --git a/binaries/data/mods/public/gui/common/functions_page_pregame_load.js b/binaries/data/mods/public/gui/common/functions_page_pregame_load.js
index f555ab93a7..0c069a5c86 100644
--- a/binaries/data/mods/public/gui/common/functions_page_pregame_load.js
+++ b/binaries/data/mods/public/gui/common/functions_page_pregame_load.js
@@ -39,7 +39,7 @@ function launchGame ()
closeMainMenuSubWindow ("pgSessionSetup");
// Display loading screen.
- switchGuiPage("page_loading.xml");
+ Engine.SwitchGuiPage("page_loading.xml");
console.write( "running startGame()" );
@@ -47,7 +47,7 @@ function launchGame ()
if (! startGame())
{
// Failed to start the game; go back to the main menu.
- switchGuiPage("page_pregame.xml");
+ Engine.SwitchGuiPage("page_pregame.xml");
// Restore default cursor.
setCursor ("arrow-default");
// Show an error message
diff --git a/binaries/data/mods/public/gui/common/setup.xml b/binaries/data/mods/public/gui/common/setup.xml
index 58b4af5b89..0371a13edb 100644
--- a/binaries/data/mods/public/gui/common/setup.xml
+++ b/binaries/data/mods/public/gui/common/setup.xml
@@ -146,43 +146,19 @@
==========================================
-->
- 0 0 0
-
+ 0 0 0
+ 255 255 255
+ 255 0 0
+ 0 0 255
+ 255 255 0
- 237 227 167
-
+ 237 227 167
+ 243 242 240
+ 43 42 40
+ 0 200 0
+ 191 191 2
+ 159 98 24
- 255 255 255
-
-
- 243 242 240
-
-
- 43 42 40
-
-
- 0 0 255
-
-
- 0 200 0
-
-
- 191 191 2
-
-
- 159 98 24
-
-
-
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/binaries/data/mods/public/simulation/components/GuiInterface.js b/binaries/data/mods/public/simulation/components/GuiInterface.js
new file mode 100644
index 0000000000..dcd097c0ff
--- /dev/null
+++ b/binaries/data/mods/public/simulation/components/GuiInterface.js
@@ -0,0 +1,31 @@
+function GuiInterface() {}
+
+GuiInterface.prototype.Init = function() {};
+
+GuiInterface.prototype.GetSimulationState = function(player)
+{
+// print("GetSimulationState "+player+"\n");
+
+ return { test: "simulation state" };
+};
+
+GuiInterface.prototype.GetEntityState = function(player, ent)
+{
+// print("GetEntityState "+player+" "+ent+"\n");
+
+ var cmpPosition = Engine.QueryInterface(ent, IID_Position);
+
+ var ret = {
+ position: cmpPosition.GetPosition()
+ };
+
+ return ret;
+};
+
+GuiInterface.prototype.SetSelectionHighlight = function(ent, colour)
+{
+ var cmpSelectable = Engine.QueryInterface(ent, IID_Selectable);
+ cmpSelectable.SetSelectionHighlight(colour);
+};
+
+Engine.RegisterComponentType(IID_GuiInterface, "GuiInterface", GuiInterface);
diff --git a/binaries/data/mods/public/simulation/components/MotionBall.js b/binaries/data/mods/public/simulation/components/MotionBall.js
new file mode 100644
index 0000000000..e985b9d719
--- /dev/null
+++ b/binaries/data/mods/public/simulation/components/MotionBall.js
@@ -0,0 +1,32 @@
+function MotionBallScripted() {}
+
+MotionBallScripted.prototype.Init = function() {
+ this.speedX = 0;
+ this.speedZ = 0;
+};
+
+MotionBallScripted.prototype.OnUpdate = function(msg) {
+ var dt = msg.turnLength;
+
+ var cmpPos = Engine.QueryInterface(this.entity, IID_Position);
+ var cmpTerrain = Engine.QueryInterface(SYSTEM_ENTITY, IID_Terrain);
+
+ var pos = cmpPos.GetPosition();
+
+ var normal = cmpTerrain.CalcNormal(pos.x, pos.z);
+
+ var g = 10;
+ var forceX = normal.x * g;
+ var forceZ = normal.z * g;
+
+ this.speedX += forceX * dt;
+ this.speedZ += forceZ * dt;
+
+ var drag = 0.5; // fractional decay per second
+ this.speedX *= Math.pow(drag, dt);
+ this.speedZ *= Math.pow(drag, dt);
+
+ cmpPos.MoveTo(pos.x + this.speedX * dt, pos.z + this.speedZ * dt);
+};
+
+Engine.RegisterComponentType(IID_Motion, "MotionBallScripted", MotionBallScripted);
diff --git a/binaries/data/mods/public/simulation/components/tests/setup.js b/binaries/data/mods/public/simulation/components/tests/setup.js
new file mode 100644
index 0000000000..35b3d2af31
--- /dev/null
+++ b/binaries/data/mods/public/simulation/components/tests/setup.js
@@ -0,0 +1,38 @@
+var g_ComponentTypes = {};
+var g_Components = {};
+
+// Emulate some engine functions:
+
+Engine.RegisterComponentType = function(iid, name, ctor)
+{
+ TS_ASSERT(!g_ComponentTypes[name]);
+ g_ComponentTypes[name] = { iid: iid, ctor: ctor };
+}
+
+Engine.QueryInterface = function(ent, iid)
+{
+ if (g_Components[ent] && g_Components[ent][iid])
+ return g_Components[ent][iid];
+ return null;
+}
+
+// TODO:
+// Engine.RegisterGlobal
+// Engine.PostMessage
+// Engine.BroadcastMessage
+
+global.AddMock = function(ent, iid, mock)
+{
+ if (!g_Components[ent])
+ g_Components[ent] = {};
+ g_Components[ent][iid] = mock;
+}
+
+global.ConstructComponent = function(ent, name, template)
+{
+ var cmp = new g_ComponentTypes[name].ctor();
+ cmp.entity = ent;
+ cmp.template = template;
+ cmp.Init();
+ return cmp;
+}
diff --git a/binaries/data/mods/public/simulation/components/tests/test_GuiInterface.js b/binaries/data/mods/public/simulation/components/tests/test_GuiInterface.js
new file mode 100644
index 0000000000..066bedb2ff
--- /dev/null
+++ b/binaries/data/mods/public/simulation/components/tests/test_GuiInterface.js
@@ -0,0 +1,14 @@
+Engine.LoadComponentScript("GuiInterface.js");
+
+var cmp = ConstructComponent(SYSTEM_ENTITY, "GuiInterface");
+
+TS_ASSERT_UNEVAL_EQUALS(cmp.GetSimulationState(), { test: "simulation state" });
+
+AddMock(10, IID_Position, {
+ GetPosition: function() {
+ return {x:1, y:2, z:3};
+ },
+});
+
+var state = cmp.GetEntityState(-1, 10);
+TS_ASSERT_UNEVAL_EQUALS(state, { position: {x:1, y:2, z:3} });
diff --git a/binaries/data/mods/public/simulation/helpers/Commands.js b/binaries/data/mods/public/simulation/helpers/Commands.js
new file mode 100644
index 0000000000..b55a4c4ca7
--- /dev/null
+++ b/binaries/data/mods/public/simulation/helpers/Commands.js
@@ -0,0 +1,30 @@
+function ProcessCommand(player, cmd)
+{
+// print("command: " + player + " " + uneval(cmd) + "\n");
+
+ switch (cmd.type)
+ {
+ case "spin":
+ for each (var ent in cmd.entities)
+ {
+ var pos = Engine.QueryInterface(ent, IID_Position);
+ if (! pos)
+ continue;
+ pos.SetYRotation(pos.GetRotation().y + 1);
+ }
+ break;
+ case "walk":
+ for each (var ent in cmd.entities)
+ {
+ var motion = Engine.QueryInterface(ent, IID_UnitMotion);
+ if (! motion)
+ continue;
+ motion.MoveToPoint(cmd.x, cmd.z);
+ }
+ break;
+ default:
+ print("Ignoring unrecognised command type '" + cmd.type + "'\n");
+ }
+}
+
+Engine.RegisterGlobal("ProcessCommand", ProcessCommand);
diff --git a/binaries/data/mods/public/simulation/templates/foundation_1x1.xml b/binaries/data/mods/public/simulation/templates/foundation_1x1.xml
new file mode 100644
index 0000000000..6502639929
--- /dev/null
+++ b/binaries/data/mods/public/simulation/templates/foundation_1x1.xml
@@ -0,0 +1,6 @@
+
+
+
+ structures/fndn_1x1.xml
+
+
diff --git a/binaries/data/mods/public/simulation/templates/foundation_2x2.xml b/binaries/data/mods/public/simulation/templates/foundation_2x2.xml
new file mode 100644
index 0000000000..474fd197c8
--- /dev/null
+++ b/binaries/data/mods/public/simulation/templates/foundation_2x2.xml
@@ -0,0 +1,6 @@
+
+
+
+ structures/fndn_2x2.xml
+
+
diff --git a/binaries/data/mods/public/simulation/templates/foundation_3x3.xml b/binaries/data/mods/public/simulation/templates/foundation_3x3.xml
new file mode 100644
index 0000000000..c45c6fd324
--- /dev/null
+++ b/binaries/data/mods/public/simulation/templates/foundation_3x3.xml
@@ -0,0 +1,6 @@
+
+
+
+ structures/fndn_3x3.xml
+
+
diff --git a/binaries/data/mods/public/simulation/templates/foundation_3x6.xml b/binaries/data/mods/public/simulation/templates/foundation_3x6.xml
new file mode 100644
index 0000000000..dbb6d9d8a4
--- /dev/null
+++ b/binaries/data/mods/public/simulation/templates/foundation_3x6.xml
@@ -0,0 +1,6 @@
+
+
+
+ structures/fndn_3x6.xml
+
+
diff --git a/binaries/data/mods/public/simulation/templates/foundation_4x4.xml b/binaries/data/mods/public/simulation/templates/foundation_4x4.xml
new file mode 100644
index 0000000000..ecc1e88078
--- /dev/null
+++ b/binaries/data/mods/public/simulation/templates/foundation_4x4.xml
@@ -0,0 +1,6 @@
+
+
+
+ structures/fndn_4x4.xml
+
+
diff --git a/binaries/data/mods/public/simulation/templates/foundation_5x5.xml b/binaries/data/mods/public/simulation/templates/foundation_5x5.xml
new file mode 100644
index 0000000000..40531dd185
--- /dev/null
+++ b/binaries/data/mods/public/simulation/templates/foundation_5x5.xml
@@ -0,0 +1,6 @@
+
+
+
+ structures/fndn_5x5.xml
+
+
diff --git a/binaries/data/mods/public/simulation/templates/foundation_6x6.xml b/binaries/data/mods/public/simulation/templates/foundation_6x6.xml
new file mode 100644
index 0000000000..e9a1e304c8
--- /dev/null
+++ b/binaries/data/mods/public/simulation/templates/foundation_6x6.xml
@@ -0,0 +1,6 @@
+
+
+
+ structures/fndn_6x6.xml
+
+
diff --git a/binaries/data/mods/public/simulation/templates/foundation_field.xml b/binaries/data/mods/public/simulation/templates/foundation_field.xml
new file mode 100644
index 0000000000..787a715c9c
--- /dev/null
+++ b/binaries/data/mods/public/simulation/templates/foundation_field.xml
@@ -0,0 +1,6 @@
+
+
+
+ structures/plot_field_found.xml
+
+
diff --git a/binaries/data/mods/public/simulation/templates/foundation_theatron.xml b/binaries/data/mods/public/simulation/templates/foundation_theatron.xml
new file mode 100644
index 0000000000..71aecfbd52
--- /dev/null
+++ b/binaries/data/mods/public/simulation/templates/foundation_theatron.xml
@@ -0,0 +1,6 @@
+
+
+
+ structures/fndn_theatron.xml
+
+
diff --git a/binaries/data/mods/public/simulation/templates/gaia/fauna_bear.xml b/binaries/data/mods/public/simulation/templates/gaia/fauna_bear.xml
new file mode 100644
index 0000000000..ea92fe2368
--- /dev/null
+++ b/binaries/data/mods/public/simulation/templates/gaia/fauna_bear.xml
@@ -0,0 +1,6 @@
+
+
+
+ fauna/bear.xml
+
+
diff --git a/binaries/data/mods/public/simulation/templates/gaia/fauna_boar.xml b/binaries/data/mods/public/simulation/templates/gaia/fauna_boar.xml
new file mode 100644
index 0000000000..5aff076f0c
--- /dev/null
+++ b/binaries/data/mods/public/simulation/templates/gaia/fauna_boar.xml
@@ -0,0 +1,6 @@
+
+
+
+ fauna/boar.xml
+
+
diff --git a/binaries/data/mods/public/simulation/templates/gaia/fauna_chicken.xml b/binaries/data/mods/public/simulation/templates/gaia/fauna_chicken.xml
new file mode 100644
index 0000000000..bea18ff0ac
--- /dev/null
+++ b/binaries/data/mods/public/simulation/templates/gaia/fauna_chicken.xml
@@ -0,0 +1,6 @@
+
+
+
+ fauna/chicken.xml
+
+
diff --git a/binaries/data/mods/public/simulation/templates/gaia/fauna_deer.xml b/binaries/data/mods/public/simulation/templates/gaia/fauna_deer.xml
new file mode 100644
index 0000000000..1567f987a0
--- /dev/null
+++ b/binaries/data/mods/public/simulation/templates/gaia/fauna_deer.xml
@@ -0,0 +1,6 @@
+
+
+
+ fauna/deer.xml
+
+
diff --git a/binaries/data/mods/public/simulation/templates/gaia/fauna_elephant.xml b/binaries/data/mods/public/simulation/templates/gaia/fauna_elephant.xml
new file mode 100644
index 0000000000..18bbc6a71d
--- /dev/null
+++ b/binaries/data/mods/public/simulation/templates/gaia/fauna_elephant.xml
@@ -0,0 +1,6 @@
+
+
+
+ fauna/elephant.xml
+
+
diff --git a/binaries/data/mods/public/simulation/templates/gaia/fauna_elephant_african_bush.xml b/binaries/data/mods/public/simulation/templates/gaia/fauna_elephant_african_bush.xml
new file mode 100644
index 0000000000..bb0f9b0e28
--- /dev/null
+++ b/binaries/data/mods/public/simulation/templates/gaia/fauna_elephant_african_bush.xml
@@ -0,0 +1,6 @@
+
+
+
+ fauna/elephant_african_bush.xml
+
+
diff --git a/binaries/data/mods/public/simulation/templates/gaia/fauna_elephant_african_infant.xml b/binaries/data/mods/public/simulation/templates/gaia/fauna_elephant_african_infant.xml
new file mode 100644
index 0000000000..2bde08823b
--- /dev/null
+++ b/binaries/data/mods/public/simulation/templates/gaia/fauna_elephant_african_infant.xml
@@ -0,0 +1,6 @@
+
+
+
+ fauna/elephant_african_baby.xml
+
+
diff --git a/binaries/data/mods/public/simulation/templates/gaia/fauna_elephant_north_african.xml b/binaries/data/mods/public/simulation/templates/gaia/fauna_elephant_north_african.xml
new file mode 100644
index 0000000000..0cf339af63
--- /dev/null
+++ b/binaries/data/mods/public/simulation/templates/gaia/fauna_elephant_north_african.xml
@@ -0,0 +1,6 @@
+
+
+
+ fauna/elephant_african_forest.xml
+
+
diff --git a/binaries/data/mods/public/simulation/templates/gaia/fauna_gazelle.xml b/binaries/data/mods/public/simulation/templates/gaia/fauna_gazelle.xml
new file mode 100644
index 0000000000..6a208fb583
--- /dev/null
+++ b/binaries/data/mods/public/simulation/templates/gaia/fauna_gazelle.xml
@@ -0,0 +1,6 @@
+
+
+
+ fauna/gazelle.xml
+
+
diff --git a/binaries/data/mods/public/simulation/templates/gaia/fauna_goat.xml b/binaries/data/mods/public/simulation/templates/gaia/fauna_goat.xml
new file mode 100644
index 0000000000..232418280f
--- /dev/null
+++ b/binaries/data/mods/public/simulation/templates/gaia/fauna_goat.xml
@@ -0,0 +1,6 @@
+
+
+
+ fauna/goat.xml
+
+
diff --git a/binaries/data/mods/public/simulation/templates/gaia/fauna_lion.xml b/binaries/data/mods/public/simulation/templates/gaia/fauna_lion.xml
new file mode 100644
index 0000000000..7ec14e2041
--- /dev/null
+++ b/binaries/data/mods/public/simulation/templates/gaia/fauna_lion.xml
@@ -0,0 +1,6 @@
+
+
+
+ fauna/lion.xml
+
+
diff --git a/binaries/data/mods/public/simulation/templates/gaia/fauna_muskox.xml b/binaries/data/mods/public/simulation/templates/gaia/fauna_muskox.xml
new file mode 100644
index 0000000000..a0c3dc7f46
--- /dev/null
+++ b/binaries/data/mods/public/simulation/templates/gaia/fauna_muskox.xml
@@ -0,0 +1,6 @@
+
+
+
+ fauna/muskox.xml
+
+
diff --git a/binaries/data/mods/public/simulation/templates/gaia/fauna_pig.xml b/binaries/data/mods/public/simulation/templates/gaia/fauna_pig.xml
new file mode 100644
index 0000000000..39f2a710e7
--- /dev/null
+++ b/binaries/data/mods/public/simulation/templates/gaia/fauna_pig.xml
@@ -0,0 +1,6 @@
+
+
+
+ fauna/pig1.xml
+
+
diff --git a/binaries/data/mods/public/simulation/templates/gaia/fauna_rabbit.xml b/binaries/data/mods/public/simulation/templates/gaia/fauna_rabbit.xml
new file mode 100644
index 0000000000..1be8aa1824
--- /dev/null
+++ b/binaries/data/mods/public/simulation/templates/gaia/fauna_rabbit.xml
@@ -0,0 +1,6 @@
+
+
+
+ fauna/rabbit1.xml
+
+
diff --git a/binaries/data/mods/public/simulation/templates/gaia/fauna_sheep.xml b/binaries/data/mods/public/simulation/templates/gaia/fauna_sheep.xml
new file mode 100644
index 0000000000..0132895212
--- /dev/null
+++ b/binaries/data/mods/public/simulation/templates/gaia/fauna_sheep.xml
@@ -0,0 +1,6 @@
+
+
+
+ fauna/sheep1.xml
+
+
diff --git a/binaries/data/mods/public/simulation/templates/gaia/fauna_tiger.xml b/binaries/data/mods/public/simulation/templates/gaia/fauna_tiger.xml
new file mode 100644
index 0000000000..3afe1160aa
--- /dev/null
+++ b/binaries/data/mods/public/simulation/templates/gaia/fauna_tiger.xml
@@ -0,0 +1,6 @@
+
+
+
+ fauna/tiger.xml
+
+
diff --git a/binaries/data/mods/public/simulation/templates/gaia/fauna_walrus.xml b/binaries/data/mods/public/simulation/templates/gaia/fauna_walrus.xml
new file mode 100644
index 0000000000..670b767833
--- /dev/null
+++ b/binaries/data/mods/public/simulation/templates/gaia/fauna_walrus.xml
@@ -0,0 +1,6 @@
+
+
+
+ fauna/walrus.xml
+
+
diff --git a/binaries/data/mods/public/simulation/templates/gaia/fauna_wolf.xml b/binaries/data/mods/public/simulation/templates/gaia/fauna_wolf.xml
new file mode 100644
index 0000000000..62094494e1
--- /dev/null
+++ b/binaries/data/mods/public/simulation/templates/gaia/fauna_wolf.xml
@@ -0,0 +1,6 @@
+
+
+
+ fauna/wolf.xml
+
+
diff --git a/binaries/data/mods/public/simulation/templates/gaia/fauna_wolf_snow.xml b/binaries/data/mods/public/simulation/templates/gaia/fauna_wolf_snow.xml
new file mode 100644
index 0000000000..b887642414
--- /dev/null
+++ b/binaries/data/mods/public/simulation/templates/gaia/fauna_wolf_snow.xml
@@ -0,0 +1,6 @@
+
+
+
+ fauna/wolf_snow.xml
+
+
diff --git a/binaries/data/mods/public/simulation/templates/gaia/fauna_zebra.xml b/binaries/data/mods/public/simulation/templates/gaia/fauna_zebra.xml
new file mode 100644
index 0000000000..5fec6086a0
--- /dev/null
+++ b/binaries/data/mods/public/simulation/templates/gaia/fauna_zebra.xml
@@ -0,0 +1,6 @@
+
+
+
+ fauna/zebra.xml
+
+
diff --git a/binaries/data/mods/public/simulation/templates/gaia/flora_bush_berry.xml b/binaries/data/mods/public/simulation/templates/gaia/flora_bush_berry.xml
new file mode 100644
index 0000000000..c568e52e0a
--- /dev/null
+++ b/binaries/data/mods/public/simulation/templates/gaia/flora_bush_berry.xml
@@ -0,0 +1,6 @@
+
+
+
+ props/flora/foliagebush.xml
+
+
diff --git a/binaries/data/mods/public/simulation/templates/gaia/flora_bush_temperate.xml b/binaries/data/mods/public/simulation/templates/gaia/flora_bush_temperate.xml
new file mode 100644
index 0000000000..7c41ef4090
--- /dev/null
+++ b/binaries/data/mods/public/simulation/templates/gaia/flora_bush_temperate.xml
@@ -0,0 +1,6 @@
+
+
+
+ props/flora/bush_tempe_a.xml
+
+
diff --git a/binaries/data/mods/public/simulation/templates/gaia/flora_tree_aleppo_pine.xml b/binaries/data/mods/public/simulation/templates/gaia/flora_tree_aleppo_pine.xml
new file mode 100644
index 0000000000..d8395ce01e
--- /dev/null
+++ b/binaries/data/mods/public/simulation/templates/gaia/flora_tree_aleppo_pine.xml
@@ -0,0 +1,6 @@
+
+
+
+ flora/trees/aleppo_pine.xml
+
+
diff --git a/binaries/data/mods/public/simulation/templates/gaia/flora_tree_baobab.xml b/binaries/data/mods/public/simulation/templates/gaia/flora_tree_baobab.xml
new file mode 100644
index 0000000000..d48c971686
--- /dev/null
+++ b/binaries/data/mods/public/simulation/templates/gaia/flora_tree_baobab.xml
@@ -0,0 +1,6 @@
+
+
+
+ flora/trees/baobab.xml
+
+
diff --git a/binaries/data/mods/public/simulation/templates/gaia/flora_tree_carob.xml b/binaries/data/mods/public/simulation/templates/gaia/flora_tree_carob.xml
new file mode 100644
index 0000000000..e19c4b1cc0
--- /dev/null
+++ b/binaries/data/mods/public/simulation/templates/gaia/flora_tree_carob.xml
@@ -0,0 +1,6 @@
+
+
+
+ flora/trees/carob.xml
+
+
diff --git a/binaries/data/mods/public/simulation/templates/gaia/flora_tree_date_palm.xml b/binaries/data/mods/public/simulation/templates/gaia/flora_tree_date_palm.xml
new file mode 100644
index 0000000000..14f5904a0f
--- /dev/null
+++ b/binaries/data/mods/public/simulation/templates/gaia/flora_tree_date_palm.xml
@@ -0,0 +1,6 @@
+
+
+
+ flora/trees/palm_date.xml
+
+
diff --git a/binaries/data/mods/public/simulation/templates/gaia/flora_tree_euro_beech.xml b/binaries/data/mods/public/simulation/templates/gaia/flora_tree_euro_beech.xml
new file mode 100644
index 0000000000..5f56bcf2e5
--- /dev/null
+++ b/binaries/data/mods/public/simulation/templates/gaia/flora_tree_euro_beech.xml
@@ -0,0 +1,6 @@
+
+
+
+ flora/trees/european_beech.xml
+
+
diff --git a/binaries/data/mods/public/simulation/templates/gaia/flora_tree_medit_fan_palm.xml b/binaries/data/mods/public/simulation/templates/gaia/flora_tree_medit_fan_palm.xml
new file mode 100644
index 0000000000..5bdd97eae9
--- /dev/null
+++ b/binaries/data/mods/public/simulation/templates/gaia/flora_tree_medit_fan_palm.xml
@@ -0,0 +1,6 @@
+
+
+
+ flora/trees/palm_medit_fan_palm.xml
+
+
diff --git a/binaries/data/mods/public/simulation/templates/gaia/flora_tree_oak.xml b/binaries/data/mods/public/simulation/templates/gaia/flora_tree_oak.xml
new file mode 100644
index 0000000000..46a16175cb
--- /dev/null
+++ b/binaries/data/mods/public/simulation/templates/gaia/flora_tree_oak.xml
@@ -0,0 +1,6 @@
+
+
+
+ flora/trees/oak.xml
+
+
diff --git a/binaries/data/mods/public/simulation/templates/gaia/flora_tree_oak_large.xml b/binaries/data/mods/public/simulation/templates/gaia/flora_tree_oak_large.xml
new file mode 100644
index 0000000000..3f0dbbc009
--- /dev/null
+++ b/binaries/data/mods/public/simulation/templates/gaia/flora_tree_oak_large.xml
@@ -0,0 +1,6 @@
+
+
+
+ flora/trees/oak_large.xml
+
+
diff --git a/binaries/data/mods/public/simulation/templates/gaia/flora_tree_pine.xml b/binaries/data/mods/public/simulation/templates/gaia/flora_tree_pine.xml
new file mode 100644
index 0000000000..44b1f9da20
--- /dev/null
+++ b/binaries/data/mods/public/simulation/templates/gaia/flora_tree_pine.xml
@@ -0,0 +1,6 @@
+
+
+
+ flora/trees/pine.xml
+
+
diff --git a/binaries/data/mods/public/simulation/templates/gaia/flora_tree_pine_w.xml b/binaries/data/mods/public/simulation/templates/gaia/flora_tree_pine_w.xml
new file mode 100644
index 0000000000..efc60824e2
--- /dev/null
+++ b/binaries/data/mods/public/simulation/templates/gaia/flora_tree_pine_w.xml
@@ -0,0 +1,6 @@
+
+
+
+ flora/trees/pine_w.xml
+
+
diff --git a/binaries/data/mods/public/simulation/templates/gaia/flora_tree_poplar.xml b/binaries/data/mods/public/simulation/templates/gaia/flora_tree_poplar.xml
new file mode 100644
index 0000000000..0fc697ab89
--- /dev/null
+++ b/binaries/data/mods/public/simulation/templates/gaia/flora_tree_poplar.xml
@@ -0,0 +1,6 @@
+
+
+
+ flora/trees/poplar.xml
+
+
diff --git a/binaries/data/mods/public/simulation/templates/gaia/flora_tree_poplar_lombardy.xml b/binaries/data/mods/public/simulation/templates/gaia/flora_tree_poplar_lombardy.xml
new file mode 100644
index 0000000000..45afa52dbc
--- /dev/null
+++ b/binaries/data/mods/public/simulation/templates/gaia/flora_tree_poplar_lombardy.xml
@@ -0,0 +1,6 @@
+
+
+
+ flora/trees/lumbardypoplar.xml
+
+
diff --git a/binaries/data/mods/public/simulation/templates/gaia/flora_tree_senegal_date_palm.xml b/binaries/data/mods/public/simulation/templates/gaia/flora_tree_senegal_date_palm.xml
new file mode 100644
index 0000000000..0a5ef1faae
--- /dev/null
+++ b/binaries/data/mods/public/simulation/templates/gaia/flora_tree_senegal_date_palm.xml
@@ -0,0 +1,6 @@
+
+
+
+ flora/trees/palm_senegal_date.xml
+
+
diff --git a/binaries/data/mods/public/simulation/templates/gaia/geology_metal_alpine.xml b/binaries/data/mods/public/simulation/templates/gaia/geology_metal_alpine.xml
new file mode 100644
index 0000000000..ee9271950f
--- /dev/null
+++ b/binaries/data/mods/public/simulation/templates/gaia/geology_metal_alpine.xml
@@ -0,0 +1,6 @@
+
+
+
+ geology/metalmine_alpine.xml
+
+
diff --git a/binaries/data/mods/public/simulation/templates/gaia/geology_metal_desert_small.xml b/binaries/data/mods/public/simulation/templates/gaia/geology_metal_desert_small.xml
new file mode 100644
index 0000000000..d39885b053
--- /dev/null
+++ b/binaries/data/mods/public/simulation/templates/gaia/geology_metal_desert_small.xml
@@ -0,0 +1,6 @@
+
+
+
+ geology/metalmine_desert_small.xml
+
+
diff --git a/binaries/data/mods/public/simulation/templates/gaia/geology_metal_greek.xml b/binaries/data/mods/public/simulation/templates/gaia/geology_metal_greek.xml
new file mode 100644
index 0000000000..b9a3a8b7a1
--- /dev/null
+++ b/binaries/data/mods/public/simulation/templates/gaia/geology_metal_greek.xml
@@ -0,0 +1,6 @@
+
+
+
+ geology/metalmine_granite_greek.xml
+
+
diff --git a/binaries/data/mods/public/simulation/templates/gaia/geology_metal_mediterranean.xml b/binaries/data/mods/public/simulation/templates/gaia/geology_metal_mediterranean.xml
new file mode 100644
index 0000000000..47af0942d4
--- /dev/null
+++ b/binaries/data/mods/public/simulation/templates/gaia/geology_metal_mediterranean.xml
@@ -0,0 +1,6 @@
+
+
+
+ geology/metalmine_mediterranean.xml
+
+
diff --git a/binaries/data/mods/public/simulation/templates/gaia/geology_metal_temperate.xml b/binaries/data/mods/public/simulation/templates/gaia/geology_metal_temperate.xml
new file mode 100644
index 0000000000..739ff0c635
--- /dev/null
+++ b/binaries/data/mods/public/simulation/templates/gaia/geology_metal_temperate.xml
@@ -0,0 +1,6 @@
+
+
+
+ geology/metalmine_granite_temperate.xml
+
+
diff --git a/binaries/data/mods/public/simulation/templates/gaia/geology_metal_tropic.xml b/binaries/data/mods/public/simulation/templates/gaia/geology_metal_tropic.xml
new file mode 100644
index 0000000000..3c518b468c
--- /dev/null
+++ b/binaries/data/mods/public/simulation/templates/gaia/geology_metal_tropic.xml
@@ -0,0 +1,6 @@
+
+
+
+ geology/metalmine_tropic.xml
+
+
diff --git a/binaries/data/mods/public/simulation/templates/gaia/geology_stone_alpine_a.xml b/binaries/data/mods/public/simulation/templates/gaia/geology_stone_alpine_a.xml
new file mode 100644
index 0000000000..ab28f8f3ad
--- /dev/null
+++ b/binaries/data/mods/public/simulation/templates/gaia/geology_stone_alpine_a.xml
@@ -0,0 +1,6 @@
+
+
+
+ geology/stonemine_alpine_a.xml
+
+
diff --git a/binaries/data/mods/public/simulation/templates/gaia/geology_stone_desert_small.xml b/binaries/data/mods/public/simulation/templates/gaia/geology_stone_desert_small.xml
new file mode 100644
index 0000000000..b73cae9340
--- /dev/null
+++ b/binaries/data/mods/public/simulation/templates/gaia/geology_stone_desert_small.xml
@@ -0,0 +1,6 @@
+
+
+
+ geology/stonemine_desert_small.xml
+
+
diff --git a/binaries/data/mods/public/simulation/templates/gaia/geology_stone_greek.xml b/binaries/data/mods/public/simulation/templates/gaia/geology_stone_greek.xml
new file mode 100644
index 0000000000..d2e1126b71
--- /dev/null
+++ b/binaries/data/mods/public/simulation/templates/gaia/geology_stone_greek.xml
@@ -0,0 +1,6 @@
+
+
+
+ geology/stonemine_granite_greek.xml
+
+
diff --git a/binaries/data/mods/public/simulation/templates/gaia/geology_stone_light.xml b/binaries/data/mods/public/simulation/templates/gaia/geology_stone_light.xml
new file mode 100644
index 0000000000..e70b7bd359
--- /dev/null
+++ b/binaries/data/mods/public/simulation/templates/gaia/geology_stone_light.xml
@@ -0,0 +1,6 @@
+
+
+
+ geology/light.xml
+
+
diff --git a/binaries/data/mods/public/simulation/templates/gaia/geology_stone_mediterranean.xml b/binaries/data/mods/public/simulation/templates/gaia/geology_stone_mediterranean.xml
new file mode 100644
index 0000000000..a403b27112
--- /dev/null
+++ b/binaries/data/mods/public/simulation/templates/gaia/geology_stone_mediterranean.xml
@@ -0,0 +1,6 @@
+
+
+
+ geology/stonemine_mediterranean.xml
+
+
diff --git a/binaries/data/mods/public/simulation/templates/gaia/geology_stone_savanna_small.xml b/binaries/data/mods/public/simulation/templates/gaia/geology_stone_savanna_small.xml
new file mode 100644
index 0000000000..bcd1dadd5d
--- /dev/null
+++ b/binaries/data/mods/public/simulation/templates/gaia/geology_stone_savanna_small.xml
@@ -0,0 +1,6 @@
+
+
+
+ geology/stonemine_savanna_small.xml
+
+
diff --git a/binaries/data/mods/public/simulation/templates/gaia/geology_stone_temperate.xml b/binaries/data/mods/public/simulation/templates/gaia/geology_stone_temperate.xml
new file mode 100644
index 0000000000..9dac9f7d0f
--- /dev/null
+++ b/binaries/data/mods/public/simulation/templates/gaia/geology_stone_temperate.xml
@@ -0,0 +1,6 @@
+
+
+
+ geology/stonemine_granite.xml
+
+
diff --git a/binaries/data/mods/public/simulation/templates/gaia/geology_stone_tropic_a.xml b/binaries/data/mods/public/simulation/templates/gaia/geology_stone_tropic_a.xml
new file mode 100644
index 0000000000..8675c7859a
--- /dev/null
+++ b/binaries/data/mods/public/simulation/templates/gaia/geology_stone_tropic_a.xml
@@ -0,0 +1,6 @@
+
+
+
+ geology/stonemine_tropic.xml
+
+
diff --git a/binaries/data/mods/public/simulation/templates/gaia/special_settlement.xml b/binaries/data/mods/public/simulation/templates/gaia/special_settlement.xml
new file mode 100644
index 0000000000..807c2ff393
--- /dev/null
+++ b/binaries/data/mods/public/simulation/templates/gaia/special_settlement.xml
@@ -0,0 +1,6 @@
+
+
+
+ structures/wrld_settlement_1.xml
+
+
diff --git a/binaries/data/mods/public/simulation/templates/other/camp_mace_hypaspist.xml b/binaries/data/mods/public/simulation/templates/other/camp_mace_hypaspist.xml
new file mode 100644
index 0000000000..b254d2e133
--- /dev/null
+++ b/binaries/data/mods/public/simulation/templates/other/camp_mace_hypaspist.xml
@@ -0,0 +1,6 @@
+
+
+
+ temp/mace_su1_hypaspist.xml
+
+
diff --git a/binaries/data/mods/public/simulation/templates/structures/celt_barracks.xml b/binaries/data/mods/public/simulation/templates/structures/celt_barracks.xml
new file mode 100644
index 0000000000..b012519868
--- /dev/null
+++ b/binaries/data/mods/public/simulation/templates/structures/celt_barracks.xml
@@ -0,0 +1,6 @@
+
+
+
+ structures/celts/barracks.xml
+
+
diff --git a/binaries/data/mods/public/simulation/templates/structures/celt_civil_centre.xml b/binaries/data/mods/public/simulation/templates/structures/celt_civil_centre.xml
new file mode 100644
index 0000000000..8067335dc3
--- /dev/null
+++ b/binaries/data/mods/public/simulation/templates/structures/celt_civil_centre.xml
@@ -0,0 +1,6 @@
+
+
+
+ structures/celts/civil_centre.xml
+
+
diff --git a/binaries/data/mods/public/simulation/templates/structures/celt_corral.xml b/binaries/data/mods/public/simulation/templates/structures/celt_corral.xml
new file mode 100644
index 0000000000..7a664f9bd9
--- /dev/null
+++ b/binaries/data/mods/public/simulation/templates/structures/celt_corral.xml
@@ -0,0 +1,6 @@
+
+
+
+ structures/plot_corral.xml
+
+
diff --git a/binaries/data/mods/public/simulation/templates/structures/celt_dock.xml b/binaries/data/mods/public/simulation/templates/structures/celt_dock.xml
new file mode 100644
index 0000000000..8fc627d522
--- /dev/null
+++ b/binaries/data/mods/public/simulation/templates/structures/celt_dock.xml
@@ -0,0 +1,6 @@
+
+
+
+ structures/celts/dock.xml
+
+
diff --git a/binaries/data/mods/public/simulation/templates/structures/celt_farmstead.xml b/binaries/data/mods/public/simulation/templates/structures/celt_farmstead.xml
new file mode 100644
index 0000000000..d030603afe
--- /dev/null
+++ b/binaries/data/mods/public/simulation/templates/structures/celt_farmstead.xml
@@ -0,0 +1,6 @@
+
+
+
+ structures/celts/farmstead.xml
+
+
diff --git a/binaries/data/mods/public/simulation/templates/structures/celt_field.xml b/binaries/data/mods/public/simulation/templates/structures/celt_field.xml
new file mode 100644
index 0000000000..e23ff137a4
--- /dev/null
+++ b/binaries/data/mods/public/simulation/templates/structures/celt_field.xml
@@ -0,0 +1,6 @@
+
+
+
+ props/special/common/field_grain.xml
+
+
diff --git a/binaries/data/mods/public/simulation/templates/structures/celt_fortress_b.xml b/binaries/data/mods/public/simulation/templates/structures/celt_fortress_b.xml
new file mode 100644
index 0000000000..8410cad496
--- /dev/null
+++ b/binaries/data/mods/public/simulation/templates/structures/celt_fortress_b.xml
@@ -0,0 +1,6 @@
+
+
+
+ structures/celts/fortress_briton.xml
+
+
diff --git a/binaries/data/mods/public/simulation/templates/structures/celt_fortress_g.xml b/binaries/data/mods/public/simulation/templates/structures/celt_fortress_g.xml
new file mode 100644
index 0000000000..0c1ea90eb6
--- /dev/null
+++ b/binaries/data/mods/public/simulation/templates/structures/celt_fortress_g.xml
@@ -0,0 +1,6 @@
+
+
+
+ structures/celts/fortress_gallic.xml
+
+
diff --git a/binaries/data/mods/public/simulation/templates/structures/celt_house.xml b/binaries/data/mods/public/simulation/templates/structures/celt_house.xml
new file mode 100644
index 0000000000..8bd2d8a256
--- /dev/null
+++ b/binaries/data/mods/public/simulation/templates/structures/celt_house.xml
@@ -0,0 +1,6 @@
+
+
+
+ structures/celts/house.xml
+
+
diff --git a/binaries/data/mods/public/simulation/templates/structures/celt_market.xml b/binaries/data/mods/public/simulation/templates/structures/celt_market.xml
new file mode 100644
index 0000000000..803c6ce536
--- /dev/null
+++ b/binaries/data/mods/public/simulation/templates/structures/celt_market.xml
@@ -0,0 +1,6 @@
+
+
+
+ structures/celts/market.xml
+
+
diff --git a/binaries/data/mods/public/simulation/templates/structures/celt_mill.xml b/binaries/data/mods/public/simulation/templates/structures/celt_mill.xml
new file mode 100644
index 0000000000..fd865c1593
--- /dev/null
+++ b/binaries/data/mods/public/simulation/templates/structures/celt_mill.xml
@@ -0,0 +1,6 @@
+
+
+
+ structures/celts/mill.xml
+
+
diff --git a/binaries/data/mods/public/simulation/templates/structures/celt_sb1.xml b/binaries/data/mods/public/simulation/templates/structures/celt_sb1.xml
new file mode 100644
index 0000000000..9a550073b9
--- /dev/null
+++ b/binaries/data/mods/public/simulation/templates/structures/celt_sb1.xml
@@ -0,0 +1,6 @@
+
+
+
+ structures/celts/special.xml
+
+
diff --git a/binaries/data/mods/public/simulation/templates/structures/celt_scout_tower.xml b/binaries/data/mods/public/simulation/templates/structures/celt_scout_tower.xml
new file mode 100644
index 0000000000..19fae334ea
--- /dev/null
+++ b/binaries/data/mods/public/simulation/templates/structures/celt_scout_tower.xml
@@ -0,0 +1,6 @@
+
+
+
+ structures/celts/scout_tower.xml
+
+
diff --git a/binaries/data/mods/public/simulation/templates/structures/celt_temple.xml b/binaries/data/mods/public/simulation/templates/structures/celt_temple.xml
new file mode 100644
index 0000000000..d0b0f72c23
--- /dev/null
+++ b/binaries/data/mods/public/simulation/templates/structures/celt_temple.xml
@@ -0,0 +1,6 @@
+
+
+
+ structures/celts/temple.xml
+
+
diff --git a/binaries/data/mods/public/simulation/templates/structures/celt_wall.xml b/binaries/data/mods/public/simulation/templates/structures/celt_wall.xml
new file mode 100644
index 0000000000..bd63d90ed9
--- /dev/null
+++ b/binaries/data/mods/public/simulation/templates/structures/celt_wall.xml
@@ -0,0 +1,6 @@
+
+
+
+ structures/celts/wall.xml
+
+
diff --git a/binaries/data/mods/public/simulation/templates/structures/celt_wall_gate.xml b/binaries/data/mods/public/simulation/templates/structures/celt_wall_gate.xml
new file mode 100644
index 0000000000..fe1f19d4e2
--- /dev/null
+++ b/binaries/data/mods/public/simulation/templates/structures/celt_wall_gate.xml
@@ -0,0 +1,6 @@
+
+
+
+ structures/celts/wall_gate.xml
+
+
diff --git a/binaries/data/mods/public/simulation/templates/structures/celt_wall_long.xml b/binaries/data/mods/public/simulation/templates/structures/celt_wall_long.xml
new file mode 100644
index 0000000000..bd63d90ed9
--- /dev/null
+++ b/binaries/data/mods/public/simulation/templates/structures/celt_wall_long.xml
@@ -0,0 +1,6 @@
+
+
+
+ structures/celts/wall.xml
+
+
diff --git a/binaries/data/mods/public/simulation/templates/structures/celt_wall_tower.xml b/binaries/data/mods/public/simulation/templates/structures/celt_wall_tower.xml
new file mode 100644
index 0000000000..ea29e5df39
--- /dev/null
+++ b/binaries/data/mods/public/simulation/templates/structures/celt_wall_tower.xml
@@ -0,0 +1,6 @@
+
+
+
+ structures/celts/wall_turret.xml
+
+
diff --git a/binaries/data/mods/public/simulation/templates/structures/hele_barracks.xml b/binaries/data/mods/public/simulation/templates/structures/hele_barracks.xml
new file mode 100644
index 0000000000..076e431714
--- /dev/null
+++ b/binaries/data/mods/public/simulation/templates/structures/hele_barracks.xml
@@ -0,0 +1,6 @@
+
+
+
+ structures/hellenes/barracks.xml
+
+
diff --git a/binaries/data/mods/public/simulation/templates/structures/hele_civil_centre.xml b/binaries/data/mods/public/simulation/templates/structures/hele_civil_centre.xml
new file mode 100644
index 0000000000..f50db413bb
--- /dev/null
+++ b/binaries/data/mods/public/simulation/templates/structures/hele_civil_centre.xml
@@ -0,0 +1,6 @@
+
+
+
+ structures/hellenes/civic_centre_new.xml
+
+
diff --git a/binaries/data/mods/public/simulation/templates/structures/hele_corral.xml b/binaries/data/mods/public/simulation/templates/structures/hele_corral.xml
new file mode 100644
index 0000000000..7a664f9bd9
--- /dev/null
+++ b/binaries/data/mods/public/simulation/templates/structures/hele_corral.xml
@@ -0,0 +1,6 @@
+
+
+
+ structures/plot_corral.xml
+
+
diff --git a/binaries/data/mods/public/simulation/templates/structures/hele_dock.xml b/binaries/data/mods/public/simulation/templates/structures/hele_dock.xml
new file mode 100644
index 0000000000..e1d9241569
--- /dev/null
+++ b/binaries/data/mods/public/simulation/templates/structures/hele_dock.xml
@@ -0,0 +1,6 @@
+
+
+
+ structures/hellenes/dock.xml
+
+
diff --git a/binaries/data/mods/public/simulation/templates/structures/hele_farmstead.xml b/binaries/data/mods/public/simulation/templates/structures/hele_farmstead.xml
new file mode 100644
index 0000000000..3e3236933f
--- /dev/null
+++ b/binaries/data/mods/public/simulation/templates/structures/hele_farmstead.xml
@@ -0,0 +1,6 @@
+
+
+
+ structures/hellenes/farmstead.xml
+
+
diff --git a/binaries/data/mods/public/simulation/templates/structures/hele_field.xml b/binaries/data/mods/public/simulation/templates/structures/hele_field.xml
new file mode 100644
index 0000000000..e23ff137a4
--- /dev/null
+++ b/binaries/data/mods/public/simulation/templates/structures/hele_field.xml
@@ -0,0 +1,6 @@
+
+
+
+ props/special/common/field_grain.xml
+
+
diff --git a/binaries/data/mods/public/simulation/templates/structures/hele_fortress.xml b/binaries/data/mods/public/simulation/templates/structures/hele_fortress.xml
new file mode 100644
index 0000000000..09afe92395
--- /dev/null
+++ b/binaries/data/mods/public/simulation/templates/structures/hele_fortress.xml
@@ -0,0 +1,6 @@
+
+
+
+ structures/hellenes/fortress.xml
+
+
diff --git a/binaries/data/mods/public/simulation/templates/structures/hele_gymnasion.xml b/binaries/data/mods/public/simulation/templates/structures/hele_gymnasion.xml
new file mode 100644
index 0000000000..b41b0ff742
--- /dev/null
+++ b/binaries/data/mods/public/simulation/templates/structures/hele_gymnasion.xml
@@ -0,0 +1,6 @@
+
+
+
+ structures/hellenes/special_gym.xml
+
+
diff --git a/binaries/data/mods/public/simulation/templates/structures/hele_house.xml b/binaries/data/mods/public/simulation/templates/structures/hele_house.xml
new file mode 100644
index 0000000000..fe32b40f2a
--- /dev/null
+++ b/binaries/data/mods/public/simulation/templates/structures/hele_house.xml
@@ -0,0 +1,6 @@
+
+
+
+ structures/hellenes/house.xml
+
+
diff --git a/binaries/data/mods/public/simulation/templates/structures/hele_market.xml b/binaries/data/mods/public/simulation/templates/structures/hele_market.xml
new file mode 100644
index 0000000000..9de99882f3
--- /dev/null
+++ b/binaries/data/mods/public/simulation/templates/structures/hele_market.xml
@@ -0,0 +1,6 @@
+
+
+
+ structures/hellenes/market.xml
+
+
diff --git a/binaries/data/mods/public/simulation/templates/structures/hele_mill.xml b/binaries/data/mods/public/simulation/templates/structures/hele_mill.xml
new file mode 100644
index 0000000000..a2a82b59a2
--- /dev/null
+++ b/binaries/data/mods/public/simulation/templates/structures/hele_mill.xml
@@ -0,0 +1,6 @@
+
+
+
+ structures/hellenes/mill.xml
+
+
diff --git a/binaries/data/mods/public/simulation/templates/structures/hele_scout_tower.xml b/binaries/data/mods/public/simulation/templates/structures/hele_scout_tower.xml
new file mode 100644
index 0000000000..3c1957c23c
--- /dev/null
+++ b/binaries/data/mods/public/simulation/templates/structures/hele_scout_tower.xml
@@ -0,0 +1,6 @@
+
+
+
+ structures/hellenes/scout_tower.xml
+
+
diff --git a/binaries/data/mods/public/simulation/templates/structures/hele_temple.xml b/binaries/data/mods/public/simulation/templates/structures/hele_temple.xml
new file mode 100644
index 0000000000..01f174b412
--- /dev/null
+++ b/binaries/data/mods/public/simulation/templates/structures/hele_temple.xml
@@ -0,0 +1,6 @@
+
+
+
+ structures/hellenes/temple_new.xml
+
+
diff --git a/binaries/data/mods/public/simulation/templates/structures/hele_theatron.xml b/binaries/data/mods/public/simulation/templates/structures/hele_theatron.xml
new file mode 100644
index 0000000000..63c43ff4d5
--- /dev/null
+++ b/binaries/data/mods/public/simulation/templates/structures/hele_theatron.xml
@@ -0,0 +1,6 @@
+
+
+
+ structures/hellenes/special_theatre.xml
+
+
diff --git a/binaries/data/mods/public/simulation/templates/structures/hele_tholos.xml b/binaries/data/mods/public/simulation/templates/structures/hele_tholos.xml
new file mode 100644
index 0000000000..263a7e6802
--- /dev/null
+++ b/binaries/data/mods/public/simulation/templates/structures/hele_tholos.xml
@@ -0,0 +1,6 @@
+
+
+
+ structures/hellenes/tholos.xml
+
+
diff --git a/binaries/data/mods/public/simulation/templates/structures/hele_wall.xml b/binaries/data/mods/public/simulation/templates/structures/hele_wall.xml
new file mode 100644
index 0000000000..b90b871cdc
--- /dev/null
+++ b/binaries/data/mods/public/simulation/templates/structures/hele_wall.xml
@@ -0,0 +1,6 @@
+
+
+
+ structures/hellenes/wall.xml
+
+
diff --git a/binaries/data/mods/public/simulation/templates/structures/hele_wall_gate.xml b/binaries/data/mods/public/simulation/templates/structures/hele_wall_gate.xml
new file mode 100644
index 0000000000..d3e220ab8b
--- /dev/null
+++ b/binaries/data/mods/public/simulation/templates/structures/hele_wall_gate.xml
@@ -0,0 +1,6 @@
+
+
+
+ structures/hellenes/wall_gate.xml
+
+
diff --git a/binaries/data/mods/public/simulation/templates/structures/hele_wall_long.xml b/binaries/data/mods/public/simulation/templates/structures/hele_wall_long.xml
new file mode 100644
index 0000000000..b90b871cdc
--- /dev/null
+++ b/binaries/data/mods/public/simulation/templates/structures/hele_wall_long.xml
@@ -0,0 +1,6 @@
+
+
+
+ structures/hellenes/wall.xml
+
+
diff --git a/binaries/data/mods/public/simulation/templates/structures/hele_wall_tower.xml b/binaries/data/mods/public/simulation/templates/structures/hele_wall_tower.xml
new file mode 100644
index 0000000000..b74fcf293d
--- /dev/null
+++ b/binaries/data/mods/public/simulation/templates/structures/hele_wall_tower.xml
@@ -0,0 +1,6 @@
+
+
+
+ structures/hellenes/wall_turret.xml
+
+
diff --git a/binaries/data/mods/public/simulation/templates/template_corpse.xml b/binaries/data/mods/public/simulation/templates/template_corpse.xml
new file mode 100644
index 0000000000..528c465509
--- /dev/null
+++ b/binaries/data/mods/public/simulation/templates/template_corpse.xml
@@ -0,0 +1,3 @@
+
+
+
diff --git a/binaries/data/mods/public/simulation/templates/template_entity_full.xml b/binaries/data/mods/public/simulation/templates/template_entity_full.xml
new file mode 100644
index 0000000000..f0d4d366d0
--- /dev/null
+++ b/binaries/data/mods/public/simulation/templates/template_entity_full.xml
@@ -0,0 +1,9 @@
+
+
+
+ 0
+ upright
+ false
+
+
+
diff --git a/binaries/data/mods/public/simulation/templates/template_entity_quasi.xml b/binaries/data/mods/public/simulation/templates/template_entity_quasi.xml
new file mode 100644
index 0000000000..53b56c1d9d
--- /dev/null
+++ b/binaries/data/mods/public/simulation/templates/template_entity_quasi.xml
@@ -0,0 +1,9 @@
+
+
+
+ 0
+ upright
+ false
+
+
+
diff --git a/binaries/data/mods/public/simulation/templates/template_foundation.xml b/binaries/data/mods/public/simulation/templates/template_foundation.xml
new file mode 100644
index 0000000000..592c394a0f
--- /dev/null
+++ b/binaries/data/mods/public/simulation/templates/template_foundation.xml
@@ -0,0 +1,3 @@
+
+
+
diff --git a/binaries/data/mods/public/simulation/templates/template_gaia.xml b/binaries/data/mods/public/simulation/templates/template_gaia.xml
new file mode 100644
index 0000000000..62ee11da29
--- /dev/null
+++ b/binaries/data/mods/public/simulation/templates/template_gaia.xml
@@ -0,0 +1,3 @@
+
+
+
diff --git a/binaries/data/mods/public/simulation/templates/template_gaia_flora.xml b/binaries/data/mods/public/simulation/templates/template_gaia_flora.xml
new file mode 100644
index 0000000000..3823aa2a43
--- /dev/null
+++ b/binaries/data/mods/public/simulation/templates/template_gaia_flora.xml
@@ -0,0 +1,3 @@
+
+
+
diff --git a/binaries/data/mods/public/simulation/templates/template_gaia_flora_bush.xml b/binaries/data/mods/public/simulation/templates/template_gaia_flora_bush.xml
new file mode 100644
index 0000000000..a9e1cced85
--- /dev/null
+++ b/binaries/data/mods/public/simulation/templates/template_gaia_flora_bush.xml
@@ -0,0 +1,3 @@
+
+
+
diff --git a/binaries/data/mods/public/simulation/templates/template_gaia_flora_bush_berry.xml b/binaries/data/mods/public/simulation/templates/template_gaia_flora_bush_berry.xml
new file mode 100644
index 0000000000..c2fe4b0527
--- /dev/null
+++ b/binaries/data/mods/public/simulation/templates/template_gaia_flora_bush_berry.xml
@@ -0,0 +1,3 @@
+
+
+
diff --git a/binaries/data/mods/public/simulation/templates/template_gaia_flora_tree.xml b/binaries/data/mods/public/simulation/templates/template_gaia_flora_tree.xml
new file mode 100644
index 0000000000..a9e1cced85
--- /dev/null
+++ b/binaries/data/mods/public/simulation/templates/template_gaia_flora_tree.xml
@@ -0,0 +1,3 @@
+
+
+
diff --git a/binaries/data/mods/public/simulation/templates/template_gaia_geo.xml b/binaries/data/mods/public/simulation/templates/template_gaia_geo.xml
new file mode 100644
index 0000000000..3823aa2a43
--- /dev/null
+++ b/binaries/data/mods/public/simulation/templates/template_gaia_geo.xml
@@ -0,0 +1,3 @@
+
+
+
diff --git a/binaries/data/mods/public/simulation/templates/template_gaia_geo_mineral.xml b/binaries/data/mods/public/simulation/templates/template_gaia_geo_mineral.xml
new file mode 100644
index 0000000000..d5b6ce07cb
--- /dev/null
+++ b/binaries/data/mods/public/simulation/templates/template_gaia_geo_mineral.xml
@@ -0,0 +1,3 @@
+
+
+
diff --git a/binaries/data/mods/public/simulation/templates/template_gaia_geo_rock.xml b/binaries/data/mods/public/simulation/templates/template_gaia_geo_rock.xml
new file mode 100644
index 0000000000..d5b6ce07cb
--- /dev/null
+++ b/binaries/data/mods/public/simulation/templates/template_gaia_geo_rock.xml
@@ -0,0 +1,3 @@
+
+
+
diff --git a/binaries/data/mods/public/simulation/templates/template_structure.xml b/binaries/data/mods/public/simulation/templates/template_structure.xml
new file mode 100644
index 0000000000..592c394a0f
--- /dev/null
+++ b/binaries/data/mods/public/simulation/templates/template_structure.xml
@@ -0,0 +1,3 @@
+
+
+
diff --git a/binaries/data/mods/public/simulation/templates/template_structure_civic.xml b/binaries/data/mods/public/simulation/templates/template_structure_civic.xml
new file mode 100644
index 0000000000..45ec6d7db8
--- /dev/null
+++ b/binaries/data/mods/public/simulation/templates/template_structure_civic.xml
@@ -0,0 +1,3 @@
+
+
+
diff --git a/binaries/data/mods/public/simulation/templates/template_structure_civic_civil_centre.xml b/binaries/data/mods/public/simulation/templates/template_structure_civic_civil_centre.xml
new file mode 100644
index 0000000000..2c0b54c0a6
--- /dev/null
+++ b/binaries/data/mods/public/simulation/templates/template_structure_civic_civil_centre.xml
@@ -0,0 +1,3 @@
+
+
+
diff --git a/binaries/data/mods/public/simulation/templates/template_structure_civic_house.xml b/binaries/data/mods/public/simulation/templates/template_structure_civic_house.xml
new file mode 100644
index 0000000000..2c0b54c0a6
--- /dev/null
+++ b/binaries/data/mods/public/simulation/templates/template_structure_civic_house.xml
@@ -0,0 +1,3 @@
+
+
+
diff --git a/binaries/data/mods/public/simulation/templates/template_structure_civic_temple.xml b/binaries/data/mods/public/simulation/templates/template_structure_civic_temple.xml
new file mode 100644
index 0000000000..2c0b54c0a6
--- /dev/null
+++ b/binaries/data/mods/public/simulation/templates/template_structure_civic_temple.xml
@@ -0,0 +1,3 @@
+
+
+
diff --git a/binaries/data/mods/public/simulation/templates/template_structure_defense_scout_tower.xml b/binaries/data/mods/public/simulation/templates/template_structure_defense_scout_tower.xml
new file mode 100644
index 0000000000..2c0b54c0a6
--- /dev/null
+++ b/binaries/data/mods/public/simulation/templates/template_structure_defense_scout_tower.xml
@@ -0,0 +1,3 @@
+
+
+
diff --git a/binaries/data/mods/public/simulation/templates/template_structure_defense_wall.xml b/binaries/data/mods/public/simulation/templates/template_structure_defense_wall.xml
new file mode 100644
index 0000000000..2c0b54c0a6
--- /dev/null
+++ b/binaries/data/mods/public/simulation/templates/template_structure_defense_wall.xml
@@ -0,0 +1,3 @@
+
+
+
diff --git a/binaries/data/mods/public/simulation/templates/template_structure_defense_wall_gate.xml b/binaries/data/mods/public/simulation/templates/template_structure_defense_wall_gate.xml
new file mode 100644
index 0000000000..2c0b54c0a6
--- /dev/null
+++ b/binaries/data/mods/public/simulation/templates/template_structure_defense_wall_gate.xml
@@ -0,0 +1,3 @@
+
+
+
diff --git a/binaries/data/mods/public/simulation/templates/template_structure_defense_wall_tower.xml b/binaries/data/mods/public/simulation/templates/template_structure_defense_wall_tower.xml
new file mode 100644
index 0000000000..2c0b54c0a6
--- /dev/null
+++ b/binaries/data/mods/public/simulation/templates/template_structure_defense_wall_tower.xml
@@ -0,0 +1,3 @@
+
+
+
diff --git a/binaries/data/mods/public/simulation/templates/template_structure_economic.xml b/binaries/data/mods/public/simulation/templates/template_structure_economic.xml
new file mode 100644
index 0000000000..45ec6d7db8
--- /dev/null
+++ b/binaries/data/mods/public/simulation/templates/template_structure_economic.xml
@@ -0,0 +1,3 @@
+
+
+
diff --git a/binaries/data/mods/public/simulation/templates/template_structure_economic_farmstead.xml b/binaries/data/mods/public/simulation/templates/template_structure_economic_farmstead.xml
new file mode 100644
index 0000000000..36513330ac
--- /dev/null
+++ b/binaries/data/mods/public/simulation/templates/template_structure_economic_farmstead.xml
@@ -0,0 +1,3 @@
+
+
+
diff --git a/binaries/data/mods/public/simulation/templates/template_structure_economic_market.xml b/binaries/data/mods/public/simulation/templates/template_structure_economic_market.xml
new file mode 100644
index 0000000000..36513330ac
--- /dev/null
+++ b/binaries/data/mods/public/simulation/templates/template_structure_economic_market.xml
@@ -0,0 +1,3 @@
+
+
+
diff --git a/binaries/data/mods/public/simulation/templates/template_structure_economic_mill.xml b/binaries/data/mods/public/simulation/templates/template_structure_economic_mill.xml
new file mode 100644
index 0000000000..36513330ac
--- /dev/null
+++ b/binaries/data/mods/public/simulation/templates/template_structure_economic_mill.xml
@@ -0,0 +1,3 @@
+
+
+
diff --git a/binaries/data/mods/public/simulation/templates/template_structure_gaia_settlement.xml b/binaries/data/mods/public/simulation/templates/template_structure_gaia_settlement.xml
new file mode 100644
index 0000000000..592c394a0f
--- /dev/null
+++ b/binaries/data/mods/public/simulation/templates/template_structure_gaia_settlement.xml
@@ -0,0 +1,3 @@
+
+
+
diff --git a/binaries/data/mods/public/simulation/templates/template_structure_military.xml b/binaries/data/mods/public/simulation/templates/template_structure_military.xml
new file mode 100644
index 0000000000..45ec6d7db8
--- /dev/null
+++ b/binaries/data/mods/public/simulation/templates/template_structure_military.xml
@@ -0,0 +1,3 @@
+
+
+
diff --git a/binaries/data/mods/public/simulation/templates/template_structure_military_barracks.xml b/binaries/data/mods/public/simulation/templates/template_structure_military_barracks.xml
new file mode 100644
index 0000000000..827977061f
--- /dev/null
+++ b/binaries/data/mods/public/simulation/templates/template_structure_military_barracks.xml
@@ -0,0 +1,3 @@
+
+
+
diff --git a/binaries/data/mods/public/simulation/templates/template_structure_military_dock.xml b/binaries/data/mods/public/simulation/templates/template_structure_military_dock.xml
new file mode 100644
index 0000000000..827977061f
--- /dev/null
+++ b/binaries/data/mods/public/simulation/templates/template_structure_military_dock.xml
@@ -0,0 +1,3 @@
+
+
+
diff --git a/binaries/data/mods/public/simulation/templates/template_structure_military_fortress.xml b/binaries/data/mods/public/simulation/templates/template_structure_military_fortress.xml
new file mode 100644
index 0000000000..827977061f
--- /dev/null
+++ b/binaries/data/mods/public/simulation/templates/template_structure_military_fortress.xml
@@ -0,0 +1,3 @@
+
+
+
diff --git a/binaries/data/mods/public/simulation/templates/template_structure_resource.xml b/binaries/data/mods/public/simulation/templates/template_structure_resource.xml
new file mode 100644
index 0000000000..45ec6d7db8
--- /dev/null
+++ b/binaries/data/mods/public/simulation/templates/template_structure_resource.xml
@@ -0,0 +1,3 @@
+
+
+
diff --git a/binaries/data/mods/public/simulation/templates/template_structure_resource_corral.xml b/binaries/data/mods/public/simulation/templates/template_structure_resource_corral.xml
new file mode 100644
index 0000000000..a28c4c2932
--- /dev/null
+++ b/binaries/data/mods/public/simulation/templates/template_structure_resource_corral.xml
@@ -0,0 +1,3 @@
+
+
+
diff --git a/binaries/data/mods/public/simulation/templates/template_structure_resource_field.xml b/binaries/data/mods/public/simulation/templates/template_structure_resource_field.xml
new file mode 100644
index 0000000000..a28c4c2932
--- /dev/null
+++ b/binaries/data/mods/public/simulation/templates/template_structure_resource_field.xml
@@ -0,0 +1,3 @@
+
+
+
diff --git a/binaries/data/mods/public/simulation/templates/template_structure_special.xml b/binaries/data/mods/public/simulation/templates/template_structure_special.xml
new file mode 100644
index 0000000000..45ec6d7db8
--- /dev/null
+++ b/binaries/data/mods/public/simulation/templates/template_structure_special.xml
@@ -0,0 +1,3 @@
+
+
+
diff --git a/binaries/data/mods/public/simulation/templates/template_unit.xml b/binaries/data/mods/public/simulation/templates/template_unit.xml
new file mode 100644
index 0000000000..ebd1ec2adc
--- /dev/null
+++ b/binaries/data/mods/public/simulation/templates/template_unit.xml
@@ -0,0 +1,4 @@
+
+
+
+
diff --git a/binaries/data/mods/public/simulation/templates/template_unit_cavalry.xml b/binaries/data/mods/public/simulation/templates/template_unit_cavalry.xml
new file mode 100644
index 0000000000..f22b42f2e2
--- /dev/null
+++ b/binaries/data/mods/public/simulation/templates/template_unit_cavalry.xml
@@ -0,0 +1,3 @@
+
+
+
diff --git a/binaries/data/mods/public/simulation/templates/template_unit_cavalry_melee.xml b/binaries/data/mods/public/simulation/templates/template_unit_cavalry_melee.xml
new file mode 100644
index 0000000000..f02a0bf0f6
--- /dev/null
+++ b/binaries/data/mods/public/simulation/templates/template_unit_cavalry_melee.xml
@@ -0,0 +1,3 @@
+
+
+
diff --git a/binaries/data/mods/public/simulation/templates/template_unit_cavalry_melee_spearman.xml b/binaries/data/mods/public/simulation/templates/template_unit_cavalry_melee_spearman.xml
new file mode 100644
index 0000000000..ed4af04f4d
--- /dev/null
+++ b/binaries/data/mods/public/simulation/templates/template_unit_cavalry_melee_spearman.xml
@@ -0,0 +1,3 @@
+
+
+
diff --git a/binaries/data/mods/public/simulation/templates/template_unit_cavalry_melee_swordsman.xml b/binaries/data/mods/public/simulation/templates/template_unit_cavalry_melee_swordsman.xml
new file mode 100644
index 0000000000..ed4af04f4d
--- /dev/null
+++ b/binaries/data/mods/public/simulation/templates/template_unit_cavalry_melee_swordsman.xml
@@ -0,0 +1,3 @@
+
+
+
diff --git a/binaries/data/mods/public/simulation/templates/template_unit_cavalry_ranged.xml b/binaries/data/mods/public/simulation/templates/template_unit_cavalry_ranged.xml
new file mode 100644
index 0000000000..f02a0bf0f6
--- /dev/null
+++ b/binaries/data/mods/public/simulation/templates/template_unit_cavalry_ranged.xml
@@ -0,0 +1,3 @@
+
+
+
diff --git a/binaries/data/mods/public/simulation/templates/template_unit_cavalry_ranged_archer.xml b/binaries/data/mods/public/simulation/templates/template_unit_cavalry_ranged_archer.xml
new file mode 100644
index 0000000000..77bcc1275b
--- /dev/null
+++ b/binaries/data/mods/public/simulation/templates/template_unit_cavalry_ranged_archer.xml
@@ -0,0 +1,3 @@
+
+
+
diff --git a/binaries/data/mods/public/simulation/templates/template_unit_cavalry_ranged_javelinist.xml b/binaries/data/mods/public/simulation/templates/template_unit_cavalry_ranged_javelinist.xml
new file mode 100644
index 0000000000..77bcc1275b
--- /dev/null
+++ b/binaries/data/mods/public/simulation/templates/template_unit_cavalry_ranged_javelinist.xml
@@ -0,0 +1,3 @@
+
+
+
diff --git a/binaries/data/mods/public/simulation/templates/template_unit_fauna.xml b/binaries/data/mods/public/simulation/templates/template_unit_fauna.xml
new file mode 100644
index 0000000000..f22b42f2e2
--- /dev/null
+++ b/binaries/data/mods/public/simulation/templates/template_unit_fauna.xml
@@ -0,0 +1,3 @@
+
+
+
diff --git a/binaries/data/mods/public/simulation/templates/template_unit_fauna_breed.xml b/binaries/data/mods/public/simulation/templates/template_unit_fauna_breed.xml
new file mode 100644
index 0000000000..65038c1c55
--- /dev/null
+++ b/binaries/data/mods/public/simulation/templates/template_unit_fauna_breed.xml
@@ -0,0 +1,3 @@
+
+
+
diff --git a/binaries/data/mods/public/simulation/templates/template_unit_fauna_breed_passive.xml b/binaries/data/mods/public/simulation/templates/template_unit_fauna_breed_passive.xml
new file mode 100644
index 0000000000..8d8f7fc874
--- /dev/null
+++ b/binaries/data/mods/public/simulation/templates/template_unit_fauna_breed_passive.xml
@@ -0,0 +1,3 @@
+
+
+
diff --git a/binaries/data/mods/public/simulation/templates/template_unit_fauna_herd.xml b/binaries/data/mods/public/simulation/templates/template_unit_fauna_herd.xml
new file mode 100644
index 0000000000..65038c1c55
--- /dev/null
+++ b/binaries/data/mods/public/simulation/templates/template_unit_fauna_herd.xml
@@ -0,0 +1,3 @@
+
+
+
diff --git a/binaries/data/mods/public/simulation/templates/template_unit_fauna_herd_passive.xml b/binaries/data/mods/public/simulation/templates/template_unit_fauna_herd_passive.xml
new file mode 100644
index 0000000000..67d5108250
--- /dev/null
+++ b/binaries/data/mods/public/simulation/templates/template_unit_fauna_herd_passive.xml
@@ -0,0 +1,3 @@
+
+
+
diff --git a/binaries/data/mods/public/simulation/templates/template_unit_fauna_hunt.xml b/binaries/data/mods/public/simulation/templates/template_unit_fauna_hunt.xml
new file mode 100644
index 0000000000..65038c1c55
--- /dev/null
+++ b/binaries/data/mods/public/simulation/templates/template_unit_fauna_hunt.xml
@@ -0,0 +1,3 @@
+
+
+
diff --git a/binaries/data/mods/public/simulation/templates/template_unit_fauna_hunt_aggressive.xml b/binaries/data/mods/public/simulation/templates/template_unit_fauna_hunt_aggressive.xml
new file mode 100644
index 0000000000..70e9064f1c
--- /dev/null
+++ b/binaries/data/mods/public/simulation/templates/template_unit_fauna_hunt_aggressive.xml
@@ -0,0 +1,3 @@
+
+
+
diff --git a/binaries/data/mods/public/simulation/templates/template_unit_fauna_hunt_defensive.xml b/binaries/data/mods/public/simulation/templates/template_unit_fauna_hunt_defensive.xml
new file mode 100644
index 0000000000..70e9064f1c
--- /dev/null
+++ b/binaries/data/mods/public/simulation/templates/template_unit_fauna_hunt_defensive.xml
@@ -0,0 +1,3 @@
+
+
+
diff --git a/binaries/data/mods/public/simulation/templates/template_unit_fauna_hunt_passive.xml b/binaries/data/mods/public/simulation/templates/template_unit_fauna_hunt_passive.xml
new file mode 100644
index 0000000000..70e9064f1c
--- /dev/null
+++ b/binaries/data/mods/public/simulation/templates/template_unit_fauna_hunt_passive.xml
@@ -0,0 +1,3 @@
+
+
+
diff --git a/binaries/data/mods/public/simulation/templates/template_unit_fauna_hunt_skittish.xml b/binaries/data/mods/public/simulation/templates/template_unit_fauna_hunt_skittish.xml
new file mode 100644
index 0000000000..70e9064f1c
--- /dev/null
+++ b/binaries/data/mods/public/simulation/templates/template_unit_fauna_hunt_skittish.xml
@@ -0,0 +1,3 @@
+
+
+
diff --git a/binaries/data/mods/public/simulation/templates/template_unit_fauna_hunt_violent.xml b/binaries/data/mods/public/simulation/templates/template_unit_fauna_hunt_violent.xml
new file mode 100644
index 0000000000..70e9064f1c
--- /dev/null
+++ b/binaries/data/mods/public/simulation/templates/template_unit_fauna_hunt_violent.xml
@@ -0,0 +1,3 @@
+
+
+
diff --git a/binaries/data/mods/public/simulation/templates/template_unit_fauna_wild.xml b/binaries/data/mods/public/simulation/templates/template_unit_fauna_wild.xml
new file mode 100644
index 0000000000..65038c1c55
--- /dev/null
+++ b/binaries/data/mods/public/simulation/templates/template_unit_fauna_wild.xml
@@ -0,0 +1,3 @@
+
+
+
diff --git a/binaries/data/mods/public/simulation/templates/template_unit_fauna_wild_aggressive.xml b/binaries/data/mods/public/simulation/templates/template_unit_fauna_wild_aggressive.xml
new file mode 100644
index 0000000000..e18e327a9f
--- /dev/null
+++ b/binaries/data/mods/public/simulation/templates/template_unit_fauna_wild_aggressive.xml
@@ -0,0 +1,3 @@
+
+
+
diff --git a/binaries/data/mods/public/simulation/templates/template_unit_fauna_wild_defensive.xml b/binaries/data/mods/public/simulation/templates/template_unit_fauna_wild_defensive.xml
new file mode 100644
index 0000000000..e18e327a9f
--- /dev/null
+++ b/binaries/data/mods/public/simulation/templates/template_unit_fauna_wild_defensive.xml
@@ -0,0 +1,3 @@
+
+
+
diff --git a/binaries/data/mods/public/simulation/templates/template_unit_fauna_wild_passive.xml b/binaries/data/mods/public/simulation/templates/template_unit_fauna_wild_passive.xml
new file mode 100644
index 0000000000..e18e327a9f
--- /dev/null
+++ b/binaries/data/mods/public/simulation/templates/template_unit_fauna_wild_passive.xml
@@ -0,0 +1,3 @@
+
+
+
diff --git a/binaries/data/mods/public/simulation/templates/template_unit_fauna_wild_violent.xml b/binaries/data/mods/public/simulation/templates/template_unit_fauna_wild_violent.xml
new file mode 100644
index 0000000000..e18e327a9f
--- /dev/null
+++ b/binaries/data/mods/public/simulation/templates/template_unit_fauna_wild_violent.xml
@@ -0,0 +1,3 @@
+
+
+
diff --git a/binaries/data/mods/public/simulation/templates/template_unit_hero.xml b/binaries/data/mods/public/simulation/templates/template_unit_hero.xml
new file mode 100644
index 0000000000..f22b42f2e2
--- /dev/null
+++ b/binaries/data/mods/public/simulation/templates/template_unit_hero.xml
@@ -0,0 +1,3 @@
+
+
+
diff --git a/binaries/data/mods/public/simulation/templates/template_unit_hero_cavalry.xml b/binaries/data/mods/public/simulation/templates/template_unit_hero_cavalry.xml
new file mode 100644
index 0000000000..9fef95060f
--- /dev/null
+++ b/binaries/data/mods/public/simulation/templates/template_unit_hero_cavalry.xml
@@ -0,0 +1,3 @@
+
+
+
diff --git a/binaries/data/mods/public/simulation/templates/template_unit_hero_infantry.xml b/binaries/data/mods/public/simulation/templates/template_unit_hero_infantry.xml
new file mode 100644
index 0000000000..fa5384a8d2
--- /dev/null
+++ b/binaries/data/mods/public/simulation/templates/template_unit_hero_infantry.xml
@@ -0,0 +1,3 @@
+
+
+
diff --git a/binaries/data/mods/public/simulation/templates/template_unit_hero_ranged.xml b/binaries/data/mods/public/simulation/templates/template_unit_hero_ranged.xml
new file mode 100644
index 0000000000..60931706c5
--- /dev/null
+++ b/binaries/data/mods/public/simulation/templates/template_unit_hero_ranged.xml
@@ -0,0 +1,3 @@
+
+
+
diff --git a/binaries/data/mods/public/simulation/templates/template_unit_infantry.xml b/binaries/data/mods/public/simulation/templates/template_unit_infantry.xml
new file mode 100644
index 0000000000..f22b42f2e2
--- /dev/null
+++ b/binaries/data/mods/public/simulation/templates/template_unit_infantry.xml
@@ -0,0 +1,3 @@
+
+
+
diff --git a/binaries/data/mods/public/simulation/templates/template_unit_infantry_melee.xml b/binaries/data/mods/public/simulation/templates/template_unit_infantry_melee.xml
new file mode 100644
index 0000000000..3a74b037f2
--- /dev/null
+++ b/binaries/data/mods/public/simulation/templates/template_unit_infantry_melee.xml
@@ -0,0 +1,3 @@
+
+
+
diff --git a/binaries/data/mods/public/simulation/templates/template_unit_infantry_melee_spearman.xml b/binaries/data/mods/public/simulation/templates/template_unit_infantry_melee_spearman.xml
new file mode 100644
index 0000000000..44f410f1e3
--- /dev/null
+++ b/binaries/data/mods/public/simulation/templates/template_unit_infantry_melee_spearman.xml
@@ -0,0 +1,3 @@
+
+
+
diff --git a/binaries/data/mods/public/simulation/templates/template_unit_infantry_melee_swordsman.xml b/binaries/data/mods/public/simulation/templates/template_unit_infantry_melee_swordsman.xml
new file mode 100644
index 0000000000..44f410f1e3
--- /dev/null
+++ b/binaries/data/mods/public/simulation/templates/template_unit_infantry_melee_swordsman.xml
@@ -0,0 +1,3 @@
+
+
+
diff --git a/binaries/data/mods/public/simulation/templates/template_unit_infantry_ranged.xml b/binaries/data/mods/public/simulation/templates/template_unit_infantry_ranged.xml
new file mode 100644
index 0000000000..3a74b037f2
--- /dev/null
+++ b/binaries/data/mods/public/simulation/templates/template_unit_infantry_ranged.xml
@@ -0,0 +1,3 @@
+
+
+
diff --git a/binaries/data/mods/public/simulation/templates/template_unit_infantry_ranged_archer.xml b/binaries/data/mods/public/simulation/templates/template_unit_infantry_ranged_archer.xml
new file mode 100644
index 0000000000..9b186a4df2
--- /dev/null
+++ b/binaries/data/mods/public/simulation/templates/template_unit_infantry_ranged_archer.xml
@@ -0,0 +1,3 @@
+
+
+
diff --git a/binaries/data/mods/public/simulation/templates/template_unit_infantry_ranged_javelinist.xml b/binaries/data/mods/public/simulation/templates/template_unit_infantry_ranged_javelinist.xml
new file mode 100644
index 0000000000..9b186a4df2
--- /dev/null
+++ b/binaries/data/mods/public/simulation/templates/template_unit_infantry_ranged_javelinist.xml
@@ -0,0 +1,3 @@
+
+
+
diff --git a/binaries/data/mods/public/simulation/templates/template_unit_infantry_ranged_slinger.xml b/binaries/data/mods/public/simulation/templates/template_unit_infantry_ranged_slinger.xml
new file mode 100644
index 0000000000..9b186a4df2
--- /dev/null
+++ b/binaries/data/mods/public/simulation/templates/template_unit_infantry_ranged_slinger.xml
@@ -0,0 +1,3 @@
+
+
+
diff --git a/binaries/data/mods/public/simulation/templates/template_unit_mechanical.xml b/binaries/data/mods/public/simulation/templates/template_unit_mechanical.xml
new file mode 100644
index 0000000000..f22b42f2e2
--- /dev/null
+++ b/binaries/data/mods/public/simulation/templates/template_unit_mechanical.xml
@@ -0,0 +1,3 @@
+
+
+
diff --git a/binaries/data/mods/public/simulation/templates/template_unit_mechanical_ship.xml b/binaries/data/mods/public/simulation/templates/template_unit_mechanical_ship.xml
new file mode 100644
index 0000000000..3798640012
--- /dev/null
+++ b/binaries/data/mods/public/simulation/templates/template_unit_mechanical_ship.xml
@@ -0,0 +1,3 @@
+
+
+
diff --git a/binaries/data/mods/public/simulation/templates/template_unit_mechanical_ship_bireme.xml b/binaries/data/mods/public/simulation/templates/template_unit_mechanical_ship_bireme.xml
new file mode 100644
index 0000000000..564912ce44
--- /dev/null
+++ b/binaries/data/mods/public/simulation/templates/template_unit_mechanical_ship_bireme.xml
@@ -0,0 +1,3 @@
+
+
+
diff --git a/binaries/data/mods/public/simulation/templates/template_unit_mechanical_ship_merchant.xml b/binaries/data/mods/public/simulation/templates/template_unit_mechanical_ship_merchant.xml
new file mode 100644
index 0000000000..564912ce44
--- /dev/null
+++ b/binaries/data/mods/public/simulation/templates/template_unit_mechanical_ship_merchant.xml
@@ -0,0 +1,3 @@
+
+
+
diff --git a/binaries/data/mods/public/simulation/templates/template_unit_mechanical_ship_quinquereme.xml b/binaries/data/mods/public/simulation/templates/template_unit_mechanical_ship_quinquereme.xml
new file mode 100644
index 0000000000..564912ce44
--- /dev/null
+++ b/binaries/data/mods/public/simulation/templates/template_unit_mechanical_ship_quinquereme.xml
@@ -0,0 +1,3 @@
+
+
+
diff --git a/binaries/data/mods/public/simulation/templates/template_unit_mechanical_ship_trireme.xml b/binaries/data/mods/public/simulation/templates/template_unit_mechanical_ship_trireme.xml
new file mode 100644
index 0000000000..564912ce44
--- /dev/null
+++ b/binaries/data/mods/public/simulation/templates/template_unit_mechanical_ship_trireme.xml
@@ -0,0 +1,3 @@
+
+
+
diff --git a/binaries/data/mods/public/simulation/templates/template_unit_mechanical_siege.xml b/binaries/data/mods/public/simulation/templates/template_unit_mechanical_siege.xml
new file mode 100644
index 0000000000..3798640012
--- /dev/null
+++ b/binaries/data/mods/public/simulation/templates/template_unit_mechanical_siege.xml
@@ -0,0 +1,3 @@
+
+
+
diff --git a/binaries/data/mods/public/simulation/templates/template_unit_mechanical_siege_ballista.xml b/binaries/data/mods/public/simulation/templates/template_unit_mechanical_siege_ballista.xml
new file mode 100644
index 0000000000..d8cdad276b
--- /dev/null
+++ b/binaries/data/mods/public/simulation/templates/template_unit_mechanical_siege_ballista.xml
@@ -0,0 +1,3 @@
+
+
+
diff --git a/binaries/data/mods/public/simulation/templates/template_unit_mechanical_siege_onager.xml b/binaries/data/mods/public/simulation/templates/template_unit_mechanical_siege_onager.xml
new file mode 100644
index 0000000000..d8cdad276b
--- /dev/null
+++ b/binaries/data/mods/public/simulation/templates/template_unit_mechanical_siege_onager.xml
@@ -0,0 +1,3 @@
+
+
+
diff --git a/binaries/data/mods/public/simulation/templates/template_unit_mechanical_siege_ram.xml b/binaries/data/mods/public/simulation/templates/template_unit_mechanical_siege_ram.xml
new file mode 100644
index 0000000000..d8cdad276b
--- /dev/null
+++ b/binaries/data/mods/public/simulation/templates/template_unit_mechanical_siege_ram.xml
@@ -0,0 +1,3 @@
+
+
+
diff --git a/binaries/data/mods/public/simulation/templates/template_unit_super.xml b/binaries/data/mods/public/simulation/templates/template_unit_super.xml
new file mode 100644
index 0000000000..f22b42f2e2
--- /dev/null
+++ b/binaries/data/mods/public/simulation/templates/template_unit_super.xml
@@ -0,0 +1,3 @@
+
+
+
diff --git a/binaries/data/mods/public/simulation/templates/template_unit_super_cavalry.xml b/binaries/data/mods/public/simulation/templates/template_unit_super_cavalry.xml
new file mode 100644
index 0000000000..fd8e7aa074
--- /dev/null
+++ b/binaries/data/mods/public/simulation/templates/template_unit_super_cavalry.xml
@@ -0,0 +1,3 @@
+
+
+
diff --git a/binaries/data/mods/public/simulation/templates/template_unit_super_infantry.xml b/binaries/data/mods/public/simulation/templates/template_unit_super_infantry.xml
new file mode 100644
index 0000000000..fd8e7aa074
--- /dev/null
+++ b/binaries/data/mods/public/simulation/templates/template_unit_super_infantry.xml
@@ -0,0 +1,3 @@
+
+
+
diff --git a/binaries/data/mods/public/simulation/templates/template_unit_super_ranged.xml b/binaries/data/mods/public/simulation/templates/template_unit_super_ranged.xml
new file mode 100644
index 0000000000..fd8e7aa074
--- /dev/null
+++ b/binaries/data/mods/public/simulation/templates/template_unit_super_ranged.xml
@@ -0,0 +1,3 @@
+
+
+
diff --git a/binaries/data/mods/public/simulation/templates/template_unit_super_siege.xml b/binaries/data/mods/public/simulation/templates/template_unit_super_siege.xml
new file mode 100644
index 0000000000..fd8e7aa074
--- /dev/null
+++ b/binaries/data/mods/public/simulation/templates/template_unit_super_siege.xml
@@ -0,0 +1,3 @@
+
+
+
diff --git a/binaries/data/mods/public/simulation/templates/template_unit_support.xml b/binaries/data/mods/public/simulation/templates/template_unit_support.xml
new file mode 100644
index 0000000000..f22b42f2e2
--- /dev/null
+++ b/binaries/data/mods/public/simulation/templates/template_unit_support.xml
@@ -0,0 +1,3 @@
+
+
+
diff --git a/binaries/data/mods/public/simulation/templates/template_unit_support_female_citizen.xml b/binaries/data/mods/public/simulation/templates/template_unit_support_female_citizen.xml
new file mode 100644
index 0000000000..d9e231b1d5
--- /dev/null
+++ b/binaries/data/mods/public/simulation/templates/template_unit_support_female_citizen.xml
@@ -0,0 +1,3 @@
+
+
+
diff --git a/binaries/data/mods/public/simulation/templates/template_unit_support_healer.xml b/binaries/data/mods/public/simulation/templates/template_unit_support_healer.xml
new file mode 100644
index 0000000000..d9e231b1d5
--- /dev/null
+++ b/binaries/data/mods/public/simulation/templates/template_unit_support_healer.xml
@@ -0,0 +1,3 @@
+
+
+
diff --git a/binaries/data/mods/public/simulation/templates/template_unit_support_trader.xml b/binaries/data/mods/public/simulation/templates/template_unit_support_trader.xml
new file mode 100644
index 0000000000..d9e231b1d5
--- /dev/null
+++ b/binaries/data/mods/public/simulation/templates/template_unit_support_trader.xml
@@ -0,0 +1,3 @@
+
+
+
diff --git a/binaries/data/mods/public/simulation/templates/units/celt_cavalry_javelinist_a.xml b/binaries/data/mods/public/simulation/templates/units/celt_cavalry_javelinist_a.xml
new file mode 100644
index 0000000000..f664a6a039
--- /dev/null
+++ b/binaries/data/mods/public/simulation/templates/units/celt_cavalry_javelinist_a.xml
@@ -0,0 +1,6 @@
+
+
+
+ units/celts/cavalry_javelinist_a.xml
+
+
diff --git a/binaries/data/mods/public/simulation/templates/units/celt_cavalry_javelinist_b.xml b/binaries/data/mods/public/simulation/templates/units/celt_cavalry_javelinist_b.xml
new file mode 100644
index 0000000000..83bbb6a135
--- /dev/null
+++ b/binaries/data/mods/public/simulation/templates/units/celt_cavalry_javelinist_b.xml
@@ -0,0 +1,6 @@
+
+
+
+ units/celts/cavalry_javelinist_b.xml
+
+
diff --git a/binaries/data/mods/public/simulation/templates/units/celt_cavalry_javelinist_e.xml b/binaries/data/mods/public/simulation/templates/units/celt_cavalry_javelinist_e.xml
new file mode 100644
index 0000000000..d74c8bc425
--- /dev/null
+++ b/binaries/data/mods/public/simulation/templates/units/celt_cavalry_javelinist_e.xml
@@ -0,0 +1,6 @@
+
+
+
+ units/celts/cavalry_javelinist_e.xml
+
+
diff --git a/binaries/data/mods/public/simulation/templates/units/celt_cavalry_spearman_a.xml b/binaries/data/mods/public/simulation/templates/units/celt_cavalry_spearman_a.xml
new file mode 100644
index 0000000000..36eaf21706
--- /dev/null
+++ b/binaries/data/mods/public/simulation/templates/units/celt_cavalry_spearman_a.xml
@@ -0,0 +1,6 @@
+
+
+
+ units/celts/cavalry_spearman_a.xml
+
+
diff --git a/binaries/data/mods/public/simulation/templates/units/celt_cavalry_spearman_b.xml b/binaries/data/mods/public/simulation/templates/units/celt_cavalry_spearman_b.xml
new file mode 100644
index 0000000000..2061d59e78
--- /dev/null
+++ b/binaries/data/mods/public/simulation/templates/units/celt_cavalry_spearman_b.xml
@@ -0,0 +1,6 @@
+
+
+
+ units/celts/cavalry_spearman_b.xml
+
+
diff --git a/binaries/data/mods/public/simulation/templates/units/celt_cavalry_spearman_e.xml b/binaries/data/mods/public/simulation/templates/units/celt_cavalry_spearman_e.xml
new file mode 100644
index 0000000000..aef0f81729
--- /dev/null
+++ b/binaries/data/mods/public/simulation/templates/units/celt_cavalry_spearman_e.xml
@@ -0,0 +1,6 @@
+
+
+
+ units/celts/cavalry_spearman_e.xml
+
+
diff --git a/binaries/data/mods/public/simulation/templates/units/celt_cavalry_swordsman_a.xml b/binaries/data/mods/public/simulation/templates/units/celt_cavalry_swordsman_a.xml
new file mode 100644
index 0000000000..26285de0e0
--- /dev/null
+++ b/binaries/data/mods/public/simulation/templates/units/celt_cavalry_swordsman_a.xml
@@ -0,0 +1,6 @@
+
+
+
+ units/celts/cavalry_swordsman_a.xml
+
+
diff --git a/binaries/data/mods/public/simulation/templates/units/celt_cavalry_swordsman_b.xml b/binaries/data/mods/public/simulation/templates/units/celt_cavalry_swordsman_b.xml
new file mode 100644
index 0000000000..e9b73564e5
--- /dev/null
+++ b/binaries/data/mods/public/simulation/templates/units/celt_cavalry_swordsman_b.xml
@@ -0,0 +1,6 @@
+
+
+
+ units/celts/cavalry_swordsman_b.xml
+
+
diff --git a/binaries/data/mods/public/simulation/templates/units/celt_cavalry_swordsman_e.xml b/binaries/data/mods/public/simulation/templates/units/celt_cavalry_swordsman_e.xml
new file mode 100644
index 0000000000..585f2a00bd
--- /dev/null
+++ b/binaries/data/mods/public/simulation/templates/units/celt_cavalry_swordsman_e.xml
@@ -0,0 +1,6 @@
+
+
+
+ units/celts/cavalry_swordsman_e.xml
+
+
diff --git a/binaries/data/mods/public/simulation/templates/units/celt_hero_boudicca.xml b/binaries/data/mods/public/simulation/templates/units/celt_hero_boudicca.xml
new file mode 100644
index 0000000000..0237034bed
--- /dev/null
+++ b/binaries/data/mods/public/simulation/templates/units/celt_hero_boudicca.xml
@@ -0,0 +1,6 @@
+
+
+
+ units/celts/boudicca_chariot.xml
+
+
diff --git a/binaries/data/mods/public/simulation/templates/units/celt_hero_brennus.xml b/binaries/data/mods/public/simulation/templates/units/celt_hero_brennus.xml
new file mode 100644
index 0000000000..192d186eac
--- /dev/null
+++ b/binaries/data/mods/public/simulation/templates/units/celt_hero_brennus.xml
@@ -0,0 +1,6 @@
+
+
+
+ units/celts/brennus.xml
+
+
diff --git a/binaries/data/mods/public/simulation/templates/units/celt_hero_britomartus.xml b/binaries/data/mods/public/simulation/templates/units/celt_hero_britomartus.xml
new file mode 100644
index 0000000000..d987a69a56
--- /dev/null
+++ b/binaries/data/mods/public/simulation/templates/units/celt_hero_britomartus.xml
@@ -0,0 +1,6 @@
+
+
+
+ units/celts/britomartus.xml
+
+
diff --git a/binaries/data/mods/public/simulation/templates/units/celt_hero_caratacos.xml b/binaries/data/mods/public/simulation/templates/units/celt_hero_caratacos.xml
new file mode 100644
index 0000000000..7de8be7ee3
--- /dev/null
+++ b/binaries/data/mods/public/simulation/templates/units/celt_hero_caratacos.xml
@@ -0,0 +1,6 @@
+
+
+
+ units/celts/caradoc.xml
+
+
diff --git a/binaries/data/mods/public/simulation/templates/units/celt_hero_cynvelin.xml b/binaries/data/mods/public/simulation/templates/units/celt_hero_cynvelin.xml
new file mode 100644
index 0000000000..2ceff505e8
--- /dev/null
+++ b/binaries/data/mods/public/simulation/templates/units/celt_hero_cynvelin.xml
@@ -0,0 +1,6 @@
+
+
+
+ units/celts/cynvelin_horse.xml
+
+
diff --git a/binaries/data/mods/public/simulation/templates/units/celt_hero_vercingetorix.xml b/binaries/data/mods/public/simulation/templates/units/celt_hero_vercingetorix.xml
new file mode 100644
index 0000000000..9378bee92b
--- /dev/null
+++ b/binaries/data/mods/public/simulation/templates/units/celt_hero_vercingetorix.xml
@@ -0,0 +1,6 @@
+
+
+
+ units/celts/vercingetorix_horse.xml
+
+
diff --git a/binaries/data/mods/public/simulation/templates/units/celt_infantry_javelinist_a.xml b/binaries/data/mods/public/simulation/templates/units/celt_infantry_javelinist_a.xml
new file mode 100644
index 0000000000..d81091f266
--- /dev/null
+++ b/binaries/data/mods/public/simulation/templates/units/celt_infantry_javelinist_a.xml
@@ -0,0 +1,6 @@
+
+
+
+ units/celts/infantry_javelinist_a.xml
+
+
diff --git a/binaries/data/mods/public/simulation/templates/units/celt_infantry_javelinist_b.xml b/binaries/data/mods/public/simulation/templates/units/celt_infantry_javelinist_b.xml
new file mode 100644
index 0000000000..add3d1de75
--- /dev/null
+++ b/binaries/data/mods/public/simulation/templates/units/celt_infantry_javelinist_b.xml
@@ -0,0 +1,6 @@
+
+
+
+ units/celts/infantry_javelinist_b.xml
+
+
diff --git a/binaries/data/mods/public/simulation/templates/units/celt_infantry_javelinist_e.xml b/binaries/data/mods/public/simulation/templates/units/celt_infantry_javelinist_e.xml
new file mode 100644
index 0000000000..61691e82d5
--- /dev/null
+++ b/binaries/data/mods/public/simulation/templates/units/celt_infantry_javelinist_e.xml
@@ -0,0 +1,6 @@
+
+
+
+ units/celts/infantry_javelinist_e.xml
+
+
diff --git a/binaries/data/mods/public/simulation/templates/units/celt_infantry_spearman_a.xml b/binaries/data/mods/public/simulation/templates/units/celt_infantry_spearman_a.xml
new file mode 100644
index 0000000000..262edd526d
--- /dev/null
+++ b/binaries/data/mods/public/simulation/templates/units/celt_infantry_spearman_a.xml
@@ -0,0 +1,6 @@
+
+
+
+ units/celts/infantry_spearman_a.xml
+
+
diff --git a/binaries/data/mods/public/simulation/templates/units/celt_infantry_spearman_b.xml b/binaries/data/mods/public/simulation/templates/units/celt_infantry_spearman_b.xml
new file mode 100644
index 0000000000..02d9b749d5
--- /dev/null
+++ b/binaries/data/mods/public/simulation/templates/units/celt_infantry_spearman_b.xml
@@ -0,0 +1,6 @@
+
+
+
+ units/celts/infantry_spearman_b.xml
+
+
diff --git a/binaries/data/mods/public/simulation/templates/units/celt_infantry_spearman_e.xml b/binaries/data/mods/public/simulation/templates/units/celt_infantry_spearman_e.xml
new file mode 100644
index 0000000000..6d88036af4
--- /dev/null
+++ b/binaries/data/mods/public/simulation/templates/units/celt_infantry_spearman_e.xml
@@ -0,0 +1,6 @@
+
+
+
+ units/celts/infantry_spearman_e.xml
+
+
diff --git a/binaries/data/mods/public/simulation/templates/units/celt_ship_merchant.xml b/binaries/data/mods/public/simulation/templates/units/celt_ship_merchant.xml
new file mode 100644
index 0000000000..f1e05c3a15
--- /dev/null
+++ b/binaries/data/mods/public/simulation/templates/units/celt_ship_merchant.xml
@@ -0,0 +1,6 @@
+
+
+
+ structures/celts/merchant.xml
+
+
diff --git a/binaries/data/mods/public/simulation/templates/units/celt_ship_trireme.xml b/binaries/data/mods/public/simulation/templates/units/celt_ship_trireme.xml
new file mode 100644
index 0000000000..fab664f12a
--- /dev/null
+++ b/binaries/data/mods/public/simulation/templates/units/celt_ship_trireme.xml
@@ -0,0 +1,6 @@
+
+
+
+ structures/celts/trireme.xml
+
+
diff --git a/binaries/data/mods/public/simulation/templates/units/celt_super_cavalry_brit.xml b/binaries/data/mods/public/simulation/templates/units/celt_super_cavalry_brit.xml
new file mode 100644
index 0000000000..c109b98f36
--- /dev/null
+++ b/binaries/data/mods/public/simulation/templates/units/celt_super_cavalry_brit.xml
@@ -0,0 +1,6 @@
+
+
+
+ units/celts/super_unit_4.xml
+
+
diff --git a/binaries/data/mods/public/simulation/templates/units/celt_super_cavalry_gaul.xml b/binaries/data/mods/public/simulation/templates/units/celt_super_cavalry_gaul.xml
new file mode 100644
index 0000000000..b508bc5aa8
--- /dev/null
+++ b/binaries/data/mods/public/simulation/templates/units/celt_super_cavalry_gaul.xml
@@ -0,0 +1,6 @@
+
+
+
+ units/celts/super_unit_2.xml
+
+
diff --git a/binaries/data/mods/public/simulation/templates/units/celt_super_infantry_brit.xml b/binaries/data/mods/public/simulation/templates/units/celt_super_infantry_brit.xml
new file mode 100644
index 0000000000..987b112054
--- /dev/null
+++ b/binaries/data/mods/public/simulation/templates/units/celt_super_infantry_brit.xml
@@ -0,0 +1,6 @@
+
+
+
+ units/celts/super_unit_3.xml
+
+
diff --git a/binaries/data/mods/public/simulation/templates/units/celt_super_infantry_gaul.xml b/binaries/data/mods/public/simulation/templates/units/celt_super_infantry_gaul.xml
new file mode 100644
index 0000000000..558c8a91c6
--- /dev/null
+++ b/binaries/data/mods/public/simulation/templates/units/celt_super_infantry_gaul.xml
@@ -0,0 +1,6 @@
+
+
+
+ units/celts/super_unit_1.xml
+
+
diff --git a/binaries/data/mods/public/simulation/templates/units/celt_support_female_citizen.xml b/binaries/data/mods/public/simulation/templates/units/celt_support_female_citizen.xml
new file mode 100644
index 0000000000..2e96b589fe
--- /dev/null
+++ b/binaries/data/mods/public/simulation/templates/units/celt_support_female_citizen.xml
@@ -0,0 +1,6 @@
+
+
+
+ units/celts/female_citizen.xml
+
+
diff --git a/binaries/data/mods/public/simulation/templates/units/celt_support_healer.xml b/binaries/data/mods/public/simulation/templates/units/celt_support_healer.xml
new file mode 100644
index 0000000000..044e80b5ee
--- /dev/null
+++ b/binaries/data/mods/public/simulation/templates/units/celt_support_healer.xml
@@ -0,0 +1,6 @@
+
+
+
+ units/celts/healer.xml
+
+
diff --git a/binaries/data/mods/public/simulation/templates/units/celt_support_trader.xml b/binaries/data/mods/public/simulation/templates/units/celt_support_trader.xml
new file mode 100644
index 0000000000..1af5e9d82f
--- /dev/null
+++ b/binaries/data/mods/public/simulation/templates/units/celt_support_trader.xml
@@ -0,0 +1,6 @@
+
+
+
+ units/celts/trader.xml
+
+
diff --git a/binaries/data/mods/public/simulation/templates/units/hele_cavalry_swordsman_a.xml b/binaries/data/mods/public/simulation/templates/units/hele_cavalry_swordsman_a.xml
new file mode 100644
index 0000000000..6cb5bd9923
--- /dev/null
+++ b/binaries/data/mods/public/simulation/templates/units/hele_cavalry_swordsman_a.xml
@@ -0,0 +1,6 @@
+
+
+
+ units/hellenes/cavalry_swordsman_a.xml
+
+
diff --git a/binaries/data/mods/public/simulation/templates/units/hele_cavalry_swordsman_b.xml b/binaries/data/mods/public/simulation/templates/units/hele_cavalry_swordsman_b.xml
new file mode 100644
index 0000000000..a88fe90f60
--- /dev/null
+++ b/binaries/data/mods/public/simulation/templates/units/hele_cavalry_swordsman_b.xml
@@ -0,0 +1,6 @@
+
+
+
+ units/hellenes/cavalry_swordsman_b.xml
+
+
diff --git a/binaries/data/mods/public/simulation/templates/units/hele_cavalry_swordsman_e.xml b/binaries/data/mods/public/simulation/templates/units/hele_cavalry_swordsman_e.xml
new file mode 100644
index 0000000000..197f26b093
--- /dev/null
+++ b/binaries/data/mods/public/simulation/templates/units/hele_cavalry_swordsman_e.xml
@@ -0,0 +1,6 @@
+
+
+
+ units/hellenes/cavalry_swordsman_e.xml
+
+
diff --git a/binaries/data/mods/public/simulation/templates/units/hele_hero_alexander.xml b/binaries/data/mods/public/simulation/templates/units/hele_hero_alexander.xml
new file mode 100644
index 0000000000..73a3d12e67
--- /dev/null
+++ b/binaries/data/mods/public/simulation/templates/units/hele_hero_alexander.xml
@@ -0,0 +1,6 @@
+
+
+
+ units/hellenes/alexander.xml
+
+
diff --git a/binaries/data/mods/public/simulation/templates/units/hele_hero_demetrius.xml b/binaries/data/mods/public/simulation/templates/units/hele_hero_demetrius.xml
new file mode 100644
index 0000000000..0ce52ddc54
--- /dev/null
+++ b/binaries/data/mods/public/simulation/templates/units/hele_hero_demetrius.xml
@@ -0,0 +1,6 @@
+
+
+
+ units/hellenes/demetrius.xml
+
+
diff --git a/binaries/data/mods/public/simulation/templates/units/hele_hero_leonidas.xml b/binaries/data/mods/public/simulation/templates/units/hele_hero_leonidas.xml
new file mode 100644
index 0000000000..43fc4cce1c
--- /dev/null
+++ b/binaries/data/mods/public/simulation/templates/units/hele_hero_leonidas.xml
@@ -0,0 +1,6 @@
+
+
+
+ units/hellenes/leonidas.xml
+
+
diff --git a/binaries/data/mods/public/simulation/templates/units/hele_hero_philip.xml b/binaries/data/mods/public/simulation/templates/units/hele_hero_philip.xml
new file mode 100644
index 0000000000..253102c126
--- /dev/null
+++ b/binaries/data/mods/public/simulation/templates/units/hele_hero_philip.xml
@@ -0,0 +1,6 @@
+
+
+
+ units/hellenes/philip_horse.xml
+
+
diff --git a/binaries/data/mods/public/simulation/templates/units/hele_hero_themistocles.xml b/binaries/data/mods/public/simulation/templates/units/hele_hero_themistocles.xml
new file mode 100644
index 0000000000..a06972f983
--- /dev/null
+++ b/binaries/data/mods/public/simulation/templates/units/hele_hero_themistocles.xml
@@ -0,0 +1,6 @@
+
+
+
+ units/hellenes/themistocles.xml
+
+
diff --git a/binaries/data/mods/public/simulation/templates/units/hele_hero_xenophon.xml b/binaries/data/mods/public/simulation/templates/units/hele_hero_xenophon.xml
new file mode 100644
index 0000000000..3350e0f570
--- /dev/null
+++ b/binaries/data/mods/public/simulation/templates/units/hele_hero_xenophon.xml
@@ -0,0 +1,6 @@
+
+
+
+ units/hellenes/xenophon.xml
+
+
diff --git a/binaries/data/mods/public/simulation/templates/units/hele_infantry_archer_a.xml b/binaries/data/mods/public/simulation/templates/units/hele_infantry_archer_a.xml
new file mode 100644
index 0000000000..e9cfc82076
--- /dev/null
+++ b/binaries/data/mods/public/simulation/templates/units/hele_infantry_archer_a.xml
@@ -0,0 +1,6 @@
+
+
+
+ units/hellenes/infantry_archer_a.xml
+
+
diff --git a/binaries/data/mods/public/simulation/templates/units/hele_infantry_archer_b.xml b/binaries/data/mods/public/simulation/templates/units/hele_infantry_archer_b.xml
new file mode 100644
index 0000000000..cd6cb76c7e
--- /dev/null
+++ b/binaries/data/mods/public/simulation/templates/units/hele_infantry_archer_b.xml
@@ -0,0 +1,6 @@
+
+
+
+ units/hellenes/infantry_archer_b.xml
+
+
diff --git a/binaries/data/mods/public/simulation/templates/units/hele_infantry_archer_e.xml b/binaries/data/mods/public/simulation/templates/units/hele_infantry_archer_e.xml
new file mode 100644
index 0000000000..29dc80f0ec
--- /dev/null
+++ b/binaries/data/mods/public/simulation/templates/units/hele_infantry_archer_e.xml
@@ -0,0 +1,6 @@
+
+
+
+ units/hellenes/infantry_archer_e.xml
+
+
diff --git a/binaries/data/mods/public/simulation/templates/units/hele_infantry_javelinist_a.xml b/binaries/data/mods/public/simulation/templates/units/hele_infantry_javelinist_a.xml
new file mode 100644
index 0000000000..56db113130
--- /dev/null
+++ b/binaries/data/mods/public/simulation/templates/units/hele_infantry_javelinist_a.xml
@@ -0,0 +1,6 @@
+
+
+
+ units/hellenes/infantry_javelinist_a.xml
+
+
diff --git a/binaries/data/mods/public/simulation/templates/units/hele_infantry_javelinist_b.xml b/binaries/data/mods/public/simulation/templates/units/hele_infantry_javelinist_b.xml
new file mode 100644
index 0000000000..631c01d4a5
--- /dev/null
+++ b/binaries/data/mods/public/simulation/templates/units/hele_infantry_javelinist_b.xml
@@ -0,0 +1,6 @@
+
+
+
+ units/hellenes/infantry_javelinist_b.xml
+
+
diff --git a/binaries/data/mods/public/simulation/templates/units/hele_infantry_javelinist_e.xml b/binaries/data/mods/public/simulation/templates/units/hele_infantry_javelinist_e.xml
new file mode 100644
index 0000000000..c303a5d4cb
--- /dev/null
+++ b/binaries/data/mods/public/simulation/templates/units/hele_infantry_javelinist_e.xml
@@ -0,0 +1,6 @@
+
+
+
+ units/hellenes/infantry_javelinist_e.xml
+
+
diff --git a/binaries/data/mods/public/simulation/templates/units/hele_infantry_spearman_a.xml b/binaries/data/mods/public/simulation/templates/units/hele_infantry_spearman_a.xml
new file mode 100644
index 0000000000..b397969c2f
--- /dev/null
+++ b/binaries/data/mods/public/simulation/templates/units/hele_infantry_spearman_a.xml
@@ -0,0 +1,6 @@
+
+
+
+ units/hellenes/infantry_spearman_a.xml
+
+
diff --git a/binaries/data/mods/public/simulation/templates/units/hele_infantry_spearman_b.xml b/binaries/data/mods/public/simulation/templates/units/hele_infantry_spearman_b.xml
new file mode 100644
index 0000000000..b14cb0eb5f
--- /dev/null
+++ b/binaries/data/mods/public/simulation/templates/units/hele_infantry_spearman_b.xml
@@ -0,0 +1,6 @@
+
+
+
+ units/hellenes/infantry_spearman_b.xml
+
+
diff --git a/binaries/data/mods/public/simulation/templates/units/hele_infantry_spearman_e.xml b/binaries/data/mods/public/simulation/templates/units/hele_infantry_spearman_e.xml
new file mode 100644
index 0000000000..ea937830b2
--- /dev/null
+++ b/binaries/data/mods/public/simulation/templates/units/hele_infantry_spearman_e.xml
@@ -0,0 +1,6 @@
+
+
+
+ units/hellenes/infantry_spearman_e.xml
+
+
diff --git a/binaries/data/mods/public/simulation/templates/units/hele_mechanical_siege_helepolis.xml b/binaries/data/mods/public/simulation/templates/units/hele_mechanical_siege_helepolis.xml
new file mode 100644
index 0000000000..028edfa525
--- /dev/null
+++ b/binaries/data/mods/public/simulation/templates/units/hele_mechanical_siege_helepolis.xml
@@ -0,0 +1,6 @@
+
+
+
+ units/hellenes/mechanical_siege_ram.xml
+
+
diff --git a/binaries/data/mods/public/simulation/templates/units/hele_mechanical_siege_lithobolos.xml b/binaries/data/mods/public/simulation/templates/units/hele_mechanical_siege_lithobolos.xml
new file mode 100644
index 0000000000..8e534a61d1
--- /dev/null
+++ b/binaries/data/mods/public/simulation/templates/units/hele_mechanical_siege_lithobolos.xml
@@ -0,0 +1,6 @@
+
+
+
+ units/hellenes/siege_rock.xml
+
+
diff --git a/binaries/data/mods/public/simulation/templates/units/hele_mechanical_siege_oxybeles.xml b/binaries/data/mods/public/simulation/templates/units/hele_mechanical_siege_oxybeles.xml
new file mode 100644
index 0000000000..9054add078
--- /dev/null
+++ b/binaries/data/mods/public/simulation/templates/units/hele_mechanical_siege_oxybeles.xml
@@ -0,0 +1,6 @@
+
+
+
+ units/hellenes/siege_spear.xml
+
+
diff --git a/binaries/data/mods/public/simulation/templates/units/hele_ship_bireme.xml b/binaries/data/mods/public/simulation/templates/units/hele_ship_bireme.xml
new file mode 100644
index 0000000000..22065de663
--- /dev/null
+++ b/binaries/data/mods/public/simulation/templates/units/hele_ship_bireme.xml
@@ -0,0 +1,6 @@
+
+
+
+ structures/hellenes/bireme.xml
+
+
diff --git a/binaries/data/mods/public/simulation/templates/units/hele_ship_merchant.xml b/binaries/data/mods/public/simulation/templates/units/hele_ship_merchant.xml
new file mode 100644
index 0000000000..9a5c7e67b4
--- /dev/null
+++ b/binaries/data/mods/public/simulation/templates/units/hele_ship_merchant.xml
@@ -0,0 +1,6 @@
+
+
+
+ structures/hellenes/merchant.xml
+
+
diff --git a/binaries/data/mods/public/simulation/templates/units/hele_ship_trireme.xml b/binaries/data/mods/public/simulation/templates/units/hele_ship_trireme.xml
new file mode 100644
index 0000000000..51c42de19e
--- /dev/null
+++ b/binaries/data/mods/public/simulation/templates/units/hele_ship_trireme.xml
@@ -0,0 +1,6 @@
+
+
+
+ structures/hellenes/trireme.xml
+
+
diff --git a/binaries/data/mods/public/simulation/templates/units/hele_ship_trireme_corinthian.xml b/binaries/data/mods/public/simulation/templates/units/hele_ship_trireme_corinthian.xml
new file mode 100644
index 0000000000..9c1ba11af4
--- /dev/null
+++ b/binaries/data/mods/public/simulation/templates/units/hele_ship_trireme_corinthian.xml
@@ -0,0 +1,6 @@
+
+
+
+ structures/hellenes/trireme_cor.xml
+
+
diff --git a/binaries/data/mods/public/simulation/templates/units/hele_super_cavalry_mace.xml b/binaries/data/mods/public/simulation/templates/units/hele_super_cavalry_mace.xml
new file mode 100644
index 0000000000..27ea93ed03
--- /dev/null
+++ b/binaries/data/mods/public/simulation/templates/units/hele_super_cavalry_mace.xml
@@ -0,0 +1,6 @@
+
+
+
+ units/hellenes/super_unit_4.xml
+
+
diff --git a/binaries/data/mods/public/simulation/templates/units/hele_super_infantry_mace.xml b/binaries/data/mods/public/simulation/templates/units/hele_super_infantry_mace.xml
new file mode 100644
index 0000000000..33a76af488
--- /dev/null
+++ b/binaries/data/mods/public/simulation/templates/units/hele_super_infantry_mace.xml
@@ -0,0 +1,6 @@
+
+
+
+ units/hellenes/super_unit_3.xml
+
+
diff --git a/binaries/data/mods/public/simulation/templates/units/hele_super_infantry_polis.xml b/binaries/data/mods/public/simulation/templates/units/hele_super_infantry_polis.xml
new file mode 100644
index 0000000000..d5e7666cf3
--- /dev/null
+++ b/binaries/data/mods/public/simulation/templates/units/hele_super_infantry_polis.xml
@@ -0,0 +1,6 @@
+
+
+
+ units/hellenes/super_unit_1.xml
+
+
diff --git a/binaries/data/mods/public/simulation/templates/units/hele_super_ranged_polis.xml b/binaries/data/mods/public/simulation/templates/units/hele_super_ranged_polis.xml
new file mode 100644
index 0000000000..2f62b08474
--- /dev/null
+++ b/binaries/data/mods/public/simulation/templates/units/hele_super_ranged_polis.xml
@@ -0,0 +1,6 @@
+
+
+
+ units/hellenes/super_unit_2.xml
+
+
diff --git a/binaries/data/mods/public/simulation/templates/units/hele_support_female_citizen.xml b/binaries/data/mods/public/simulation/templates/units/hele_support_female_citizen.xml
new file mode 100644
index 0000000000..539135761f
--- /dev/null
+++ b/binaries/data/mods/public/simulation/templates/units/hele_support_female_citizen.xml
@@ -0,0 +1,6 @@
+
+
+
+ units/hellenes/female_citizen.xml
+
+
diff --git a/binaries/data/mods/public/simulation/templates/units/hele_support_healer.xml b/binaries/data/mods/public/simulation/templates/units/hele_support_healer.xml
new file mode 100644
index 0000000000..191fe8a6eb
--- /dev/null
+++ b/binaries/data/mods/public/simulation/templates/units/hele_support_healer.xml
@@ -0,0 +1,6 @@
+
+
+
+ units/hellenes/healer.xml
+
+
diff --git a/binaries/data/mods/public/simulation/templates/units/hele_support_trader.xml b/binaries/data/mods/public/simulation/templates/units/hele_support_trader.xml
new file mode 100644
index 0000000000..21045d2cec
--- /dev/null
+++ b/binaries/data/mods/public/simulation/templates/units/hele_support_trader.xml
@@ -0,0 +1,6 @@
+
+
+
+ units/hellenes/trader.xml
+
+
diff --git a/binaries/data/tests/test_setup.js b/binaries/data/tests/test_setup.js
new file mode 100644
index 0000000000..e43d78b3e6
--- /dev/null
+++ b/binaries/data/tests/test_setup.js
@@ -0,0 +1,39 @@
+// The engine provides:
+// Engine.TS_FAIL = function(msg) { ... }
+//
+// This file define global helper functions for common test assertions.
+// (Functions should be defined with local names too, so they show up properly
+// in stack traces.)
+
+function fail(msg)
+{
+ // Get a list of callers
+ var trace = (new Error).stack.split("\n");
+ // Remove the Error ctor and this function from the stack
+ trace = trace.splice(2);
+ print("Stack trace:\n" + trace.join("\n"));
+ Engine.TS_FAIL(msg);
+}
+
+global.TS_FAIL = function TS_FAIL(msg)
+{
+ fail(msg);
+}
+
+global.TS_ASSERT = function TS_ASSERT(e)
+{
+ if (!e)
+ fail("Assert failed");
+}
+
+global.TS_ASSERT_EQUALS = function TS_ASSERT_EQUALS(x, y)
+{
+ if (!(x === y))
+ fail("Expected equal, got "+uneval(x)+" !== "+uneval(y));
+}
+
+global.TS_ASSERT_UNEVAL_EQUALS = function TS_ASSERT_UNEVAL_EQUALS(x, y)
+{
+ if (!(uneval(x) === uneval(y)))
+ fail("Expected equal, got "+uneval(x)+" !== "+uneval(y));
+}
diff --git a/binaries/data/tools/atlas/scripts/section/map.js b/binaries/data/tools/atlas/scripts/section/map.js
index db83b84267..d33b732fc2 100644
--- a/binaries/data/tools/atlas/scripts/section/map.js
+++ b/binaries/data/tools/atlas/scripts/section/map.js
@@ -49,6 +49,38 @@ function setupSimTest(window)
}
updateEnableStatus();
window.sizer.add(sizer, 0, wxStretch.EXPAND | wxDirection.LEFT|wxDirection.RIGHT, 2);
+
+ var dumpDisplayButton = new wxButton(window, -1, 'Display sim state');
+ dumpDisplayButton.onClicked = function ()
+ {
+ var state = Atlas.Message.SimStateDebugDump(false).dump;
+ if (state.length > 10240) // avoid giant message boxes that crash
+ state = state.substr(0, 10240)+"...";
+ wxMessageBox(state);
+ };
+ window.sizer.add(dumpDisplayButton);
+
+ var dumpButton = new wxButton(window, -1, 'Dump sim state to disk');
+ dumpButton.toolTip = 'Saves to sim-dump-$(TIMESTAMP).txt in working directory';
+ dumpButton.onClicked = function () {
+ var filename = 'sim-dump-' + (new Date().getTime()) + '.txt';
+ var state = Atlas.Message.SimStateDebugDump(false).dump;
+ var file = new wxFFile(filename, 'w'); // TODO: error check
+ file.write(state);
+ file.close();
+ };
+ window.sizer.add(dumpButton);
+
+ var dumpBinButton = new wxButton(window, -1, 'Dump binary sim state to disk');
+ dumpBinButton.toolTip = 'Saves to sim-dump-$(TIMESTAMP).dat in working directory';
+ dumpBinButton.onClicked = function () {
+ var filename = 'sim-dump-' + (new Date().getTime()) + '.dat';
+ var state = Atlas.Message.SimStateDebugDump(true).dump;
+ var file = new wxFFile(filename, 'w'); // TODO: error check
+ file.write(state);
+ file.close();
+ };
+ window.sizer.add(dumpBinButton);
}
function generateRMS(name)
diff --git a/build/docs/builddoc.bat b/build/docs/builddoc.bat
index a7c59b7b72..3c782e6bb0 100644
--- a/build/docs/builddoc.bat
+++ b/build/docs/builddoc.bat
@@ -1 +1 @@
-"cppdoc_cmd.exe" -overwrite -autoview -autoquit -title="0 A.D." -company="Wildfire Games" -hier -include-const -include-anonymous -document-preprocessor -comment-format="/**;*;*/;AFTER///;//;///" -classdir=projects -module="cppdoc-standard" -extensions="cpp,h" -languages="cpp=cpp,h=cpp" -enable-author=true -enable-deprecations=true -enable-since=true -enable-version=true -file-links-for-globals=true -generate-deprecations-list=true -generate-hierarchy=true -header-background-dark="#ccccff" -header-background-light="#eeeeff" -include-private=true -include-protected=true -index-file-base=index -overview-html=overview.html -reduce-summary-font=true -selected-text-background=navy -selected-text-foreground=white -separate-index-pages=true -show-cppdoc-version=true -show-timestamp=true -summary-html=project.html -suppress-details=false -suppress-frames-links=false -table-background=white -wrap-long-lines=true "..\..\source" #"..\..\source\tools" #"..\..\source\i18n\tests2" "..\..\docs\generated\index.html"
+"cppdoc_cmd.exe" -overwrite -autoview -autoquit -title="0 A.D." -company="Wildfire Games" -hier -include-const -include-anonymous -document-preprocessor -comment-format="/**;*;*/;AFTER///;//;///" -classdir=projects -module="cppdoc-standard" -extensions="cpp,h" -languages="cpp=cpp,h=cpp" -enable-author=true -enable-deprecations=true -enable-since=true -enable-version=true -file-links-for-globals=true -generate-deprecations-list=true -generate-hierarchy=true -header-background-dark="#ccccff" -header-background-light="#eeeeff" -include-private=true -include-protected=true -index-file-base=index -overview-html=overview.html -reduce-summary-font=true -selected-text-background=navy -selected-text-foreground=white -separate-index-pages=true -show-cppdoc-version=true -show-timestamp=true -summary-html=project.html -suppress-details=false -suppress-frames-links=false -table-background=white -wrap-long-lines=true "..\..\source" #"..\..\source\tools" #"..\..\source\i18n\tests2" #"..\..\source\dcdt" "..\..\docs\generated\index.html"
diff --git a/build/docs/builddoc.sh b/build/docs/builddoc.sh
index 52d60b541c..75b0189c2e 100755
--- a/build/docs/builddoc.sh
+++ b/build/docs/builddoc.sh
@@ -1 +1 @@
-./cppdoc -overwrite -autoview -autoquit -title="0 A.D." -company="Wildfire Games" -hier -include-const -include-anonymous -document-preprocessor -comment-format="/**;*;*/;AFTER///;//;///" -classdir=projects -module="cppdoc-standard" -extensions="cpp,h" -languages="cpp=cpp,h=cpp" -enable-author=true -enable-deprecations=true -enable-since=true -enable-version=true -file-links-for-globals=true -generate-deprecations-list=true -generate-hierarchy=true -header-background-dark="#ccccff" -header-background-light="#eeeeff" -include-private=true -include-protected=true -index-file-base=index -overview-html=overview.html -reduce-summary-font=true -selected-text-background=navy -selected-text-foreground=white -separate-index-pages=true -show-cppdoc-version=true -show-timestamp=true -summary-html=project.html -suppress-details=false -suppress-frames-links=false -table-background=white -wrap-long-lines=true "../../source" \#"../../source/tools" \#"../../source/i18n/tests2" "../../docs/generated/index.html"
\ No newline at end of file
+./cppdoc -overwrite -autoview -autoquit -title="0 A.D." -company="Wildfire Games" -hier -include-const -include-anonymous -document-preprocessor -comment-format="/**;*;*/;AFTER///;//;///" -classdir=projects -module="cppdoc-standard" -extensions="cpp,h" -languages="cpp=cpp,h=cpp" -enable-author=true -enable-deprecations=true -enable-since=true -enable-version=true -file-links-for-globals=true -generate-deprecations-list=true -generate-hierarchy=true -header-background-dark="#ccccff" -header-background-light="#eeeeff" -include-private=true -include-protected=true -index-file-base=index -overview-html=overview.html -reduce-summary-font=true -selected-text-background=navy -selected-text-foreground=white -separate-index-pages=true -show-cppdoc-version=true -show-timestamp=true -summary-html=project.html -suppress-details=false -suppress-frames-links=false -table-background=white -wrap-long-lines=true "../../source" \#"../../source/tools" \#"../../source/i18n/tests2" \#"../../source/dcdt" "../../docs/generated/index.html"
\ No newline at end of file
diff --git a/build/errorlist/errorlist.exe b/build/errorlist/errorlist.exe
deleted file mode 100755
index 1a9e9045fa..0000000000
Binary files a/build/errorlist/errorlist.exe and /dev/null differ
diff --git a/build/errorlist/errorlist.pl b/build/errorlist/errorlist.pl
index 9a3486a712..015a1ed2f8 100755
--- a/build/errorlist/errorlist.pl
+++ b/build/errorlist/errorlist.pl
@@ -1,4 +1,4 @@
-#!perl -w
+#!/usr/bin/perl -w
++$|;
END { print "\n\nPress enter to exit.\n"; }
@@ -74,21 +74,21 @@ print $out <<'.';
.
for (sort keys %topgroups) {
- print $out "class PSERROR_$_ : public PSERROR {};\n";
+ print $out "class PSERROR_$_ : public PSERROR { protected: PSERROR_$_(const char* msg); };\n";
}
print $out "\n";
for (sort { $a->[1] cmp $b->[1] } map [$_, do{(my $c=$_)=~s/~/_/;$c} ], keys %groups) {
my ($base, $name) = split /~/, $_->[0];
- print $out "class PSERROR_${base}_$name : public PSERROR_$base {};\n";
+ print $out "class PSERROR_${base}_$name : public PSERROR_$base { protected: PSERROR_${base}_$name(const char* msg); };\n";
}
print $out "\n";
for (sort { $a->[1] cmp $b->[1] } map [$_, do{(my $c=$_)=~s/~/_/;$c} ], keys %types) {
my ($base, $name) = split /~/, $_->[0];
- print $out "class PSERROR_${base}_$name : public PSERROR_$base { public: PSRETURN getCode() const; };\n";
+ print $out "class PSERROR_${base}_$name : public PSERROR_$base { public: PSERROR_${base}_$name(); PSERROR_${base}_$name(const char* msg); PSRETURN getCode() const; };\n";
}
print $out "\n";
@@ -179,22 +179,32 @@ for (sort keys %types) {
print $out "\n";
+for (sort keys %topgroups) {
+ print $out "PSERROR_${_}::PSERROR_${_}(const char* msg) : PSERROR(msg) { }\n";
+}
+
+for (sort keys %groups) {
+ my ($base, $name) = split /~/;
+ print $out "PSERROR_${base}_${name}::PSERROR_${base}_${name}(const char* msg) : PSERROR_$base(msg) { }\n";
+}
+
+print $out "\n";
for (sort keys %types) {
my ($base, $name) = split /~/;
- print $out qq~PSRETURN PSERROR_${base}_${name}::getCode() const { return 0x~.unpack('H*',$types{$_}).qq~; }\n~;
+ print $out "PSERROR_${base}_${name}::PSERROR_${base}_${name}() : PSERROR_$base(NULL) { }\n";
+ print $out "PSERROR_${base}_${name}::PSERROR_${base}_${name}(const char* msg) : PSERROR_$base(msg) { }\n";
+ print $out "PSRETURN PSERROR_${base}_${name}::getCode() const { return 0x".unpack('H*',$types{$_})."; }\n";
+ print $out "\n";
}
print $out <<".";
+PSERROR::PSERROR(const char* msg) : m_msg(msg) { }
+
const char* PSERROR::what() const throw ()
{
- return GetErrorString(getCode());
-}
-
-const char* GetErrorString(const PSERROR& err)
-{
- return GetErrorString(err.getCode());
+ return m_msg ? m_msg : GetErrorString(getCode());
}
const char* GetErrorString(PSRETURN code)
diff --git a/build/premake/extern_libs.lua b/build/premake/extern_libs.lua
index 6e05701021..4ca09d9c88 100644
--- a/build/premake/extern_libs.lua
+++ b/build/premake/extern_libs.lua
@@ -75,6 +75,8 @@ extern_lib_defs = {
osx_names = { "boost_signals-mt", "boost_filesystem-mt", "boost_system-mt" }
},
cryptopp = {
+ win_names = { "cryptopp" },
+ unix_names = { "cryptopp" },
},
cxxtest = {
},
diff --git a/build/premake/premake.lua b/build/premake/premake.lua
index ef36fce4bb..b0bb784c6e 100755
--- a/build/premake/premake.lua
+++ b/build/premake/premake.lua
@@ -208,7 +208,7 @@ function package_set_build_flags()
end
-- To use our local SpiderMonkey library, it needs to be part of the runtime dynamic linker
- -- path. So try to add the cwd (assuming it'll be binaries/system/) with -rpath
+ -- path. So try to add the cwd (assuming it'll be binaries/system/) with -rpath:
-- (TODO: is this a sane way to do it?)
tinsert(package.linkoptions, {"-Wl,-rpath=."})
@@ -405,6 +405,34 @@ function setup_all_libs ()
}
setup_static_lib_package("network", source_dirs, extern_libs, {})
+
+ source_dirs = {
+ "simulation2",
+ "simulation2/components",
+ "simulation2/helpers",
+ "simulation2/scripting",
+ "simulation2/serialization",
+ "simulation2/system",
+ "simulation2/testcomponents",
+ }
+ extern_libs = {
+ "boost",
+ "cryptopp",
+ "spidermonkey",
+ }
+ setup_static_lib_package("simulation2", source_dirs, extern_libs, {})
+
+
+ source_dirs = {
+ "scriptinterface",
+ }
+ extern_libs = {
+ "boost",
+ "spidermonkey",
+ }
+ setup_static_lib_package("scriptinterface", source_dirs, extern_libs, {})
+
+
source_dirs = {
"ps",
"ps/scripting",
@@ -587,6 +615,7 @@ used_extern_libs = {
"cxxtest",
"comsuppw",
"enet",
+ "cryptopp",
}
-- Bundles static libs together with main.cpp and builds game executable.
diff --git a/docs/doxygen/config b/docs/doxygen/config
new file mode 100644
index 0000000000..d514b37705
--- /dev/null
+++ b/docs/doxygen/config
@@ -0,0 +1,28 @@
+PROJECT_NAME = Pyrogenesis
+PROJECT_NUMBER = trunk
+
+TAB_SIZE = 4
+
+INPUT = ../../source/simulation2 ../../source/scriptinterface
+INCLUDE_PATH = ../../source
+EXAMPLE_PATH = ../../source
+RECURSIVE = YES
+EXCLUDE_PATTERNS = */.svn* */tests/test_*
+EXCLUDE = ../../source/dcdt ../../source/tools ../../source/i18n/tests2
+
+JAVADOC_AUTOBRIEF = YES
+
+EXTRACT_ALL = YES
+EXTRACT_PRIVATE = YES
+EXTRACT_STATIC = YES
+EXTRACT_ANON_NSPACES = YES
+
+SHOW_DIRECTORIES = YES
+STRIP_CODE_COMMENTS = NO
+GENERATE_LATEX = NO
+
+MACRO_EXPANSION = YES
+EXPAND_ONLY_PREDEF = YES
+PREDEFINED = "UNUSED(x)=x"
+EXPAND_AS_DEFINED += DEFAULT_COMPONENT_ALLOCATOR DEFAULT_SCRIPT_WRAPPER DEFAULT_INTERFACE_WRAPPER DEFAULT_MESSAGE_IMPL
+EXPAND_AS_DEFINED += MESSAGE INTERFACE COMPONENT
diff --git a/source/graphics/GameView.cpp b/source/graphics/GameView.cpp
index b2adf4d836..ccfd4c4a05 100644
--- a/source/graphics/GameView.cpp
+++ b/source/graphics/GameView.cpp
@@ -56,6 +56,8 @@
#include "simulation/EntityOrders.h"
#include "simulation/LOSManager.h"
#include "simulation/Projectile.h"
+#include "simulation2/Simulation2.h"
+#include "simulation2/MessageTypes.h"
float g_MaxZoomHeight=350.0f; //note: Max terrain height is this minus YMinOffset
float g_YMinOffset=15.0f;
@@ -389,7 +391,18 @@ void CGameView::EnumerateObjects(const CFrustum& frustum, SceneCollector* c)
}
PROFILE_END( "submit terrain" );
+ if (g_UseSimulation2)
+ {
+ PROFILE_START( "submit sim components" );
+ m->Game->GetSimulation2()->BroadcastMessage(CMessageRenderSubmit(*c, frustum, m->Culling));
+ PROFILE_END( "submit sim components" );
+ return;
+ }
+
+ // Old simulation:
+
PROFILE_START( "submit models" );
+
CWorld* world = m->Game->GetWorld();
CUnitManager& unitMan = world->GetUnitManager();
CProjectileManager& pProjectileMan = world->GetProjectileManager();
diff --git a/source/graphics/MapIO.h b/source/graphics/MapIO.h
index 71a72cc243..46326a2400 100644
--- a/source/graphics/MapIO.h
+++ b/source/graphics/MapIO.h
@@ -22,7 +22,7 @@ class CMapIO
{
public:
// current file version given to saved maps
- enum { FILE_VERSION = 4 };
+ enum { FILE_VERSION = 5 };
// supported file read version - file with version less than this will be reject
enum { FILE_READ_VERSION = 1 };
@@ -36,14 +36,6 @@ public:
// priority
u32 m_Priority;
};
-
- // description of an object for I/O purposes
- struct SObjectDesc {
- // index into the object array
- u16 m_ObjectIndex;
- // transformation matrix
- float m_Transform[16];
- };
#pragma pack(pop)
};
diff --git a/source/graphics/MapReader.cpp b/source/graphics/MapReader.cpp
index 24454a2714..192a1ec5b1 100644
--- a/source/graphics/MapReader.cpp
+++ b/source/graphics/MapReader.cpp
@@ -44,6 +44,8 @@
#include "simulation/TriggerManager.h"
#include "simulation/EntityTemplate.h"
#include "simulation/EntityTemplateCollection.h"
+#include "simulation2/Simulation2.h"
+#include "simulation2/components/ICmpPosition.h"
#define LOG_CATEGORY L"graphics"
@@ -77,7 +79,14 @@ void CMapReader::LoadMap(const VfsPath& pathname, CTerrain *pTerrain_,
}
// delete all existing entities
- g_EntityManager.DeleteAll();
+ if (g_UseSimulation2)
+ {
+ g_Game->GetSimulation2()->ResetState();
+ }
+ else
+ {
+ g_EntityManager.DeleteAll();
+ }
// delete all remaining non-entity units
pUnitMan->DeleteAll();
pUnitMan->SetNextID(0);
@@ -106,41 +115,11 @@ int CMapReader::UnpackMap()
return ret;
if (unpacker.GetVersion() < 4)
- UnpackObjects();
-
- if (unpacker.GetVersion() >= 2 && unpacker.GetVersion() < 4)
- UnpackLightEnv();
+ debug_warn(L"Old unsupported map version - objects and lighting will be lost");
return 0;
}
-// UnpackLightEnv: unpack lighting parameters from input stream
-void CMapReader::UnpackLightEnv()
-{
- unpacker.UnpackRaw(&m_LightEnv.m_SunColor, sizeof(m_LightEnv.m_SunColor));
- unpacker.UnpackRaw(&m_LightEnv.m_Elevation, sizeof(m_LightEnv.m_Elevation));
- unpacker.UnpackRaw(&m_LightEnv.m_Rotation, sizeof(m_LightEnv.m_Rotation));
- unpacker.UnpackRaw(&m_LightEnv.m_TerrainAmbientColor, sizeof(m_LightEnv.m_TerrainAmbientColor));
- unpacker.UnpackRaw(&m_LightEnv.m_UnitsAmbientColor, sizeof(m_LightEnv.m_UnitsAmbientColor));
- m_LightEnv.CalculateSunDirection();
-}
-
-// UnpackObjects: unpack world objects from input stream
-void CMapReader::UnpackObjects()
-{
- // unpack object types
- const size_t numObjTypes = unpacker.UnpackSize();
- m_ObjectTypes.resize(numObjTypes);
- for (size_t i=0; i selections; // TODO: read from file
- CUnit* unit = pUnitMan->CreateUnit(m_ObjectTypes.at(m_Objects[i].m_ObjectIndex), NULL, selections);
-
- if (unit)
- {
- CMatrix3D transform;
- cpu_memcpy(&transform._11, m_Objects[i].m_Transform, sizeof(float)*16);
- unit->GetModel()->SetTransform(transform);
- }
+ // Make units start out conforming correctly
+ g_EntityManager.ConformAll();
}
- //Make units start out conforming correctly
- g_EntityManager.ConformAll();
- if (unpacker.GetVersion() >= 2)
+ if (unpacker.GetVersion() >= 4)
{
// copy over the lighting parameters
*pLightEnv = m_LightEnv;
@@ -302,6 +263,7 @@ private:
void ReadTriggers(XMBElement parent);
void ReadTriggerGroup(XMBElement parent, MapTriggerGroup& group);
int ReadEntities(XMBElement parent, double end_time);
+ int ReadOldEntities(XMBElement parent, double end_time);
int ReadNonEntities(XMBElement parent, double end_time);
};
@@ -802,7 +764,85 @@ int CXMLReader::ReadEntities(XMBElement parent, double end_time)
{
XMBElementList entities = parent.GetChildNodes();
- // If this is the first time in ReadEntities, find the next free ID number
+ while (entity_idx < entities.Count)
+ {
+ // all new state at this scope and below doesn't need to be
+ // wrapped, since we only yield after a complete iteration.
+
+ XMBElement entity = entities.Item(entity_idx++);
+ debug_assert(entity.GetNodeName() == el_entity);
+
+ XMBAttributeList attrs = entity.GetAttributes();
+ utf16string uid = attrs.GetNamedItem(at_uid);
+ debug_assert(!uid.empty());
+ int EntityUid = CStr(uid).ToInt();
+
+ CStrW TemplateName;
+ CFixedVector3D Position;
+ CFixedVector3D Orientation;
+
+ XERO_ITER_EL(entity, setting)
+ {
+ int element_name = setting.GetNodeName();
+
+ //
+ if (element_name == el_template)
+ {
+ TemplateName = setting.GetText();
+ }
+ //
+ else if (element_name == el_position)
+ {
+ XMBAttributeList attrs = setting.GetAttributes();
+ Position = CFixedVector3D(
+ CFixed_23_8::FromFloat(CStr(attrs.GetNamedItem(at_x)).ToFloat()),
+ CFixed_23_8::FromFloat(CStr(attrs.GetNamedItem(at_y)).ToFloat()),
+ CFixed_23_8::FromFloat(CStr(attrs.GetNamedItem(at_z)).ToFloat()));
+ // TODO: shouldn't use floats here
+ }
+ //
+ else if (element_name == el_orientation)
+ {
+ XMBAttributeList attrs = setting.GetAttributes();
+ Orientation = CFixedVector3D(
+ CFixed_23_8::FromFloat(CStr(attrs.GetNamedItem(at_x)).ToFloat()),
+ CFixed_23_8::FromFloat(CStr(attrs.GetNamedItem(at_y)).ToFloat()),
+ CFixed_23_8::FromFloat(CStr(attrs.GetNamedItem(at_z)).ToFloat()));
+ // TODO: shouldn't use floats here
+ // TODO: what happens if some attributes are missing?
+ }
+ else
+ debug_warn(L"Invalid map XML data");
+ }
+
+ CSimulation2& sim = *g_Game->GetSimulation2();
+ entity_id_t ent = sim.AddEntity(TemplateName, EntityUid);
+ if (ent == INVALID_ENTITY)
+ LOGERROR(L"Failed to load entity template '%ls'", TemplateName.c_str());
+ else
+ {
+ CmpPtr cmpPosition(sim, ent);
+ if (!cmpPosition.null())
+ {
+ cmpPosition->JumpTo(Position.X, Position.Z);
+ cmpPosition->SetYRotation(Orientation.Y);
+ // TODO: other components
+ }
+ // TODO: load all the other data too
+ }
+
+ completed_jobs++;
+ LDR_CHECK_TIMEOUT(completed_jobs, total_jobs);
+ }
+
+ return 0;
+}
+
+int CXMLReader::ReadOldEntities(XMBElement parent, double end_time)
+{
+ XMBElementList entities = parent.GetChildNodes();
+
+ // If this is the first time in ReadOldEntities, find the next free ID number
// in case we need to allocate new ones in the future
if (entity_idx == 0)
{
@@ -878,19 +918,56 @@ int CXMLReader::ReadEntities(XMBElement parent, double end_time)
{
std::set selections; // TODO: read from file
- HEntity ent = g_EntityManager.Create(base, Position, Orientation, selections);
+ if (g_UseSimulation2)
+ {
+ // The old version uses a flat entity naming system, so we need
+ // to translate it into the hierarchical filename
+ if (TemplateName.Find(L"flora") == 0 || TemplateName.Find(L"fauna") == 0 || TemplateName.Find(L"geology") == 0 || TemplateName.Find(L"special") == 0)
+ TemplateName = L"gaia/" + TemplateName;
+ else if (TemplateName.Find(L"cart") == 0 || TemplateName.Find(L"celt") == 0 || TemplateName.Find(L"hele") == 0 ||
+ TemplateName.Find(L"iber") == 0 || TemplateName.Find(L"pers") == 0 || TemplateName.Find(L"rome") == 0)
+ {
+ if (TemplateName.Find(L"cavalry") == 5 || TemplateName.Find(L"hero") == 5 || TemplateName.Find(L"infantry") == 5 ||
+ TemplateName.Find(L"mechanical") == 5 || TemplateName.Find(L"ship") == 5 || TemplateName.Find(L"super") == 5 || TemplateName.Find(L"support") == 5)
+ TemplateName = L"units/" + TemplateName;
+ else
+ TemplateName = L"structures/" + TemplateName;
+ }
+ else if (TemplateName.Find(L"skeleton") == 0)
+ TemplateName = L"units/" + TemplateName;
+ else if (TemplateName.Find(L"camp") == 0 || TemplateName.Find(L"fence") == 0 || TemplateName.Find(L"temp") == 0)
+ TemplateName = L"other/" + TemplateName;
- if (! ent)
- LOG(CLogger::Error, LOG_CATEGORY, L"Failed to create entity of type '%ls'", TemplateName.c_str());
+ entity_id_t ent = g_Game->GetSimulation2()->AddEntity(TemplateName);
+ if (ent != INVALID_ENTITY)
+ {
+ CmpPtr cmpPos(*g_Game->GetSimulation2(), ent);
+ if (!cmpPos.null())
+ {
+ entity_pos_t x = entity_pos_t::FromFloat(Position.X);
+ entity_pos_t z = entity_pos_t::FromFloat(Position.Z);
+ cmpPos->JumpTo(x, z);
+ cmpPos->SetYRotation(CFixed_23_8::FromFloat(Orientation));
+ }
+ // TODO: load player ID too
+ }
+ }
else
{
- ent->m_actor->SetPlayerID(PlayerID);
- g_EntityManager.AddEntityClassData(ent);
+ HEntity ent = g_EntityManager.Create(base, Position, Orientation, selections);
- if (unitId < 0)
- ent->m_actor->SetID(m_MapReader.pUnitMan->GetNewID());
+ if (! ent)
+ LOG(CLogger::Error, LOG_CATEGORY, L"Failed to create entity of type '%ls'", TemplateName.c_str());
else
- ent->m_actor->SetID(unitId);
+ {
+ ent->m_actor->SetPlayerID(PlayerID);
+ g_EntityManager.AddEntityClassData(ent);
+
+ if (unitId < 0)
+ ent->m_actor->SetID(m_MapReader.pUnitMan->GetNewID());
+ else
+ ent->m_actor->SetID(unitId);
+ }
}
}
@@ -913,7 +990,7 @@ int CXMLReader::ReadNonEntities(XMBElement parent, double end_time)
XMBElement nonentity = nonentities.Item(nonentity_idx++);
debug_assert(nonentity.GetNodeName() == el_nonentity);
- CStr ActorName;
+ CStrW ActorName;
CVector3D Position;
float Orientation = 0.f;
@@ -947,18 +1024,36 @@ int CXMLReader::ReadNonEntities(XMBElement parent, double end_time)
std::set selections; // TODO: read from file
- CUnit* unit = m_MapReader.pUnitMan->CreateUnit(ActorName, NULL, selections);
-
- if (unit)
+ if (g_UseSimulation2)
{
- CMatrix3D m;
- m.SetYRotation(Orientation + PI);
- m.Translate(Position);
- unit->GetModel()->SetTransform(m);
+ entity_id_t ent = g_Game->GetSimulation2()->AddEntity(L"actor|" + ActorName);
+ if (ent != INVALID_ENTITY)
+ {
+ CmpPtr cmpPos(*g_Game->GetSimulation2(), ent);
+ if (!cmpPos.null())
+ {
+ entity_pos_t x = entity_pos_t::FromFloat(Position.X); // TODO: these should all be parsed as fixeds probably
+ entity_pos_t z = entity_pos_t::FromFloat(Position.Z);
+ cmpPos->JumpTo(x, z);
+ cmpPos->SetYRotation(CFixed_23_8::FromFloat(Orientation));
+ }
+ }
+ }
+ else
+ {
+ CUnit* unit = m_MapReader.pUnitMan->CreateUnit(ActorName, NULL, selections);
- // TODO: save object IDs in the map file, and load them again,
- // so that triggers have a persistent identifier for objects
- unit->SetID(m_MapReader.pUnitMan->GetNewID());
+ if (unit)
+ {
+ CMatrix3D m;
+ m.SetYRotation(Orientation + PI);
+ m.Translate(Position);
+ unit->GetModel()->SetTransform(m);
+
+ // TODO: save object IDs in the map file, and load them again,
+ // so that triggers have a persistent identifier for objects
+ unit->SetID(m_MapReader.pUnitMan->GetNewID());
+ }
}
completed_jobs++;
@@ -989,18 +1084,24 @@ int CXMLReader::ProgressiveRead()
{
ReadCamera(node);
}
- else if (name == "Entities")
+ else if (m_MapReader.unpacker.GetVersion() <= 4 && name == "Entities")
{
- ret = ReadEntities(node, end_time);
+ ret = ReadOldEntities(node, end_time);
if (ret != 0) // error or timed out
return ret;
}
- else if (name == "Nonentities")
+ else if (m_MapReader.unpacker.GetVersion() <= 4 && name == "Nonentities")
{
ret = ReadNonEntities(node, end_time);
if (ret != 0) // error or timed out
return ret;
}
+ else if (name == "Entities")
+ {
+ ret = ReadEntities(node, end_time);
+ if (ret != 0) // error or timed out
+ return ret;
+ }
else if (name == "Paths")
{
ReadCinema(node);
diff --git a/source/graphics/MapReader.h b/source/graphics/MapReader.h
index 9bb8a2f17b..27a69ca344 100644
--- a/source/graphics/MapReader.h
+++ b/source/graphics/MapReader.h
@@ -53,10 +53,6 @@ private:
int UnpackTerrain();
//UnpackCinema: unpack the cinematic tracks from the input stream
int UnpackCinema();
- // UnpackObjects: unpack world objects from the input stream
- void UnpackObjects();
- // UnpackObjects: unpack lighting parameters from the input stream
- void UnpackLightEnv();
// UnpackMap: unpack the given data from the raw data stream into local variables
int UnpackMap();
@@ -78,10 +74,6 @@ private:
std::vector m_TerrainTextures;
// tile descriptions for each tile
std::vector m_Tiles;
- // list of object types used by map
- std::vector m_ObjectTypes;
- // descriptions for each objects
- std::vector m_Objects;
// lightenv stored in file
CLightEnv m_LightEnv;
diff --git a/source/graphics/MapWriter.cpp b/source/graphics/MapWriter.cpp
index fbef13d5a7..0b4734a455 100644
--- a/source/graphics/MapWriter.cpp
+++ b/source/graphics/MapWriter.cpp
@@ -45,6 +45,11 @@
#include "simulation/EntityTemplateCollection.h"
#include "simulation/TriggerManager.h"
#include "simulation/Entity.h"
+#include "simulation2/Simulation2.h"
+#include "simulation2/components/ICmpPosition.h"
+#include "simulation2/components/ICmpTemplateManager.h"
+
+#define CURRENT_FILE_VERSION (g_UseSimulation2 ? FILE_VERSION : 4)
///////////////////////////////////////////////////////////////////////////////////////////////////
// CMapWriter constructor: nothing to do at the minute
@@ -58,7 +63,7 @@ void CMapWriter::SaveMap(const VfsPath& pathname, CTerrain* pTerrain,
CUnitManager* pUnitMan, WaterManager* pWaterMan, SkyManager* pSkyMan,
CLightEnv* pLightEnv, CCamera* pCamera, CCinemaManager* pCinema)
{
- CFilePacker packer(FILE_VERSION, "PSMP");
+ CFilePacker packer(CURRENT_FILE_VERSION, "PSMP");
// build necessary data
PackMap(packer, pTerrain);
@@ -180,6 +185,7 @@ void CMapWriter::WriteXML(const VfsPath& filename,
{
XML_Element("Scenario");
+ XML_Attribute("version", (int)CURRENT_FILE_VERSION);
{
XML_Element("Environment");
@@ -272,6 +278,50 @@ void CMapWriter::WriteXML(const VfsPath& filename,
const std::vector& units = pUnitMan->GetUnits();
+ if (g_UseSimulation2)
+ {
+ XML_Element("Entities");
+
+ CSimulation2& sim = *g_Game->GetSimulation2();
+
+ CmpPtr cmpTemplateManager(sim, SYSTEM_ENTITY);
+ debug_assert(!cmpTemplateManager.null());
+
+ // This will probably need to be changed in the future, but for now we'll
+ // just save all entities that have a position
+ const CSimulation2::InterfaceList& ents = sim.GetEntitiesWithInterface(IID_Position);
+ for (CSimulation2::InterfaceList::const_iterator it = ents.begin(); it != ents.end(); ++it)
+ {
+ entity_id_t ent = it->first;
+
+ XML_Element("Entity");
+ XML_Attribute("uid", ent);
+
+ XML_Setting("Template", cmpTemplateManager->GetCurrentTemplateName(ent));
+
+ // TODO: player id
+
+ CmpPtr cmpPosition(sim, ent);
+ if (!cmpPosition.null())
+ {
+ CFixedVector3D pos = cmpPosition->GetPosition();
+ CFixedVector3D rot = cmpPosition->GetRotation();
+ {
+ XML_Element("Position");
+ XML_Attribute("x", pos.X.ToDouble());
+ XML_Attribute("z", pos.Z.ToDouble());
+ // TODO: height offset etc
+ }
+ {
+ XML_Element("Orientation");
+ XML_Attribute("y", rot.Y.ToDouble());
+ // TODO: X, Z maybe
+ }
+ }
+ }
+ }
+
+ if (!g_UseSimulation2)
{
XML_Element("Entities");
@@ -307,6 +357,7 @@ void CMapWriter::WriteXML(const VfsPath& filename,
}
}
}
+ if (!g_UseSimulation2)
{
XML_Element("Nonentities");
diff --git a/source/graphics/MeshManager.h b/source/graphics/MeshManager.h
index 078e4f1c24..32e5a8caa9 100644
--- a/source/graphics/MeshManager.h
+++ b/source/graphics/MeshManager.h
@@ -20,12 +20,13 @@
#include "ps/CStr.h"
#include "lib/file/vfs/vfs_path.h"
+#include "lib/sysdep/stl.h"
#include
#include
class CModelDef;
-typedef shared_ptr CModelDefPtr;
+typedef boost::shared_ptr CModelDefPtr;
class CColladaManager;
diff --git a/source/graphics/Overlay.h b/source/graphics/Overlay.h
new file mode 100644
index 0000000000..fffd757549
--- /dev/null
+++ b/source/graphics/Overlay.h
@@ -0,0 +1,35 @@
+/* Copyright (C) 2010 Wildfire Games.
+ * This file is part of 0 A.D.
+ *
+ * 0 A.D. is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * 0 A.D. is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with 0 A.D. If not, see .
+ */
+
+#ifndef INCLUDED_GRAPHICS_OVERLAY
+#define INCLUDED_GRAPHICS_OVERLAY
+
+#include "ps/Overlay.h" // CColor (TODO: that file has nothing to do with overlays, it should be renamed)
+
+/**
+ * Line-based overlay. Exists in world-space, but gets rendered on top
+ * of all other objects. Designed for selection circles.
+ */
+struct SOverlayLine
+{
+ CColor m_Color;
+ std::vector m_Coords; // (x, y, z) vertex coordinate triples; shape is not automatically closed
+};
+
+// TODO: OverlaySprite, OverlayText
+
+#endif // INCLUDED_GRAPHICS_OVERLAY
diff --git a/source/graphics/Terrain.cpp b/source/graphics/Terrain.cpp
index 2af06dc08c..54999f3247 100644
--- a/source/graphics/Terrain.cpp
+++ b/source/graphics/Terrain.cpp
@@ -35,6 +35,7 @@
#include
#include "Terrain.h"
#include "Patch.h"
+#include "maths/FixedVector3D.h"
#include "maths/MathUtil.h"
#include "ps/CLogger.h"
@@ -140,6 +141,20 @@ void CTerrain::CalcPosition(ssize_t i, ssize_t j, CVector3D& pos) const
pos.Z = float(j*CELL_SIZE);
}
+///////////////////////////////////////////////////////////////////////////////
+// CalcPositionFixed: calculate the world space position of the vertex at (i,j)
+void CTerrain::CalcPositionFixed(ssize_t i, ssize_t j, CFixedVector3D& pos) const
+{
+ u16 height;
+ if ((size_t)i < (size_t)m_MapSize && (size_t)j < (size_t)m_MapSize) // will reject negative coordinates
+ height = m_Heightmap[j*m_MapSize + i];
+ else
+ height = 0;
+ pos.X = CFixed_23_8::FromInt(i)*CELL_SIZE;
+ pos.Y = CFixed_23_8::FromInt(height)/HEIGHT_UNITS_PER_METRE;
+ pos.Z = CFixed_23_8::FromInt(j)*CELL_SIZE;
+}
+
///////////////////////////////////////////////////////////////////////////////
// CalcNormal: calculate the world space normal of the vertex at (i,j)
@@ -147,34 +162,34 @@ void CTerrain::CalcNormal(ssize_t i, ssize_t j, CVector3D& normal) const
{
CVector3D left, right, up, down;
- left.Clear();
- right.Clear();
- up.Clear();
- down.Clear();
+ // Calculate normals of the four half-tile triangles surrounding this vertex:
// get position of vertex where normal is being evaluated
CVector3D basepos;
- CalcPosition(i,j,basepos);
+ CalcPosition(i, j, basepos);
- CVector3D tmp;
- if (i>0) {
- CalcPosition(i-1,j,tmp);
- left=tmp-basepos;
+ if (i > 0) {
+ CalcPosition(i-1, j, left);
+ left -= basepos;
+ left.Normalize();
}
- if (i0) {
- CalcPosition(i,j-1,tmp);
- up=tmp-basepos;
+ if (j > 0) {
+ CalcPosition(i, j-1, up);
+ up -= basepos;
+ up.Normalize();
}
- if (j0.00001f) normal*=1.0f/nlen;
}
+///////////////////////////////////////////////////////////////////////////////
+// CalcNormalFixed: calculate the world space normal of the vertex at (i,j)
+void CTerrain::CalcNormalFixed(ssize_t i, ssize_t j, CFixedVector3D& normal) const
+{
+ CFixedVector3D left, right, up, down;
+
+ // Calculate normals of the four half-tile triangles surrounding this vertex:
+
+ // get position of vertex where normal is being evaluated
+ CFixedVector3D basepos;
+ CalcPositionFixed(i, j, basepos);
+
+ if (i > 0) {
+ CalcPositionFixed(i-1, j, left);
+ left -= basepos;
+ left.Normalize();
+ }
+
+ if (i < m_MapSize-1) {
+ CalcPositionFixed(i+1, j, right);
+ right -= basepos;
+ right.Normalize();
+ }
+
+ if (j > 0) {
+ CalcPositionFixed(i, j-1, up);
+ up -= basepos;
+ up.Normalize();
+ }
+
+ if (j < m_MapSize-1) {
+ CalcPositionFixed(i, j+1, down);
+ down -= basepos;
+ down.Normalize();
+ }
+
+ CFixedVector3D n0 = up.Cross(left);
+ CFixedVector3D n1 = left.Cross(down);
+ CFixedVector3D n2 = down.Cross(right);
+ CFixedVector3D n3 = right.Cross(up);
+
+ // Compute the mean of the normals
+ normal = n0 + n1 + n2 + n3;
+ normal.Normalize();
+}
///////////////////////////////////////////////////////////////////////////////
// GetPatch: return the patch at (i,j) in patch space, or null if the patch is
diff --git a/source/graphics/Terrain.h b/source/graphics/Terrain.h
index d8b2c399ea..488e5cba78 100644
--- a/source/graphics/Terrain.h
+++ b/source/graphics/Terrain.h
@@ -31,16 +31,19 @@ class CEntity;
class CPatch;
class CMiniPatch;
class CVector2D;
-
+class CFixedVector3D;
///////////////////////////////////////////////////////////////////////////////
// Terrain Constants:
-//
-// CELL_SIZE: size of each tile in x and z
-const ssize_t CELL_SIZE = 4;
-// HEIGHT_SCALE: vertical scale of terrain - terrain has a coordinate range of
-// 0 to 65536*HEIGHT_SCALE
-const float HEIGHT_SCALE = 0.35f/256.0f;
+
+/// metres [world space units] per tile in x and z
+const ssize_t CELL_SIZE = 4;
+
+/// number of u16 height units per metre
+const ssize_t HEIGHT_UNITS_PER_METRE = 731; // == int(256.0f/0.35f)
+
+/// metres per u16 height unit
+const float HEIGHT_SCALE = 1.f / HEIGHT_UNITS_PER_METRE;
///////////////////////////////////////////////////////////////////////////////
// CTerrain: main terrain class; contains the heightmap describing elevation
@@ -99,6 +102,7 @@ public:
// calculate the position of a given vertex
void CalcPosition(ssize_t i, ssize_t j, CVector3D& pos) const;
+ void CalcPositionFixed(ssize_t i, ssize_t j, CFixedVector3D& pos) const;
// calculate the vertex under a given position (rounding down coordinates)
static void CalcFromPosition(const CVector3D& pos, ssize_t& i, ssize_t& j)
{
@@ -113,6 +117,7 @@ public:
}
// calculate the normal at a given vertex
void CalcNormal(ssize_t i, ssize_t j, CVector3D& normal) const;
+ void CalcNormalFixed(ssize_t i, ssize_t j, CFixedVector3D& normal) const;
// flatten out an area of terrain (specified in world space coords); return
// the average height of the flattened area
diff --git a/source/graphics/UnitManager.cpp b/source/graphics/UnitManager.cpp
index 2157bc9d4f..d708919e77 100644
--- a/source/graphics/UnitManager.cpp
+++ b/source/graphics/UnitManager.cpp
@@ -149,6 +149,7 @@ CUnit* CUnitManager::CreateUnit(const CStr& actorName, CEntity* entity, const st
///////////////////////////////////////////////////////////////////////////////
// FindByID
+// TODO: this is hopelessly inefficient
CUnit* CUnitManager::FindByID(size_t id) const
{
if (id == invalidUnitId)
diff --git a/source/graphics/tests/test_MeshManager.h b/source/graphics/tests/test_MeshManager.h
index 79f0883177..225b021246 100644
--- a/source/graphics/tests/test_MeshManager.h
+++ b/source/graphics/tests/test_MeshManager.h
@@ -19,7 +19,6 @@
#include "lib/file/vfs/vfs.h"
#include "lib/file/io/io.h"
-#include "lib/sysdep/sysdep.h" // sys_get_executable_name
#include "graphics/ColladaManager.h"
#include "graphics/MeshManager.h"
@@ -27,17 +26,6 @@
#include "ps/CLogger.h"
-// we need the (version-controlled) binaries/data directory because it
-// contains input files (it is assumed that developer's machines have
-// write access to those directories). note that argv0 isn't
-// available, so we use sys_get_executable_name.
-static fs::wpath DataDir()
-{
- fs::wpath path;
- TS_ASSERT_OK(sys_get_executable_name(path));
- return path.branch_path()/L"../data";
-}
-
static fs::wpath MOD_PATH(DataDir()/L"mods/_test.mesh");
static fs::wpath CACHE_PATH(DataDir()/L"_testcache");
diff --git a/source/graphics/tests/test_Terrain.h b/source/graphics/tests/test_Terrain.h
new file mode 100644
index 0000000000..7d1a922e44
--- /dev/null
+++ b/source/graphics/tests/test_Terrain.h
@@ -0,0 +1,98 @@
+/* Copyright (C) 2009 Wildfire Games.
+ * This file is part of 0 A.D.
+ *
+ * 0 A.D. is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * 0 A.D. is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with 0 A.D. If not, see .
+ */
+
+#include "lib/self_test.h"
+
+#include "graphics/Terrain.h"
+
+#include "graphics/RenderableObject.h"
+#include "maths/FixedVector3D.h"
+
+class TestTerrain : public CxxTest::TestSuite
+{
+ void SetVertex(CTerrain& terrain, ssize_t i, ssize_t j, u16 height)
+ {
+ terrain.GetHeightMap()[j*terrain.GetVerticesPerSide() + i] = height;
+ terrain.MakeDirty(RENDERDATA_UPDATE_VERTICES);
+ }
+
+ void Set45Slope(CTerrain& terrain)
+ {
+ SetVertex(terrain, 0, 0, 100);
+ SetVertex(terrain, 0, 1, 100);
+ SetVertex(terrain, 0, 2, 100);
+ SetVertex(terrain, 1, 0, 100 + CELL_SIZE*HEIGHT_UNITS_PER_METRE);
+ SetVertex(terrain, 1, 1, 100 + CELL_SIZE*HEIGHT_UNITS_PER_METRE);
+ SetVertex(terrain, 1, 2, 100 + CELL_SIZE*HEIGHT_UNITS_PER_METRE);
+ SetVertex(terrain, 2, 0, 100 + 2*CELL_SIZE*HEIGHT_UNITS_PER_METRE);
+ SetVertex(terrain, 2, 1, 100 + 2*CELL_SIZE*HEIGHT_UNITS_PER_METRE);
+ SetVertex(terrain, 2, 2, 100 + 2*CELL_SIZE*HEIGHT_UNITS_PER_METRE);
+ SetVertex(terrain, 3, 0, 100 + 2*CELL_SIZE*HEIGHT_UNITS_PER_METRE);
+ SetVertex(terrain, 3, 1, 100 + 2*CELL_SIZE*HEIGHT_UNITS_PER_METRE);
+ SetVertex(terrain, 3, 2, 100 + 2*CELL_SIZE*HEIGHT_UNITS_PER_METRE);
+
+ }
+
+public:
+ void test_CalcNormal()
+ {
+ CTerrain terrain;
+ terrain.Initialize(4, NULL);
+ Set45Slope(terrain);
+
+ CVector3D vec;
+
+ terrain.CalcNormal(1, 1, vec);
+ TS_ASSERT_DELTA(vec.X, -1.f/sqrt(2.f), 0.01f);
+ TS_ASSERT_DELTA(vec.Y, 1.f/sqrt(2.f), 0.01f);
+ TS_ASSERT_EQUALS(vec.Z, 0.f);
+
+ terrain.CalcNormal(2, 1, vec);
+ TS_ASSERT_DELTA(vec.X, (-1.f/sqrt(2.f)) / sqrt(2.f+sqrt(2.f)), 0.01f);
+ TS_ASSERT_DELTA(vec.Y, (1.f+1.f/sqrt(2.f)) / sqrt(2.f+sqrt(2.f)), 0.01f);
+ TS_ASSERT_EQUALS(vec.Z, 0);
+
+ terrain.CalcNormal(5, 1, vec);
+ TS_ASSERT_EQUALS(vec.X, 0.f);
+ TS_ASSERT_EQUALS(vec.Y, 1.f);
+ TS_ASSERT_EQUALS(vec.Z, 0.f);
+ }
+
+ void test_CalcNormalFixed()
+ {
+ CTerrain terrain;
+ terrain.Initialize(4, NULL);
+ Set45Slope(terrain);
+
+ CFixedVector3D vec;
+
+ terrain.CalcNormalFixed(1, 1, vec);
+ TS_ASSERT_DELTA(vec.X.ToFloat(), -1.f/sqrt(2.f), 0.01f);
+ TS_ASSERT_DELTA(vec.Y.ToFloat(), 1.f/sqrt(2.f), 0.01f);
+ TS_ASSERT_EQUALS(vec.Z.ToFloat(), 0.f);
+
+ terrain.CalcNormalFixed(2, 1, vec);
+ TS_ASSERT_DELTA(vec.X.ToFloat(), (-1.f/sqrt(2.f)) / sqrt(2.f+sqrt(2.f)), 0.01f);
+ TS_ASSERT_DELTA(vec.Y.ToFloat(), (1.f+1.f/sqrt(2.f)) / sqrt(2.f+sqrt(2.f)), 0.01f);
+ TS_ASSERT_EQUALS(vec.Z.ToFloat(), 0);
+
+ terrain.CalcNormalFixed(5, 1, vec);
+ TS_ASSERT_EQUALS(vec.X.ToFloat(), 0.f);
+ TS_ASSERT_EQUALS(vec.Y.ToFloat(), 1.f);
+ TS_ASSERT_EQUALS(vec.Z.ToFloat(), 0.f);
+ }
+};
diff --git a/source/gui/CGUI.h b/source/gui/CGUI.h
index f26943df03..9f0b13d5d0 100644
--- a/source/gui/CGUI.h
+++ b/source/gui/CGUI.h
@@ -90,8 +90,7 @@ struct SGUIScrollBarStyle;
class GUITooltip;
/**
- * The main object that includes the whole GUI. Is singleton
- * and accessed by g_GUI.
+ * The main object that represents a whole GUI page.
*
* No interfacial functions throws.
*/
diff --git a/source/gui/GUIManager.cpp b/source/gui/GUIManager.cpp
index 376291d8d4..36dd67c71d 100644
--- a/source/gui/GUIManager.cpp
+++ b/source/gui/GUIManager.cpp
@@ -1,3 +1,20 @@
+/* Copyright (C) 2010 Wildfire Games.
+ * This file is part of 0 A.D.
+ *
+ * 0 A.D. is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * 0 A.D. is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with 0 A.D. If not, see .
+ */
+
#include "precompiled.h"
#include "GUIManager.h"
@@ -8,6 +25,7 @@
#include "ps/CLogger.h"
#include "ps/Profile.h"
#include "ps/XML/Xeromyces.h"
+#include "scriptinterface/ScriptInterface.h"
CGUIManager* g_GUI = NULL;
@@ -46,21 +64,24 @@ CGUIManager::SGUIPage::~SGUIPage()
JS_RemoveRoot(g_ScriptingHost.GetContext(), &initData);
}
-CGUIManager::CGUIManager()
+CGUIManager::CGUIManager(ScriptInterface& scriptInterface) :
+ m_ScriptInterface(scriptInterface)
{
+ debug_assert(ScriptInterface::GetCallbackData(scriptInterface.GetContext()) == NULL);
+ scriptInterface.SetCallbackData(this);
}
CGUIManager::~CGUIManager()
{
}
-void CGUIManager::SwitchPage(const CStrW& pageName, jsval initData)
+void CGUIManager::SwitchPage(const CStrW& pageName, CScriptVal initData)
{
m_PageStack.clear();
PushPage(pageName, initData);
}
-void CGUIManager::PushPage(const CStrW& pageName, jsval initData)
+void CGUIManager::PushPage(const CStrW& pageName, CScriptVal initData)
{
m_PageStack.push_back(SGUIPage());
m_PageStack.back().name = pageName;
@@ -122,8 +143,7 @@ void CGUIManager::LoadPage(SGUIPage& page)
page.gui->SendEventToAll("load");
// Call the init() function
- jsval rval;
- if (! JS_CallFunctionName(g_ScriptingHost.GetContext(), page.gui->GetScriptObject(), "init", 1, &page.initData, &rval))
+ if (!m_ScriptInterface.CallFunctionVoid(OBJECT_TO_JSVAL(page.gui->GetScriptObject()), "init", page.initData))
{
LOGERROR(L"GUI page '%ls': Failed to call init() function", page.name.c_str());
}
@@ -143,6 +163,42 @@ LibError CGUIManager::ReloadChangedFiles(const VfsPath& path)
return INFO::OK;
}
+
+InReaction CGUIManager::HandleEvent(const SDL_Event_* ev)
+{
+ // We want scripts to have access to the raw input events, so they can do complex
+ // processing when necessary (e.g. for unit selection and camera movement).
+ // Sometimes they'll want to be layered behind the GUI widgets (e.g. to detect mousedowns on the
+ // visible game area), sometimes they'll want to intercepts events before the GUI (e.g.
+ // to capture all mouse events until a mouseup after dragging).
+ // So we call two separate handler functions:
+
+ bool handled;
+ {
+ PROFILE("handleInputBeforeGui");
+ if (m_ScriptInterface.CallFunction(OBJECT_TO_JSVAL(top()->GetScriptObject()), "handleInputBeforeGui", *ev, handled))
+ if (handled)
+ return IN_HANDLED;
+ }
+
+ {
+ PROFILE("handle event in native GUI");
+ InReaction r = top()->HandleEvent(ev);
+ if (r != IN_PASS)
+ return r;
+ }
+
+ {
+ PROFILE("handleInputAfterGui");
+ if (m_ScriptInterface.CallFunction(OBJECT_TO_JSVAL(top()->GetScriptObject()), "handleInputAfterGui", *ev, handled))
+ if (handled)
+ return IN_HANDLED;
+ }
+
+ return IN_PASS;
+}
+
+
bool CGUIManager::GetPreDefinedColor(const CStr& name, CColor& output)
{
return top()->GetPreDefinedColor(name, output);
@@ -191,11 +247,6 @@ JSObject* CGUIManager::GetScriptObject()
return top()->GetScriptObject();
}
-InReaction CGUIManager::HandleEvent(const SDL_Event_* ev)
-{
- return top()->HandleEvent(ev);
-}
-
// This returns a shared_ptr to make sure the CGUI doesn't get deallocated
// while we're in the middle of calling a function on it (e.g. if a GUI script
// calls SwitchPage)
diff --git a/source/gui/GUIManager.h b/source/gui/GUIManager.h
index 62673b87f4..d31b1279fc 100644
--- a/source/gui/GUIManager.h
+++ b/source/gui/GUIManager.h
@@ -1,10 +1,27 @@
+/* Copyright (C) 2010 Wildfire Games.
+ * This file is part of 0 A.D.
+ *
+ * 0 A.D. is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * 0 A.D. is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with 0 A.D. If not, see .
+ */
+
#ifndef INCLUDED_GUIMANAGER
#define INCLUDED_GUIMANAGER
#include "lib/input.h"
#include "lib/file/vfs/vfs_path.h"
#include "ps/CStr.h"
-#include "scripting/SpiderMonkey.h"
+#include "scriptinterface/ScriptVal.h"
#include
@@ -25,17 +42,20 @@ struct SGUIIcon;
*/
class CGUIManager
{
+ NONCOPYABLE(CGUIManager);
public:
- CGUIManager();
+ CGUIManager(ScriptInterface& scriptInterface);
~CGUIManager();
- // Load a new GUI page and make it active, All current pages will be destroyed.
- void SwitchPage(const CStrW& name, jsval initData);
+ ScriptInterface& GetScriptInterface() { return m_ScriptInterface; }
+
+ // Load a new GUI page and make it active. All current pages will be destroyed.
+ void SwitchPage(const CStrW& name, CScriptVal initData);
// Load a new GUI page and make it active. All current pages will be retained,
// and will still be drawn and receive tick events, but will not receive
// user inputs.
- void PushPage(const CStrW& name, jsval initData);
+ void PushPage(const CStrW& name, CScriptVal initData);
// Unload the currently active GUI page, and make the previous page active.
// (There must be at least two pages when you call this.)
@@ -44,6 +64,9 @@ public:
// Hotload pages when their .xml files have changed
LibError ReloadChangedFiles(const VfsPath& path);
+ // Handle input events
+ InReaction HandleEvent(const SDL_Event_* ev);
+
// These functions are all equivalent to the CGUI functions of the same
// name, applied to the currently active GUI page:
@@ -60,18 +83,20 @@ public:
JSObject* GetScriptObject();
- InReaction HandleEvent(const SDL_Event_* ev);
-
private:
struct SGUIPage
{
SGUIPage();
SGUIPage(const SGUIPage&);
~SGUIPage();
+
CStrW name;
std::set inputs; // for hotloading
- jsval initData;
- shared_ptr gui;
+
+ JSContext* cx;
+ CScriptVal initData; // data to be passed to the init() function
+
+ shared_ptr gui; // the actual GUI page
};
void LoadPage(SGUIPage& page);
@@ -80,6 +105,8 @@ private:
typedef std::vector PageStackType;
PageStackType m_PageStack;
+
+ ScriptInterface& m_ScriptInterface;
};
extern CGUIManager* g_GUI;
diff --git a/source/gui/IGUIObject.cpp b/source/gui/IGUIObject.cpp
index 29803cd746..153ed61054 100644
--- a/source/gui/IGUIObject.cpp
+++ b/source/gui/IGUIObject.cpp
@@ -451,7 +451,7 @@ void IGUIObject::RegisterScriptHandler(const CStr& Action, const CStr& Code, CGU
sprintf_s(buf, ARRAY_SIZE(buf), "__eventhandler%d", x++);
JSFunction* func = JS_CompileFunction(g_ScriptingHost.getContext(), pGUI->m_ScriptObject,
- buf, paramCount, paramNames, (const char*)Code, Code.length(), CodeName, 0);
+ buf, paramCount, paramNames, Code.c_str(), Code.length(), CodeName, 0);
debug_assert(func); // TODO: Handle errors
if (func)
SetScriptHandler(Action, JS_GetFunctionObject(func));
@@ -502,13 +502,10 @@ void IGUIObject::ScriptEvent(const CStr& Action)
// Don't garbage collect the mouse
JS_AddRoot(g_ScriptingHost.getContext(), &mouseObj);
- const int paramCount = 1;
- jsval paramData[paramCount];
- paramData[0] = OBJECT_TO_JSVAL(mouseObj);
+ jsval paramData[] = { OBJECT_TO_JSVAL(mouseObj) };
jsval result;
-
- JSBool ok = JS_CallFunctionValue(g_ScriptingHost.getContext(), jsGuiObject, OBJECT_TO_JSVAL(*it->second), 1, paramData, &result);
+ JSBool ok = JS_CallFunctionValue(g_ScriptingHost.getContext(), jsGuiObject, OBJECT_TO_JSVAL(*it->second), ARRAY_SIZE(paramData), paramData, &result);
if (!ok)
{
JS_ReportError(g_ScriptingHost.getContext(), "Errors executing script action \"%s\"", Action.c_str());
diff --git a/source/gui/scripting/GuiScriptConversions.cpp b/source/gui/scripting/GuiScriptConversions.cpp
new file mode 100644
index 0000000000..506338e7b8
--- /dev/null
+++ b/source/gui/scripting/GuiScriptConversions.cpp
@@ -0,0 +1,132 @@
+/* Copyright (C) 2010 Wildfire Games.
+ * This file is part of 0 A.D.
+ *
+ * 0 A.D. is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * 0 A.D. is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with 0 A.D. If not, see .
+ */
+
+#include "precompiled.h"
+
+#include "scriptinterface/ScriptInterface.h"
+
+#include "lib/external_libraries/sdl.h"
+#include "ps/Hotkey.h"
+
+#include "js/jsapi.h"
+
+#define SET(obj, name, value) STMT(jsval v_ = ToJSVal(cx, (value)); JS_SetProperty(cx, (obj), (name), &v_))
+ // ignore JS_SetProperty return value, because errors should be impossible
+ // and we can't do anything useful in the case of errors anyway
+
+template<> jsval ScriptInterface::ToJSVal(JSContext* cx, SDL_Event_ const& val)
+{
+ const char* typeName;
+
+ switch (val.ev.type)
+ {
+ case SDL_ACTIVEEVENT: typeName = "activeevent"; break;
+ case SDL_KEYDOWN: typeName = "keydown"; break;
+ case SDL_KEYUP: typeName = "keyup"; break;
+ case SDL_MOUSEMOTION: typeName = "mousemotion"; break;
+ case SDL_MOUSEBUTTONDOWN: typeName = "mousebuttondown"; break;
+ case SDL_MOUSEBUTTONUP: typeName = "mousebuttonup"; break;
+ case SDL_HOTKEYDOWN: typeName = "hotkeydown"; break;
+ case SDL_HOTKEYUP: typeName = "hotkeyup"; break;
+ case SDL_GUIHOTKEYPRESS: typeName = "guihotkeypress"; break;
+ default: typeName = "(unknown)"; break;
+ }
+
+ ScriptInterface::LocalRootScope scope(cx);
+ if (! scope.OK())
+ return JSVAL_VOID;
+
+ JSObject* obj = JS_NewObject(cx, NULL, NULL, NULL);
+ if (! obj)
+ return JSVAL_VOID;
+
+ SET(obj, "type", typeName);
+
+ switch (val.ev.type)
+ {
+ case SDL_ACTIVEEVENT:
+ {
+ SET(obj, "gain", (int)val.ev.active.gain);
+ SET(obj, "state", (int)val.ev.active.state);
+ break;
+ }
+ case SDL_KEYDOWN:
+ case SDL_KEYUP:
+ {
+ // SET(obj, "which", (int)val.ev.key.which); // (not in wsdl.h)
+ // SET(obj, "state", (int)val.ev.key.state); // (not in wsdl.h)
+
+ JSObject* keysym = JS_NewObject(cx, NULL, NULL, NULL);
+ if (! keysym)
+ return JSVAL_VOID;
+ jsval keysymVal = OBJECT_TO_JSVAL(keysym);
+ JS_SetProperty(cx, obj, "keysym", &keysymVal);
+
+ // SET(keysym, "scancode", (int)val.ev.key.keysym.scancode); // (not in wsdl.h)
+ SET(keysym, "sym", (int)val.ev.key.keysym.sym);
+ // SET(keysym, "mod", (int)val.ev.key.keysym.mod); // (not in wsdl.h)
+ if (val.ev.key.keysym.unicode)
+ {
+ std::wstring unicode(1, (wchar_t)val.ev.key.keysym.unicode);
+ SET(keysym, "unicode", unicode);
+ }
+ else
+ {
+ SET(keysym, "unicode", CScriptVal(JSVAL_VOID));
+ }
+ // TODO: scripts have no idea what all the key/mod enum values are;
+ // we should probably expose them as constants if we expect scripts to use them
+
+ break;
+ }
+ case SDL_MOUSEMOTION:
+ {
+ // SET(obj, "which", (int)val.ev.motion.which); // (not in wsdl.h)
+ // SET(obj, "state", (int)val.ev.motion.state); // (not in wsdl.h)
+ SET(obj, "x", (int)val.ev.motion.x);
+ SET(obj, "y", (int)val.ev.motion.y);
+ // SET(obj, "xrel", (int)val.ev.motion.xrel); // (not in wsdl.h)
+ // SET(obj, "yrel", (int)val.ev.motion.yrel); // (not in wsdl.h)
+ break;
+ }
+ case SDL_MOUSEBUTTONDOWN:
+ case SDL_MOUSEBUTTONUP:
+ {
+ // SET(obj, "which", (int)val.ev.button.which); // (not in wsdl.h)
+ SET(obj, "button", (int)val.ev.button.button);
+ SET(obj, "state", (int)val.ev.button.state);
+ SET(obj, "x", (int)val.ev.button.x);
+ SET(obj, "y", (int)val.ev.button.y);
+ break;
+ }
+ case SDL_HOTKEYDOWN:
+ case SDL_HOTKEYUP:
+ {
+ CStr name = HotkeyGetName(val.ev.user.code);
+ SET(obj, "hotkey", name.c_str());
+ break;
+ }
+ case SDL_GUIHOTKEYPRESS:
+ {
+ CStr* name = static_cast(val.ev.user.data1);
+ SET(obj, "object", name->c_str());
+ break;
+ }
+ }
+
+ return OBJECT_TO_JSVAL(obj);
+}
diff --git a/source/gui/scripting/ScriptFunctions.cpp b/source/gui/scripting/ScriptFunctions.cpp
new file mode 100644
index 0000000000..744c74a8b5
--- /dev/null
+++ b/source/gui/scripting/ScriptFunctions.cpp
@@ -0,0 +1,221 @@
+/* Copyright (C) 2010 Wildfire Games.
+ * This file is part of 0 A.D.
+ *
+ * 0 A.D. is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * 0 A.D. is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with 0 A.D. If not, see .
+ */
+
+#include "precompiled.h"
+
+#include "scriptinterface/ScriptInterface.h"
+
+#include "graphics/Camera.h"
+#include "graphics/GameView.h"
+#include "gui/GUIManager.h"
+#include "ps/CLogger.h"
+#include "ps/Game.h"
+#include "ps/Overlay.h"
+#include "ps/Player.h"
+#include "simulation2/Simulation2.h"
+#include "simulation2/components/ICmpGuiInterface.h"
+#include "simulation2/components/ICmpCommandQueue.h"
+#include "simulation2/helpers/Selection.h"
+
+/*
+ * This file defines a set of functions that are available to GUI scripts, to allow
+ * interaction with the rest of the engine.
+ * Functions are exposed to scripts within the global object 'Engine', so
+ * scripts should call "Engine.FunctionName(...)" etc.
+ */
+
+namespace {
+
+CScriptVal GetActiveGui(void* UNUSED(cbdata))
+{
+ return OBJECT_TO_JSVAL(g_GUI->GetScriptObject());
+}
+
+void PushGuiPage(void* UNUSED(cbdata), std::wstring name, CScriptVal initData)
+{
+ g_GUI->PushPage(name, initData);
+}
+
+void SwitchGuiPage(void* UNUSED(cbdata), std::wstring name, CScriptVal initData)
+{
+ g_GUI->SwitchPage(name, initData);
+}
+
+void PopGuiPage(void* UNUSED(cbdata))
+{
+ g_GUI->PopPage();
+}
+
+bool IsNewSimulation(void* UNUSED(cbdata))
+{
+ return g_UseSimulation2;
+}
+
+// TODO: this should probably be moved into ScriptInterface in case anyone else wants to use it
+static jsval CloneValueBetweenContexts(JSContext* cxFrom, JSContext* cxTo, jsval val)
+{
+ if (JSVAL_IS_INT(val) || JSVAL_IS_BOOLEAN(val) || JSVAL_IS_NULL(val) || JSVAL_IS_VOID(val))
+ return val;
+
+ if (JSVAL_IS_DOUBLE(val))
+ {
+ jsval rval;
+ if (JS_NewNumberValue(cxTo, *JSVAL_TO_DOUBLE(val), &rval))
+ return rval;
+ else
+ return JSVAL_VOID;
+ }
+
+ if (JSVAL_IS_STRING(val))
+ {
+ JSString* str = JS_NewUCStringCopyN(cxTo, JS_GetStringChars(JSVAL_TO_STRING(val)), JS_GetStringLength(JSVAL_TO_STRING(val)));
+ if (str == NULL)
+ return JSVAL_VOID;
+ return STRING_TO_JSVAL(str);
+ }
+
+ if (JSVAL_IS_OBJECT(val))
+ {
+ jsval source;
+ if (!JS_CallFunctionName(cxFrom, JSVAL_TO_OBJECT(val), "toSource", 0, NULL, &source))
+ return JSVAL_VOID;
+ if (!JSVAL_IS_STRING(source))
+ return JSVAL_VOID;
+ JS_AddRoot(cxFrom, &source);
+ jsval rval;
+ JSBool ok = JS_EvaluateUCScript(cxTo, JS_GetGlobalObject(cxTo),
+ JS_GetStringChars(JSVAL_TO_STRING(source)), JS_GetStringLength(JSVAL_TO_STRING(source)),
+ "(CloneValueBetweenContexts)", 0, &rval);
+ JS_RemoveRoot(cxFrom, &source);
+ return ok ? rval : JSVAL_VOID;
+ }
+
+ LOGERROR(L"CloneValueBetweenContexts: value is of unexpected type");
+ return JSVAL_VOID;
+}
+
+CScriptVal GetSimulationState(void* cbdata)
+{
+ CGUIManager* guiManager = static_cast (cbdata);
+
+ if (!g_UseSimulation2 || !g_Game)
+ return JSVAL_VOID;
+ CSimulation2* sim = g_Game->GetSimulation2();
+ debug_assert(sim);
+ CmpPtr gui(*sim, SYSTEM_ENTITY);
+ if (gui.null())
+ return JSVAL_VOID;
+
+ int player = -1;
+ if (g_Game && g_Game->GetLocalPlayer())
+ player = g_Game->GetLocalPlayer()->GetPlayerID();
+
+ return CloneValueBetweenContexts(sim->GetScriptInterface().GetContext(), guiManager->GetScriptInterface().GetContext(), gui->GetSimulationState(player).get());
+}
+
+CScriptVal GetEntityState(void* cbdata, entity_id_t ent)
+{
+ CGUIManager* guiManager = static_cast (cbdata);
+
+ if (!g_UseSimulation2 || !g_Game)
+ return JSVAL_VOID;
+ CSimulation2* sim = g_Game->GetSimulation2();
+ debug_assert(sim);
+ CmpPtr gui(*sim, SYSTEM_ENTITY);
+ if (gui.null())
+ return JSVAL_VOID;
+
+ int player = -1;
+ if (g_Game && g_Game->GetLocalPlayer())
+ player = g_Game->GetLocalPlayer()->GetPlayerID();
+
+ return CloneValueBetweenContexts(sim->GetScriptInterface().GetContext(), guiManager->GetScriptInterface().GetContext(), gui->GetEntityState(player, ent).get());
+}
+
+void SetEntitySelectionHighlight(void* UNUSED(cbdata), entity_id_t ent, CColor color)
+{
+ if (!g_UseSimulation2 || !g_Game)
+ return;
+ CSimulation2* sim = g_Game->GetSimulation2();
+ debug_assert(sim);
+ CmpPtr gui(*sim, SYSTEM_ENTITY);
+ if (gui.null())
+ return;
+
+ // TODO: stop duplicating all this prolog code
+
+ gui->SetSelectionHighlight(ent, color);
+}
+
+void PostNetworkCommand(void* cbdata, CScriptVal cmd)
+{
+ CGUIManager* guiManager = static_cast (cbdata);
+
+ if (!g_UseSimulation2 || !g_Game)
+ return;
+ CSimulation2* sim = g_Game->GetSimulation2();
+ debug_assert(sim);
+ CmpPtr queue(*sim, SYSTEM_ENTITY);
+ if (queue.null())
+ return;
+
+ int player = -1;
+ if (g_Game && g_Game->GetLocalPlayer())
+ player = g_Game->GetLocalPlayer()->GetPlayerID();
+
+ jsval cmd2 = CloneValueBetweenContexts(guiManager->GetScriptInterface().GetContext(), sim->GetScriptInterface().GetContext(), cmd.get());
+
+ queue->PushClientCommand(player, cmd2);
+ // TODO: This shouldn't call Push, it should send the message to the network layer
+ // (which should propagate it across the network and eventually call Push on the
+ // appropriate turn)
+}
+
+std::vector PickEntitiesAtPoint(void* UNUSED(cbdata), int x, int y)
+{
+ return EntitySelection::PickEntitiesAtPoint(*g_Game->GetSimulation2(), *g_Game->GetView()->GetCamera(), x, y);
+}
+
+CFixedVector3D GetTerrainAtPoint(void* UNUSED(cbdata), int x, int y)
+{
+ CVector3D pos = g_Game->GetView()->GetCamera()->GetWorldCoordinates(x, y, false);
+ return CFixedVector3D(CFixed_23_8::FromFloat(pos.X), CFixed_23_8::FromFloat(pos.Y), CFixed_23_8::FromFloat(pos.Z));
+}
+
+} // namespace
+
+void GuiScriptingInit(ScriptInterface& scriptInterface)
+{
+ // GUI manager functions:
+ scriptInterface.RegisterFunction("GetActiveGui");
+ scriptInterface.RegisterFunction("PushGuiPage");
+ scriptInterface.RegisterFunction("SwitchGuiPage");
+ scriptInterface.RegisterFunction("PopGuiPage");
+
+ // Simulation<->GUI interface functions:
+ scriptInterface.RegisterFunction("IsNewSimulation");
+ scriptInterface.RegisterFunction("GetSimulationState");
+ scriptInterface.RegisterFunction("GetEntityState");
+ scriptInterface.RegisterFunction("SetEntitySelectionHighlight");
+
+ scriptInterface.RegisterFunction("PostNetworkCommand");
+
+ // Entity picking
+ scriptInterface.RegisterFunction, int, int, &PickEntitiesAtPoint>("PickEntitiesAtPoint");
+ scriptInterface.RegisterFunction("GetTerrainAtPoint");
+
+}
diff --git a/source/gui/scripting/ScriptFunctions.h b/source/gui/scripting/ScriptFunctions.h
new file mode 100644
index 0000000000..f739ca044f
--- /dev/null
+++ b/source/gui/scripting/ScriptFunctions.h
@@ -0,0 +1,25 @@
+/* Copyright (C) 2010 Wildfire Games.
+ * This file is part of 0 A.D.
+ *
+ * 0 A.D. is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * 0 A.D. is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with 0 A.D. If not, see .
+ */
+
+#ifndef INCLUDED_GUI_SCRIPTFUNCTIONS
+#define INCLUDED_GUI_SCRIPTFUNCTIONS
+
+class ScriptInterface;
+
+void GuiScriptingInit(ScriptInterface& scriptInterface);
+
+#endif // INCLUDED_GUI_SCRIPTFUNCTIONS
diff --git a/source/i18n/Interface.cpp b/source/i18n/Interface.cpp
index 4605bf2749..0401bbaf89 100644
--- a/source/i18n/Interface.cpp
+++ b/source/i18n/Interface.cpp
@@ -87,7 +87,7 @@ CLocale_interface* I18n::NewLocale(JSContext* cx, JSObject* scope)
}
catch (PSERROR_I18n& e)
{
- LOG(CLogger::Error, LOG_CATEGORY, L"Error creating locale object ('%hs')", GetErrorString(e));
+ LOG(CLogger::Error, LOG_CATEGORY, L"Error creating locale object ('%hs')", e.what());
return NULL;
}
}
diff --git a/source/lib/debug.h b/source/lib/debug.h
index a05aa9d525..ccd35e20cf 100644
--- a/source/lib/debug.h
+++ b/source/lib/debug.h
@@ -31,6 +31,7 @@
// - the output routines make for platform-independent logging and
// crashlogs with "last-known activity" reporting.
+#include "lib/lib_errors.h"
/**
* trigger a breakpoint when reached/"called".
diff --git a/source/lib/external_libraries/cryptopp.h b/source/lib/external_libraries/cryptopp.h
new file mode 100644
index 0000000000..de977f2f19
--- /dev/null
+++ b/source/lib/external_libraries/cryptopp.h
@@ -0,0 +1,41 @@
+/* Copyright (C) 2010 Wildfire Games.
+ * This file is part of 0 A.D.
+ *
+ * 0 A.D. is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * 0 A.D. is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with 0 A.D. If not, see .
+ */
+
+/*
+ * bring in Crypto++ SHA algorithms
+ */
+
+#ifndef INCLUDED_CRYPTOPP
+#define INCLUDED_CRYPTOPP
+
+// not W4-clean
+#if MSC_VERSION
+# pragma warning(push, 3)
+#endif
+
+// Crypto++ and SpiderMonkey both define IS_(LITTLE|BIG)_ENDIAN,
+// so undefine SM's to avoid redefinition warnings
+#undef IS_LITTLE_ENDIAN
+#undef IS_BIG_ENDIAN
+
+#include "cryptopp/sha.h"
+
+#if MSC_VERSION
+# pragma warning(pop)
+#endif
+
+#endif // #ifndef INCLUDED_CRYPTOPP
diff --git a/source/lib/external_libraries/dbghelp_funcs.h b/source/lib/external_libraries/dbghelp_funcs.h
index a0ac9f400d..49373fdbf2 100644
--- a/source/lib/external_libraries/dbghelp_funcs.h
+++ b/source/lib/external_libraries/dbghelp_funcs.h
@@ -1,3 +1,20 @@
+/* Copyright (C) 2010 Wildfire Games.
+ * This file is part of 0 A.D.
+ *
+ * 0 A.D. is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * 0 A.D. is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with 0 A.D. If not, see .
+ */
+
FUNC(BOOL, SymInitializeW, (__in HANDLE hProcess, __in_opt PCWSTR UserSearchPath, __in BOOL fInvadeProcess))
FUNC(DWORD, SymGetOptions, (VOID))
FUNC(DWORD, SymSetOptions, (__in DWORD SymOptions))
diff --git a/source/lib/file/file_system.h b/source/lib/file/file_system.h
index 0292bacb6a..46fa642a85 100644
--- a/source/lib/file/file_system.h
+++ b/source/lib/file/file_system.h
@@ -18,6 +18,8 @@
#ifndef INCLUDED_FILE_SYSTEM
#define INCLUDED_FILE_SYSTEM
+#include "lib/external_libraries/boost_filesystem.h"
+
class FileInfo
{
public:
diff --git a/source/lib/file/vfs/vfs_path.h b/source/lib/file/vfs/vfs_path.h
index b16ec4cdcf..009c4e3d00 100644
--- a/source/lib/file/vfs/vfs_path.h
+++ b/source/lib/file/vfs/vfs_path.h
@@ -18,6 +18,8 @@
#ifndef INCLUDED_VFS_PATH
#define INCLUDED_VFS_PATH
+#include "lib/external_libraries/boost_filesystem.h"
+
struct VfsPathTraits;
/**
diff --git a/source/lib/lib_errors.h b/source/lib/lib_errors.h
index f0b54f768f..653101a73c 100644
--- a/source/lib/lib_errors.h
+++ b/source/lib/lib_errors.h
@@ -175,6 +175,8 @@ Notes:
#ifndef INCLUDED_LIB_ERRORS
#define INCLUDED_LIB_ERRORS
+#include "lib/lib.h"
+
// note: this loses compiler type safety (being able to prevent
// return 1 when a LibError is the return value), but allows splitting
// up the error namespace into separate headers.
diff --git a/source/lib/path_util.h b/source/lib/path_util.h
index 3f9de53434..2a81f402f3 100644
--- a/source/lib/path_util.h
+++ b/source/lib/path_util.h
@@ -32,6 +32,8 @@
#ifndef INCLUDED_PATH_UTIL
#define INCLUDED_PATH_UTIL
+#include "lib/external_libraries/boost_filesystem.h"
+
namespace ERR
{
const LibError PATH_EMPTY = -100300;
diff --git a/source/lib/posix/posix_types.h b/source/lib/posix/posix_types.h
index 1d769f64b9..d8b993cd4b 100644
--- a/source/lib/posix/posix_types.h
+++ b/source/lib/posix/posix_types.h
@@ -19,6 +19,9 @@
* lightweight header that defines POSIX types.
*/
+#ifndef INCLUDED_POSIX_TYPES
+#define INCLUDED_POSIX_TYPES
+
// this header defines e.g. ssize_t and int8_t without pulling in all
// POSIX declarations.
// included from lib/types.h in place of posix.h; this helps avoid conflicts
@@ -49,3 +52,5 @@
#include
#endif // #if !OS_WIN
+
+#endif // #ifndef INCLUDED_POSIX_TYPES
diff --git a/source/lib/precompiled.h b/source/lib/precompiled.h
index c08695afe4..5897b6e2a2 100644
--- a/source/lib/precompiled.h
+++ b/source/lib/precompiled.h
@@ -20,6 +20,17 @@
* source file (VC6..8 requirement).
*/
+// some libraries have only a small number of source files, and the
+// overhead of including loads of headers here outweighs the improvements to
+// incremental rebuild performance.
+// they can set MINIMAL_PCH to 1 so we include far fewer headers (but
+// still do the global disabling of warnings and include config headers etc),
+// or set it to 2 to remove STL headers too (precompiling STL helps performance
+// in most non-tiny cases)
+#ifndef MINIMAL_PCH
+# define MINIMAL_PCH 0
+#endif
+
#define _SECURE_SCL 0
#include "lib/sysdep/compiler.h" // MSC_VERSION, HAVE_PCH
@@ -61,22 +72,25 @@
// (must come before any system headers because it fixes off_t)
#include "lib/posix/posix_types.h"
+#include "lib/code_annotation.h"
+
// (must come before any use of due to incompatibility with ICC's mathimf.h)
#if ICC_VERSION
#include
#endif
#include "lib/sysdep/arch.h"
-#include "lib/sysdep/stl.h"
#include "lib/lib_api.h"
-
#include "lib/types.h"
+
+#if !MINIMAL_PCH
+#include "lib/sysdep/stl.h"
#include "lib/lib.h"
#include "lib/lib_errors.h"
-#include "lib/code_annotation.h"
#include "lib/secure_crt.h"
#include "lib/debug.h"
+#endif // !MINIMAL_PCH
// Boost
// .. if this package isn't going to be statically linked, we're better off
@@ -85,10 +99,13 @@
#ifndef LIB_STATIC_LINK
# define BOOST_ALL_DYN_LINK
#endif
+
// the following boost libraries have been included in TR1 and are
// thus deemed usable:
#include
using boost::shared_ptr;
+#if !MINIMAL_PCH
+// (these ones are used more rarely, so we don't enable them in minimal configurations)
#include
using boost::array;
#include
@@ -98,6 +115,7 @@ using boost::function;
#include
using boost::bind;
#include "lib/external_libraries/boost_filesystem.h"
+#endif // !MINIMAL_PCH
// (this must come after boost and common lib headers)
#include "lib/posix/posix.h"
@@ -121,6 +139,7 @@ using boost::bind;
// anything placed here won't need to be compiled in each translation unit,
// but will cause a complete rebuild if they change.
+#if !MINIMAL_PCH
// all new-form C library headers
#include
#include
@@ -140,7 +159,9 @@ using boost::bind;
#include
#include
#include
+#endif // !MINIMAL_PCH
+#if MINIMAL_PCH < 2
// all C++98 STL headers
#include
#include
@@ -155,7 +176,9 @@ using boost::bind;
#include
#include
#include
+#endif
+#if !MINIMAL_PCH
// all other C++98 headers
#include
#include
@@ -177,7 +200,9 @@ using boost::bind;
#include
#include
#include
+#endif // !MINIMAL_PCH
+#if !MINIMAL_PCH
// STL extensions
#if GCC_VERSION >= 402 // (see comment in stl.h about GCC versions)
# include
@@ -189,6 +214,7 @@ using boost::bind;
# include
# include
#endif
+#endif // !MINIMAL_PCH
#endif // #if CONFIG_PCH
diff --git a/source/lib/self_test.h b/source/lib/self_test.h
index 15f86d41c9..b5611c7af1 100644
--- a/source/lib/self_test.h
+++ b/source/lib/self_test.h
@@ -212,12 +212,55 @@ namespace CxxTest
CXXTEST_COPY_CONST_TRAITS( CStrW );
}
+// Perform nice printing of vectors
+#include "maths/FixedVector3D.h"
+#include "maths/Vector3D.h"
+namespace CxxTest
+{
+ template<>
+ class ValueTraits
+ {
+ CFixedVector3D v;
+ std::string str;
+ public:
+ ValueTraits(const CFixedVector3D& v) : v(v)
+ {
+ std::stringstream s;
+ s << "[" << v.X.ToDouble() << ", " << v.Y.ToDouble() << ", " << v.Z.ToDouble() << "]";
+ str = s.str();
+ }
+ const char* asString() const
+ {
+ return str.c_str();
+ }
+ };
+
+ template<>
+ class ValueTraits
+ {
+ CVector3D v;
+ std::string str;
+ public:
+ ValueTraits(const CVector3D& v) : v(v)
+ {
+ std::stringstream s;
+ s << "[" << v.X << ", " << v.Y << ", " << v.Z << "]";
+ str = s.str();
+ }
+ const char* asString() const
+ {
+ return str.c_str();
+ }
+ };
+}
+
#define TS_ASSERT_OK(expr) TS_ASSERT_EQUALS((expr), INFO::OK)
#define TS_ASSERT_STR_EQUALS(str1, str2) TS_ASSERT_EQUALS(std::string(str1), std::string(str2))
#define TS_ASSERT_WSTR_EQUALS(str1, str2) TS_ASSERT_EQUALS(std::wstring(str1), std::wstring(str2))
bool ts_str_contains(const std::wstring& str1, const std::wstring& str2); // defined in test_setup.cpp
-#define TS_ASSERT_WSTR_CONTAINS(str1, str2) TS_ASSERT(ts_str_contains(str1, str2))
+#define TS_ASSERT_WSTR_CONTAINS(str1, str2) TSM_ASSERT(str1, ts_str_contains(str1, str2))
+#define TS_ASSERT_WSTR_NOT_CONTAINS(str1, str2) TSM_ASSERT(str1, !ts_str_contains(str1, str2))
template
std::vector ts_make_vector(T* start, size_t size_bytes)
@@ -226,4 +269,13 @@ std::vector ts_make_vector(T* start, size_t size_bytes)
}
#define TS_ASSERT_VECTOR_EQUALS_ARRAY(vec1, array) TS_ASSERT_EQUALS(vec1, ts_make_vector((array), sizeof(array)))
+class ScriptInterface;
+// Script-based testing setup (defined in test_setup.cpp). Defines TS_* functions.
+void ScriptTestSetup(ScriptInterface&);
+
+// Default game data directory
+// (TODO: game-specific functions like this probably shouldn't be inside lib/, but it's useful
+// here since lots of tests use it)
+fs::wpath DataDir(); // defined in test_setup.cpp
+
#endif // #ifndef INCLUDED_SELF_TEST
diff --git a/source/lib/sysdep/os/win/wposix/waio.h b/source/lib/sysdep/os/win/wposix/waio.h
index 738c4bf569..ddeb34327a 100644
--- a/source/lib/sysdep/os/win/wposix/waio.h
+++ b/source/lib/sysdep/os/win/wposix/waio.h
@@ -26,6 +26,7 @@
#include "no_crt_posix.h"
+#include "lib/lib_errors.h"
// Note: transfer buffers, offsets, and lengths must be sector-aligned
// (we don't bother copying to an align buffer because the file cache
diff --git a/source/lib/sysdep/tests/test_sysdep.h b/source/lib/sysdep/tests/test_sysdep.h
index 701404567c..4f02ea5199 100644
--- a/source/lib/sysdep/tests/test_sysdep.h
+++ b/source/lib/sysdep/tests/test_sysdep.h
@@ -21,6 +21,7 @@
#include "lib/path_util.h"
#include "lib/secure_crt.h"
#include "lib/wchar.h"
+#include "lib/sysdep/cpu.h"
#include "lib/sysdep/sysdep.h"
#include "lib/posix/posix.h" // fminf etc.
diff --git a/source/main.cpp b/source/main.cpp
index 93fcdd123e..97a46bc077 100644
--- a/source/main.cpp
+++ b/source/main.cpp
@@ -58,6 +58,7 @@ that of Atlas depending on commandline parameters.
#include "graphics/Camera.h"
#include "graphics/GameView.h"
#include "simulation/Scheduler.h"
+#include "simulation2/Simulation2.h"
#include "sound/CMusicPlayer.h"
#include "sound/SoundGroupMgr.h"
#include "gui/GUIManager.h"
@@ -383,6 +384,11 @@ static void RunGameOrAtlas(int argc, const char* argv[])
// might run Atlas.
CXeromyces::Startup();
+ // allow switching to new simulation system, before any
+ // other init code makes use of it
+ if (args.Has("sim2"))
+ g_UseSimulation2 = true;
+
// run Atlas (if requested via args)
bool ran_atlas = ATLAS_RunIfOnCmdLine(args);
// Atlas handles the whole init/shutdown/etc sequence by itself;
diff --git a/source/maths/Fixed.cpp b/source/maths/Fixed.cpp
new file mode 100644
index 0000000000..767c499fad
--- /dev/null
+++ b/source/maths/Fixed.cpp
@@ -0,0 +1,55 @@
+/* Copyright (C) 2010 Wildfire Games.
+ * This file is part of 0 A.D.
+ *
+ * 0 A.D. is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * 0 A.D. is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with 0 A.D. If not, see .
+ */
+
+#include "precompiled.h"
+
+#include "Fixed.h"
+
+// Based on http://www.dspguru.com/dsp/tricks/fixed-point-atan2-with-self-normalization
+CFixed_23_8 atan2_approx(CFixed_23_8 y, CFixed_23_8 x)
+{
+ CFixed_23_8 zero;
+
+ // Special case to avoid division-by-zero
+ if (x.IsZero() && y.IsZero())
+ return zero;
+
+ CFixed_23_8 c1;
+ c1.SetInternalValue(201); // pi/4 << 8
+
+ CFixed_23_8 c2;
+ c2.SetInternalValue(603); // 3*pi/4 << 8
+
+ CFixed_23_8 abs_y = y.Absolute();
+
+ CFixed_23_8 angle;
+ if (x >= zero)
+ {
+ CFixed_23_8 r = (x - abs_y) / (x + abs_y);
+ angle = c1 - c1.Multiply(r);
+ }
+ else
+ {
+ CFixed_23_8 r = (x + abs_y) / (abs_y - x);
+ angle = c2 - c1.Multiply(r);
+ }
+
+ if (y < zero)
+ return -angle;
+ else
+ return angle;
+}
diff --git a/source/maths/Fixed.h b/source/maths/Fixed.h
new file mode 100644
index 0000000000..694a655845
--- /dev/null
+++ b/source/maths/Fixed.h
@@ -0,0 +1,156 @@
+/* Copyright (C) 2010 Wildfire Games.
+ * This file is part of 0 A.D.
+ *
+ * 0 A.D. is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * 0 A.D. is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with 0 A.D. If not, see .
+ */
+
+#ifndef INCLUDED_FIXED
+#define INCLUDED_FIXED
+
+#include "lib/types.h"
+
+template
+inline T round_away_from_zero(float value)
+{
+ return (T)(value >= 0 ? value + 0.5f : value - 0.5f);
+}
+
+/**
+ * A simple fixed-point number class, with no fancy features
+ * like overflow checking or anything. (It has very few basic
+ * features too, and needs to be substantially improved before
+ * it'll be of much use.)
+ *
+ * Use CFixed_23_8 rather than using this class directly.
+ */
+template
+class CFixed
+{
+private:
+ T value;
+
+ explicit CFixed(T v) : value(v) { }
+
+public:
+ enum { fract_bits = fract_bits_ };
+
+ CFixed() : value(0) { }
+
+ T GetInternalValue() const { return value; }
+ void SetInternalValue(T n) { value = n; }
+
+ // Conversion to/from primitive types:
+
+ static CFixed FromInt(int n)
+ {
+ return CFixed(n << fract_bits);
+ }
+ static CFixed FromFloat(float n)
+ {
+ if (!isfinite(n))
+ return CFixed(0);
+ float scaled = n * fract_pow2;
+ return CFixed(round_away_from_zero(scaled));
+ }
+ static CFixed FromDouble(double n)
+ {
+ if (!isfinite(n))
+ return CFixed(0);
+ double scaled = n * fract_pow2;
+ return CFixed(round_away_from_zero(scaled));
+ }
+
+ float ToFloat() const
+ {
+ return value / (float)fract_pow2;
+ }
+ double ToDouble() const
+ {
+ return value / (double)fract_pow2;
+ }
+ int ToInt_RoundToZero() const
+ {
+ if (value > 0)
+ return value >> fract_bits;
+ else
+ return (value + fract_pow2 - 1) >> fract_bits;
+ }
+
+ /// Returns true if the number is precisely 0.
+ bool IsZero() const { return value == 0; }
+
+ /// Equality.
+ bool operator==(CFixed n) const { return (value == n.value); }
+
+ /// Numeric comparison.
+ bool operator<=(CFixed n) const { return (value <= n.value); }
+
+ /// Numeric comparison.
+ bool operator<(CFixed n) const { return (value < n.value); }
+
+ /// Numeric comparison.
+ bool operator>=(CFixed n) const { return (value >= n.value); }
+
+ /// Numeric comparison.
+ bool operator>(CFixed n) const { return (value > n.value); }
+
+ // Basic arithmetic:
+
+ /// Add a CFixed. Might overflow.
+ CFixed operator+(CFixed n) const { return CFixed(value + n.value); }
+
+ /// Subtract a CFixed. Might overflow.
+ CFixed operator-(CFixed n) const { return CFixed(value - n.value); }
+
+ /// Negate a CFixed.
+ CFixed operator-() const { return CFixed(-value); }
+
+ /// Divide by a CFixed. Must not have n.IsZero(). Might overflow.
+ CFixed operator/(CFixed n) const
+ {
+ i64 t = (i64)value << fract_bits;
+ return CFixed((T)(t / (i64)n.value));
+ }
+
+ /// Multiply by an integer. Might overflow.
+ CFixed operator*(int n) const { return CFixed(value * n); }
+
+ /// Divide by an integer. Must not have n == 0. Cannot overflow.
+ CFixed operator/(int n) const { return CFixed(value / n); }
+
+ CFixed Absolute() const { return CFixed(abs(value)); }
+
+ /**
+ * Multiply by a CFixed. Likely to overflow if both numbers are large,
+ * so we use an ugly name instead of operator* to make it obvious.
+ */
+ CFixed Multiply(CFixed n) const
+ {
+ i64 t = (i64)value * (i64)n.value;
+ return CFixed((T)(t >> fract_bits));
+ }
+};
+
+/**
+ * A fixed-point number class with 1-bit sign, 23-bit integral part, 8-bit fractional part.
+ */
+typedef CFixed CFixed_23_8;
+
+/**
+ * Inaccurate approximation of atan2 over fixed-point numbers.
+ * Maximum error is almost 0.08 radians (4.5 degrees).
+ */
+CFixed_23_8 atan2_approx(CFixed_23_8 y, CFixed_23_8 x);
+
+#endif // INCLUDED_FIXED
diff --git a/source/maths/FixedVector3D.h b/source/maths/FixedVector3D.h
new file mode 100644
index 0000000000..152b4325c2
--- /dev/null
+++ b/source/maths/FixedVector3D.h
@@ -0,0 +1,162 @@
+/* Copyright (C) 2010 Wildfire Games.
+ * This file is part of 0 A.D.
+ *
+ * 0 A.D. is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * 0 A.D. is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with 0 A.D. If not, see .
+ */
+
+#ifndef INCLUDED_FIXED_VECTOR3D
+#define INCLUDED_FIXED_VECTOR3D
+
+#include "maths/Fixed.h"
+#include "maths/Sqrt.h"
+
+class CFixedVector3D
+{
+private:
+ typedef CFixed_23_8 fixed;
+
+public:
+ fixed X, Y, Z;
+
+ CFixedVector3D() { }
+
+ CFixedVector3D(fixed X, fixed Y, fixed Z) : X(X), Y(Y), Z(Z) { }
+
+ /// Vector equality
+ bool operator==(const CFixedVector3D& v) const
+ {
+ return (X == v.X && Y == v.Y && Z == v.Z);
+ }
+
+ /// Vector addition
+ CFixedVector3D operator+(const CFixedVector3D& v) const
+ {
+ return CFixedVector3D(X + v.X, Y + v.Y, Z + v.Z);
+ }
+
+ /// Vector subtraction
+ CFixedVector3D operator-(const CFixedVector3D& v) const
+ {
+ return CFixedVector3D(X - v.X, Y - v.Y, Z - v.Z);
+ }
+
+ /// Negation
+ CFixedVector3D operator-() const
+ {
+ return CFixedVector3D(-X, -Y, -Z);
+ }
+
+ /// Vector addition
+ CFixedVector3D& operator+=(const CFixedVector3D& v)
+ {
+ *this = *this + v;
+ return *this;
+ }
+
+ /// Vector subtraction
+ CFixedVector3D& operator-=(const CFixedVector3D& v)
+ {
+ *this = *this - v;
+ return *this;
+ }
+
+
+ /**
+ * Returns the length of the vector.
+ * Will not overflow if the result can be represented as type 'fixed'.
+ */
+ fixed Length() const
+ {
+ // Do intermediate calculations with 64-bit ints to avoid overflows
+ i64 x = (i64)X.GetInternalValue();
+ i64 y = (i64)Y.GetInternalValue();
+ i64 z = (i64)Z.GetInternalValue();
+ u64 d2 = (u64)(x * x + y * y + z * z);
+ u32 d = isqrt64(d2);
+ fixed r;
+ r.SetInternalValue((i32)d);
+ return r;
+ }
+
+ /**
+ * Normalize the vector so that length is close to 1.
+ * If length is 0, does nothing.
+ * WARNING: The fixed-point numbers only have 8-bit fractional parts, so
+ * a normalized vector will be very imprecise.
+ */
+ void Normalize()
+ {
+ fixed l = Length();
+ if (!l.IsZero())
+ {
+ X = X / l;
+ Y = Y / l;
+ Z = Z / l;
+ }
+ }
+
+ /**
+ * Normalize the vector so that length is close to n.
+ * If length is 0, does nothing.
+ */
+ void Normalize(fixed n)
+ {
+ if (n.IsZero())
+ {
+ X = Y = Z = fixed::FromInt(0);
+ return;
+ }
+
+ fixed l = Length();
+ // TODO: work out whether this is giving decent precision
+ fixed d = l / n;
+ if (!d.IsZero())
+ {
+ X = X / d;
+ Y = Y / d;
+ Z = Z / d;
+ }
+ }
+
+ /**
+ * Compute the cross product of this vector with another.
+ */
+ CFixedVector3D Cross(const CFixedVector3D& v)
+ {
+ i64 x = ((i64)Y.GetInternalValue() * (i64)v.Z.GetInternalValue()) - ((i64)Z.GetInternalValue() * (i64)v.Y.GetInternalValue());
+ i64 y = ((i64)Z.GetInternalValue() * (i64)v.X.GetInternalValue()) - ((i64)X.GetInternalValue() * (i64)v.Z.GetInternalValue());
+ i64 z = ((i64)X.GetInternalValue() * (i64)v.Y.GetInternalValue()) - ((i64)Y.GetInternalValue() * (i64)v.X.GetInternalValue());
+ CFixedVector3D ret;
+ ret.X.SetInternalValue((i32)(x >> fixed::fract_bits));
+ ret.Y.SetInternalValue((i32)(y >> fixed::fract_bits));
+ ret.Z.SetInternalValue((i32)(z >> fixed::fract_bits));
+ return ret;
+ }
+
+ /**
+ * Compute the dot product of this vector with another.
+ */
+ fixed Dot(const CFixedVector3D& v)
+ {
+ i64 x = (i64)X.GetInternalValue() * (i64)v.X.GetInternalValue();
+ i64 y = (i64)Y.GetInternalValue() * (i64)v.Y.GetInternalValue();
+ i64 z = (i64)Z.GetInternalValue() * (i64)v.Z.GetInternalValue();
+ i64 sum = x + y + z;
+ fixed ret;
+ ret.SetInternalValue((i32)(sum >> fixed::fract_bits));
+ return ret;
+ }
+};
+
+#endif // INCLUDED_FIXED_VECTOR3D
diff --git a/source/maths/MathUtil.h b/source/maths/MathUtil.h
index f718f3f937..3ea54fdc55 100644
--- a/source/maths/MathUtil.h
+++ b/source/maths/MathUtil.h
@@ -1,4 +1,4 @@
-/* Copyright (C) 2009 Wildfire Games.
+/* Copyright (C) 2010 Wildfire Games.
* This file is part of 0 A.D.
*
* 0 A.D. is free software: you can redistribute it and/or modify
@@ -18,6 +18,23 @@
#ifndef INCLUDED_MATHUTIL
#define INCLUDED_MATHUTIL
+
+// C99 math constants (missing on MSVC):
+#ifndef INFINITY
+#define INFINITY (std::numeric_limits::infinity())
+#endif
+#ifndef NAN
+#define NAN (std::numeric_limits::quiet_NaN())
+#endif
+
+// POSIX math constants (missing on MSVC):
+#ifndef M_PI
+#define M_PI 3.14159265358979323846
+#endif
+#ifndef M_PI_2
+#define M_PI_2 1.57079632679489661923
+#endif
+
#ifndef PI
#define PI 3.14159265358979323846f
#endif
diff --git a/source/maths/Sqrt.cpp b/source/maths/Sqrt.cpp
new file mode 100644
index 0000000000..b63a2df1f0
--- /dev/null
+++ b/source/maths/Sqrt.cpp
@@ -0,0 +1,48 @@
+/* Copyright (C) 2010 Wildfire Games.
+ * This file is part of 0 A.D.
+ *
+ * 0 A.D. is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * 0 A.D. is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with 0 A.D. If not, see .
+ */
+
+#include "precompiled.h"
+
+#include "Sqrt.h"
+
+// Based on http://freaknet.org/martin/tape/gos/misc/personal/msc/sqrt/sqrt.html
+u32 isqrt64(u64 n)
+{
+ u64 op = n;
+ u64 res = 0;
+ u64 one = (u64)1 << 62; // highest power of four <= than the argument
+
+ while (one > op)
+ one >>= 2;
+
+ while (one != 0)
+ {
+ if (op >= res + one)
+ {
+ op -= (res + one);
+ res += (one << 1);
+ }
+ res >>= 1;
+ one >>= 2;
+ }
+ return (u32)res;
+}
+
+// TODO: This should be equivalent to (u32)sqrt((double)n), and in practice
+// that seems to be true for all input, so do we actually need this integer-only
+// implementation? i.e. are there any platforms / compiler settings where
+// sqrt(double) won't give the correct answer? and is sqrt(double) faster?
diff --git a/source/maths/Sqrt.h b/source/maths/Sqrt.h
new file mode 100644
index 0000000000..8db047123c
--- /dev/null
+++ b/source/maths/Sqrt.h
@@ -0,0 +1,27 @@
+/* Copyright (C) 2010 Wildfire Games.
+ * This file is part of 0 A.D.
+ *
+ * 0 A.D. is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * 0 A.D. is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with 0 A.D. If not, see .
+ */
+
+#ifndef INCLUDED_MATH_SQRT
+#define INCLUDED_MATH_SQRT
+
+/**
+ * 64-bit integer square root.
+ * Returns r such that r^2 <= n < (r+1)^2, for the complete u64 range.
+ */
+u32 isqrt64(u64 n);
+
+#endif // INCLUDED_MATH_SQRT
diff --git a/source/maths/tests/test_Fixed.h b/source/maths/tests/test_Fixed.h
new file mode 100644
index 0000000000..fd1bd93b7c
--- /dev/null
+++ b/source/maths/tests/test_Fixed.h
@@ -0,0 +1,162 @@
+/* Copyright (C) 2009 Wildfire Games.
+ * This file is part of 0 A.D.
+ *
+ * 0 A.D. is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * 0 A.D. is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with 0 A.D. If not, see .
+ */
+
+#include "lib/self_test.h"
+
+#include "maths/Fixed.h"
+#include "maths/MathUtil.h"
+
+class TestFixed : public CxxTest::TestSuite
+{
+public:
+ void test_basic()
+ {
+ CFixed_23_8 a = CFixed_23_8::FromInt(1234567);
+ TS_ASSERT_EQUALS((a + a).ToDouble(), 2469134);
+ TS_ASSERT_EQUALS((a - a).ToDouble(), 0);
+ TS_ASSERT_EQUALS((-a).ToDouble(), -1234567);
+ TS_ASSERT_EQUALS((a / a).ToDouble(), 1);
+ TS_ASSERT_EQUALS((a / 127).ToDouble(), 9721);
+ TS_ASSERT_EQUALS((a * 2).ToDouble(), 2469134);
+ }
+
+ void test_FromInt()
+ {
+ CFixed_23_8 a = CFixed_23_8::FromInt(123);
+ TS_ASSERT_EQUALS(a.ToFloat(), 123.0f);
+ TS_ASSERT_EQUALS(a.ToDouble(), 123.0);
+ TS_ASSERT_EQUALS(a.ToInt_RoundToZero(), 123);
+ }
+
+ void test_FromFloat()
+ {
+ CFixed_23_8 a = CFixed_23_8::FromFloat(123.125f);
+ TS_ASSERT_EQUALS(a.ToFloat(), 123.125f);
+ TS_ASSERT_EQUALS(a.ToDouble(), 123.125);
+
+ CFixed_23_8 b = CFixed_23_8::FromFloat(-123.125f);
+ TS_ASSERT_EQUALS(b.ToFloat(), -123.125f);
+ TS_ASSERT_EQUALS(b.ToDouble(), -123.125);
+
+ CFixed_23_8 c = CFixed_23_8::FromFloat(INFINITY);
+ TS_ASSERT_EQUALS(c.GetInternalValue(), (i32)0);
+
+ CFixed_23_8 d = CFixed_23_8::FromFloat(-INFINITY);
+ TS_ASSERT_EQUALS(d.GetInternalValue(), (i32)0);
+
+ CFixed_23_8 e = CFixed_23_8::FromFloat(NAN);
+ TS_ASSERT_EQUALS(e.GetInternalValue(), (i32)0);
+ }
+
+ void test_FromDouble()
+ {
+ CFixed_23_8 a = CFixed_23_8::FromDouble(123.125);
+ TS_ASSERT_EQUALS(a.ToFloat(), 123.125f);
+ TS_ASSERT_EQUALS(a.ToDouble(), 123.125);
+
+ CFixed_23_8 b = CFixed_23_8::FromDouble(-123.125);
+ TS_ASSERT_EQUALS(b.ToFloat(), -123.125f);
+ TS_ASSERT_EQUALS(b.ToDouble(), -123.125);
+
+ CFixed_23_8 c = CFixed_23_8::FromDouble(INFINITY);
+ TS_ASSERT_EQUALS(c.GetInternalValue(), (i32)0);
+
+ CFixed_23_8 d = CFixed_23_8::FromDouble(-INFINITY);
+ TS_ASSERT_EQUALS(d.GetInternalValue(), (i32)0);
+
+ CFixed_23_8 e = CFixed_23_8::FromDouble(NAN);
+ TS_ASSERT_EQUALS(e.GetInternalValue(), (i32)0);
+ }
+
+ void test_FromFloat_Rounding()
+ {
+ double eps = pow(2.0, -8.0);
+ TS_ASSERT_EQUALS(CFixed_23_8::FromFloat(eps).ToDouble(), eps);
+ TS_ASSERT_EQUALS(CFixed_23_8::FromFloat(eps * 0.5625).ToDouble(), eps);
+ TS_ASSERT_EQUALS(CFixed_23_8::FromFloat(eps * 0.5).ToDouble(), eps);
+ TS_ASSERT_EQUALS(CFixed_23_8::FromFloat(eps * 0.4375).ToDouble(), 0.0);
+ TS_ASSERT_EQUALS(CFixed_23_8::FromFloat(-eps).ToDouble(), -eps);
+ TS_ASSERT_EQUALS(CFixed_23_8::FromFloat(-eps * 0.5625).ToDouble(), -eps);
+ TS_ASSERT_EQUALS(CFixed_23_8::FromFloat(-eps * 0.5).ToDouble(), -eps);
+ TS_ASSERT_EQUALS(CFixed_23_8::FromFloat(-eps * 0.4375).ToDouble(), 0.0);
+ }
+
+ void test_RoundToZero()
+ {
+ TS_ASSERT_EQUALS(CFixed_23_8::FromFloat(10.f).ToInt_RoundToZero(), 10);
+ TS_ASSERT_EQUALS(CFixed_23_8::FromFloat(10.1f).ToInt_RoundToZero(), 10);
+ TS_ASSERT_EQUALS(CFixed_23_8::FromFloat(10.5f).ToInt_RoundToZero(), 10);
+ TS_ASSERT_EQUALS(CFixed_23_8::FromFloat(10.99f).ToInt_RoundToZero(), 10);
+ TS_ASSERT_EQUALS(CFixed_23_8::FromFloat(0.1f).ToInt_RoundToZero(), 0);
+ TS_ASSERT_EQUALS(CFixed_23_8::FromFloat(0.0f).ToInt_RoundToZero(), 0);
+ TS_ASSERT_EQUALS(CFixed_23_8::FromFloat(-0.1f).ToInt_RoundToZero(), 0);
+ TS_ASSERT_EQUALS(CFixed_23_8::FromFloat(-0.99f).ToInt_RoundToZero(), 0);
+ TS_ASSERT_EQUALS(CFixed_23_8::FromFloat(-1.0f).ToInt_RoundToZero(), -1);
+ TS_ASSERT_EQUALS(CFixed_23_8::FromFloat(-2.0f).ToInt_RoundToZero(), -2);
+ TS_ASSERT_EQUALS(CFixed_23_8::FromFloat(-2.5f).ToInt_RoundToZero(), -2);
+ TS_ASSERT_EQUALS(CFixed_23_8::FromFloat(-2.99f).ToInt_RoundToZero(), -2);
+ }
+
+ // TODO: test all the arithmetic operators
+
+ void test_Atan2()
+ {
+ typedef CFixed_23_8 f;
+
+ // Special cases from atan2 man page:
+ TS_ASSERT_DELTA(atan2_approx(f::FromInt(0), f::FromInt(-1)).ToDouble(), M_PI, 0.01);
+ TS_ASSERT_EQUALS(atan2_approx(f::FromInt(0), f::FromInt(+1)).ToDouble(), 0);
+ TS_ASSERT_DELTA(atan2_approx(f::FromInt(-1), f::FromInt(0)).ToDouble(), -M_PI_2, 0.01);
+ TS_ASSERT_DELTA(atan2_approx(f::FromInt(+1), f::FromInt(0)).ToDouble(), +M_PI_2, 0.01);
+ TS_ASSERT_EQUALS(atan2_approx(f::FromInt(0), f::FromInt(0)).ToDouble(), 0);
+
+ // Test that it approximately matches libc's atan2
+ #define T(y, x) TS_ASSERT_DELTA(atan2_approx(f::FromDouble(y), f::FromDouble(x)).ToDouble(), atan2((double)(y), (double)(x)), 0.078)
+
+ // Quadrants
+ T(1, 1);
+ T(-1, 1);
+ T(1, -1);
+ T(-1, -1);
+
+ // Scale
+ T(10, 10);
+ T(100, 100);
+ T(1000, 1000);
+ T(10000, 10000);
+
+ // Some arbitrary cases
+ T(2, 1);
+ T(3, 1);
+ T(4, 1);
+ T(10, 1);
+ T(1000, 1);
+ T(1, 2);
+ T(1, 3);
+ T(1, 4);
+ T(1, 10);
+ T(1, 1000);
+
+ // The highest-error region
+ for (double x = 2.0; x < 4.0; x += 0.01)
+ {
+ T(1, x);
+ }
+
+ #undef T
+ }
+};
diff --git a/source/maths/tests/test_FixedVector3D.h b/source/maths/tests/test_FixedVector3D.h
new file mode 100644
index 0000000000..74618b8216
--- /dev/null
+++ b/source/maths/tests/test_FixedVector3D.h
@@ -0,0 +1,114 @@
+/* Copyright (C) 2009 Wildfire Games.
+ * This file is part of 0 A.D.
+ *
+ * 0 A.D. is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * 0 A.D. is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with 0 A.D. If not, see .
+ */
+
+#include "lib/self_test.h"
+
+#include "maths/FixedVector3D.h"
+
+#define TS_ASSERT_VEC_EQUALS(v, x, y, z) \
+ TS_ASSERT_EQUALS(v.X.ToDouble(), x); \
+ TS_ASSERT_EQUALS(v.Y.ToDouble(), y); \
+ TS_ASSERT_EQUALS(v.Z.ToDouble(), z);
+
+class TestFixedVector3D : public CxxTest::TestSuite
+{
+ typedef CFixed_23_8 fixed;
+public:
+ void test_basic()
+ {
+ CFixedVector3D v1 (fixed::FromInt(1), fixed::FromInt(2), fixed::FromInt(3));
+ CFixedVector3D v2 (fixed::FromInt(10), fixed::FromInt(20), fixed::FromInt(30));
+ CFixedVector3D v3;
+ TS_ASSERT_VEC_EQUALS(v1, 1, 2, 3);
+ TS_ASSERT_VEC_EQUALS(v2, 10, 20, 30);
+ TS_ASSERT_VEC_EQUALS(v3, 0, 0, 0);
+ v3 = v1 + v2;
+ TS_ASSERT_VEC_EQUALS(v3, 11, 22, 33);
+ v3 += v2;
+ TS_ASSERT_VEC_EQUALS(v3, 21, 42, 63);
+ v3 -= v2;
+ TS_ASSERT_VEC_EQUALS(v3, 11, 22, 33);
+ v3 = v1 - v2;
+ TS_ASSERT_VEC_EQUALS(v3, -9, -18, -27);
+ v3 = -v3;
+ TS_ASSERT_VEC_EQUALS(v3, 9, 18, 27);
+ }
+
+ void test_Length()
+ {
+ CFixedVector3D v1 (fixed::FromInt(3), fixed::FromInt(4), fixed::FromInt(12));
+ TS_ASSERT_EQUALS(v1.Length().ToDouble(), 13.0);
+
+ fixed max;
+ max.SetInternalValue((i32)0x7fffffff);
+ CFixedVector3D v2 (max, fixed::FromInt(0), fixed::FromInt(0));
+ TS_ASSERT_EQUALS(v2.Length().ToDouble(), max.ToDouble());
+
+ fixed large;
+ large.SetInternalValue((i32)((double)0x7fffffff/sqrt(3.0))+1); // largest value that shouldn't cause overflow
+ CFixedVector3D v3 (large, large, large);
+ TS_ASSERT_DELTA(v3.Length().ToDouble(), sqrt(3.0)*large.ToDouble(), 0.01);
+ }
+
+ void test_Normalize()
+ {
+ CFixedVector3D v0 (fixed::FromInt(0), fixed::FromInt(0), fixed::FromInt(0));
+ v0.Normalize();
+ TS_ASSERT_EQUALS(v0.X.ToDouble(), 0.0);
+ TS_ASSERT_EQUALS(v0.Y.ToDouble(), 0.0);
+ TS_ASSERT_EQUALS(v0.Z.ToDouble(), 0.0);
+
+ CFixedVector3D v1 (fixed::FromInt(3), fixed::FromInt(4), fixed::FromInt(12));
+ v1.Normalize();
+ TS_ASSERT_DELTA(v1.X.ToDouble(), 3.0/13.0, 0.01);
+ TS_ASSERT_DELTA(v1.Y.ToDouble(), 4.0/13.0, 0.01);
+ TS_ASSERT_DELTA(v1.Z.ToDouble(), 12.0/13.0, 0.01);
+
+ fixed max;
+ max.SetInternalValue((i32)0x7fffffff);
+ CFixedVector3D v2 (max, fixed::FromInt(0), fixed::FromInt(0));
+ v2.Normalize();
+ TS_ASSERT_EQUALS(v2.X.ToDouble(), 1.0);
+ TS_ASSERT_EQUALS(v2.Y.ToDouble(), 0.0);
+ TS_ASSERT_EQUALS(v2.Z.ToDouble(), 0.0);
+
+ fixed large;
+ large.SetInternalValue((i32)((double)0x7fffffff/sqrt(3.0))+1); // largest value that shouldn't cause overflow
+ CFixedVector3D v3 (large, large, large);
+ v3.Normalize();
+ TS_ASSERT_DELTA(v3.X.ToDouble(), 1.0/sqrt(3.0), 0.01);
+ TS_ASSERT_DELTA(v3.Y.ToDouble(), 1.0/sqrt(3.0), 0.01);
+ TS_ASSERT_DELTA(v3.Z.ToDouble(), 1.0/sqrt(3.0), 0.01);
+ }
+
+ void test_Cross()
+ {
+ CFixedVector3D v1 (fixed::FromInt(5), fixed::FromInt(6), fixed::FromInt(7));
+ CFixedVector3D v2 (fixed::FromInt(8), fixed::FromInt(9), fixed::FromInt(-10));
+ CFixedVector3D v3 = v1.Cross(v2);
+ TS_ASSERT_EQUALS(v3.X.ToDouble(), 6*-10 - 7*9);
+ TS_ASSERT_EQUALS(v3.Y.ToDouble(), 7*8 - 5*-10);
+ TS_ASSERT_EQUALS(v3.Z.ToDouble(), 5*9 - 8*6);
+ }
+
+ void test_Dot()
+ {
+ CFixedVector3D v1 (fixed::FromInt(5), fixed::FromInt(6), fixed::FromInt(7));
+ CFixedVector3D v2 (fixed::FromInt(8), fixed::FromInt(9), fixed::FromInt(-10));
+ TS_ASSERT_EQUALS(v1.Dot(v2).ToDouble(), 5*8 + 6*9 + 7*-10);
+ }
+};
diff --git a/source/maths/tests/test_Sqrt.h b/source/maths/tests/test_Sqrt.h
new file mode 100644
index 0000000000..23f5799856
--- /dev/null
+++ b/source/maths/tests/test_Sqrt.h
@@ -0,0 +1,86 @@
+/* Copyright (C) 2009 Wildfire Games.
+ * This file is part of 0 A.D.
+ *
+ * 0 A.D. is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * 0 A.D. is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with 0 A.D. If not, see .
+ */
+
+#include "lib/self_test.h"
+
+#include "maths/Sqrt.h"
+
+#include
+
+class TestSqrt : public CxxTest::TestSuite
+{
+public:
+ void t(u32 n)
+ {
+ TS_ASSERT_EQUALS(isqrt64((u64)n*(u64)n), n);
+ }
+
+ void s(u64 n, u64 exp)
+ {
+ TS_ASSERT_EQUALS((u64)isqrt64(n), exp);
+ }
+
+ void test_sqrt()
+ {
+ t(0);
+ t(1);
+ t(2);
+ t(255);
+ t(256);
+ t(257);
+ t(65535);
+ t(65536);
+ t(65537);
+ t(16777215);
+ t(16777216);
+ t(16777217);
+ t(2147483647);
+ t(2147483648u);
+ t(2147483649u);
+ t(4294967295u);
+
+ s(2, 1);
+ s(3, 1);
+ s(4, 2);
+ s(255, 15);
+ s(256, 16);
+ s(257, 16);
+ s(65535, 255);
+ s(65536, 256);
+ s(65537, 256);
+ s(999999, 999);
+ s(1000000, 1000);
+ s(1000001, 1000);
+ s((u64)-1, 4294967295u);
+ }
+
+ void test_random()
+ {
+ // Test with some random u64s, to make sure the output agrees with floor(sqrt(double))
+ // (TODO: This might be making non-portable assumptions about sqrt(double))
+
+ boost::mt19937 rng;
+ boost::uniform_int ints(0, (u64)-1);
+ boost::variate_generator > gen(rng, ints);
+
+ for (size_t i = 0; i < 1024; ++i)
+ {
+ u64 n = gen();
+ s(n, (u64)sqrt((double)n));
+ }
+ }
+};
diff --git a/source/mocks/dlfcn.h b/source/mocks/dlfcn.h
index 8dd7dab96c..d4f0982cae 100644
--- a/source/mocks/dlfcn.h
+++ b/source/mocks/dlfcn.h
@@ -1,3 +1,20 @@
+/* Copyright (C) 2010 Wildfire Games.
+ * This file is part of 0 A.D.
+ *
+ * 0 A.D. is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * 0 A.D. is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with 0 A.D. If not, see .
+ */
+
#include
#include
CXXTEST_MOCK_GLOBAL(
diff --git a/source/mocks/mocks_real.cpp b/source/mocks/mocks_real.cpp
index 1d181afe0a..4ef3b0a1b6 100644
--- a/source/mocks/mocks_real.cpp
+++ b/source/mocks/mocks_real.cpp
@@ -1,3 +1,20 @@
+/* Copyright (C) 2010 Wildfire Games.
+ * This file is part of 0 A.D.
+ *
+ * 0 A.D. is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * 0 A.D. is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with 0 A.D. If not, see .
+ */
+
#define CXXTEST_MOCK_REAL_SOURCE_FILE
// Pull in the common config headers from precompiled.h,
diff --git a/source/mocks/mocks_test.cpp b/source/mocks/mocks_test.cpp
index c72c4b579f..37ed2d037e 100644
--- a/source/mocks/mocks_test.cpp
+++ b/source/mocks/mocks_test.cpp
@@ -1,3 +1,20 @@
+/* Copyright (C) 2010 Wildfire Games.
+ * This file is part of 0 A.D.
+ *
+ * 0 A.D. is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * 0 A.D. is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with 0 A.D. If not, see .
+ */
+
#define CXXTEST_MOCK_TEST_SOURCE_FILE
// Pull in the common config headers from precompiled.h,
diff --git a/source/mocks/unistd.h b/source/mocks/unistd.h
index b252952644..647bebabfa 100644
--- a/source/mocks/unistd.h
+++ b/source/mocks/unistd.h
@@ -1,3 +1,20 @@
+/* Copyright (C) 2010 Wildfire Games.
+ * This file is part of 0 A.D.
+ *
+ * 0 A.D. is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * 0 A.D. is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with 0 A.D. If not, see .
+ */
+
#include
#include
CXXTEST_MOCK_GLOBAL(
diff --git a/source/network/SocketBase.cpp b/source/network/SocketBase.cpp
index 2be2bfa23e..aabe75ee4f 100644
--- a/source/network/SocketBase.cpp
+++ b/source/network/SocketBase.cpp
@@ -23,6 +23,8 @@
#include "lib/sysdep/os/win/wposix/wsock_internal.h"
#endif
+#include "lib/sysdep/cpu.h"
+
#include "Network.h"
#include "NetworkInternal.h"
diff --git a/source/pch/gui/precompiled.h b/source/pch/gui/precompiled.h
index f5f59b57d1..8d3653b99f 100644
--- a/source/pch/gui/precompiled.h
+++ b/source/pch/gui/precompiled.h
@@ -16,5 +16,3 @@
*/
#include "lib/precompiled.h" // common precompiled header
-
-// "gui"-specific PCH:
diff --git a/source/pch/i18n/precompiled.h b/source/pch/i18n/precompiled.h
index 6081fdc45c..96a6d96832 100644
--- a/source/pch/i18n/precompiled.h
+++ b/source/pch/i18n/precompiled.h
@@ -15,6 +15,9 @@
* along with 0 A.D. If not, see .
*/
+#define MINIMAL_PCH 1
#include "lib/precompiled.h" // common precompiled header
-// "i18n"-specific PCH:
+// Minimal is a bit *too* minimal to let things compile, so include a few more headers
+#include "lib/debug.h"
+#include "lib/secure_crt.h"
diff --git a/source/pch/network/precompiled.h b/source/pch/network/precompiled.h
index 15130e1271..221eef9ce8 100644
--- a/source/pch/network/precompiled.h
+++ b/source/pch/network/precompiled.h
@@ -15,10 +15,5 @@
* along with 0 A.D. If not, see .
*/
+#define MINIMAL_PCH 0
#include "lib/precompiled.h" // common precompiled header
-
-// network-specific PCH:
-
-#if HAVE_PCH
-
-#endif // HAVE_PCH
diff --git a/source/pch/scriptinterface/precompiled.cpp b/source/pch/scriptinterface/precompiled.cpp
new file mode 100644
index 0000000000..82eb54bbb0
--- /dev/null
+++ b/source/pch/scriptinterface/precompiled.cpp
@@ -0,0 +1,18 @@
+/* Copyright (C) 2009 Wildfire Games.
+ * This file is part of 0 A.D.
+ *
+ * 0 A.D. is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * 0 A.D. is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with 0 A.D. If not, see .
+ */
+
+#include "precompiled.h"
diff --git a/source/pch/scriptinterface/precompiled.h b/source/pch/scriptinterface/precompiled.h
new file mode 100644
index 0000000000..afa0bbc8e9
--- /dev/null
+++ b/source/pch/scriptinterface/precompiled.h
@@ -0,0 +1,19 @@
+/* Copyright (C) 2009 Wildfire Games.
+ * This file is part of 0 A.D.
+ *
+ * 0 A.D. is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * 0 A.D. is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with 0 A.D. If not, see .
+ */
+
+#define MINIMAL_PCH 2
+#include "lib/precompiled.h" // common precompiled header
diff --git a/source/pch/simulation2/precompiled.cpp b/source/pch/simulation2/precompiled.cpp
new file mode 100644
index 0000000000..82eb54bbb0
--- /dev/null
+++ b/source/pch/simulation2/precompiled.cpp
@@ -0,0 +1,18 @@
+/* Copyright (C) 2009 Wildfire Games.
+ * This file is part of 0 A.D.
+ *
+ * 0 A.D. is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * 0 A.D. is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with 0 A.D. If not, see .
+ */
+
+#include "precompiled.h"
diff --git a/source/pch/simulation2/precompiled.h b/source/pch/simulation2/precompiled.h
new file mode 100644
index 0000000000..0740c54659
--- /dev/null
+++ b/source/pch/simulation2/precompiled.h
@@ -0,0 +1,24 @@
+/* Copyright (C) 2009 Wildfire Games.
+ * This file is part of 0 A.D.
+ *
+ * 0 A.D. is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * 0 A.D. is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with 0 A.D. If not, see .
+ */
+
+#define MINIMAL_PCH 1
+#include "lib/precompiled.h" // common precompiled header
+
+// Minimal is a bit *too* minimal to let things compile, so include a few more headers
+#include "lib/debug.h"
+#include
+using boost::shared_ptr;
diff --git a/source/ps/ConfigDB.cpp b/source/ps/ConfigDB.cpp
index fc32475b2e..a6244398b8 100644
--- a/source/ps/ConfigDB.cpp
+++ b/source/ps/ConfigDB.cpp
@@ -283,6 +283,7 @@ bool CConfigDB::Reload(EConfigNamespace ns)
}
else
{
+ LOG(CLogger::Normal, LOG_CATEGORY, L"Loading config file \"%ls\"", m_ConfigFile[ns].c_str());
LibError ret = g_VFS->LoadFile(m_ConfigFile[ns], buffer, buflen);
if (ret != INFO::OK)
{
diff --git a/source/ps/Errors.cpp b/source/ps/Errors.cpp
index 9f9d25d041..9179097df1 100644
--- a/source/ps/Errors.cpp
+++ b/source/ps/Errors.cpp
@@ -4,131 +4,153 @@
#include "Errors.h"
-class PSERROR_CVFSFile : public PSERROR {};
-class PSERROR_DllLoader : public PSERROR {};
-class PSERROR_Error : public PSERROR {};
-class PSERROR_File : public PSERROR {};
-class PSERROR_GUI : public PSERROR {};
-class PSERROR_Game : public PSERROR {};
-class PSERROR_I18n : public PSERROR {};
-class PSERROR_Renderer : public PSERROR {};
-class PSERROR_Scripting : public PSERROR {};
-class PSERROR_System : public PSERROR {};
-class PSERROR_Xeromyces : public PSERROR {};
+class PSERROR_CVFSFile : public PSERROR { protected: PSERROR_CVFSFile(const char* msg); };
+class PSERROR_Deserialize : public PSERROR { protected: PSERROR_Deserialize(const char* msg); };
+class PSERROR_DllLoader : public PSERROR { protected: PSERROR_DllLoader(const char* msg); };
+class PSERROR_Error : public PSERROR { protected: PSERROR_Error(const char* msg); };
+class PSERROR_File : public PSERROR { protected: PSERROR_File(const char* msg); };
+class PSERROR_GUI : public PSERROR { protected: PSERROR_GUI(const char* msg); };
+class PSERROR_Game : public PSERROR { protected: PSERROR_Game(const char* msg); };
+class PSERROR_I18n : public PSERROR { protected: PSERROR_I18n(const char* msg); };
+class PSERROR_Renderer : public PSERROR { protected: PSERROR_Renderer(const char* msg); };
+class PSERROR_Scripting : public PSERROR { protected: PSERROR_Scripting(const char* msg); };
+class PSERROR_Serialize : public PSERROR { protected: PSERROR_Serialize(const char* msg); };
+class PSERROR_System : public PSERROR { protected: PSERROR_System(const char* msg); };
+class PSERROR_Xeromyces : public PSERROR { protected: PSERROR_Xeromyces(const char* msg); };
-class PSERROR_Game_World : public PSERROR_Game {};
-class PSERROR_I18n_Script : public PSERROR_I18n {};
-class PSERROR_Scripting_DefineType : public PSERROR_Scripting {};
-class PSERROR_Scripting_LoadFile : public PSERROR_Scripting {};
+class PSERROR_Game_World : public PSERROR_Game { protected: PSERROR_Game_World(const char* msg); };
+class PSERROR_I18n_Script : public PSERROR_I18n { protected: PSERROR_I18n_Script(const char* msg); };
+class PSERROR_Scripting_DefineType : public PSERROR_Scripting { protected: PSERROR_Scripting_DefineType(const char* msg); };
+class PSERROR_Scripting_LoadFile : public PSERROR_Scripting { protected: PSERROR_Scripting_LoadFile(const char* msg); };
-class PSERROR_CVFSFile_AlreadyLoaded : public PSERROR_CVFSFile { public: PSRETURN getCode() const; };
-class PSERROR_CVFSFile_InvalidBufferAccess : public PSERROR_CVFSFile { public: PSRETURN getCode() const; };
-class PSERROR_CVFSFile_LoadFailed : public PSERROR_CVFSFile { public: PSRETURN getCode() const; };
-class PSERROR_DllLoader_DllNotLoaded : public PSERROR_DllLoader { public: PSRETURN getCode() const; };
-class PSERROR_DllLoader_SymbolNotFound : public PSERROR_DllLoader { public: PSRETURN getCode() const; };
-class PSERROR_Error_InvalidError : public PSERROR_Error { public: PSRETURN getCode() const; };
-class PSERROR_File_InvalidType : public PSERROR_File { public: PSRETURN getCode() const; };
-class PSERROR_File_InvalidVersion : public PSERROR_File { public: PSRETURN getCode() const; };
-class PSERROR_File_OpenFailed : public PSERROR_File { public: PSRETURN getCode() const; };
-class PSERROR_File_ReadFailed : public PSERROR_File { public: PSRETURN getCode() const; };
-class PSERROR_File_UnexpectedEOF : public PSERROR_File { public: PSRETURN getCode() const; };
-class PSERROR_File_WriteFailed : public PSERROR_File { public: PSRETURN getCode() const; };
-class PSERROR_GUI_InvalidSetting : public PSERROR_GUI { public: PSRETURN getCode() const; };
-class PSERROR_GUI_JSOpenFailed : public PSERROR_GUI { public: PSRETURN getCode() const; };
-class PSERROR_GUI_NameAmbiguity : public PSERROR_GUI { public: PSRETURN getCode() const; };
-class PSERROR_GUI_NullObjectProvided : public PSERROR_GUI { public: PSRETURN getCode() const; };
-class PSERROR_GUI_ObjectNeedsName : public PSERROR_GUI { public: PSRETURN getCode() const; };
-class PSERROR_GUI_OperationNeedsGUIObject : public PSERROR_GUI { public: PSRETURN getCode() const; };
-class PSERROR_GUI_UnableToParse : public PSERROR_GUI { public: PSRETURN getCode() const; };
-class PSERROR_Game_World_MapLoadFailed : public PSERROR_Game_World { public: PSRETURN getCode() const; };
-class PSERROR_I18n_Script_SetupFailed : public PSERROR_I18n_Script { public: PSRETURN getCode() const; };
-class PSERROR_Renderer_VBOFailed : public PSERROR_Renderer { public: PSRETURN getCode() const; };
-class PSERROR_Scripting_CallFunctionFailed : public PSERROR_Scripting { public: PSRETURN getCode() const; };
-class PSERROR_Scripting_ConversionFailed : public PSERROR_Scripting { public: PSRETURN getCode() const; };
-class PSERROR_Scripting_CreateObjectFailed : public PSERROR_Scripting { public: PSRETURN getCode() const; };
-class PSERROR_Scripting_DefineConstantFailed : public PSERROR_Scripting { public: PSRETURN getCode() const; };
-class PSERROR_Scripting_DefineType_AlreadyExists : public PSERROR_Scripting_DefineType { public: PSRETURN getCode() const; };
-class PSERROR_Scripting_DefineType_CreationFailed : public PSERROR_Scripting_DefineType { public: PSRETURN getCode() const; };
-class PSERROR_Scripting_LoadFile_EvalErrors : public PSERROR_Scripting_LoadFile { public: PSRETURN getCode() const; };
-class PSERROR_Scripting_LoadFile_OpenFailed : public PSERROR_Scripting_LoadFile { public: PSRETURN getCode() const; };
-class PSERROR_Scripting_RegisterFunctionFailed : public PSERROR_Scripting { public: PSRETURN getCode() const; };
-class PSERROR_Scripting_SetupFailed : public PSERROR_Scripting { public: PSRETURN getCode() const; };
-class PSERROR_Scripting_TypeDoesNotExist : public PSERROR_Scripting { public: PSRETURN getCode() const; };
-class PSERROR_System_RequiredExtensionsMissing : public PSERROR_System { public: PSRETURN getCode() const; };
-class PSERROR_System_SDLInitFailed : public PSERROR_System { public: PSRETURN getCode() const; };
-class PSERROR_System_VmodeFailed : public PSERROR_System { public: PSRETURN getCode() const; };
-class PSERROR_Xeromyces_XMLOpenFailed : public PSERROR_Xeromyces { public: PSRETURN getCode() const; };
-class PSERROR_Xeromyces_XMLParseError : public PSERROR_Xeromyces { public: PSRETURN getCode() const; };
+class PSERROR_CVFSFile_AlreadyLoaded : public PSERROR_CVFSFile { public: PSERROR_CVFSFile_AlreadyLoaded(); PSERROR_CVFSFile_AlreadyLoaded(const char* msg); PSRETURN getCode() const; };
+class PSERROR_CVFSFile_InvalidBufferAccess : public PSERROR_CVFSFile { public: PSERROR_CVFSFile_InvalidBufferAccess(); PSERROR_CVFSFile_InvalidBufferAccess(const char* msg); PSRETURN getCode() const; };
+class PSERROR_CVFSFile_LoadFailed : public PSERROR_CVFSFile { public: PSERROR_CVFSFile_LoadFailed(); PSERROR_CVFSFile_LoadFailed(const char* msg); PSRETURN getCode() const; };
+class PSERROR_Deserialize_InvalidCharInString : public PSERROR_Deserialize { public: PSERROR_Deserialize_InvalidCharInString(); PSERROR_Deserialize_InvalidCharInString(const char* msg); PSRETURN getCode() const; };
+class PSERROR_Deserialize_OutOfBounds : public PSERROR_Deserialize { public: PSERROR_Deserialize_OutOfBounds(); PSERROR_Deserialize_OutOfBounds(const char* msg); PSRETURN getCode() const; };
+class PSERROR_Deserialize_ReadFailed : public PSERROR_Deserialize { public: PSERROR_Deserialize_ReadFailed(); PSERROR_Deserialize_ReadFailed(const char* msg); PSRETURN getCode() const; };
+class PSERROR_Deserialize_ScriptError : public PSERROR_Deserialize { public: PSERROR_Deserialize_ScriptError(); PSERROR_Deserialize_ScriptError(const char* msg); PSRETURN getCode() const; };
+class PSERROR_DllLoader_DllNotLoaded : public PSERROR_DllLoader { public: PSERROR_DllLoader_DllNotLoaded(); PSERROR_DllLoader_DllNotLoaded(const char* msg); PSRETURN getCode() const; };
+class PSERROR_DllLoader_SymbolNotFound : public PSERROR_DllLoader { public: PSERROR_DllLoader_SymbolNotFound(); PSERROR_DllLoader_SymbolNotFound(const char* msg); PSRETURN getCode() const; };
+class PSERROR_Error_InvalidError : public PSERROR_Error { public: PSERROR_Error_InvalidError(); PSERROR_Error_InvalidError(const char* msg); PSRETURN getCode() const; };
+class PSERROR_File_InvalidType : public PSERROR_File { public: PSERROR_File_InvalidType(); PSERROR_File_InvalidType(const char* msg); PSRETURN getCode() const; };
+class PSERROR_File_InvalidVersion : public PSERROR_File { public: PSERROR_File_InvalidVersion(); PSERROR_File_InvalidVersion(const char* msg); PSRETURN getCode() const; };
+class PSERROR_File_OpenFailed : public PSERROR_File { public: PSERROR_File_OpenFailed(); PSERROR_File_OpenFailed(const char* msg); PSRETURN getCode() const; };
+class PSERROR_File_ReadFailed : public PSERROR_File { public: PSERROR_File_ReadFailed(); PSERROR_File_ReadFailed(const char* msg); PSRETURN getCode() const; };
+class PSERROR_File_UnexpectedEOF : public PSERROR_File { public: PSERROR_File_UnexpectedEOF(); PSERROR_File_UnexpectedEOF(const char* msg); PSRETURN getCode() const; };
+class PSERROR_File_WriteFailed : public PSERROR_File { public: PSERROR_File_WriteFailed(); PSERROR_File_WriteFailed(const char* msg); PSRETURN getCode() const; };
+class PSERROR_GUI_InvalidSetting : public PSERROR_GUI { public: PSERROR_GUI_InvalidSetting(); PSERROR_GUI_InvalidSetting(const char* msg); PSRETURN getCode() const; };
+class PSERROR_GUI_JSOpenFailed : public PSERROR_GUI { public: PSERROR_GUI_JSOpenFailed(); PSERROR_GUI_JSOpenFailed(const char* msg); PSRETURN getCode() const; };
+class PSERROR_GUI_NameAmbiguity : public PSERROR_GUI { public: PSERROR_GUI_NameAmbiguity(); PSERROR_GUI_NameAmbiguity(const char* msg); PSRETURN getCode() const; };
+class PSERROR_GUI_NullObjectProvided : public PSERROR_GUI { public: PSERROR_GUI_NullObjectProvided(); PSERROR_GUI_NullObjectProvided(const char* msg); PSRETURN getCode() const; };
+class PSERROR_GUI_ObjectNeedsName : public PSERROR_GUI { public: PSERROR_GUI_ObjectNeedsName(); PSERROR_GUI_ObjectNeedsName(const char* msg); PSRETURN getCode() const; };
+class PSERROR_GUI_OperationNeedsGUIObject : public PSERROR_GUI { public: PSERROR_GUI_OperationNeedsGUIObject(); PSERROR_GUI_OperationNeedsGUIObject(const char* msg); PSRETURN getCode() const; };
+class PSERROR_GUI_UnableToParse : public PSERROR_GUI { public: PSERROR_GUI_UnableToParse(); PSERROR_GUI_UnableToParse(const char* msg); PSRETURN getCode() const; };
+class PSERROR_Game_World_MapLoadFailed : public PSERROR_Game_World { public: PSERROR_Game_World_MapLoadFailed(); PSERROR_Game_World_MapLoadFailed(const char* msg); PSRETURN getCode() const; };
+class PSERROR_I18n_Script_SetupFailed : public PSERROR_I18n_Script { public: PSERROR_I18n_Script_SetupFailed(); PSERROR_I18n_Script_SetupFailed(const char* msg); PSRETURN getCode() const; };
+class PSERROR_Renderer_VBOFailed : public PSERROR_Renderer { public: PSERROR_Renderer_VBOFailed(); PSERROR_Renderer_VBOFailed(const char* msg); PSRETURN getCode() const; };
+class PSERROR_Scripting_CallFunctionFailed : public PSERROR_Scripting { public: PSERROR_Scripting_CallFunctionFailed(); PSERROR_Scripting_CallFunctionFailed(const char* msg); PSRETURN getCode() const; };
+class PSERROR_Scripting_ConversionFailed : public PSERROR_Scripting { public: PSERROR_Scripting_ConversionFailed(); PSERROR_Scripting_ConversionFailed(const char* msg); PSRETURN getCode() const; };
+class PSERROR_Scripting_CreateObjectFailed : public PSERROR_Scripting { public: PSERROR_Scripting_CreateObjectFailed(); PSERROR_Scripting_CreateObjectFailed(const char* msg); PSRETURN getCode() const; };
+class PSERROR_Scripting_DefineConstantFailed : public PSERROR_Scripting { public: PSERROR_Scripting_DefineConstantFailed(); PSERROR_Scripting_DefineConstantFailed(const char* msg); PSRETURN getCode() const; };
+class PSERROR_Scripting_DefineType_AlreadyExists : public PSERROR_Scripting_DefineType { public: PSERROR_Scripting_DefineType_AlreadyExists(); PSERROR_Scripting_DefineType_AlreadyExists(const char* msg); PSRETURN getCode() const; };
+class PSERROR_Scripting_DefineType_CreationFailed : public PSERROR_Scripting_DefineType { public: PSERROR_Scripting_DefineType_CreationFailed(); PSERROR_Scripting_DefineType_CreationFailed(const char* msg); PSRETURN getCode() const; };
+class PSERROR_Scripting_LoadFile_EvalErrors : public PSERROR_Scripting_LoadFile { public: PSERROR_Scripting_LoadFile_EvalErrors(); PSERROR_Scripting_LoadFile_EvalErrors(const char* msg); PSRETURN getCode() const; };
+class PSERROR_Scripting_LoadFile_OpenFailed : public PSERROR_Scripting_LoadFile { public: PSERROR_Scripting_LoadFile_OpenFailed(); PSERROR_Scripting_LoadFile_OpenFailed(const char* msg); PSRETURN getCode() const; };
+class PSERROR_Scripting_RegisterFunctionFailed : public PSERROR_Scripting { public: PSERROR_Scripting_RegisterFunctionFailed(); PSERROR_Scripting_RegisterFunctionFailed(const char* msg); PSRETURN getCode() const; };
+class PSERROR_Scripting_SetupFailed : public PSERROR_Scripting { public: PSERROR_Scripting_SetupFailed(); PSERROR_Scripting_SetupFailed(const char* msg); PSRETURN getCode() const; };
+class PSERROR_Scripting_TypeDoesNotExist : public PSERROR_Scripting { public: PSERROR_Scripting_TypeDoesNotExist(); PSERROR_Scripting_TypeDoesNotExist(const char* msg); PSRETURN getCode() const; };
+class PSERROR_Serialize_InvalidCharInString : public PSERROR_Serialize { public: PSERROR_Serialize_InvalidCharInString(); PSERROR_Serialize_InvalidCharInString(const char* msg); PSRETURN getCode() const; };
+class PSERROR_Serialize_InvalidScriptValue : public PSERROR_Serialize { public: PSERROR_Serialize_InvalidScriptValue(); PSERROR_Serialize_InvalidScriptValue(const char* msg); PSRETURN getCode() const; };
+class PSERROR_Serialize_OutOfBounds : public PSERROR_Serialize { public: PSERROR_Serialize_OutOfBounds(); PSERROR_Serialize_OutOfBounds(const char* msg); PSRETURN getCode() const; };
+class PSERROR_Serialize_ScriptError : public PSERROR_Serialize { public: PSERROR_Serialize_ScriptError(); PSERROR_Serialize_ScriptError(const char* msg); PSRETURN getCode() const; };
+class PSERROR_System_RequiredExtensionsMissing : public PSERROR_System { public: PSERROR_System_RequiredExtensionsMissing(); PSERROR_System_RequiredExtensionsMissing(const char* msg); PSRETURN getCode() const; };
+class PSERROR_System_SDLInitFailed : public PSERROR_System { public: PSERROR_System_SDLInitFailed(); PSERROR_System_SDLInitFailed(const char* msg); PSRETURN getCode() const; };
+class PSERROR_System_VmodeFailed : public PSERROR_System { public: PSERROR_System_VmodeFailed(); PSERROR_System_VmodeFailed(const char* msg); PSRETURN getCode() const; };
+class PSERROR_Xeromyces_XMLOpenFailed : public PSERROR_Xeromyces { public: PSERROR_Xeromyces_XMLOpenFailed(); PSERROR_Xeromyces_XMLOpenFailed(const char* msg); PSRETURN getCode() const; };
+class PSERROR_Xeromyces_XMLParseError : public PSERROR_Xeromyces { public: PSERROR_Xeromyces_XMLParseError(); PSERROR_Xeromyces_XMLParseError(const char* msg); PSRETURN getCode() const; };
extern const PSRETURN PSRETURN_CVFSFile_AlreadyLoaded = 0x01000001;
extern const PSRETURN PSRETURN_CVFSFile_InvalidBufferAccess = 0x01000002;
extern const PSRETURN PSRETURN_CVFSFile_LoadFailed = 0x01000003;
-extern const PSRETURN PSRETURN_DllLoader_DllNotLoaded = 0x02000001;
-extern const PSRETURN PSRETURN_DllLoader_SymbolNotFound = 0x02000002;
-extern const PSRETURN PSRETURN_Error_InvalidError = 0x03000001;
-extern const PSRETURN PSRETURN_File_InvalidType = 0x04000001;
-extern const PSRETURN PSRETURN_File_InvalidVersion = 0x04000002;
-extern const PSRETURN PSRETURN_File_OpenFailed = 0x04000003;
-extern const PSRETURN PSRETURN_File_ReadFailed = 0x04000004;
-extern const PSRETURN PSRETURN_File_UnexpectedEOF = 0x04000005;
-extern const PSRETURN PSRETURN_File_WriteFailed = 0x04000006;
-extern const PSRETURN PSRETURN_GUI_InvalidSetting = 0x05000001;
-extern const PSRETURN PSRETURN_GUI_JSOpenFailed = 0x05000002;
-extern const PSRETURN PSRETURN_GUI_NameAmbiguity = 0x05000003;
-extern const PSRETURN PSRETURN_GUI_NullObjectProvided = 0x05000004;
-extern const PSRETURN PSRETURN_GUI_ObjectNeedsName = 0x05000005;
-extern const PSRETURN PSRETURN_GUI_OperationNeedsGUIObject = 0x05000006;
-extern const PSRETURN PSRETURN_GUI_UnableToParse = 0x05000007;
-extern const PSRETURN PSRETURN_Game_World_MapLoadFailed = 0x06040001;
-extern const PSRETURN PSRETURN_I18n_Script_SetupFailed = 0x07030001;
-extern const PSRETURN PSRETURN_Renderer_VBOFailed = 0x08000001;
-extern const PSRETURN PSRETURN_Scripting_DefineType_AlreadyExists = 0x09010001;
-extern const PSRETURN PSRETURN_Scripting_DefineType_CreationFailed = 0x09010002;
-extern const PSRETURN PSRETURN_Scripting_LoadFile_EvalErrors = 0x09020001;
-extern const PSRETURN PSRETURN_Scripting_LoadFile_OpenFailed = 0x09020002;
-extern const PSRETURN PSRETURN_Scripting_CallFunctionFailed = 0x09000001;
-extern const PSRETURN PSRETURN_Scripting_ConversionFailed = 0x09000002;
-extern const PSRETURN PSRETURN_Scripting_CreateObjectFailed = 0x09000003;
-extern const PSRETURN PSRETURN_Scripting_DefineConstantFailed = 0x09000004;
-extern const PSRETURN PSRETURN_Scripting_RegisterFunctionFailed = 0x09000005;
-extern const PSRETURN PSRETURN_Scripting_SetupFailed = 0x09000006;
-extern const PSRETURN PSRETURN_Scripting_TypeDoesNotExist = 0x09000007;
-extern const PSRETURN PSRETURN_System_RequiredExtensionsMissing = 0x0a000001;
-extern const PSRETURN PSRETURN_System_SDLInitFailed = 0x0a000002;
-extern const PSRETURN PSRETURN_System_VmodeFailed = 0x0a000003;
-extern const PSRETURN PSRETURN_Xeromyces_XMLOpenFailed = 0x0b000001;
-extern const PSRETURN PSRETURN_Xeromyces_XMLParseError = 0x0b000002;
+extern const PSRETURN PSRETURN_Deserialize_InvalidCharInString = 0x02000001;
+extern const PSRETURN PSRETURN_Deserialize_OutOfBounds = 0x02000002;
+extern const PSRETURN PSRETURN_Deserialize_ReadFailed = 0x02000003;
+extern const PSRETURN PSRETURN_Deserialize_ScriptError = 0x02000004;
+extern const PSRETURN PSRETURN_DllLoader_DllNotLoaded = 0x03000001;
+extern const PSRETURN PSRETURN_DllLoader_SymbolNotFound = 0x03000002;
+extern const PSRETURN PSRETURN_Error_InvalidError = 0x04000001;
+extern const PSRETURN PSRETURN_File_InvalidType = 0x05000001;
+extern const PSRETURN PSRETURN_File_InvalidVersion = 0x05000002;
+extern const PSRETURN PSRETURN_File_OpenFailed = 0x05000003;
+extern const PSRETURN PSRETURN_File_ReadFailed = 0x05000004;
+extern const PSRETURN PSRETURN_File_UnexpectedEOF = 0x05000005;
+extern const PSRETURN PSRETURN_File_WriteFailed = 0x05000006;
+extern const PSRETURN PSRETURN_GUI_InvalidSetting = 0x06000001;
+extern const PSRETURN PSRETURN_GUI_JSOpenFailed = 0x06000002;
+extern const PSRETURN PSRETURN_GUI_NameAmbiguity = 0x06000003;
+extern const PSRETURN PSRETURN_GUI_NullObjectProvided = 0x06000004;
+extern const PSRETURN PSRETURN_GUI_ObjectNeedsName = 0x06000005;
+extern const PSRETURN PSRETURN_GUI_OperationNeedsGUIObject = 0x06000006;
+extern const PSRETURN PSRETURN_GUI_UnableToParse = 0x06000007;
+extern const PSRETURN PSRETURN_Game_World_MapLoadFailed = 0x07040001;
+extern const PSRETURN PSRETURN_I18n_Script_SetupFailed = 0x08030001;
+extern const PSRETURN PSRETURN_Renderer_VBOFailed = 0x09000001;
+extern const PSRETURN PSRETURN_Scripting_DefineType_AlreadyExists = 0x0a010001;
+extern const PSRETURN PSRETURN_Scripting_DefineType_CreationFailed = 0x0a010002;
+extern const PSRETURN PSRETURN_Scripting_LoadFile_EvalErrors = 0x0a020001;
+extern const PSRETURN PSRETURN_Scripting_LoadFile_OpenFailed = 0x0a020002;
+extern const PSRETURN PSRETURN_Scripting_CallFunctionFailed = 0x0a000001;
+extern const PSRETURN PSRETURN_Scripting_ConversionFailed = 0x0a000002;
+extern const PSRETURN PSRETURN_Scripting_CreateObjectFailed = 0x0a000003;
+extern const PSRETURN PSRETURN_Scripting_DefineConstantFailed = 0x0a000004;
+extern const PSRETURN PSRETURN_Scripting_RegisterFunctionFailed = 0x0a000005;
+extern const PSRETURN PSRETURN_Scripting_SetupFailed = 0x0a000006;
+extern const PSRETURN PSRETURN_Scripting_TypeDoesNotExist = 0x0a000007;
+extern const PSRETURN PSRETURN_Serialize_InvalidCharInString = 0x0b000001;
+extern const PSRETURN PSRETURN_Serialize_InvalidScriptValue = 0x0b000002;
+extern const PSRETURN PSRETURN_Serialize_OutOfBounds = 0x0b000003;
+extern const PSRETURN PSRETURN_Serialize_ScriptError = 0x0b000004;
+extern const PSRETURN PSRETURN_System_RequiredExtensionsMissing = 0x0c000001;
+extern const PSRETURN PSRETURN_System_SDLInitFailed = 0x0c000002;
+extern const PSRETURN PSRETURN_System_VmodeFailed = 0x0c000003;
+extern const PSRETURN PSRETURN_Xeromyces_XMLOpenFailed = 0x0d000001;
+extern const PSRETURN PSRETURN_Xeromyces_XMLParseError = 0x0d000002;
extern const PSRETURN MASK__PSRETURN_CVFSFile = 0xff000000;
extern const PSRETURN CODE__PSRETURN_CVFSFile = 0x01000000;
+extern const PSRETURN MASK__PSRETURN_Deserialize = 0xff000000;
+extern const PSRETURN CODE__PSRETURN_Deserialize = 0x02000000;
extern const PSRETURN MASK__PSRETURN_DllLoader = 0xff000000;
-extern const PSRETURN CODE__PSRETURN_DllLoader = 0x02000000;
+extern const PSRETURN CODE__PSRETURN_DllLoader = 0x03000000;
extern const PSRETURN MASK__PSRETURN_Error = 0xff000000;
-extern const PSRETURN CODE__PSRETURN_Error = 0x03000000;
+extern const PSRETURN CODE__PSRETURN_Error = 0x04000000;
extern const PSRETURN MASK__PSRETURN_File = 0xff000000;
-extern const PSRETURN CODE__PSRETURN_File = 0x04000000;
+extern const PSRETURN CODE__PSRETURN_File = 0x05000000;
extern const PSRETURN MASK__PSRETURN_GUI = 0xff000000;
-extern const PSRETURN CODE__PSRETURN_GUI = 0x05000000;
+extern const PSRETURN CODE__PSRETURN_GUI = 0x06000000;
extern const PSRETURN MASK__PSRETURN_Game = 0xff000000;
-extern const PSRETURN CODE__PSRETURN_Game = 0x06000000;
+extern const PSRETURN CODE__PSRETURN_Game = 0x07000000;
extern const PSRETURN MASK__PSRETURN_I18n = 0xff000000;
-extern const PSRETURN CODE__PSRETURN_I18n = 0x07000000;
+extern const PSRETURN CODE__PSRETURN_I18n = 0x08000000;
extern const PSRETURN MASK__PSRETURN_Renderer = 0xff000000;
-extern const PSRETURN CODE__PSRETURN_Renderer = 0x08000000;
-extern const PSRETURN MASK__PSRETURN_Scripting = 0xff000000;
-extern const PSRETURN CODE__PSRETURN_Scripting = 0x09000000;
-extern const PSRETURN MASK__PSRETURN_System = 0x0a000000;
-extern const PSRETURN CODE__PSRETURN_System = 0x0a000000;
-extern const PSRETURN MASK__PSRETURN_Xeromyces = 0x0b000000;
-extern const PSRETURN CODE__PSRETURN_Xeromyces = 0x0b000000;
+extern const PSRETURN CODE__PSRETURN_Renderer = 0x09000000;
+extern const PSRETURN MASK__PSRETURN_Scripting = 0x0a000000;
+extern const PSRETURN CODE__PSRETURN_Scripting = 0x0a000000;
+extern const PSRETURN MASK__PSRETURN_Serialize = 0x0b000000;
+extern const PSRETURN CODE__PSRETURN_Serialize = 0x0b000000;
+extern const PSRETURN MASK__PSRETURN_System = 0x0c000000;
+extern const PSRETURN CODE__PSRETURN_System = 0x0c000000;
+extern const PSRETURN MASK__PSRETURN_Xeromyces = 0x0d000000;
+extern const PSRETURN CODE__PSRETURN_Xeromyces = 0x0d000000;
extern const PSRETURN MASK__PSRETURN_Game_World = 0xffff0000;
-extern const PSRETURN CODE__PSRETURN_Game_World = 0x06040000;
+extern const PSRETURN CODE__PSRETURN_Game_World = 0x07040000;
extern const PSRETURN MASK__PSRETURN_I18n_Script = 0xffff0000;
-extern const PSRETURN CODE__PSRETURN_I18n_Script = 0x07030000;
-extern const PSRETURN MASK__PSRETURN_Scripting_DefineType = 0xffff0000;
-extern const PSRETURN CODE__PSRETURN_Scripting_DefineType = 0x09010000;
-extern const PSRETURN MASK__PSRETURN_Scripting_LoadFile = 0xffff0000;
-extern const PSRETURN CODE__PSRETURN_Scripting_LoadFile = 0x09020000;
+extern const PSRETURN CODE__PSRETURN_I18n_Script = 0x08030000;
+extern const PSRETURN MASK__PSRETURN_Scripting_DefineType = 0x0aff0000;
+extern const PSRETURN CODE__PSRETURN_Scripting_DefineType = 0x0a010000;
+extern const PSRETURN MASK__PSRETURN_Scripting_LoadFile = 0x0aff0000;
+extern const PSRETURN CODE__PSRETURN_Scripting_LoadFile = 0x0a020000;
extern const PSRETURN MASK__PSRETURN_CVFSFile_AlreadyLoaded = 0xffffffff;
extern const PSRETURN CODE__PSRETURN_CVFSFile_AlreadyLoaded = 0x01000001;
@@ -136,124 +158,301 @@ extern const PSRETURN MASK__PSRETURN_CVFSFile_InvalidBufferAccess = 0xffffffff;
extern const PSRETURN CODE__PSRETURN_CVFSFile_InvalidBufferAccess = 0x01000002;
extern const PSRETURN MASK__PSRETURN_CVFSFile_LoadFailed = 0xffffffff;
extern const PSRETURN CODE__PSRETURN_CVFSFile_LoadFailed = 0x01000003;
+extern const PSRETURN MASK__PSRETURN_Deserialize_InvalidCharInString = 0xffffffff;
+extern const PSRETURN CODE__PSRETURN_Deserialize_InvalidCharInString = 0x02000001;
+extern const PSRETURN MASK__PSRETURN_Deserialize_OutOfBounds = 0xffffffff;
+extern const PSRETURN CODE__PSRETURN_Deserialize_OutOfBounds = 0x02000002;
+extern const PSRETURN MASK__PSRETURN_Deserialize_ReadFailed = 0xffffffff;
+extern const PSRETURN CODE__PSRETURN_Deserialize_ReadFailed = 0x02000003;
+extern const PSRETURN MASK__PSRETURN_Deserialize_ScriptError = 0xffffffff;
+extern const PSRETURN CODE__PSRETURN_Deserialize_ScriptError = 0x02000004;
extern const PSRETURN MASK__PSRETURN_DllLoader_DllNotLoaded = 0xffffffff;
-extern const PSRETURN CODE__PSRETURN_DllLoader_DllNotLoaded = 0x02000001;
+extern const PSRETURN CODE__PSRETURN_DllLoader_DllNotLoaded = 0x03000001;
extern const PSRETURN MASK__PSRETURN_DllLoader_SymbolNotFound = 0xffffffff;
-extern const PSRETURN CODE__PSRETURN_DllLoader_SymbolNotFound = 0x02000002;
+extern const PSRETURN CODE__PSRETURN_DllLoader_SymbolNotFound = 0x03000002;
extern const PSRETURN MASK__PSRETURN_Error_InvalidError = 0xffffffff;
-extern const PSRETURN CODE__PSRETURN_Error_InvalidError = 0x03000001;
+extern const PSRETURN CODE__PSRETURN_Error_InvalidError = 0x04000001;
extern const PSRETURN MASK__PSRETURN_File_InvalidType = 0xffffffff;
-extern const PSRETURN CODE__PSRETURN_File_InvalidType = 0x04000001;
+extern const PSRETURN CODE__PSRETURN_File_InvalidType = 0x05000001;
extern const PSRETURN MASK__PSRETURN_File_InvalidVersion = 0xffffffff;
-extern const PSRETURN CODE__PSRETURN_File_InvalidVersion = 0x04000002;
+extern const PSRETURN CODE__PSRETURN_File_InvalidVersion = 0x05000002;
extern const PSRETURN MASK__PSRETURN_File_OpenFailed = 0xffffffff;
-extern const PSRETURN CODE__PSRETURN_File_OpenFailed = 0x04000003;
+extern const PSRETURN CODE__PSRETURN_File_OpenFailed = 0x05000003;
extern const PSRETURN MASK__PSRETURN_File_ReadFailed = 0xffffffff;
-extern const PSRETURN CODE__PSRETURN_File_ReadFailed = 0x04000004;
+extern const PSRETURN CODE__PSRETURN_File_ReadFailed = 0x05000004;
extern const PSRETURN MASK__PSRETURN_File_UnexpectedEOF = 0xffffffff;
-extern const PSRETURN CODE__PSRETURN_File_UnexpectedEOF = 0x04000005;
+extern const PSRETURN CODE__PSRETURN_File_UnexpectedEOF = 0x05000005;
extern const PSRETURN MASK__PSRETURN_File_WriteFailed = 0xffffffff;
-extern const PSRETURN CODE__PSRETURN_File_WriteFailed = 0x04000006;
+extern const PSRETURN CODE__PSRETURN_File_WriteFailed = 0x05000006;
extern const PSRETURN MASK__PSRETURN_GUI_InvalidSetting = 0xffffffff;
-extern const PSRETURN CODE__PSRETURN_GUI_InvalidSetting = 0x05000001;
+extern const PSRETURN CODE__PSRETURN_GUI_InvalidSetting = 0x06000001;
extern const PSRETURN MASK__PSRETURN_GUI_JSOpenFailed = 0xffffffff;
-extern const PSRETURN CODE__PSRETURN_GUI_JSOpenFailed = 0x05000002;
+extern const PSRETURN CODE__PSRETURN_GUI_JSOpenFailed = 0x06000002;
extern const PSRETURN MASK__PSRETURN_GUI_NameAmbiguity = 0xffffffff;
-extern const PSRETURN CODE__PSRETURN_GUI_NameAmbiguity = 0x05000003;
+extern const PSRETURN CODE__PSRETURN_GUI_NameAmbiguity = 0x06000003;
extern const PSRETURN MASK__PSRETURN_GUI_NullObjectProvided = 0xffffffff;
-extern const PSRETURN CODE__PSRETURN_GUI_NullObjectProvided = 0x05000004;
+extern const PSRETURN CODE__PSRETURN_GUI_NullObjectProvided = 0x06000004;
extern const PSRETURN MASK__PSRETURN_GUI_ObjectNeedsName = 0xffffffff;
-extern const PSRETURN CODE__PSRETURN_GUI_ObjectNeedsName = 0x05000005;
+extern const PSRETURN CODE__PSRETURN_GUI_ObjectNeedsName = 0x06000005;
extern const PSRETURN MASK__PSRETURN_GUI_OperationNeedsGUIObject = 0xffffffff;
-extern const PSRETURN CODE__PSRETURN_GUI_OperationNeedsGUIObject = 0x05000006;
+extern const PSRETURN CODE__PSRETURN_GUI_OperationNeedsGUIObject = 0x06000006;
extern const PSRETURN MASK__PSRETURN_GUI_UnableToParse = 0xffffffff;
-extern const PSRETURN CODE__PSRETURN_GUI_UnableToParse = 0x05000007;
+extern const PSRETURN CODE__PSRETURN_GUI_UnableToParse = 0x06000007;
extern const PSRETURN MASK__PSRETURN_Game_World_MapLoadFailed = 0xffffffff;
-extern const PSRETURN CODE__PSRETURN_Game_World_MapLoadFailed = 0x06040001;
+extern const PSRETURN CODE__PSRETURN_Game_World_MapLoadFailed = 0x07040001;
extern const PSRETURN MASK__PSRETURN_I18n_Script_SetupFailed = 0xffffffff;
-extern const PSRETURN CODE__PSRETURN_I18n_Script_SetupFailed = 0x07030001;
+extern const PSRETURN CODE__PSRETURN_I18n_Script_SetupFailed = 0x08030001;
extern const PSRETURN MASK__PSRETURN_Renderer_VBOFailed = 0xffffffff;
-extern const PSRETURN CODE__PSRETURN_Renderer_VBOFailed = 0x08000001;
+extern const PSRETURN CODE__PSRETURN_Renderer_VBOFailed = 0x09000001;
extern const PSRETURN MASK__PSRETURN_Scripting_DefineType_AlreadyExists = 0xffffffff;
-extern const PSRETURN CODE__PSRETURN_Scripting_DefineType_AlreadyExists = 0x09010001;
+extern const PSRETURN CODE__PSRETURN_Scripting_DefineType_AlreadyExists = 0x0a010001;
extern const PSRETURN MASK__PSRETURN_Scripting_DefineType_CreationFailed = 0xffffffff;
-extern const PSRETURN CODE__PSRETURN_Scripting_DefineType_CreationFailed = 0x09010002;
+extern const PSRETURN CODE__PSRETURN_Scripting_DefineType_CreationFailed = 0x0a010002;
extern const PSRETURN MASK__PSRETURN_Scripting_LoadFile_EvalErrors = 0xffffffff;
-extern const PSRETURN CODE__PSRETURN_Scripting_LoadFile_EvalErrors = 0x09020001;
+extern const PSRETURN CODE__PSRETURN_Scripting_LoadFile_EvalErrors = 0x0a020001;
extern const PSRETURN MASK__PSRETURN_Scripting_LoadFile_OpenFailed = 0xffffffff;
-extern const PSRETURN CODE__PSRETURN_Scripting_LoadFile_OpenFailed = 0x09020002;
+extern const PSRETURN CODE__PSRETURN_Scripting_LoadFile_OpenFailed = 0x0a020002;
extern const PSRETURN MASK__PSRETURN_Scripting_CallFunctionFailed = 0xffffffff;
-extern const PSRETURN CODE__PSRETURN_Scripting_CallFunctionFailed = 0x09000001;
+extern const PSRETURN CODE__PSRETURN_Scripting_CallFunctionFailed = 0x0a000001;
extern const PSRETURN MASK__PSRETURN_Scripting_ConversionFailed = 0xffffffff;
-extern const PSRETURN CODE__PSRETURN_Scripting_ConversionFailed = 0x09000002;
+extern const PSRETURN CODE__PSRETURN_Scripting_ConversionFailed = 0x0a000002;
extern const PSRETURN MASK__PSRETURN_Scripting_CreateObjectFailed = 0xffffffff;
-extern const PSRETURN CODE__PSRETURN_Scripting_CreateObjectFailed = 0x09000003;
+extern const PSRETURN CODE__PSRETURN_Scripting_CreateObjectFailed = 0x0a000003;
extern const PSRETURN MASK__PSRETURN_Scripting_DefineConstantFailed = 0xffffffff;
-extern const PSRETURN CODE__PSRETURN_Scripting_DefineConstantFailed = 0x09000004;
+extern const PSRETURN CODE__PSRETURN_Scripting_DefineConstantFailed = 0x0a000004;
extern const PSRETURN MASK__PSRETURN_Scripting_RegisterFunctionFailed = 0xffffffff;
-extern const PSRETURN CODE__PSRETURN_Scripting_RegisterFunctionFailed = 0x09000005;
+extern const PSRETURN CODE__PSRETURN_Scripting_RegisterFunctionFailed = 0x0a000005;
extern const PSRETURN MASK__PSRETURN_Scripting_SetupFailed = 0xffffffff;
-extern const PSRETURN CODE__PSRETURN_Scripting_SetupFailed = 0x09000006;
+extern const PSRETURN CODE__PSRETURN_Scripting_SetupFailed = 0x0a000006;
extern const PSRETURN MASK__PSRETURN_Scripting_TypeDoesNotExist = 0xffffffff;
-extern const PSRETURN CODE__PSRETURN_Scripting_TypeDoesNotExist = 0x09000007;
+extern const PSRETURN CODE__PSRETURN_Scripting_TypeDoesNotExist = 0x0a000007;
+extern const PSRETURN MASK__PSRETURN_Serialize_InvalidCharInString = 0xffffffff;
+extern const PSRETURN CODE__PSRETURN_Serialize_InvalidCharInString = 0x0b000001;
+extern const PSRETURN MASK__PSRETURN_Serialize_InvalidScriptValue = 0xffffffff;
+extern const PSRETURN CODE__PSRETURN_Serialize_InvalidScriptValue = 0x0b000002;
+extern const PSRETURN MASK__PSRETURN_Serialize_OutOfBounds = 0xffffffff;
+extern const PSRETURN CODE__PSRETURN_Serialize_OutOfBounds = 0x0b000003;
+extern const PSRETURN MASK__PSRETURN_Serialize_ScriptError = 0xffffffff;
+extern const PSRETURN CODE__PSRETURN_Serialize_ScriptError = 0x0b000004;
extern const PSRETURN MASK__PSRETURN_System_RequiredExtensionsMissing = 0xffffffff;
-extern const PSRETURN CODE__PSRETURN_System_RequiredExtensionsMissing = 0x0a000001;
+extern const PSRETURN CODE__PSRETURN_System_RequiredExtensionsMissing = 0x0c000001;
extern const PSRETURN MASK__PSRETURN_System_SDLInitFailed = 0xffffffff;
-extern const PSRETURN CODE__PSRETURN_System_SDLInitFailed = 0x0a000002;
+extern const PSRETURN CODE__PSRETURN_System_SDLInitFailed = 0x0c000002;
extern const PSRETURN MASK__PSRETURN_System_VmodeFailed = 0xffffffff;
-extern const PSRETURN CODE__PSRETURN_System_VmodeFailed = 0x0a000003;
+extern const PSRETURN CODE__PSRETURN_System_VmodeFailed = 0x0c000003;
extern const PSRETURN MASK__PSRETURN_Xeromyces_XMLOpenFailed = 0xffffffff;
-extern const PSRETURN CODE__PSRETURN_Xeromyces_XMLOpenFailed = 0x0b000001;
+extern const PSRETURN CODE__PSRETURN_Xeromyces_XMLOpenFailed = 0x0d000001;
extern const PSRETURN MASK__PSRETURN_Xeromyces_XMLParseError = 0xffffffff;
-extern const PSRETURN CODE__PSRETURN_Xeromyces_XMLParseError = 0x0b000002;
+extern const PSRETURN CODE__PSRETURN_Xeromyces_XMLParseError = 0x0d000002;
+PSERROR_CVFSFile::PSERROR_CVFSFile(const char* msg) : PSERROR(msg) { }
+PSERROR_Deserialize::PSERROR_Deserialize(const char* msg) : PSERROR(msg) { }
+PSERROR_DllLoader::PSERROR_DllLoader(const char* msg) : PSERROR(msg) { }
+PSERROR_Error::PSERROR_Error(const char* msg) : PSERROR(msg) { }
+PSERROR_File::PSERROR_File(const char* msg) : PSERROR(msg) { }
+PSERROR_GUI::PSERROR_GUI(const char* msg) : PSERROR(msg) { }
+PSERROR_Game::PSERROR_Game(const char* msg) : PSERROR(msg) { }
+PSERROR_I18n::PSERROR_I18n(const char* msg) : PSERROR(msg) { }
+PSERROR_Renderer::PSERROR_Renderer(const char* msg) : PSERROR(msg) { }
+PSERROR_Scripting::PSERROR_Scripting(const char* msg) : PSERROR(msg) { }
+PSERROR_Serialize::PSERROR_Serialize(const char* msg) : PSERROR(msg) { }
+PSERROR_System::PSERROR_System(const char* msg) : PSERROR(msg) { }
+PSERROR_Xeromyces::PSERROR_Xeromyces(const char* msg) : PSERROR(msg) { }
+PSERROR_Game_World::PSERROR_Game_World(const char* msg) : PSERROR_Game(msg) { }
+PSERROR_I18n_Script::PSERROR_I18n_Script(const char* msg) : PSERROR_I18n(msg) { }
+PSERROR_Scripting_DefineType::PSERROR_Scripting_DefineType(const char* msg) : PSERROR_Scripting(msg) { }
+PSERROR_Scripting_LoadFile::PSERROR_Scripting_LoadFile(const char* msg) : PSERROR_Scripting(msg) { }
+
+PSERROR_CVFSFile_AlreadyLoaded::PSERROR_CVFSFile_AlreadyLoaded() : PSERROR_CVFSFile(NULL) { }
+PSERROR_CVFSFile_AlreadyLoaded::PSERROR_CVFSFile_AlreadyLoaded(const char* msg) : PSERROR_CVFSFile(msg) { }
PSRETURN PSERROR_CVFSFile_AlreadyLoaded::getCode() const { return 0x01000001; }
+
+PSERROR_CVFSFile_InvalidBufferAccess::PSERROR_CVFSFile_InvalidBufferAccess() : PSERROR_CVFSFile(NULL) { }
+PSERROR_CVFSFile_InvalidBufferAccess::PSERROR_CVFSFile_InvalidBufferAccess(const char* msg) : PSERROR_CVFSFile(msg) { }
PSRETURN PSERROR_CVFSFile_InvalidBufferAccess::getCode() const { return 0x01000002; }
+
+PSERROR_CVFSFile_LoadFailed::PSERROR_CVFSFile_LoadFailed() : PSERROR_CVFSFile(NULL) { }
+PSERROR_CVFSFile_LoadFailed::PSERROR_CVFSFile_LoadFailed(const char* msg) : PSERROR_CVFSFile(msg) { }
PSRETURN PSERROR_CVFSFile_LoadFailed::getCode() const { return 0x01000003; }
-PSRETURN PSERROR_DllLoader_DllNotLoaded::getCode() const { return 0x02000001; }
-PSRETURN PSERROR_DllLoader_SymbolNotFound::getCode() const { return 0x02000002; }
-PSRETURN PSERROR_Error_InvalidError::getCode() const { return 0x03000001; }
-PSRETURN PSERROR_File_InvalidType::getCode() const { return 0x04000001; }
-PSRETURN PSERROR_File_InvalidVersion::getCode() const { return 0x04000002; }
-PSRETURN PSERROR_File_OpenFailed::getCode() const { return 0x04000003; }
-PSRETURN PSERROR_File_ReadFailed::getCode() const { return 0x04000004; }
-PSRETURN PSERROR_File_UnexpectedEOF::getCode() const { return 0x04000005; }
-PSRETURN PSERROR_File_WriteFailed::getCode() const { return 0x04000006; }
-PSRETURN PSERROR_GUI_InvalidSetting::getCode() const { return 0x05000001; }
-PSRETURN PSERROR_GUI_JSOpenFailed::getCode() const { return 0x05000002; }
-PSRETURN PSERROR_GUI_NameAmbiguity::getCode() const { return 0x05000003; }
-PSRETURN PSERROR_GUI_NullObjectProvided::getCode() const { return 0x05000004; }
-PSRETURN PSERROR_GUI_ObjectNeedsName::getCode() const { return 0x05000005; }
-PSRETURN PSERROR_GUI_OperationNeedsGUIObject::getCode() const { return 0x05000006; }
-PSRETURN PSERROR_GUI_UnableToParse::getCode() const { return 0x05000007; }
-PSRETURN PSERROR_Game_World_MapLoadFailed::getCode() const { return 0x06040001; }
-PSRETURN PSERROR_I18n_Script_SetupFailed::getCode() const { return 0x07030001; }
-PSRETURN PSERROR_Renderer_VBOFailed::getCode() const { return 0x08000001; }
-PSRETURN PSERROR_Scripting_DefineType_AlreadyExists::getCode() const { return 0x09010001; }
-PSRETURN PSERROR_Scripting_DefineType_CreationFailed::getCode() const { return 0x09010002; }
-PSRETURN PSERROR_Scripting_LoadFile_EvalErrors::getCode() const { return 0x09020001; }
-PSRETURN PSERROR_Scripting_LoadFile_OpenFailed::getCode() const { return 0x09020002; }
-PSRETURN PSERROR_Scripting_CallFunctionFailed::getCode() const { return 0x09000001; }
-PSRETURN PSERROR_Scripting_ConversionFailed::getCode() const { return 0x09000002; }
-PSRETURN PSERROR_Scripting_CreateObjectFailed::getCode() const { return 0x09000003; }
-PSRETURN PSERROR_Scripting_DefineConstantFailed::getCode() const { return 0x09000004; }
-PSRETURN PSERROR_Scripting_RegisterFunctionFailed::getCode() const { return 0x09000005; }
-PSRETURN PSERROR_Scripting_SetupFailed::getCode() const { return 0x09000006; }
-PSRETURN PSERROR_Scripting_TypeDoesNotExist::getCode() const { return 0x09000007; }
-PSRETURN PSERROR_System_RequiredExtensionsMissing::getCode() const { return 0x0a000001; }
-PSRETURN PSERROR_System_SDLInitFailed::getCode() const { return 0x0a000002; }
-PSRETURN PSERROR_System_VmodeFailed::getCode() const { return 0x0a000003; }
-PSRETURN PSERROR_Xeromyces_XMLOpenFailed::getCode() const { return 0x0b000001; }
-PSRETURN PSERROR_Xeromyces_XMLParseError::getCode() const { return 0x0b000002; }
+
+PSERROR_Deserialize_InvalidCharInString::PSERROR_Deserialize_InvalidCharInString() : PSERROR_Deserialize(NULL) { }
+PSERROR_Deserialize_InvalidCharInString::PSERROR_Deserialize_InvalidCharInString(const char* msg) : PSERROR_Deserialize(msg) { }
+PSRETURN PSERROR_Deserialize_InvalidCharInString::getCode() const { return 0x02000001; }
+
+PSERROR_Deserialize_OutOfBounds::PSERROR_Deserialize_OutOfBounds() : PSERROR_Deserialize(NULL) { }
+PSERROR_Deserialize_OutOfBounds::PSERROR_Deserialize_OutOfBounds(const char* msg) : PSERROR_Deserialize(msg) { }
+PSRETURN PSERROR_Deserialize_OutOfBounds::getCode() const { return 0x02000002; }
+
+PSERROR_Deserialize_ReadFailed::PSERROR_Deserialize_ReadFailed() : PSERROR_Deserialize(NULL) { }
+PSERROR_Deserialize_ReadFailed::PSERROR_Deserialize_ReadFailed(const char* msg) : PSERROR_Deserialize(msg) { }
+PSRETURN PSERROR_Deserialize_ReadFailed::getCode() const { return 0x02000003; }
+
+PSERROR_Deserialize_ScriptError::PSERROR_Deserialize_ScriptError() : PSERROR_Deserialize(NULL) { }
+PSERROR_Deserialize_ScriptError::PSERROR_Deserialize_ScriptError(const char* msg) : PSERROR_Deserialize(msg) { }
+PSRETURN PSERROR_Deserialize_ScriptError::getCode() const { return 0x02000004; }
+
+PSERROR_DllLoader_DllNotLoaded::PSERROR_DllLoader_DllNotLoaded() : PSERROR_DllLoader(NULL) { }
+PSERROR_DllLoader_DllNotLoaded::PSERROR_DllLoader_DllNotLoaded(const char* msg) : PSERROR_DllLoader(msg) { }
+PSRETURN PSERROR_DllLoader_DllNotLoaded::getCode() const { return 0x03000001; }
+
+PSERROR_DllLoader_SymbolNotFound::PSERROR_DllLoader_SymbolNotFound() : PSERROR_DllLoader(NULL) { }
+PSERROR_DllLoader_SymbolNotFound::PSERROR_DllLoader_SymbolNotFound(const char* msg) : PSERROR_DllLoader(msg) { }
+PSRETURN PSERROR_DllLoader_SymbolNotFound::getCode() const { return 0x03000002; }
+
+PSERROR_Error_InvalidError::PSERROR_Error_InvalidError() : PSERROR_Error(NULL) { }
+PSERROR_Error_InvalidError::PSERROR_Error_InvalidError(const char* msg) : PSERROR_Error(msg) { }
+PSRETURN PSERROR_Error_InvalidError::getCode() const { return 0x04000001; }
+
+PSERROR_File_InvalidType::PSERROR_File_InvalidType() : PSERROR_File(NULL) { }
+PSERROR_File_InvalidType::PSERROR_File_InvalidType(const char* msg) : PSERROR_File(msg) { }
+PSRETURN PSERROR_File_InvalidType::getCode() const { return 0x05000001; }
+
+PSERROR_File_InvalidVersion::PSERROR_File_InvalidVersion() : PSERROR_File(NULL) { }
+PSERROR_File_InvalidVersion::PSERROR_File_InvalidVersion(const char* msg) : PSERROR_File(msg) { }
+PSRETURN PSERROR_File_InvalidVersion::getCode() const { return 0x05000002; }
+
+PSERROR_File_OpenFailed::PSERROR_File_OpenFailed() : PSERROR_File(NULL) { }
+PSERROR_File_OpenFailed::PSERROR_File_OpenFailed(const char* msg) : PSERROR_File(msg) { }
+PSRETURN PSERROR_File_OpenFailed::getCode() const { return 0x05000003; }
+
+PSERROR_File_ReadFailed::PSERROR_File_ReadFailed() : PSERROR_File(NULL) { }
+PSERROR_File_ReadFailed::PSERROR_File_ReadFailed(const char* msg) : PSERROR_File(msg) { }
+PSRETURN PSERROR_File_ReadFailed::getCode() const { return 0x05000004; }
+
+PSERROR_File_UnexpectedEOF::PSERROR_File_UnexpectedEOF() : PSERROR_File(NULL) { }
+PSERROR_File_UnexpectedEOF::PSERROR_File_UnexpectedEOF(const char* msg) : PSERROR_File(msg) { }
+PSRETURN PSERROR_File_UnexpectedEOF::getCode() const { return 0x05000005; }
+
+PSERROR_File_WriteFailed::PSERROR_File_WriteFailed() : PSERROR_File(NULL) { }
+PSERROR_File_WriteFailed::PSERROR_File_WriteFailed(const char* msg) : PSERROR_File(msg) { }
+PSRETURN PSERROR_File_WriteFailed::getCode() const { return 0x05000006; }
+
+PSERROR_GUI_InvalidSetting::PSERROR_GUI_InvalidSetting() : PSERROR_GUI(NULL) { }
+PSERROR_GUI_InvalidSetting::PSERROR_GUI_InvalidSetting(const char* msg) : PSERROR_GUI(msg) { }
+PSRETURN PSERROR_GUI_InvalidSetting::getCode() const { return 0x06000001; }
+
+PSERROR_GUI_JSOpenFailed::PSERROR_GUI_JSOpenFailed() : PSERROR_GUI(NULL) { }
+PSERROR_GUI_JSOpenFailed::PSERROR_GUI_JSOpenFailed(const char* msg) : PSERROR_GUI(msg) { }
+PSRETURN PSERROR_GUI_JSOpenFailed::getCode() const { return 0x06000002; }
+
+PSERROR_GUI_NameAmbiguity::PSERROR_GUI_NameAmbiguity() : PSERROR_GUI(NULL) { }
+PSERROR_GUI_NameAmbiguity::PSERROR_GUI_NameAmbiguity(const char* msg) : PSERROR_GUI(msg) { }
+PSRETURN PSERROR_GUI_NameAmbiguity::getCode() const { return 0x06000003; }
+
+PSERROR_GUI_NullObjectProvided::PSERROR_GUI_NullObjectProvided() : PSERROR_GUI(NULL) { }
+PSERROR_GUI_NullObjectProvided::PSERROR_GUI_NullObjectProvided(const char* msg) : PSERROR_GUI(msg) { }
+PSRETURN PSERROR_GUI_NullObjectProvided::getCode() const { return 0x06000004; }
+
+PSERROR_GUI_ObjectNeedsName::PSERROR_GUI_ObjectNeedsName() : PSERROR_GUI(NULL) { }
+PSERROR_GUI_ObjectNeedsName::PSERROR_GUI_ObjectNeedsName(const char* msg) : PSERROR_GUI(msg) { }
+PSRETURN PSERROR_GUI_ObjectNeedsName::getCode() const { return 0x06000005; }
+
+PSERROR_GUI_OperationNeedsGUIObject::PSERROR_GUI_OperationNeedsGUIObject() : PSERROR_GUI(NULL) { }
+PSERROR_GUI_OperationNeedsGUIObject::PSERROR_GUI_OperationNeedsGUIObject(const char* msg) : PSERROR_GUI(msg) { }
+PSRETURN PSERROR_GUI_OperationNeedsGUIObject::getCode() const { return 0x06000006; }
+
+PSERROR_GUI_UnableToParse::PSERROR_GUI_UnableToParse() : PSERROR_GUI(NULL) { }
+PSERROR_GUI_UnableToParse::PSERROR_GUI_UnableToParse(const char* msg) : PSERROR_GUI(msg) { }
+PSRETURN PSERROR_GUI_UnableToParse::getCode() const { return 0x06000007; }
+
+PSERROR_Game_World_MapLoadFailed::PSERROR_Game_World_MapLoadFailed() : PSERROR_Game_World(NULL) { }
+PSERROR_Game_World_MapLoadFailed::PSERROR_Game_World_MapLoadFailed(const char* msg) : PSERROR_Game_World(msg) { }
+PSRETURN PSERROR_Game_World_MapLoadFailed::getCode() const { return 0x07040001; }
+
+PSERROR_I18n_Script_SetupFailed::PSERROR_I18n_Script_SetupFailed() : PSERROR_I18n_Script(NULL) { }
+PSERROR_I18n_Script_SetupFailed::PSERROR_I18n_Script_SetupFailed(const char* msg) : PSERROR_I18n_Script(msg) { }
+PSRETURN PSERROR_I18n_Script_SetupFailed::getCode() const { return 0x08030001; }
+
+PSERROR_Renderer_VBOFailed::PSERROR_Renderer_VBOFailed() : PSERROR_Renderer(NULL) { }
+PSERROR_Renderer_VBOFailed::PSERROR_Renderer_VBOFailed(const char* msg) : PSERROR_Renderer(msg) { }
+PSRETURN PSERROR_Renderer_VBOFailed::getCode() const { return 0x09000001; }
+
+PSERROR_Scripting_DefineType_AlreadyExists::PSERROR_Scripting_DefineType_AlreadyExists() : PSERROR_Scripting_DefineType(NULL) { }
+PSERROR_Scripting_DefineType_AlreadyExists::PSERROR_Scripting_DefineType_AlreadyExists(const char* msg) : PSERROR_Scripting_DefineType(msg) { }
+PSRETURN PSERROR_Scripting_DefineType_AlreadyExists::getCode() const { return 0x0a010001; }
+
+PSERROR_Scripting_DefineType_CreationFailed::PSERROR_Scripting_DefineType_CreationFailed() : PSERROR_Scripting_DefineType(NULL) { }
+PSERROR_Scripting_DefineType_CreationFailed::PSERROR_Scripting_DefineType_CreationFailed(const char* msg) : PSERROR_Scripting_DefineType(msg) { }
+PSRETURN PSERROR_Scripting_DefineType_CreationFailed::getCode() const { return 0x0a010002; }
+
+PSERROR_Scripting_LoadFile_EvalErrors::PSERROR_Scripting_LoadFile_EvalErrors() : PSERROR_Scripting_LoadFile(NULL) { }
+PSERROR_Scripting_LoadFile_EvalErrors::PSERROR_Scripting_LoadFile_EvalErrors(const char* msg) : PSERROR_Scripting_LoadFile(msg) { }
+PSRETURN PSERROR_Scripting_LoadFile_EvalErrors::getCode() const { return 0x0a020001; }
+
+PSERROR_Scripting_LoadFile_OpenFailed::PSERROR_Scripting_LoadFile_OpenFailed() : PSERROR_Scripting_LoadFile(NULL) { }
+PSERROR_Scripting_LoadFile_OpenFailed::PSERROR_Scripting_LoadFile_OpenFailed(const char* msg) : PSERROR_Scripting_LoadFile(msg) { }
+PSRETURN PSERROR_Scripting_LoadFile_OpenFailed::getCode() const { return 0x0a020002; }
+
+PSERROR_Scripting_CallFunctionFailed::PSERROR_Scripting_CallFunctionFailed() : PSERROR_Scripting(NULL) { }
+PSERROR_Scripting_CallFunctionFailed::PSERROR_Scripting_CallFunctionFailed(const char* msg) : PSERROR_Scripting(msg) { }
+PSRETURN PSERROR_Scripting_CallFunctionFailed::getCode() const { return 0x0a000001; }
+
+PSERROR_Scripting_ConversionFailed::PSERROR_Scripting_ConversionFailed() : PSERROR_Scripting(NULL) { }
+PSERROR_Scripting_ConversionFailed::PSERROR_Scripting_ConversionFailed(const char* msg) : PSERROR_Scripting(msg) { }
+PSRETURN PSERROR_Scripting_ConversionFailed::getCode() const { return 0x0a000002; }
+
+PSERROR_Scripting_CreateObjectFailed::PSERROR_Scripting_CreateObjectFailed() : PSERROR_Scripting(NULL) { }
+PSERROR_Scripting_CreateObjectFailed::PSERROR_Scripting_CreateObjectFailed(const char* msg) : PSERROR_Scripting(msg) { }
+PSRETURN PSERROR_Scripting_CreateObjectFailed::getCode() const { return 0x0a000003; }
+
+PSERROR_Scripting_DefineConstantFailed::PSERROR_Scripting_DefineConstantFailed() : PSERROR_Scripting(NULL) { }
+PSERROR_Scripting_DefineConstantFailed::PSERROR_Scripting_DefineConstantFailed(const char* msg) : PSERROR_Scripting(msg) { }
+PSRETURN PSERROR_Scripting_DefineConstantFailed::getCode() const { return 0x0a000004; }
+
+PSERROR_Scripting_RegisterFunctionFailed::PSERROR_Scripting_RegisterFunctionFailed() : PSERROR_Scripting(NULL) { }
+PSERROR_Scripting_RegisterFunctionFailed::PSERROR_Scripting_RegisterFunctionFailed(const char* msg) : PSERROR_Scripting(msg) { }
+PSRETURN PSERROR_Scripting_RegisterFunctionFailed::getCode() const { return 0x0a000005; }
+
+PSERROR_Scripting_SetupFailed::PSERROR_Scripting_SetupFailed() : PSERROR_Scripting(NULL) { }
+PSERROR_Scripting_SetupFailed::PSERROR_Scripting_SetupFailed(const char* msg) : PSERROR_Scripting(msg) { }
+PSRETURN PSERROR_Scripting_SetupFailed::getCode() const { return 0x0a000006; }
+
+PSERROR_Scripting_TypeDoesNotExist::PSERROR_Scripting_TypeDoesNotExist() : PSERROR_Scripting(NULL) { }
+PSERROR_Scripting_TypeDoesNotExist::PSERROR_Scripting_TypeDoesNotExist(const char* msg) : PSERROR_Scripting(msg) { }
+PSRETURN PSERROR_Scripting_TypeDoesNotExist::getCode() const { return 0x0a000007; }
+
+PSERROR_Serialize_InvalidCharInString::PSERROR_Serialize_InvalidCharInString() : PSERROR_Serialize(NULL) { }
+PSERROR_Serialize_InvalidCharInString::PSERROR_Serialize_InvalidCharInString(const char* msg) : PSERROR_Serialize(msg) { }
+PSRETURN PSERROR_Serialize_InvalidCharInString::getCode() const { return 0x0b000001; }
+
+PSERROR_Serialize_InvalidScriptValue::PSERROR_Serialize_InvalidScriptValue() : PSERROR_Serialize(NULL) { }
+PSERROR_Serialize_InvalidScriptValue::PSERROR_Serialize_InvalidScriptValue(const char* msg) : PSERROR_Serialize(msg) { }
+PSRETURN PSERROR_Serialize_InvalidScriptValue::getCode() const { return 0x0b000002; }
+
+PSERROR_Serialize_OutOfBounds::PSERROR_Serialize_OutOfBounds() : PSERROR_Serialize(NULL) { }
+PSERROR_Serialize_OutOfBounds::PSERROR_Serialize_OutOfBounds(const char* msg) : PSERROR_Serialize(msg) { }
+PSRETURN PSERROR_Serialize_OutOfBounds::getCode() const { return 0x0b000003; }
+
+PSERROR_Serialize_ScriptError::PSERROR_Serialize_ScriptError() : PSERROR_Serialize(NULL) { }
+PSERROR_Serialize_ScriptError::PSERROR_Serialize_ScriptError(const char* msg) : PSERROR_Serialize(msg) { }
+PSRETURN PSERROR_Serialize_ScriptError::getCode() const { return 0x0b000004; }
+
+PSERROR_System_RequiredExtensionsMissing::PSERROR_System_RequiredExtensionsMissing() : PSERROR_System(NULL) { }
+PSERROR_System_RequiredExtensionsMissing::PSERROR_System_RequiredExtensionsMissing(const char* msg) : PSERROR_System(msg) { }
+PSRETURN PSERROR_System_RequiredExtensionsMissing::getCode() const { return 0x0c000001; }
+
+PSERROR_System_SDLInitFailed::PSERROR_System_SDLInitFailed() : PSERROR_System(NULL) { }
+PSERROR_System_SDLInitFailed::PSERROR_System_SDLInitFailed(const char* msg) : PSERROR_System(msg) { }
+PSRETURN PSERROR_System_SDLInitFailed::getCode() const { return 0x0c000002; }
+
+PSERROR_System_VmodeFailed::PSERROR_System_VmodeFailed() : PSERROR_System(NULL) { }
+PSERROR_System_VmodeFailed::PSERROR_System_VmodeFailed(const char* msg) : PSERROR_System(msg) { }
+PSRETURN PSERROR_System_VmodeFailed::getCode() const { return 0x0c000003; }
+
+PSERROR_Xeromyces_XMLOpenFailed::PSERROR_Xeromyces_XMLOpenFailed() : PSERROR_Xeromyces(NULL) { }
+PSERROR_Xeromyces_XMLOpenFailed::PSERROR_Xeromyces_XMLOpenFailed(const char* msg) : PSERROR_Xeromyces(msg) { }
+PSRETURN PSERROR_Xeromyces_XMLOpenFailed::getCode() const { return 0x0d000001; }
+
+PSERROR_Xeromyces_XMLParseError::PSERROR_Xeromyces_XMLParseError() : PSERROR_Xeromyces(NULL) { }
+PSERROR_Xeromyces_XMLParseError::PSERROR_Xeromyces_XMLParseError(const char* msg) : PSERROR_Xeromyces(msg) { }
+PSRETURN PSERROR_Xeromyces_XMLParseError::getCode() const { return 0x0d000002; }
+
+
+PSERROR::PSERROR(const char* msg) : m_msg(msg) { }
const char* PSERROR::what() const throw ()
{
- return GetErrorString(getCode());
-}
-
-const char* GetErrorString(const PSERROR& err)
-{
- return GetErrorString(err.getCode());
+ return m_msg ? m_msg : GetErrorString(getCode());
}
const char* GetErrorString(PSRETURN code)
@@ -263,41 +462,49 @@ const char* GetErrorString(PSRETURN code)
case 0x01000001: return "CVFSFile_AlreadyLoaded";
case 0x01000002: return "CVFSFile_InvalidBufferAccess";
case 0x01000003: return "CVFSFile_LoadFailed";
- case 0x02000001: return "DllLoader_DllNotLoaded";
- case 0x02000002: return "DllLoader_SymbolNotFound";
- case 0x03000001: return "Error_InvalidError";
- case 0x04000001: return "File_InvalidType";
- case 0x04000002: return "File_InvalidVersion";
- case 0x04000003: return "File_OpenFailed";
- case 0x04000004: return "File_ReadFailed";
- case 0x04000005: return "File_UnexpectedEOF";
- case 0x04000006: return "File_WriteFailed";
- case 0x05000001: return "GUI_InvalidSetting";
- case 0x05000002: return "GUI_JSOpenFailed";
- case 0x05000003: return "GUI_NameAmbiguity";
- case 0x05000004: return "GUI_NullObjectProvided";
- case 0x05000005: return "GUI_ObjectNeedsName";
- case 0x05000006: return "GUI_OperationNeedsGUIObject";
- case 0x05000007: return "GUI_UnableToParse";
- case 0x06040001: return "Game_World_MapLoadFailed";
- case 0x07030001: return "I18n_Script_SetupFailed";
- case 0x08000001: return "Renderer_VBOFailed";
- case 0x09010001: return "Scripting_DefineType_AlreadyExists";
- case 0x09010002: return "Scripting_DefineType_CreationFailed";
- case 0x09020001: return "Scripting_LoadFile_EvalErrors";
- case 0x09020002: return "Scripting_LoadFile_OpenFailed";
- case 0x09000001: return "Scripting_CallFunctionFailed";
- case 0x09000002: return "Scripting_ConversionFailed";
- case 0x09000003: return "Scripting_CreateObjectFailed";
- case 0x09000004: return "Scripting_DefineConstantFailed";
- case 0x09000005: return "Scripting_RegisterFunctionFailed";
- case 0x09000006: return "Scripting_SetupFailed";
- case 0x09000007: return "Scripting_TypeDoesNotExist";
- case 0x0a000001: return "System_RequiredExtensionsMissing";
- case 0x0a000002: return "System_SDLInitFailed";
- case 0x0a000003: return "System_VmodeFailed";
- case 0x0b000001: return "Xeromyces_XMLOpenFailed";
- case 0x0b000002: return "Xeromyces_XMLParseError";
+ case 0x02000001: return "Deserialize_InvalidCharInString";
+ case 0x02000002: return "Deserialize_OutOfBounds";
+ case 0x02000003: return "Deserialize_ReadFailed";
+ case 0x02000004: return "Deserialize_ScriptError";
+ case 0x03000001: return "DllLoader_DllNotLoaded";
+ case 0x03000002: return "DllLoader_SymbolNotFound";
+ case 0x04000001: return "Error_InvalidError";
+ case 0x05000001: return "File_InvalidType";
+ case 0x05000002: return "File_InvalidVersion";
+ case 0x05000003: return "File_OpenFailed";
+ case 0x05000004: return "File_ReadFailed";
+ case 0x05000005: return "File_UnexpectedEOF";
+ case 0x05000006: return "File_WriteFailed";
+ case 0x06000001: return "GUI_InvalidSetting";
+ case 0x06000002: return "GUI_JSOpenFailed";
+ case 0x06000003: return "GUI_NameAmbiguity";
+ case 0x06000004: return "GUI_NullObjectProvided";
+ case 0x06000005: return "GUI_ObjectNeedsName";
+ case 0x06000006: return "GUI_OperationNeedsGUIObject";
+ case 0x06000007: return "GUI_UnableToParse";
+ case 0x07040001: return "Game_World_MapLoadFailed";
+ case 0x08030001: return "I18n_Script_SetupFailed";
+ case 0x09000001: return "Renderer_VBOFailed";
+ case 0x0a010001: return "Scripting_DefineType_AlreadyExists";
+ case 0x0a010002: return "Scripting_DefineType_CreationFailed";
+ case 0x0a020001: return "Scripting_LoadFile_EvalErrors";
+ case 0x0a020002: return "Scripting_LoadFile_OpenFailed";
+ case 0x0a000001: return "Scripting_CallFunctionFailed";
+ case 0x0a000002: return "Scripting_ConversionFailed";
+ case 0x0a000003: return "Scripting_CreateObjectFailed";
+ case 0x0a000004: return "Scripting_DefineConstantFailed";
+ case 0x0a000005: return "Scripting_RegisterFunctionFailed";
+ case 0x0a000006: return "Scripting_SetupFailed";
+ case 0x0a000007: return "Scripting_TypeDoesNotExist";
+ case 0x0b000001: return "Serialize_InvalidCharInString";
+ case 0x0b000002: return "Serialize_InvalidScriptValue";
+ case 0x0b000003: return "Serialize_OutOfBounds";
+ case 0x0b000004: return "Serialize_ScriptError";
+ case 0x0c000001: return "System_RequiredExtensionsMissing";
+ case 0x0c000002: return "System_SDLInitFailed";
+ case 0x0c000003: return "System_VmodeFailed";
+ case 0x0d000001: return "Xeromyces_XMLOpenFailed";
+ case 0x0d000002: return "Xeromyces_XMLParseError";
default: return "Unrecognised error";
}
@@ -310,41 +517,49 @@ void ThrowError(PSRETURN code)
case 0x01000001: throw PSERROR_CVFSFile_AlreadyLoaded(); break;
case 0x01000002: throw PSERROR_CVFSFile_InvalidBufferAccess(); break;
case 0x01000003: throw PSERROR_CVFSFile_LoadFailed(); break;
- case 0x02000001: throw PSERROR_DllLoader_DllNotLoaded(); break;
- case 0x02000002: throw PSERROR_DllLoader_SymbolNotFound(); break;
- case 0x03000001: throw PSERROR_Error_InvalidError(); break;
- case 0x04000001: throw PSERROR_File_InvalidType(); break;
- case 0x04000002: throw PSERROR_File_InvalidVersion(); break;
- case 0x04000003: throw PSERROR_File_OpenFailed(); break;
- case 0x04000004: throw PSERROR_File_ReadFailed(); break;
- case 0x04000005: throw PSERROR_File_UnexpectedEOF(); break;
- case 0x04000006: throw PSERROR_File_WriteFailed(); break;
- case 0x05000001: throw PSERROR_GUI_InvalidSetting(); break;
- case 0x05000002: throw PSERROR_GUI_JSOpenFailed(); break;
- case 0x05000003: throw PSERROR_GUI_NameAmbiguity(); break;
- case 0x05000004: throw PSERROR_GUI_NullObjectProvided(); break;
- case 0x05000005: throw PSERROR_GUI_ObjectNeedsName(); break;
- case 0x05000006: throw PSERROR_GUI_OperationNeedsGUIObject(); break;
- case 0x05000007: throw PSERROR_GUI_UnableToParse(); break;
- case 0x06040001: throw PSERROR_Game_World_MapLoadFailed(); break;
- case 0x07030001: throw PSERROR_I18n_Script_SetupFailed(); break;
- case 0x08000001: throw PSERROR_Renderer_VBOFailed(); break;
- case 0x09010001: throw PSERROR_Scripting_DefineType_AlreadyExists(); break;
- case 0x09010002: throw PSERROR_Scripting_DefineType_CreationFailed(); break;
- case 0x09020001: throw PSERROR_Scripting_LoadFile_EvalErrors(); break;
- case 0x09020002: throw PSERROR_Scripting_LoadFile_OpenFailed(); break;
- case 0x09000001: throw PSERROR_Scripting_CallFunctionFailed(); break;
- case 0x09000002: throw PSERROR_Scripting_ConversionFailed(); break;
- case 0x09000003: throw PSERROR_Scripting_CreateObjectFailed(); break;
- case 0x09000004: throw PSERROR_Scripting_DefineConstantFailed(); break;
- case 0x09000005: throw PSERROR_Scripting_RegisterFunctionFailed(); break;
- case 0x09000006: throw PSERROR_Scripting_SetupFailed(); break;
- case 0x09000007: throw PSERROR_Scripting_TypeDoesNotExist(); break;
- case 0x0a000001: throw PSERROR_System_RequiredExtensionsMissing(); break;
- case 0x0a000002: throw PSERROR_System_SDLInitFailed(); break;
- case 0x0a000003: throw PSERROR_System_VmodeFailed(); break;
- case 0x0b000001: throw PSERROR_Xeromyces_XMLOpenFailed(); break;
- case 0x0b000002: throw PSERROR_Xeromyces_XMLParseError(); break;
+ case 0x02000001: throw PSERROR_Deserialize_InvalidCharInString(); break;
+ case 0x02000002: throw PSERROR_Deserialize_OutOfBounds(); break;
+ case 0x02000003: throw PSERROR_Deserialize_ReadFailed(); break;
+ case 0x02000004: throw PSERROR_Deserialize_ScriptError(); break;
+ case 0x03000001: throw PSERROR_DllLoader_DllNotLoaded(); break;
+ case 0x03000002: throw PSERROR_DllLoader_SymbolNotFound(); break;
+ case 0x04000001: throw PSERROR_Error_InvalidError(); break;
+ case 0x05000001: throw PSERROR_File_InvalidType(); break;
+ case 0x05000002: throw PSERROR_File_InvalidVersion(); break;
+ case 0x05000003: throw PSERROR_File_OpenFailed(); break;
+ case 0x05000004: throw PSERROR_File_ReadFailed(); break;
+ case 0x05000005: throw PSERROR_File_UnexpectedEOF(); break;
+ case 0x05000006: throw PSERROR_File_WriteFailed(); break;
+ case 0x06000001: throw PSERROR_GUI_InvalidSetting(); break;
+ case 0x06000002: throw PSERROR_GUI_JSOpenFailed(); break;
+ case 0x06000003: throw PSERROR_GUI_NameAmbiguity(); break;
+ case 0x06000004: throw PSERROR_GUI_NullObjectProvided(); break;
+ case 0x06000005: throw PSERROR_GUI_ObjectNeedsName(); break;
+ case 0x06000006: throw PSERROR_GUI_OperationNeedsGUIObject(); break;
+ case 0x06000007: throw PSERROR_GUI_UnableToParse(); break;
+ case 0x07040001: throw PSERROR_Game_World_MapLoadFailed(); break;
+ case 0x08030001: throw PSERROR_I18n_Script_SetupFailed(); break;
+ case 0x09000001: throw PSERROR_Renderer_VBOFailed(); break;
+ case 0x0a010001: throw PSERROR_Scripting_DefineType_AlreadyExists(); break;
+ case 0x0a010002: throw PSERROR_Scripting_DefineType_CreationFailed(); break;
+ case 0x0a020001: throw PSERROR_Scripting_LoadFile_EvalErrors(); break;
+ case 0x0a020002: throw PSERROR_Scripting_LoadFile_OpenFailed(); break;
+ case 0x0a000001: throw PSERROR_Scripting_CallFunctionFailed(); break;
+ case 0x0a000002: throw PSERROR_Scripting_ConversionFailed(); break;
+ case 0x0a000003: throw PSERROR_Scripting_CreateObjectFailed(); break;
+ case 0x0a000004: throw PSERROR_Scripting_DefineConstantFailed(); break;
+ case 0x0a000005: throw PSERROR_Scripting_RegisterFunctionFailed(); break;
+ case 0x0a000006: throw PSERROR_Scripting_SetupFailed(); break;
+ case 0x0a000007: throw PSERROR_Scripting_TypeDoesNotExist(); break;
+ case 0x0b000001: throw PSERROR_Serialize_InvalidCharInString(); break;
+ case 0x0b000002: throw PSERROR_Serialize_InvalidScriptValue(); break;
+ case 0x0b000003: throw PSERROR_Serialize_OutOfBounds(); break;
+ case 0x0b000004: throw PSERROR_Serialize_ScriptError(); break;
+ case 0x0c000001: throw PSERROR_System_RequiredExtensionsMissing(); break;
+ case 0x0c000002: throw PSERROR_System_SDLInitFailed(); break;
+ case 0x0c000003: throw PSERROR_System_VmodeFailed(); break;
+ case 0x0d000001: throw PSERROR_Xeromyces_XMLOpenFailed(); break;
+ case 0x0d000002: throw PSERROR_Xeromyces_XMLParseError(); break;
default: throw PSERROR_Error_InvalidError(); // Hmm...
}
diff --git a/source/ps/Errors.h b/source/ps/Errors.h
index 13d3fbe223..2292c2db64 100644
--- a/source/ps/Errors.h
+++ b/source/ps/Errors.h
@@ -18,6 +18,58 @@
#ifndef INCLUDED_ERRORS
#define INCLUDED_ERRORS
+/*
+
+The overly-complex error system works as follows:
+
+A source file (typically a .h) can declare errors as follows:
+
+ ERROR_GROUP(ModuleName);
+ ERROR_TYPE(ModuleName, FrobnificationFailed);
+ ERROR_SUBGROUP(ModuleName, ComponentName);
+ ERROR_TYPE(ModuleName_ComponentName, FileNotFound);
+
+etc, to build up a hierarchy of error types.
+
+Then you have to run the /build/errorlist/errorlist.pl script, to regenerate
+the Errors.cpp file.
+
+Then you can use the declared errors as an error code:
+
+ PSRETURN foo() { return PSRETURN_ModuleName_FrobnificationFailed; }
+
+ if (ret != PSRETURN_OK)
+ ... // something failed
+
+ if (ret)
+ ... // something failed
+
+ if (ret == PSRETURN_ModuleName_FrobnificationFailed)
+ ... // particular error
+
+ if (ERROR_IS(ret, PSRETURN_ModuleName))
+ ... // matches any type PSRETURN_ModuleName_* (and PSRETURN_ModuleName_*_* etc)
+
+And you can use it as an exception:
+
+ void foo() { throw PSERROR_ModuleName_FrobnificationFailed(); }
+
+ void bar() { throw PSERROR_ModuleName_FrobnificationFailed("More informative message"); }
+
+ try {
+ foo();
+ } catch (PSERROR_ModuleName_FrobnificationFailed e) {
+ // catches that particular error type
+ } catch (PSERROR_ModuleName e) {
+ // catches anything in the hierarchy
+ } catch (PSERROR e) {
+ std::cout << e.what();
+ }
+
+plus a few extra things for converting between error codes and exceptions.
+
+*/
+
#include
typedef u32 PSRETURN;
@@ -25,20 +77,23 @@ typedef u32 PSRETURN;
class PSERROR : public std::exception
{
public:
+ PSERROR(const char* msg);
virtual const char* what() const throw ();
virtual PSRETURN getCode() const = 0; // for functions that catch exceptions then return error codes
+private:
+ const char* m_msg;
};
-#define ERROR_GROUP(a) class PSERROR_##a : public PSERROR {}; \
+#define ERROR_GROUP(a) class PSERROR_##a : public PSERROR { protected: PSERROR_##a(const char* msg); }; \
extern const PSRETURN MASK__PSRETURN_##a; \
extern const PSRETURN CODE__PSRETURN_##a
-#define ERROR_SUBGROUP(a,b) class PSERROR_##a##_##b : public PSERROR_##a {}; \
+#define ERROR_SUBGROUP(a,b) class PSERROR_##a##_##b : public PSERROR_##a { protected: PSERROR_##a##_##b(const char* msg); }; \
extern const PSRETURN MASK__PSRETURN_##a##_##b; \
extern const PSRETURN CODE__PSRETURN_##a##_##b
-#define ERROR_TYPE(a,b) class PSERROR_##a##_##b : public PSERROR_##a { public: PSRETURN getCode() const; }; \
+#define ERROR_TYPE(a,b) class PSERROR_##a##_##b : public PSERROR_##a { public: PSERROR_##a##_##b(); PSERROR_##a##_##b(const char* msg); PSRETURN getCode() const; }; \
extern const PSRETURN MASK__PSRETURN_##a##_##b; \
extern const PSRETURN CODE__PSRETURN_##a##_##b; \
extern const PSRETURN PSRETURN_##a##_##b
@@ -50,7 +105,6 @@ const PSRETURN MASK__PSRETURN_OK = 0xFFFFFFFF;
const PSRETURN CODE__PSRETURN_OK = 0;
const char* GetErrorString(PSRETURN code);
-const char* GetErrorString(const PSERROR& err);
void ThrowError(PSRETURN code);
#endif
diff --git a/source/ps/Filesystem.cpp b/source/ps/Filesystem.cpp
index d3ad1fa086..e24003808f 100644
--- a/source/ps/Filesystem.cpp
+++ b/source/ps/Filesystem.cpp
@@ -20,8 +20,9 @@
#include "gui/GUIManager.h"
#include "ps/CLogger.h"
+#include "ps/Game.h"
+#include "simulation2/Simulation2.h"
-#include "lib/posix/posix_time.h" // usleep
#include "lib/res/h_mgr.h" // h_reload
#include "lib/sysdep/dir_watch.h"
@@ -69,6 +70,8 @@ LibError ReloadChangedFiles()
RETURN_ERR(g_VFS->GetVirtualPath(notifications[i].Pathname(), pathname));
RETURN_ERR(g_VFS->Invalidate(pathname));
RETURN_ERR(g_GUI->ReloadChangedFiles(pathname));
+ if (g_Game && g_Game->GetSimulation2())
+ RETURN_ERR(g_Game->GetSimulation2()->ReloadChangedFile(pathname));
RETURN_ERR(h_reload(pathname));
}
}
diff --git a/source/ps/Game.cpp b/source/ps/Game.cpp
index ce595d7d6d..ed2fb66078 100644
--- a/source/ps/Game.cpp
+++ b/source/ps/Game.cpp
@@ -39,6 +39,7 @@
#include "simulation/Entity.h"
#include "simulation/EntityManager.h"
#include "simulation/Simulation.h"
+#include "simulation2/Simulation2.h"
#include "gui/GUIManager.h"
@@ -70,6 +71,7 @@ CGame *g_Game=NULL;
CGame::CGame():
m_World(new CWorld(this)),
m_Simulation(new CSimulation(this)),
+ m_Simulation2(g_UseSimulation2 ? new CSimulation2(&m_World->GetUnitManager(), m_World->GetTerrain()) : NULL),
m_GameView(new CGameView(this)),
m_pLocalPlayer(NULL),
m_GameStarted(false),
@@ -79,6 +81,13 @@ CGame::CGame():
// Need to set the CObjectManager references after various objects have
// been initialised, so do it here rather than via the initialisers above.
m_World->GetUnitManager().SetObjectManager(m_GameView->GetObjectManager());
+
+ if (g_UseSimulation2)
+ {
+ m_Simulation2->LoadScripts(L"simulation/helpers/");
+ m_Simulation2->LoadScripts(L"simulation/components/");
+ m_Simulation2->ResetState();
+ }
}
#if MSC_VERSION
@@ -95,6 +104,7 @@ CGame::~CGame()
g_Profiler.StructuralReset();
delete m_GameView;
+ delete m_Simulation2;
delete m_Simulation;
delete m_World;
}
@@ -227,9 +237,17 @@ bool CGame::Update(double deltaTime, bool doInterpolate)
deltaTime *= m_SimRate;
bool ok = m_Simulation->Update(deltaTime);
+ if (g_UseSimulation2)
+ m_Simulation2->Update(deltaTime);
if (doInterpolate)
+ {
m_Simulation->Interpolate(deltaTime);
+ if (g_UseSimulation2)
+ m_Simulation2->Interpolate(deltaTime);
+ }
+ g_GUI->SendEventToAll("SimulationUpdate");
+
// TODO Detect game over and bring up the summary screen or something
// ^ Quick game over hack is implemented, no summary screen however
/*if (m_World->GetEntityManager().GetDeath())
diff --git a/source/ps/Game.h b/source/ps/Game.h
index 41a07bf244..7ec00848d1 100644
--- a/source/ps/Game.h
+++ b/source/ps/Game.h
@@ -29,6 +29,7 @@
class CWorld;
class CSimulation;
+class CSimulation2;
class CGameView;
class CSimulation;
class CPlayer;
@@ -57,6 +58,10 @@ class CGame
* pointer to the CSimulation object operating on the game world.
**/
CSimulation *m_Simulation;
+ /**
+ * pointer to the CSimulation2 object operating on the game world.
+ **/
+ CSimulation2 *m_Simulation2;
/**
* pointer to the CGameView object representing the view into the game world.
**/
@@ -186,6 +191,13 @@ public:
**/
inline CSimulation *GetSimulation()
{ return m_Simulation; }
+ /**
+ * Get the pointer to the simulation2 object.
+ *
+ * @return CSimulation2 * the value of m_Simulation2.
+ **/
+ inline CSimulation2 *GetSimulation2()
+ { return m_Simulation2; }
/**
* Set the simulation scale multiplier.
diff --git a/source/ps/GameSetup/GameSetup.cpp b/source/ps/GameSetup/GameSetup.cpp
index ac6af8b428..949e828555 100644
--- a/source/ps/GameSetup/GameSetup.cpp
+++ b/source/ps/GameSetup/GameSetup.cpp
@@ -65,22 +65,31 @@
#include "simulation/EntityManager.h"
#include "simulation/Scheduler.h"
+#include "simulation2/Simulation2.h"
+
#include "scripting/ScriptableComplex.inl"
#include "scripting/ScriptingHost.h"
#include "scripting/DOMEvent.h"
#include "scripting/GameEvents.h"
#include "scripting/ScriptableComplex.h"
+
#include "maths/scripting/JSInterface_Vector3D.h"
+
#include "graphics/scripting/JSInterface_Camera.h"
#include "graphics/scripting/JSInterface_LightEnv.h"
+
#include "ps/scripting/JSInterface_Selection.h"
#include "ps/scripting/JSInterface_Console.h"
#include "ps/scripting/JSCollection.h"
+
#include "simulation/scripting/SimulationScriptInit.h"
-#include "gui/scripting/JSInterface_IGUIObject.h"
-#include "gui/scripting/JSInterface_GUITypes.h"
+
#include "gui/GUI.h"
#include "gui/GUIManager.h"
+#include "gui/scripting/JSInterface_IGUIObject.h"
+#include "gui/scripting/JSInterface_GUITypes.h"
+#include "gui/scripting/ScriptFunctions.h"
+
#include "sound/JSI_Sound.h"
#include "network/NetLog.h"
@@ -447,6 +456,8 @@ static void RegisterJavascriptInterfaces()
// GUI
CGUI::ScriptingInit();
+
+ GuiScriptingInit(g_ScriptingHost.GetScriptInterface());
}
@@ -859,7 +870,7 @@ void Init(const CmdLineArgs& args, int flags)
const bool setup_gui = ((flags & INIT_NO_GUI) == 0 && g_AutostartMap.empty());
// GUI is notified in SetVideoMode, so this must come before that.
- g_GUI = new CGUIManager();
+ g_GUI = new CGUIManager(g_ScriptingHost.GetScriptInterface());
// default to windowed, so users don't get stuck if e.g. half the
// filesystem is missing and the config files aren't loaded
diff --git a/source/ps/Hotkey.cpp b/source/ps/Hotkey.cpp
index 4647b4a5c3..fff7713a4c 100644
--- a/source/ps/Hotkey.cpp
+++ b/source/ps/Hotkey.cpp
@@ -631,8 +631,14 @@ InReaction HotkeyInputHandler( const SDL_Event_* ev )
return( IN_PASS );
}
+CStr HotkeyGetName(int hotkey)
+{
+ if (hotkey < 0 || hotkey >= HOTKEY_LAST)
+ return "";
+ return hotkeyInfo[hotkey].name;
+}
-bool HotkeyRespondsTo( int hotkey, int sdlkey )
+bool HotkeyRespondsTo(int hotkey, int sdlkey)
{
for (KeyMapping::iterator it = hotkeyMap[sdlkey].begin(); it != hotkeyMap[sdlkey].end(); ++it)
if (it->mapsTo == hotkey)
@@ -641,7 +647,7 @@ bool HotkeyRespondsTo( int hotkey, int sdlkey )
}
-bool HotkeyIsPressed( const CStr& keyname )
+bool HotkeyIsPressed(const CStr& keyname)
{
return hotkeys[FindKeyCode(keyname)];
}
diff --git a/source/ps/Hotkey.h b/source/ps/Hotkey.h
index 57f73cdd35..41b245cf4d 100644
--- a/source/ps/Hotkey.h
+++ b/source/ps/Hotkey.h
@@ -134,19 +134,24 @@ enum
};
extern void LoadHotkeys();
-extern InReaction HotkeyInputHandler( const SDL_Event_* ev );
-extern void HotkeyRegisterGuiObject( const CStr& objName, const CStr& hotkeyName );
+extern InReaction HotkeyInputHandler(const SDL_Event_* ev);
+extern void HotkeyRegisterGuiObject(const CStr& objName, const CStr& hotkeyName);
+
+/**
+ * @return the name of the specified HOTKEY_*, or empty string if not defined
+ **/
+extern CStr HotkeyGetName(int hotkey);
/**
* @return whether the specified HOTKEY_* responds to the specified SDLK_*
* (mainly for the screenshot system to know whether it needs to override
* the printscreen screen). Ignores modifier keys.
**/
-extern bool HotkeyRespondsTo( int hotkey, int sdlkey );
+extern bool HotkeyRespondsTo(int hotkey, int sdlkey);
/**
* @return whether one of the key combinations for the given hotkey is pressed
**/
-extern bool HotkeyIsPressed( const CStr& keyname );
+extern bool HotkeyIsPressed(const CStr& keyname);
extern bool hotkeys[HOTKEY_LAST];
diff --git a/source/ps/Util.cpp b/source/ps/Util.cpp
index 343523c02b..117d91e0fb 100644
--- a/source/ps/Util.cpp
+++ b/source/ps/Util.cpp
@@ -25,6 +25,7 @@
#include "lib/allocators/shared_ptr.h"
#include "lib/sysdep/gfx.h"
#include "lib/sysdep/snd.h"
+#include "lib/sysdep/cpu.h"
#include "lib/sysdep/os_cpu.h"
#include "lib/sysdep/arch/x86_x64/topology.h"
#include "lib/tex/tex.h"
diff --git a/source/ps/XML/XMLWriter.cpp b/source/ps/XML/XMLWriter.cpp
index d0ad006e71..7fcab8f983 100644
--- a/source/ps/XML/XMLWriter.cpp
+++ b/source/ps/XML/XMLWriter.cpp
@@ -21,6 +21,8 @@
#include "ps/CLogger.h"
#include "ps/Filesystem.h"
+#include "lib/wchar.h"
+#include "lib/sysdep/cpu.h"
#define LOG_CATEGORY L"xml"
@@ -260,3 +262,7 @@ template <> void XMLWriter_File::ElementAttribute(const char* name, const
{
ElementAttribute(name, value.ToUTF8(), newelement);
}
+template <> void XMLWriter_File::ElementAttribute(const char* name, const std::wstring& value, bool newelement)
+{
+ ElementAttribute(name, utf8_from_wstring(value).c_str(), newelement);
+}
diff --git a/source/ps/XML/Xeromyces.cpp b/source/ps/XML/Xeromyces.cpp
index b13962dbee..4edae51564 100644
--- a/source/ps/XML/Xeromyces.cpp
+++ b/source/ps/XML/Xeromyces.cpp
@@ -198,6 +198,30 @@ bool CXeromyces::ReadXMBFile(const VfsPath& filename)
return true;
}
+PSRETURN CXeromyces::LoadString(const char* xml)
+{
+ debug_assert(g_XeromycesStarted);
+
+ xmlDocPtr doc = xmlReadMemory(xml, strlen(xml), "", NULL, XML_PARSE_NONET|XML_PARSE_NOCDATA);
+ if (! doc)
+ {
+ LOG(CLogger::Error, LOG_CATEGORY, L"CXeromyces: Failed to parse XML string");
+ return PSRETURN_Xeromyces_XMLParseError;
+ }
+
+ WriteBuffer writeBuffer;
+ CreateXMB(doc, writeBuffer);
+
+ xmlFreeDoc(doc);
+
+ m_XMBBuffer = writeBuffer.Data(); // add a reference
+
+ // Set up the XMBFile
+ const bool ok = Initialise((const char*)m_XMBBuffer.get());
+ debug_assert(ok);
+
+ return PSRETURN_OK;
+}
static void FindNames(const xmlNodePtr node, std::set& elementNames, std::set& attributeNames)
diff --git a/source/ps/XML/Xeromyces.h b/source/ps/XML/Xeromyces.h
index f486307b7f..c221330780 100644
--- a/source/ps/XML/Xeromyces.h
+++ b/source/ps/XML/Xeromyces.h
@@ -47,6 +47,9 @@ public:
// Load from an XML file (with invisible XMB caching).
PSRETURN Load(const VfsPath& filename);
+ // Load from an in-memory XML string (with no caching)
+ PSRETURN LoadString(const char* xml);
+
// Call once when initialising the program, to load libxml2.
// This should be run in the main thread, before any thread
// uses libxml2.
diff --git a/source/ps/XML/tests/test_Xeromyces.h b/source/ps/XML/tests/test_Xeromyces.h
index c10bd7f139..2f1747a4ba 100644
--- a/source/ps/XML/tests/test_Xeromyces.h
+++ b/source/ps/XML/tests/test_Xeromyces.h
@@ -17,21 +17,23 @@
#include "lib/self_test.h"
+#include "ps/CLogger.h"
#include "ps/XML/Xeromyces.h"
#include "lib/file/vfs/vfs.h"
-#include "lib/sysdep/sysdep.h"
-
-// FIXME: copied from test_MeshManager
-static fs::wpath DataDir()
-{
- fs::wpath path;
- TS_ASSERT_OK(sys_get_executable_name(path));
- return path.branch_path()/L"../data";
-}
class TestXeromyces : public CxxTest::TestSuite
{
public:
+ void setUp()
+ {
+ CXeromyces::Startup();
+ }
+
+ void tearDown()
+ {
+ CXeromyces::Terminate();
+ }
+
void test_paths()
{
PIVFS vfs = CreateVfs(20*MiB);
@@ -49,4 +51,18 @@ public:
// TODO: Should test the reading/parsing/writing code,
// and parse error handling
+
+ void test_LoadString()
+ {
+ CXeromyces xero;
+ TS_ASSERT_EQUALS(xero.LoadString("bar"), PSRETURN_OK);
+ TS_ASSERT_STR_EQUALS(xero.GetElementString(xero.GetRoot().GetNodeName()), "test");
+ }
+
+ void test_LoadString_invalid()
+ {
+ TestLogger logger;
+ CXeromyces xero;
+ TS_ASSERT_EQUALS(xero.LoadString(""), PSRETURN_Xeromyces_XMLParseError);
+ }
};
diff --git a/source/ps/utf16string.h b/source/ps/utf16string.h
index 20063d9801..f5f06d55a9 100644
--- a/source/ps/utf16string.h
+++ b/source/ps/utf16string.h
@@ -26,8 +26,8 @@
// We now use this code on Windows as well, because wchar_t is a
// native type and distinct from utf16_t.
#include
-
-#include "lib/sysdep/cpu.h" // cpu_memcpy
+#include
+#include
typedef uint16_t utf16_t;
@@ -78,7 +78,7 @@ struct utf16_traits
static char_type* copy(char_type* s1, const char_type* s2, size_t n)
{
- return (char_type *)cpu_memcpy(s1, s2, n*sizeof(char_type));
+ return (char_type *)memcpy(s1, s2, n*sizeof(char_type));
}
static char_type* assign(char_type* s, size_t n, char_type a)
diff --git a/source/renderer/OverlayRenderer.cpp b/source/renderer/OverlayRenderer.cpp
new file mode 100644
index 0000000000..6e4ccab2bc
--- /dev/null
+++ b/source/renderer/OverlayRenderer.cpp
@@ -0,0 +1,80 @@
+/* Copyright (C) 2009 Wildfire Games.
+ * This file is part of 0 A.D.
+ *
+ * 0 A.D. is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * 0 A.D. is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with 0 A.D. If not, see .
+ */
+
+#include "precompiled.h"
+
+#include "OverlayRenderer.h"
+
+#include "graphics/Overlay.h"
+#include "lib/ogl.h"
+#include "renderer/Renderer.h"
+
+struct OverlayRendererInternals
+{
+ std::vector lines;
+};
+
+OverlayRenderer::OverlayRenderer()
+{
+ m = new OverlayRendererInternals();
+}
+
+OverlayRenderer::~OverlayRenderer()
+{
+ delete m;
+}
+
+void OverlayRenderer::Submit(SOverlayLine* overlay)
+{
+ m->lines.push_back(overlay);
+}
+
+void OverlayRenderer::EndFrame()
+{
+ m->lines.clear();
+ // this should leave the capacity unchanged, which is okay since it
+ // won't be very large or very variable
+}
+
+void OverlayRenderer::PrepareForRendering()
+{
+ // This is where we should do something like sort the overlays by
+ // colour/sprite/etc for more efficient rendering
+}
+
+void OverlayRenderer::RenderOverlays()
+{
+ // Unbind any vertex buffer object, if our card supports VBO's
+ if (g_Renderer.GetCapabilities().m_VBO)
+ {
+ pglBindBufferARB(GL_ARRAY_BUFFER_ARB, 0);
+ }
+
+ for (size_t i = 0; i < m->lines.size(); ++i)
+ {
+ SOverlayLine* line = m->lines[i];
+ if (line->m_Coords.empty())
+ continue;
+
+ debug_assert(line->m_Coords.size() % 3 == 0);
+
+ glColor4fv(line->m_Color.FloatArray());
+
+ glInterleavedArrays(GL_V3F, sizeof(float)*3, &line->m_Coords[0]);
+ glDrawArrays(GL_LINE_STRIP, 0, line->m_Coords.size()/3);
+ }
+}
diff --git a/source/renderer/OverlayRenderer.h b/source/renderer/OverlayRenderer.h
new file mode 100644
index 0000000000..67852bf8ec
--- /dev/null
+++ b/source/renderer/OverlayRenderer.h
@@ -0,0 +1,61 @@
+/* Copyright (C) 2009 Wildfire Games.
+ * This file is part of 0 A.D.
+ *
+ * 0 A.D. is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * 0 A.D. is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with 0 A.D. If not, see .
+ */
+
+#ifndef INCLUDED_OVERLAYRENDERER
+#define INCLUDED_OVERLAYRENDERER
+
+struct SOverlayLine;
+
+struct OverlayRendererInternals;
+
+/**
+ * Class OverlayRenderer: Render various bits of data that overlay the
+ * game world (selection circles, health bars, etc).
+ */
+class OverlayRenderer
+{
+public:
+ OverlayRenderer();
+ ~OverlayRenderer();
+
+ /**
+ * Add a line overlay for rendering in this frame.
+ */
+ void Submit(SOverlayLine* overlay);
+
+ /**
+ * Prepare internal data structures for rendering.
+ * Must be called after all Submit calls for a frame, and before
+ * any rendering calls.
+ */
+ void PrepareForRendering();
+
+ /**
+ * Reset the list of submitted overlays.
+ */
+ void EndFrame();
+
+ /**
+ * Render all the submitted overlays.
+ */
+ void RenderOverlays();
+
+private:
+ OverlayRendererInternals* m;
+};
+
+#endif // INCLUDED_OVERLAYRENDERER
diff --git a/source/renderer/Renderer.cpp b/source/renderer/Renderer.cpp
index e95db4cbc1..e7a8ec1fd1 100644
--- a/source/renderer/Renderer.cpp
+++ b/source/renderer/Renderer.cpp
@@ -55,15 +55,16 @@
#include "renderer/HWLightingModelRenderer.h"
#include "renderer/InstancingModelRenderer.h"
#include "renderer/ModelRenderer.h"
+#include "renderer/OverlayRenderer.h"
#include "renderer/PlayerRenderer.h"
#include "renderer/RenderModifiers.h"
#include "renderer/RenderPathVertexShader.h"
#include "renderer/ShadowMap.h"
+#include "renderer/SkyManager.h"
#include "renderer/TerrainOverlay.h"
#include "renderer/TerrainRenderer.h"
#include "renderer/TransparencyRenderer.h"
#include "renderer/WaterManager.h"
-#include "renderer/SkyManager.h"
#define LOG_CATEGORY L"graphics"
@@ -220,6 +221,9 @@ public:
/// Terrain renderer
TerrainRenderer* terrainRenderer;
+ /// Overlay renderer
+ OverlayRenderer overlayRenderer;
+
/// Shadow map
ShadowMap* shadow;
@@ -1211,6 +1215,10 @@ void CRenderer::RenderSubmissions()
m->terrainRenderer->PrepareForRendering();
PROFILE_END("prepare terrain");
+ PROFILE_START("prepare overlays");
+ m->overlayRenderer.PrepareForRendering();
+ PROFILE_END("prepare overlays");
+
if (m_Options.m_Shadows)
{
MICROLOG(L"render shadows");
@@ -1292,7 +1300,12 @@ void CRenderer::RenderSubmissions()
// (really this should be cleaned up by whoever set it)
glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE);
- //// Particle Engine Rendering.
+ PROFILE_START("render overlays");
+ m->overlayRenderer.RenderOverlays();
+ PROFILE_END("render overlays");
+ ogl_WarnIfError();
+
+ // Particle Engine Rendering.
MICROLOG(L"render particles");
CParticleEngine::GetInstance()->RenderParticles();
ogl_WarnIfError();
@@ -1309,6 +1322,7 @@ void CRenderer::RenderSubmissions()
// empty lists
MICROLOG(L"empty lists");
m->terrainRenderer->EndFrame();
+ m->overlayRenderer.EndFrame();
// Finish model renderers
m->Model.Normal->EndFrame();
@@ -1381,6 +1395,11 @@ void CRenderer::Submit(CPatch* patch)
m->terrainRenderer->Submit(patch);
}
+void CRenderer::Submit(SOverlayLine* overlay)
+{
+ m->overlayRenderer.Submit(overlay);
+}
+
void CRenderer::SubmitNonRecursive(CModel* model)
{
if (model->GetFlags() & MODELFLAG_CASTSHADOWS) {
diff --git a/source/renderer/Renderer.h b/source/renderer/Renderer.h
index b1cd1ffac1..c1a8d6b7fe 100644
--- a/source/renderer/Renderer.h
+++ b/source/renderer/Renderer.h
@@ -341,6 +341,7 @@ protected:
//BEGIN: Implementation of SceneCollector
void Submit(CPatch* patch);
+ void Submit(SOverlayLine* overlay);
void SubmitNonRecursive(CModel* model);
//END: Implementation of SceneCollector
diff --git a/source/renderer/Scene.h b/source/renderer/Scene.h
index 6c97b71cd5..7804ed8bbb 100644
--- a/source/renderer/Scene.h
+++ b/source/renderer/Scene.h
@@ -31,6 +31,7 @@
class CFrustum;
class CModel;
class CPatch;
+struct SOverlayLine;
class SceneCollector;
@@ -64,6 +65,11 @@ public:
*/
virtual void Submit(CPatch* patch) = 0;
+ /**
+ * Submit a line-based overlay that is part of the scene.
+ */
+ virtual void Submit(SOverlayLine* overlay) = 0;
+
/**
* Submit a model that is part of the scene,
* without submitting attached models.
diff --git a/source/renderer/VertexBuffer.cpp b/source/renderer/VertexBuffer.cpp
index 021ae9f3e9..6f0b538aa2 100644
--- a/source/renderer/VertexBuffer.cpp
+++ b/source/renderer/VertexBuffer.cpp
@@ -22,6 +22,7 @@
#include "precompiled.h"
#include "ps/Errors.h"
#include "lib/ogl.h"
+#include "lib/sysdep/cpu.h"
#include "Renderer.h"
#include "VertexBuffer.h"
#include "VertexBufferManager.h"
diff --git a/source/scripting/ScriptGlue.cpp b/source/scripting/ScriptGlue.cpp
index daa9f3cb91..b3a724d53c 100644
--- a/source/scripting/ScriptGlue.cpp
+++ b/source/scripting/ScriptGlue.cpp
@@ -60,6 +60,7 @@
#include "renderer/Renderer.h"
#include "renderer/SkyManager.h"
#include "renderer/WaterManager.h"
+#include "scriptinterface/ScriptInterface.h"
#include "simulation/Entity.h"
#include "simulation/EntityFormation.h"
#include "simulation/EntityHandles.h"
@@ -881,56 +882,6 @@ JSBool ForceGarbageCollection(JSContext* cx, JSObject* UNUSED(obj), uintN argc,
-//-----------------------------------------------------------------------------
-// GUI
-//-----------------------------------------------------------------------------
-
-// Returns the sort-of-global object associated with the current GUI.
-// params:
-// returns: global object
-// notes:
-// - Useful for accessing an object from another scope.
-JSBool GetActiveGui(JSContext* UNUSED(cx), JSObject*, uintN UNUSED(argc), jsval* UNUSED(argv), jsval* rval)
-{
- *rval = OBJECT_TO_JSVAL(g_GUI->GetScriptObject());
- return JS_TRUE;
-}
-
-JSBool PushGuiPage(JSContext* cx, JSObject*, uintN UNUSED(argc), jsval* argv, jsval* UNUSED(rval))
-{
- try
- {
- CStrW name = ToPrimitive(cx, argv[0]);
- g_GUI->PushPage(name, argv[1]);
- return JS_TRUE;
- }
- catch (PSERROR_Scripting&)
- {
- return JS_FALSE;
- }
-}
-
-JSBool SwitchGuiPage(JSContext* cx, JSObject*, uintN UNUSED(argc), jsval* argv, jsval* UNUSED(rval))
-{
- try
- {
- CStrW name = ToPrimitive(cx, argv[0]);
- g_GUI->SwitchPage(name, argv[1]);
- return JS_TRUE;
- }
- catch (PSERROR_Scripting&)
- {
- return JS_FALSE;
- }
-}
-
-JSBool PopGuiPage(JSContext* UNUSED(cx), JSObject*, uintN UNUSED(argc), jsval* UNUSED(argv), jsval* UNUSED(rval))
-{
- g_GUI->PopPage();
- return JS_TRUE;
-}
-
-
//-----------------------------------------------------------------------------
// Misc. Engine Interface
//-----------------------------------------------------------------------------
@@ -1435,6 +1386,8 @@ JSBool isGameRunning( JSContext* cx, JSObject* UNUSED(globalObject), uintN argc,
return JS_TRUE;
}
+
+
//-----------------------------------------------------------------------------
// function table
//-----------------------------------------------------------------------------
@@ -1493,12 +1446,6 @@ JSFunctionSpec ScriptFunctionTable[] =
// Territory rendering
JS_FUNC("toggleTerritoryRendering", ToggleTerritoryRendering, 0)
- // GUI
- JS_FUNC("getActiveGui", GetActiveGui, 0)
- JS_FUNC("pushGuiPage", PushGuiPage, 2)
- JS_FUNC("switchGuiPage", SwitchGuiPage, 2)
- JS_FUNC("popGuiPage", PopGuiPage, 0)
-
// Events
JS_FUNC("addGlobalHandler", AddGlobalHandler, 2)
JS_FUNC("removeGlobalHandler", RemoveGlobalHandler, 2)
diff --git a/source/scripting/ScriptableComplex.h b/source/scripting/ScriptableComplex.h
index a6730b1d2c..f562a926d3 100644
--- a/source/scripting/ScriptableComplex.h
+++ b/source/scripting/ScriptableComplex.h
@@ -38,6 +38,8 @@ which #includes ScriptableComplex.h.
#include "simulation/ScriptObject.h"
#include "JSConversions.h"
+#include "lib/sysdep/stl.h"
+
#include
class IJSComplex;
diff --git a/source/scripting/ScriptableObject.h b/source/scripting/ScriptableObject.h
index e201f1e2ea..4216fecf96 100644
--- a/source/scripting/ScriptableObject.h
+++ b/source/scripting/ScriptableObject.h
@@ -20,11 +20,13 @@
// A quick way to add (mostly) sensibly-behaving JavaScript interfaces to native classes.
//
+#ifndef INCLUDED_SCRIPTABLEOBJECT
+#define INCLUDED_SCRIPTABLEOBJECT
+
#include "scripting/ScriptingHost.h"
#include "JSConversions.h"
-#ifndef INCLUDED_SCRIPTABLEOBJECT
-#define INCLUDED_SCRIPTABLEOBJECT
+#include "lib/sysdep/stl.h"
#define ALLOW_NONSHARED_NATIVES
diff --git a/source/scripting/ScriptingHost.cpp b/source/scripting/ScriptingHost.cpp
index 23b4539601..57f7c2cb64 100644
--- a/source/scripting/ScriptingHost.cpp
+++ b/source/scripting/ScriptingHost.cpp
@@ -24,6 +24,7 @@
#include "ps/Profile.h"
#include "ps/CLogger.h"
#include "ps/Filesystem.h"
+#include "scriptinterface/ScriptInterface.h"
#if OS_WIN
@@ -43,7 +44,7 @@ namespace
JSClass GlobalClass =
{
- "global", 0,
+ "global", JSCLASS_GLOBAL_FLAGS,
JS_PropertyStub, JS_PropertyStub,
JS_PropertyStub, JS_PropertyStub,
JS_EnumerateStub, JS_ResolveStub,
@@ -85,14 +86,18 @@ ScriptingHost::ScriptingHost()
if( JS_DefineProperties( m_Context, m_GlobalObject, ScriptGlobalTable ) == JS_FALSE )
throw PSERROR_Scripting_SetupFailed();
+
+ m_ScriptInterface = new ScriptInterface("Engine", m_Context);
}
ScriptingHost::~ScriptingHost()
{
+ delete m_ScriptInterface;
+
if (m_Context != NULL)
{
JS_EndRequest(m_Context);
- JS_DestroyContext(m_Context);
+ JS_DestroyContext(m_Context);
m_Context = NULL;
}
@@ -103,6 +108,11 @@ ScriptingHost::~ScriptingHost()
}
}
+ScriptInterface& ScriptingHost::GetScriptInterface()
+{
+ return *m_ScriptInterface;
+}
+
void ScriptingHost::FinalShutdown()
{
// This should only be called once per process, just to clean up before
@@ -186,27 +196,6 @@ void ScriptingHost::DefineConstant(const std::string & name, int value)
throw PSERROR_Scripting_DefineConstantFailed();
}
-void ScriptingHost::DefineConstant(const std::string & name, double value)
-{
- // First remove this constant if it already exists
- JS_DeleteProperty(m_Context, m_GlobalObject, name.c_str());
-
- struct JSConstDoubleSpec spec[2];
-
- spec[0].name = name.c_str();
- spec[0].dval = value;
- spec[0].flags = JSPROP_READONLY;
-
- spec[1].name = 0;
- spec[1].dval = 0.0;
- spec[1].flags = 0;
-
- JSBool ok = JS_DefineConstDoubles(m_Context, m_GlobalObject, spec);
-
- if (ok == JS_FALSE)
- throw PSERROR_Scripting_DefineConstantFailed();
-}
-
void ScriptingHost::DefineCustomObjectType(JSClass *clasp, JSNative constructor, uintN minArgs, JSPropertySpec *ps, JSFunctionSpec *fs, JSPropertySpec *static_ps, JSFunctionSpec *static_fs)
{
std::string typeName = clasp->name;
@@ -292,67 +281,12 @@ void ScriptingHost::SetGlobal(const std::string &globalName, jsval value)
JS_SetProperty(m_Context, m_GlobalObject, globalName.c_str(), &value);
}
-// unused
-jsval ScriptingHost::GetGlobal(const std::string &globalName)
-{
- jsval vp;
- JS_GetProperty(m_Context, m_GlobalObject, globalName.c_str(), &vp);
- return vp;
-}
-
-
-
-
-
-
-
//----------------------------------------------------------------------------
// conversions
//----------------------------------------------------------------------------
-/*
-// These have been removed in favour of ToPrimitive(value)
-int ScriptingHost::ValueToInt(const jsval value)
-{
- int32 i = 0;
-
- JSBool ok = JS_ValueToInt32(m_Context, value, &i);
-
- if (!ok)
- throw PSERROR_Scripting_ConversionFailed();
-
- return i;
-}
-
-bool ScriptingHost::ValueToBool(const jsval value)
-{
- JSBool b;
-
- JSBool ok = JS_ValueToBoolean(m_Context, value, &b);
-
- if (!ok)
- throw PSERROR_Scripting_ConversionFailed();
-
- return b == JS_TRUE;
-}
-
-
-double ScriptingHost::ValueToDouble(const jsval value)
-{
- jsdouble d;
-
- JSBool ok = JS_ValueToNumber(m_Context, value, &d);
-
- if (ok == JS_FALSE || !isfinite(d))
- throw PSERROR_Scripting_ConversionFailed();
-
- return d;
-}
-
-
-*/
std::string ScriptingHost::ValueToString(const jsval value)
{
JSString* string = JS_ValueToString(m_Context, value);
@@ -363,19 +297,6 @@ std::string ScriptingHost::ValueToString(const jsval value)
}
CStrW ScriptingHost::ValueToUCString( const jsval value )
-{
- return CStrW(ValueToUTF16(value));
-}
-
-jsval ScriptingHost::UCStringToValue( const CStrW& str )
-{
- utf16string utf16=str.utf16();
- return UTF16ToValue(utf16);
-}
-
-
-
-utf16string ScriptingHost::ValueToUTF16( const jsval value )
{
JSString* string = JS_ValueToString(m_Context, value);
if (string == NULL)
@@ -383,12 +304,12 @@ utf16string ScriptingHost::ValueToUTF16( const jsval value )
jschar *strptr=JS_GetStringChars(string);
size_t length=JS_GetStringLength(string);
- return utf16string(strptr, strptr+length);
+ return std::wstring(strptr, strptr+length);
}
-jsval ScriptingHost::UTF16ToValue(const utf16string &str)
+jsval ScriptingHost::UCStringToValue( const CStrW& str )
{
- return STRING_TO_JSVAL(JS_NewUCStringCopyZ(m_Context, str.c_str()));
+ return STRING_TO_JSVAL(JS_NewUCStringCopyZ(m_Context, str.utf16().c_str()));
}
//----------------------------------------------------------------------------
diff --git a/source/scripting/ScriptingHost.h b/source/scripting/ScriptingHost.h
index 62cb53a8ed..c1359dc58d 100644
--- a/source/scripting/ScriptingHost.h
+++ b/source/scripting/ScriptingHost.h
@@ -49,34 +49,22 @@ ERROR_TYPE(Scripting_DefineType, CreationFailed);
#include "ps/Singleton.h"
#include "ps/CStr.h"
+class ScriptInterface;
+
class IPropertyOwner
{
};
-/*
-class DelayedScriptExecutor
-{
-public:
- DelayedScriptExecutor(const std::string & functionName, float delaySeconds)
- : m_FunctionName(functionName), m_SecondsToExecution(delaySeconds)
- {
- }
-
- std::string m_FunctionName;
- float m_SecondsToExecution;
-};
-*/
-
-class CustomType
-{
-public:
- JSObject * m_Object;
- JSClass * m_Class;
-};
-
class ScriptingHost : public Singleton < ScriptingHost >
{
private:
+ class CustomType
+ {
+ public:
+ JSObject * m_Object;
+ JSClass * m_Class;
+ };
+
JSRuntime * m_RunTime;
JSContext * m_Context;
JSObject * m_GlobalObject;
@@ -91,11 +79,18 @@ private:
// A hook to capture function calls
static void* jshook_function( JSContext* cx, JSStackFrame* fp, JSBool before, JSBool* ok, void* closure );
#endif
+
+ // The long-term plan is to migrate from ScriptingHost to the newer shinier ScriptInterface.
+ // For now, just have a ScriptInterface that hooks onto the ScriptingHost's context so they
+ // can both be used.
+ ScriptInterface* m_ScriptInterface;
public:
ScriptingHost();
~ScriptingHost();
+ ScriptInterface& GetScriptInterface();
+
static void FinalShutdown();
// Helpers:
@@ -103,6 +98,7 @@ public:
// TODO: Remove one of these
inline JSContext *getContext() { return m_Context; }
inline JSContext *GetContext() { return m_Context; }
+
inline JSObject* GetGlobalObject() { return m_GlobalObject; }
void RunMemScript(const char* script, size_t size, const char* filename = 0, int line = 0, JSObject* globalObject = 0);
@@ -116,7 +112,6 @@ public:
void RegisterFunction(const std::string & functionName, JSNative function, int numArgs);
void DefineConstant(const std::string & name, int value);
- void DefineConstant(const std::string & name, double value);
void DefineCustomObjectType(JSClass *clasp, JSNative constructor, uintN nargs, JSPropertySpec *ps, JSFunctionSpec *fs, JSPropertySpec *static_ps, JSFunctionSpec *static_fs);
@@ -129,16 +124,9 @@ public:
double GetObjectProperty_Double(JSObject* object, const char* propertyName);
void SetGlobal(const std::string& globalName, jsval value);
- jsval GetGlobal(const std::string& globalName);
- int ValueToInt(const jsval value);
- bool ValueToBool(const jsval value);
std::string ValueToString(const jsval value);
- CStrW ValueToUCString( const jsval value );
- utf16string ValueToUTF16( const jsval value );
- double ValueToDouble(const jsval value);
-
- jsval UTF16ToValue(const utf16string &str);
+ CStrW ValueToUCString(const jsval value);
jsval UCStringToValue(const CStrW& str);
static void ErrorReporter(JSContext * context, const char * message, JSErrorReport * report);
diff --git a/source/scriptinterface/NativeWrapperDecls.h b/source/scriptinterface/NativeWrapperDecls.h
new file mode 100644
index 0000000000..864b1dc468
--- /dev/null
+++ b/source/scriptinterface/NativeWrapperDecls.h
@@ -0,0 +1,70 @@
+/* Copyright (C) 2009 Wildfire Games.
+ * This file is part of 0 A.D.
+ *
+ * 0 A.D. is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * 0 A.D. is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with 0 A.D. If not, see .
+ */
+
+#include
+#include
+
+// Define lots of useful macros:
+
+// Varieties of comma-separated list to fit on the head/tail/whole of another comma-separated list
+#define NUMBERED_LIST_HEAD(z, i, data) data##i,
+#define NUMBERED_LIST_TAIL(z, i, data) ,data##i
+#define NUMBERED_LIST_BALANCED(z, i, data) BOOST_PP_COMMA_IF(i) data##i
+// Some other things
+#define TYPED_ARGS(z, i, data) , T##i a##i
+#define CONVERT_ARG(z, i, data) T##i a##i; if (! ScriptInterface::FromJSVal(cx, argv[i], a##i)) return JS_FALSE;
+
+// List-generating macros, named roughly after their first list item
+#define TYPENAME_T0_HEAD(z, i) BOOST_PP_REPEAT_##z (i, NUMBERED_LIST_HEAD, typename T) // "typename T0, typename T1, "
+#define TYPENAME_T0_TAIL(z, i) BOOST_PP_REPEAT_##z (i, NUMBERED_LIST_TAIL, typename T) // ", typename T0, typename T1"
+#define T0(z, i) BOOST_PP_REPEAT_##z (i, NUMBERED_LIST_BALANCED, T) // "T0, T1"
+#define T0_HEAD(z, i) BOOST_PP_REPEAT_##z (i, NUMBERED_LIST_HEAD, T) // "T0, T1, "
+#define T0_TAIL(z, i) BOOST_PP_REPEAT_##z (i, NUMBERED_LIST_TAIL, T) // ", T0, T1"
+#define T0_A0(z, i) BOOST_PP_REPEAT_##z (i, TYPED_ARGS, ~) // "T0 a0, T1 a1"
+#define A0(z, i) BOOST_PP_REPEAT_##z (i, NUMBERED_LIST_BALANCED, a) // "a0, a1"
+#define A0_TAIL(z, i) BOOST_PP_REPEAT_##z (i, NUMBERED_LIST_TAIL, a) // ", a0, a1"
+
+// Define RegisterFunction
+#define OVERLOADS(z, i, data) \
+ template \
+ void RegisterFunction(const char* name) { \
+ Register(name, call, nargs<0 T0_TAIL(z,i)>()); \
+ }
+BOOST_PP_REPEAT(SCRIPT_INTERFACE_MAX_ARGS, OVERLOADS, ~)
+#undef OVERLOADS
+
+// JSNative-compatible function that wraps the function identified in the template argument list
+// (Definition comes later, since it depends on some things we haven't defined yet)
+#define OVERLOADS(z, i, data) \
+ template \
+ static JSBool call(JSContext* cx, JSObject* obj, uintN argc, jsval* argv, jsval* rval);
+BOOST_PP_REPEAT(SCRIPT_INTERFACE_MAX_ARGS, OVERLOADS, ~)
+#undef OVERLOADS
+
+// Similar, for class methods
+#define OVERLOADS(z, i, data) \
+ template \
+ static JSBool callMethod(JSContext* cx, JSObject* obj, uintN argc, jsval* argv, jsval* rval);
+BOOST_PP_REPEAT(SCRIPT_INTERFACE_MAX_ARGS, OVERLOADS, ~)
+#undef OVERLOADS
+
+// Argument-number counter
+#define OVERLOADS(z, i, data) \
+ template /* add a dummy parameter so we still compile with 0 template args */ \
+ static size_t nargs() { return i; }
+BOOST_PP_REPEAT(SCRIPT_INTERFACE_MAX_ARGS, OVERLOADS, ~)
+#undef OVERLOADS
diff --git a/source/scriptinterface/NativeWrapperDefns.h b/source/scriptinterface/NativeWrapperDefns.h
new file mode 100644
index 0000000000..06892b7ad4
--- /dev/null
+++ b/source/scriptinterface/NativeWrapperDefns.h
@@ -0,0 +1,116 @@
+/* Copyright (C) 2009 Wildfire Games.
+ * This file is part of 0 A.D.
+ *
+ * 0 A.D. is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * 0 A.D. is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with 0 A.D. If not, see .
+ */
+
+// (NativeWrapperDecls.h set up a lot of the macros we use here)
+
+
+// ScriptInterface_NativeWrapper::call(cx, rval, fptr, args...) will call fptr(cbdata, args...),
+// and if T != void then it will store the result in rval:
+
+// Templated on the return type so void can be handled separately
+template
+struct ScriptInterface_NativeWrapper {
+ #define OVERLOADS(z, i, data) \
+ template \
+ static void call(JSContext* cx, jsval& rval, F fptr T0_A0(z,i)) { \
+ rval = ScriptInterface::ToJSVal(cx, fptr(ScriptInterface::GetCallbackData(cx) A0_TAIL(z,i))); \
+ }
+
+ BOOST_PP_REPEAT(SCRIPT_INTERFACE_MAX_ARGS, OVERLOADS, ~)
+ #undef OVERLOADS
+};
+
+// Overloaded to ignore the return value from void functions
+template <>
+struct ScriptInterface_NativeWrapper {
+ #define OVERLOADS(z, i, data) \
+ template \
+ static void call(JSContext* cx, jsval& /*rval*/, F fptr T0_A0(z,i)) { \
+ fptr(ScriptInterface::GetCallbackData(cx) A0_TAIL(z,i)); \
+ }
+ BOOST_PP_REPEAT(SCRIPT_INTERFACE_MAX_ARGS, OVERLOADS, ~)
+ #undef OVERLOADS
+};
+
+// Same idea but for method calls:
+
+template
+struct ScriptInterface_NativeMethodWrapper {
+ #define OVERLOADS(z, i, data) \
+ template \
+ static void call(JSContext* cx, jsval& rval, TC* c, F fptr T0_A0(z,i)) { \
+ rval = ScriptInterface::ToJSVal(cx, (c->*fptr)( A0(z,i) )); \
+ }
+
+ BOOST_PP_REPEAT(SCRIPT_INTERFACE_MAX_ARGS, OVERLOADS, ~)
+ #undef OVERLOADS
+};
+
+template
+struct ScriptInterface_NativeMethodWrapper {
+ #define OVERLOADS(z, i, data) \
+ template \
+ static void call(JSContext* /*cx*/, jsval& /*rval*/, TC* c, F fptr T0_A0(z,i)) { \
+ (c->*fptr)( A0(z,i) ); \
+ }
+ BOOST_PP_REPEAT(SCRIPT_INTERFACE_MAX_ARGS, OVERLOADS, ~)
+ #undef OVERLOADS
+};
+
+
+
+// JSNative-compatible function that wraps the function identified in the template argument list
+#define OVERLOADS(z, i, data) \
+ template \
+ JSBool ScriptInterface::call(JSContext* cx, JSObject* /*obj*/, uintN /*argc*/, jsval* argv, jsval* rval) { \
+ (void)argv; /* avoid 'unused parameter' warnings */ \
+ BOOST_PP_REPEAT_##z (i, CONVERT_ARG, ~) \
+ ScriptInterface_NativeWrapper::call(cx, *rval, fptr A0_TAIL(z,i)); \
+ return (ScriptInterface::IsExceptionPending(cx) ? JS_FALSE : JS_TRUE); \
+ }
+BOOST_PP_REPEAT(SCRIPT_INTERFACE_MAX_ARGS, OVERLOADS, ~)
+#undef OVERLOADS
+
+// Same idea but for methods
+#define OVERLOADS(z, i, data) \
+ template \
+ JSBool ScriptInterface::callMethod(JSContext* cx, JSObject* obj, uintN /*argc*/, jsval* argv, jsval* rval) { \
+ (void)argv; /* avoid 'unused parameter' warnings */ \
+ if (ScriptInterface::GetClass(cx, obj) != CLS) return JS_FALSE; \
+ TC* c = static_cast(ScriptInterface::GetPrivate(cx, obj)); \
+ if (! c) return JS_FALSE; \
+ BOOST_PP_REPEAT_##z (i, CONVERT_ARG, ~) \
+ ScriptInterface_NativeMethodWrapper::call(cx, *rval, c, fptr A0_TAIL(z,i)); \
+ return (ScriptInterface::IsExceptionPending(cx) ? JS_FALSE : JS_TRUE); \
+ }
+BOOST_PP_REPEAT(SCRIPT_INTERFACE_MAX_ARGS, OVERLOADS, ~)
+#undef OVERLOADS
+
+// Clean up our mess
+#undef NUMBERED_LIST_HEAD
+#undef NUMBERED_LIST_TAIL
+#undef NUMBERED_LIST_BALANCED
+#undef TYPED_ARGS
+#undef CONVERT_ARG
+#undef TYPENAME_T0_HEAD
+#undef TYPENAME_T0_TAIL
+#undef T0
+#undef T0_HEAD
+#undef T0_TAIL
+#undef T0_A0
+#undef A0
+#undef A0_TAIL
diff --git a/source/scriptinterface/ScriptConversions.cpp b/source/scriptinterface/ScriptConversions.cpp
new file mode 100644
index 0000000000..0141f41cc0
--- /dev/null
+++ b/source/scriptinterface/ScriptConversions.cpp
@@ -0,0 +1,219 @@
+/* Copyright (C) 2010 Wildfire Games.
+ * This file is part of 0 A.D.
+ *
+ * 0 A.D. is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * 0 A.D. is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with 0 A.D. If not, see .
+ */
+
+#include "precompiled.h"
+
+#include "ScriptInterface.h"
+
+#include "ps/utf16string.h"
+
+#include "js/jsapi.h"
+
+#define FAIL(msg) do { JS_ReportError(cx, msg); return false; } while (false)
+
+template<> bool ScriptInterface::FromJSVal(JSContext* cx, jsval v, bool& out)
+{
+ JSBool ret;
+ if (!JS_ValueToBoolean(cx, v, &ret))
+ return false;
+ out = (ret ? true : false);
+ return true;
+}
+
+template<> bool ScriptInterface::FromJSVal(JSContext* cx, jsval v, float& out)
+{
+ jsdouble ret;
+ if (!JS_ValueToNumber(cx, v, &ret))
+ return false;
+ out = ret;
+ return true;
+}
+
+template<> bool ScriptInterface::FromJSVal(JSContext* cx, jsval v, i32& out)
+{
+ int32 ret;
+ if (!JS_ValueToECMAInt32(cx, v, &ret))
+ return false;
+ out = ret;
+ return true;
+}
+
+template<> bool ScriptInterface::FromJSVal(JSContext* cx, jsval v, u32& out)
+{
+ uint32 ret;
+ if (!JS_ValueToECMAUint32(cx, v, &ret))
+ return false;
+ out = ret;
+ return true;
+}
+
+// NOTE: we can't define a jsval specialisation, because that conflicts with integer types
+template<> bool ScriptInterface::FromJSVal(JSContext* UNUSED(cx), jsval v, CScriptVal& out)
+{
+ out = v;
+ return true;
+}
+
+template<> bool ScriptInterface::FromJSVal(JSContext* cx, jsval v, CScriptValRooted& out)
+{
+ out = CScriptValRooted(cx, v);
+ return true;
+}
+
+template<> bool ScriptInterface::FromJSVal(JSContext* cx, jsval v, std::wstring& out)
+{
+ JSString* ret = JS_ValueToString(cx, v);
+ if (!ret)
+ FAIL("Argument must be convertible to a string");
+ jschar* ch = JS_GetStringChars(ret);
+ out = std::wstring(ch, ch + JS_GetStringLength(ret));
+ return true;
+}
+
+template<> bool ScriptInterface::FromJSVal(JSContext* cx, jsval v, std::string& out)
+{
+ JSString* ret = JS_ValueToString(cx, v);
+ if (!ret)
+ FAIL("Argument must be convertible to a string");
+ char* ch = JS_GetStringBytes(ret);
+ out = std::string(ch, ch + JS_GetStringLength(ret));
+ // TODO: if JS_GetStringBytes fails it'll return a zero-length string
+ // and we'll overflow its bounds by using JS_GetStringLength - should
+ // use one of the new SpiderMonkey 1.8 functions instead
+ return true;
+}
+
+/*
+template bool ScriptInterface::FromJSVal >(JSContext* cx, jsval v, std::vector& out)
+{
+ JSObject* obj;
+ if (!JS_ValueToObject(cx, v, &obj) || obj == NULL || !JS_IsArrayObject(cx, obj))
+ FAIL("Argument must be an array");
+ jsuint length;
+ if (!JS_GetArrayLength(cx, obj, &length))
+ FAIL("Failed to get array length");
+ out.reserve(length);
+ for (jsuint i = 0; i < length; ++i)
+ {
+ jsval el;
+ if (!JS_GetElement(cx, obj, i, &el))
+ FAIL("Failed to read array element");
+ T el2;
+ if (!FromJSVal::Convert(cx, el, el2))
+ return false;
+ out.push_back(el2);
+ }
+ return true;
+}
+*/
+
+////////////////////////////////////////////////////////////////
+// Primitive types:
+
+template<> jsval ScriptInterface::ToJSVal(JSContext* UNUSED(cx), const bool& val)
+{
+ return val ? JSVAL_TRUE : JSVAL_FALSE;
+}
+
+template<> jsval ScriptInterface::ToJSVal(JSContext* cx, const float& val)
+{
+ jsval rval = JSVAL_VOID;
+ JS_NewNumberValue(cx, val, &rval); // ignore return value
+ return rval;
+}
+
+template<> jsval ScriptInterface::ToJSVal(JSContext* cx, const i32& val)
+{
+ if (INT_FITS_IN_JSVAL(val))
+ return INT_TO_JSVAL(val);
+ jsval rval = JSVAL_VOID;
+ JS_NewNumberValue(cx, val, &rval); // ignore return value
+ return rval;
+}
+
+template<> jsval ScriptInterface::ToJSVal(JSContext* cx, const u32& val)
+{
+ if (val <= JSVAL_INT_MAX)
+ return INT_TO_JSVAL(val);
+ jsval rval = JSVAL_VOID;
+ JS_NewNumberValue(cx, val, &rval); // ignore return value
+ return rval;
+}
+
+// NOTE: we can't define a jsval specialisation, because that conflicts with integer types
+template<> jsval ScriptInterface::ToJSVal(JSContext* UNUSED(cx), const CScriptVal& val)
+{
+ return val.get();
+}
+
+template<> jsval ScriptInterface::ToJSVal(JSContext* UNUSED(cx), const CScriptValRooted& val)
+{
+ return val.get();
+}
+
+template<> jsval ScriptInterface::ToJSVal(JSContext* cx, const std::wstring& val)
+{
+ utf16string utf16(val.begin(), val.end());
+ JSString* str = JS_NewUCStringCopyN(cx, reinterpret_cast (utf16.c_str()), utf16.length());
+ if (str)
+ return STRING_TO_JSVAL(str);
+ return JSVAL_VOID;
+}
+
+template<> jsval ScriptInterface::ToJSVal(JSContext* cx, const std::string& val)
+{
+ JSString* str = JS_NewStringCopyN(cx, val.c_str(), val.length());
+ if (str)
+ return STRING_TO_JSVAL(str);
+ return JSVAL_VOID;
+}
+
+template<> jsval ScriptInterface::ToJSVal(JSContext* cx, const char* const& val)
+{
+ JSString* str = JS_NewStringCopyZ(cx, val);
+ if (str)
+ return STRING_TO_JSVAL(str);
+ return JSVAL_VOID;
+}
+
+////////////////////////////////////////////////////////////////
+// Compound types:
+
+template static jsval ToJSVal_vector(JSContext* cx, const std::vector& val)
+{
+ JSObject* obj = JS_NewArrayObject(cx, 0, NULL);
+ if (!obj)
+ return JSVAL_VOID;
+ JS_AddRoot(cx, &obj);
+ for (size_t i = 0; i < val.size(); ++i)
+ {
+ jsval el = ScriptInterface::ToJSVal(cx, val[i]);
+ JS_SetElement(cx, obj, (jsint)i, &el);
+ }
+ JS_RemoveRoot(cx, &obj);
+ return OBJECT_TO_JSVAL(obj);
+}
+
+template<> jsval ScriptInterface::ToJSVal >(JSContext* cx, const std::vector& val)
+{
+ return ToJSVal_vector(cx, val);
+}
+
+template<> jsval ScriptInterface::ToJSVal >(JSContext* cx, const std::vector& val)
+{
+ return ToJSVal_vector(cx, val);
+}
diff --git a/source/scriptinterface/ScriptInterface.cpp b/source/scriptinterface/ScriptInterface.cpp
new file mode 100644
index 0000000000..3156f1b6d2
--- /dev/null
+++ b/source/scriptinterface/ScriptInterface.cpp
@@ -0,0 +1,465 @@
+/* Copyright (C) 2009 Wildfire Games.
+ * This file is part of 0 A.D.
+ *
+ * 0 A.D. is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * 0 A.D. is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with 0 A.D. If not, see .
+ */
+
+#include "precompiled.h"
+
+#include "ScriptInterface.h"
+
+#include "lib/debug.h"
+#include "ps/CLogger.h"
+#include "ps/utf16string.h"
+
+#include
+
+#include "js/jsapi.h"
+
+#include
+#include
+
+#ifdef USE_VALGRIND
+# include
+#endif
+
+const int RUNTIME_SIZE = 4 * 1024 * 1024; // TODO: how much memory is needed?
+const int STACK_CHUNK_SIZE = 8192;
+
+////////////////////////////////////////////////////////////////
+
+struct ScriptInterface_impl
+{
+ ScriptInterface_impl(const char* nativeScopeName, JSContext* cx);
+ ~ScriptInterface_impl();
+ void Register(const char* name, JSNative fptr, uintN nargs);
+
+ JSRuntime* m_rt; // NULL if m_cx is shared; non-NULL if we own m_cx
+ JSContext* m_cx;
+ JSObject* m_glob; // global scope object
+ JSObject* m_nativeScope; // native function scope object
+};
+
+namespace
+{
+
+JSClass global_class = {
+ "global", JSCLASS_GLOBAL_FLAGS,
+ JS_PropertyStub, JS_PropertyStub, JS_PropertyStub, JS_PropertyStub,
+ JS_EnumerateStub, JS_ResolveStub, JS_ConvertStub, JS_FinalizeStub,
+ NULL, NULL, NULL, NULL,
+ NULL, NULL, NULL, NULL
+};
+
+void ErrorReporter(JSContext* UNUSED(cx), const char* message, JSErrorReport* report)
+{
+ std::stringstream msg;
+ bool isWarning = JSREPORT_IS_WARNING(report->flags);
+ msg << (isWarning ? "JavaScript warning: " : "JavaScript error: ");
+ if (report->filename)
+ {
+ msg << report->filename;
+ msg << " line " << report->lineno << "\n";
+ }
+ msg << message;
+ if (isWarning)
+ LOGWARNING(L"%hs", msg.str().c_str());
+ else
+ LOGERROR(L"%hs", msg.str().c_str());
+#ifdef USE_VALGRIND
+ // When running under Valgrind, print more information in the error message
+ VALGRIND_PRINTF_BACKTRACE("->");
+#endif
+}
+
+// Functions in the global namespace:
+
+JSBool print(JSContext* cx, JSObject* UNUSED(obj), uintN argc, jsval* argv, jsval* UNUSED(rval))
+{
+ for (uintN i = 0; i < argc; ++i)
+ {
+ std::string str;
+ if (!ScriptInterface::FromJSVal(cx, argv[i], str))
+ return JS_FALSE;
+ printf("%s", str.c_str());
+ }
+ fflush(stdout);
+ return JS_TRUE;
+}
+
+} // anonymous namespace
+
+ScriptInterface_impl::ScriptInterface_impl(const char* nativeScopeName, JSContext* cx)
+{
+ JSBool ok;
+
+ if (cx)
+ {
+ m_rt = NULL;
+ m_cx = cx;
+ m_glob = JS_GetGlobalObject(m_cx);
+ }
+ else
+ {
+ m_rt = JS_NewRuntime(RUNTIME_SIZE);
+ debug_assert(m_rt); // TODO: error handling
+
+ m_cx = JS_NewContext(m_rt, STACK_CHUNK_SIZE);
+ debug_assert(m_cx);
+
+ // For GC debugging with SpiderMonkey 1.8+:
+ // JS_SetGCZeal(m_cx, 2);
+
+ JS_SetContextPrivate(m_cx, NULL);
+
+ JS_SetErrorReporter(m_cx, ErrorReporter);
+
+ JS_SetOptions(m_cx, JSOPTION_STRICT // "warn on dubious practice"
+ | JSOPTION_XML // "ECMAScript for XML support: parse as a token"
+ | JSOPTION_VAROBJFIX // "recommended" (fixes variable scoping)
+ );
+
+ // Threadsafe SpiderMonkey requires that we have a request before doing anything much
+ JS_BeginRequest(m_cx);
+
+ m_glob = JS_NewObject(m_cx, &global_class, NULL, NULL);
+ ok = JS_InitStandardClasses(m_cx, m_glob);
+
+ JS_DefineProperty(m_cx, m_glob, "global", OBJECT_TO_JSVAL(m_glob), NULL, NULL, JSPROP_ENUMERATE | JSPROP_READONLY
+ | JSPROP_PERMANENT);
+ }
+
+ m_nativeScope = JS_DefineObject(m_cx, m_glob, nativeScopeName, NULL, NULL, JSPROP_ENUMERATE | JSPROP_READONLY
+ | JSPROP_PERMANENT);
+
+ JS_DefineFunction(m_cx, m_glob, "print", ::print, 0, JSPROP_ENUMERATE | JSPROP_READONLY | JSPROP_PERMANENT);
+}
+
+ScriptInterface_impl::~ScriptInterface_impl()
+{
+ if (m_rt) // if we own the context:
+ {
+ JS_EndRequest(m_cx);
+ JS_DestroyContext(m_cx);
+ JS_DestroyRuntime(m_rt);
+ }
+}
+
+static JSBool LoadScript(JSContext* cx, const jschar* chars, uintN length, const char* filename, jsval* rval)
+{
+ JSFunction* func = JS_CompileUCFunction(cx, NULL, NULL, 0, NULL, chars, length, filename, 1);
+ if (!func)
+ return JS_FALSE;
+ JS_AddRoot(cx, &func); // TODO: do we need to root this?
+ *rval = OBJECT_TO_JSVAL((JSObject*)func);
+ jsval scriptRval;
+ JSBool ok = JS_CallFunction(cx, NULL, func, 0, NULL, &scriptRval);
+ JS_RemoveRoot(cx, &func);
+ return ok;
+}
+
+void ScriptInterface_impl::Register(const char* name, JSNative fptr, uintN nargs)
+{
+ JS_DefineFunction(m_cx, m_nativeScope, name, fptr, nargs, JSPROP_ENUMERATE | JSPROP_READONLY | JSPROP_PERMANENT);
+}
+
+ScriptInterface::ScriptInterface(const char* nativeScopeName, JSContext* cx) :
+ m(new ScriptInterface_impl(nativeScopeName, cx))
+{
+}
+
+ScriptInterface::~ScriptInterface()
+{
+}
+
+void ScriptInterface::ShutDown()
+{
+ JS_ShutDown();
+}
+
+void ScriptInterface::SetCallbackData(void* cbdata)
+{
+ JS_SetContextPrivate(m->m_cx, cbdata);
+}
+
+void* ScriptInterface::GetCallbackData(JSContext* cx)
+{
+ return JS_GetContextPrivate(cx);
+}
+
+void ScriptInterface::Register(const char* name, JSNative fptr, size_t nargs)
+{
+ m->Register(name, fptr, (uintN)nargs);
+}
+
+JSContext* ScriptInterface::GetContext()
+{
+ return m->m_cx;
+}
+
+bool ScriptInterface::AddRoot(void* ptr, const char* name)
+{
+ return JS_AddNamedRoot(m->m_cx, ptr, name) ? true : false;
+}
+
+bool ScriptInterface::RemoveRoot(void* ptr)
+{
+ return JS_RemoveRoot(m->m_cx, ptr) ? true : false;
+}
+
+ScriptInterface::LocalRootScope::LocalRootScope(JSContext* cx) :
+ m_cx(cx)
+{
+ m_OK = JS_EnterLocalRootScope(m_cx) ? true : false;
+}
+
+ScriptInterface::LocalRootScope::~LocalRootScope()
+{
+ if (m_OK)
+ JS_LeaveLocalRootScope(m_cx);
+}
+
+bool ScriptInterface::LocalRootScope::OK()
+{
+ return m_OK;
+}
+
+jsval ScriptInterface::CallConstructor(jsval ctor)
+{
+ // Constructing JS objects similarly to "new Foo" is non-trivial.
+ // https://developer.mozilla.org/En/SpiderMonkey/JSAPI_Phrasebook#Constructing_an_object_with_new
+ // suggests some ugly ways, so we'll use a different way that's less compatible but less ugly
+
+ if (!(JSVAL_IS_OBJECT(ctor) && JS_ObjectIsFunction(m->m_cx, JSVAL_TO_OBJECT(ctor))))
+ {
+ LOGERROR(L"CallConstructor: ctor is not a function object");
+ return JSVAL_VOID;
+ }
+
+ // Get the constructor's prototype
+ // (Can't use JS_GetPrototype, since we want .prototype not .__proto__)
+ jsval protoVal;
+ if (!JS_GetProperty(m->m_cx, JSVAL_TO_OBJECT(ctor), "prototype", &protoVal))
+ {
+ LOGERROR(L"CallConstructor: can't get prototype");
+ return JSVAL_VOID;
+ }
+
+ if (!JSVAL_IS_OBJECT(protoVal))
+ {
+ LOGERROR(L"CallConstructor: prototype is not an object");
+ return JSVAL_VOID;
+ }
+
+ JSObject* proto = JSVAL_TO_OBJECT(protoVal);
+ JSObject* parent = JS_GetParent(m->m_cx, JSVAL_TO_OBJECT(ctor));
+ // TODO: rooting?
+ if (!proto || !parent)
+ {
+ LOGERROR(L"CallConstructor: null proto/parent");
+ return JSVAL_VOID;
+ }
+
+ JSObject* obj = JS_NewObject(m->m_cx, NULL, proto, parent);
+ if (!obj)
+ {
+ LOGERROR(L"CallConstructor: object creation failed");
+ return JSVAL_VOID;
+ }
+
+ jsval rval;
+ if (!JS_CallFunctionValue(m->m_cx, obj, ctor, 0, NULL, &rval))
+ {
+ LOGERROR(L"CallConstructor: ctor failed");
+ return JSVAL_VOID;
+ }
+
+ return OBJECT_TO_JSVAL(obj);
+}
+
+bool ScriptInterface::CallFunctionVoid(jsval val, const char* name)
+{
+ jsval jsRet;
+ std::vector argv;
+ return CallFunction_(val, name, argv, jsRet);
+}
+
+bool ScriptInterface::CallFunction_(jsval val, const char* name, std::vector& args, jsval& ret)
+{
+ const uintN argc = args.size();
+ jsval* argv = NULL;
+ if (argc)
+ argv = &args[0];
+
+ JSObject* obj;
+ if (!JS_ValueToObject(m->m_cx, val, &obj) || obj == NULL)
+ return false;
+ JS_AddRoot(m->m_cx, &obj);
+
+ // Check that the named function actually exists, to avoid ugly JS error reports
+ // when calling an undefined value
+ JSBool found;
+ if (!JS_HasProperty(m->m_cx, obj, name, &found) || !found)
+ {
+ JS_RemoveRoot(m->m_cx, &obj);
+ return false;
+ }
+
+ JSBool ok = JS_CallFunctionName(m->m_cx, obj, name, argc, argv, &ret);
+ JS_RemoveRoot(m->m_cx, &obj);
+
+ return ok ? true : false;
+}
+
+jsval ScriptInterface::GetGlobalObject()
+{
+ return OBJECT_TO_JSVAL(JS_GetGlobalObject(m->m_cx));
+}
+
+bool ScriptInterface::SetGlobal_(const char* name, jsval value)
+{
+ JSBool ok = JS_DefineProperty(m->m_cx, m->m_glob, name, value, NULL, NULL, JSPROP_ENUMERATE | JSPROP_READONLY
+ | JSPROP_PERMANENT);
+ return ok ? true : false;
+}
+
+bool ScriptInterface::SetProperty_(jsval obj, const char* name, jsval value, bool constant)
+{
+ uintN attrs;
+ if (constant)
+ attrs = JSPROP_READONLY | JSPROP_PERMANENT;
+ else
+ attrs = JSPROP_ENUMERATE;
+
+ if (! JSVAL_IS_OBJECT(obj))
+ return false;
+ JSObject* object = JSVAL_TO_OBJECT(obj);
+
+ if (! JS_DefineProperty(m->m_cx, object, name, value, NULL, NULL, attrs))
+ return false;
+ return true;
+}
+
+bool ScriptInterface::GetProperty_(jsval obj, const char* name, jsval& out)
+{
+ if (! JSVAL_IS_OBJECT(obj))
+ return false;
+ JSObject* object = JSVAL_TO_OBJECT(obj);
+
+ if (!JS_GetProperty(m->m_cx, object, name, &out))
+ return false;
+ return true;
+}
+
+bool ScriptInterface::EnumeratePropertyNamesWithPrefix(jsval obj, const char* prefix, std::vector& out)
+{
+ LOCAL_ROOT_SCOPE;
+
+ utf16string prefix16 (prefix, prefix+strlen(prefix));
+
+ if (! JSVAL_IS_OBJECT(obj))
+ return false; // TODO: log error messages
+
+ JSObject* it = JS_NewPropertyIterator(m->m_cx, JSVAL_TO_OBJECT(obj));
+ if (!it)
+ return false;
+
+ while (true)
+ {
+ jsid idp;
+ jsval val;
+ if (! JS_NextProperty(m->m_cx, it, &idp) || ! JS_IdToValue(m->m_cx, idp, &val))
+ return false;
+ if (val == JSVAL_VOID)
+ break; // end of iteration
+ if (! JSVAL_IS_STRING(val))
+ continue; // ignore integer properties
+
+ JSString* name = JSVAL_TO_STRING(val);
+ size_t len = JS_GetStringLength(name);
+ jschar* chars = JS_GetStringChars(name);
+ if (len >= prefix16.size() && memcmp(chars, prefix16.c_str(), prefix16.size()*2) == 0)
+ out.push_back(std::string(chars, chars+len)); // handles Unicode poorly
+ }
+
+ // Recurse up the prototype chain
+ JSObject* prototype = JS_GetPrototype(m->m_cx, JSVAL_TO_OBJECT(obj));
+ if (prototype)
+ {
+ if (! EnumeratePropertyNamesWithPrefix(OBJECT_TO_JSVAL(prototype), prefix, out))
+ return false;
+ }
+
+ return true;
+}
+
+bool ScriptInterface::SetPrototype(jsval obj, jsval proto)
+{
+ if (!JSVAL_IS_OBJECT(obj) || !JSVAL_IS_OBJECT(proto))
+ return false;
+ return JS_SetPrototype(m->m_cx, JSVAL_TO_OBJECT(obj), JSVAL_TO_OBJECT(proto)) ? true : false;
+}
+
+bool ScriptInterface::LoadScript(const std::wstring& filename, const std::wstring& code)
+{
+ std::string fnAscii(filename.begin(), filename.end());
+ utf16string codeUtf16(code.begin(), code.end());
+ jsval rval;
+ JSBool ok = ::LoadScript(m->m_cx, reinterpret_cast (codeUtf16.c_str()), (uintN)(codeUtf16.length()),
+ fnAscii.c_str(), &rval);
+ return ok ? true : false;
+}
+
+bool ScriptInterface::Eval(const char* code)
+{
+ jsval rval;
+ return Eval_(code, rval);
+}
+
+bool ScriptInterface::Eval_(const char* code, jsval& rval)
+{
+ utf16string codeUtf16(code, code+strlen(code));
+
+ JSBool ok = JS_EvaluateUCScript(m->m_cx, m->m_glob, (const jschar*)codeUtf16.c_str(), (uintN)codeUtf16.length(), "(eval)", 1, &rval);
+ return ok ? true : false;
+}
+
+void ScriptInterface::ReportError(const char* msg)
+{
+ // JS_ReportError by itself doesn't seem to set a JS-style exception, and so
+ // script callers will be unable to catch anything. So use JS_SetPendingException
+ // to make sure there really is a script-level exception. But just set it to undefined
+ // because there's not much value yet in throwing a real exception object.
+ JS_SetPendingException(m->m_cx, JSVAL_VOID);
+ // And report the actual error
+ JS_ReportError(m->m_cx, "%s", msg);
+
+ // TODO: Why doesn't JS_ReportPendingException(m->m_cx); work?
+}
+
+bool ScriptInterface::IsExceptionPending(JSContext* cx)
+{
+ return JS_IsExceptionPending(cx) ? true : false;
+}
+
+JSClass* ScriptInterface::GetClass(JSContext* cx, JSObject* obj)
+{
+ return JS_GetClass(cx, obj);
+}
+
+void* ScriptInterface::GetPrivate(JSContext* cx, JSObject* obj)
+{
+ // TODO: use JS_GetInstancePrivate
+ return JS_GetPrivate(cx, obj);
+}
diff --git a/source/scriptinterface/ScriptInterface.h b/source/scriptinterface/ScriptInterface.h
new file mode 100644
index 0000000000..6eab37b29f
--- /dev/null
+++ b/source/scriptinterface/ScriptInterface.h
@@ -0,0 +1,306 @@
+/* Copyright (C) 2009 Wildfire Games.
+ * This file is part of 0 A.D.
+ *
+ * 0 A.D. is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * 0 A.D. is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with 0 A.D. If not, see .
+ */
+
+#ifndef INCLUDED_SCRIPTINTERFACE
+#define INCLUDED_SCRIPTINTERFACE
+
+// XXX: This is largely copied from tools/atlas/AtlasScript
+// Duplication is bad - they should use a shared version of the common code,
+// and just add their own extensions individually
+
+#include
+#include
+#include
+
+#include "ScriptTypes.h"
+#include "ScriptVal.h"
+
+// Set the maximum number of function arguments that can be handled
+// (This should be as small as possible (for compiler efficiency),
+// but as large as necessary for all wrapped functions)
+#define SCRIPT_INTERFACE_MAX_ARGS 4
+
+struct ScriptInterface_impl;
+class ScriptClass;
+class ScriptInterface
+{
+public:
+
+ /**
+ * Constructor.
+ * @param nativeScopeName Name of global object that functions (via RegisterFunction) will
+ * be placed into, as a scoping mechanism; typically "Engine"
+ * @param cx NULL if the object should create and manage its own context; otherwise
+ * an existing context which it will share
+ */
+ ScriptInterface(const char* nativeScopeName, JSContext* cx = NULL);
+
+ ~ScriptInterface();
+
+ /**
+ * Shut down the JS system to clean up memory. Must only be called when there
+ * are no ScriptInterfaces alive.
+ */
+ static void ShutDown();
+
+ void SetCallbackData(void* cbdata);
+ static void* GetCallbackData(JSContext* cx);
+
+ JSContext* GetContext();
+
+ /**
+ * Call a constructor function, roughly equivalent to JS "new ctor".
+ *
+ * @return The new object; or 0 on failure, and logs an error message
+ */
+ jsval CallConstructor(jsval ctor);
+
+ /**
+ * Call the named property on the given object, with void return type and 0 arguments
+ */
+ bool CallFunctionVoid(jsval val, const char* name);
+
+ /**
+ * Call the named property on the given object, with void return type and 1 argument
+ */
+ template
+ bool CallFunctionVoid(jsval val, const char* name, const T0& a0);
+
+ /**
+ * Call the named property on the given object, with void return type and 2 arguments
+ */
+ template
+ bool CallFunctionVoid(jsval val, const char* name, const T0& a0, const T1& a1);
+
+ /**
+ * Call the named property on the given object, with return type R and 0 arguments
+ */
+ template
+ bool CallFunction(jsval val, const char* name, R& ret);
+
+ /**
+ * Call the named property on the given object, with return type R and 1 argument
+ */
+ template
+ bool CallFunction(jsval val, const char* name, const T0& a0, R& ret);
+
+ /**
+ * Call the named property on the given object, with return type R and 2 arguments
+ */
+ template
+ bool CallFunction(jsval val, const char* name, const T0& a0, const T1& a1, R& ret);
+
+ jsval GetGlobalObject();
+
+ /**
+ * Set the named property on the global object
+ */
+ template
+ bool SetGlobal(const char* name, const T& value);
+
+ /**
+ * Set the named property on the given object.
+ * Optionally makes it {ReadOnly, DontDelete, DontEnum}.
+ */
+ template
+ bool SetProperty(jsval obj, const char* name, const T& value, bool constant);
+
+ template
+ bool GetProperty(jsval obj, const char* name, T& out);
+
+ bool EnumeratePropertyNamesWithPrefix(jsval obj, const char* prefix, std::vector& out);
+
+ bool SetPrototype(jsval obj, jsval proto);
+
+ bool Eval(const char* code);
+
+ template bool Eval(const char* code, T& out);
+
+ /**
+ * Report the given error message through the JS error reporting mechanism,
+ * and throw a JS exception. (Callers can check IsPendingException, and must
+ * return JS_FALSE in that case to propagate the exception.)
+ */
+ void ReportError(const char* msg);
+
+ /**
+ * Load and execute the given script in a new function scope.
+ * @param filename Name for debugging purposes (not used to load the file)
+ * @param code JS code to execute
+ * @return true on successful compilation and execution; false otherwise
+ */
+ bool LoadScript(const std::wstring& filename, const std::wstring& code);
+
+ /**
+ * Convert a jsval to a C++ type. (This might trigger GC.)
+ */
+ template static bool FromJSVal(JSContext* cx, jsval val, T& ret);
+
+ /**
+ * Convert a C++ type to a jsval. (This might trigger GC. The return
+ * value must be rooted if you don't want it to be collected.)
+ */
+ template static jsval ToJSVal(JSContext* cx, T const& val);
+
+ bool AddRoot(void* ptr, const char* name);
+ bool RemoveRoot(void* ptr);
+
+ // Helper class for automatically rooting values
+ class LocalRootScope
+ {
+ JSContext* m_cx;
+ bool m_OK;
+ public:
+ // Tries to enter local root scope, so newly created
+ // values won't be GCed. This might fail, so check OK()
+ LocalRootScope(JSContext* cx);
+ // Returns true if the local root scope was successfully entered
+ bool OK();
+ // Leaves the local root scope
+ ~LocalRootScope();
+ private:
+ LocalRootScope& operator=(const LocalRootScope&);
+ };
+#define LOCAL_ROOT_SCOPE LocalRootScope scope(GetContext()); if (! scope.OK()) return false
+
+private:
+ bool CallFunction_(jsval val, const char* name, std::vector& args, jsval& ret);
+ bool Eval_(const char* code, jsval& ret);
+ bool SetGlobal_(const char* name, jsval value);
+ bool SetProperty_(jsval obj, const char* name, jsval value, bool readonly);
+ bool GetProperty_(jsval obj, const char* name, jsval& value);
+ static bool IsExceptionPending(JSContext* cx);
+ static JSClass* GetClass(JSContext* cx, JSObject* obj);
+ static void* GetPrivate(JSContext* cx, JSObject* obj);
+
+ void Register(const char* name, JSNative fptr, size_t nargs);
+ std::auto_ptr m;
+
+// The nasty macro/template bits are split into a separate file so you don't have to look at them
+public:
+ #include "NativeWrapperDecls.h"
+ // This declares:
+ //
+ // template
+ // void RegisterFunction(const char* functionName);
+ //
+ // template
+ // static JSNative call;
+ //
+ // template
+ // static JSNative callMethod;
+ //
+ // template
+ // static size_t nargs();
+};
+
+// Implement those declared functions
+#include "NativeWrapperDefns.h"
+
+template
+bool ScriptInterface::CallFunction(jsval val, const char* name, R& ret)
+{
+ LOCAL_ROOT_SCOPE;
+ jsval jsRet;
+ std::vector argv;
+ bool ok = CallFunction_(val, name, argv, jsRet);
+ if (!ok)
+ return false;
+ return FromJSVal(GetContext(), jsRet, ret);
+}
+
+template
+bool ScriptInterface::CallFunctionVoid(jsval val, const char* name, const T0& a0)
+{
+ LOCAL_ROOT_SCOPE;
+ jsval jsRet;
+ std::vector argv;
+ argv.push_back(ToJSVal(GetContext(), a0));
+ return CallFunction_(val, name, argv, jsRet);
+}
+
+template
+bool ScriptInterface::CallFunctionVoid(jsval val, const char* name, const T0& a0, const T1& a1)
+{
+ LOCAL_ROOT_SCOPE;
+ jsval jsRet;
+ std::vector argv;
+ argv.push_back(ToJSVal(GetContext(), a0));
+ argv.push_back(ToJSVal(GetContext(), a1));
+ return CallFunction_(val, name, argv, jsRet);
+}
+
+template
+bool ScriptInterface::CallFunction(jsval val, const char* name, const T0& a0, R& ret)
+{
+ LOCAL_ROOT_SCOPE;
+ jsval jsRet;
+ std::vector argv;
+ argv.push_back(ToJSVal(GetContext(), a0));
+ bool ok = CallFunction_(val, name, argv, jsRet);
+ if (!ok)
+ return false;
+ return FromJSVal(GetContext(), jsRet, ret);
+}
+
+template
+bool ScriptInterface::CallFunction(jsval val, const char* name, const T0& a0, const T1& a1, R& ret)
+{
+ LOCAL_ROOT_SCOPE;
+ jsval jsRet;
+ std::vector argv;
+ argv.push_back(ToJSVal(GetContext(), a0));
+ argv.push_back(ToJSVal(GetContext(), a1));
+ bool ok = CallFunction_(val, name, argv, jsRet);
+ if (!ok)
+ return false;
+ return FromJSVal(GetContext(), jsRet, ret);
+}
+
+template
+bool ScriptInterface::SetGlobal(const char* name, const T& value)
+{
+ LOCAL_ROOT_SCOPE;
+ return SetGlobal_(name, ToJSVal(GetContext(), value));
+}
+
+template
+bool ScriptInterface::SetProperty(jsval obj, const char* name, const T& value, bool readonly)
+{
+ LOCAL_ROOT_SCOPE;
+ return SetProperty_(obj, name, ToJSVal(GetContext(), value), readonly);
+}
+
+template
+bool ScriptInterface::GetProperty(jsval obj, const char* name, T& out)
+{
+ jsval val;
+ if (! GetProperty_(obj, name, val))
+ return false;
+ return FromJSVal(GetContext(), val, out);
+}
+
+template
+bool ScriptInterface::Eval(const char* code, T& ret)
+{
+ jsval rval;
+ if (! Eval_(code, rval))
+ return false;
+ return FromJSVal(GetContext(), rval, ret);
+}
+
+#endif // INCLUDED_SCRIPTINTERFACE
diff --git a/source/scriptinterface/ScriptTypes.h b/source/scriptinterface/ScriptTypes.h
new file mode 100644
index 0000000000..8aeb1dfd6a
--- /dev/null
+++ b/source/scriptinterface/ScriptTypes.h
@@ -0,0 +1,39 @@
+/* Copyright (C) 2009 Wildfire Games.
+ * This file is part of 0 A.D.
+ *
+ * 0 A.D. is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * 0 A.D. is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with 0 A.D. If not, see .
+ */
+
+#ifndef INCLUDED_SCRIPTTYPES
+#define INCLUDED_SCRIPTTYPES
+
+#ifdef _WIN32
+# define XP_WIN
+#else
+# define XP_UNIX
+#endif
+// (we don't support XP_OS2 or XP_BEOS)
+
+#include "js/jspubtd.h"
+
+#if JS_VERSION <= 160
+// 1.6 doesn't support the standards-conforming globals behaviour,
+// so we can't use this flag there
+# define JSCLASS_GLOBAL_FLAGS 0
+#endif
+
+class ScriptInterface;
+class CScriptVal;
+
+#endif // INCLUDED_SCRIPTTYPES
diff --git a/source/scriptinterface/ScriptVal.cpp b/source/scriptinterface/ScriptVal.cpp
new file mode 100644
index 0000000000..23b02e6386
--- /dev/null
+++ b/source/scriptinterface/ScriptVal.cpp
@@ -0,0 +1,50 @@
+/* Copyright (C) 2009 Wildfire Games.
+ * This file is part of 0 A.D.
+ *
+ * 0 A.D. is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * 0 A.D. is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with 0 A.D. If not, see .
+ */
+
+#include "precompiled.h"
+
+#include "ScriptVal.h"
+
+#include "js/jsapi.h"
+
+struct Unrooter
+{
+ Unrooter(JSContext* cx) : cx(cx) { }
+ void operator()(jsval* p) { JS_RemoveRoot(cx, p); delete p; }
+ JSContext* cx;
+};
+
+CScriptValRooted::CScriptValRooted(JSContext* cx, jsval val)
+{
+ jsval* p = new jsval(val);
+ JS_AddNamedRoot(cx, p, "CScriptValRooted");
+ m_Val = boost::shared_ptr(p, Unrooter(cx));
+}
+
+CScriptValRooted::CScriptValRooted(JSContext* cx, CScriptVal val)
+{
+ jsval* p = new jsval(val.get());
+ JS_AddNamedRoot(cx, p, "CScriptValRooted");
+ m_Val = boost::shared_ptr(p, Unrooter(cx));
+}
+
+jsval CScriptValRooted::get() const
+{
+ if (!m_Val)
+ return JSVAL_VOID;
+ return *m_Val;
+}
diff --git a/source/scriptinterface/ScriptVal.h b/source/scriptinterface/ScriptVal.h
new file mode 100644
index 0000000000..b2a2091fc0
--- /dev/null
+++ b/source/scriptinterface/ScriptVal.h
@@ -0,0 +1,54 @@
+/* Copyright (C) 2009 Wildfire Games.
+ * This file is part of 0 A.D.
+ *
+ * 0 A.D. is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * 0 A.D. is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with 0 A.D. If not, see .
+ */
+
+#ifndef INCLUDED_SCRIPTVAL
+#define INCLUDED_SCRIPTVAL
+
+#include "ScriptTypes.h"
+#include
+
+/**
+ * A trivial wrapper around a jsval. Used to avoid template overload ambiguities
+ * with jsval (which is just an integer), for any code that uses
+ * ScriptInterface::ToJSVal or ScriptInterface::FromJSVal
+ */
+class CScriptVal
+{
+public:
+ CScriptVal() : m_Val(0) { }
+ CScriptVal(jsval val) : m_Val(val) { }
+
+ jsval get() const { return m_Val; }
+
+private:
+ jsval m_Val;
+};
+
+class CScriptValRooted
+{
+public:
+ CScriptValRooted() { }
+ CScriptValRooted(JSContext* cx, jsval val);
+ CScriptValRooted(JSContext* cx, CScriptVal val);
+
+ jsval get() const;
+
+private:
+ boost::shared_ptr m_Val;
+};
+
+#endif // INCLUDED_SCRIPTVAL
diff --git a/source/scriptinterface/tests/test_ScriptConversions.h b/source/scriptinterface/tests/test_ScriptConversions.h
new file mode 100644
index 0000000000..21d8393b52
--- /dev/null
+++ b/source/scriptinterface/tests/test_ScriptConversions.h
@@ -0,0 +1,178 @@
+/* Copyright (C) 2010 Wildfire Games.
+ * This file is part of 0 A.D.
+ *
+ * 0 A.D. is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * 0 A.D. is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with 0 A.D. If not, see .
+ */
+
+#include "lib/self_test.h"
+
+#include "scriptinterface/ScriptInterface.h"
+
+#include "maths/Fixed.h"
+#include "maths/MathUtil.h"
+
+#include "js/jsapi.h"
+
+class TestScriptConversions : public CxxTest::TestSuite
+{
+ template
+ void convert_to(const T& value, const std::string& expected)
+ {
+ ScriptInterface script("Test");
+ JSContext* cx = script.GetContext();
+
+ jsval v1 = ScriptInterface::ToJSVal(cx, value);
+ JS_AddRoot(cx, &v1);
+
+ // We want to convert values to strings, but can't just call toSource() on them
+ // since they might not be objects. So just use uneval.
+ std::string source;
+ TS_ASSERT(script.CallFunction(OBJECT_TO_JSVAL(JS_GetGlobalObject(cx)), "uneval", CScriptVal(v1), source));
+
+ TS_ASSERT_STR_EQUALS(source, expected);
+
+ JS_RemoveRoot(cx, &v1);
+ }
+
+ template
+ void roundtrip(const T& value, const std::string& expected)
+ {
+ ScriptInterface script("Test");
+ JSContext* cx = script.GetContext();
+
+ jsval v1 = ScriptInterface::ToJSVal(cx, value);
+ JS_AddRoot(cx, &v1);
+
+ std::string source;
+ TS_ASSERT(script.CallFunction(OBJECT_TO_JSVAL(JS_GetGlobalObject(cx)), "uneval", CScriptVal(v1), source));
+
+ TS_ASSERT_STR_EQUALS(source, expected);
+
+ T v2 = T();
+ TS_ASSERT(ScriptInterface::FromJSVal(script.GetContext(), v1, v2));
+ TS_ASSERT_EQUALS(value, v2);
+
+ JS_RemoveRoot(cx, &v1);
+ }
+
+public:
+ void test_roundtrip()
+ {
+ roundtrip(true, "true");
+ roundtrip(false, "false");
+
+ roundtrip(0, "0");
+ roundtrip(0.5, "0.5");
+ roundtrip(1e9f, "1000000000");
+ roundtrip(1e30f, "1.0000000150474662e+30");
+
+ roundtrip(0, "0");
+ roundtrip(123, "123");
+ roundtrip(-123, "-123");
+ roundtrip(1073741822, "1073741822"); // JSVAL_INT_MAX-1
+ roundtrip(1073741823, "1073741823"); // JSVAL_INT_MAX
+ roundtrip(1073741824, "1073741824"); // JSVAL_INT_MAX+1
+#if JS_VERSION >= 180
+ roundtrip(-1073741823, "-1073741823"); // JSVAL_INT_MIN+1
+ roundtrip(-1073741824, "-1073741824"); // JSVAL_INT_MIN
+ roundtrip(-1073741825, "-1073741825"); // JSVAL_INT_MIN-1
+#else
+ roundtrip(-1073741822, "-1073741822"); // JSVAL_INT_MIN+1
+ roundtrip(-1073741823, "-1073741823"); // JSVAL_INT_MIN
+ roundtrip(-1073741824, "-1073741824"); // JSVAL_INT_MIN-1
+#endif
+
+ roundtrip(0, "0");
+ roundtrip(123, "123");
+ roundtrip(1073741822, "1073741822"); // JSVAL_INT_MAX-1
+ roundtrip(1073741823, "1073741823"); // JSVAL_INT_MAX
+ roundtrip(1073741824, "1073741824"); // JSVAL_INT_MAX+1
+
+ std::string s1 = "test";
+ s1[1] = '\0';
+
+ std::wstring w1 = L"test";
+ w1[1] = '\0';
+
+ roundtrip("", "\"\"");
+ roundtrip("test", "\"test\"");
+#if JS_VERSION >= 180
+ roundtrip(s1, "\"t\\0st\"");
+#else
+ roundtrip(s1, "\"t\\x00st\"");
+#endif
+ // TODO: should test non-ASCII strings
+
+ roundtrip(L"", "\"\"");
+ roundtrip(L"test", "\"test\"");
+#if JS_VERSION >= 180
+ roundtrip(w1, "\"t\\0st\"");
+#else
+ roundtrip(w1, "\"t\\x00st\"");
+#endif
+ // TODO: should test non-ASCII strings
+
+ convert_to("", "\"\"");
+ convert_to("test", "\"test\"");
+ convert_to(s1.c_str(), "\"t\"");
+
+ roundtrip(CFixed_23_8::FromInt(0), "0");
+ roundtrip(CFixed_23_8::FromInt(123), "123");
+ roundtrip(CFixed_23_8::FromInt(-123), "-123");
+ roundtrip(CFixed_23_8::FromDouble(123.25), "123.25");
+ }
+
+ void test_integers()
+ {
+ ScriptInterface script("Test");
+ JSContext* cx = script.GetContext();
+
+ TS_ASSERT(JSVAL_IS_INT(ScriptInterface::ToJSVal(cx, 0)));
+
+ TS_ASSERT(JSVAL_IS_INT(ScriptInterface::ToJSVal(cx, 1073741822))); // JSVAL_INT_MAX-1
+ TS_ASSERT(JSVAL_IS_INT(ScriptInterface::ToJSVal