#include "StarLuaGameConverters.hpp" namespace Star { LuaValue LuaConverter::from(LuaEngine& engine, CollisionKind k) { return engine.createString(CollisionKindNames.getRight(k)); } Maybe LuaConverter::to(LuaEngine&, LuaValue const& v) { if (auto str = v.ptr()) return CollisionKindNames.maybeLeft(str->ptr()); return {}; } LuaValue LuaConverter::from(LuaEngine& engine, CollisionSet const& s) { auto collisionTable = engine.createTable(); int i = 1; for (auto const& v : CollisionKindNames) { if (s.contains(v.first)) { collisionTable.set(i++, v.second); } } return collisionTable; } Maybe LuaConverter::to(LuaEngine& engine, LuaValue const& v) { auto table = v.ptr(); if (!table) return {}; CollisionSet result; bool failed = false; table->iterate([&result, &failed, &engine](LuaValue, LuaValue value) { if (auto k = engine.luaMaybeTo(move(value))) { result.insert(*k); return true; } else { failed = true; return false; } }); if (failed) return {}; return result; } LuaValue LuaConverter::from(LuaEngine& engine, PlatformerAStar::Path const& path) { auto convertNode = [&engine](PlatformerAStar::Node const& node) { auto table = engine.createTable(); table.set("position", node.position); table.set("velocity", node.velocity); return table; }; LuaTable pathTable = engine.createTable(); int pathTableIndex = 1; for (auto const& edge : path) { auto edgeTable = engine.createTable(); edgeTable.set("cost", edge.cost); edgeTable.set("action", PlatformerAStar::ActionNames.getRight(edge.action)); edgeTable.set("jumpVelocity", edge.jumpVelocity); edgeTable.set("source", convertNode(edge.source)); edgeTable.set("target", convertNode(edge.target)); pathTable.set(pathTableIndex++, move(edgeTable)); } return pathTable; } LuaMethods LuaUserDataMethods::make() { LuaMethods methods; methods.registerMethodWithSignature, PlatformerAStar::PathFinder&, Maybe>( "explore", mem_fn(&PlatformerAStar::PathFinder::explore)); methods.registerMethodWithSignature, PlatformerAStar::PathFinder&>( "result", mem_fn(&PlatformerAStar::PathFinder::result)); return methods; } Maybe LuaConverter::to(LuaEngine&, LuaValue const& v) { PlatformerAStar::Parameters p; p.returnBest = false; p.mustEndOnGround = false; p.enableWalkSpeedJumps = false; p.enableVerticalJumpAirControl = false; if (v == LuaNil) return p; auto table = v.ptr(); if (!table) return {}; try { p.maxDistance = table->get>("maxDistance"); p.returnBest = table->get>("returnBest").value(false); p.mustEndOnGround = table->get>("mustEndOnGround").value(false); p.enableWalkSpeedJumps = table->get>("enableWalkSpeedJumps").value(false); p.enableVerticalJumpAirControl = table->get>("enableVerticalJumpAirControl").value(false); p.swimCost = table->get>("swimCost"); p.jumpCost = table->get>("jumpCost"); p.liquidJumpCost = table->get>("liquidJumpCost"); p.dropCost = table->get>("dropCost"); p.boundBox = table->get("boundBox"); p.standingBoundBox = table->get("standingBoundBox"); p.droppingBoundBox = table->get("droppingBoundBox"); p.smallJumpMultiplier = table->get>("smallJumpMultiplier"); p.jumpDropXMultiplier = table->get>("jumpDropXMultiplier"); p.maxFScore = table->get("maxFScore"); p.maxNodesToSearch = table->get("maxNodesToSearch"); p.maxLandingVelocity = table->get>("maxLandingVelocity"); } catch (LuaConversionException const&) { return {}; } return p; } LuaValue LuaConverter::from(LuaEngine& engine, ActorJumpProfile const& v) { auto table = engine.createTable(); table.set("jumpSpeed", v.jumpSpeed); table.set("jumpControlForce", v.jumpControlForce); table.set("jumpInitialPercentage", v.jumpInitialPercentage); table.set("jumpHoldTime", v.jumpHoldTime); table.set("jumpTotalHoldTime", v.jumpTotalHoldTime); table.set("multiJump", v.multiJump); table.set("reJumpDelay", v.reJumpDelay); table.set("autoJump", v.autoJump); table.set("collisionCancelled", v.collisionCancelled); return table; } Maybe LuaConverter::to(LuaEngine&, LuaValue const& v) { if (v == LuaNil) return ActorJumpProfile(); auto table = v.ptr(); if (!table) return {}; try { ActorJumpProfile ajp; ajp.jumpSpeed = table->get>("jumpSpeed"); ajp.jumpControlForce = table->get>("jumpControlForce"); ajp.jumpInitialPercentage = table->get>("jumpInitialPercentage"); ajp.jumpHoldTime = table->get>("jumpHoldTime"); ajp.jumpTotalHoldTime = table->get>("jumpTotalHoldTime"); ajp.multiJump = table->get>("multiJump"); ajp.reJumpDelay = table->get>("reJumpDelay"); ajp.autoJump = table->get>("autoJump"); ajp.collisionCancelled = table->get>("collisionCancelled"); return ajp; } catch (LuaConversionException const&) { return {}; } } LuaValue LuaConverter::from(LuaEngine& engine, ActorMovementParameters const& v) { auto table = engine.createTable(); table.set("mass", v.mass); table.set("gravityMultiplier", v.gravityMultiplier); table.set("liquidBuoyancy", v.liquidBuoyancy); table.set("airBuoyancy", v.airBuoyancy); table.set("bounceFactor", v.bounceFactor); table.set("slopeSlidingFactor", v.slopeSlidingFactor); table.set("maxMovementPerStep", v.maxMovementPerStep); table.set("maximumCorrection", v.maximumCorrection); table.set("speedLimit", v.speedLimit); table.set("standingPoly", v.standingPoly); table.set("crouchingPoly", v.crouchingPoly); table.set("stickyCollision", v.stickyCollision); table.set("stickyForce", v.stickyForce); table.set("walkSpeed", v.walkSpeed); table.set("runSpeed", v.runSpeed); table.set("flySpeed", v.flySpeed); table.set("airFriction", v.airFriction); table.set("liquidFriction", v.liquidFriction); table.set("minimumLiquidPercentage", v.minimumLiquidPercentage); table.set("liquidImpedance", v.liquidImpedance); table.set("normalGroundFriction", v.normalGroundFriction); table.set("ambulatingGroundFriction", v.ambulatingGroundFriction); table.set("groundForce", v.groundForce); table.set("airForce", v.airForce); table.set("liquidForce", v.liquidForce); table.set("airJumpProfile", v.airJumpProfile); table.set("liquidJumpProfile", v.liquidJumpProfile); table.set("fallStatusSpeedMin", v.fallStatusSpeedMin); table.set("fallThroughSustainFrames", v.fallThroughSustainFrames); table.set("maximumPlatformCorrection", v.maximumPlatformCorrection); table.set("maximumPlatformCorrectionVelocityFactor", v.maximumPlatformCorrectionVelocityFactor); table.set("physicsEffectCategories", v.physicsEffectCategories); table.set("groundMovementMinimumSustain", v.groundMovementMinimumSustain); table.set("groundMovementMaximumSustain", v.groundMovementMaximumSustain); table.set("groundMovementCheckDistance", v.groundMovementCheckDistance); table.set("collisionEnabled", v.collisionEnabled); table.set("frictionEnabled", v.frictionEnabled); table.set("gravityEnabled", v.gravityEnabled); return table; } Maybe LuaConverter::to(LuaEngine&, LuaValue const& v) { if (v == LuaNil) return ActorMovementParameters(); auto table = v.ptr(); if (!table) return {}; try { ActorMovementParameters amp; amp.mass = table->get>("mass"); amp.gravityMultiplier = table->get>("gravityMultiplier"); amp.liquidBuoyancy = table->get>("liquidBuoyancy"); amp.airBuoyancy = table->get>("airBuoyancy"); amp.bounceFactor = table->get>("bounceFactor"); amp.slopeSlidingFactor = table->get>("slopeSlidingFactor"); amp.maxMovementPerStep = table->get>("maxMovementPerStep"); amp.maximumCorrection = table->get>("maximumCorrection"); amp.speedLimit = table->get>("speedLimit"); amp.standingPoly = table->get>("standingPoly").orMaybe(table->get>("collisionPoly")); amp.crouchingPoly = table->get>("crouchingPoly").orMaybe(table->get>("collisionPoly")); amp.stickyCollision = table->get>("stickyCollision"); amp.stickyForce = table->get>("stickyForce"); amp.walkSpeed = table->get>("walkSpeed"); amp.runSpeed = table->get>("runSpeed"); amp.flySpeed = table->get>("flySpeed"); amp.airFriction = table->get>("airFriction"); amp.liquidFriction = table->get>("liquidFriction"); amp.minimumLiquidPercentage = table->get>("minimumLiquidPercentage"); amp.liquidImpedance = table->get>("liquidImpedance"); amp.normalGroundFriction = table->get>("normalGroundFriction"); amp.ambulatingGroundFriction = table->get>("ambulatingGroundFriction"); amp.groundForce = table->get>("groundForce"); amp.airForce = table->get>("airForce"); amp.liquidForce = table->get>("liquidForce"); amp.airJumpProfile = table->get("airJumpProfile"); amp.liquidJumpProfile = table->get("liquidJumpProfile"); amp.fallStatusSpeedMin = table->get>("fallStatusSpeedMin"); amp.fallThroughSustainFrames = table->get>("fallThroughSustainFrames"); amp.maximumPlatformCorrection = table->get>("maximumPlatformCorrection"); amp.maximumPlatformCorrectionVelocityFactor = table->get>("maximumPlatformCorrectionVelocityFactor"); amp.physicsEffectCategories = table->get>("physicsEffectCategories"); amp.groundMovementMinimumSustain = table->get>("groundMovementMinimumSustain"); amp.groundMovementMaximumSustain = table->get>("groundMovementMaximumSustain"); amp.groundMovementCheckDistance = table->get>("groundMovementCheckDistance"); amp.collisionEnabled = table->get>("collisionEnabled"); amp.frictionEnabled = table->get>("frictionEnabled"); amp.gravityEnabled = table->get>("gravityEnabled"); return amp; } catch (LuaConversionException const&) { return {}; } } LuaValue LuaConverter::from(LuaEngine& engine, ActorMovementModifiers const& v) { auto table = engine.createTable(); table.set("groundMovementModifier", v.groundMovementModifier); table.set("liquidMovementModifier", v.liquidMovementModifier); table.set("speedModifier", v.speedModifier); table.set("airJumpModifier", v.airJumpModifier); table.set("liquidJumpModifier", v.liquidJumpModifier); table.set("runningSuppressed", v.runningSuppressed); table.set("jumpingSuppressed", v.jumpingSuppressed); table.set("facingSuppressed", v.facingSuppressed); table.set("movementSuppressed", v.movementSuppressed); return table; } Maybe LuaConverter::to(LuaEngine&, LuaValue const& v) { if (v == LuaNil) return ActorMovementModifiers(); auto table = v.ptr(); if (!table) return {}; try { ActorMovementModifiers amm; amm.groundMovementModifier = table->get>("groundMovementModifier").value(1.0f); amm.liquidMovementModifier = table->get>("liquidMovementModifier").value(1.0f); amm.speedModifier = table->get>("speedModifier").value(1.0f); amm.airJumpModifier = table->get>("airJumpModifier").value(1.0f); amm.liquidJumpModifier = table->get>("liquidJumpModifier").value(1.0f); amm.runningSuppressed = table->get>("runningSuppressed").value(false); amm.jumpingSuppressed = table->get>("jumpingSuppressed").value(false); amm.facingSuppressed = table->get>("facingSuppressed").value(false); amm.movementSuppressed = table->get>("movementSuppressed").value(false); return amm; } catch (LuaConversionException const&) { return {}; } } LuaValue LuaConverter::from(LuaEngine& engine, StatModifier const& v) { return engine.luaFrom(jsonFromStatModifier(v)); } Maybe LuaConverter::to(LuaEngine& engine, LuaValue v) { auto json = engine.luaMaybeTo(move(v)); if (!json) return {}; try { return jsonToStatModifier(json.take()); } catch (JsonException const&) { return {}; } } LuaValue LuaConverter::from(LuaEngine& engine, EphemeralStatusEffect const& v) { auto table = engine.createTable(); table.set("effect", v.uniqueEffect); table.set("duration", v.duration); return table; } Maybe LuaConverter::to(LuaEngine& engine, LuaValue const& v) { if (auto s = v.ptr()) { return EphemeralStatusEffect{UniqueStatusEffect(s->ptr()), {}}; } else if (auto table = v.ptr()) { auto effect = engine.luaMaybeTo(table->get("effect")); auto duration = engine.luaMaybeTo>(table->get("duratino")); if (effect && duration) return EphemeralStatusEffect{effect.take(), duration.take()}; } return {}; } LuaValue LuaConverter::from(LuaEngine& engine, DamageRequest const& v) { auto table = engine.createTable(); table.set("hitType", HitTypeNames.getRight(v.hitType)); table.set("damageType", DamageTypeNames.getRight(v.damageType)); table.set("damage", v.damage); table.set("knockbackMomentum", v.knockbackMomentum); table.set("sourceEntityId", v.sourceEntityId); table.set("damageSourceKind", v.damageSourceKind); table.set("statusEffects", v.statusEffects); return table; } Maybe LuaConverter::to(LuaEngine&, LuaValue const& v) { auto table = v.ptr(); if (!table) return {}; try { DamageRequest dr; if (auto hitType = table->get>("hitType")) dr.hitType = HitTypeNames.getLeft(*hitType); if (auto damageType = table->get>("damageType")) dr.damageType = DamageTypeNames.getLeft(*damageType); dr.damage = table->get("damage"); if (auto knockbackMomentum = table->get>("knockbackMomentum")) dr.knockbackMomentum = *knockbackMomentum; if (auto sourceEntityId = table->get>("sourceEntityId")) dr.sourceEntityId = *sourceEntityId; if (auto damageSourceKind = table->get>("damageSourceKind")) dr.damageSourceKind = damageSourceKind.take(); if (auto statusEffects = table->get>>("statusEffects")) dr.statusEffects = statusEffects.take(); return dr; } catch (LuaConversionException const&) { return {}; } catch (MapException const&) { return {}; } } LuaValue LuaConverter::from(LuaEngine& engine, DamageNotification const& v) { auto table = engine.createTable(); table.set("sourceEntityId", v.sourceEntityId); table.set("targetEntityId", v.targetEntityId); table.set("position", v.position); table.set("damageDealt", v.damageDealt); table.set("healthLost", v.healthLost); table.set("hitType", HitTypeNames.getRight(v.hitType)); table.set("damageSourceKind", v.damageSourceKind); table.set("targetMaterialKind", v.targetMaterialKind); return table; } Maybe LuaConverter::to(LuaEngine&, LuaValue const& v) { auto table = v.ptr(); if (!table) return {}; try { DamageNotification dn; dn.sourceEntityId = table->get("sourceEntityId"); dn.targetEntityId = table->get("targetEntityId"); dn.position = table->get("position"); dn.damageDealt = table->get("damageDealt"); dn.healthLost = table->get("healthLost"); dn.hitType = HitTypeNames.getLeft(table->get("hitType")); dn.damageSourceKind = table->get("damageSourceKind"); dn.targetMaterialKind = table->get("targetMaterialKind"); return dn; } catch (LuaConversionException const&) { return {}; } catch (MapException const&) { return {}; } } LuaValue LuaConverter::from(LuaEngine& engine, LiquidLevel const& v) { auto table = engine.createTable(); table.set(1, v.liquid); table.set(2, v.level); return table; } Maybe LuaConverter::to(LuaEngine& engine, LuaValue const& v) { if (auto table = v.ptr()) { auto liquid = engine.luaMaybeTo(table->get(1)); auto level = engine.luaMaybeTo(table->get(2)); if (liquid && level) return LiquidLevel(liquid.take(), level.take()); } return {}; } LuaValue LuaConverter::from(LuaEngine& engine, Collection const& c) { auto table = engine.createTable(); table.set("name", c.name); table.set("type", CollectionTypeNames.getRight(c.type)); table.set("title", c.title); return table; } Maybe LuaConverter::to(LuaEngine& engine, LuaValue const& v) { if (auto table = v.ptr()) { auto name = engine.luaMaybeTo(table->get("name")); auto type = engine.luaMaybeTo(table->get("type")); auto title = engine.luaMaybeTo(table->get("title")); if (name && type && CollectionTypeNames.hasRightValue(*type) && title) return Collection(*name, CollectionTypeNames.getLeft(*type), *title); } return {}; } LuaValue LuaConverter::from(LuaEngine& engine, Collectable const& c) { auto table = engine.createTable(); table.set("name", c.name); table.set("order", c.order); table.set("title", c.title); table.set("description", c.description); table.set("icon", c.icon); return table; } Maybe LuaConverter::to(LuaEngine& engine, LuaValue const& v) { if (auto table = v.ptr()) { auto name = engine.luaMaybeTo(table->get("name")); if (name) { return Collectable(*name, engine.luaMaybeTo(table->get("order")).value(0), engine.luaMaybeTo(table->get("title")).value(""), engine.luaMaybeTo(table->get("description")).value(""), engine.luaMaybeTo(table->get("icon")).value("")); } } return {}; } LuaMethods LuaUserDataMethods::make() { LuaMethods methods; methods.registerMethodWithSignature( "run", [](BehaviorStateWeakPtr const& behavior, float dt) -> NodeStatus { if (behavior.expired()) throw StarException("Use of expired blackboard"); return behavior.lock()->run(dt); }); methods.registerMethodWithSignature( "clear", [](BehaviorStateWeakPtr const& behavior) { if (behavior.expired()) throw StarException("Use of expired blackboard"); behavior.lock()->clear(); }); methods.registerMethodWithSignature( "blackboard", [](BehaviorStateWeakPtr const& behavior) -> BlackboardWeakPtr { if (behavior.expired()) throw StarException("Use of expired blackboard"); return behavior.lock()->blackboardPtr(); }); return methods; } LuaValue LuaConverter::from(LuaEngine&, NodeStatus const& status) { if (status == NodeStatus::Success) return true; else if (status == NodeStatus::Failure) return false; else return {}; } NodeStatus LuaConverter::to(LuaEngine&, LuaValue const& v) { if (v.is()) return v.get() == true ? NodeStatus::Success : NodeStatus::Failure; else return NodeStatus::Running; } LuaMethods LuaUserDataMethods::make() { LuaMethods methods; auto get =[](BlackboardWeakPtr const& board, NodeParameterType const& type, String const& key) -> LuaValue { if (board.expired()) throw StarException("Use of expired blackboard"); return board.lock()->get(type, key); }; auto set = [](BlackboardWeakPtr const& board, NodeParameterType const& type, String const& key, LuaValue const& value) { if (board.expired()) throw StarException("Use of expired blackboard"); board.lock()->set(type, key, value); }; methods.registerMethodWithSignature("get", [&](BlackboardWeakPtr const& board, String const& type, String const& key) -> LuaValue { return get(board, NodeParameterTypeNames.getLeft(type), key); }); methods.registerMethodWithSignature("set", [&](BlackboardWeakPtr const& board, String const& type, String const& key, LuaValue const& value) { set(board, NodeParameterTypeNames.getLeft(type), key, value); }); methods.registerMethodWithSignature( "getEntity", [&](BlackboardWeakPtr const& board, String const& key) -> LuaValue { return get(board, NodeParameterType::Entity, key); }); methods.registerMethodWithSignature( "getPosition", [&](BlackboardWeakPtr const& board, String const& key) -> LuaValue { return get(board, NodeParameterType::Position, key); }); methods.registerMethodWithSignature( "getVec2", [&](BlackboardWeakPtr const& board, String const& key) -> LuaValue { return get(board, NodeParameterType::Vec2, key); }); methods.registerMethodWithSignature( "getNumber", [&](BlackboardWeakPtr const& board, String const& key) -> LuaValue { return get(board, NodeParameterType::Number, key); }); methods.registerMethodWithSignature( "getBool", [&](BlackboardWeakPtr const& board, String const& key) -> LuaValue { return get(board, NodeParameterType::Bool, key); }); methods.registerMethodWithSignature( "getList", [&](BlackboardWeakPtr const& board, String const& key) -> LuaValue { return get(board, NodeParameterType::List, key); }); methods.registerMethodWithSignature( "getTable", [&](BlackboardWeakPtr const& board, String const& key) -> LuaValue { return get(board, NodeParameterType::Table, key); }); methods.registerMethodWithSignature( "getString", [&](BlackboardWeakPtr const& board, String const& key) -> LuaValue { return get(board, NodeParameterType::String, key); }); methods.registerMethodWithSignature( "setEntity", [&](BlackboardWeakPtr const& board, String const& key, LuaValue const& value) { set(board, NodeParameterType::Entity, key, value); }); methods.registerMethodWithSignature( "setPosition", [&](BlackboardWeakPtr const& board, String const& key, LuaValue const& value) { set(board, NodeParameterType::Position, key, value); }); methods.registerMethodWithSignature( "setVec2", [&](BlackboardWeakPtr const& board, String const& key, LuaValue const& value) { set(board, NodeParameterType::Vec2, key, value); }); methods.registerMethodWithSignature( "setNumber", [&](BlackboardWeakPtr const& board, String const& key, LuaValue const& value) { set(board, NodeParameterType::Number, key, value); }); methods.registerMethodWithSignature( "setBool", [&](BlackboardWeakPtr const& board, String const& key, LuaValue const& value) { set(board, NodeParameterType::Bool, key, value); }); methods.registerMethodWithSignature( "setList", [&](BlackboardWeakPtr const& board, String const& key, LuaValue const& value) { set(board, NodeParameterType::List, key, value); }); methods.registerMethodWithSignature( "setTable", [&](BlackboardWeakPtr const& board, String const& key, LuaValue const& value) { set(board, NodeParameterType::Table, key, value); }); methods.registerMethodWithSignature( "setString", [&](BlackboardWeakPtr const& board, String const& key, LuaValue const& value) { set(board, NodeParameterType::String, key, value); }); return methods; } }