From 83f51a6892629921b4cc482b986656a0a5cc5f6a Mon Sep 17 00:00:00 2001 From: Kelly Rauchenberger Date: Thu, 3 May 2018 14:41:01 -0400 Subject: Added simple AI implementation The new AutomatingSystem and AutomatableComponent are responsible for simple AI tasks. This currently is limited to moving entities at a certain speed for certain periods of time. These tasks are arranged as a set of behaviors, which are picked randomly when automation starts or when a behavior finishes executing. A behavior is a sequence of actions that run one after another. Currently, if an automated entity is blocked from moving by a collision, it will be coerced out of its intended path. This is because the automation parameters are stored as a speed and a duration, rather than a starting location and an ending location. This may end up being changed, or made configurable, as this is an early implementation of this feature and will need to be more complex later. Added an RNG object to the Game class, so that the AutomatingSystem can pick behaviors at random. --- src/components/automatable.h | 96 ++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 96 insertions(+) create mode 100644 src/components/automatable.h (limited to 'src/components/automatable.h') diff --git a/src/components/automatable.h b/src/components/automatable.h new file mode 100644 index 0000000..b37945f --- /dev/null +++ b/src/components/automatable.h @@ -0,0 +1,96 @@ +#ifndef AUTOMATABLE_H_3D519131 +#define AUTOMATABLE_H_3D519131 + +#include "component.h" +#include +#include + +class AutomatableComponent : public Component { +public: + + /** + * Helper class that defines an automatable action. + */ + class Action { + public: + + /** + * The horizontal and vertical speed, in pixels/sec, that the entity should + * move at. + */ + double speedX; + double speedY; + + /** + * The duration of the action in seconds. + */ + double dur; + }; + + /** + * Helper type that defines a behavior that an entity can exhibit, which is a + * list of actions that are stepped through in sequence. + */ + using Behavior = std::vector; + + /** + * A group of behaviors that the entity can exhibit, which are picked at + * random at the start of automation and whenever a behavior completes. + * + * @managed_by RealizingSystem + */ + std::vector behaviors; + + /** + * A random distribution over the above behaviors. + * + * @managed_by RealizingSystem + */ + std::discrete_distribution behaviorDist; + + /** + * A flag indicating whether a behavior is currently executing. + * + * @managed_by AutomatingSystem + */ + bool behaviorRunning = false; + + /** + * A flag indicating whether an action is currently executing. + * + * @managed_by AutomatingSystem + */ + bool actionRunning = false; + + /** + * The index of the currently executing behavior, if there is one. + * + * @managed_by AutomatingSystem + */ + size_t currentBehavior; + + /** + * The index of the currently executing action, if there is one. + * + * @managed_by AutomatingSystem + */ + size_t currentAction; + + /** + * The amount of time remaining, in seconds, of the currently executing + * action. + * + * @managed_by AutomatingSystem + */ + double remaining; + + /** + * If this flag is disabled, the entity will be ignored by the automating + * system. + * + * @managed_by RealizingSystem + */ + bool active = false; +}; + +#endif /* end of include guard: AUTOMATABLE_H_3D519131 */ -- cgit 1.4.1 From 5c82f052c26303318e81ddd76475c1d188cc74f4 Mon Sep 17 00:00:00 2001 From: Kelly Rauchenberger Date: Tue, 8 May 2018 21:09:36 -0400 Subject: Simplified positions/sizes with vectors Positions and sizes are now stored as vectors (of doubles and ints, respectively). This allows for at least minor code simplification in many places, and cleans up the CollisionParams code in PonderingSystem quite a bit. --- src/components/automatable.h | 4 +- src/components/playable.h | 4 +- src/components/ponderable.h | 10 +- src/components/realizable.h | 4 +- src/components/transformable.h | 13 +- src/systems/animating.cpp | 8 +- src/systems/automating.cpp | 3 +- src/systems/orienting.cpp | 14 +- src/systems/playing.cpp | 19 +-- src/systems/playing.h | 4 +- src/systems/pondering.cpp | 294 +++++++++++++++-------------------------- src/systems/pondering.h | 34 +++-- src/systems/realizing.cpp | 38 +++--- src/vector.h | 111 ++++++++++++++++ 14 files changed, 285 insertions(+), 275 deletions(-) create mode 100644 src/vector.h (limited to 'src/components/automatable.h') diff --git a/src/components/automatable.h b/src/components/automatable.h index b37945f..c1fd1a3 100644 --- a/src/components/automatable.h +++ b/src/components/automatable.h @@ -4,6 +4,7 @@ #include "component.h" #include #include +#include "vector.h" class AutomatableComponent : public Component { public: @@ -18,8 +19,7 @@ public: * The horizontal and vertical speed, in pixels/sec, that the entity should * move at. */ - double speedX; - double speedY; + vec2d speed; /** * The duration of the action in seconds. diff --git a/src/components/playable.h b/src/components/playable.h index 94d4326..b8af0f2 100644 --- a/src/components/playable.h +++ b/src/components/playable.h @@ -3,6 +3,7 @@ #include "component.h" #include "entity_manager.h" +#include "vector.h" class PlayableComponent : public Component { public: @@ -24,8 +25,7 @@ public: * @managed_by PlayingSystem */ size_t checkpointMapId; - double checkpointX; - double checkpointY; + vec2d checkpointPos; }; diff --git a/src/components/ponderable.h b/src/components/ponderable.h index eff20e9..c0312b4 100644 --- a/src/components/ponderable.h +++ b/src/components/ponderable.h @@ -4,6 +4,7 @@ #include #include "component.h" #include "entity_manager.h" +#include "vector.h" class PonderableComponent : public Component { public: @@ -45,14 +46,12 @@ public: /** * The velocity of the body. */ - double velX = 0.0; - double velY = 0.0; + vec2d vel = { 0.0, 0.0 }; /** * The acceleration of the body. */ - double accelX = 0.0; - double accelY = 0.0; + vec2d accel = { 0.0, 0.0 }; /** * The type of physical body that the entity is meant to assume. The body will @@ -89,8 +88,7 @@ public: * * @managed_by PonderingSystem */ - double relX; - double relY; + vec2d rel = { 0.0, 0.0 }; /** * The bodies that are being ferried by this body. diff --git a/src/components/realizable.h b/src/components/realizable.h index 0858e7a..b749aeb 100644 --- a/src/components/realizable.h +++ b/src/components/realizable.h @@ -5,6 +5,7 @@ #include #include #include "entity_manager.h" +#include "vector.h" class RealizableComponent : public Component { public: @@ -31,8 +32,7 @@ public: * @managed_by RealizingSystem */ int startingMapId; - int startingX; - int startingY; + vec2i startingPos; /** * The set of map entities loaded by this entity. It is only intended for diff --git a/src/components/transformable.h b/src/components/transformable.h index 6f3c2ef..bb21996 100644 --- a/src/components/transformable.h +++ b/src/components/transformable.h @@ -2,6 +2,7 @@ #define LOCATABLE_H_39E526CA #include "component.h" +#include "vector.h" class TransformableComponent : public Component { public: @@ -15,24 +16,20 @@ public: * so, use PonderingSystem::unferry on the body to ensure that it is not * ferried. */ - double x; - double y; + vec2d pos; /** * The size of the entity. */ - int w; - int h; + vec2i size; /** * For prototypes, the original coordinates and size of the entity. * * @managed_by RealizingSystem */ - double origX; - double origY; - int origW; - int origH; + vec2d origPos; + vec2i origSize; }; #endif /* end of include guard: LOCATABLE_H_39E526CA */ diff --git a/src/systems/animating.cpp b/src/systems/animating.cpp index 8543ba2..50a32fc 100644 --- a/src/systems/animating.cpp +++ b/src/systems/animating.cpp @@ -64,10 +64,10 @@ void AnimatingSystem::render(Texture& texture) } Rectangle dstrect { - static_cast(transform.x), - static_cast(transform.y), - transform.w, - transform.h}; + static_cast(transform.pos.x()), + static_cast(transform.pos.y()), + transform.size.w(), + transform.size.h()}; const AnimationSet& aset = sprite.animationSet; game_.getRenderer().blit( diff --git a/src/systems/automating.cpp b/src/systems/automating.cpp index 0d85957..61b97d9 100644 --- a/src/systems/automating.cpp +++ b/src/systems/automating.cpp @@ -54,8 +54,7 @@ void AutomatingSystem::tick(double dt) auto& ponderable = game_.getEntityManager(). getComponent(entity); - ponderable.velX = curAction.speedX; - ponderable.velY = curAction.speedY; + ponderable.vel = curAction.speed; automatable.remaining -= dt; } diff --git a/src/systems/orienting.cpp b/src/systems/orienting.cpp index 206ebf6..d73ddd2 100644 --- a/src/systems/orienting.cpp +++ b/src/systems/orienting.cpp @@ -24,27 +24,27 @@ void OrientingSystem::tick(double) { case OrientableComponent::WalkState::still: { - ponderable.velX = 0.0; + ponderable.vel.x() = 0.0; break; } case OrientableComponent::WalkState::left: { - ponderable.velX = -WALK_SPEED; + ponderable.vel.x() = -WALK_SPEED; break; } case OrientableComponent::WalkState::right: { - ponderable.velX = WALK_SPEED; + ponderable.vel.x() = WALK_SPEED; break; } } - if (orientable.isJumping() && (ponderable.velY > 0)) + if (orientable.isJumping() && (ponderable.vel.y() > 0)) { orientable.setJumping(false); } @@ -122,8 +122,8 @@ void OrientingSystem::jump(id_type entity) playSound("res/Randomize87.wav", 0.25); - ponderable.velY = JUMP_VELOCITY; - ponderable.accelY = JUMP_GRAVITY; + ponderable.vel.y() = JUMP_VELOCITY; + ponderable.accel.y() = JUMP_GRAVITY; auto& animating = game_.getSystemManager().getSystem(); if (orientable.isFacingRight()) @@ -147,7 +147,7 @@ void OrientingSystem::stopJumping(id_type entity) auto& ponderable = game_.getEntityManager(). getComponent(entity); - ponderable.accelY = NORMAL_GRAVITY; + ponderable.accel.y() = NORMAL_GRAVITY; } } diff --git a/src/systems/playing.cpp b/src/systems/playing.cpp index acec4e7..dabc9a5 100644 --- a/src/systems/playing.cpp +++ b/src/systems/playing.cpp @@ -42,10 +42,9 @@ void PlayingSystem::initPlayer() auto& transformable = game_.getEntityManager(). emplaceComponent(player); - transformable.x = realizable.startingX; - transformable.y = realizable.startingY; - transformable.w = 10; - transformable.h = 12; + transformable.pos = realizable.startingPos; + transformable.size.w() = 10; + transformable.size.h() = 12; game_.getSystemManager().getSystem().initializeBody( player, @@ -59,8 +58,7 @@ void PlayingSystem::initPlayer() playable.mapId = realizable.activeMap; playable.checkpointMapId = realizable.startingMapId; - playable.checkpointX = realizable.startingX; - playable.checkpointY = realizable.startingY; + playable.checkpointPos = realizable.startingPos; realizing.enterActiveMap(player); @@ -70,8 +68,7 @@ void PlayingSystem::initPlayer() void PlayingSystem::changeMap( id_type player, size_t mapId, - double x, - double y) + vec2d warpPos) { auto& playable = game_.getEntityManager(). getComponent(player); @@ -103,8 +100,7 @@ void PlayingSystem::changeMap( pondering.unferry(player); - transformable.x = x; - transformable.y = y; + transformable.pos = warpPos; if (realizable.activePlayer == player) { @@ -139,8 +135,7 @@ void PlayingSystem::die(id_type player) changeMap( player, playable.checkpointMapId, - playable.checkpointX, - playable.checkpointY); + playable.checkpointPos); animatable.frozen = false; animatable.flickering = false; diff --git a/src/systems/playing.h b/src/systems/playing.h index 9ba403b..31f79ab 100644 --- a/src/systems/playing.h +++ b/src/systems/playing.h @@ -2,6 +2,7 @@ #define PLAYING_H_70A54F7D #include "system.h" +#include "vector.h" class PlayingSystem : public System { public: @@ -15,8 +16,7 @@ public: void changeMap( id_type player, size_t mapId, - double x, - double y); + vec2d warpPos); void die(id_type player); diff --git a/src/systems/pondering.cpp b/src/systems/pondering.cpp index 7b3ab2d..ec83270 100644 --- a/src/systems/pondering.cpp +++ b/src/systems/pondering.cpp @@ -47,7 +47,7 @@ void PonderingSystem::initializeBody( if (type == PonderableComponent::Type::freefalling) { - ponderable.accelY = NORMAL_GRAVITY; + ponderable.accel.y() = NORMAL_GRAVITY; } } @@ -56,10 +56,10 @@ void PonderingSystem::initPrototype(id_type prototype) auto& ponderable = game_.getEntityManager(). getComponent(prototype); - ponderable.velX = 0.0; - ponderable.velY = 0.0; - ponderable.accelX = 0.0; - ponderable.accelY = 0.0; + ponderable.vel.x() = 0.0; + ponderable.vel.y() = 0.0; + ponderable.accel.x() = 0.0; + ponderable.accel.y() = 0.0; ponderable.grounded = false; ponderable.frozen = false; ponderable.collidable = true; @@ -102,19 +102,17 @@ void PonderingSystem::tickBody( // Accelerate if (!ponderable.frozen) { - ponderable.velX += ponderable.accelX * dt; - ponderable.velY += ponderable.accelY * dt; + ponderable.vel += ponderable.accel * dt; if ((ponderable.type == PonderableComponent::Type::freefalling) - && (ponderable.velY > TERMINAL_VELOCITY)) + && (ponderable.vel.y() > TERMINAL_VELOCITY)) { - ponderable.velY = TERMINAL_VELOCITY; + ponderable.vel.y() = TERMINAL_VELOCITY; } } // Move - double newX = transformable.x; - double newY = transformable.y; + vec2d newPos = transformable.pos; if (!ponderable.frozen) { @@ -123,19 +121,13 @@ void PonderingSystem::tickBody( auto& ferryTrans = game_.getEntityManager(). getComponent(ponderable.ferry); - newX = ferryTrans.x + ponderable.relX; - newY = ferryTrans.y + ponderable.relY; + newPos = ferryTrans.pos + ponderable.rel; } - newX += ponderable.velX * dt; - newY += ponderable.velY * dt; + newPos += ponderable.vel * dt; } - CollisionResult result = - moveBody( - entity, - newX, - newY); + CollisionResult result = moveBody(entity, newPos); // Perform cleanup for orientable entites bool groundedChanged = (ponderable.grounded != result.grounded); @@ -194,8 +186,7 @@ void PonderingSystem::tickBody( auto& ferryTrans = game_.getEntityManager(). getComponent(ponderable.ferry); - ponderable.relX = transformable.x - ferryTrans.x; - ponderable.relY = transformable.y - ferryTrans.y; + ponderable.rel = transformable.pos - ferryTrans.pos; } // Handle ferry passengers @@ -212,35 +203,34 @@ void PonderingSystem::tickBody( // Move to an adjacent map, if necessary if (result.adjacentlyWarping) { - double warpX = result.newX; - double warpY = result.newY; + vec2d warpPos = result.pos; switch (result.adjWarpDir) { case Direction::left: { - warpX = GAME_WIDTH + WALL_GAP - transformable.w; + warpPos.x() = GAME_WIDTH + WALL_GAP - transformable.size.w(); break; } case Direction::right: { - warpX = -WALL_GAP; + warpPos.x() = -WALL_GAP; break; } case Direction::up: { - warpY = MAP_HEIGHT * TILE_HEIGHT - transformable.h; + warpPos.y() = MAP_HEIGHT * TILE_HEIGHT - transformable.size.h(); break; } case Direction::down: { - warpY = -WALL_GAP; + warpPos.y() = -WALL_GAP; break; } @@ -250,15 +240,13 @@ void PonderingSystem::tickBody( changeMap( entity, result.adjWarpMapId, - warpX, - warpY); + warpPos); } } -CollisionResult PonderingSystem::moveBody( +PonderingSystem::CollisionResult PonderingSystem::moveBody( id_type entity, - double x, - double y) + vec2d newPos) { auto& ponderable = game_.getEntityManager(). getComponent(entity); @@ -266,26 +254,29 @@ CollisionResult PonderingSystem::moveBody( auto& transformable = game_.getEntityManager(). getComponent(entity); - const double oldX = transformable.x; - const double oldY = transformable.y; - const double oldRight = oldX + transformable.w; - const double oldBottom = oldY + transformable.h; - CollisionResult result; if (ponderable.collidable) { - result = detectCollisions(entity, x, y); + result = detectCollisions(entity, newPos); } else { - result.newX = x; - result.newY = y; + result.pos = newPos; } // Move if (!ponderable.frozen) { - transformable.x = result.newX; - transformable.y = result.newY; + transformable.pos = result.pos; + + if (result.blockedHoriz) + { + ponderable.vel.x() = 0.0; + } + + if (result.blockedVert) + { + ponderable.vel.y() = 0.0; + } } return result; @@ -311,21 +302,14 @@ namespace CollisionParams { return (colliderAxis > entityAxis); } - inline static double OldAxis(const TransformableComponent& transformable) + inline static double EntityAxis(const vec2d& pos, const vec2i& size) { - return HorizVert::AxisOldLower(transformable); + return HorizVert::AxisLower(pos); } - inline static double NewAxis( - const CollisionResult& result, - const TransformableComponent&) + inline static double ObjectAxis(const vec2d& pos, const vec2i& size) { - return HorizVert::AxisNewLower(result); - } - - inline static double ObjectAxis(const TransformableComponent& transformable) - { - return HorizVert::AxisOldUpper(transformable); + return HorizVert::AxisUpper(pos, size); } inline static bool Closer(double left, double right) @@ -352,21 +336,14 @@ namespace CollisionParams { return (colliderAxis < entityAxis); } - inline static double OldAxis(const TransformableComponent& transformable) + inline static double EntityAxis(const vec2d& pos, const vec2i& size) { - return HorizVert::AxisOldUpper(transformable); + return HorizVert::AxisUpper(pos, size); } - inline static double NewAxis( - const CollisionResult& result, - const TransformableComponent& transformable) + inline static double ObjectAxis(const vec2d& pos, const vec2i& size) { - return HorizVert::AxisNewUpper(result, transformable); - } - - inline static double ObjectAxis(const TransformableComponent& transformable) - { - return HorizVert::AxisOldLower(transformable); + return HorizVert::AxisLower(pos); } inline static bool Closer(double left, double right) @@ -375,121 +352,62 @@ namespace CollisionParams { } }; - class Horizontal { + template + class HorizVert { public: - inline static double AxisOldLower( - const TransformableComponent& transformable) + inline static double AxisLower(const vec2d& pos) { - return transformable.x; + return pos.coords[Axis]; } - inline static double AxisOldUpper( - const TransformableComponent& transformable) + inline static double AxisUpper(const vec2d& pos, const vec2i& size) { - return transformable.x + transformable.w; + return pos.coords[Axis] + size.coords[Axis]; } - inline static double AxisNewLower(const CollisionResult& result) + inline static double NonAxisLower(const vec2d& pos) { - return result.newX; + return pos.coords[NonAxis]; } - inline static double AxisNewUpper( - const CollisionResult& result, - const TransformableComponent& transformable) + inline static double NonAxisUpper(const vec2d& pos, const vec2i& size) { - return result.newX + transformable.w; + return pos.coords[NonAxis] + size.coords[NonAxis]; } - inline static double NonAxisOldLower( - const TransformableComponent& transformable) - { - return transformable.y; - } - - inline static double NonAxisOldUpper( - const TransformableComponent& transformable) - { - return transformable.y + transformable.h; - } - - inline static double NonAxisNewLower( - const CollisionResult& result, - const TransformableComponent& transformable) - { - return result.newY; - } - - inline static double NonAxisNewUpper( - const CollisionResult& result, - const TransformableComponent& transformable) - { - return result.newY + transformable.h; - } }; - class Vertical { - public: - - inline static double AxisOldLower( - const TransformableComponent& transformable) - { - return transformable.y; - } - - inline static double AxisOldUpper( - const TransformableComponent& transformable) - { - return transformable.y + transformable.h; - } + using Horizontal = HorizVert<0, 1>; + using Vertical = HorizVert<1, 0>; - inline static double AxisNewLower(const CollisionResult& result) - { - return result.newY; - } + template + class DetectCollisions : public AscDesc { + public: - inline static double AxisNewUpper( - const CollisionResult& result, - const TransformableComponent& transformable) - { - return result.newY + transformable.h; - } + static const Direction Dir = dir; - inline static double NonAxisOldLower( - const TransformableComponent& transformable) + inline static double EntityAxis(const vec2d& pos, const vec2i& size) { - return transformable.x; + return AscDesc::EntityAxis(pos, size); } - inline static double NonAxisOldUpper( - const TransformableComponent& transformable) + inline static double ObjectAxis(const vec2d& pos, const vec2i& size) { - return transformable.x + transformable.w; + return AscDesc::ObjectAxis(pos, size); } - inline static double NonAxisNewLower( - const CollisionResult& result, - const TransformableComponent& transformable) + inline static double EntityAxis(const TransformableComponent& transformable) { - return result.newX; + return AscDesc::EntityAxis(transformable.pos, transformable.size); } - inline static double NonAxisNewUpper( - const CollisionResult& result, - const TransformableComponent& transformable) + inline static double ObjectAxis(const TransformableComponent& transformable) { - return result.newX + transformable.w; + return AscDesc::ObjectAxis(transformable.pos, transformable.size); } }; - template - class DetectCollisions : public AscDesc { - public: - - static const Direction Dir = dir; - }; - class Left : public DetectCollisions> { public: @@ -531,23 +449,22 @@ namespace CollisionParams { }; }; -CollisionResult PonderingSystem::detectCollisions( +PonderingSystem::CollisionResult PonderingSystem::detectCollisions( id_type entity, - double x, - double y) + vec2d newPos) { auto& transformable = game_.getEntityManager(). getComponent(entity); CollisionResult result; - result.newX = x; - result.newY = transformable.y; + result.pos.x() = newPos.x(); + result.pos.y() = transformable.pos.y(); // Find horizontal collisions. - if (result.newX < transformable.x) + if (result.pos.x() < transformable.pos.x()) { detectCollisionsInDirection(entity, result); - } else if (result.newX > transformable.x) + } else if (result.pos.x() > transformable.pos.x()) { detectCollisionsInDirection(entity, result); } @@ -555,13 +472,13 @@ CollisionResult PonderingSystem::detectCollisions( // Find vertical collisions if (!result.stopProcessing) { - result.newY = y; + result.pos.y() = newPos.y(); result.touchedWall = false; - if (result.newY < transformable.y) + if (result.pos.y() < transformable.pos.y()) { detectCollisionsInDirection(entity, result); - } else if (result.newY > transformable.y) + } else if (result.pos.y() > transformable.pos.y()) { detectCollisionsInDirection(entity, result); } @@ -586,25 +503,25 @@ void PonderingSystem::detectCollisionsInDirection( getComponent(mapEntity); // Get old location. - auto& transformable = game_.getEntityManager(). + auto& transform = game_.getEntityManager(). getComponent(entity); bool boundaryCollision = false; auto boundaries = Param::MapBoundaries(mappable); - auto it = boundaries.lower_bound(Param::OldAxis(transformable)); + auto it = boundaries.lower_bound(Param::EntityAxis(transform)); // Find the axis distance of the closest environmental boundary. for (; (it != std::end(boundaries)) && Param::AtLeastInAxisSweep( it->first, - Param::NewAxis(result, transformable)); + Param::EntityAxis(result.pos, transform.size)); it++) { // Check that the boundary is in range for the other axis. - if ((Param::NonAxisNewUpper(result, transformable) > it->second.lower) && - (Param::NonAxisNewLower(result, transformable) < it->second.upper)) + if ((Param::NonAxisUpper(result.pos, transform.size) > it->second.lower) && + (Param::NonAxisLower(result.pos) < it->second.upper)) { // We have a collision! boundaryCollision = true; @@ -644,16 +561,16 @@ void PonderingSystem::detectCollisionsInDirection( // Check if the entity would move into the potential collider, if (Param::IsPastAxis( Param::ObjectAxis(colliderTrans), - Param::NewAxis(result, transformable)) && + Param::EntityAxis(result.pos, transform.size)) && // that it wasn't already colliding, !Param::IsPastAxis( Param::ObjectAxis(colliderTrans), - Param::OldAxis(transformable)) && + Param::EntityAxis(transform)) && // that the position on the non-axis is in range, - (Param::NonAxisOldUpper(colliderTrans) > - Param::NonAxisNewLower(result, transformable)) && - (Param::NonAxisOldLower(colliderTrans) < - Param::NonAxisNewUpper(result, transformable)) && + (Param::NonAxisUpper(colliderTrans.pos, colliderTrans.size) > + Param::NonAxisLower(result.pos)) && + (Param::NonAxisLower(colliderTrans.pos) < + Param::NonAxisUpper(result.pos, transform.size)) && // and that the collider is not farther away than the environmental // boundary. (!boundaryCollision || @@ -688,7 +605,7 @@ void PonderingSystem::detectCollisionsInDirection( // Check if the entity would still move into the potential collider. if (!Param::IsPastAxis( Param::ObjectAxis(colliderTrans), - Param::NewAxis(result, transformable))) + Param::EntityAxis(result.pos, transform.size))) { break; } @@ -702,8 +619,8 @@ void PonderingSystem::detectCollisionsInDirection( Param::Dir, colliderPonder.colliderType, Param::ObjectAxis(colliderTrans), - Param::NonAxisOldLower(colliderTrans), - Param::NonAxisOldUpper(colliderTrans), + Param::NonAxisLower(colliderTrans.pos), + Param::NonAxisUpper(colliderTrans.pos, colliderTrans.size), result); if (result.stopProcessing) @@ -724,8 +641,8 @@ void PonderingSystem::detectCollisionsInDirection( (it->first == boundaryAxis); it++) { - if ((Param::NonAxisNewUpper(result, transformable) > it->second.lower) && - (Param::NonAxisNewLower(result, transformable) < it->second.upper)) + if ((Param::NonAxisLower(result.pos) < it->second.upper) && + (Param::NonAxisUpper(result.pos, transform.size) > it->second.lower)) { processCollision( entity, @@ -756,9 +673,6 @@ void PonderingSystem::processCollision( double upper, CollisionResult& result) { - auto& ponderable = game_.getEntityManager(). - getComponent(entity); - auto& transformable = game_.getEntityManager(). getComponent(entity); @@ -823,29 +737,29 @@ void PonderingSystem::processCollision( { case Direction::left: { - result.newX = GAME_WIDTH + WALL_GAP - transformable.w; + result.pos.x() = GAME_WIDTH + WALL_GAP - transformable.size.w(); break; } case Direction::right: { - result.newX = -WALL_GAP; + result.pos.x() = -WALL_GAP; break; } case Direction::up: { - result.newY = - MAP_HEIGHT * TILE_HEIGHT + WALL_GAP - transformable.h; + result.pos.y() = + MAP_HEIGHT * TILE_HEIGHT + WALL_GAP - transformable.pos.h(); break; } case Direction::down: { - result.newY = -WALL_GAP; + result.pos.y() = -WALL_GAP; break; } @@ -905,33 +819,33 @@ void PonderingSystem::processCollision( { case Direction::left: { - result.newX = axis; - ponderable.velX = 0.0; + result.pos.x() = axis; + result.blockedHoriz = true; break; } case Direction::right: { - result.newX = axis - transformable.w; - ponderable.velX = 0.0; + result.pos.x() = axis - transformable.size.w(); + result.blockedHoriz = true; break; } case Direction::up: { - result.newY = axis; - ponderable.velY = 0.0; + result.pos.y() = axis; + result.blockedVert = true; break; } case Direction::down: { - result.newY = axis - transformable.h; + result.pos.y() = axis - transformable.size.h(); + result.blockedVert = true; result.groundEntity = collider; - ponderable.velY = 0.0; result.grounded = true; break; diff --git a/src/systems/pondering.h b/src/systems/pondering.h index abc6db2..273db67 100644 --- a/src/systems/pondering.h +++ b/src/systems/pondering.h @@ -4,19 +4,7 @@ #include "system.h" #include "components/ponderable.h" #include "direction.h" - -struct CollisionResult -{ - double newX; - double newY; - bool stopProcessing = false; - bool touchedWall = false; - bool adjacentlyWarping = false; - Direction adjWarpDir; - size_t adjWarpMapId; - bool grounded = false; - EntityManager::id_type groundEntity; -}; +#include "vector.h" class PonderingSystem : public System { public: @@ -47,7 +35,19 @@ public: private: - + struct CollisionResult + { + vec2d pos; + bool stopProcessing = false; + bool touchedWall = false; + bool blockedHoriz = false; + bool blockedVert = false; + bool adjacentlyWarping = false; + Direction adjWarpDir; + size_t adjWarpMapId; + bool grounded = false; + id_type groundEntity; + }; void tickBody( id_type entity, @@ -56,13 +56,11 @@ private: CollisionResult moveBody( id_type entity, - double x, - double y); + vec2d newPos); CollisionResult detectCollisions( id_type entity, - double x, - double y); + vec2d newPos); template void detectCollisionsInDirection( diff --git a/src/systems/realizing.cpp b/src/systems/realizing.cpp index 8e670ac..f9285ad 100644 --- a/src/systems/realizing.cpp +++ b/src/systems/realizing.cpp @@ -93,20 +93,20 @@ void parseAI( if (direction == "left") { - action.speedX = -speed; - action.speedY = 0; + action.speed.x() = -speed; + action.speed.y() = 0; } else if (direction == "right") { - action.speedX = speed; - action.speedY = 0; + action.speed.x() = speed; + action.speed.y() = 0; } else if (direction == "up") { - action.speedX = 0; - action.speedY = -speed; + action.speed.x() = 0; + action.speed.y() = -speed; } else if (direction == "down") { - action.speedX = 0; - action.speedY = speed; + action.speed.x() = 0; + action.speed.y() = speed; } action.dur = length / speed; @@ -186,11 +186,11 @@ EntityManager::id_type RealizingSystem::initSingleton( } key = getProp(top, "startx"); - realizable.startingX = atoi(reinterpret_cast(key)); + realizable.startingPos.x() = atoi(reinterpret_cast(key)); xmlFree(key); key = getProp(top, "starty"); - realizable.startingY = atoi(reinterpret_cast(key)); + realizable.startingPos.y() = atoi(reinterpret_cast(key)); xmlFree(key); key = getProp(top, "startmap"); @@ -260,11 +260,11 @@ EntityManager::id_type RealizingSystem::initSingleton( emplaceComponent(mapObject); key = getProp(mapNode, "x"); - transformable.origX = atoi(reinterpret_cast(key)); + transformable.origPos.x() = atoi(reinterpret_cast(key)); xmlFree(key); key = getProp(mapNode, "y"); - transformable.origY = atoi(reinterpret_cast(key)); + transformable.origPos.y() = atoi(reinterpret_cast(key)); xmlFree(key); // Set the sprite and size using the prototype definition. @@ -273,17 +273,17 @@ EntityManager::id_type RealizingSystem::initSingleton( xmlFree(key); key = getProp(prototypeNode, "width"); - transformable.origW = atoi(reinterpret_cast(key)); + transformable.origSize.w() = atoi(reinterpret_cast(key)); xmlFree(key); key = getProp(prototypeNode, "height"); - transformable.origH = atoi(reinterpret_cast(key)); + transformable.origSize.h() = atoi(reinterpret_cast(key)); xmlFree(key); AnimationSet objectAnim( spritePath.c_str(), - transformable.origW, - transformable.origH, + transformable.origSize.w(), + transformable.origSize.h(), 1); objectAnim.emplaceAnimation("static", 0, 1, 1); @@ -503,10 +503,8 @@ void RealizingSystem::loadMap(id_type mapEntity) auto& transformable = game_.getEntityManager(). getComponent(prototype); - transformable.x = transformable.origX; - transformable.y = transformable.origY; - transformable.w = transformable.origW; - transformable.h = transformable.origH; + transformable.pos = transformable.origPos; + transformable.size = transformable.origSize; } if (game_.getEntityManager().hasComponent(prototype)) diff --git a/src/vector.h b/src/vector.h new file mode 100644 index 0000000..3abd98a --- /dev/null +++ b/src/vector.h @@ -0,0 +1,111 @@ +#ifndef COORDINATES_H_A45D34FB +#define COORDINATES_H_A45D34FB + +template +class vec2 { +public: + + T coords[2]; + + vec2() = default; + + vec2(double x, double y) : coords{x, y} + { + } + + inline T& x() + { + return coords[0]; + } + + inline const T& x() const + { + return coords[0]; + } + + inline T& w() + { + return coords[0]; + } + + inline const T& w() const + { + return coords[0]; + } + + inline T& y() + { + return coords[1]; + } + + inline const T& y() const + { + return coords[1]; + } + + inline T& h() + { + return coords[1]; + } + + inline const T& h() const + { + return coords[1]; + } + + template + operator vec2() const + { + return vec2(x(), y()); + } + + vec2 operator+(const vec2& other) const + { + return vec2(x() + other.x(), y() + other.y()); + } + + vec2& operator+=(const vec2& other) + { + x() += other.x(); + y() += other.y(); + + return *this; + } + + vec2 operator-(const vec2& other) const + { + return vec2(x() - other.x(), y() - other.y()); + } + + vec2 operator-=(const vec2& other) + { + x() -= other.x(); + y() -= other.y(); + + return *this; + } + + vec2 operator-() const + { + return vec2(-x(), -y()); + } + + vec2 operator*(double s) const + { + return vec2(x() * s, y() * s); + } + + vec2& operator*=(double s) + { + x() *= s; + y() *= s; + + return *this; + } + +}; + +using vec2d = vec2; +using vec2i = vec2; + +#endif /* end of include guard: COORDINATES_H_A45D34FB */ -- cgit 1.4.1 From 4bbfeae42a1245b1b84e8847787d7643e6a6f2cf Mon Sep 17 00:00:00 2001 From: Kelly Rauchenberger Date: Thu, 10 May 2018 19:27:59 -0400 Subject: Started integrating Lua as a scripting engine Currently moving platforms are able to have their movement controlled by a script rather than by XML, which is probably a better implementation and scales better to other things. The scripts, instead of using the components as state, use the stack as state. In this way, they pretend to be multithreaded. For instance, the moving platform calls moveRight and then moveLeft. Both of those functions internally make calls that say to wait until the next tick. When the AutomatingSystem ticks, it continues execution of all scripts (sequentially, of course) until they ask for the next tick again. This is implemented using coroutines. --- CMakeLists.txt | 5 +- res/platform.lua | 27 + src/components/automatable.h | 81 +- src/components/realizable.h | 3 + src/systems/automating.cpp | 99 +- src/systems/automating.h | 3 + src/systems/realizing.cpp | 153 +- src/vector.h | 10 +- vendor/sol.hpp | 21575 +++++++++++++++++++++++++++++++++++++++++ 9 files changed, 21688 insertions(+), 268 deletions(-) create mode 100644 res/platform.lua create mode 100644 vendor/sol.hpp (limited to 'src/components/automatable.h') diff --git a/CMakeLists.txt b/CMakeLists.txt index 04ca668..fbc843c 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -16,6 +16,7 @@ find_package(GLEW REQUIRED) find_package(portaudio REQUIRED) find_package(libsndfile REQUIRED) find_package(libxml2 REQUIRED) +find_package(lua REQUIRED) IF(APPLE) FIND_LIBRARY(COCOA_LIBRARY Cocoa) @@ -32,6 +33,7 @@ set(ALL_LIBS ${PORTAUDIO_LIBRARIES} ${LIBSNDFILE_LIBRARY} ${LIBXML2_LIBRARIES} + ${LUA_LIBRARIES} ${EXTRA_LIBS} ) @@ -40,6 +42,7 @@ include_directories( ${GLFW_INCLUDE_DIRS} ${OPENGL_INCLUDE_DIRS} ${GLEW_INCLUDE_DIRS} + ${LUA_INCLUDE_DIRS} src vendor ) @@ -71,6 +74,6 @@ add_executable(Aromatherapy vendor/stb_image.cpp ) -set_property(TARGET Aromatherapy PROPERTY CXX_STANDARD 11) +set_property(TARGET Aromatherapy PROPERTY CXX_STANDARD 17) set_property(TARGET Aromatherapy PROPERTY CXX_STANDARD_REQUIRED ON) target_link_libraries(Aromatherapy ${ALL_LIBS}) diff --git a/res/platform.lua b/res/platform.lua new file mode 100644 index 0000000..31a7cba --- /dev/null +++ b/res/platform.lua @@ -0,0 +1,27 @@ +function moveLeft(entity, len, speed) + local remaining = len / speed + + while (remaining > 0) do + print("no") + --entity:ponderable().vel:x(-speed) + remaining = remaining - coroutine.yield() + end +end + +function moveRight(entity, len, speed) + local remaining = len / speed + + while (remaining > 0) do + print("no2") + --entity:ponderable().vel:x(speed) + remaining = remaining - coroutine.yield() + end +end + +function run(entity) + print("yes") + while true do + moveRight(entity, 90, 30) + moveLeft(entity, 90, 30) + end +end \ No newline at end of file diff --git a/src/components/automatable.h b/src/components/automatable.h index c1fd1a3..d30340a 100644 --- a/src/components/automatable.h +++ b/src/components/automatable.h @@ -2,87 +2,16 @@ #define AUTOMATABLE_H_3D519131 #include "component.h" -#include -#include -#include "vector.h" +#include +#include class AutomatableComponent : public Component { public: - /** - * Helper class that defines an automatable action. - */ - class Action { - public: - - /** - * The horizontal and vertical speed, in pixels/sec, that the entity should - * move at. - */ - vec2d speed; - - /** - * The duration of the action in seconds. - */ - double dur; - }; - - /** - * Helper type that defines a behavior that an entity can exhibit, which is a - * list of actions that are stepped through in sequence. - */ - using Behavior = std::vector; - - /** - * A group of behaviors that the entity can exhibit, which are picked at - * random at the start of automation and whenever a behavior completes. - * - * @managed_by RealizingSystem - */ - std::vector behaviors; - - /** - * A random distribution over the above behaviors. - * - * @managed_by RealizingSystem - */ - std::discrete_distribution behaviorDist; - - /** - * A flag indicating whether a behavior is currently executing. - * - * @managed_by AutomatingSystem - */ - bool behaviorRunning = false; - - /** - * A flag indicating whether an action is currently executing. - * - * @managed_by AutomatingSystem - */ - bool actionRunning = false; - - /** - * The index of the currently executing behavior, if there is one. - * - * @managed_by AutomatingSystem - */ - size_t currentBehavior; + std::unique_ptr runner; + std::unique_ptr behavior; - /** - * The index of the currently executing action, if there is one. - * - * @managed_by AutomatingSystem - */ - size_t currentAction; - - /** - * The amount of time remaining, in seconds, of the currently executing - * action. - * - * @managed_by AutomatingSystem - */ - double remaining; + sol::environment origBehavior; /** * If this flag is disabled, the entity will be ignored by the automating diff --git a/src/components/realizable.h b/src/components/realizable.h index b749aeb..bc834a2 100644 --- a/src/components/realizable.h +++ b/src/components/realizable.h @@ -4,6 +4,7 @@ #include "component.h" #include #include +#include #include "entity_manager.h" #include "vector.h" @@ -69,6 +70,8 @@ public: * The entity ID of the currently active player. */ id_type activePlayer; + + sol::state scriptEngine; }; #endif /* end of include guard: REALIZABLE_H_36D8D71E */ diff --git a/src/systems/automating.cpp b/src/systems/automating.cpp index 61b97d9..6cec3bf 100644 --- a/src/systems/automating.cpp +++ b/src/systems/automating.cpp @@ -2,13 +2,24 @@ #include "game.h" #include "components/automatable.h" #include "components/ponderable.h" -#include "systems/pondering.h" +#include "components/realizable.h" +#include "systems/realizing.h" +#include "vector.h" + +struct script_entity { + using id_type = EntityManager::id_type; + + id_type id; + + script_entity(id_type id) : id(id) + { + } +}; void AutomatingSystem::tick(double dt) { auto entities = game_.getEntityManager().getEntitiesWithComponents< - AutomatableComponent, - PonderableComponent>(); + AutomatableComponent>(); for (id_type entity : entities) { @@ -20,43 +31,7 @@ void AutomatingSystem::tick(double dt) continue; } - if (automatable.behaviorRunning && - (automatable.remaining <= 0.0)) - { - automatable.currentAction++; - automatable.actionRunning = false; - - if (automatable.currentAction == - automatable.behaviors[automatable.currentBehavior].size()) - { - automatable.behaviorRunning = false; - } - } - - if (!automatable.behaviorRunning) - { - automatable.currentBehavior = automatable.behaviorDist(game_.getRng()); - automatable.currentAction = 0; - automatable.behaviorRunning = true; - } - - AutomatableComponent::Action& curAction = - automatable.behaviors - [automatable.currentBehavior] - [automatable.currentAction]; - - if (!automatable.actionRunning) - { - automatable.remaining = curAction.dur; - automatable.actionRunning = true; - } - - auto& ponderable = game_.getEntityManager(). - getComponent(entity); - - ponderable.vel = curAction.speed; - - automatable.remaining -= dt; + (*automatable.behavior)(dt); } } @@ -65,6 +40,46 @@ void AutomatingSystem::initPrototype(id_type prototype) auto& automatable = game_.getEntityManager(). getComponent(prototype); - automatable.behaviorRunning = false; - automatable.actionRunning = false; + auto& realizable = game_.getEntityManager(). + getComponent( + game_.getSystemManager().getSystem().getSingleton()); + automatable.behavior.reset(); + automatable.runner = std::unique_ptr(new sol::thread(sol::thread::create(realizable.scriptEngine.lua_state()))); + automatable.behavior = std::unique_ptr(new sol::coroutine(automatable.runner->state()["run"])); + (*automatable.behavior)(script_entity(prototype)); +} + +void AutomatingSystem::initScriptEngine(sol::state& scriptEngine) +{ + scriptEngine.open_libraries(sol::lib::base, sol::lib::coroutine); + scriptEngine.new_usertype( + "vec2d", + sol::constructors(), + "x", sol::property( + [] (vec2d& v) -> double { return v.x(); }, + [] (vec2d& v, double x) { v.x() = x; }), + "y", sol::property( + [] (vec2d& v) -> double { return v.y(); }, + [] (vec2d& v, double y) { v.y() = y; })); + + scriptEngine.new_usertype( + "vec2i", + sol::constructors(), + "x", [] (vec2i& v) -> int& { return v.x(); }, + "y", [] (vec2i& v) -> int& { return v.y(); }); + + scriptEngine.new_usertype( + "entity", + sol::constructors(), + "id", &script_entity::id, + "ponderable", + [&] (script_entity& entity) -> PonderableComponent& { + return game_.getEntityManager(). + getComponent(entity.id); + }); + + scriptEngine.new_usertype( + "ponderable", + "vel", &PonderableComponent::vel, + "accel", &PonderableComponent::accel); } diff --git a/src/systems/automating.h b/src/systems/automating.h index c78b7cf..117b622 100644 --- a/src/systems/automating.h +++ b/src/systems/automating.h @@ -2,6 +2,7 @@ #define AUTOMATING_H_E6E5D76E #include "system.h" +#include class AutomatingSystem : public System { public: @@ -14,6 +15,8 @@ public: void initPrototype(id_type prototype); + void initScriptEngine(sol::state& scriptEngine); + }; #endif /* end of include guard: AUTOMATING_H_E6E5D76E */ diff --git a/src/systems/realizing.cpp b/src/systems/realizing.cpp index f9285ad..28e2279 100644 --- a/src/systems/realizing.cpp +++ b/src/systems/realizing.cpp @@ -29,92 +29,6 @@ inline xmlChar* getProp(xmlNodePtr node, const char* attr) return key; } -void parseAI( - xmlNodePtr node, - std::vector& behavior, - const std::map& items) -{ - xmlChar* key = nullptr; - - if (!xmlStrcmp( - node->name, - reinterpret_cast("switch"))) - { - key = getProp(node, "item"); - std::string switchItem = reinterpret_cast(key); - xmlFree(key); - - for (xmlNodePtr switchNode = node->xmlChildrenNode; - switchNode != nullptr; - switchNode = switchNode->next) - { - if (!xmlStrcmp( - switchNode->name, - reinterpret_cast("case"))) - { - key = getProp(switchNode, "value"); - int caseValue = atoi(reinterpret_cast(key)); - xmlFree(key); - - if (items.at(switchItem) == caseValue) - { - for (xmlNodePtr caseNode = switchNode->xmlChildrenNode; - caseNode != nullptr; - caseNode = caseNode->next) - { - parseAI( - caseNode, - behavior, - items); - } - } - } - } - } else if (!xmlStrcmp( - node->name, - reinterpret_cast("move"))) - { - key = getProp(node, "direction"); - std::string direction = reinterpret_cast(key); - xmlFree(key); - - key = getProp(node, "length-var"); - std::string lengthVar = reinterpret_cast(key); - xmlFree(key); - - key = getProp(node, "speed-var"); - std::string speedVar = reinterpret_cast(key); - xmlFree(key); - - double length = items.at(lengthVar); - double speed = items.at(speedVar); - - AutomatableComponent::Action action; - - if (direction == "left") - { - action.speed.x() = -speed; - action.speed.y() = 0; - } else if (direction == "right") - { - action.speed.x() = speed; - action.speed.y() = 0; - } else if (direction == "up") - { - action.speed.x() = 0; - action.speed.y() = -speed; - } else if (direction == "down") - { - action.speed.x() = 0; - action.speed.y() = speed; - } - - action.dur = length / speed; - - behavior.push_back(std::move(action)); - } -} - // TODO: neither the XML doc nor any of the emplaced entities are properly // destroyed if this method throws an exception. EntityManager::id_type RealizingSystem::initSingleton( @@ -126,6 +40,9 @@ EntityManager::id_type RealizingSystem::initSingleton( auto& realizable = game_.getEntityManager(). emplaceComponent(world); + game_.getSystemManager().getSystem(). + initScriptEngine(realizable.scriptEngine); + realizable.worldFile = worldFile; realizable.prototypeFile = prototypeFile; @@ -299,68 +216,14 @@ EntityManager::id_type RealizingSystem::initSingleton( game_.getSystemManager().getSystem(). initializeBody(mapObject, PonderableComponent::Type::vacuumed); - // Look for any object configuration. - std::map items; - - for (xmlNodePtr objectNode = mapNode->xmlChildrenNode; - objectNode != nullptr; - objectNode = objectNode->next) + if (prototypeId == "movplat") { - if (!xmlStrcmp( - objectNode->name, - reinterpret_cast("item"))) - { - key = getProp(objectNode, "id"); - std::string itemName = reinterpret_cast(key); - xmlFree(key); - - key = xmlNodeGetContent(objectNode); - int itemVal = atoi(reinterpret_cast(key)); - xmlFree(key); - - items[itemName] = itemVal; - } - } + auto& automatable = game_.getEntityManager(). + emplaceComponent(mapObject); - // Add any AI behaviors. - std::vector behaviorWeights; - for (xmlNodePtr protoSubNode = prototypeNode->xmlChildrenNode; - protoSubNode != nullptr; - protoSubNode = protoSubNode->next) - { - if (!xmlStrcmp( - protoSubNode->name, - reinterpret_cast("ai"))) - { - if (!game_.getEntityManager(). - hasComponent(mapObject)) - { - game_.getEntityManager(). - emplaceComponent(mapObject); - } - - auto& automatable = game_.getEntityManager(). - getComponent(mapObject); - - key = getProp(protoSubNode, "chance"); - behaviorWeights.push_back(atof(reinterpret_cast(key))); - xmlFree(key); - - std::vector behavior; - - for (xmlNodePtr aiNode = protoSubNode->xmlChildrenNode; - aiNode != nullptr; - aiNode = aiNode->next) - { - parseAI( - aiNode, - behavior, - items); - } - - automatable.behaviors.push_back(std::move(behavior)); - } + realizable.scriptEngine.script_file( + "res/platform.lua");//, } mappable.objects.push_back(mapObject); diff --git a/src/vector.h b/src/vector.h index 3abd98a..9355dd5 100644 --- a/src/vector.h +++ b/src/vector.h @@ -7,9 +7,11 @@ public: T coords[2]; - vec2() = default; + vec2() : coords{0, 0} + { + } - vec2(double x, double y) : coords{x, y} + vec2(T x, T y) : coords{x, y} { } @@ -90,12 +92,12 @@ public: return vec2(-x(), -y()); } - vec2 operator*(double s) const + vec2 operator*(T s) const { return vec2(x() * s, y() * s); } - vec2& operator*=(double s) + vec2& operator*=(T s) { x() *= s; y() *= s; diff --git a/vendor/sol.hpp b/vendor/sol.hpp new file mode 100644 index 0000000..d033cba --- /dev/null +++ b/vendor/sol.hpp @@ -0,0 +1,21575 @@ +// The MIT License (MIT) + +// Copyright (c) 2013-2018 Rapptz, ThePhD and contributors + +// Permission is hereby granted, free of charge, to any person obtaining a copy of +// this software and associated documentation files (the "Software"), to deal in +// the Software without restriction, including without limitation the rights to +// use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of +// the Software, and to permit persons to whom the Software is furnished to do so, +// subject to the following conditions: + +// The above copyright notice and this permission notice shall be included in all +// copies or substantial portions of the Software. + +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS +// FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR +// COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER +// IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN +// CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + +// This file was generated with a script. +// Generated 2018-04-18 00:12:41.772355 UTC +// This header was generated with sol v2.20.0 (revision 8b77411) +// https://github.com/ThePhD/sol2 + +#ifndef SOL_SINGLE_INCLUDE_HPP +#define SOL_SINGLE_INCLUDE_HPP + +// beginning of sol.hpp + +#ifndef SOL_HPP +#define SOL_HPP + +#if defined(UE_BUILD_DEBUG) || defined(UE_BUILD_DEVELOPMENT) || defined(UE_BUILD_TEST) || defined(UE_BUILD_SHIPPING) || defined(UE_SERVER) +#define SOL_INSIDE_UNREAL 1 +#endif // Unreal Engine 4 bullshit + +#if defined(SOL_INSIDE_UNREAL) && SOL_INSIDE_UNREAL +#ifdef check +#define SOL_INSIDE_UNREAL_REMOVED_CHECK +#undef check +#endif +#endif // Unreal Engine 4 Bullshit + +#if defined(__GNUC__) +#pragma GCC diagnostic push +#pragma GCC diagnostic ignored "-Wshadow" +#pragma GCC diagnostic ignored "-Wconversion" +#if __GNUC__ > 6 +#pragma GCC diagnostic ignored "-Wnoexcept-type" +#endif +#elif defined(__clang__) +#elif defined _MSC_VER +#pragma warning( push ) +#pragma warning( disable : 4324 ) // structure was padded due to alignment specifier +#pragma warning( disable : 4503 ) // decorated name horse shit +#pragma warning( disable : 4702 ) // unreachable code +#pragma warning( disable: 4127 ) // 'conditional expression is constant' yeah that's the point your old compilers don't have `if constexpr` you jerk +#pragma warning( disable: 4505 ) // some other nonsense warning +#endif // clang++ vs. g++ vs. VC++ + +// beginning of sol/forward.hpp + +// beginning of sol/feature_test.hpp + +#if (defined(__cplusplus) && __cplusplus == 201703L) || (defined(_MSC_VER) && _MSC_VER > 1900 && ((defined(_HAS_CXX17) && _HAS_CXX17 == 1) || (defined(_MSVC_LANG) && (_MSVC_LANG > 201402L)))) +#ifndef SOL_CXX17_FEATURES +#define SOL_CXX17_FEATURES 1 +#endif // C++17 features macro +#endif // C++17 features check + +#if defined(SOL_CXX17_FEATURES) && SOL_CXX17_FEATURES +#if defined(__cpp_noexcept_function_type) || ((defined(_MSC_VER) && _MSC_VER > 1911) && (defined(_MSVC_LANG) && ((_MSVC_LANG >= 201403L)))) +#ifndef SOL_NOEXCEPT_FUNCTION_TYPE +#define SOL_NOEXCEPT_FUNCTION_TYPE 1 +#endif // noexcept is part of a function's type +#endif // compiler-specific checks +#if defined(__clang__) && defined(__APPLE__) +#if defined(__has_include) +#if __has_include() +#define SOL_STD_VARIANT 1 +#endif // has include nonsense +#endif // __has_include +#else +#define SOL_STD_VARIANT 1 +#endif // Clang screws up variant +#endif // C++17 only + +// beginning of sol/config.hpp + +#ifdef _MSC_VER + #if defined(_DEBUG) && !defined(NDEBUG) + + #ifndef SOL_IN_DEBUG_DETECTED + #define SOL_IN_DEBUG_DETECTED 1 + #endif + + #endif // VC++ Debug macros + + #ifndef _CPPUNWIND + #ifndef SOL_NO_EXCEPTIONS + #define SOL_NO_EXCEPTIONS 1 + #endif + #endif // Automatic Exceptions + + #ifndef _CPPRTTI + #ifndef SOL_NO_RTTI + #define SOL_NO_RTTI 1 + #endif + #endif // Automatic RTTI +#elif defined(__GNUC__) || defined(__clang__) + + #if !defined(NDEBUG) && !defined(__OPTIMIZE__) + + #ifndef SOL_IN_DEBUG_DETECTED + #define SOL_IN_DEBUG_DETECTED 1 + #endif + + #endif // Not Debug && g++ optimizer flag + + #ifndef __EXCEPTIONS + #ifndef SOL_NO_EXCEPTIONS + #define SOL_NO_EXCEPTIONS 1 + #endif + #endif // No Exceptions + + #ifndef __GXX_RTTI + #ifndef SOL_NO_RTII + #define SOL_NO_RTTI 1 + #endif + #endif // No RTTI + +#endif // vc++ || clang++/g++ + +#if defined(SOL_CHECK_ARGUMENTS) && SOL_CHECK_ARGUMENTS + + // Checks low-level getter function + // (and thusly, affects nearly entire framework) + #if !defined(SOL_SAFE_GETTER) + #define SOL_SAFE_GETTER 1 + #endif + + // Checks access on usertype functions + // local my_obj = my_type.new() + // my_obj.my_member_function() + // -- bad syntax and crash + #if !defined(SOL_SAFE_USERTYPE) + #define SOL_SAFE_USERTYPE 1 + #endif + + // Checks sol::reference derived boundaries + // sol::function ref(L, 1); + // sol::userdata sref(L, 2); + #if !defined(SOL_SAFE_REFERENCES) + #define SOL_SAFE_REFERENCES 1 + #endif + + // Changes all typedefs of sol::function to point to the + // protected_function version, instead of unsafe_function + #if !defined(SOL_SAFE_FUNCTION) + #define SOL_SAFE_FUNCTION 1 + #endif + + // Checks function parameters and + // returns upon call into/from Lua + // local a = 1 + // local b = "woof" + // my_c_function(a, b) + #if !defined(SOL_SAFE_FUNCTION_CALLS) + #define SOL_SAFE_FUNCTION_CALLS 1 + #endif + + // Checks conversions + // int v = lua["bark"]; + // int v2 = my_sol_function(); + #if !defined(SOL_SAFE_PROXIES) + #define SOL_SAFE_PROXIES 1 + #endif + + // Check overflowing number conversions + // for things like 64 bit integers that don't fit in a typical lua_Number + // for Lua 5.1 and 5.2 + #if !defined(SOL_SAFE_NUMERICS) + #define SOL_SAFE_NUMERICS 1 + #endif + + // Turn off Number Precision Checks + // if this is defined, we do not do range + // checks on integers / unsigned integers that might + // be bigger than what Lua can represent + #if !defined(SOL_NO_CHECK_NUMBER_PRECISION) + // off by default + #define SOL_NO_CHECK_NUMBER_PRECISION 0 + #endif + +#endif // Turn on Safety for all if top-level macro is defined + +#if defined(SOL_IN_DEBUG_DETECTED) && SOL_IN_DEBUG_DETECTED + + #if !defined(SOL_SAFE_REFERENCES) + // Ensure that references are forcefully type-checked upon construction + #define SOL_SAFE_REFERENCES 1 + #endif + + // Safe usertypes checks for errors such as + // obj = my_type.new() + // obj.f() -- note the '.' instead of ':' + // usertypes should be safe no matter what + #if !defined(SOL_SAFE_USERTYPE) + #define SOL_SAFE_USERTYPE 1 + #endif + + #if !defined(SOL_SAFE_FUNCTION_CALLS) + // Function calls from Lua should be automatically safe in debug mode + #define SOL_SAFE_FUNCTION_CALLS 1 + #endif + + // Print any exceptions / errors that occur + // in debug mode to the default error stream / console + #if !defined(SOL_PRINT_ERRORS) + #define SOL_PRINT_ERRORS 1 + #endif + +#endif // DEBUG: Turn on all debug safety features for VC++ / g++ / clang++ and similar + +#if !defined(SOL_PRINT_ERRORS) +#define SOL_PRINT_ERRORS 0 +#endif + +#if !defined(SOL_DEFAULT_PASS_ON_ERROR) +#define SOL_DEFAULT_PASS_ON_ERROR 0 +#endif + +#if !defined(SOL_ENABLE_INTEROP) +#define SOL_ENABLE_INTEROP 0 +#endif + +#if defined(__MAC_OS_X_VERSION_MAX_ALLOWED) || defined(__OBJC__) || defined(nil) +#if !defined(SOL_NO_NIL) +#define SOL_NO_NIL 1 +#endif +#endif // avoiding nil defines / keywords + +#if defined(SOL_USE_BOOST) && SOL_USE_BOOST +#ifndef SOL_UNORDERED_MAP_COMPATIBLE_HASH +#define SOL_UNORDERED_MAP_COMPATIBLE_HASH 1 +#endif // SOL_UNORDERED_MAP_COMPATIBLE_HASH +#endif + +#ifndef SOL_STACK_STRING_OPTIMIZATION_SIZE +#define SOL_STACK_STRING_OPTIMIZATION_SIZE 1024 +#endif // Optimized conversion routines using a KB or so off the stack + +// end of sol/config.hpp + +// end of sol/feature_test.hpp + +namespace sol { + + template + class basic_reference; + using reference = basic_reference; + using main_reference = basic_reference; + class stack_reference; + + struct proxy_base_tag; + template + struct proxy_base; + template + struct proxy; + + template + class usertype; + template + class simple_usertype; + template + class basic_table_core; + template + using table_core = basic_table_core; + template + using main_table_core = basic_table_core; + template + using stack_table_core = basic_table_core; + template + using basic_table = basic_table_core; + typedef table_core table; + typedef table_core global_table; + typedef main_table_core main_table; + typedef main_table_core main_global_table; + typedef stack_table_core stack_table; + typedef stack_table_core stack_global_table; + template + struct basic_environment; + using environment = basic_environment; + using main_environment = basic_environment; + using stack_environment = basic_environment; + template + class basic_function; + template + class basic_protected_function; + using unsafe_function = basic_function; + using safe_function = basic_protected_function; + using main_unsafe_function = basic_function; + using main_safe_function = basic_protected_function; + using stack_unsafe_function = basic_function; + using stack_safe_function = basic_protected_function; + using stack_aligned_unsafe_function = basic_function; + using stack_aligned_safe_function = basic_protected_function; + using protected_function = safe_function; + using main_protected_function = main_safe_function; + using stack_protected_function = stack_safe_function; + using stack_aligned_protected_function = stack_aligned_safe_function; +#if defined(SOL_SAFE_FUNCTION) && SOL_SAFE_FUNCTION + using function = protected_function; + using main_function = main_protected_function; + using stack_function = stack_protected_function; +#else + using function = unsafe_function; + using main_function = main_unsafe_function; + using stack_function = stack_unsafe_function; +#endif + using stack_aligned_function = stack_aligned_unsafe_function; + using stack_aligned_stack_handler_function = basic_protected_function; + + struct unsafe_function_result; + struct protected_function_result; + using safe_function_result = protected_function_result; +#if defined(SOL_SAFE_FUNCTION) && SOL_SAFE_FUNCTION + using function_result = safe_function_result; +#else + using function_result = unsafe_function_result; +#endif + + template + class basic_object; + template + class basic_userdata; + template + class basic_lightuserdata; + template + class basic_coroutine; + template + class basic_thread; + + using object = basic_object; + using userdata = basic_userdata; + using lightuserdata = basic_lightuserdata; + using thread = basic_thread; + using coroutine = basic_coroutine; + using main_object = basic_object; + using main_userdata = basic_userdata; + using main_lightuserdata = basic_lightuserdata; + using main_coroutine = basic_coroutine; + using stack_object = basic_object; + using stack_userdata = basic_userdata; + using stack_lightuserdata = basic_lightuserdata; + using stack_thread = basic_thread; + using stack_coroutine = basic_coroutine; + + struct stack_proxy_base; + struct stack_proxy; + struct variadic_args; + struct variadic_results; + struct stack_count; + struct this_state; + struct this_main_state; + struct this_environment; + + template + struct as_table_t; + template + struct as_container_t; + template + struct nested; + template + struct light; + template + struct user; + template + struct as_args_t; + template + struct protect_t; + template + struct filter_wrapper; +} // namespace sol + +// end of sol/forward.hpp + +// beginning of sol/state.hpp + +// beginning of sol/state_view.hpp + +// beginning of sol/error.hpp + +#include +#include + +namespace sol { + namespace detail { + struct direct_error_tag {}; + const auto direct_error = direct_error_tag{}; + } // namespace detail + + class error : public std::runtime_error { + private: + // Because VC++ is upsetting, most of the time! + std::string w; + + public: + error(const std::string& str) + : error(detail::direct_error, "lua: error: " + str) { + } + error(std::string&& str) + : error(detail::direct_error, "lua: error: " + std::move(str)) { + } + error(detail::direct_error_tag, const std::string& str) + : std::runtime_error(""), w(str) { + } + error(detail::direct_error_tag, std::string&& str) + : std::runtime_error(""), w(std::move(str)) { + } + + error(const error& e) = default; + error(error&& e) = default; + error& operator=(const error& e) = default; + error& operator=(error&& e) = default; + + virtual const char* what() const noexcept override { + return w.c_str(); + } + }; + +} // namespace sol + +// end of sol/error.hpp + +// beginning of sol/table.hpp + +// beginning of sol/table_core.hpp + +// beginning of sol/proxy.hpp + +// beginning of sol/traits.hpp + +// beginning of sol/tuple.hpp + +#include +#include + +namespace sol { + namespace detail { + using swallow = std::initializer_list; + } // namespace detail + + template + struct types { + typedef std::make_index_sequence indices; + static constexpr std::size_t size() { + return sizeof...(Args); + } + }; + namespace meta { + namespace detail { + template + struct tuple_types_ { typedef types type; }; + + template + struct tuple_types_> { typedef types type; }; + } // namespace detail + + template + using unqualified = std::remove_cv>; + + template + using unqualified_t = typename unqualified::type; + + template + using tuple_types = typename detail::tuple_types_::type; + + template + struct pop_front_type; + + template + using pop_front_type_t = typename pop_front_type::type; + + template + struct pop_front_type> { + typedef void front_type; + typedef types type; + }; + + template + struct pop_front_type> { + typedef Arg front_type; + typedef types type; + }; + + template + using tuple_element = std::tuple_element>; + + template + using tuple_element_t = std::tuple_element_t>; + + template + using unqualified_tuple_element = unqualified>; + + template + using unqualified_tuple_element_t = unqualified_t>; + + } // namespace meta +} // namespace sol + +// end of sol/tuple.hpp + +// beginning of sol/bind_traits.hpp + +namespace sol { +namespace meta { + namespace meta_detail { + + template + struct check_deducible_signature { + struct nat {}; + template + static auto test(int) -> decltype(&G::operator(), void()); + template + static auto test(...) -> nat; + + using type = std::is_void(0))>; + }; + } // namespace meta_detail + + template + struct has_deducible_signature : meta_detail::check_deducible_signature::type {}; + + namespace meta_detail { + + template + struct void_tuple_element : meta::tuple_element {}; + + template + struct void_tuple_element> { typedef void type; }; + + template + using void_tuple_element_t = typename void_tuple_element::type; + + template + struct basic_traits { + private: + typedef std::conditional_t::value, int, T>& first_type; + + public: + static const bool is_noexcept = it_is_noexcept; + static const bool is_member_function = std::is_void::value; + static const bool has_c_var_arg = has_c_variadic; + static const std::size_t arity = sizeof...(Args); + static const std::size_t free_arity = sizeof...(Args) + static_cast(!std::is_void::value); + typedef types args_list; + typedef std::tuple args_tuple; + typedef T object_type; + typedef R return_type; + typedef tuple_types returns_list; + typedef R(function_type)(Args...); + typedef std::conditional_t::value, args_list, types> free_args_list; + typedef std::conditional_t::value, R(Args...), R(first_type, Args...)> free_function_type; + typedef std::conditional_t::value, R (*)(Args...), R (*)(first_type, Args...)> free_function_pointer_type; + typedef std::remove_pointer_t signature_type; + template + using arg_at = void_tuple_element_t; + }; + + template ::value> + struct fx_traits : basic_traits {}; + + // Free Functions + template + struct fx_traits : basic_traits { + typedef R (*function_pointer_type)(Args...); + }; + + template + struct fx_traits : basic_traits { + typedef R (*function_pointer_type)(Args...); + }; + + template + struct fx_traits : basic_traits { + typedef R (*function_pointer_type)(Args..., ...); + }; + + template + struct fx_traits : basic_traits { + typedef R (*function_pointer_type)(Args..., ...); + }; + + // Member Functions + /* C-Style Variadics */ + template + struct fx_traits : basic_traits { + typedef R (T::*function_pointer_type)(Args...); + }; + + template + struct fx_traits : basic_traits { + typedef R (T::*function_pointer_type)(Args..., ...); + }; + + /* Const Volatile */ + template + struct fx_traits : basic_traits { + typedef R (T::*function_pointer_type)(Args...) const; + }; + + template + struct fx_traits : basic_traits { + typedef R (T::*function_pointer_type)(Args..., ...) const; + }; + + template + struct fx_traits : basic_traits { + typedef R (T::*function_pointer_type)(Args...) const volatile; + }; + + template + struct fx_traits : basic_traits { + typedef R (T::*function_pointer_type)(Args..., ...) const volatile; + }; + + /* Member Function Qualifiers */ + template + struct fx_traits : basic_traits { + typedef R (T::*function_pointer_type)(Args...) &; + }; + + template + struct fx_traits : basic_traits { + typedef R (T::*function_pointer_type)(Args..., ...) &; + }; + + template + struct fx_traits : basic_traits { + typedef R (T::*function_pointer_type)(Args...) const&; + }; + + template + struct fx_traits : basic_traits { + typedef R (T::*function_pointer_type)(Args..., ...) const&; + }; + + template + struct fx_traits : basic_traits { + typedef R (T::*function_pointer_type)(Args...) const volatile&; + }; + + template + struct fx_traits : basic_traits { + typedef R (T::*function_pointer_type)(Args..., ...) const volatile&; + }; + + template + struct fx_traits : basic_traits { + typedef R (T::*function_pointer_type)(Args...) &&; + }; + + template + struct fx_traits : basic_traits { + typedef R (T::*function_pointer_type)(Args..., ...) &&; + }; + + template + struct fx_traits : basic_traits { + typedef R (T::*function_pointer_type)(Args...) const&&; + }; + + template + struct fx_traits : basic_traits { + typedef R (T::*function_pointer_type)(Args..., ...) const&&; + }; + + template + struct fx_traits : basic_traits { + typedef R (T::*function_pointer_type)(Args...) const volatile&&; + }; + + template + struct fx_traits : basic_traits { + typedef R (T::*function_pointer_type)(Args..., ...) const volatile&&; + }; + +#if defined(SOL_NOEXCEPT_FUNCTION_TYPE) && SOL_NOEXCEPT_FUNCTION_TYPE + + template + struct fx_traits : basic_traits { + typedef R (*function_pointer_type)(Args...) noexcept; + }; + + template + struct fx_traits : basic_traits { + typedef R (*function_pointer_type)(Args...) noexcept; + }; + + template + struct fx_traits : basic_traits { + typedef R (*function_pointer_type)(Args..., ...) noexcept; + }; + + template + struct fx_traits : basic_traits { + typedef R (*function_pointer_type)(Args..., ...) noexcept; + }; + + template + struct fx_traits : basic_traits { + typedef R (T::*function_pointer_type)(Args...) noexcept; + }; + + template + struct fx_traits : basic_traits { + typedef R (T::*function_pointer_type)(Args..., ...) noexcept; + }; + + /* Const Volatile */ + template + struct fx_traits : basic_traits { + typedef R (T::*function_pointer_type)(Args...) const noexcept; + }; + + template + struct fx_traits : basic_traits { + typedef R (T::*function_pointer_type)(Args..., ...) const noexcept; + }; + + template + struct fx_traits : basic_traits { + typedef R (T::*function_pointer_type)(Args...) const volatile noexcept; + }; + + template + struct fx_traits : basic_traits { + typedef R (T::*function_pointer_type)(Args..., ...) const volatile noexcept; + }; + + template + struct fx_traits : basic_traits { + typedef R (T::*function_pointer_type)(Args...) & noexcept; + }; + + template + struct fx_traits : basic_traits { + typedef R (T::*function_pointer_type)(Args..., ...) & noexcept; + }; + + template + struct fx_traits : basic_traits { + typedef R (T::*function_pointer_type)(Args...) const& noexcept; + }; + + template + struct fx_traits : basic_traits { + typedef R (T::*function_pointer_type)(Args..., ...) const& noexcept; + }; + + template + struct fx_traits : basic_traits { + typedef R (T::*function_pointer_type)(Args...) const volatile& noexcept; + }; + + template + struct fx_traits : basic_traits { + typedef R (T::*function_pointer_type)(Args..., ...) const volatile& noexcept; + }; + + template + struct fx_traits : basic_traits { + typedef R (T::*function_pointer_type)(Args...) && noexcept; + }; + + template + struct fx_traits : basic_traits { + typedef R (T::*function_pointer_type)(Args..., ...) && noexcept; + }; + + template + struct fx_traits : basic_traits { + typedef R (T::*function_pointer_type)(Args...) const&& noexcept; + }; + + template + struct fx_traits : basic_traits { + typedef R (T::*function_pointer_type)(Args..., ...) const&& noexcept; + }; + + template + struct fx_traits : basic_traits { + typedef R (T::*function_pointer_type)(Args...) const volatile&& noexcept; + }; + + template + struct fx_traits : basic_traits { + typedef R (T::*function_pointer_type)(Args..., ...) const volatile&& noexcept; + }; + +#endif // noexcept is part of a function's type + +#if defined(_MSC_VER) && defined(_M_IX86) + template + struct fx_traits : basic_traits { + typedef R(__stdcall* function_pointer_type)(Args...); + }; + + template + struct fx_traits : basic_traits { + typedef R(__stdcall* function_pointer_type)(Args...); + }; + + template + struct fx_traits : basic_traits { + typedef R (__stdcall T::*function_pointer_type)(Args...); + }; + + /* Const Volatile */ + template + struct fx_traits : basic_traits { + typedef R (__stdcall T::*function_pointer_type)(Args...) const; + }; + + template + struct fx_traits : basic_traits { + typedef R (__stdcall T::*function_pointer_type)(Args...) const volatile; + }; + + /* Member Function Qualifiers */ + template + struct fx_traits : basic_traits { + typedef R (__stdcall T::*function_pointer_type)(Args...) &; + }; + + template + struct fx_traits : basic_traits { + typedef R (__stdcall T::*function_pointer_type)(Args...) const&; + }; + + template + struct fx_traits : basic_traits { + typedef R (__stdcall T::*function_pointer_type)(Args...) const volatile&; + }; + + template + struct fx_traits : basic_traits { + typedef R (__stdcall T::*function_pointer_type)(Args...) &&; + }; + + template + struct fx_traits : basic_traits { + typedef R (__stdcall T::*function_pointer_type)(Args...) const&&; + }; + + template + struct fx_traits : basic_traits { + typedef R (__stdcall T::*function_pointer_type)(Args...) const volatile&&; + }; + +#if defined(SOL_NOEXCEPT_FUNCTION_TYPE) && SOL_NOEXCEPT_FUNCTION_TYPE + + template + struct fx_traits : basic_traits { + typedef R(__stdcall* function_pointer_type)(Args...) noexcept; + }; + + template + struct fx_traits : basic_traits { + typedef R(__stdcall* function_pointer_type)(Args...) noexcept; + }; + + /* __stdcall cannot be applied to functions with varargs*/ + /*template + struct fx_traits<__stdcall R(Args..., ...) noexcept, false> : basic_traits { + typedef R(__stdcall* function_pointer_type)(Args..., ...) noexcept; + }; + + template + struct fx_traits : basic_traits { + typedef R(__stdcall* function_pointer_type)(Args..., ...) noexcept; + };*/ + + template + struct fx_traits : basic_traits { + typedef R (__stdcall T::*function_pointer_type)(Args...) noexcept; + }; + + /* __stdcall does not work with varargs */ + /*template + struct fx_traits : basic_traits { + typedef R (__stdcall T::*function_pointer_type)(Args..., ...) noexcept; + };*/ + + /* Const Volatile */ + template + struct fx_traits : basic_traits { + typedef R (__stdcall T::*function_pointer_type)(Args...) const noexcept; + }; + + /* __stdcall does not work with varargs */ + /*template + struct fx_traits : basic_traits { + typedef R (__stdcall T::*function_pointer_type)(Args..., ...) const noexcept; + };*/ + + template + struct fx_traits : basic_traits { + typedef R (__stdcall T::*function_pointer_type)(Args...) const volatile noexcept; + }; + + /* __stdcall does not work with varargs */ + /*template + struct fx_traits : basic_traits { + typedef R (__stdcall T::*function_pointer_type)(Args..., ...) const volatile noexcept; + };*/ + + template + struct fx_traits : basic_traits { + typedef R (__stdcall T::*function_pointer_type)(Args...) & noexcept; + }; + + /* __stdcall does not work with varargs */ + /*template + struct fx_traits : basic_traits { + typedef R (__stdcall T::*function_pointer_type)(Args..., ...) & noexcept; + };*/ + + template + struct fx_traits : basic_traits { + typedef R (__stdcall T::*function_pointer_type)(Args...) const& noexcept; + }; + + /* __stdcall does not work with varargs */ + /*template + struct fx_traits : basic_traits { + typedef R (__stdcall T::*function_pointer_type)(Args..., ...) const& noexcept; + };*/ + + template + struct fx_traits : basic_traits { + typedef R (__stdcall T::*function_pointer_type)(Args...) const volatile& noexcept; + }; + + /* __stdcall does not work with varargs */ + /*template + struct fx_traits : basic_traits { + typedef R (__stdcall T::*function_pointer_type)(Args..., ...) const volatile& noexcept; + };*/ + + template + struct fx_traits : basic_traits { + typedef R (__stdcall T::*function_pointer_type)(Args...) && noexcept; + }; + + /* __stdcall does not work with varargs */ + /*template + struct fx_traits : basic_traits { + typedef R (__stdcall T::*function_pointer_type)(Args..., ...) && noexcept; + };*/ + + template + struct fx_traits : basic_traits { + typedef R (__stdcall T::*function_pointer_type)(Args...) const&& noexcept; + }; + + /* __stdcall does not work with varargs */ + /*template + struct fx_traits : basic_traits { + typedef R (__stdcall T::*function_pointer_type)(Args..., ...) const&& noexcept; + };*/ + + template + struct fx_traits : basic_traits { + typedef R (__stdcall T::*function_pointer_type)(Args...) const volatile&& noexcept; + }; + + /* __stdcall does not work with varargs */ + /*template + struct fx_traits : basic_traits { + typedef R (__stdcall T::*function_pointer_type)(Args..., ...) const volatile&& noexcept; + };*/ +#endif // noexcept is part of a function's type +#endif // __stdcall x86 VC++ bug + + template + struct fx_traits : fx_traits::function_type, false> {}; + + template ::value> + struct callable_traits : fx_traits> { + }; + + template + struct callable_traits { + typedef std::conditional_t::value, std::add_lvalue_reference_t, R> return_type; + typedef return_type Arg; + typedef T object_type; + using signature_type = R(T::*); + static const bool is_noexcept = false; + static const bool is_member_function = false; + static const std::size_t arity = 1; + static const std::size_t free_arity = 2; + typedef std::tuple args_tuple; + typedef types args_list; + typedef types free_args_list; + typedef meta::tuple_types returns_list; + typedef return_type(function_type)(T&, return_type); + typedef return_type(*function_pointer_type)(T&, Arg); + typedef return_type(*free_function_pointer_type)(T&, Arg); + template + using arg_at = void_tuple_element_t; + }; + + } // namespace meta_detail + + template + struct bind_traits : meta_detail::callable_traits {}; + + template + using function_args_t = typename bind_traits::args_list; + + template + using function_signature_t = typename bind_traits::signature_type; + + template + using function_return_t = typename bind_traits::return_type; +} +} // namespace sol::meta + +// end of sol/bind_traits.hpp + +// beginning of sol/string_view.hpp + +#if defined(SOL_CXX17_FEATURES) && SOL_CXX17_FEATURES +#include +#endif // C++17 features +#include +#if defined(SOL_USE_BOOST) && SOL_USE_BOOST +#include +#endif + +namespace sol { +#if defined(SOL_CXX17_FEATURES) && SOL_CXX17_FEATURES + template > + using basic_string_view = std::basic_string_view; + typedef std::string_view string_view; + typedef std::wstring_view wstring_view; + typedef std::u16string_view u16string_view; + typedef std::u32string_view u32string_view; + typedef std::hash string_view_hash; +#else + template > + struct basic_string_view { + std::size_t s; + const Char* p; + + basic_string_view(const std::string& r) + : basic_string_view(r.data(), r.size()) { + } + basic_string_view(const Char* ptr) + : basic_string_view(ptr, Traits::length(ptr)) { + } + basic_string_view(const Char* ptr, std::size_t sz) + : s(sz), p(ptr) { + } + + static int compare(const Char* lhs_p, std::size_t lhs_sz, const Char* rhs_p, std::size_t rhs_sz) { + int result = Traits::compare(lhs_p, rhs_p, lhs_sz < rhs_sz ? lhs_sz : rhs_sz); + if (result != 0) + return result; + if (lhs_sz < rhs_sz) + return -1; + if (lhs_sz > rhs_sz) + return 1; + return 0; + } + + const Char* begin() const { + return p; + } + + const Char* end() const { + return p + s; + } + + const Char* cbegin() const { + return p; + } + + const Char* cend() const { + return p + s; + } + + const Char* data() const { + return p; + } + + std::size_t size() const { + return s; + } + + std::size_t length() const { + return size(); + } + + operator std::basic_string() const { + return std::basic_string(data(), size()); + } + + bool operator==(const basic_string_view& r) const { + return compare(p, s, r.data(), r.size()) == 0; + } + + bool operator==(const Char* r) const { + return compare(r, Traits::length(r), p, s) == 0; + } + + bool operator==(const std::basic_string& r) const { + return compare(r.data(), r.size(), p, s) == 0; + } + + bool operator!=(const basic_string_view& r) const { + return !(*this == r); + } + + bool operator!=(const char* r) const { + return !(*this == r); + } + + bool operator!=(const std::basic_string& r) const { + return !(*this == r); + } + }; + + template > + struct basic_string_view_hash { + typedef basic_string_view argument_type; + typedef std::size_t result_type; + + template + result_type operator()(const std::basic_string& r) const { + return (*this)(argument_type(r.c_str(), r.size())); + } + + result_type operator()(const argument_type& r) const { +#if defined(SOL_USE_BOOST) && SOL_USE_BOOST + return boost::hash_range(r.begin(), r.end()); +#else + // Modified, from libstdc++ + // An implementation attempt at Fowler No Voll, 1a. + // Supposedly, used in MSVC, + // GCC (libstdc++) uses MurmurHash of some sort for 64-bit though...? + // But, well. Can't win them all, right? + // This should normally only apply when NOT using boost, + // so this should almost never be tapped into... + std::size_t hash = 0; + const unsigned char* cptr = reinterpret_cast(r.data()); + for (std::size_t sz = r.size(); sz != 0; --sz) { + hash ^= static_cast(*cptr++); + hash *= static_cast(1099511628211ULL); + } + return hash; +#endif + } + }; +} // namespace sol + +namespace std { + template + struct hash< ::sol::basic_string_view > : ::sol::basic_string_view_hash {}; +} // namespace std + +namespace sol { + using string_view = basic_string_view; + using wstring_view = basic_string_view; + using u16string_view = basic_string_view; + using u32string_view = basic_string_view; + using string_view_hash = std::hash; +#endif // C++17 Support +} // namespace sol + +// end of sol/string_view.hpp + +#include +#include +#include +#include +#include + +namespace sol { + template + using index_value = std::integral_constant; + + namespace meta { + template + struct identity { typedef T type; }; + + template + using identity_t = typename identity::type; + + template + struct is_tuple : std::false_type {}; + + template + struct is_tuple> : std::true_type {}; + + template + struct is_builtin_type : std::integral_constant::value || std::is_pointer::value || std::is_array::value> {}; + + template + struct unwrapped { + typedef T type; + }; + + template + struct unwrapped> { + typedef T type; + }; + + template + using unwrapped_t = typename unwrapped::type; + + template + struct unwrap_unqualified : unwrapped> {}; + + template + using unwrap_unqualified_t = typename unwrap_unqualified::type; + + template + struct remove_member_pointer; + + template + struct remove_member_pointer { + typedef R type; + }; + + template + struct remove_member_pointer { + typedef R type; + }; + + template + using remove_member_pointer_t = remove_member_pointer; + + namespace meta_detail { + template class Templ> + struct is_specialization_of : std::false_type {}; + template class Templ> + struct is_specialization_of, Templ> : std::true_type {}; + } + + template class Templ> + using is_specialization_of = meta_detail::is_specialization_of, Templ>; + + template + struct all_same : std::true_type {}; + + template + struct all_same : std::integral_constant::value && all_same::value> {}; + + template + struct any_same : std::false_type {}; + + template + struct any_same : std::integral_constant::value || any_same::value> {}; + + template + using boolean = std::integral_constant; + + template + using invoke_t = typename T::type; + + template + using invoke_b = boolean; + + template + using neg = boolean; + + template + using condition = std::conditional_t; + + template + struct all : boolean {}; + + template + struct all : condition, boolean> {}; + + template + struct any : boolean {}; + + template + struct any : condition, any> {}; + + enum class enable_t { + _ + }; + + constexpr const auto enabler = enable_t::_; + + template + using disable_if_t = std::enable_if_t; + + template + using enable = std::enable_if_t::value, enable_t>; + + template + using disable = std::enable_if_t>::value, enable_t>; + + template + using enable_any = std::enable_if_t::value, enable_t>; + + template + using disable_any = std::enable_if_t>::value, enable_t>; + + template + struct find_in_pack_v : boolean {}; + + template + struct find_in_pack_v : any, find_in_pack_v> {}; + + namespace meta_detail { + template + struct index_in_pack : std::integral_constant {}; + + template + struct index_in_pack : std::conditional_t::value, std::integral_constant, index_in_pack> {}; + } // namespace meta_detail + + template + struct index_in_pack : meta_detail::index_in_pack<0, T, Args...> {}; + + template + struct index_in : meta_detail::index_in_pack<0, T, List> {}; + + template + struct index_in> : meta_detail::index_in_pack<0, T, Args...> {}; + + template + struct at_in_pack {}; + + template + using at_in_pack_t = typename at_in_pack::type; + + template + struct at_in_pack : std::conditional> {}; + + template + struct at_in_pack<0, Arg, Args...> { typedef Arg type; }; + + namespace meta_detail { + template class Pred, typename... Ts> + struct count_for_pack : std::integral_constant {}; + template class Pred, typename T, typename... Ts> + struct count_for_pack : std::conditional_t < sizeof...(Ts) + == 0 + || Limit<2, + std::integral_constant(Limit != 0 && Pred::value)>, + count_for_pack(Pred::value), Pred, Ts...>> {}; + template class Pred, typename... Ts> + struct count_2_for_pack : std::integral_constant {}; + template class Pred, typename T, typename U, typename... Ts> + struct count_2_for_pack : std::conditional_t(Pred::value)>, + count_2_for_pack(Pred::value), Pred, Ts...>> {}; + } // namespace meta_detail + + template