summary refs log tree commit diff stats
diff options
context:
space:
mode:
-rw-r--r--CMakeLists.txt2
-rw-r--r--res/platform.lua24
-rw-r--r--scripts/checkpoint.lua17
-rw-r--r--scripts/common.lua21
-rw-r--r--scripts/movplat.lua8
-rw-r--r--src/components/automatable.h25
-rw-r--r--src/components/playable.h3
-rw-r--r--src/components/ponderable.h3
-rw-r--r--src/components/prototypable.h22
-rw-r--r--src/components/realizable.h3
-rw-r--r--src/components/runnable.h15
-rw-r--r--src/game.cpp4
-rw-r--r--src/systems/automating.cpp106
-rw-r--r--src/systems/automating.h22
-rw-r--r--src/systems/pondering.cpp13
-rw-r--r--src/systems/realizing.cpp66
-rw-r--r--src/systems/scripting.cpp219
-rw-r--r--src/systems/scripting.h28
18 files changed, 393 insertions, 208 deletions
diff --git a/CMakeLists.txt b/CMakeLists.txt index fbc843c..837df0d 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt
@@ -70,7 +70,7 @@ add_executable(Aromatherapy
70 src/systems/playing.cpp 70 src/systems/playing.cpp
71 src/systems/scheduling.cpp 71 src/systems/scheduling.cpp
72 src/systems/realizing.cpp 72 src/systems/realizing.cpp
73 src/systems/automating.cpp 73 src/systems/scripting.cpp
74 vendor/stb_image.cpp 74 vendor/stb_image.cpp
75) 75)
76 76
diff --git a/res/platform.lua b/res/platform.lua deleted file mode 100644 index 5200e22..0000000 --- a/res/platform.lua +++ /dev/null
@@ -1,24 +0,0 @@
1function moveLeft(entity, len, speed)
2 local remaining = len / speed
3
4 while (remaining > 0) do
5 entity:ponderable().vel.x = -speed
6 remaining = remaining - coroutine.yield()
7 end
8end
9
10function moveRight(entity, len, speed)
11 local remaining = len / speed
12
13 while (remaining > 0) do
14 entity:ponderable().vel.x = speed
15 remaining = remaining - coroutine.yield()
16 end
17end
18
19function run(entity)
20 while true do
21 moveRight(entity, 90, 30)
22 moveLeft(entity, 90, 30)
23 end
24end \ No newline at end of file
diff --git a/scripts/checkpoint.lua b/scripts/checkpoint.lua new file mode 100644 index 0000000..452f81d --- /dev/null +++ b/scripts/checkpoint.lua
@@ -0,0 +1,17 @@
1checkpoint = {}
2
3function checkpoint.OnTouch(id, player)
4 curMap = entity.new(realizing():singleton():realizable().activeMap)
5
6 if not player:playable().checkpointMapObject or
7 not curMap:mappable().mapId == player:playable().checkpointMapId or
8 not id:prototypable().mapObjectIndex ==
9 player:playable().checkpointMapObjectIndex then
10
11 player:playable().checkpointMapObject = true
12 player:playable().checkpointMapId = curMap:mappable().mapId
13 player:playable().checkpointMapObjectIndex =
14 id:prototypable().mapObjectIndex
15 player:playable().checkpointPos = player:transformable().pos
16 end
17end
diff --git a/scripts/common.lua b/scripts/common.lua new file mode 100644 index 0000000..d84d97d --- /dev/null +++ b/scripts/common.lua
@@ -0,0 +1,21 @@
1function waitForTick()
2 return coroutine.yield()
3end
4
5function moveLeft(id, len, speed)
6 local remaining = len / speed
7
8 while (remaining > 0) do
9 id:ponderable().vel.x = -speed
10 remaining = remaining - waitForTick()
11 end
12end
13
14function moveRight(id, len, speed)
15 local remaining = len / speed
16
17 while (remaining > 0) do
18 id:ponderable().vel.x = speed
19 remaining = remaining - waitForTick()
20 end
21end
diff --git a/scripts/movplat.lua b/scripts/movplat.lua new file mode 100644 index 0000000..21cc61a --- /dev/null +++ b/scripts/movplat.lua
@@ -0,0 +1,8 @@
1movplat = {}
2
3function movplat.Behavior(id)
4 while true do
5 moveRight(id, 90, 30)
6 moveLeft(id, 90, 30)
7 end
8end
diff --git a/src/components/automatable.h b/src/components/automatable.h deleted file mode 100644 index d30340a..0000000 --- a/src/components/automatable.h +++ /dev/null
@@ -1,25 +0,0 @@
1#ifndef AUTOMATABLE_H_3D519131
2#define AUTOMATABLE_H_3D519131
3
4#include "component.h"
5#include <sol.hpp>
6#include <memory>
7
8class AutomatableComponent : public Component {
9public:
10
11 std::unique_ptr<sol::thread> runner;
12 std::unique_ptr<sol::coroutine> behavior;
13
14 sol::environment origBehavior;
15
16 /**
17 * If this flag is disabled, the entity will be ignored by the automating
18 * system.
19 *
20 * @managed_by RealizingSystem
21 */
22 bool active = false;
23};
24
25#endif /* end of include guard: AUTOMATABLE_H_3D519131 */
diff --git a/src/components/playable.h b/src/components/playable.h index b8af0f2..7404f1f 100644 --- a/src/components/playable.h +++ b/src/components/playable.h
@@ -27,6 +27,9 @@ public:
27 size_t checkpointMapId; 27 size_t checkpointMapId;
28 vec2d checkpointPos; 28 vec2d checkpointPos;
29 29
30 bool checkpointMapObject = false;
31 size_t checkpointMapObjectIndex;
32
30}; 33};
31 34
32#endif /* end of include guard: PLAYABLE_H_DDC566C3 */ 35#endif /* end of include guard: PLAYABLE_H_DDC566C3 */
diff --git a/src/components/ponderable.h b/src/components/ponderable.h index e6aa976..221d267 100644 --- a/src/components/ponderable.h +++ b/src/components/ponderable.h
@@ -34,7 +34,8 @@ public:
34 platform, 34 platform,
35 adjacency, 35 adjacency,
36 warp, 36 warp,
37 danger 37 danger,
38 event
38 }; 39 };
39 40
40 /** 41 /**
diff --git a/src/components/prototypable.h b/src/components/prototypable.h new file mode 100644 index 0000000..4659e7c --- /dev/null +++ b/src/components/prototypable.h
@@ -0,0 +1,22 @@
1#ifndef PROTOTYPABLE_H_817F2205
2#define PROTOTYPABLE_H_817F2205
3
4#include "component.h"
5#include "entity_manager.h"
6
7class PrototypableComponent : public Component {
8public:
9
10 using id_type = EntityManager::id_type;
11
12 size_t mapObjectIndex;
13
14 std::string prototypeId;
15
16 bool hasBehavior = false;
17 bool runningBehavior = false;
18
19 id_type behaviorScript;
20};
21
22#endif /* end of include guard: PROTOTYPABLE_H_817F2205 */
diff --git a/src/components/realizable.h b/src/components/realizable.h index bc834a2..b749aeb 100644 --- a/src/components/realizable.h +++ b/src/components/realizable.h
@@ -4,7 +4,6 @@
4#include "component.h" 4#include "component.h"
5#include <set> 5#include <set>
6#include <map> 6#include <map>
7#include <sol.hpp>
8#include "entity_manager.h" 7#include "entity_manager.h"
9#include "vector.h" 8#include "vector.h"
10 9
@@ -70,8 +69,6 @@ public:
70 * The entity ID of the currently active player. 69 * The entity ID of the currently active player.
71 */ 70 */
72 id_type activePlayer; 71 id_type activePlayer;
73
74 sol::state scriptEngine;
75}; 72};
76 73
77#endif /* end of include guard: REALIZABLE_H_36D8D71E */ 74#endif /* end of include guard: REALIZABLE_H_36D8D71E */
diff --git a/src/components/runnable.h b/src/components/runnable.h new file mode 100644 index 0000000..1b994fb --- /dev/null +++ b/src/components/runnable.h
@@ -0,0 +1,15 @@
1#ifndef AUTOMATABLE_H_3D519131
2#define AUTOMATABLE_H_3D519131
3
4#include "component.h"
5#include <sol.hpp>
6#include <memory>
7
8class RunnableComponent : public Component {
9public:
10
11 std::unique_ptr<sol::thread> runner;
12 std::unique_ptr<sol::coroutine> callable;
13};
14
15#endif /* end of include guard: AUTOMATABLE_H_3D519131 */
diff --git a/src/game.cpp b/src/game.cpp index bf2b10b..f2992e1 100644 --- a/src/game.cpp +++ b/src/game.cpp
@@ -12,7 +12,7 @@
12#include "systems/playing.h" 12#include "systems/playing.h"
13#include "systems/scheduling.h" 13#include "systems/scheduling.h"
14#include "systems/realizing.h" 14#include "systems/realizing.h"
15#include "systems/automating.h" 15#include "systems/scripting.h"
16#include "animation.h" 16#include "animation.h"
17#include "consts.h" 17#include "consts.h"
18 18
@@ -36,7 +36,7 @@ Game::Game(std::mt19937& rng) : rng_(rng)
36 systemManager_.emplaceSystem<PlayingSystem>(*this); 36 systemManager_.emplaceSystem<PlayingSystem>(*this);
37 systemManager_.emplaceSystem<SchedulingSystem>(*this); 37 systemManager_.emplaceSystem<SchedulingSystem>(*this);
38 systemManager_.emplaceSystem<ControllingSystem>(*this); 38 systemManager_.emplaceSystem<ControllingSystem>(*this);
39 systemManager_.emplaceSystem<AutomatingSystem>(*this); 39 systemManager_.emplaceSystem<ScriptingSystem>(*this);
40 systemManager_.emplaceSystem<OrientingSystem>(*this); 40 systemManager_.emplaceSystem<OrientingSystem>(*this);
41 systemManager_.emplaceSystem<PonderingSystem>(*this); 41 systemManager_.emplaceSystem<PonderingSystem>(*this);
42 systemManager_.emplaceSystem<MappingSystem>(*this); 42 systemManager_.emplaceSystem<MappingSystem>(*this);
diff --git a/src/systems/automating.cpp b/src/systems/automating.cpp deleted file mode 100644 index 4a5357d..0000000 --- a/src/systems/automating.cpp +++ /dev/null
@@ -1,106 +0,0 @@
1#include "automating.h"
2#include "game.h"
3#include "components/automatable.h"
4#include "components/ponderable.h"
5#include "components/realizable.h"
6#include "components/transformable.h"
7#include "systems/realizing.h"
8#include "vector.h"
9
10struct script_entity {
11 using id_type = EntityManager::id_type;
12
13 id_type id;
14
15 script_entity(id_type id) : id(id)
16 {
17 }
18};
19
20void AutomatingSystem::tick(double dt)
21{
22 auto entities = game_.getEntityManager().getEntitiesWithComponents<
23 AutomatableComponent>();
24
25 for (id_type entity : entities)
26 {
27 auto& automatable = game_.getEntityManager().
28 getComponent<AutomatableComponent>(entity);
29
30 if (!automatable.active)
31 {
32 continue;
33 }
34
35 auto result = (*automatable.behavior)(dt);
36 if (!result.valid())
37 {
38 sol::error e = result;
39 throw std::runtime_error(e.what());
40 }
41 }
42}
43
44void AutomatingSystem::initPrototype(id_type prototype)
45{
46 auto& automatable = game_.getEntityManager().
47 getComponent<AutomatableComponent>(prototype);
48
49 auto& realizable = game_.getEntityManager().
50 getComponent<RealizableComponent>(
51 game_.getSystemManager().getSystem<RealizingSystem>().getSingleton());
52 automatable.behavior.reset();
53 automatable.runner = std::unique_ptr<sol::thread>(new sol::thread(sol::thread::create(realizable.scriptEngine.lua_state())));
54 automatable.behavior = std::unique_ptr<sol::coroutine>(new sol::coroutine(automatable.runner->state()["run"]));
55
56 auto result = (*automatable.behavior)(script_entity(prototype));
57 if (!result.valid())
58 {
59 sol::error e = result;
60 throw std::runtime_error(e.what());
61 }
62}
63
64void AutomatingSystem::initScriptEngine(sol::state& scriptEngine)
65{
66 scriptEngine.open_libraries(sol::lib::base, sol::lib::coroutine);
67 scriptEngine.new_usertype<vec2d>(
68 "vec2d",
69 sol::constructors<vec2d(), vec2d(double, double)>(),
70 "x", sol::property(
71 [] (vec2d& v) -> double { return v.x(); },
72 [] (vec2d& v, double x) { v.x() = x; }),
73 "y", sol::property(
74 [] (vec2d& v) -> double { return v.y(); },
75 [] (vec2d& v, double y) { v.y() = y; }));
76
77 scriptEngine.new_usertype<vec2i>(
78 "vec2i",
79 sol::constructors<vec2i(), vec2i(int, int)>(),
80 "x", [] (vec2i& v) -> int& { return v.x(); },
81 "y", [] (vec2i& v) -> int& { return v.y(); });
82
83 scriptEngine.new_usertype<script_entity>(
84 "entity",
85 sol::constructors<script_entity(id_type)>(),
86 "id", &script_entity::id,
87 "transformable",
88 [&] (script_entity& entity) -> TransformableComponent& {
89 return game_.getEntityManager().
90 getComponent<TransformableComponent>(entity.id);
91 },
92 "ponderable",
93 [&] (script_entity& entity) -> PonderableComponent& {
94 return game_.getEntityManager().
95 getComponent<PonderableComponent>(entity.id);
96 });
97
98 scriptEngine.new_usertype<TransformableComponent>(
99 "transformable",
100 "pos", &TransformableComponent::pos);
101
102 scriptEngine.new_usertype<PonderableComponent>(
103 "ponderable",
104 "vel", &PonderableComponent::vel,
105 "accel", &PonderableComponent::accel);
106}
diff --git a/src/systems/automating.h b/src/systems/automating.h deleted file mode 100644 index 117b622..0000000 --- a/src/systems/automating.h +++ /dev/null
@@ -1,22 +0,0 @@
1#ifndef AUTOMATING_H_E6E5D76E
2#define AUTOMATING_H_E6E5D76E
3
4#include "system.h"
5#include <sol.hpp>
6
7class AutomatingSystem : public System {
8public:
9
10 AutomatingSystem(Game& game) : System(game)
11 {
12 }
13
14 void tick(double dt);
15
16 void initPrototype(id_type prototype);
17
18 void initScriptEngine(sol::state& scriptEngine);
19
20};
21
22#endif /* end of include guard: AUTOMATING_H_E6E5D76E */
diff --git a/src/systems/pondering.cpp b/src/systems/pondering.cpp index c806cc8..a3eb36d 100644 --- a/src/systems/pondering.cpp +++ b/src/systems/pondering.cpp
@@ -11,6 +11,7 @@
11#include "systems/orienting.h" 11#include "systems/orienting.h"
12#include "systems/playing.h" 12#include "systems/playing.h"
13#include "systems/realizing.h" 13#include "systems/realizing.h"
14#include "systems/scripting.h"
14#include "consts.h" 15#include "consts.h"
15 16
16void PonderingSystem::tick(double dt) 17void PonderingSystem::tick(double dt)
@@ -857,6 +858,18 @@ void PonderingSystem::processCollision(
857 break; 858 break;
858 } 859 }
859 860
861 case PonderableComponent::Collision::event:
862 {
863 if (game_.getEntityManager().
864 hasComponent<PlayableComponent>(entity))
865 {
866 game_.getSystemManager().getSystem<ScriptingSystem>().
867 onTouch(collider, entity);
868 }
869
870 break;
871 }
872
860 default: 873 default:
861 { 874 {
862 // Not yet implemented. 875 // Not yet implemented.
diff --git a/src/systems/realizing.cpp b/src/systems/realizing.cpp index 28e2279..2ee5897 100644 --- a/src/systems/realizing.cpp +++ b/src/systems/realizing.cpp
@@ -12,11 +12,11 @@
12#include "components/playable.h" 12#include "components/playable.h"
13#include "components/ponderable.h" 13#include "components/ponderable.h"
14#include "components/transformable.h" 14#include "components/transformable.h"
15#include "components/automatable.h" 15#include "components/prototypable.h"
16#include "systems/mapping.h" 16#include "systems/mapping.h"
17#include "systems/animating.h" 17#include "systems/animating.h"
18#include "systems/pondering.h" 18#include "systems/pondering.h"
19#include "systems/automating.h" 19#include "systems/scripting.h"
20 20
21inline xmlChar* getProp(xmlNodePtr node, const char* attr) 21inline xmlChar* getProp(xmlNodePtr node, const char* attr)
22{ 22{
@@ -40,9 +40,6 @@ EntityManager::id_type RealizingSystem::initSingleton(
40 auto& realizable = game_.getEntityManager(). 40 auto& realizable = game_.getEntityManager().
41 emplaceComponent<RealizableComponent>(world); 41 emplaceComponent<RealizableComponent>(world);
42 42
43 game_.getSystemManager().getSystem<AutomatingSystem>().
44 initScriptEngine(realizable.scriptEngine);
45
46 realizable.worldFile = worldFile; 43 realizable.worldFile = worldFile;
47 realizable.prototypeFile = prototypeFile; 44 realizable.prototypeFile = prototypeFile;
48 45
@@ -216,14 +213,28 @@ EntityManager::id_type RealizingSystem::initSingleton(
216 game_.getSystemManager().getSystem<PonderingSystem>(). 213 game_.getSystemManager().getSystem<PonderingSystem>().
217 initializeBody(mapObject, PonderableComponent::Type::vacuumed); 214 initializeBody(mapObject, PonderableComponent::Type::vacuumed);
218 215
216
217
218
219
220 auto& prototypable = game_.getEntityManager().
221 emplaceComponent<PrototypableComponent>(mapObject);
222
223 prototypable.prototypeId = prototypeId;
224
225 key = getProp(mapNode, "index");
226 prototypable.mapObjectIndex = atoi(reinterpret_cast<char*>(key));
227 xmlFree(key);
228
219 if (prototypeId == "movplat") 229 if (prototypeId == "movplat")
220 { 230 {
221 auto& automatable = game_.getEntityManager(). 231 prototypable.hasBehavior = true;
222 emplaceComponent<AutomatableComponent>(mapObject); 232 } else if (prototypeId == "checkpoint")
223 233 {
234 auto& ponderable = game_.getEntityManager().
235 getComponent<PonderableComponent>(mapObject);
224 236
225 realizable.scriptEngine.script_file( 237 ponderable.colliderType = PonderableComponent::Collision::event;
226 "res/platform.lua");//,
227 } 238 }
228 239
229 mappable.objects.push_back(mapObject); 240 mappable.objects.push_back(mapObject);
@@ -319,7 +330,6 @@ void RealizingSystem::loadMap(id_type mapEntity)
319 330
320 auto& animating = game_.getSystemManager().getSystem<AnimatingSystem>(); 331 auto& animating = game_.getSystemManager().getSystem<AnimatingSystem>();
321 auto& pondering = game_.getSystemManager().getSystem<PonderingSystem>(); 332 auto& pondering = game_.getSystemManager().getSystem<PonderingSystem>();
322 auto& automating = game_.getSystemManager().getSystem<AutomatingSystem>();
323 333
324 std::set<id_type> players = 334 std::set<id_type> players =
325 game_.getEntityManager().getEntitiesWithComponents< 335 game_.getEntityManager().getEntitiesWithComponents<
@@ -380,11 +390,6 @@ void RealizingSystem::loadMap(id_type mapEntity)
380 pondering.initPrototype(prototype); 390 pondering.initPrototype(prototype);
381 } 391 }
382 392
383 if (game_.getEntityManager().hasComponent<AutomatableComponent>(prototype))
384 {
385 automating.initPrototype(prototype);
386 }
387
388 enterActiveMap(prototype); 393 enterActiveMap(prototype);
389 } 394 }
390 395
@@ -419,12 +424,19 @@ void RealizingSystem::enterActiveMap(id_type entity)
419 ponderable.active = true; 424 ponderable.active = true;
420 } 425 }
421 426
422 if (game_.getEntityManager().hasComponent<AutomatableComponent>(entity)) 427 if (game_.getEntityManager().hasComponent<PrototypableComponent>(entity))
423 { 428 {
424 auto& automatable = game_.getEntityManager(). 429 auto& prototypable = game_.getEntityManager().
425 getComponent<AutomatableComponent>(entity); 430 getComponent<PrototypableComponent>(entity);
431
432 if (prototypable.hasBehavior)
433 {
434 auto& scripting = game_.getSystemManager().getSystem<ScriptingSystem>();
426 435
427 automatable.active = true; 436 prototypable.hasBehavior = true;
437 prototypable.runningBehavior = true;
438 prototypable.behaviorScript = scripting.runBehaviorScript(entity);
439 }
428 } 440 }
429} 441}
430 442
@@ -446,11 +458,17 @@ void RealizingSystem::leaveActiveMap(id_type entity)
446 ponderable.active = false; 458 ponderable.active = false;
447 } 459 }
448 460
449 if (game_.getEntityManager().hasComponent<AutomatableComponent>(entity)) 461 if (game_.getEntityManager().hasComponent<PrototypableComponent>(entity))
450 { 462 {
451 auto& automatable = game_.getEntityManager(). 463 auto& prototypable = game_.getEntityManager().
452 getComponent<AutomatableComponent>(entity); 464 getComponent<PrototypableComponent>(entity);
453 465
454 automatable.active = false; 466 if (prototypable.runningBehavior)
467 {
468 auto& scripting = game_.getSystemManager().getSystem<ScriptingSystem>();
469 scripting.killScript(prototypable.behaviorScript);
470
471 prototypable.runningBehavior = false;
472 }
455 } 473 }
456} 474}
diff --git a/src/systems/scripting.cpp b/src/systems/scripting.cpp new file mode 100644 index 0000000..dc1fff5 --- /dev/null +++ b/src/systems/scripting.cpp
@@ -0,0 +1,219 @@
1#include "scripting.h"
2#include "game.h"
3#include "components/runnable.h"
4#include "components/ponderable.h"
5#include "components/realizable.h"
6#include "components/transformable.h"
7#include "components/playable.h"
8#include "components/mappable.h"
9#include "components/prototypable.h"
10#include "systems/realizing.h"
11#include "vector.h"
12
13struct script_entity {
14 using id_type = EntityManager::id_type;
15
16 id_type id;
17
18 script_entity(id_type id) : id(id)
19 {
20 }
21};
22
23ScriptingSystem::ScriptingSystem(Game& game) : System(game)
24{
25 id_type entity = game_.getEntityManager().emplaceEntity();
26
27 engine.open_libraries(sol::lib::base, sol::lib::coroutine);
28
29 engine.new_usertype<vec2d>(
30 "vec2d",
31 sol::constructors<vec2d(), vec2d(double, double)>(),
32 "x", sol::property(
33 [] (vec2d& v) -> double { return v.x(); },
34 [] (vec2d& v, double x) { v.x() = x; }),
35 "y", sol::property(
36 [] (vec2d& v) -> double { return v.y(); },
37 [] (vec2d& v, double y) { v.y() = y; }));
38
39 engine.new_usertype<vec2i>(
40 "vec2i",
41 sol::constructors<vec2i(), vec2i(int, int)>(),
42 "x", [] (vec2i& v) -> int& { return v.x(); },
43 "y", [] (vec2i& v) -> int& { return v.y(); });
44
45 engine.new_usertype<script_entity>(
46 "entity",
47 sol::constructors<script_entity(id_type)>(),
48 "id", &script_entity::id,
49 "transformable",
50 [&] (script_entity& entity) -> TransformableComponent& {
51 return game_.getEntityManager().
52 getComponent<TransformableComponent>(entity.id);
53 },
54 "ponderable",
55 [&] (script_entity& entity) -> PonderableComponent& {
56 return game_.getEntityManager().
57 getComponent<PonderableComponent>(entity.id);
58 },
59 "mappable",
60 [&] (script_entity& entity) -> MappableComponent& {
61 return game_.getEntityManager().
62 getComponent<MappableComponent>(entity.id);
63 },
64 "playable",
65 [&] (script_entity& entity) -> PlayableComponent& {
66 return game_.getEntityManager().
67 getComponent<PlayableComponent>(entity.id);
68 },
69 "realizable",
70 [&] (script_entity& entity) -> RealizableComponent& {
71 return game_.getEntityManager().
72 getComponent<RealizableComponent>(entity.id);
73 },
74 "prototypable",
75 [&] (script_entity& entity) -> PrototypableComponent& {
76 return game_.getEntityManager().
77 getComponent<PrototypableComponent>(entity.id);
78 });
79
80 engine.new_usertype<TransformableComponent>(
81 "transformable",
82 "pos", &TransformableComponent::pos);
83
84 engine.new_usertype<PonderableComponent>(
85 "ponderable",
86 "vel", &PonderableComponent::vel,
87 "accel", &PonderableComponent::accel);
88
89 engine.new_usertype<MappableComponent>(
90 "mappable",
91 "mapId", &MappableComponent::mapId);
92
93 engine.new_usertype<PlayableComponent>(
94 "playable",
95 "checkpointPos", &PlayableComponent::checkpointPos,
96 "checkpointMapId", &PlayableComponent::checkpointMapId,
97 "checkpointMapObject", &PlayableComponent::checkpointMapObject,
98 "checkpointMapObjectIndex", &PlayableComponent::checkpointMapObjectIndex);
99
100 engine.new_usertype<RealizableComponent>(
101 "realizable",
102 "activeMap", &RealizableComponent::activeMap);
103
104 engine.new_usertype<PrototypableComponent>(
105 "prototypable",
106 "mapObjectIndex", &PrototypableComponent::mapObjectIndex,
107 "prototypeId", &PrototypableComponent::prototypeId);
108
109 engine.new_usertype<RealizingSystem>(
110 "realizing",
111 "singleton",
112 [&] (RealizingSystem& realizing) -> script_entity {
113 return realizing.getSingleton();
114 });
115
116 engine.set_function(
117 "realizing",
118 [&] () {
119 return game_.getSystemManager().getSystem<RealizingSystem>();
120 });
121
122 engine.script_file("scripts/common.lua");
123 engine.script_file("scripts/movplat.lua");
124 engine.script_file("scripts/checkpoint.lua");
125}
126
127void ScriptingSystem::tick(double dt)
128{
129 auto entities = game_.getEntityManager().getEntitiesWithComponents<
130 RunnableComponent>();
131
132 for (id_type entity : entities)
133 {
134 auto& runnable = game_.getEntityManager().
135 getComponent<RunnableComponent>(entity);
136
137 if (*runnable.callable)
138 {
139 auto result = (*runnable.callable)(dt);
140 if (!result.valid())
141 {
142 sol::error e = result;
143 throw std::runtime_error(e.what());
144 }
145 }
146
147 if (!*runnable.callable)
148 {
149 game_.getEntityManager().deleteEntity(entity);
150 }
151 }
152}
153
154void ScriptingSystem::killScript(id_type entity)
155{
156 if (game_.getEntityManager().hasComponent<RunnableComponent>(entity))
157 {
158 game_.getEntityManager().deleteEntity(entity);
159 }
160}
161
162template <typename... Args>
163EntityManager::id_type ScriptingSystem::runScript(
164 std::string event,
165 id_type entity,
166 Args&&... args)
167{
168 auto& prototypable = game_.getEntityManager().
169 getComponent<PrototypableComponent>(entity);
170
171 id_type script = game_.getEntityManager().emplaceEntity();
172
173 auto& runnable = game_.getEntityManager().
174 emplaceComponent<RunnableComponent>(script);
175
176 runnable.runner =
177 std::unique_ptr<sol::thread>(
178 new sol::thread(
179 sol::thread::create(
180 engine.lua_state())));
181
182 runnable.callable =
183 std::unique_ptr<sol::coroutine>(
184 new sol::coroutine(
185 runnable.runner->state().
186 traverse_get<sol::function>(
187 prototypable.prototypeId,
188 event)));
189
190 if (!*runnable.callable)
191 {
192 throw std::runtime_error("Error running script");
193 }
194
195 auto result = (*runnable.callable)(
196 script_entity(entity),
197 std::forward<Args>(args)...);
198
199 if (!result.valid())
200 {
201 sol::error e = result;
202 throw std::runtime_error(e.what());
203 }
204
205 return script;
206}
207
208EntityManager::id_type ScriptingSystem::runBehaviorScript(id_type entity)
209{
210 return runScript("Behavior", entity);
211}
212
213void ScriptingSystem::onTouch(id_type entity, id_type player)
214{
215 runScript(
216 "OnTouch",
217 entity,
218 script_entity(player));
219}
diff --git a/src/systems/scripting.h b/src/systems/scripting.h new file mode 100644 index 0000000..d5380f1 --- /dev/null +++ b/src/systems/scripting.h
@@ -0,0 +1,28 @@
1#ifndef AUTOMATING_H_E6E5D76E
2#define AUTOMATING_H_E6E5D76E
3
4#include "system.h"
5#include <sol.hpp>
6
7class ScriptingSystem : public System {
8public:
9
10 ScriptingSystem(Game& game);
11
12 void tick(double dt);
13
14 void killScript(id_type entity);
15
16 id_type runBehaviorScript(id_type entity);
17
18 void onTouch(id_type entity, id_type player);
19
20private:
21
22 template <typename... Args>
23 id_type runScript(std::string event, id_type entity, Args&&... args);
24
25 sol::state engine;
26};
27
28#endif /* end of include guard: AUTOMATING_H_E6E5D76E */