This commit is contained in:
Aria 2025-03-21 22:23:30 +11:00
commit 9c94d113d3
Signed by untrusted user who does not match committer: aria
GPG key ID: 19AB7AA462B8AB3B
10260 changed files with 1237388 additions and 0 deletions

View file

@ -0,0 +1,37 @@
#include "StarBehaviorLuaBindings.hpp"
#include "StarLuaGameConverters.hpp"
#include "StarRoot.hpp"
namespace Star {
LuaCallbacks LuaBindings::makeBehaviorLuaCallbacks(List<BehaviorStatePtr>* list) {
LuaCallbacks callbacks;
callbacks.registerCallback("behavior", [list](Json const& config, JsonObject const& parameters, LuaTable context, Maybe<LuaUserData> blackboard) -> BehaviorStateWeakPtr {
auto behaviorDatabase = Root::singleton().behaviorDatabase();
Maybe<BlackboardWeakPtr> board = {};
if (blackboard && blackboard->is<BlackboardWeakPtr>())
board = blackboard->get<BlackboardWeakPtr>();
BehaviorTreeConstPtr tree;
if (config.isType(Json::Type::String)) {
if (parameters.empty()) {
tree = behaviorDatabase->behaviorTree(config.toString());
} else {
JsonObject treeConfig = behaviorDatabase->behaviorConfig(config.toString()).toObject();
treeConfig.set("parameters", jsonMerge(treeConfig.get("parameters"), parameters));
tree = behaviorDatabase->buildTree(treeConfig);
}
} else {
tree = behaviorDatabase->buildTree(config.set("parameters", jsonMerge(config.getObject("parameters", {}), parameters)));
}
BehaviorStatePtr state = make_shared<BehaviorState>(tree, context, board);
list->append(state);
return weak_ptr<BehaviorState>(state);
});
return callbacks;
}
}

View file

@ -0,0 +1,17 @@
#ifndef STAR_BEHAVIOR_LUA_BINDINGS_HPP
#define STAR_BEHAVIOR_LUA_BINDINGS_HPP
#include "StarLua.hpp"
#include "StarBehaviorState.hpp"
namespace Star {
STAR_CLASS(Root);
STAR_CLASS(UniverseClient);
namespace LuaBindings {
LuaCallbacks makeBehaviorLuaCallbacks(List<BehaviorStatePtr>* list);
}
}
#endif

View file

@ -0,0 +1,219 @@
#include "StarCelestialLuaBindings.hpp"
#include "StarUniverseClient.hpp"
#include "StarSystemWorldClient.hpp"
#include "StarLuaGameConverters.hpp"
#include "StarCelestialGraphics.hpp"
#include "StarBiomeDatabase.hpp"
#include "StarJsonExtra.hpp"
namespace Star {
LuaCallbacks LuaBindings::makeCelestialCallbacks(UniverseClient* client) {
LuaCallbacks callbacks;
auto systemWorld = client->systemWorldClient();
auto celestialDatabase = client->celestialDatabase();
callbacks.registerCallback("skyFlying", [client]() {
return client->currentSky()->flying();
});
callbacks.registerCallback("skyFlyingType", [client]() -> String {
return FlyingTypeNames.getRight(client->currentSky()->flyingType());
});
callbacks.registerCallback("skyWarpPhase", [client]() -> String {
return WarpPhaseNames.getRight(client->currentSky()->warpPhase());
});
callbacks.registerCallback("skyWarpProgress", [client]() -> float {
return client->currentSky()->warpProgress();
});
callbacks.registerCallback("skyInHyperspace", [client]() -> bool {
return client->currentSky()->inHyperspace();
});
callbacks.registerCallback("flyShip", [client,systemWorld](Vec3I const& system, Json const& destination) {
auto location = jsonToSystemLocation(destination);
client->flyShip(system, location);
});
callbacks.registerCallback("flying", [systemWorld]() {
return systemWorld->flying();
});
callbacks.registerCallback("shipSystemPosition", [systemWorld]() -> Maybe<Vec2F> {
return systemWorld->shipPosition();
});
callbacks.registerCallback("shipDestination", [systemWorld]() -> Json {
return jsonFromSystemLocation(systemWorld->shipDestination());
});
callbacks.registerCallback("shipLocation", [systemWorld]() -> Json {
return jsonFromSystemLocation(systemWorld->shipLocation());
});
callbacks.registerCallback("currentSystem", [systemWorld]() -> Json {
return systemWorld->currentSystem().toJson();
});
callbacks.registerCallback("planetSize", [systemWorld](Json const& coords) -> float {
return systemWorld->planetSize(CelestialCoordinate(coords));
});
callbacks.registerCallback("planetPosition", [systemWorld](Json const& coords) -> Vec2F {
return systemWorld->planetPosition(CelestialCoordinate(coords));
});
callbacks.registerCallback("planetParameters", [celestialDatabase](Json const& coords) -> Json {
CelestialCoordinate coordinate = CelestialCoordinate(coords);
if (auto celestialParameters = celestialDatabase->parameters(coordinate))
return celestialParameters->parameters();
return Json();
});
callbacks.registerCallback("visitableParameters", [celestialDatabase](Json const& coords) -> Json {
CelestialCoordinate coordinate = CelestialCoordinate(coords);
if (auto parameters = celestialDatabase->parameters(coordinate)) {
if (auto visitableParameters = parameters->visitableParameters())
return visitableParameters->store();
}
return {};
});
callbacks.registerCallback("planetName", [celestialDatabase](Json const& coords) -> Maybe<String> {
CelestialCoordinate coordinate = CelestialCoordinate(coords);
if (auto parameters = celestialDatabase->parameters(coordinate))
return parameters->name();
return {};
});
callbacks.registerCallback("planetSeed", [celestialDatabase](Json const& coords) -> Maybe<uint64_t> {
CelestialCoordinate coordinate = CelestialCoordinate(coords);
if (auto parameters = celestialDatabase->parameters(coordinate))
return parameters->seed();
return {};
});
callbacks.registerCallback("clusterSize", [systemWorld](Json const& coords) -> float {
return systemWorld->clusterSize(CelestialCoordinate(coords));
});
callbacks.registerCallback("planetOres", [celestialDatabase](Json const& coords, float threatLevel) -> List<String> {
CelestialCoordinate coordinate = CelestialCoordinate(coords);
auto parameters = celestialDatabase->parameters(coordinate);
if (!parameters)
return {};
auto visitableParameters = parameters->visitableParameters();
if (!visitableParameters)
return {};
auto biomeDatabase = Root::singleton().biomeDatabase();
auto addOres = [biomeDatabase, threatLevel](StringSet& oreList, String const& biomeName) {
oreList.addAll(biomeDatabase->biomeOres(biomeName, threatLevel));
};
StringSet planetOres;
if (auto const& terrestrialParameters = as<TerrestrialWorldParameters>(visitableParameters)) {
addOres(planetOres, terrestrialParameters->primaryBiome);
addOres(planetOres, terrestrialParameters->surfaceLayer.primaryRegion.biome);
addOres(planetOres, terrestrialParameters->subsurfaceLayer.primaryRegion.biome);
for (auto layer : terrestrialParameters->undergroundLayers)
addOres(planetOres, layer.primaryRegion.biome);
addOres(planetOres, terrestrialParameters->coreLayer.primaryRegion.biome);
} else if (auto const& asteroidParameters = as<AsteroidsWorldParameters>(visitableParameters)) {
addOres(planetOres, asteroidParameters->asteroidBiome);
}
return planetOres.values();
});
callbacks.registerCallback("systemPosition", [systemWorld](Json const& l) -> Maybe<Vec2F> {
auto location = jsonToSystemLocation(l);
return systemWorld->systemLocationPosition(location);
});
callbacks.registerCallback("orbitPosition", [systemWorld](Json const& orbit) -> Vec2F {
return systemWorld->orbitPosition(CelestialOrbit::fromJson(orbit));
});
callbacks.registerCallback("systemObjects", [systemWorld]() -> List<String> {
return systemWorld->objects().transformed([](SystemObjectPtr object) { return object->uuid().hex(); });
});
callbacks.registerCallback("objectType", [systemWorld](String const& uuid) -> Maybe<String> {
if (auto object = systemWorld->getObject(Uuid(uuid)))
return object->name();
else
return {};
});
callbacks.registerCallback("objectParameters", [systemWorld](String const& uuid) -> Json {
if (auto object = systemWorld->getObject(Uuid(uuid)))
return object->parameters();
else
return {};
});
callbacks.registerCallback("objectWarpActionWorld", [systemWorld](String const& uuid) -> Maybe<String> {
if (Maybe<WarpAction> action = systemWorld->objectWarpAction((Uuid(uuid)))) {
return action.get().maybe<WarpToWorld>().apply([](WarpToWorld const& warp) { return printWorldId(warp.world); });
} else {
return {};
}
});
callbacks.registerCallback("objectOrbit", [systemWorld](String const& uuid) -> Json {
if (auto object = systemWorld->getObject(Uuid(uuid)))
return jsonFromMaybe<CelestialOrbit>(object->orbit(), [](CelestialOrbit const& orbit) { return orbit.toJson(); });
else
return {};
});
callbacks.registerCallback("objectPosition", [systemWorld](String const& uuid) -> Maybe<Vec2F> {
if (auto object = systemWorld->getObject(Uuid(uuid)))
return object->position();
else
return {};
});
callbacks.registerCallback("objectTypeConfig", [](String const& typeName) -> Json {
return SystemWorld::systemObjectTypeConfig(typeName);
});
callbacks.registerCallback("systemSpawnObject", [systemWorld](String const& typeName, Maybe<Vec2F> const& position, Maybe<String> uuidHex, Maybe<JsonObject> parameters) -> String {
Maybe<Uuid> uuid = uuidHex.apply([](auto const& u) { return Uuid(u); });
return systemWorld->spawnObject(typeName, position, uuid, parameters.value({})).hex();
});
callbacks.registerCallback("playerShips", [systemWorld]() -> List<String> {
return systemWorld->ships().transformed([](SystemClientShipPtr ship) { return ship->uuid().hex(); });
});
callbacks.registerCallback("playerShipPosition", [systemWorld](String const& uuid) -> Maybe<Vec2F> {
if (auto ship = systemWorld->getShip(Uuid(uuid)))
return ship->position();
else
return {};
});
callbacks.registerCallback("hasChildren", [celestialDatabase](Json const& coords) -> Maybe<bool> {
CelestialCoordinate coordinate = CelestialCoordinate(coords);
return celestialDatabase->hasChildren(coordinate);
});
callbacks.registerCallback("children", [celestialDatabase](Json const& coords) -> List<Json> {
CelestialCoordinate coordinate = CelestialCoordinate(coords);
return celestialDatabase->children(coordinate).transformed([](CelestialCoordinate const& c) { return c.toJson(); });
});
callbacks.registerCallback("childOrbits", [celestialDatabase](Json const& coords) -> List<int> {
return celestialDatabase->childOrbits(CelestialCoordinate(coords));
});
callbacks.registerCallback("scanSystems", [celestialDatabase](RectI const& region, Maybe<StringSet> const& includedTypes) -> List<Json> {
return celestialDatabase->scanSystems(region, includedTypes).transformed([](CelestialCoordinate const& c) { return c.toJson(); });
});
callbacks.registerCallback("scanConstellationLines", [celestialDatabase](RectI const& region) -> List<pair<Vec2I, Vec2I>> {
return celestialDatabase->scanConstellationLines(region);
});
callbacks.registerCallback("scanRegionFullyLoaded", [celestialDatabase](RectI const& region) -> bool {
return celestialDatabase->scanRegionFullyLoaded(region);
});
callbacks.registerCallback("centralBodyImages", [celestialDatabase](Json const& coords) -> List<pair<String, float>> {
CelestialCoordinate coordinate = CelestialCoordinate(coords);
return CelestialGraphics::drawSystemCentralBody(celestialDatabase, coordinate);
});
callbacks.registerCallback("planetaryObjectImages", [celestialDatabase](Json const& coords) -> List<pair<String, float>> {
CelestialCoordinate coordinate = CelestialCoordinate(coords);
return CelestialGraphics::drawSystemPlanetaryObject(celestialDatabase, coordinate);
});
callbacks.registerCallback("worldImages", [celestialDatabase](Json const& coords) -> List<pair<String, float>> {
CelestialCoordinate coordinate = CelestialCoordinate(coords);
return CelestialGraphics::drawWorld(celestialDatabase, coordinate);
});
callbacks.registerCallback("starImages", [celestialDatabase](Json const& coords, float twinkleTime) -> List<pair<String, float>> {
CelestialCoordinate coordinate = CelestialCoordinate(coords);
return CelestialGraphics::drawSystemTwinkle(celestialDatabase, coordinate, twinkleTime);
});
return callbacks;
}
}

View file

@ -0,0 +1,16 @@
#ifndef STAR_ROOT_LUA_BINDINGS_HPP
#define STAR_ROOT_LUA_BINDINGS_HPP
#include "StarLua.hpp"
namespace Star {
STAR_CLASS(Root);
STAR_CLASS(UniverseClient);
namespace LuaBindings {
LuaCallbacks makeCelestialCallbacks(UniverseClient* client);
}
}
#endif

View file

@ -0,0 +1,15 @@
#include "StarConfigLuaBindings.hpp"
#include "StarJsonExtra.hpp"
#include "StarLuaGameConverters.hpp"
namespace Star {
LuaCallbacks LuaBindings::makeConfigCallbacks(function<Json(String const&, Json const&)> getParameter) {
LuaCallbacks callbacks;
callbacks.registerCallback("getParameter", getParameter);
return callbacks;
}
}

View file

@ -0,0 +1,13 @@
#ifndef STAR_CONFIG_LUA_BINDINGS_HPP
#define STAR_CONFIG_LUA_BINDINGS_HPP
#include "StarLua.hpp"
namespace Star {
namespace LuaBindings {
LuaCallbacks makeConfigCallbacks(function<Json(String const&, Json const&)> getParameter);
}
}
#endif

View file

@ -0,0 +1,77 @@
#include "StarEntityLuaBindings.hpp"
#include "StarJsonExtra.hpp"
#include "StarLuaGameConverters.hpp"
#include "StarPlayer.hpp"
#include "StarMonster.hpp"
#include "StarNpc.hpp"
#include "StarWorld.hpp"
namespace Star {
LuaCallbacks LuaBindings::makeEntityCallbacks(Entity const* entity) {
LuaCallbacks callbacks;
callbacks.registerCallbackWithSignature<EntityId>("id", bind(EntityCallbacks::id, entity));
callbacks.registerCallbackWithSignature<LuaTable, LuaEngine&>(
"damageTeam", bind(EntityCallbacks::damageTeam, entity, _1));
callbacks.registerCallbackWithSignature<bool, EntityId>(
"isValidTarget", bind(EntityCallbacks::isValidTarget, entity, _1));
callbacks.registerCallbackWithSignature<Vec2F, EntityId>(
"distanceToEntity", bind(EntityCallbacks::distanceToEntity, entity, _1));
callbacks.registerCallbackWithSignature<bool, EntityId>(
"entityInSight", bind(EntityCallbacks::entityInSight, entity, _1));
callbacks.registerCallback("position", [entity]() { return entity->position(); });
callbacks.registerCallback("entityType", [entity]() { return EntityTypeNames.getRight(entity->entityType()); });
callbacks.registerCallback("uniqueId", [entity]() { return entity->uniqueId(); });
callbacks.registerCallback("persistent", [entity]() { return entity->persistent(); });
return callbacks;
}
EntityId LuaBindings::EntityCallbacks::id(Entity const* entity) {
return entity->entityId();
}
LuaTable LuaBindings::EntityCallbacks::damageTeam(Entity const* entity, LuaEngine& engine) {
auto table = engine.createTable();
auto team = entity->getTeam();
table.set("type", TeamTypeNames.getRight(team.type));
table.set("team", team.team);
return table;
}
bool LuaBindings::EntityCallbacks::isValidTarget(Entity const* entity, EntityId entityId) {
auto target = entity->world()->entity(entityId);
if (!target || !entity->getTeam().canDamage(target->getTeam(), false))
return false;
if (auto monster = as<Monster>(target))
return monster->aggressive();
if (auto npc = as<Npc>(target)) {
if (auto attackerNpc = as<Npc>(entity))
return npc->aggressive() || attackerNpc->aggressive();
return true;
}
return is<Player>(target);
}
Vec2F LuaBindings::EntityCallbacks::distanceToEntity(Entity const* entity, EntityId entityId) {
Vec2F dist;
if (auto target = entity->world()->entity(entityId))
dist = entity->world()->geometry().diff(target->position(), entity->position());
return dist;
}
bool LuaBindings::EntityCallbacks::entityInSight(Entity const* entity, EntityId entityId) {
if (auto target = entity->world()->entity(entityId))
return !entity->world()->lineTileCollision(target->position(), entity->position());
else
return false;
}
}

View file

@ -0,0 +1,22 @@
#ifndef STAR_ENTITY_LUA_BINDINGS_HPP
#define STAR_ENTITY_LUA_BINDINGS_HPP
#include "StarLua.hpp"
#include "StarEntity.hpp"
namespace Star {
namespace LuaBindings {
LuaCallbacks makeEntityCallbacks(Entity const* entity);
namespace EntityCallbacks {
EntityId id(Entity const* entity);
LuaTable damageTeam(Entity const* entity, LuaEngine& engine);
bool isValidTarget(Entity const* entity, EntityId entityId);
Vec2F distanceToEntity(Entity const* entity, EntityId entityId);
bool entityInSight(Entity const* entity, EntityId entityId);
}
}
}
#endif

View file

@ -0,0 +1,168 @@
#include "StarFireableItemLuaBindings.hpp"
#include "StarJsonExtra.hpp"
#include "StarLuaGameConverters.hpp"
#include "StarCasting.hpp"
#include "StarFireableItem.hpp"
namespace Star {
LuaCallbacks LuaBindings::makeFireableItemCallbacks(FireableItem* fireableItem) {
LuaCallbacks callbacks;
callbacks.registerCallbackWithSignature<void, Maybe<String>>("fire", bind(FireableItemCallbacks::fire, fireableItem, _1));
callbacks.registerCallbackWithSignature<void>("triggerCooldown", bind(FireableItemCallbacks::triggerCooldown, fireableItem));
callbacks.registerCallbackWithSignature<void, float>("setCooldown", bind(FireableItemCallbacks::setCooldown, fireableItem, _1));
callbacks.registerCallbackWithSignature<void>("endCooldown", bind(FireableItemCallbacks::endCooldown, fireableItem));
callbacks.registerCallbackWithSignature<float>("cooldownTime", bind(FireableItemCallbacks::cooldownTime, fireableItem));
callbacks.registerCallbackWithSignature<Json, String, Json>("fireableParam", bind(FireableItemCallbacks::fireableParam, fireableItem, _1, _2));
callbacks.registerCallbackWithSignature<String>("fireMode", bind(FireableItemCallbacks::fireMode, fireableItem));
callbacks.registerCallbackWithSignature<bool>("ready", bind(FireableItemCallbacks::ready, fireableItem));
callbacks.registerCallbackWithSignature<bool>("firing", bind(FireableItemCallbacks::firing, fireableItem));
callbacks.registerCallbackWithSignature<bool>("windingUp", bind(FireableItemCallbacks::windingUp, fireableItem));
callbacks.registerCallbackWithSignature<bool>("coolingDown", bind(FireableItemCallbacks::coolingDown, fireableItem));
callbacks.registerCallbackWithSignature<bool>("ownerFullEnergy", bind(FireableItemCallbacks::ownerFullEnergy, fireableItem));
callbacks.registerCallbackWithSignature<bool>("ownerEnergy", bind(FireableItemCallbacks::ownerEnergy, fireableItem));
callbacks.registerCallbackWithSignature<bool>("ownerEnergyLocked", bind(FireableItemCallbacks::ownerEnergyLocked, fireableItem));
callbacks.registerCallbackWithSignature<bool, float>("ownerConsumeEnergy", bind(FireableItemCallbacks::ownerConsumeEnergy, fireableItem, _1));
callbacks.registerCallbackWithSignature<Vec2F>("ownerAimPosition", [fireableItem]() {
return fireableItem->owner()->aimPosition();
});
return callbacks;
}
// Triggers the item to fire
//
// @param[opt] fireMode fireMode to trigger; should be 'Primary' or 'Alt'
// (defaults to Primary)
// @return nil
void LuaBindings::FireableItemCallbacks::fire(FireableItem* fireableItem, Maybe<String> const& mode) {
auto fireMode = FireMode::Primary;
if (mode) {
if (mode->equalsIgnoreCase("Alt"))
fireMode = FireMode::Alt;
else if (!mode->equalsIgnoreCase("Primary"))
throw StarException("Invalid fire mode specified! Must be 'Primary' or 'Alt'");
}
if (fireableItem->ready())
fireableItem->fire(fireMode, false, true);
}
// Triggers the item's cooldown
//
// @return nil
void LuaBindings::FireableItemCallbacks::triggerCooldown(FireableItem* fireableItem) {
fireableItem->triggerCooldown();
}
// Sets the item's current cooldown to the specified time (will not change the
// default cooldown)
//
// @param cooldownTime time in seconds for this cooldown period
// @return nil
void LuaBindings::FireableItemCallbacks::setCooldown(FireableItem* fireableItem, float cooldownTime) {
fireableItem->setCoolingDown(cooldownTime > 0);
fireableItem->setFireTimer(cooldownTime);
}
// Ends the item's cooldown, readying it to fire
//
// @return nil
void LuaBindings::FireableItemCallbacks::endCooldown(FireableItem* fireableItem) {
fireableItem->setCoolingDown(false);
fireableItem->setFireTimer(0);
}
// Returns the item's default cooldown time
//
// @return the default cooldown time in seconds
float LuaBindings::FireableItemCallbacks::cooldownTime(FireableItem* fireableItem) {
return fireableItem->cooldownTime();
}
// Gets the value of a configuration option for this item.
//
// @string name the name of the configuration parameter to get, as specified in
// the
// item's configuration
// @param[opt] default a default value that will be returned if the given
// configuration key does not exist in the item's configuration.
// @return[1] nil if the item has no configuration option with the given name,
// and no default value is given.
// @return[2] the value of the configuration option, or the given default value.
Json LuaBindings::FireableItemCallbacks::fireableParam(
FireableItem* fireableItem, String const& name, Json const& def) {
return fireableItem->fireableParam(name, def);
}
// Gets the current fire mode of the item
//
// @return string representation of the fire mode: 'Primary', 'Alt' or 'None'
String LuaBindings::FireableItemCallbacks::fireMode(FireableItem* fireableItem) {
if (fireableItem->fireMode() == FireMode::Primary)
return "Primary";
else if (fireableItem->fireMode() == FireMode::Alt)
return "Alt";
else
return "None";
}
// Determine whether the item is currently ready to be fired
//
// @return true if the item is ready
bool LuaBindings::FireableItemCallbacks::ready(FireableItem* fireableItem) {
return fireableItem->ready();
}
// Determine whether the item is currently firing
//
// @return true if the item is firing
bool LuaBindings::FireableItemCallbacks::firing(FireableItem* fireableItem) {
return fireableItem->firing();
}
// Determine whether the item is currently winding up to fire
//
// @return true if the item is winding up
bool LuaBindings::FireableItemCallbacks::windingUp(FireableItem* fireableItem) {
return fireableItem->windup();
}
// Determine whether the item is currently cooling down from firing
//
// @return true if the item is cooling down
bool LuaBindings::FireableItemCallbacks::coolingDown(FireableItem* fireableItem) {
return fireableItem->coolingDown();
}
// Determine whether the item's owner has full energy
//
// @return true if the owner's energy is full
bool LuaBindings::FireableItemCallbacks::ownerFullEnergy(FireableItem* fireableItem) {
return fireableItem->owner()->fullEnergy();
}
// Determine the amount of energy that the item's owner currently has
//
// @return the owner's current energy
bool LuaBindings::FireableItemCallbacks::ownerEnergy(FireableItem* fireableItem) {
return fireableItem->owner()->energy();
}
// Determine whether the item's owner's energy pool is currently locked
//
// @return true if the owner's energy pool is currently locked
bool LuaBindings::FireableItemCallbacks::ownerEnergyLocked(FireableItem* fireableItem) {
return fireableItem->owner()->energyLocked();
}
// Attempt to consume the specified amount of the owner's energy
//
// @param amount the amount of energy to consume
// @return true if the energy was consumed successfully
bool LuaBindings::FireableItemCallbacks::ownerConsumeEnergy(FireableItem* fireableItem, float energy) {
return fireableItem->owner()->consumeEnergy(energy);
}
}

View file

@ -0,0 +1,33 @@
#ifndef STAR_FIREABLE_ITEM_LUA_BINDINGS_HPP
#define STAR_FIREABLE_ITEM_LUA_BINDINGS_HPP
#include "StarLua.hpp"
namespace Star {
STAR_CLASS(FireableItem);
namespace LuaBindings {
LuaCallbacks makeFireableItemCallbacks(FireableItem* fireableItem);
namespace FireableItemCallbacks {
void fire(FireableItem* fireableItem, Maybe<String> const& mode);
void triggerCooldown(FireableItem* fireableItem);
void setCooldown(FireableItem* fireableItem, float cooldownTime);
void endCooldown(FireableItem* fireableItem);
float cooldownTime(FireableItem* fireableItem);
Json fireableParam(FireableItem* fireableItem, String const& name, Json const& def);
String fireMode(FireableItem* fireableItem);
bool ready(FireableItem* fireableItem);
bool firing(FireableItem* fireableItem);
bool windingUp(FireableItem* fireableItem);
bool coolingDown(FireableItem* fireableItem);
bool ownerFullEnergy(FireableItem* fireableItem);
bool ownerEnergy(FireableItem* fireableItem);
bool ownerEnergyLocked(FireableItem* fireableItem);
bool ownerConsumeEnergy(FireableItem* fireableItem, float energy);
}
}
}
#endif

View file

@ -0,0 +1,246 @@
#include "StarItemLuaBindings.hpp"
#include "StarJsonExtra.hpp"
#include "StarLuaGameConverters.hpp"
#include "StarCasting.hpp"
#include "StarItem.hpp"
#include "StarToolUserItem.hpp"
namespace Star {
LuaCallbacks LuaBindings::makeItemCallbacks(Item* item) {
LuaCallbacks callbacks;
callbacks.registerCallbackWithSignature<String>("name", bind(ItemCallbacks::name, item));
callbacks.registerCallbackWithSignature<size_t>("count", bind(ItemCallbacks::count, item));
callbacks.registerCallbackWithSignature<size_t, size_t>("setCount", bind(ItemCallbacks::setCount, item, _1));
callbacks.registerCallbackWithSignature<size_t>("maxStack", bind(ItemCallbacks::maxStack, item));
callbacks.registerCallbackWithSignature<bool, Json, Maybe<bool>>("matches", bind(ItemCallbacks::matches, item, _1, _2));
callbacks.registerCallbackWithSignature<bool, size_t>("consume", bind(ItemCallbacks::consume, item, _1));
callbacks.registerCallbackWithSignature<bool>("empty", bind(ItemCallbacks::empty, item));
callbacks.registerCallbackWithSignature<Json>("descriptor", bind(ItemCallbacks::descriptor, item));
callbacks.registerCallbackWithSignature<String>("description", bind(ItemCallbacks::description, item));
callbacks.registerCallbackWithSignature<String>("friendlyName", bind(ItemCallbacks::friendlyName, item));
callbacks.registerCallbackWithSignature<int>("rarity", bind(ItemCallbacks::rarity, item));
callbacks.registerCallbackWithSignature<String>("rarityString", bind(ItemCallbacks::rarityString, item));
callbacks.registerCallbackWithSignature<size_t>("price", bind(ItemCallbacks::price, item));
callbacks.registerCallbackWithSignature<Json>("fuelAmount", bind(ItemCallbacks::fuelAmount, item));
callbacks.registerCallbackWithSignature<Json>("iconDrawables", bind(ItemCallbacks::iconDrawables, item));
callbacks.registerCallbackWithSignature<Json>("dropDrawables", bind(ItemCallbacks::dropDrawables, item));
callbacks.registerCallbackWithSignature<String>("largeImage", bind(ItemCallbacks::largeImage, item));
callbacks.registerCallbackWithSignature<String>("tooltipKind", bind(ItemCallbacks::tooltipKind, item));
callbacks.registerCallbackWithSignature<String>("category", bind(ItemCallbacks::category, item));
callbacks.registerCallbackWithSignature<String>("pickupSound", bind(ItemCallbacks::pickupSound, item));
callbacks.registerCallbackWithSignature<bool>("twoHanded", bind(ItemCallbacks::twoHanded, item));
callbacks.registerCallbackWithSignature<float>("timeToLive", bind(ItemCallbacks::timeToLive, item));
callbacks.registerCallbackWithSignature<Json>("learnBlueprintsOnPickup", bind(ItemCallbacks::learnBlueprintsOnPickup, item));
callbacks.registerCallbackWithSignature<bool, String>("hasItemTag", bind(ItemCallbacks::hasItemTag, item, _1));
callbacks.registerCallbackWithSignature<Json>("pickupQuestTemplates", bind(ItemCallbacks::pickupQuestTemplates, item));
return callbacks;
}
// Returns the name of the item. (Unique identifier)
//
// @return A string containing the name of the item as specified in its
// configuration
String LuaBindings::ItemCallbacks::name(Item* item) {
return item->name();
}
// Returns the number of items in this stack
//
// @return An integer containing the number of items in this stack
size_t LuaBindings::ItemCallbacks::count(Item* item) {
return item->count();
}
// Sets the number of items in the stack (up to maxStack)
//
// @param count The desired amount
// @return An integer containing the number of items that overflowed
size_t LuaBindings::ItemCallbacks::setCount(Item* item, size_t count) {
return item->setCount(count);
}
// Returns the maximum number of items in this item's stack
//
// @return An integer containing the number of items in this item's maximum
// stack
size_t LuaBindings::ItemCallbacks::maxStack(Item* item) {
return item->maxStack();
}
// Returns whether or not the serialized item descriptor passed logically
// matches this item
// Checks both name and parameters and uses the item's internal list of matching
// descriptors
//
// @see is
// @param descriptor A properly serialized item descriptor
// @return A bool true if matches, false if not.
//
bool LuaBindings::ItemCallbacks::matches(Item* item, Json const& desc, Maybe<bool> exactMatch) {
ItemDescriptor itemDesc = ItemDescriptor(desc);
return item->matches(itemDesc, exactMatch.value(false));
}
// If the given number of this item is available, consumes that number and
// returns true, otherwise
// returns false.
//
// @param toConsume The number of items you'd like to consume from this stack
// @return true if items were successfully consumed, false otherwise
bool LuaBindings::ItemCallbacks::consume(Item* item, size_t count) {
return item->consume(count);
}
// Returns the number of items in the stack is equal to 0
//
// @return true if stack is empty, false otherwise
bool LuaBindings::ItemCallbacks::empty(Item* item) {
return item->empty();
}
// Returns the descriptor of this item
//
// @return a table containing a serialized item descriptor
Json LuaBindings::ItemCallbacks::descriptor(Item* item) {
return item->descriptor().toJson();
}
// Returns the item description
//
// @return a string containing the item's description
String LuaBindings::ItemCallbacks::description(Item* item) {
return item->description();
}
// Returns the friendly name of the item
//
// @return a string containing the friendly name of the item
String LuaBindings::ItemCallbacks::friendlyName(Item* item) {
return item->friendlyName();
}
// Returns the rarity of the item as an integer
// Common = 0,
// Uncommon = 1,
// Rare = 2,
// Legendary = 3
// Essential = 4
//
// @return an integer representing the rarity of the item
int LuaBindings::ItemCallbacks::rarity(Item* item) {
return (int)item->rarity();
}
// Returns the rarity of the item as a string
//
// @return a string representing the rarity of the item
String LuaBindings::ItemCallbacks::rarityString(Item* item) {
return RarityNames.getRight(item->rarity());
}
// Returns the shop price of the item
//
// @return an integer representing the shop price of the item in pixels (before
// modifiers)
size_t LuaBindings::ItemCallbacks::price(Item* item) {
return item->price();
}
// Returns the amount of fuel given for buring this item stack in an engine
//
// @return an integer representing the amount of fuel in the entire stack
unsigned LuaBindings::ItemCallbacks::fuelAmount(Item* item) {
return item->instanceValue("fuelAmount", 0).toUInt();
}
// Returns the iconDrawables for this item serialized into json
//
// @return List of tables containing the serialized icon drawables for this
// item.
Json LuaBindings::ItemCallbacks::iconDrawables(Item* item) {
return jsonFromList<Drawable>(item->iconDrawables(), [](Drawable const& drawable) { return drawable.toJson(); });
}
// Returns the dropDrawables for this item serialized into json
//
// @return List of tables containing the serialized drop drawables for this
// item.
Json LuaBindings::ItemCallbacks::dropDrawables(Item* item) {
return jsonFromList<Drawable>(item->dropDrawables(), [](Drawable const& drawable) { return drawable.toJson(); });
}
// Returns the large image for this item as displayed on mouseover in the
// tooltip
//
// @return String containing a path to the largeImage for this item
String LuaBindings::ItemCallbacks::largeImage(Item* item) {
return item->largeImage();
}
// Returns the inspection kind of this item (as defined in item config, defaults
// to empty string)
//
// @return String containing the inspection kind
String LuaBindings::ItemCallbacks::tooltipKind(Item* item) {
return item->tooltipKind();
}
// Returns the category of this item (as defined in item config)
//
// @return String containing the category
String LuaBindings::ItemCallbacks::category(Item* item) {
return item->category();
}
// Returns the pickup sound for the item
//
// @return string containing the path to the pickup sound for this item
String LuaBindings::ItemCallbacks::pickupSound(Item* item) {
return item->pickupSound();
}
// Returns whether or not the item is two handed
//
// @return bool containing true if the item is twoHanded, false otherwise
bool LuaBindings::ItemCallbacks::twoHanded(Item* item) {
return item->twoHanded();
}
// Returns the time to live for this item as an item drop
//
// @return float containing the time to live for this item
float LuaBindings::ItemCallbacks::timeToLive(Item* item) {
return item->timeToLive();
}
// Returns a list of item descriptors representing recipes whose blueprints you
// learn when you pick
// this item up
//
// @return a list of tables containing serialize item descriptors
Json LuaBindings::ItemCallbacks::learnBlueprintsOnPickup(Item* item) {
return jsonFromList<ItemDescriptor>(
item->learnBlueprintsOnPickup(), [](ItemDescriptor const& descriptor) { return descriptor.toJson(); });
}
// Returns whether or not this items has a specific item tag
//
// @param itemTag a string containing the tag value
// @return a bool representing whether or not this item contains that tag
bool LuaBindings::ItemCallbacks::hasItemTag(Item* item, String const& itemTag) {
return item->hasItemTag(itemTag);
}
// Returns the pickup Quest Templates for this item
//
// @return a list of string containing the different quest templates triggered
// by this item on
// pickup
Json LuaBindings::ItemCallbacks::pickupQuestTemplates(Item* item) {
return item->pickupQuestTemplates().transformed(mem_fn(&QuestArcDescriptor::toJson));
}
}

View file

@ -0,0 +1,45 @@
#ifndef STAR_ITEM_LUA_BINDINGS_HPP
#define STAR_ITEM_LUA_BINDINGS_HPP
#include "StarLua.hpp"
#include "StarVector.hpp"
namespace Star {
STAR_CLASS(Item);
namespace LuaBindings {
LuaCallbacks makeItemCallbacks(Item* item);
namespace ItemCallbacks {
String name(Item* item);
size_t count(Item* item);
size_t setCount(Item* item, size_t count);
size_t maxStack(Item* item);
bool matches(Item* item, Json const& descriptor, Maybe<bool> exactMatch);
Json matchingDescriptors(Item* item);
bool consume(Item* item, size_t count);
bool empty(Item* item);
Json descriptor(Item* item);
String description(Item* item);
String friendlyName(Item* item);
int rarity(Item* item);
String rarityString(Item* item);
size_t price(Item* item);
unsigned fuelAmount(Item* item);
Json iconDrawables(Item* item);
Json dropDrawables(Item* item);
String largeImage(Item* item);
String tooltipKind(Item* item);
String category(Item* item);
String pickupSound(Item* item);
bool twoHanded(Item* item);
float timeToLive(Item* item);
Json learnBlueprintsOnPickup(Item* item);
bool hasItemTag(Item* item, String const& itemTag);
Json pickupQuestTemplates(Item* item);
}
}
}
#endif

View file

@ -0,0 +1,440 @@
#ifndef STAR_ACTOR_MOVEMENT_COMPONENT_HPP
#define STAR_ACTOR_MOVEMENT_COMPONENT_HPP
#include "StarActorMovementController.hpp"
#include "StarLuaGameConverters.hpp"
namespace Star {
// Wraps a LuaUpdatableComponent to handle the particularly tricky case of
// maintaining ActorMovementController controls when we do not call the script
// update every tick.
template <typename Base>
class LuaActorMovementComponent : public Base {
public:
LuaActorMovementComponent();
void addActorMovementCallbacks(ActorMovementController* actorMovementController);
void removeActorMovementCallbacks();
// If true, then the controls are automatically cleared on script update.
// Defaults to true
bool autoClearControls() const;
void setAutoClearControls(bool autoClearControls);
// Updates the lua script component and applies held controls. If no script
// update is scheduled this tick, then the controls from the last update will
// be held and not cleared. If a script update is scheduled this tick, then
// the controls will be cleared only if autoClearControls is set to true.
template <typename Ret = LuaValue, typename... V>
Maybe<Ret> update(V&&... args);
private:
void performControls();
void clearControls();
ActorMovementController* m_movementController;
bool m_autoClearControls;
float m_controlRotation;
Vec2F m_controlAcceleration;
Vec2F m_controlForce;
Maybe<tuple<Vec2F, float>> m_controlApproachVelocity;
Maybe<tuple<float, float, float, bool>> m_controlApproachVelocityAlongAngle;
Maybe<ActorMovementParameters> m_controlParameters;
Maybe<ActorMovementModifiers> m_controlModifiers;
Maybe<tuple<Direction, bool>> m_controlMove;
Maybe<Direction> m_controlFace;
bool m_controlDown;
bool m_controlCrouch;
Maybe<bool> m_controlJump;
bool m_controlHoldJump;
Maybe<Vec2F> m_controlFly;
bool m_resetPathMove;
Maybe<pair<Vec2F, bool>> m_controlPathMove;
Maybe<pair<Vec2F, bool>> m_pathMoveResult;
};
template <typename Base>
LuaActorMovementComponent<Base>::LuaActorMovementComponent()
: m_autoClearControls(true),
m_controlRotation(0.0f),
m_controlDown(false),
m_controlCrouch(false),
m_controlHoldJump(false) {}
template <typename Base>
void LuaActorMovementComponent<Base>::addActorMovementCallbacks(ActorMovementController* actorMovementController) {
m_movementController = actorMovementController;
if (m_movementController) {
LuaCallbacks callbacks;
callbacks.registerCallback("mass", [this]() {
return m_movementController->mass();
});
callbacks.registerCallback("boundBox", [this]() {
return m_movementController->collisionPoly().boundBox();
});
callbacks.registerCallback("collisionPoly", [this]() {
return m_movementController->collisionPoly();
});
callbacks.registerCallback("collisionBody", [this]() {
return m_movementController->collisionBody();
});
callbacks.registerCallback("position", [this]() {
return m_movementController->position();
});
callbacks.registerCallback("xPosition", [this]() {
return m_movementController->xPosition();
});
callbacks.registerCallback("yPosition", [this]() {
return m_movementController->yPosition();
});
callbacks.registerCallback("velocity", [this]() {
return m_movementController->velocity();
});
callbacks.registerCallback("xVelocity", [this]() {
return m_movementController->xVelocity();
});
callbacks.registerCallback("yVelocity", [this]() {
return m_movementController->yVelocity();
});
callbacks.registerCallback("rotation", [this]() {
return m_movementController->rotation();
});
callbacks.registerCallback("isColliding", [this]() {
return m_movementController->isColliding();
});
callbacks.registerCallback("isNullColliding", [this]() {
return m_movementController->isNullColliding();
});
callbacks.registerCallback("isCollisionStuck", [this]() {
return m_movementController->isCollisionStuck();
});
callbacks.registerCallback("stickingDirection", [this]() {
return m_movementController->stickingDirection();
});
callbacks.registerCallback("liquidPercentage", [this]() {
return m_movementController->liquidPercentage();
});
callbacks.registerCallback("liquidId", [this]() {
return m_movementController->liquidId();
});
callbacks.registerCallback("onGround", [this]() {
return m_movementController->onGround();
});
callbacks.registerCallback("zeroG", [this]() {
return m_movementController->zeroG();
});
callbacks.registerCallback("atWorldLimit", [this](bool bottomOnly) {
return m_movementController->atWorldLimit(bottomOnly);
});
callbacks.registerCallback("setAnchorState", [this](EntityId anchorableEntity, size_t anchorPosition) {
m_movementController->setAnchorState({anchorableEntity, anchorPosition});
});
callbacks.registerCallback("resetAnchorState", [this]() {
m_movementController->resetAnchorState();
});
callbacks.registerCallback("anchorState", [this]() {
if (auto anchorState = m_movementController->anchorState())
return LuaVariadic<LuaValue>{LuaInt(anchorState->entityId), LuaInt(anchorState->positionIndex)};
return LuaVariadic<LuaValue>();
});
callbacks.registerCallback("setPosition", [this](Vec2F const& pos) {
m_movementController->setPosition(pos);
});
callbacks.registerCallback("setXPosition", [this](float xPosition) {
m_movementController->setXPosition(xPosition);
});
callbacks.registerCallback("setYPosition", [this](float yPosition) {
m_movementController->setYPosition(yPosition);
});
callbacks.registerCallback("translate", [this](Vec2F const& translate) {
m_movementController->translate(translate);
});
callbacks.registerCallback("setVelocity", [this](Vec2F const& vel) {
m_resetPathMove = true;
m_movementController->setVelocity(vel);
});
callbacks.registerCallback("setXVelocity", [this](float xVel) {
m_resetPathMove = true;
m_movementController->setXVelocity(xVel);
});
callbacks.registerCallback("setYVelocity", [this](float yVel) {
m_resetPathMove = true;
m_movementController->setYVelocity(yVel);
});
callbacks.registerCallback("addMomentum", [this](Vec2F const& momentum) {
m_resetPathMove = true;
m_movementController->addMomentum(momentum);
});
callbacks.registerCallback("setRotation", [this](float rotation) {
m_resetPathMove = true;
m_movementController->setRotation(rotation);
});
callbacks.registerCallback("baseParameters", [this]() {
return m_movementController->baseParameters();
});
callbacks.registerCallback("walking", [this]() {
return m_movementController->walking();
});
callbacks.registerCallback("running", [this]() {
return m_movementController->running();
});
callbacks.registerCallback("movingDirection", [this]() {
return numericalDirection(m_movementController->movingDirection());
});
callbacks.registerCallback("facingDirection", [this]() {
return numericalDirection(m_movementController->facingDirection());
});
callbacks.registerCallback("crouching", [this]() {
return m_movementController->crouching();
});
callbacks.registerCallback("flying", [this]() {
return m_movementController->flying();
});
callbacks.registerCallback("falling", [this]() {
return m_movementController->falling();
});
callbacks.registerCallback("canJump", [this]() {
return m_movementController->canJump();
});
callbacks.registerCallback("jumping", [this]() {
return m_movementController->jumping();
});
callbacks.registerCallback("groundMovement", [this]() {
return m_movementController->groundMovement();
});
callbacks.registerCallback("liquidMovement", [this]() {
return m_movementController->liquidMovement();
});
callbacks.registerCallback("controlRotation", [this](float rotation) {
m_controlRotation += rotation;
});
callbacks.registerCallback("controlAcceleration", [this](Vec2F const& accel) {
m_controlAcceleration += accel;
});
callbacks.registerCallback("controlForce", [this](Vec2F const& force) {
m_controlForce += force;
});
callbacks.registerCallback("controlApproachVelocity", [this](Vec2F const& arg1, float arg2) {
m_controlApproachVelocity.set(make_tuple(arg1, arg2));
});
callbacks.registerCallback("controlApproachVelocityAlongAngle", [this](float angle, float targetVelocity, float maxControlForce, bool positiveOnly) {
m_controlApproachVelocityAlongAngle.set(make_tuple(angle, targetVelocity, maxControlForce, positiveOnly));
});
callbacks.registerCallback("controlApproachXVelocity", [this](float targetXVelocity, float maxControlForce) {
m_controlApproachVelocityAlongAngle.set(make_tuple(0.0f, targetXVelocity, maxControlForce, false));
});
callbacks.registerCallback("controlApproachYVelocity", [this](float targetYVelocity, float maxControlForce) {
m_controlApproachVelocityAlongAngle.set(
make_tuple(Constants::pi / 2.0f, targetYVelocity, maxControlForce, false));
});
callbacks.registerCallback("controlParameters", [this](ActorMovementParameters const& arg1) {
m_controlParameters = m_controlParameters.value().merge(arg1);
});
callbacks.registerCallback("controlModifiers", [this](ActorMovementModifiers const& arg1) {
m_controlModifiers = m_controlModifiers.value().combine(arg1);
});
callbacks.registerCallback("controlMove", [this](Maybe<float> const& arg1, Maybe<bool> const& arg2) {
if (auto direction = directionOf(arg1.value()))
m_controlMove.set(make_tuple(*direction, arg2.value(true)));
});
callbacks.registerCallback("controlFace", [this](Maybe<float> const& arg1) {
if (auto direction = directionOf(arg1.value()))
m_controlFace = *direction;
});
callbacks.registerCallback("controlDown", [this]() {
m_controlDown = true;
});
callbacks.registerCallback("controlCrouch", [this]() {
m_controlCrouch = true;
});
callbacks.registerCallback("controlJump", [this](bool arg1) {
m_controlJump = arg1;
});
callbacks.registerCallback("controlHoldJump", [this]() {
m_controlHoldJump = true;
});
callbacks.registerCallback("controlFly", [this](Vec2F const& arg1) {
m_controlFly = arg1;
});
callbacks.registerCallback("controlPathMove", [this](Vec2F const& position, Maybe<bool> run, Maybe<PlatformerAStar::Parameters> parameters) -> Maybe<bool> {
if (m_pathMoveResult && m_pathMoveResult->first == position) {
return take(m_pathMoveResult).apply([](pair<Vec2F, bool> const& p) { return p.second; });
} else {
m_pathMoveResult.reset();
auto result = m_movementController->pathMove(position, run.value(false), parameters);
if (result.isNothing())
m_controlPathMove = pair<Vec2F, bool>(position, run.value(false));
return result.apply([](pair<Vec2F, bool> const& p) { return p.second; });
}
});
callbacks.registerCallback("pathfinding", [this]() -> bool {
return m_movementController->pathfinding();
});
callbacks.registerCallbackWithSignature<bool>("autoClearControls", bind(&LuaActorMovementComponent::autoClearControls, this));
callbacks.registerCallbackWithSignature<void, bool>("setAutoClearControls", bind(&LuaActorMovementComponent::setAutoClearControls, this, _1));
callbacks.registerCallbackWithSignature<void>("clearControls", bind(&LuaActorMovementComponent::clearControls, this));
Base::addCallbacks("mcontroller", callbacks);
} else {
Base::removeCallbacks("mcontroller");
}
}
template <typename Base>
void LuaActorMovementComponent<Base>::removeActorMovementCallbacks() {
addActorMovementCallbacks(nullptr);
}
template <typename Base>
bool LuaActorMovementComponent<Base>::autoClearControls() const {
return m_autoClearControls;
}
template <typename Base>
void LuaActorMovementComponent<Base>::setAutoClearControls(bool autoClearControls) {
m_autoClearControls = autoClearControls;
}
template <typename Base>
template <typename Ret, typename... V>
Maybe<Ret> LuaActorMovementComponent<Base>::update(V&&... args) {
if (Base::updateReady()) {
if (m_autoClearControls)
clearControls();
}
Maybe<Ret> ret = Base::template update<Ret>(forward<V>(args)...);
performControls();
return ret;
}
template <typename Base>
void LuaActorMovementComponent<Base>::performControls() {
if (m_movementController) {
m_movementController->controlRotation(m_controlRotation);
m_movementController->controlAcceleration(m_controlAcceleration);
m_movementController->controlForce(m_controlForce);
if (m_controlApproachVelocity)
tupleUnpackFunction(bind(&ActorMovementController::controlApproachVelocity, m_movementController, _1, _2), *m_controlApproachVelocity);
if (m_controlApproachVelocityAlongAngle)
tupleUnpackFunction(bind(&ActorMovementController::controlApproachVelocityAlongAngle, m_movementController, _1, _2, _3, _4), *m_controlApproachVelocityAlongAngle);
if (m_controlParameters)
m_movementController->controlParameters(*m_controlParameters);
if (m_controlModifiers)
m_movementController->controlModifiers(*m_controlModifiers);
if (m_controlMove)
tupleUnpackFunction(bind(&ActorMovementController::controlMove, m_movementController, _1, _2), *m_controlMove);
if (m_controlFace)
m_movementController->controlFace(*m_controlFace);
if (m_controlDown)
m_movementController->controlDown();
if (m_controlCrouch)
m_movementController->controlCrouch();
if (m_controlJump)
m_movementController->controlJump(*m_controlJump);
if (m_controlHoldJump && !m_movementController->onGround())
m_movementController->controlJump();
if (m_controlFly)
m_movementController->controlFly(*m_controlFly);
// some action was taken that has priority over pathing, setting position or velocity
if (m_resetPathMove)
m_controlPathMove = {};
if (m_controlPathMove && m_pathMoveResult.isNothing())
m_pathMoveResult = m_movementController->controlPathMove(m_controlPathMove->first, m_controlPathMove->second);
}
}
template <typename Base>
void LuaActorMovementComponent<Base>::clearControls() {
m_controlRotation = {};
m_controlAcceleration = {};
m_controlForce = {};
m_controlApproachVelocity = {};
m_controlApproachVelocityAlongAngle = {};
m_controlParameters = {};
m_controlModifiers = {};
m_controlMove = {};
m_controlFace = {};
m_controlDown = {};
m_controlCrouch = {};
m_controlJump = {};
m_controlHoldJump = {};
m_controlFly = {};
m_resetPathMove = false;
// Clear path move result one clear after controlPathMove is no longer called
// to keep the result available for the following update
if (m_controlPathMove.isNothing())
m_pathMoveResult = {};
m_controlPathMove = {};
}
}
#endif

View file

@ -0,0 +1,145 @@
#ifndef STAR_LUA_ANIMATION_COMPONENT_HPP
#define STAR_LUA_ANIMATION_COMPONENT_HPP
#include "StarLuaComponents.hpp"
#include "StarJsonExtra.hpp"
#include "StarLightSource.hpp"
#include "StarDrawable.hpp"
#include "StarEntityRenderingTypes.hpp"
#include "StarMixer.hpp"
#include "StarParticleDatabase.hpp"
#include "StarParticle.hpp"
#include "StarRoot.hpp"
#include "StarAssets.hpp"
#include "StarLuaConverters.hpp"
namespace Star {
STAR_EXCEPTION(LuaAnimationComponentException, LuaComponentException);
// Lua component that allows lua to directly produce drawables, light sources,
// audios, and particles. Adds a "localAnimation" callback table.
template <typename Base>
class LuaAnimationComponent : public Base {
public:
LuaAnimationComponent();
List<pair<Drawable, Maybe<EntityRenderLayer>>> const& drawables();
List<LightSource> const& lightSources();
List<Particle> pullNewParticles();
List<AudioInstancePtr> pullNewAudios();
protected:
// Clears looping audio on context shutdown
void contextShutdown() override;
private:
List<Particle> m_pendingParticles;
List<AudioInstancePtr> m_pendingAudios;
List<AudioInstancePtr> m_activeAudio;
List<pair<Drawable, Maybe<EntityRenderLayer>>> m_drawables;
List<LightSource> m_lightSources;
};
template <typename Base>
LuaAnimationComponent<Base>::LuaAnimationComponent() {
LuaCallbacks animationCallbacks;
animationCallbacks.registerCallback("playAudio", [this](String const& sound, Maybe<int> loops, Maybe<float> volume) {
auto audio = make_shared<AudioInstance>(*Root::singleton().assets()->audio(sound));
audio->setLoops(loops.value(0));
audio->setVolume(volume.value(1.0f));
m_pendingAudios.append(audio);
m_activeAudio.append(audio);
});
animationCallbacks.registerCallback("spawnParticle", [this](Json const& particleConfig, Maybe<Vec2F> const& position) {
auto particle = Root::singleton().particleDatabase()->particle(particleConfig);
particle.translate(position.value());
m_pendingParticles.append(particle);
});
animationCallbacks.registerCallback("clearDrawables", [this]() {
m_drawables.clear();
});
animationCallbacks.registerCallback("addDrawable", [this](LuaTable const& drawableTable, Maybe<String> renderLayerName) {
Maybe<EntityRenderLayer> renderLayer;
if (renderLayerName)
renderLayer = parseRenderLayer(*renderLayerName);
Color color = drawableTable.get<Maybe<Color>>("color").value(Color::White);
Drawable drawable;
if (auto line = drawableTable.get<Maybe<Line2F>>("line"))
drawable = Drawable::makeLine(line.take(), drawableTable.get<float>("width"), color);
else if (auto poly = drawableTable.get<Maybe<PolyF>>("poly"))
drawable = Drawable::makePoly(poly.take(), color);
else if (auto image = drawableTable.get<Maybe<String>>("image"))
drawable = Drawable::makeImage(image.take(), 1.0f / TilePixels, drawableTable.get<Maybe<bool>>("centered").value(true), Vec2F(), color);
else
throw LuaAnimationComponentException("Drawable table must have 'line', 'poly', or 'image'");
if (auto transformation = drawableTable.get<Maybe<Mat3F>>("transformation"))
drawable.transform(*transformation);
if (auto rotation = drawableTable.get<Maybe<float>>("rotation"))
drawable.rotate(*rotation);
if (drawableTable.get<bool>("mirrored"))
drawable.scale(Vec2F(-1, 1));
if (auto scale = drawableTable.get<Maybe<float>>("scale"))
drawable.scale(*scale);
if (auto position = drawableTable.get<Maybe<Vec2F>>("position"))
drawable.translate(*position);
drawable.fullbright = drawableTable.get<bool>("fullbright");
m_drawables.append({move(drawable), renderLayer});
});
animationCallbacks.registerCallback("clearLightSources", [this]() {
m_lightSources.clear();
});
animationCallbacks.registerCallback("addLightSource", [this](LuaTable const& lightSourceTable) {
m_lightSources.append({
lightSourceTable.get<Vec2F>("position"),
lightSourceTable.get<Color>("color").toRgb(),
lightSourceTable.get<Maybe<bool>>("pointLight").value(),
lightSourceTable.get<Maybe<float>>("pointBeam").value(),
lightSourceTable.get<Maybe<float>>("beamAngle").value(),
lightSourceTable.get<Maybe<float>>("beamAmbience").value()
});
});
Base::addCallbacks("localAnimator", move(animationCallbacks));
}
template <typename Base>
List<pair<Drawable, Maybe<EntityRenderLayer>>> const& LuaAnimationComponent<Base>::drawables() {
return m_drawables;
}
template <typename Base>
List<LightSource> const& LuaAnimationComponent<Base>::lightSources() {
return m_lightSources;
}
template <typename Base>
List<Particle> LuaAnimationComponent<Base>::pullNewParticles() {
return take(m_pendingParticles);
}
template <typename Base>
List<AudioInstancePtr> LuaAnimationComponent<Base>::pullNewAudios() {
eraseWhere(m_activeAudio, [](AudioInstancePtr const& audio) {
return audio->finished();
});
return take(m_pendingAudios);
}
template <typename Base>
void LuaAnimationComponent<Base>::contextShutdown() {
for (auto const& audio : m_activeAudio)
audio->setLoops(0);
m_activeAudio.clear();
Base::contextShutdown();
}
}
#endif

View file

@ -0,0 +1,155 @@
#include "StarLuaComponents.hpp"
#include "StarUtilityLuaBindings.hpp"
#include "StarRootLuaBindings.hpp"
namespace Star {
LuaBaseComponent::LuaBaseComponent() {
addCallbacks("sb", LuaBindings::makeUtilityCallbacks());
addCallbacks("root", LuaBindings::makeRootCallbacks());
setAutoReInit(true);
}
LuaBaseComponent::~LuaBaseComponent() {}
StringList const& LuaBaseComponent::scripts() const {
return m_scripts;
}
void LuaBaseComponent::setScript(String script) {
setScripts({move(script)});
}
void LuaBaseComponent::setScripts(StringList scripts) {
if (initialized())
throw LuaComponentException("Cannot call LuaWorldComponent::setScripts when LuaWorldComponent is initialized");
m_scripts = move(scripts);
}
void LuaBaseComponent::addCallbacks(String groupName, LuaCallbacks callbacks) {
if (!m_callbacks.insert(groupName, callbacks).second)
throw LuaComponentException::format("Duplicate callbacks named '%s' in LuaBaseComponent", groupName);
if (m_context)
m_context->setCallbacks(groupName, callbacks);
}
bool LuaBaseComponent::removeCallbacks(String const& groupName) {
if (m_callbacks.remove(groupName)) {
if (m_context)
m_context->remove(groupName);
return true;
}
return false;
}
bool LuaBaseComponent::autoReInit() const {
return (bool)m_reloadTracker;
}
void LuaBaseComponent::setAutoReInit(bool autoReInit) {
if (autoReInit) {
m_reloadTracker = make_shared<TrackerListener>();
Root::singleton().registerReloadListener(m_reloadTracker);
} else {
m_reloadTracker.reset();
}
}
void LuaBaseComponent::setLuaRoot(LuaRootPtr luaRoot) {
m_luaRoot = move(luaRoot);
}
LuaRootPtr const& LuaBaseComponent::luaRoot() {
return m_luaRoot;
}
bool LuaBaseComponent::init() {
uninit();
if (!m_luaRoot)
return false;
m_error.reset();
try {
m_context = m_luaRoot->createContext(m_scripts);
} catch (LuaException const& e) {
Logger::error("Exception while creating lua context for scripts '%s': %s", m_scripts, outputException(e, true));
m_error = String(printException(e, false));
m_context.reset();
return false;
}
contextSetup();
if (m_context->containsPath("init")) {
try {
m_context->invokePath("init");
} catch (LuaException const& e) {
Logger::error("Exception while calling script init: %s", outputException(e, true));
m_error = String(printException(e, false));
m_context.reset();
return false;
}
}
return true;
}
void LuaBaseComponent::uninit() {
if (m_context) {
if (m_context->containsPath("uninit")) {
try {
m_context->invokePath("uninit");
} catch (LuaException const& e) {
Logger::error("Exception while calling script uninit: %s", outputException(e, true));
m_error = String(printException(e, false));
}
}
contextShutdown();
m_context.reset();
}
m_error.reset();
}
bool LuaBaseComponent::initialized() const {
return m_context.isValid();
}
Maybe<String> const& LuaBaseComponent::error() const {
return m_error;
}
Maybe<LuaContext> const& LuaBaseComponent::context() const {
return m_context;
}
Maybe<LuaContext>& LuaBaseComponent::context() {
return m_context;
}
void LuaBaseComponent::contextSetup() {
m_context->setPath("self", m_context->createTable());
for (auto const& p : m_callbacks)
m_context->setCallbacks(p.first, p.second);
}
void LuaBaseComponent::contextShutdown() {}
void LuaBaseComponent::setError(String error) {
m_context.reset();
m_error = move(error);
}
bool LuaBaseComponent::checkInitialization() {
// We should re-initialize if we are either already initialized or in an
// error state (which means we WERE initialized until we had an error)
bool shouldBeInitialized = initialized() || error();
if (shouldBeInitialized && m_reloadTracker && m_reloadTracker->pullTriggered())
init();
return initialized();
}
}

View file

@ -0,0 +1,333 @@
#ifndef STAR_LUA_COMPONENT_HPP
#define STAR_LUA_COMPONENT_HPP
#include "StarPeriodic.hpp"
#include "StarLogging.hpp"
#include "StarListener.hpp"
#include "StarWorld.hpp"
#include "StarWorldLuaBindings.hpp"
namespace Star {
STAR_EXCEPTION(LuaComponentException, LuaException);
// Basic lua component that can be initialized (takes and then owns a script
// context, calls the script context's init function) and uninitialized
// (releases the context, calls the context 'uninit' function).
//
// Callbacks can be added and removed whether or not the context is initialized
// or not, they will be added back during a call to init. 'root' callbacks are
// available by default as well as an ephemeral 'self' table.
//
// All script function calls (init / uninit / invoke) guard against missing
// functions. If the function is missing, it will do nothing and return
// nothing. If the function exists but throws an error, the error will be
// logged and the component will go into the error state.
//
// Whenever an error is set, all function calls or eval will fail until the
// error is cleared by re-initializing.
//
// If 'autoReInit' is set, Monitors Root for reloads, and if a root reload
// occurs, will automatically (on the next call to invoke) uninit and then
// re-init the script before calling invoke. 'autoReInit' defaults to true.
class LuaBaseComponent {
public:
LuaBaseComponent();
// The LuaBaseComponent destructor does NOT call the 'unint' entry point in
// the script. In order to do so, uninit() must be called manually before
// destruction. This is because during destruction, it is highly likely that
// callbacks may not be valid, and highly likely that exceptions could be
// thrown.
virtual ~LuaBaseComponent();
LuaBaseComponent(LuaBaseComponent const& component) = delete;
LuaBaseComponent& operator=(LuaBaseComponent const& component) = delete;
StringList const& scripts() const;
void setScript(String script);
void setScripts(StringList scripts);
void addCallbacks(String groupName, LuaCallbacks callbacks);
bool removeCallbacks(String const& groupName);
// If true, component will automatically uninit and re-init when root is
// reloaded.
bool autoReInit() const;
void setAutoReInit(bool autoReInit);
// Lua components require access to a LuaRoot object to initialize /
// uninitialize.
void setLuaRoot(LuaRootPtr luaRoot);
LuaRootPtr const& luaRoot();
// init returns true on success, false if there has been an error
// initializing the script. LuaRoot must be set before calling or this will
// always fail. Calls the 'init' entry point on the script context.
bool init();
// uninit will uninitialize the LuaComponent if it is currently initialized.
// This calls the 'uninit' entry point on the script context before
// destroying the context.
void uninit();
bool initialized() const;
template <typename Ret = LuaValue, typename... V>
Maybe<Ret> invoke(String const& name, V&&... args);
template <typename Ret = LuaValue>
Maybe<LuaValue> eval(String const& code);
// Returns last error, if there has been an error. Errors can only be
// cleared by re-initializing the context.
Maybe<String> const& error() const;
Maybe<LuaContext> const& context() const;
Maybe<LuaContext>& context();
protected:
virtual void contextSetup();
virtual void contextShutdown();
void setError(String error);
// Checks the initialization state of the script, while also reloading the
// script and clearing the error state if a root reload has occurred.
bool checkInitialization();
private:
StringList m_scripts;
StringMap<LuaCallbacks> m_callbacks;
LuaRootPtr m_luaRoot;
TrackerListenerPtr m_reloadTracker;
Maybe<LuaContext> m_context;
Maybe<String> m_error;
};
// Wraps a basic lua component to add a persistent storage table translated
// into JSON that can be stored outside of the script context.
template <typename Base>
class LuaStorableComponent : public Base {
public:
JsonObject getScriptStorage() const;
void setScriptStorage(JsonObject storage);
protected:
virtual void contextSetup() override;
virtual void contextShutdown() override;
private:
JsonObject m_storage;
};
// Wraps a basic lua component with an 'update' method and an embedded tick
// rate. Every call to 'update' here will only call the internal script
// 'update' at the configured delta. Adds a update tick controls under the
// 'script' callback table.
template <typename Base>
class LuaUpdatableComponent : public Base {
public:
LuaUpdatableComponent();
unsigned updateDelta() const;
float updateDt() const;
void setUpdateDelta(unsigned updateDelta);
// Returns true if the next update will call the internal script update
// method.
bool updateReady() const;
template <typename Ret = LuaValue, typename... V>
Maybe<Ret> update(V&&... args);
private:
Periodic m_updatePeriodic;
};
// Wraps a basic lua component so that world callbacks are added on init, and
// removed on uninit, and sets the world LuaRoot as the LuaBaseComponent
// LuaRoot automatically.
template <typename Base>
class LuaWorldComponent : public Base {
public:
void init(World* world);
void uninit();
protected:
using Base::setLuaRoot;
using Base::init;
};
// Component for scripts which can be used as entity message handlers, provides
// a 'message' table with 'setHandler' callback to set message handlers.
template <typename Base>
class LuaMessageHandlingComponent : public Base {
public:
LuaMessageHandlingComponent();
Maybe<Json> handleMessage(String const& message, bool localMessage, JsonArray const& args = {});
protected:
virtual void contextShutdown() override;
private:
StringMap<LuaFunction> m_messageHandlers;
};
template <typename Ret, typename... V>
Maybe<Ret> LuaBaseComponent::invoke(String const& name, V&&... args) {
if (!checkInitialization())
return {};
try {
auto method = m_context->getPath(name);
if (method == LuaNil)
return {};
return m_context->luaTo<LuaFunction>(move(method)).invoke<Ret>(forward<V>(args)...);
} catch (LuaException const& e) {
Logger::error("Exception while invoking lua function '%s'. %s", name, outputException(e, true));
setError(printException(e, false));
return {};
}
}
template <typename Ret>
Maybe<LuaValue> LuaBaseComponent::eval(String const& code) {
if (!checkInitialization())
return {};
try {
return m_context->eval<Ret>(code);
} catch (LuaException const& e) {
Logger::error("Exception while evaluating lua in context: %s", outputException(e, true));
return {};
}
}
template <typename Base>
JsonObject LuaStorableComponent<Base>::getScriptStorage() const {
if (Base::initialized())
return Base::context()->template getPath<JsonObject>("storage");
else
return m_storage;
}
template <typename Base>
void LuaStorableComponent<Base>::setScriptStorage(JsonObject storage) {
if (Base::initialized())
Base::context()->setPath("storage", move(storage));
else
m_storage = move(storage);
}
template <typename Base>
void LuaStorableComponent<Base>::contextSetup() {
Base::contextSetup();
Base::context()->setPath("storage", move(m_storage));
}
template <typename Base>
void LuaStorableComponent<Base>::contextShutdown() {
m_storage = Base::context()->template getPath<JsonObject>("storage");
Base::contextShutdown();
}
template <typename Base>
LuaUpdatableComponent<Base>::LuaUpdatableComponent() {
m_updatePeriodic.setStepCount(1);
LuaCallbacks scriptCallbacks;
scriptCallbacks.registerCallback("updateDt", [this]() {
return updateDt();
});
scriptCallbacks.registerCallback("setUpdateDelta", [this](unsigned d) {
setUpdateDelta(d);
});
Base::addCallbacks("script", move(scriptCallbacks));
}
template <typename Base>
unsigned LuaUpdatableComponent<Base>::updateDelta() const {
return m_updatePeriodic.stepCount();
}
template <typename Base>
float LuaUpdatableComponent<Base>::updateDt() const {
return m_updatePeriodic.stepCount() * WorldTimestep;
}
template <typename Base>
void LuaUpdatableComponent<Base>::setUpdateDelta(unsigned updateDelta) {
m_updatePeriodic.setStepCount(updateDelta);
}
template <typename Base>
bool LuaUpdatableComponent<Base>::updateReady() const {
return m_updatePeriodic.ready();
}
template <typename Base>
template <typename Ret, typename... V>
Maybe<Ret> LuaUpdatableComponent<Base>::update(V&&... args) {
if (!m_updatePeriodic.tick())
return {};
return Base::template invoke<Ret>("update", forward<V>(args)...);
}
template <typename Base>
void LuaWorldComponent<Base>::init(World* world) {
if (Base::initialized())
uninit();
Base::setLuaRoot(world->luaRoot());
Base::addCallbacks("world", LuaBindings::makeWorldCallbacks(world));
Base::init();
}
template <typename Base>
void LuaWorldComponent<Base>::uninit() {
Base::uninit();
Base::removeCallbacks("world");
}
template <typename Base>
LuaMessageHandlingComponent<Base>::LuaMessageHandlingComponent() {
LuaCallbacks scriptCallbacks;
scriptCallbacks.registerCallback("setHandler",
[this](String message, Maybe<LuaFunction> handler) {
if (handler)
m_messageHandlers.set(move(message), handler.take());
else
m_messageHandlers.remove(message);
});
Base::addCallbacks("message", move(scriptCallbacks));
}
template <typename Base>
Maybe<Json> LuaMessageHandlingComponent<Base>::handleMessage(
String const& message, bool localMessage, JsonArray const& args) {
if (!Base::initialized())
return {};
if (auto handler = m_messageHandlers.ptr(message)) {
try {
return handler->template invoke<Json>(message, localMessage, luaUnpack(args));
} catch (LuaException const& e) {
Logger::error(
"Exception while invoking lua message handler for message '%s'. %s", message, outputException(e, true));
Base::setError(String(printException(e, false)));
}
}
return {};
}
template <typename Base>
void LuaMessageHandlingComponent<Base>::contextShutdown() {
m_messageHandlers.clear();
Base::contextShutdown();
}
}
#endif

View file

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

View file

@ -0,0 +1,151 @@
#ifndef STAR_LUA_GAME_CONVERTERS_HPP
#define STAR_LUA_GAME_CONVERTERS_HPP
#include "StarLuaConverters.hpp"
#include "StarCollisionBlock.hpp"
#include "StarPlatformerAStar.hpp"
#include "StarActorMovementController.hpp"
#include "StarDamage.hpp"
#include "StarCollectionDatabase.hpp"
#include "StarBehaviorState.hpp"
#include "StarSystemWorld.hpp"
namespace Star {
template <>
struct LuaConverter<CollisionKind> {
static LuaValue from(LuaEngine& engine, CollisionKind k);
static Maybe<CollisionKind> to(LuaEngine& engine, LuaValue const& v);
};
template <>
struct LuaConverter<CollisionSet> {
static LuaValue from(LuaEngine& engine, CollisionSet const& s);
static Maybe<CollisionSet> to(LuaEngine& engine, LuaValue const& v);
};
template <typename T>
struct LuaConverter<RpcPromise<T>> : LuaUserDataConverter<RpcPromise<T>> {};
template <typename T>
struct LuaUserDataMethods<RpcPromise<T>> {
static LuaMethods<RpcPromise<T>> make();
};
template <>
struct LuaConverter<PlatformerAStar::Path> {
static LuaValue from(LuaEngine& engine, PlatformerAStar::Path const& path);
};
template <>
struct LuaConverter<PlatformerAStar::PathFinder> : LuaUserDataConverter<PlatformerAStar::PathFinder> {};
template <>
struct LuaUserDataMethods<PlatformerAStar::PathFinder> {
static LuaMethods<PlatformerAStar::PathFinder> make();
};
template <>
struct LuaConverter<PlatformerAStar::Parameters> {
static Maybe<PlatformerAStar::Parameters> to(LuaEngine& engine, LuaValue const& v);
};
template <>
struct LuaConverter<ActorJumpProfile> {
static LuaValue from(LuaEngine& engine, ActorJumpProfile const& v);
static Maybe<ActorJumpProfile> to(LuaEngine& engine, LuaValue const& v);
};
template <>
struct LuaConverter<ActorMovementParameters> {
static LuaValue from(LuaEngine& engine, ActorMovementParameters const& v);
static Maybe<ActorMovementParameters> to(LuaEngine& engine, LuaValue const& v);
};
template <>
struct LuaConverter<ActorMovementModifiers> {
static LuaValue from(LuaEngine& engine, ActorMovementModifiers const& v);
static Maybe<ActorMovementModifiers> to(LuaEngine& engine, LuaValue const& v);
};
template <>
struct LuaConverter<StatModifier> {
static LuaValue from(LuaEngine& engine, StatModifier const& v);
static Maybe<StatModifier> to(LuaEngine& engine, LuaValue v);
};
template <>
struct LuaConverter<EphemeralStatusEffect> {
static LuaValue from(LuaEngine& engine, EphemeralStatusEffect const& v);
static Maybe<EphemeralStatusEffect> to(LuaEngine& engine, LuaValue const& v);
};
template <>
struct LuaConverter<DamageRequest> {
static LuaValue from(LuaEngine& engine, DamageRequest const& v);
static Maybe<DamageRequest> to(LuaEngine& engine, LuaValue const& v);
};
template <>
struct LuaConverter<DamageNotification> {
static LuaValue from(LuaEngine& engine, DamageNotification const& v);
static Maybe<DamageNotification> to(LuaEngine& engine, LuaValue const& v);
};
template <>
struct LuaConverter<LiquidLevel> {
static LuaValue from(LuaEngine& engine, LiquidLevel const& v);
static Maybe<LiquidLevel> to(LuaEngine& engine, LuaValue const& v);
};
template <typename T>
LuaMethods<RpcPromise<T>> LuaUserDataMethods<RpcPromise<T>>::make() {
LuaMethods<RpcPromise<T>> methods;
methods.template registerMethodWithSignature<bool, RpcPromise<T>&>("finished", mem_fn(&RpcPromise<T>::finished));
methods.template registerMethodWithSignature<bool, RpcPromise<T>&>("succeeded", mem_fn(&RpcPromise<T>::succeeded));
methods.template registerMethodWithSignature<Maybe<T>, RpcPromise<T>&>("result", mem_fn(&RpcPromise<T>::result));
methods.template registerMethodWithSignature<Maybe<String>, RpcPromise<T>&>("error", mem_fn(&RpcPromise<T>::error));
return methods;
}
template <>
struct LuaConverter<Collection> {
static LuaValue from(LuaEngine& engine, Collection const& c);
static Maybe<Collection> to(LuaEngine& engine, LuaValue const& v);
};
template <>
struct LuaConverter<Collectable> {
static LuaValue from(LuaEngine& engine, Collectable const& c);
static Maybe<Collectable> to(LuaEngine& engine, LuaValue const& v);
};
// BehaviorState contains Lua references, putting it in a UserData violates
// the "don't put lua references in userdata, just don't" rule. We get around it by keeping
// a weak pointer to the behavior state, forcing it to be destroyed elsewhere.
template <>
struct LuaConverter<BehaviorStateWeakPtr> : LuaUserDataConverter<BehaviorStateWeakPtr> {};
template <>
struct LuaUserDataMethods<BehaviorStateWeakPtr> {
static LuaMethods<BehaviorStateWeakPtr> make();
};
template <>
struct LuaConverter<NodeStatus> {
static LuaValue from(LuaEngine& engine, NodeStatus const& status);
static NodeStatus to(LuaEngine& engine, LuaValue const& v);
};
// Weak pointer for the same reasons as BehaviorState.
template <>
struct LuaConverter<BlackboardWeakPtr> : LuaUserDataConverter<BlackboardWeakPtr> {};
template <>
struct LuaUserDataMethods<BlackboardWeakPtr> {
static LuaMethods<BlackboardWeakPtr> make();
};
}
#endif

View file

@ -0,0 +1,161 @@
#include "StarLuaRoot.hpp"
#include "StarAssets.hpp"
namespace Star {
LuaRoot::LuaRoot() {
auto& root = Root::singleton();
m_luaEngine = LuaEngine::create(root.configuration()->get("safeScripts").toBool());
m_luaEngine->setRecursionLimit(root.configuration()->get("scriptRecursionLimit").toUInt());
m_luaEngine->setInstructionLimit(root.configuration()->get("scriptInstructionLimit").toUInt());
m_luaEngine->setProfilingEnabled(root.configuration()->get("scriptProfilingEnabled").toBool());
m_luaEngine->setInstructionMeasureInterval(root.configuration()->get("scriptInstructionMeasureInterval").toUInt());
m_scriptCache = make_shared<ScriptCache>();
m_rootReloadListener = make_shared<CallbackListener>([cache = m_scriptCache]() {
cache->clear();
});
root.registerReloadListener(m_rootReloadListener);
m_storageDirectory = root.toStoragePath("lua");
}
LuaRoot::~LuaRoot() {
auto profile = m_luaEngine->getProfile();
if (!profile.empty()) {
profile.sort([](auto const& a, auto const& b) {
return a.totalTime > b.totalTime;
});
std::function<Json (LuaProfileEntry const&)> jsonFromProfileEntry = [&](LuaProfileEntry const& entry) -> Json {
JsonObject profile;
profile.set("function", entry.name.value("<function>"));
profile.set("scope", entry.nameScope.value("?"));
profile.set("source", strf("%s:%s", entry.source, entry.sourceLine));
profile.set("self", entry.selfTime);
profile.set("total", entry.totalTime);
List<LuaProfileEntry> calls;
for (auto p : entry.calls)
calls.append(*p.second);
profile.set("calls", calls.sorted([](auto const& a, auto const& b) { return a.totalTime > b.totalTime; }).transformed(jsonFromProfileEntry));
return profile;
};
String profileSummary = Json(profile.transformed(jsonFromProfileEntry)).repr(1);
if (!File::isDirectory(m_storageDirectory)) {
Logger::info("Creating lua storage directory");
File::makeDirectory(m_storageDirectory);
}
String filename = strf("%s.luaprofile", Time::printCurrentDateAndTime("<year>-<month>-<day>-<hours>-<minutes>-<seconds>-<millis>"));
String path = File::relativeTo(m_storageDirectory, filename);
Logger::info("Writing lua profile %s", filename);
File::writeFile(profileSummary, path);
}
}
void LuaRoot::loadScript(String const& assetPath) {
m_scriptCache->loadScript(*m_luaEngine, assetPath);
}
bool LuaRoot::scriptLoaded(String const& assetPath) const {
return m_scriptCache->scriptLoaded(assetPath);
}
void LuaRoot::unloadScript(String const& assetPath) {
m_scriptCache->unloadScript(assetPath);
}
LuaContext LuaRoot::createContext(String const& script) {
return createContext(StringList{script});
}
LuaContext LuaRoot::createContext(StringList const& scriptPaths) {
auto newContext = m_luaEngine->createContext();
auto cache = m_scriptCache;
newContext.setRequireFunction([cache](LuaContext& context, LuaString const& module) {
if (!context.get("_SBLOADED").is<LuaTable>())
context.set("_SBLOADED", context.createTable());
auto t = context.get<LuaTable>("_SBLOADED");
if (!t.contains(module)) {
t.set(module, true);
cache->loadContextScript(context, module.toString());
}
});
for (auto const& scriptPath : scriptPaths)
cache->loadContextScript(newContext, scriptPath);
return newContext;
}
void LuaRoot::collectGarbage(Maybe<unsigned> steps) {
m_luaEngine->collectGarbage(steps);
}
void LuaRoot::setAutoGarbageCollection(bool autoGarbageColleciton) {
m_luaEngine->setAutoGarbageCollection(autoGarbageColleciton);
}
void LuaRoot::tuneAutoGarbageCollection(float pause, float stepMultiplier) {
m_luaEngine->tuneAutoGarbageCollection(pause, stepMultiplier);
}
size_t LuaRoot::luaMemoryUsage() const {
return m_luaEngine->memoryUsage();
}
size_t LuaRoot::scriptCacheMemoryUsage() const {
return m_scriptCache->memoryUsage();
}
void LuaRoot::clearScriptCache() const {
return m_scriptCache->clear();
}
LuaEngine& LuaRoot::luaEngine() const {
return *m_luaEngine;
}
void LuaRoot::ScriptCache::loadScript(LuaEngine& engine, String const& assetPath) {
auto assets = Root::singleton().assets();
RecursiveMutexLocker locker(mutex);
scripts[assetPath] = engine.compile(*assets->bytes(assetPath), assetPath);
}
bool LuaRoot::ScriptCache::scriptLoaded(String const& assetPath) const {
RecursiveMutexLocker locker(mutex);
return scripts.contains(assetPath);
}
void LuaRoot::ScriptCache::unloadScript(String const& assetPath) {
RecursiveMutexLocker locker(mutex);
scripts.remove(assetPath);
}
void LuaRoot::ScriptCache::clear() {
RecursiveMutexLocker locker(mutex);
scripts.clear();
}
void LuaRoot::ScriptCache::loadContextScript(LuaContext& context, String const& assetPath) {
RecursiveMutexLocker locker(mutex);
if (!scriptLoaded(assetPath))
loadScript(context.engine(), assetPath);
context.load(scripts.get(assetPath));
}
size_t LuaRoot::ScriptCache::memoryUsage() const {
RecursiveMutexLocker locker(mutex);
size_t total = 0;
for (auto const& p : scripts)
total += p.second.size();
return total;
}
}

View file

@ -0,0 +1,68 @@
#ifndef STAR_LUA_ROOT_HPP
#define STAR_LUA_ROOT_HPP
#include "StarThread.hpp"
#include "StarLua.hpp"
#include "StarRoot.hpp"
namespace Star {
STAR_CLASS(LuaRoot);
// Loads and caches lua scripts from assets. Automatically clears cache on
// root reload. Uses an internal LuaEngine, so this and all contexts are meant
// for single threaded access and have no locking.
class LuaRoot {
public:
LuaRoot();
~LuaRoot();
void loadScript(String const& assetPath);
bool scriptLoaded(String const& assetPath) const;
void unloadScript(String const& assetPath);
// A script context can be created from the combination of several scripts,
// the functions / data in each script will be loaded in order, so that later
// specified scripts will overwrite previous ones.
//
// The LuaContext that is returned will have its 'require' function
// overloaded to take absolute asset paths and load that asset path as a lua
// module, with protection from duplicate loading.
LuaContext createContext(String const& script);
LuaContext createContext(StringList const& scriptPaths = {});
void collectGarbage(Maybe<unsigned> steps = {});
void setAutoGarbageCollection(bool autoGarbageColleciton);
void tuneAutoGarbageCollection(float pause, float stepMultiplier);
size_t luaMemoryUsage() const;
size_t scriptCacheMemoryUsage() const;
void clearScriptCache() const;
LuaEngine& luaEngine() const;
private:
class ScriptCache {
public:
void loadScript(LuaEngine& engine, String const& assetPath);
bool scriptLoaded(String const& assetPath) const;
void unloadScript(String const& assetPath);
void clear();
void loadContextScript(LuaContext& context, String const& assetPath);
size_t memoryUsage() const;
private:
mutable RecursiveMutex mutex;
StringMap<ByteArray> scripts;
};
LuaEnginePtr m_luaEngine;
shared_ptr<ScriptCache> m_scriptCache;
ListenerPtr m_rootReloadListener;
String m_storageDirectory;
};
}
#endif

View file

@ -0,0 +1,83 @@
#include "StarMovementControllerLuaBindings.hpp"
#include "StarMovementController.hpp"
#include "StarLuaGameConverters.hpp"
namespace Star {
LuaCallbacks LuaBindings::makeMovementControllerCallbacks(MovementController* movementController) {
LuaCallbacks callbacks;
callbacks.registerCallback(
"parameters", [movementController]() { return movementController->parameters().toJson(); });
callbacks.registerCallbackWithSignature<void, Json>(
"applyParameters", bind(&MovementController::applyParameters, movementController, _1));
callbacks.registerCallbackWithSignature<void, Json>(
"resetParameters", bind(&MovementController::resetParameters, movementController, _1));
callbacks.registerCallbackWithSignature<float>("mass", bind(&MovementController::mass, movementController));
callbacks.registerCallbackWithSignature<PolyF>(
"collisionPoly", bind(&MovementController::collisionPoly, movementController));
callbacks.registerCallbackWithSignature<Vec2F>("position", bind(&MovementController::position, movementController));
callbacks.registerCallbackWithSignature<float>("xPosition", bind(&MovementController::xPosition, movementController));
callbacks.registerCallbackWithSignature<float>("yPosition", bind(&MovementController::yPosition, movementController));
callbacks.registerCallbackWithSignature<Vec2F>("velocity", bind(&MovementController::velocity, movementController));
callbacks.registerCallbackWithSignature<float>("xVelocity", bind(&MovementController::xVelocity, movementController));
callbacks.registerCallbackWithSignature<float>("yVelocity", bind(&MovementController::yVelocity, movementController));
callbacks.registerCallbackWithSignature<float>("rotation", bind(&MovementController::rotation, movementController));
callbacks.registerCallbackWithSignature<PolyF>(
"collisionBody", bind(&MovementController::collisionBody, movementController));
callbacks.registerCallbackWithSignature<RectF>(
"collisionBoundBox", bind(&MovementController::collisionBoundBox, movementController));
callbacks.registerCallbackWithSignature<RectF>(
"localBoundBox", bind(&MovementController::localBoundBox, movementController));
callbacks.registerCallbackWithSignature<bool>(
"isColliding", bind(&MovementController::isColliding, movementController));
callbacks.registerCallbackWithSignature<bool>(
"isNullColliding", bind(&MovementController::isNullColliding, movementController));
callbacks.registerCallbackWithSignature<bool>(
"isCollisionStuck", bind(&MovementController::isCollisionStuck, movementController));
callbacks.registerCallbackWithSignature<Maybe<float>>(
"stickingDirection", bind(&MovementController::stickingDirection, movementController));
callbacks.registerCallbackWithSignature<float>(
"liquidPercentage", bind(&MovementController::liquidPercentage, movementController));
callbacks.registerCallbackWithSignature<LiquidId>(
"liquidId", bind(&MovementController::liquidId, movementController));
callbacks.registerCallbackWithSignature<bool>("onGround", bind(&MovementController::onGround, movementController));
callbacks.registerCallbackWithSignature<bool>("zeroG", bind(&MovementController::zeroG, movementController));
callbacks.registerCallbackWithSignature<bool, bool>("atWorldLimit", bind(&MovementController::atWorldLimit, movementController, _1));
callbacks.registerCallbackWithSignature<void, Vec2F>(
"setPosition", bind(&MovementController::setPosition, movementController, _1));
callbacks.registerCallbackWithSignature<void, float>(
"setXPosition", bind(&MovementController::setXPosition, movementController, _1));
callbacks.registerCallbackWithSignature<void, float>(
"setYPosition", bind(&MovementController::setYPosition, movementController, _1));
callbacks.registerCallbackWithSignature<void, Vec2F>(
"translate", bind(&MovementController::translate, movementController, _1));
callbacks.registerCallbackWithSignature<void, Vec2F>(
"setVelocity", bind(&MovementController::setVelocity, movementController, _1));
callbacks.registerCallbackWithSignature<void, float>(
"setXVelocity", bind(&MovementController::setXVelocity, movementController, _1));
callbacks.registerCallbackWithSignature<void, float>(
"setYVelocity", bind(&MovementController::setYVelocity, movementController, _1));
callbacks.registerCallbackWithSignature<void, Vec2F>(
"addMomentum", bind(&MovementController::addMomentum, movementController, _1));
callbacks.registerCallbackWithSignature<void, float>(
"setRotation", bind(&MovementController::setRotation, movementController, _1));
callbacks.registerCallbackWithSignature<void, float>(
"rotate", bind(&MovementController::rotate, movementController, _1));
callbacks.registerCallbackWithSignature<void, Vec2F>(
"accelerate", bind(&MovementController::accelerate, movementController, _1));
callbacks.registerCallbackWithSignature<void, Vec2F>(
"force", bind(&MovementController::force, movementController, _1));
callbacks.registerCallbackWithSignature<void, Vec2F, float>(
"approachVelocity", bind(&MovementController::approachVelocity, movementController, _1, _2));
callbacks.registerCallbackWithSignature<void, float, float, float, bool>("approachVelocityAlongAngle",
bind(&MovementController::approachVelocityAlongAngle, movementController, _1, _2, _3, _4));
callbacks.registerCallbackWithSignature<void, float, float>(
"approachXVelocity", bind(&MovementController::approachXVelocity, movementController, _1, _2));
callbacks.registerCallbackWithSignature<void, float, float>(
"approachYVelocity", bind(&MovementController::approachYVelocity, movementController, _1, _2));
return callbacks;
}
}

View file

@ -0,0 +1,15 @@
#ifndef STAR_MOVEMENT_CONTROLLER_LUA_BINDINGS_HPP
#define STAR_MOVEMENT_CONTROLLER_LUA_BINDINGS_HPP
#include "StarLua.hpp"
namespace Star {
STAR_CLASS(MovementController);
namespace LuaBindings {
LuaCallbacks makeMovementControllerCallbacks(MovementController* movementController);
}
}
#endif

View file

@ -0,0 +1,112 @@
#include "StarNetworkedAnimatorLuaBindings.hpp"
#include "StarNetworkedAnimator.hpp"
#include "StarJsonExtra.hpp"
#include "StarLuaGameConverters.hpp"
namespace Star {
LuaCallbacks LuaBindings::makeNetworkedAnimatorCallbacks(NetworkedAnimator* networkedAnimator) {
LuaCallbacks callbacks;
callbacks.registerCallbackWithSignature<bool, String, String, bool>(
"setAnimationState", bind(&NetworkedAnimator::setState, networkedAnimator, _1, _2, _3));
callbacks.registerCallbackWithSignature<String, String>(
"animationState", bind(&NetworkedAnimator::state, networkedAnimator, _1));
callbacks.registerCallbackWithSignature<Json, String, String>(
"animationStateProperty", bind(&NetworkedAnimator::stateProperty, networkedAnimator, _1, _2));
callbacks.registerCallbackWithSignature<void, String, String>(
"setGlobalTag", bind(&NetworkedAnimator::setGlobalTag, networkedAnimator, _1, _2));
callbacks.registerCallbackWithSignature<void, String, String, String>(
"setPartTag", bind(&NetworkedAnimator::setPartTag, networkedAnimator, _1, _2, _3));
callbacks.registerCallback("setFlipped",
[networkedAnimator](bool flipped, Maybe<float> relativeCenterLine) {
networkedAnimator->setFlipped(flipped, relativeCenterLine.value());
});
callbacks.registerCallbackWithSignature<void, float>(
"setAnimationRate", bind(&NetworkedAnimator::setAnimationRate, networkedAnimator, _1));
callbacks.registerCallbackWithSignature<void, String, float, bool>(
"rotateGroup", bind(&NetworkedAnimator::rotateGroup, networkedAnimator, _1, _2, _3));
callbacks.registerCallbackWithSignature<float, String>(
"currentRotationAngle", bind(&NetworkedAnimator::currentRotationAngle, networkedAnimator, _1));
callbacks.registerCallbackWithSignature<bool, String>(
"hasTransformationGroup", bind(&NetworkedAnimator::hasTransformationGroup, networkedAnimator, _1));
callbacks.registerCallbackWithSignature<void, String, Vec2F>("translateTransformationGroup",
bind(&NetworkedAnimator::translateTransformationGroup, networkedAnimator, _1, _2));
callbacks.registerCallback("rotateTransformationGroup",
[networkedAnimator](String const& transformationGroup, float rotation, Maybe<Vec2F> const& rotationCenter) {
networkedAnimator->rotateTransformationGroup(transformationGroup, rotation, rotationCenter.value());
});
callbacks.registerCallback("scaleTransformationGroup",
[networkedAnimator](LuaEngine& engine, String const& transformationGroup, LuaValue scale, Maybe<Vec2F> const& scaleCenter) {
if (auto cs = engine.luaMaybeTo<Vec2F>(scale))
networkedAnimator->scaleTransformationGroup(transformationGroup, *cs, scaleCenter.value());
else
networkedAnimator->scaleTransformationGroup(transformationGroup, engine.luaTo<float>(scale), scaleCenter.value());
});
callbacks.registerCallbackWithSignature<void, String, float, float, float, float, float, float>(
"transformTransformationGroup",
bind(&NetworkedAnimator::transformTransformationGroup, networkedAnimator, _1, _2, _3, _4, _5, _6, _7));
callbacks.registerCallbackWithSignature<void, String>(
"resetTransformationGroup", bind(&NetworkedAnimator::resetTransformationGroup, networkedAnimator, _1));
callbacks.registerCallbackWithSignature<void, String, bool>(
"setParticleEmitterActive", bind(&NetworkedAnimator::setParticleEmitterActive, networkedAnimator, _1, _2));
callbacks.registerCallbackWithSignature<void, String, float>("setParticleEmitterEmissionRate",
bind(&NetworkedAnimator::setParticleEmitterEmissionRate, networkedAnimator, _1, _2));
callbacks.registerCallbackWithSignature<void, String, unsigned>("setParticleEmitterBurstCount",
bind(&NetworkedAnimator::setParticleEmitterBurstCount, networkedAnimator, _1, _2));
callbacks.registerCallbackWithSignature<void, String, RectF>("setParticleEmitterOffsetRegion",
bind(&NetworkedAnimator::setParticleEmitterOffsetRegion, networkedAnimator, _1, _2));
callbacks.registerCallbackWithSignature<void, String>(
"burstParticleEmitter", bind(&NetworkedAnimator::burstParticleEmitter, networkedAnimator, _1));
callbacks.registerCallbackWithSignature<void, String, bool>(
"setLightActive", bind(&NetworkedAnimator::setLightActive, networkedAnimator, _1, _2));
callbacks.registerCallbackWithSignature<void, String, Vec2F>(
"setLightPosition", bind(&NetworkedAnimator::setLightPosition, networkedAnimator, _1, _2));
callbacks.registerCallbackWithSignature<void, String, Color>(
"setLightColor", bind(&NetworkedAnimator::setLightColor, networkedAnimator, _1, _2));
callbacks.registerCallbackWithSignature<void, String, float>(
"setLightPointAngle", bind(&NetworkedAnimator::setLightPointAngle, networkedAnimator, _1, _2));
callbacks.registerCallbackWithSignature<bool, String>(
"hasSound", bind(&NetworkedAnimator::hasSound, networkedAnimator, _1));
callbacks.registerCallbackWithSignature<void, String, StringList>(
"setSoundPool", bind(&NetworkedAnimator::setSoundPool, networkedAnimator, _1, _2));
callbacks.registerCallbackWithSignature<void, String, Vec2F>(
"setSoundPosition", bind(&NetworkedAnimator::setSoundPosition, networkedAnimator, _1, _2));
callbacks.registerCallback("playSound",
[networkedAnimator](String const& sound, Maybe<int> loops) {
networkedAnimator->playSound(sound, loops.value());
});
callbacks.registerCallback("setSoundVolume",
[networkedAnimator](String const& sound, float targetVolume, Maybe<float> rampTime) {
networkedAnimator->setSoundVolume(sound, targetVolume, rampTime.value(0));
});
callbacks.registerCallback("setSoundPitch",
[networkedAnimator](String const& sound, float targetPitch, Maybe<float> rampTime) {
networkedAnimator->setSoundPitchMultiplier(sound, targetPitch, rampTime.value(0));
});
callbacks.registerCallback("stopAllSounds",
[networkedAnimator](String const& sound, Maybe<float> rampTime) {
networkedAnimator->stopAllSounds(sound, rampTime.value());
});
callbacks.registerCallbackWithSignature<void, String, bool>(
"setEffectActive", bind(&NetworkedAnimator::setEffectEnabled, networkedAnimator, _1, _2));
callbacks.registerCallbackWithSignature<Maybe<Vec2F>, String, String>("partPoint", bind(&NetworkedAnimator::partPoint, networkedAnimator, _1, _2));
callbacks.registerCallbackWithSignature<Maybe<PolyF>, String, String>("partPoly", bind(&NetworkedAnimator::partPoly, networkedAnimator, _1, _2));
callbacks.registerCallbackWithSignature<Json, String, String>("partProperty", bind(&NetworkedAnimator::partProperty, networkedAnimator, _1, _2));
callbacks.registerCallback("transformPoint", [networkedAnimator] (Vec2F point, String const& part) -> Vec2F {
return networkedAnimator->partTransformation(part).transformVec2(point);
});
callbacks.registerCallback("transformPoly", [networkedAnimator] (PolyF poly, String const& part) -> PolyF {
poly.transform(networkedAnimator->partTransformation(part));
return poly;
});
return callbacks;
}
}

View file

@ -0,0 +1,18 @@
#ifndef STAR_NETWORKED_ANIMATOR_LUA_BINDINGS_HPP
#define STAR_NETWORKED_ANIMATOR_LUA_BINDINGS_HPP
#include "StarLua.hpp"
#include "StarPoly.hpp"
#include "StarColor.hpp"
namespace Star {
STAR_CLASS(NetworkedAnimator);
namespace LuaBindings {
LuaCallbacks makeNetworkedAnimatorCallbacks(NetworkedAnimator* networkedAnimator);
}
}
#endif

View file

@ -0,0 +1,446 @@
#include "StarPlayerLuaBindings.hpp"
#include "StarClientContext.hpp"
#include "StarItem.hpp"
#include "StarItemDatabase.hpp"
#include "StarPlayer.hpp"
#include "StarPlayerInventory.hpp"
#include "StarPlayerTech.hpp"
#include "StarPlayerLog.hpp"
#include "StarQuestManager.hpp"
#include "StarWarping.hpp"
#include "StarStatistics.hpp"
#include "StarPlayerUniverseMap.hpp"
#include "StarJsonExtra.hpp"
namespace Star {
LuaCallbacks LuaBindings::makePlayerCallbacks(Player* player) {
LuaCallbacks callbacks;
callbacks.registerCallback("id", [player]() { return player->entityId(); });
callbacks.registerCallback("uniqueId", [player]() { return player->uniqueId(); });
callbacks.registerCallback("species", [player]() { return player->species(); });
callbacks.registerCallback("gender", [player]() { return GenderNames.getRight(player->gender()); });
callbacks.registerCallback("isAdmin", [player]() { return player->isAdmin(); });
callbacks.registerCallback("interact", [player](String const& type, Json const& configData, Maybe<EntityId> const& sourceEntityId) {
player->interact(InteractAction(type, sourceEntityId.value(NullEntityId), configData));
});
callbacks.registerCallback("shipUpgrades", [player]() { return player->clientContext()->shipUpgrades().toJson(); });
callbacks.registerCallback("upgradeShip", [player](Json const& upgrades) {
player->clientContext()->rpcInterface()->invokeRemote("ship.applyShipUpgrades", upgrades);
});
callbacks.registerCallback("setUniverseFlag", [player](String const& flagName) {
player->clientContext()->rpcInterface()->invokeRemote("universe.setFlag", flagName);
});
callbacks.registerCallback("giveBlueprint", [player](Json const& item) { player->addBlueprint(ItemDescriptor(item)); });
callbacks.registerCallback("blueprintKnown", [player](Json const& item) { return player->blueprintKnown(ItemDescriptor(item)); });
callbacks.registerCallback("makeTechAvailable", [player](String const& tech) {
player->techs()->makeAvailable(tech);
});
callbacks.registerCallback("makeTechUnavailable", [player](String const& tech) {
player->techs()->makeUnavailable(tech);
});
callbacks.registerCallback("enableTech", [player](String const& tech) {
player->techs()->enable(tech);
});
callbacks.registerCallback("equipTech", [player](String const& tech) {
player->techs()->equip(tech);
});
callbacks.registerCallback("unequipTech", [player](String const& tech) {
player->techs()->unequip(tech);
});
callbacks.registerCallback("availableTechs", [player]() {
return player->techs()->availableTechs();
});
callbacks.registerCallback("enabledTechs", [player]() {
return player->techs()->enabledTechs();
});
callbacks.registerCallback("equippedTech", [player](String typeName) {
return player->techs()->equippedTechs().maybe(TechTypeNames.getLeft(typeName));
});
callbacks.registerCallback("currency", [player](String const& currencyType) { return player->currency(currencyType); });
callbacks.registerCallback("addCurrency", [player](String const& currencyType, uint64_t amount) {
player->inventory()->addCurrency(currencyType, amount);
});
callbacks.registerCallback("consumeCurrency", [player](String const& currencyType, uint64_t amount) {
return player->inventory()->consumeCurrency(currencyType, amount);
});
callbacks.registerCallback("cleanupItems", [player]() {
player->inventory()->cleanup();
});
callbacks.registerCallback("giveItem", [player](Json const& item) {
player->giveItem(ItemDescriptor(item));
});
callbacks.registerCallback("giveEssentialItem", [player](String const& slotName, Json const& item) {
auto itemDatabase = Root::singleton().itemDatabase();
player->inventory()->setEssentialItem(EssentialItemNames.getLeft(slotName), itemDatabase->item(ItemDescriptor(item)));
});
callbacks.registerCallback("essentialItem", [player](String const& slotName) {
return itemSafeDescriptor(player->inventory()->essentialItem(EssentialItemNames.getLeft(slotName))).toJson();
});
callbacks.registerCallback("removeEssentialItem", [player](String const& slotName) {
player->inventory()->setEssentialItem(EssentialItemNames.getLeft(slotName), {});
});
callbacks.registerCallback("setEquippedItem", [player](String const& slotName, Json const& item) {
auto itemDatabase = Root::singleton().itemDatabase();
auto slot = InventorySlot(EquipmentSlotNames.getLeft(slotName));
player->inventory()->setItem(slot, itemDatabase->item(ItemDescriptor(item)));
});
callbacks.registerCallback("equippedItem", [player](String const& slotName) {
auto slot = InventorySlot(EquipmentSlotNames.getLeft(slotName));
if (auto item = player->inventory()->itemsAt(slot))
return item->descriptor().toJson();
return Json();
});
callbacks.registerCallback("hasItem", [player](Json const& item, Maybe<bool> exactMatch) {
return player->hasItem(ItemDescriptor(item), exactMatch.value(false));
});
callbacks.registerCallback("hasCountOfItem", [player](Json const& item, Maybe<bool> exactMatch) {
return player->hasCountOfItem(ItemDescriptor(item), exactMatch.value(false));
});
callbacks.registerCallback("consumeItem", [player](Json const& item, Maybe<bool> consumePartial, Maybe<bool> exactMatch) {
return player->takeItem(ItemDescriptor(item), consumePartial.value(false), exactMatch.value(false)).toJson();
});
callbacks.registerCallback("inventoryTags", [player]() {
StringMap<size_t> inventoryTags;
for (auto const& item : player->inventory()->allItems()) {
for (auto tag : item->itemTags())
++inventoryTags[tag];
}
return inventoryTags;
});
callbacks.registerCallback("itemsWithTag", [player](String const& tag) {
JsonArray items;
for (auto const& item : player->inventory()->allItems()) {
for (auto itemTag : item->itemTags()) {
if (itemTag == tag)
items.append(item->descriptor().toJson());
}
}
return items;
});
callbacks.registerCallback("consumeTaggedItem", [player](String const& itemTag, uint64_t count) {
for (auto const& item : player->inventory()->allItems()) {
if (item->hasItemTag(itemTag)) {
uint64_t takeCount = min(item->count(), count);
player->takeItem(item->descriptor().singular().multiply(takeCount));
count -= takeCount;
if (count == 0)
break;
}
}
});
callbacks.registerCallback("hasItemWithParameter", [player](String const& parameterName, Json const& parameterValue) {
for (auto const& item : player->inventory()->allItems()) {
if (item->instanceValue(parameterName, Json()) == parameterValue)
return true;
}
return false;
});
callbacks.registerCallback("consumeItemWithParameter", [player](String const& parameterName, Json const& parameterValue, uint64_t count) {
for (auto const& item : player->inventory()->allItems()) {
if (item->instanceValue(parameterName, Json()) == parameterValue) {
uint64_t takeCount = min(item->count(), count);
player->takeItem(item->descriptor().singular().multiply(takeCount));
count -= takeCount;
if (count == 0)
break;
}
}
});
callbacks.registerCallback("getItemWithParameter", [player](String const& parameterName, Json const& parameterValue) -> Json {
for (auto const& item : player->inventory()->allItems()) {
if (item->instanceValue(parameterName, Json()) == parameterValue)
return item->descriptor().toJson();
}
return {};
});
callbacks.registerCallback("primaryHandItem", [player]() -> Maybe<Json> {
if (!player->primaryHandItem())
return {};
return player->primaryHandItem()->descriptor().toJson();
});
callbacks.registerCallback("altHandItem", [player]() -> Maybe<Json> {
if (!player->altHandItem())
return {};
return player->altHandItem()->descriptor().toJson();
});
callbacks.registerCallback("primaryHandItemTags", [player]() -> StringSet {
if (!player->primaryHandItem())
return {};
return player->primaryHandItem()->itemTags();
});
callbacks.registerCallback("altHandItemTags", [player]() -> StringSet {
if (!player->altHandItem())
return {};
return player->altHandItem()->itemTags();
});
callbacks.registerCallback("swapSlotItem", [player]() -> Maybe<Json> {
if (!player->inventory()->swapSlotItem())
return {};
return player->inventory()->swapSlotItem()->descriptor().toJson();
});
callbacks.registerCallback("setSwapSlotItem", [player](Json const& item) {
auto itemDatabase = Root::singleton().itemDatabase();
player->inventory()->setSwapSlotItem(itemDatabase->item(ItemDescriptor(item)));
});
callbacks.registerCallback("canStartQuest",
[player](Json const& quest) { return player->questManager()->canStart(QuestArcDescriptor::fromJson(quest)); });
callbacks.registerCallback("startQuest", [player](Json const& quest, Maybe<String> const& serverUuid, Maybe<String> const& worldId) {
auto questArc = QuestArcDescriptor::fromJson(quest);
auto followUp = make_shared<Quest>(questArc, 0, player);
if (serverUuid)
followUp->setServerUuid(Uuid(*serverUuid));
if (worldId)
followUp->setWorldId(parseWorldId(*worldId));
player->questManager()->offer(followUp);
return followUp->questId();
});
callbacks.registerCallback("hasQuest", [player](String const& questId) {
return player->questManager()->hasQuest(questId);
});
callbacks.registerCallback("hasAcceptedQuest", [player](String const& questId) {
return player->questManager()->hasAcceptedQuest(questId);
});
callbacks.registerCallback("hasActiveQuest", [player](String const& questId) {
return player->questManager()->isActive(questId);
});
callbacks.registerCallback("hasCompletedQuest", [player](String const& questId) {
return player->questManager()->hasCompleted(questId);
});
callbacks.registerCallback("currentQuestWorld", [player]() -> Maybe<String> {
auto maybeQuest = player->questManager()->currentQuest();
if (maybeQuest) {
auto quest = *maybeQuest;
if (auto worldId = quest->worldId())
return printWorldId(*worldId);
}
return {};
});
callbacks.registerCallback("questWorlds", [player]() -> List<pair<String, bool>> {
List<pair<String, bool>> res;
auto maybeCurrentQuest = player->questManager()->currentQuest();
for (auto q : player->questManager()->listActiveQuests()) {
if (auto worldId = q->worldId()) {
bool isCurrentQuest = maybeCurrentQuest && maybeCurrentQuest.get()->questId() == q->questId();
res.append(pair<String, bool>(printWorldId(*worldId), isCurrentQuest));
}
}
return res;
});
callbacks.registerCallback("currentQuestLocation", [player]() -> Json {
auto maybeQuest = player->questManager()->currentQuest();
if (maybeQuest) {
if (auto questLocation = maybeQuest.get()->location())
return JsonObject{{"system", jsonFromVec3I(questLocation->first)}, {"location", jsonFromSystemLocation(questLocation->second)}};
}
return {};
});
callbacks.registerCallback("questLocations", [player]() -> List<pair<Json, bool>> {
List<pair<Json, bool>> res;
auto maybeCurrentQuest = player->questManager()->currentQuest();
for (auto q : player->questManager()->listActiveQuests()) {
if (auto questLocation = q->location()) {
bool isCurrentQuest = maybeCurrentQuest && maybeCurrentQuest.get()->questId() == q->questId();
auto locationJson = JsonObject{{"system", jsonFromVec3I(questLocation->first)}, {"location", jsonFromSystemLocation(questLocation->second)}};
res.append(pair<Json, bool>(locationJson, isCurrentQuest));
}
}
return res;
});
callbacks.registerCallback("enableMission", [player](String const& mission) {
AiState& aiState = player->aiState();
if (!aiState.completedMissions.contains(mission))
aiState.availableMissions.add(mission);
});
callbacks.registerCallback("completeMission", [player](String const& mission) {
AiState& aiState = player->aiState();
aiState.availableMissions.remove(mission);
aiState.completedMissions.add(mission);
});
callbacks.registerCallback("hasCompletedMission", [player](String const& mission) -> bool {
return player->aiState().completedMissions.contains(mission);
});
callbacks.registerCallback("radioMessage", [player](Json const& messageConfig, Maybe<float> const& delay) {
player->queueRadioMessage(messageConfig, delay.value(0));
});
callbacks.registerCallback("worldId", [player]() { return printWorldId(player->clientContext()->playerWorldId()); });
callbacks.registerCallback("serverUuid", [player]() { return player->clientContext()->serverUuid().hex(); });
callbacks.registerCallback("ownShipWorldId", [player]() { return printWorldId(ClientShipWorldId(player->uuid())); });
callbacks.registerCallback("lounge", [player](EntityId entityId, Maybe<size_t> anchorIndex) {
return player->lounge(entityId, anchorIndex.value(0));
});
callbacks.registerCallback("isLounging", [player]() { return (bool)player->loungingIn(); });
callbacks.registerCallback("loungingIn", [player]() -> Maybe<EntityId> {
if (auto anchorState = player->loungingIn())
return anchorState->entityId;
return {};
});
callbacks.registerCallback("stopLounging", [player]() { player->stopLounging(); });
callbacks.registerCallback("playTime", [player]() { return player->log()->playTime(); });
callbacks.registerCallback("introComplete", [player]() { return player->log()->introComplete(); });
callbacks.registerCallback("setIntroComplete", [player](bool complete) {
return player->log()->setIntroComplete(complete);
});
callbacks.registerCallback("warp", [player](String action, Maybe<String> animation, Maybe<bool> deploy) {
player->setPendingWarp(action, animation, deploy.value(false));
});
callbacks.registerCallback("canDeploy", [player]() {
return player->canDeploy();
});
callbacks.registerCallback("isDeployed", [player]() -> bool {
return player->isDeployed();
});
callbacks.registerCallback("confirm", [player](Json dialogConfig) {
auto pair = RpcPromise<Json>::createPair();
player->queueConfirmation(dialogConfig, pair.second);
return pair.first;
});
callbacks.registerCallback("playCinematic", [player](Json const& cinematic, Maybe<bool> unique) {
player->setPendingCinematic(cinematic, unique.value(false));
});
callbacks.registerCallback("recordEvent", [player](String const& eventName, Json const& fields) {
player->statistics()->recordEvent(eventName, fields);
});
callbacks.registerCallback("worldHasOrbitBookmark", [player](Json const& coords) -> bool {
CelestialCoordinate coordinate = CelestialCoordinate(coords);
return player->universeMap()->worldBookmark(coordinate).isValid();
});
callbacks.registerCallback("orbitBookmarks", [player]() -> List<pair<Vec3I, Json>> {
return player->universeMap()->orbitBookmarks().transformed([](pair<Vec3I, OrbitBookmark> const& p) -> pair<Vec3I, Json> {
return {p.first, p.second.toJson()};
});
});
callbacks.registerCallback("systemBookmarks", [player](Json const& coords) -> List<Json> {
CelestialCoordinate coordinate = CelestialCoordinate(coords);
return player->universeMap()->systemBookmarks(coordinate).transformed([](OrbitBookmark const& bookmark) {
return bookmark.toJson();
});
});
callbacks.registerCallback("addOrbitBookmark", [player](Json const& system, Json const& bookmarkConfig) {
CelestialCoordinate coordinate = CelestialCoordinate(system);
return player->universeMap()->addOrbitBookmark(coordinate, OrbitBookmark::fromJson(bookmarkConfig));
});
callbacks.registerCallback("removeOrbitBookmark", [player](Json const& system, Json const& bookmarkConfig) {
CelestialCoordinate coordinate = CelestialCoordinate(system);
return player->universeMap()->removeOrbitBookmark(coordinate, OrbitBookmark::fromJson(bookmarkConfig));
});
callbacks.registerCallback("teleportBookmarks", [player]() -> List<Json> {
return player->universeMap()->teleportBookmarks().transformed([](TeleportBookmark const& bookmark) -> Json {
return bookmark.toJson();
});
});
callbacks.registerCallback("addTeleportBookmark", [player](Json const& bookmarkConfig) {
return player->universeMap()->addTeleportBookmark(TeleportBookmark::fromJson(bookmarkConfig));
});
callbacks.registerCallback("removeTeleportBookmark", [player](Json const& bookmarkConfig) {
player->universeMap()->removeTeleportBookmark(TeleportBookmark::fromJson(bookmarkConfig));
});
callbacks.registerCallback("isMapped", [player](Json const& coords) {
CelestialCoordinate coordinate = CelestialCoordinate(coords);
return player->universeMap()->isMapped(coordinate);
});
callbacks.registerCallback("mappedObjects", [player](Json const& coords) -> Json {
CelestialCoordinate coordinate = CelestialCoordinate(coords);
JsonObject json;
for (auto p : player->universeMap()->mappedObjects(coordinate)) {
JsonObject object = {
{"typeName", p.second.typeName},
{"orbit", jsonFromMaybe<CelestialOrbit>(p.second.orbit, [](CelestialOrbit const& o) { return o.toJson(); })},
{"parameters", p.second.parameters}
};
json.set(p.first.hex(), object);
}
return json;
});
callbacks.registerCallback("collectables", [player](String const& collection) {
return player->log()->collectables(collection);
});
callbacks.registerCallback("getProperty", [player](String const& name, Maybe<Json> const& defaultValue) -> Json {
return player->getGenericProperty(name, defaultValue.value(Json()));
});
callbacks.registerCallback("setProperty", [player](String const& name, Json const& value) {
player->setGenericProperty(name, value);
});
callbacks.registerCallback("addScannedObject", [player](String const& objectName) -> bool {
return player->log()->addScannedObject(objectName);
});
callbacks.registerCallback("removeScannedObject", [player](String const& objectName) {
player->log()->removeScannedObject(objectName);
});
return callbacks;
}
}

View file

@ -0,0 +1,15 @@
#ifndef STAR_PLAYER_LUA_BINDINGS_HPP
#define STAR_PLAYER_LUA_BINDINGS_HPP
#include "StarLua.hpp"
namespace Star {
STAR_CLASS(Player);
namespace LuaBindings {
LuaCallbacks makePlayerCallbacks(Player* player);
}
}
#endif

View file

@ -0,0 +1,338 @@
#include "StarRootLuaBindings.hpp"
#include "StarLuaGameConverters.hpp"
#include "StarRoot.hpp"
#include "StarStoredFunctions.hpp"
#include "StarNpcDatabase.hpp"
#include "StarProjectileDatabase.hpp"
#include "StarImageMetadataDatabase.hpp"
#include "StarLiquidsDatabase.hpp"
#include "StarItemDatabase.hpp"
#include "StarTenantDatabase.hpp"
#include "StarTechDatabase.hpp"
#include "StarTreasure.hpp"
#include "StarBehaviorDatabase.hpp"
#include "StarNameGenerator.hpp"
#include "StarNpc.hpp"
#include "StarMonster.hpp"
#include "StarJsonExtra.hpp"
#include "StarBiomeDatabase.hpp"
#include "StarVersioningDatabase.hpp"
#include "StarMaterialDatabase.hpp"
#include "StarCollectionDatabase.hpp"
#include "StarBehaviorDatabase.hpp"
#include "StarDamageDatabase.hpp"
#include "StarDungeonGenerator.hpp"
namespace Star {
LuaCallbacks LuaBindings::makeRootCallbacks() {
LuaCallbacks callbacks;
auto root = Root::singletonPtr();
callbacks.registerCallbackWithSignature<Json, String>("assetJson", bind(RootCallbacks::assetJson, root, _1));
callbacks.registerCallbackWithSignature<Json, String, Json>("makeCurrentVersionedJson", bind(RootCallbacks::makeCurrentVersionedJson, root, _1, _2));
callbacks.registerCallbackWithSignature<Json, Json, String>("loadVersionedJson", bind(RootCallbacks::loadVersionedJson, root, _1, _2));
callbacks.registerCallbackWithSignature<double, String, double>("evalFunction", bind(RootCallbacks::evalFunction, root, _1, _2));
callbacks.registerCallbackWithSignature<double, String, double, double>("evalFunction2", bind(RootCallbacks::evalFunction2, root, _1, _2, _3));
callbacks.registerCallbackWithSignature<Vec2U, String>("imageSize", bind(RootCallbacks::imageSize, root, _1));
callbacks.registerCallbackWithSignature<List<Vec2I>, String, Vec2F, float, bool>("imageSpaces", bind(RootCallbacks::imageSpaces, root, _1, _2, _3, _4));
callbacks.registerCallbackWithSignature<RectU, String>("nonEmptyRegion", bind(RootCallbacks::nonEmptyRegion, root, _1));
callbacks.registerCallbackWithSignature<Json, String>("npcConfig", bind(RootCallbacks::npcConfig, root, _1));
callbacks.registerCallbackWithSignature<float, String>("projectileGravityMultiplier", bind(RootCallbacks::projectileGravityMultiplier, root, _1));
callbacks.registerCallbackWithSignature<Json, String>("projectileConfig", bind(RootCallbacks::projectileConfig, root, _1));
callbacks.registerCallbackWithSignature<Json, String>("recipesForItem", bind(RootCallbacks::recipesForItem, root, _1));
callbacks.registerCallbackWithSignature<String, String>("itemType", bind(RootCallbacks::itemType, root, _1));
callbacks.registerCallbackWithSignature<Json, String>("itemTags", bind(RootCallbacks::itemTags, root, _1));
callbacks.registerCallbackWithSignature<bool, String, String>("itemHasTag", bind(RootCallbacks::itemHasTag, root, _1, _2));
callbacks.registerCallbackWithSignature<Json, Json, Maybe<float>, Maybe<uint64_t>>("itemConfig", bind(RootCallbacks::itemConfig, root, _1, _2, _3));
callbacks.registerCallbackWithSignature<Json, Json, Maybe<float>, Maybe<uint64_t>>("createItem", bind(RootCallbacks::createItem, root, _1, _2, _3));
callbacks.registerCallbackWithSignature<Json, String>("tenantConfig", bind(RootCallbacks::tenantConfig, root, _1));
callbacks.registerCallbackWithSignature<Json, StringMap<unsigned>>("getMatchingTenants", bind(RootCallbacks::getMatchingTenants, root, _1));
callbacks.registerCallbackWithSignature<Json, LiquidId>("liquidStatusEffects", bind(RootCallbacks::liquidStatusEffects, root, _1));
callbacks.registerCallbackWithSignature<String, String, Maybe<uint64_t>>("generateName", bind(RootCallbacks::generateName, root, _1, _2));
callbacks.registerCallbackWithSignature<Json, String>("questConfig", bind(RootCallbacks::questConfig, root, _1));
callbacks.registerCallbackWithSignature<JsonArray, String, String, String, float, Maybe<uint64_t>, Maybe<JsonObject>>("npcPortrait", bind(RootCallbacks::npcPortrait, root, _1, _2, _3, _4, _5, _6));
callbacks.registerCallbackWithSignature<Json, String, String, float, Maybe<uint64_t>, Maybe<JsonObject>>("npcVariant", bind(RootCallbacks::npcVariant, root, _1, _2, _3, _4, _5));
callbacks.registerCallbackWithSignature<JsonArray, String, Maybe<JsonObject>>("monsterPortrait", bind(RootCallbacks::monsterPortrait, root, _1, _2));
callbacks.registerCallbackWithSignature<bool, String>("isTreasurePool", bind(RootCallbacks::isTreasurePool, root, _1));
callbacks.registerCallbackWithSignature<JsonArray, String, float, Maybe<uint64_t>>("createTreasure", bind(RootCallbacks::createTreasure, root, _1, _2, _3));
callbacks.registerCallbackWithSignature<Maybe<String>, String, Maybe<String>>("materialMiningSound", bind(RootCallbacks::materialMiningSound, root, _1, _2));
callbacks.registerCallbackWithSignature<Maybe<String>, String, Maybe<String>>("materialFootstepSound", bind(RootCallbacks::materialFootstepSound, root, _1, _2));
callbacks.registerCallback("materialConfig", [root](String const& materialName) -> Json {
auto materialId = root->materialDatabase()->materialId(materialName);
if (auto path = root->materialDatabase()->materialPath(materialId))
return JsonObject{{"path", *path}, {"config", root->materialDatabase()->materialConfig(materialId).get()}};
return {};
});
callbacks.registerCallback("modConfig", [root](String const& modName) -> Json {
auto modId = root->materialDatabase()->modId(modName);
if (auto path = root->materialDatabase()->modPath(modId))
return JsonObject{{"path", *path}, {"config", root->materialDatabase()->modConfig(modId).get()}};
return {};
});
callbacks.registerCallback("liquidConfig", [root](LuaEngine& engine, LuaValue nameOrId) -> Json {
LiquidId liquidId;
if (auto id = engine.luaMaybeTo<uint8_t>(nameOrId))
liquidId = *id;
else if (auto name = engine.luaMaybeTo<String>(nameOrId))
liquidId = root->liquidsDatabase()->liquidId(*name);
else
return {};
if (auto path = root->liquidsDatabase()->liquidPath(liquidId))
return JsonObject{{"path", *path}, {"config", root->liquidsDatabase()->liquidConfig(liquidId).get()}};
return {};
});
callbacks.registerCallback("liquidName", [root](LiquidId liquidId) -> String {
return root->liquidsDatabase()->liquidName(liquidId);
});
callbacks.registerCallback("liquidId", [root](String liquidName) -> LiquidId {
return root->liquidsDatabase()->liquidId(liquidName);
});
callbacks.registerCallback("monsterSkillParameter", [root](String const& skillName, String const& configParameterName) {
return root->monsterDatabase()->skillConfigParameter(skillName, configParameterName);
});
callbacks.registerCallback("monsterParameters", [root](String const& monsterType, Maybe<uint64_t> seed) {
return root->monsterDatabase()->monsterVariant(monsterType, seed.value(0)).parameters;
});
callbacks.registerCallback("monsterMovementSettings", [root](String const& monsterType, Maybe<uint64_t> seed) {
return root->monsterDatabase()->monsterVariant(monsterType, seed.value(0)).movementSettings;
});
callbacks.registerCallback("createBiome", [root](String const& biomeName, uint64_t seed, float verticalMidPoint, float threatLevel) {
try {
return root->biomeDatabase()->createBiome(biomeName, seed, verticalMidPoint, threatLevel)->toJson();
} catch (BiomeException const&) {
return Json();
}
});
callbacks.registerCallback("materialHealth", [root](String const& materialName) {
auto materialId = root->materialDatabase()->materialId(materialName);
return root->materialDatabase()->materialDamageParameters(materialId).totalHealth();
});
callbacks.registerCallback("techType", [root](String const& techName) {
return TechTypeNames.getRight(root->techDatabase()->tech(techName).type);
});
callbacks.registerCallback("hasTech", [root](String const& tech) {
return root->techDatabase()->contains(tech);
});
callbacks.registerCallback("techConfig", [root](String const& tech) {
return root->techDatabase()->tech(tech).parameters;
});
callbacks.registerCallbackWithSignature<Maybe<String>, String>("treeStemDirectory", [root](String const& stemName) {
return root->plantDatabase()->treeStemDirectory(stemName);
});
callbacks.registerCallbackWithSignature<Maybe<String>, String>("treeFoliageDirectory", [root](String const& foliageName) {
return root->plantDatabase()->treeFoliageDirectory(foliageName);
});
callbacks.registerCallback("collection", [root](String const& collectionName) {
return root->collectionDatabase()->collection(collectionName);
});
callbacks.registerCallback("collectables", [root](String const& collectionName) {
return root->collectionDatabase()->collectables(collectionName);
});
callbacks.registerCallback("elementalResistance", [root](String const& damageKindName) -> String {
DamageKind const& damageKind = root->damageDatabase()->damageKind(damageKindName);
return root->damageDatabase()->elementalType(damageKind.elementalType).resistanceStat;
});
callbacks.registerCallback("dungeonMetadata", [root](String const& name) {
return root->dungeonDefinitions()->getMetadata(name);
});
callbacks.registerCallback("systemObjectTypeConfig", [](String const& name) -> Json {
return SystemWorld::systemObjectTypeConfig(name);
});
callbacks.registerCallback("itemDescriptorsMatch", [](Json const& descriptor1, Json const& descriptor2, Maybe<bool> exactMatch) -> bool {
return ItemDescriptor(descriptor1).matches(ItemDescriptor(descriptor2), exactMatch.value(false));
});
return callbacks;
}
Json LuaBindings::RootCallbacks::assetJson(Root* root, String const& path) {
return root->assets()->json(path);
}
Json LuaBindings::RootCallbacks::makeCurrentVersionedJson(Root* root, String const& identifier, Json const& content) {
return root->versioningDatabase()->makeCurrentVersionedJson(identifier, content).toJson();
}
Json LuaBindings::RootCallbacks::loadVersionedJson(Root* root, Json const& versionedJson, String const& identifier) {
return root->versioningDatabase()->loadVersionedJson(VersionedJson::fromJson(versionedJson), identifier);
}
double LuaBindings::RootCallbacks::evalFunction(Root* root, String const& arg1, double arg2) {
return root->functionDatabase()->function(arg1)->evaluate(arg2);
}
double LuaBindings::RootCallbacks::evalFunction2(Root* root, String const& arg1, double arg2, double arg3) {
return root->functionDatabase()->function2(arg1)->evaluate(arg2, arg3);
}
Vec2U LuaBindings::RootCallbacks::imageSize(Root* root, String const& arg1) {
return root->imageMetadataDatabase()->imageSize(arg1);
}
List<Vec2I> LuaBindings::RootCallbacks::imageSpaces(
Root* root, String const& arg1, Vec2F const& arg2, float arg3, bool arg4) {
return root->imageMetadataDatabase()->imageSpaces(arg1, arg2, arg3, arg4);
}
RectU LuaBindings::RootCallbacks::nonEmptyRegion(Root* root, String const& arg1) {
return root->imageMetadataDatabase()->nonEmptyRegion(arg1);
}
Json LuaBindings::RootCallbacks::npcConfig(Root* root, String const& arg1) {
return root->npcDatabase()->buildConfig(arg1);
}
float LuaBindings::RootCallbacks::projectileGravityMultiplier(Root* root, String const& arg1) {
auto projectileDatabase = root->projectileDatabase();
return projectileDatabase->gravityMultiplier(arg1);
}
Json LuaBindings::RootCallbacks::projectileConfig(Root* root, String const& arg1) {
auto projectileDatabase = root->projectileDatabase();
return projectileDatabase->projectileConfig(arg1);
}
Json LuaBindings::RootCallbacks::recipesForItem(Root* root, String const& arg1) {
auto recipes = root->itemDatabase()->recipesForOutputItem(arg1);
JsonArray result;
for (auto recipe : recipes)
result.append(recipe.toJson());
return result;
}
String LuaBindings::RootCallbacks::itemType(Root* root, String const& itemName) {
return ItemTypeNames.getRight(root->itemDatabase()->itemType(itemName));
}
Json LuaBindings::RootCallbacks::itemTags(Root* root, String const& itemName) {
return jsonFromStringSet(root->itemDatabase()->itemTags(itemName));
}
bool LuaBindings::RootCallbacks::itemHasTag(Root* root, String const& itemName, String const& itemTag) {
return root->itemDatabase()->itemTags(itemName).contains(itemTag);
}
Json LuaBindings::RootCallbacks::itemConfig(Root* root, Json const& descJson, Maybe<float> const& level, Maybe<uint64_t> const& seed) {
ItemDescriptor descriptor(descJson);
if (!root->itemDatabase()->hasItem(descriptor.name()))
return {};
auto config = root->itemDatabase()->itemConfig(descriptor.name(), descriptor.parameters(), level, seed);
return JsonObject{{"directory", config.directory}, {"config", config.config}, {"parameters", config.parameters}};
}
Json LuaBindings::RootCallbacks::createItem(Root* root, Json const& descriptor, Maybe<float> const& level, Maybe<uint64_t> const& seed) {
auto item = root->itemDatabase()->item(ItemDescriptor(descriptor), level, seed);
return item->descriptor().toJson();
}
Json LuaBindings::RootCallbacks::tenantConfig(Root* root, String const& tenantName) {
return root->tenantDatabase()->getTenant(tenantName)->config;
}
JsonArray LuaBindings::RootCallbacks::getMatchingTenants(Root* root, StringMap<unsigned> const& colonyTags) {
return root->tenantDatabase()
->getMatchingTenants(colonyTags)
.transformed([](TenantPtr const& tenant) { return tenant->config; });
}
Json LuaBindings::RootCallbacks::liquidStatusEffects(Root* root, LiquidId arg1) {
if (auto liquidSettings = root->liquidsDatabase()->liquidSettings(arg1))
return liquidSettings->statusEffects;
return Json();
}
String LuaBindings::RootCallbacks::generateName(Root* root, String const& rulesAsset, Maybe<uint64_t> seed) {
return root->nameGenerator()->generateName(rulesAsset, seed.value(Random::randu64()));
}
Json LuaBindings::RootCallbacks::questConfig(Root* root, String const& templateId) {
return root->questTemplateDatabase()->questTemplate(templateId)->config;
}
JsonArray LuaBindings::RootCallbacks::npcPortrait(Root* root,
String const& portraitMode,
String const& species,
String const& typeName,
float level,
Maybe<uint64_t> seed,
Maybe<JsonObject> const& parameters) {
auto npcDatabase = root->npcDatabase();
auto npcVariant = npcDatabase->generateNpcVariant(species, typeName, level, seed.value(Random::randu64()), parameters.value(JsonObject{}));
auto drawables = npcDatabase->npcPortrait(npcVariant, PortraitModeNames.getLeft(portraitMode));
return drawables.transformed(mem_fn(&Drawable::toJson));
}
Json LuaBindings::RootCallbacks::npcVariant(Root* root, String const& species, String const& typeName, float level, Maybe<uint64_t> seed, Maybe<JsonObject> const& parameters) {
auto npcDatabase = root->npcDatabase();
auto npcVariant = npcDatabase->generateNpcVariant(
species, typeName, level, seed.value(Random::randu64()), parameters.value(JsonObject{}));
return npcDatabase->writeNpcVariantToJson(npcVariant);
}
JsonArray LuaBindings::RootCallbacks::monsterPortrait(Root* root, String const& typeName, Maybe<JsonObject> const& parameters) {
auto monsterDatabase = root->monsterDatabase();
auto seed = 0; // use a static seed to utilize caching
auto monsterVariant = monsterDatabase->monsterVariant(typeName, seed, parameters.value(JsonObject{}));
auto drawables = monsterDatabase->monsterPortrait(monsterVariant);
return drawables.transformed(mem_fn(&Drawable::toJson));
}
bool LuaBindings::RootCallbacks::isTreasurePool(Root* root, String const& pool) {
return root->treasureDatabase()->isTreasurePool(pool);
}
JsonArray LuaBindings::RootCallbacks::createTreasure(
Root* root, String const& pool, float level, Maybe<uint64_t> seed) {
auto treasure = root->treasureDatabase()->createTreasure(pool, level, seed.value(Random::randu64()));
return treasure.transformed([](ItemPtr const& item) { return item->descriptor().toJson(); });
}
Maybe<String> LuaBindings::RootCallbacks::materialMiningSound(
Root* root, String const& materialName, Maybe<String> const& modName) {
auto materialDatabase = root->materialDatabase();
auto materialId = materialDatabase->materialId(materialName);
auto modId = modName.apply(bind(&MaterialDatabase::modId, materialDatabase, _1)).value(NoModId);
auto sound = materialDatabase->miningSound(materialId, modId);
if (sound.empty())
return {};
return sound;
}
Maybe<String> LuaBindings::RootCallbacks::materialFootstepSound(
Root* root, String const& materialName, Maybe<String> const& modName) {
auto materialDatabase = root->materialDatabase();
auto materialId = materialDatabase->materialId(materialName);
auto modId = modName.apply(bind(&MaterialDatabase::modId, materialDatabase, _1)).value(NoModId);
auto sound = materialDatabase->footstepSound(materialId, modId);
if (sound.empty())
return {};
return sound;
}
}

View file

@ -0,0 +1,60 @@
#ifndef STAR_ROOT_LUA_BINDINGS_HPP
#define STAR_ROOT_LUA_BINDINGS_HPP
#include "StarRect.hpp"
#include "StarGameTypes.hpp"
#include "StarLua.hpp"
namespace Star {
STAR_CLASS(Root);
namespace LuaBindings {
LuaCallbacks makeRootCallbacks();
namespace RootCallbacks {
Json assetJson(Root* root, String const& path);
Json makeCurrentVersionedJson(Root* root, String const& identifier, Json const& content);
Json loadVersionedJson(Root* root, Json const& versionedJson, String const& expectedIdentifier);
double evalFunction(Root* root, String const& arg1, double arg2);
double evalFunction2(Root* root, String const& arg1, double arg2, double arg3);
Vec2U imageSize(Root* root, String const& arg1);
List<Vec2I> imageSpaces(Root* root, String const& arg1, Vec2F const& arg2, float arg3, bool arg4);
RectU nonEmptyRegion(Root* root, String const& arg1);
Json npcConfig(Root* root, String const& arg1);
float projectileGravityMultiplier(Root* root, String const& arg1);
Json projectileConfig(Root* root, String const& arg1);
Json recipesForItem(Root* root, String const& arg1);
String itemType(Root* root, String const& itemName);
Json itemTags(Root* root, String const& itemName);
bool itemHasTag(Root* root, String const& itemName, String const& itemTag);
Json itemConfig(Root* root, Json const& descriptor, Maybe<float> const& level, Maybe<uint64_t> const& seed);
Json createItem(Root* root, Json const& descriptor, Maybe<float> const& level, Maybe<uint64_t> const& seed);
Json tenantConfig(Root* root, String const& tenantName);
JsonArray getMatchingTenants(Root* root, StringMap<unsigned> const& colonyTags);
Json liquidStatusEffects(Root* root, LiquidId arg1);
String generateName(Root* root, String const& rulesAsset, Maybe<uint64_t> seed);
Json questConfig(Root* root, String const& templateId);
JsonArray npcPortrait(Root* root,
String const& portraitMode,
String const& species,
String const& typeName,
float level,
Maybe<uint64_t> seed,
Maybe<JsonObject> const& parameters);
Json npcVariant(Root* root,
String const& species,
String const& typeName,
float level,
Maybe<uint64_t> seed,
Maybe<JsonObject> const& parameters);
JsonArray monsterPortrait(Root* root, String const& typeName, Maybe<JsonObject> const& parameters);
bool isTreasurePool(Root* root, String const& pool);
JsonArray createTreasure(Root* root, String const& pool, float level, Maybe<uint64_t> seed);
Maybe<String> materialMiningSound(Root* root, String const& materialName, Maybe<String> const& modName);
Maybe<String> materialFootstepSound(Root* root, String const& materialName, Maybe<String> const& modName);
}
}
}
#endif

View file

@ -0,0 +1,27 @@
#include "StarScriptedAnimatorLuaBindings.hpp"
#include "StarJsonExtra.hpp"
#include "StarLuaGameConverters.hpp"
namespace Star {
LuaCallbacks LuaBindings::makeScriptedAnimatorCallbacks(const NetworkedAnimator* animator, function<Json(String const&, Json const&)> getParameter) {
LuaCallbacks callbacks;
callbacks.registerCallback("animationParameter", getParameter);
callbacks.registerCallback("partPoint", [animator](String const& partName, String const& propertyName) {
return animator->partPoint(partName, propertyName);
});
callbacks.registerCallback("partPoly", [animator](String const& partName, String const& propertyName) { return animator->partPoly(partName, propertyName); });
callbacks.registerCallback("transformPoint", [animator] (Vec2F point, String const& part) -> Vec2F {
return animator->partTransformation(part).transformVec2(point);
});
callbacks.registerCallback("transformPoly", [animator] (PolyF poly, String const& part) -> PolyF {
poly.transform(animator->partTransformation(part));
return poly;
});
return callbacks;
}
}

View file

@ -0,0 +1,14 @@
#ifndef STAR_SCRIPTED_ANIMATOR_LUA_BINDINGS_HPP
#define STAR_SCRIPTED_ANIMATOR_LUA_BINDINGS_HPP
#include "StarLua.hpp"
#include "StarNetworkedAnimator.hpp"
namespace Star {
namespace LuaBindings {
LuaCallbacks makeScriptedAnimatorCallbacks(const NetworkedAnimator* animator, function<Json(String const&, Json const&)> getParameter);
}
}
#endif

View file

@ -0,0 +1,271 @@
#include "StarStatusControllerLuaBindings.hpp"
#include "StarStatusController.hpp"
#include "StarJsonExtra.hpp"
#include "StarLuaGameConverters.hpp"
namespace Star {
LuaCallbacks LuaBindings::makeStatusControllerCallbacks(StatusController* statController) {
LuaCallbacks callbacks;
callbacks.registerCallbackWithSignature<Json, String, Json>(
"statusProperty", bind(StatusControllerCallbacks::statusProperty, statController, _1, _2));
callbacks.registerCallbackWithSignature<void, String, Json>(
"setStatusProperty", bind(StatusControllerCallbacks::setStatusProperty, statController, _1, _2));
callbacks.registerCallbackWithSignature<float, String>(
"stat", bind(StatusControllerCallbacks::stat, statController, _1));
callbacks.registerCallbackWithSignature<bool, String>(
"statPositive", bind(StatusControllerCallbacks::statPositive, statController, _1));
callbacks.registerCallbackWithSignature<StringList>(
"resourceNames", bind(StatusControllerCallbacks::resourceNames, statController));
callbacks.registerCallbackWithSignature<bool, String>(
"isResource", bind(StatusControllerCallbacks::isResource, statController, _1));
callbacks.registerCallbackWithSignature<float, String>(
"resource", bind(StatusControllerCallbacks::resource, statController, _1));
callbacks.registerCallbackWithSignature<bool, String>(
"resourcePositive", bind(StatusControllerCallbacks::resourcePositive, statController, _1));
callbacks.registerCallbackWithSignature<void, String, float>(
"setResource", bind(StatusControllerCallbacks::setResource, statController, _1, _2));
callbacks.registerCallbackWithSignature<void, String, float>(
"modifyResource", bind(StatusControllerCallbacks::modifyResource, statController, _1, _2));
callbacks.registerCallbackWithSignature<float, String, float>(
"giveResource", bind(StatusControllerCallbacks::giveResource, statController, _1, _2));
callbacks.registerCallbackWithSignature<bool, String, float>(
"consumeResource", bind(StatusControllerCallbacks::consumeResource, statController, _1, _2));
callbacks.registerCallbackWithSignature<bool, String, float>(
"overConsumeResource", bind(StatusControllerCallbacks::overConsumeResource, statController, _1, _2));
callbacks.registerCallbackWithSignature<bool, String>(
"resourceLocked", bind(StatusControllerCallbacks::resourceLocked, statController, _1));
callbacks.registerCallbackWithSignature<void, String, bool>(
"setResourceLocked", bind(StatusControllerCallbacks::setResourceLocked, statController, _1, _2));
callbacks.registerCallbackWithSignature<void, String>(
"resetResource", bind(StatusControllerCallbacks::resetResource, statController, _1));
callbacks.registerCallbackWithSignature<void>(
"resetAllResources", bind(StatusControllerCallbacks::resetAllResources, statController));
callbacks.registerCallbackWithSignature<Maybe<float>, String>(
"resourceMax", bind(StatusControllerCallbacks::resourceMax, statController, _1));
callbacks.registerCallbackWithSignature<Maybe<float>, String>(
"resourcePercentage", bind(StatusControllerCallbacks::resourcePercentage, statController, _1));
callbacks.registerCallbackWithSignature<float, String, float>(
"setResourcePercentage", bind(StatusControllerCallbacks::setResourcePercentage, statController, _1, _2));
callbacks.registerCallbackWithSignature<float, String, float>(
"modifyResourcePercentage", bind(StatusControllerCallbacks::modifyResourcePercentage, statController, _1, _2));
callbacks.registerCallbackWithSignature<JsonArray, String>(
"getPersistentEffects", bind(StatusControllerCallbacks::getPersistentEffects, statController, _1));
callbacks.registerCallbackWithSignature<void, String, Json>(
"addPersistentEffect", bind(StatusControllerCallbacks::addPersistentEffect, statController, _1, _2));
callbacks.registerCallbackWithSignature<void, String, JsonArray>(
"addPersistentEffects", bind(StatusControllerCallbacks::addPersistentEffects, statController, _1, _2));
callbacks.registerCallbackWithSignature<void, String, JsonArray>(
"setPersistentEffects", bind(StatusControllerCallbacks::setPersistentEffects, statController, _1, _2));
callbacks.registerCallbackWithSignature<void, String>(
"clearPersistentEffects", bind(StatusControllerCallbacks::clearPersistentEffects, statController, _1));
callbacks.registerCallbackWithSignature<void>(
"clearAllPersistentEffects", bind(StatusControllerCallbacks::clearAllPersistentEffects, statController));
callbacks.registerCallbackWithSignature<void, String, Maybe<float>, Maybe<EntityId>>(
"addEphemeralEffect", bind(StatusControllerCallbacks::addEphemeralEffect, statController, _1, _2, _3));
callbacks.registerCallbackWithSignature<void, JsonArray, Maybe<EntityId>>(
"addEphemeralEffects", bind(StatusControllerCallbacks::addEphemeralEffects, statController, _1, _2));
callbacks.registerCallbackWithSignature<void, String>(
"removeEphemeralEffect", bind(StatusControllerCallbacks::removeEphemeralEffect, statController, _1));
callbacks.registerCallbackWithSignature<void>(
"clearEphemeralEffects", bind(StatusControllerCallbacks::clearEphemeralEffects, statController));
callbacks.registerCallbackWithSignature<LuaTupleReturn<List<Json>, uint64_t>, Maybe<uint64_t>>(
"damageTakenSince", bind(StatusControllerCallbacks::damageTakenSince, statController, _1));
callbacks.registerCallbackWithSignature<LuaTupleReturn<List<Json>, uint64_t>, Maybe<uint64_t>>(
"inflictedHitsSince", bind(StatusControllerCallbacks::inflictedHitsSince, statController, _1));
callbacks.registerCallbackWithSignature<LuaTupleReturn<List<Json>, uint64_t>, Maybe<uint64_t>>(
"inflictedDamageSince", bind(StatusControllerCallbacks::inflictedDamageSince, statController, _1));
callbacks.registerCallbackWithSignature<List<JsonArray>>("activeUniqueStatusEffectSummary",
bind(&StatusControllerCallbacks::activeUniqueStatusEffectSummary, statController));
callbacks.registerCallbackWithSignature<bool, String>("uniqueStatusEffectActive",
bind(&StatusControllerCallbacks::uniqueStatusEffectActive, statController, _1));
callbacks.registerCallbackWithSignature<String>("primaryDirectives", bind(&StatusController::primaryDirectives, statController));
callbacks.registerCallback("setPrimaryDirectives", [statController](Maybe<String> const& directives) { statController->setPrimaryDirectives(directives.value()); });
callbacks.registerCallbackWithSignature<void, DamageRequest>("applySelfDamageRequest", bind(&StatusController::applySelfDamageRequest, statController, _1));
return callbacks;
}
Json LuaBindings::StatusControllerCallbacks::statusProperty(
StatusController* statController, String const& arg1, Json const& arg2) {
return statController->statusProperty(arg1, arg2);
}
void LuaBindings::StatusControllerCallbacks::setStatusProperty(
StatusController* statController, String const& arg1, Json const& arg2) {
statController->setStatusProperty(arg1, arg2);
}
float LuaBindings::StatusControllerCallbacks::stat(StatusController* statController, String const& arg1) {
return statController->stat(arg1);
}
bool LuaBindings::StatusControllerCallbacks::statPositive(StatusController* statController, String const& arg1) {
return statController->statPositive(arg1);
}
StringList LuaBindings::StatusControllerCallbacks::resourceNames(StatusController* statController) {
return statController->resourceNames();
}
bool LuaBindings::StatusControllerCallbacks::isResource(StatusController* statController, String const& arg1) {
return statController->isResource(arg1);
}
float LuaBindings::StatusControllerCallbacks::resource(StatusController* statController, String const& arg1) {
return statController->resource(arg1);
}
bool LuaBindings::StatusControllerCallbacks::resourcePositive(StatusController* statController, String const& arg1) {
return statController->resourcePositive(arg1);
}
void LuaBindings::StatusControllerCallbacks::setResource(
StatusController* statController, String const& arg1, float arg2) {
statController->setResource(arg1, arg2);
}
void LuaBindings::StatusControllerCallbacks::modifyResource(
StatusController* statController, String const& arg1, float arg2) {
statController->modifyResource(arg1, arg2);
}
float LuaBindings::StatusControllerCallbacks::giveResource(
StatusController* statController, String const& resourceName, float amount) {
return statController->giveResource(resourceName, amount);
}
bool LuaBindings::StatusControllerCallbacks::consumeResource(
StatusController* statController, String const& arg1, float arg2) {
return statController->consumeResource(arg1, arg2);
}
bool LuaBindings::StatusControllerCallbacks::overConsumeResource(
StatusController* statController, String const& arg1, float arg2) {
return statController->overConsumeResource(arg1, arg2);
}
bool LuaBindings::StatusControllerCallbacks::resourceLocked(StatusController* statController, String const& arg1) {
return statController->resourceLocked(arg1);
}
void LuaBindings::StatusControllerCallbacks::setResourceLocked(
StatusController* statController, String const& arg1, bool arg2) {
statController->setResourceLocked(arg1, arg2);
}
void LuaBindings::StatusControllerCallbacks::resetResource(StatusController* statController, String const& arg1) {
statController->resetResource(arg1);
}
void LuaBindings::StatusControllerCallbacks::resetAllResources(StatusController* statController) {
statController->resetAllResources();
}
Maybe<float> LuaBindings::StatusControllerCallbacks::resourceMax(StatusController* statController, String const& arg1) {
return statController->resourceMax(arg1);
}
Maybe<float> LuaBindings::StatusControllerCallbacks::resourcePercentage(
StatusController* statController, String const& arg1) {
return statController->resourcePercentage(arg1);
}
float LuaBindings::StatusControllerCallbacks::setResourcePercentage(
StatusController* statController, String const& arg1, float arg2) {
return statController->setResourcePercentage(arg1, arg2);
}
float LuaBindings::StatusControllerCallbacks::modifyResourcePercentage(
StatusController* statController, String const& arg1, float arg2) {
return statController->modifyResourcePercentage(arg1, arg2);
}
JsonArray LuaBindings::StatusControllerCallbacks::getPersistentEffects(
StatusController* statController, String const& arg1) {
return statController->getPersistentEffects(arg1).transformed(jsonFromPersistentStatusEffect);
}
void LuaBindings::StatusControllerCallbacks::addPersistentEffect(
StatusController* statController, String const& arg1, Json const& arg2) {
addPersistentEffects(statController, arg1, JsonArray{arg2});
}
void LuaBindings::StatusControllerCallbacks::addPersistentEffects(
StatusController* statController, String const& arg1, JsonArray const& arg2) {
statController->addPersistentEffects(arg1, arg2.transformed(jsonToPersistentStatusEffect));
}
void LuaBindings::StatusControllerCallbacks::setPersistentEffects(
StatusController* statController, String const& arg1, JsonArray const& arg2) {
statController->setPersistentEffects(arg1, arg2.transformed(jsonToPersistentStatusEffect));
}
void LuaBindings::StatusControllerCallbacks::clearPersistentEffects(
StatusController* statController, String const& arg1) {
statController->clearPersistentEffects(arg1);
}
void LuaBindings::StatusControllerCallbacks::clearAllPersistentEffects(StatusController* statController) {
statController->clearAllPersistentEffects();
}
void LuaBindings::StatusControllerCallbacks::addEphemeralEffect(
StatusController* statController, String const& arg1, Maybe<float> arg2, Maybe<EntityId> sourceEntityId) {
statController->addEphemeralEffect(EphemeralStatusEffect{UniqueStatusEffect{arg1}, arg2}, sourceEntityId);
}
void LuaBindings::StatusControllerCallbacks::addEphemeralEffects(
StatusController* statController, JsonArray const& arg1, Maybe<EntityId> sourceEntityId) {
statController->addEphemeralEffects(arg1.transformed(jsonToEphemeralStatusEffect), sourceEntityId);
}
void LuaBindings::StatusControllerCallbacks::removeEphemeralEffect(
StatusController* statController, String const& arg1) {
statController->removeEphemeralEffect(UniqueStatusEffect{arg1});
}
void LuaBindings::StatusControllerCallbacks::clearEphemeralEffects(StatusController* statController) {
statController->clearEphemeralEffects();
}
LuaTupleReturn<List<Json>, uint64_t> LuaBindings::StatusControllerCallbacks::damageTakenSince(
StatusController* statController, Maybe<uint64_t> timestep) {
auto pair = statController->damageTakenSince(timestep.value());
return luaTupleReturn(pair.first.transformed(mem_fn(&DamageNotification::toJson)), pair.second);
}
LuaTupleReturn<List<Json>, uint64_t> LuaBindings::StatusControllerCallbacks::inflictedHitsSince(
StatusController* statController, Maybe<uint64_t> timestep) {
auto pair = statController->inflictedHitsSince(timestep.value());
return luaTupleReturn(
pair.first.transformed([](auto const& p) { return p.second.toJson().set("targetEntityId", p.first); }),
pair.second);
}
LuaTupleReturn<List<Json>, uint64_t> LuaBindings::StatusControllerCallbacks::inflictedDamageSince(
StatusController* statController, Maybe<uint64_t> timestep) {
auto pair = statController->inflictedDamageSince(timestep.value());
return luaTupleReturn(pair.first.transformed(mem_fn(&DamageNotification::toJson)), pair.second);
}
List<JsonArray> LuaBindings::StatusControllerCallbacks::activeUniqueStatusEffectSummary(
StatusController* statController) {
auto summary = statController->activeUniqueStatusEffectSummary();
return summary.transformed([](pair<UniqueStatusEffect, Maybe<float>> effect) {
JsonArray effectJson = {effect.first};
if (effect.second)
effectJson.append(*effect.second);
return effectJson;
});
}
bool LuaBindings::StatusControllerCallbacks::uniqueStatusEffectActive(
StatusController* statController, String const& effectName) {
return statController->uniqueStatusEffectActive(effectName);
}
}

View file

@ -0,0 +1,59 @@
#ifndef STAR_STAT_CONTROLLER_LUA_BINDINGS_HPP
#define STAR_STAT_CONTROLLER_LUA_BINDINGS_HPP
#include "StarLua.hpp"
#include "StarEntity.hpp"
namespace Star {
STAR_CLASS(StatusController);
namespace LuaBindings {
LuaCallbacks makeStatusControllerCallbacks(StatusController* statController);
namespace StatusControllerCallbacks {
Json statusProperty(StatusController* statController, String const& arg1, Json const& arg2);
void setStatusProperty(StatusController* statController, String const& arg1, Json const& arg2);
float stat(StatusController* statController, String const& arg1);
bool statPositive(StatusController* statController, String const& arg1);
StringList resourceNames(StatusController* statController);
bool isResource(StatusController* statController, String const& arg1);
float resource(StatusController* statController, String const& arg1);
bool resourcePositive(StatusController* statController, String const& arg1);
void setResource(StatusController* statController, String const& arg1, float arg2);
void modifyResource(StatusController* statController, String const& arg1, float arg2);
float giveResource(StatusController* statController, String const& resourceName, float amount);
bool consumeResource(StatusController* statController, String const& arg1, float arg2);
bool overConsumeResource(StatusController* statController, String const& arg1, float arg2);
bool resourceLocked(StatusController* statController, String const& arg1);
void setResourceLocked(StatusController* statController, String const& arg1, bool arg2);
void resetResource(StatusController* statController, String const& arg1);
void resetAllResources(StatusController* statController);
Maybe<float> resourceMax(StatusController* statController, String const& arg1);
Maybe<float> resourcePercentage(StatusController* statController, String const& arg1);
float setResourcePercentage(StatusController* statController, String const& arg1, float arg2);
float modifyResourcePercentage(StatusController* statController, String const& arg1, float arg2);
JsonArray getPersistentEffects(StatusController* statController, String const& arg1);
void addPersistentEffect(StatusController* statController, String const& arg1, Json const& arg2);
void addPersistentEffects(StatusController* statController, String const& arg1, JsonArray const& arg2);
void setPersistentEffects(StatusController* statController, String const& arg1, JsonArray const& arg2);
void clearPersistentEffects(StatusController* statController, String const& arg1);
void clearAllPersistentEffects(StatusController* statController);
void addEphemeralEffect(StatusController* statController,
String const& uniqueEffect,
Maybe<float> duration,
Maybe<EntityId> sourceEntityId);
void addEphemeralEffects(StatusController* statController, JsonArray const& arg1, Maybe<EntityId> sourceEntityId);
void removeEphemeralEffect(StatusController* statController, String const& arg1);
void clearEphemeralEffects(StatusController* statController);
LuaTupleReturn<List<Json>, uint64_t> damageTakenSince(StatusController* statController, Maybe<uint64_t> timestep);
LuaTupleReturn<List<Json>, uint64_t> inflictedHitsSince(StatusController* statController, Maybe<uint64_t> timestep);
LuaTupleReturn<List<Json>, uint64_t> inflictedDamageSince(
StatusController* statController, Maybe<uint64_t> timestep);
List<JsonArray> activeUniqueStatusEffectSummary(StatusController* statController);
bool uniqueStatusEffectActive(StatusController* statController, String const& effectName);
}
}
}
#endif

View file

@ -0,0 +1,110 @@
#include "StarUniverseServerLuaBindings.hpp"
#include "StarJsonExtra.hpp"
#include "StarLuaGameConverters.hpp"
#include "StarUniverseServer.hpp"
namespace Star {
LuaCallbacks LuaBindings::makeUniverseServerCallbacks(UniverseServer* universe) {
LuaCallbacks callbacks;
callbacks.registerCallbackWithSignature<List<ConnectionId>>("clientIds", bind(UniverseServerCallbacks::clientIds, universe));
callbacks.registerCallbackWithSignature<size_t>("numberOfClients", bind(UniverseServerCallbacks::numberOfClients, universe));
callbacks.registerCallbackWithSignature<bool, ConnectionId>("isConnectedClient", bind(UniverseServerCallbacks::isConnectedClient, universe, _1));
callbacks.registerCallbackWithSignature<String, ConnectionId>("clientNick", bind(UniverseServerCallbacks::clientNick, universe, _1));
callbacks.registerCallbackWithSignature<Maybe<ConnectionId>, String>("findNick", bind(UniverseServerCallbacks::findNick, universe, _1));
callbacks.registerCallbackWithSignature<void, String>("adminBroadcast", bind(UniverseServerCallbacks::adminBroadcast, universe, _1));
callbacks.registerCallbackWithSignature<void, ConnectionId, String>("adminWhisper", bind(UniverseServerCallbacks::adminWhisper, universe, _1, _2));
callbacks.registerCallbackWithSignature<bool, ConnectionId>("isAdmin", bind(UniverseServerCallbacks::isAdmin, universe, _1));
callbacks.registerCallbackWithSignature<bool, ConnectionId>("isPvp", bind(UniverseServerCallbacks::isPvp, universe, _1));
callbacks.registerCallbackWithSignature<void, ConnectionId, bool>("setPvp", bind(UniverseServerCallbacks::setPvp, universe, _1, _2));
return callbacks;
}
// Gets a list of client ids
//
// @return A list of numerical client IDs.
List<ConnectionId> LuaBindings::UniverseServerCallbacks::clientIds(UniverseServer* universe) {
return universe->clientIds();
}
// Gets the number of logged in clients
//
// @return An integer containing the number of logged in clients
size_t LuaBindings::UniverseServerCallbacks::numberOfClients(UniverseServer* universe) {
return universe->numberOfClients();
}
// Returns whether or not the provided client ID is currently connected
//
// @param clientId the client ID in question
// @return A bool that is true if the client is connected and false otherwise
bool LuaBindings::UniverseServerCallbacks::isConnectedClient(UniverseServer* universe, ConnectionId arg1) {
return universe->isConnectedClient(arg1);
}
// Returns the nickname for the given client ID
//
// @param clientId the client ID in question
// @return A string containing the nickname of the given client
String LuaBindings::UniverseServerCallbacks::clientNick(UniverseServer* universe, ConnectionId arg1) {
return universe->clientNick(arg1);
}
// Returns the client ID for the given nick
//
// @param nick the nickname of the client to search for
// @return An integer containing the clientID of the nick in question
Maybe<ConnectionId> LuaBindings::UniverseServerCallbacks::findNick(UniverseServer* universe, String const& arg1) {
return universe->findNick(arg1);
}
// Sends a message to all logged in clients
//
// @param message the message to broadcast
// @return nil
void LuaBindings::UniverseServerCallbacks::adminBroadcast(UniverseServer* universe, String const& arg1) {
universe->adminBroadcast(arg1);
}
// Sends a message to a specific client
//
// @param clientId the client id to whisper
// @param message the message to whisper
// @return nil
void LuaBindings::UniverseServerCallbacks::adminWhisper(UniverseServer* universe, ConnectionId arg1, String const& arg2) {
ConnectionId client = arg1;
String message = arg2;
universe->adminWhisper(client, message);
}
// Returns whether or not a specific client is flagged as an admin
//
// @param clientId the client id to check
// @return a boolean containing true if the client is an admin, false otherwise
bool LuaBindings::UniverseServerCallbacks::isAdmin(UniverseServer* universe, ConnectionId arg1) {
return universe->isAdmin(arg1);
}
// Returns whether or not a specific client is flagged as pvp
//
// @param clientId the client id to check
// @return a boolean containing true if the client is flagged as pvp, false
// otherwise
bool LuaBindings::UniverseServerCallbacks::isPvp(UniverseServer* universe, ConnectionId arg1) {
return universe->isPvp(arg1);
}
// Set (or unset) the pvp status of a specific user
//
// @param clientId the client id to check
// @param setPvp set pvp status to this bool, defaults to true
// @return nil
void LuaBindings::UniverseServerCallbacks::setPvp(UniverseServer* universe, ConnectionId arg1, Maybe<bool> arg2) {
ConnectionId client = arg1;
bool setPvpTo = arg2.value(true);
universe->setPvp(client, setPvpTo);
}
}

View file

@ -0,0 +1,29 @@
#ifndef STAR_UNIVERSE_SERVER_LUA_BINDINGS_HPP
#define STAR_UNIVERSE_SERVER_LUA_BINDINGS_HPP
#include "StarLua.hpp"
#include "StarGameTypes.hpp"
namespace Star {
STAR_CLASS(UniverseServer);
namespace LuaBindings {
LuaCallbacks makeUniverseServerCallbacks(UniverseServer* universe);
namespace UniverseServerCallbacks {
List<ConnectionId> clientIds(UniverseServer* universe);
size_t numberOfClients(UniverseServer* universe);
bool isConnectedClient(UniverseServer* universe, ConnectionId arg1);
String clientNick(UniverseServer* universe, ConnectionId arg1);
Maybe<ConnectionId> findNick(UniverseServer* universe, String const& arg1);
void adminBroadcast(UniverseServer* universe, String const& arg1);
void adminWhisper(UniverseServer* universe, ConnectionId arg1, String const& arg2);
bool isAdmin(UniverseServer* universe, ConnectionId arg1);
bool isPvp(UniverseServer* universe, ConnectionId arg1);
void setPvp(UniverseServer* universe, ConnectionId arg1, Maybe<bool> arg2);
}
}
}
#endif

View file

@ -0,0 +1,252 @@
#include "StarUtilityLuaBindings.hpp"
#include "StarJsonExtra.hpp"
#include "StarLuaGameConverters.hpp"
#include "StarUuid.hpp"
#include "StarRandom.hpp"
#include "StarPerlin.hpp"
#include "StarXXHash.hpp"
#include "StarLogging.hpp"
#include "StarInterpolation.hpp"
namespace Star {
template <>
struct LuaConverter<RandomSource> : LuaUserDataConverter<RandomSource> {};
template <>
struct LuaUserDataMethods<RandomSource> {
static LuaMethods<RandomSource> make() {
LuaMethods<RandomSource> methods;
methods.registerMethod("init",
[](RandomSource& randomSource, Maybe<uint64_t> seed) {
if (seed)
randomSource.init(*seed);
else
randomSource.init();
});
methods.registerMethod("addEntropy",
[](RandomSource& randomSource, Maybe<uint64_t> seed) {
if (seed)
randomSource.addEntropy(*seed);
else
randomSource.addEntropy();
});
methods.registerMethodWithSignature<uint32_t, RandomSource&>("randu32", mem_fn(&RandomSource::randu32));
methods.registerMethodWithSignature<uint64_t, RandomSource&>("randu64", mem_fn(&RandomSource::randu64));
methods.registerMethodWithSignature<int32_t, RandomSource&>("randi32", mem_fn(&RandomSource::randi32));
methods.registerMethodWithSignature<int64_t, RandomSource&>("randi64", mem_fn(&RandomSource::randi64));
methods.registerMethod("randf",
[](RandomSource& randomSource, Maybe<float> arg1, Maybe<float> arg2) {
if (arg1 && arg2)
return randomSource.randf(*arg1, *arg2);
else
return randomSource.randf();
});
methods.registerMethod("randd",
[](RandomSource& randomSource, Maybe<double> arg1, Maybe<double> arg2) {
if (arg1 && arg2)
return randomSource.randd(*arg1, *arg2);
else
return randomSource.randd();
});
methods.registerMethodWithSignature<bool, RandomSource&>("randb", mem_fn(&RandomSource::randb));
methods.registerMethod("randInt",
[](RandomSource& randomSource, int64_t arg1, Maybe<int64_t> arg2) {
if (arg2)
return randomSource.randInt(arg1, *arg2);
else
return randomSource.randInt(arg1);
});
methods.registerMethod("randUInt",
[](RandomSource& randomSource, uint64_t arg1, Maybe<uint64_t> arg2) {
if (arg2)
return randomSource.randUInt(arg1, *arg2);
else
return randomSource.randUInt(arg1);
});
return methods;
}
};
template <>
struct LuaConverter<PerlinF> : LuaUserDataConverter<PerlinF> {};
template <>
struct LuaUserDataMethods<PerlinF> {
static LuaMethods<PerlinF> make() {
LuaMethods<PerlinF> methods;
methods.registerMethod("get",
[](PerlinF& perlinF, float x, Maybe<float> y, Maybe<float> z) {
if (y && z)
return perlinF.get(x, *y, *z);
else if (y)
return perlinF.get(x, *y);
else
return perlinF.get(x);
});
return methods;
}
};
String LuaBindings::formatLua(String const& string, List<LuaValue> const& args) {
auto argsIt = args.begin();
auto argsEnd = args.end();
auto popArg = [&argsIt, &argsEnd]() -> LuaValue {
if (argsIt == argsEnd)
return LuaNil;
return *argsIt++;
};
auto stringIt = string.begin();
auto stringEnd = string.end();
String result;
while (stringIt != stringEnd) {
if (*stringIt == '%') {
auto next = stringIt;
++next;
if (next == stringEnd)
throw StarException("No specifier following '%'");
else if (*next == '%')
result += '%';
else if (*next == 's')
result += toString(popArg());
else
throw StarException::format("Improper lua log format specifier %%%c", *next);
++next;
stringIt = next;
} else {
result += *stringIt++;
}
}
return result;
}
LuaCallbacks LuaBindings::makeUtilityCallbacks() {
LuaCallbacks callbacks;
callbacks.registerCallback("nrand", UtilityCallbacks::nrand);
callbacks.registerCallback("makeUuid", UtilityCallbacks::makeUuid);
callbacks.registerCallback("logInfo", UtilityCallbacks::logInfo);
callbacks.registerCallback("logWarn", UtilityCallbacks::logWarn);
callbacks.registerCallback("logError", UtilityCallbacks::logError);
callbacks.registerCallback("setLogMap", UtilityCallbacks::setLogMap);
callbacks.registerCallback("printJson", UtilityCallbacks::printJson);
callbacks.registerCallback("print", UtilityCallbacks::print);
callbacks.registerCallback("interpolateSinEase", UtilityCallbacks::interpolateSinEase);
callbacks.registerCallback("replaceTags", UtilityCallbacks::replaceTags);
callbacks.registerCallback("jsonMerge", [](Json const& a, Json const& b) { return jsonMerge(a, b); });
callbacks.registerCallback("jsonQuery", [](Json const& json, String const& path, Json const& def) { return json.query(path, def); });
callbacks.registerCallback("makeRandomSource",
[](Maybe<uint64_t> seed) {
if (seed)
return RandomSource(*seed);
else
return RandomSource();
});
callbacks.registerCallback("makePerlinSource", [](Json const& config) { return PerlinF(config); });
auto hash64LuaValues = [](LuaVariadic<LuaValue> const& values) -> uint64_t {
XXHash64 hash;
for (auto const& value : values) {
if (auto b = value.ptr<LuaBoolean>())
xxHash64Push(hash, *b);
else if (auto i = value.ptr<LuaInt>())
xxHash64Push(hash, *i);
else if (auto f = value.ptr<LuaFloat>())
xxHash64Push(hash, *f);
else if (auto s = value.ptr<LuaString>())
xxHash64Push(hash, s->ptr());
else
throw LuaException("Unhashable lua type passed to staticRandomXX binding");
}
return hash.digest();
};
callbacks.registerCallback("staticRandomI32",
[hash64LuaValues](LuaVariadic<LuaValue> const& hashValues) { return (int32_t)hash64LuaValues(hashValues); });
callbacks.registerCallback("staticRandomI32Range",
[hash64LuaValues](int32_t min, int32_t max, LuaVariadic<LuaValue> const& hashValues) {
if (max < min)
throw LuaException("Maximum bound in staticRandomI32Range must be >= minimum bound!");
uint64_t denom = (uint64_t)(-1) / ((uint64_t)(max - min) + 1);
return (int32_t)(hash64LuaValues(hashValues) / denom + min);
});
callbacks.registerCallback("staticRandomDouble",
[hash64LuaValues](LuaVariadic<LuaValue> const& hashValues) {
return (hash64LuaValues(hashValues) & 0x7fffffffffffffff) / 9223372036854775808.0;
});
callbacks.registerCallback("staticRandomDoubleRange",
[hash64LuaValues](double min, double max, LuaVariadic<LuaValue> const& hashValues) {
if (max < min)
throw LuaException("Maximum bound in staticRandomDoubleRange must be >= minimum bound!");
return (hash64LuaValues(hashValues) & 0x7fffffffffffffff) / 9223372036854775808.0 * (max - min) + min;
});
return callbacks;
}
double LuaBindings::UtilityCallbacks::nrand(Maybe<double> const& stdev, Maybe<double> const& mean) {
return Random::nrandd(stdev.value(1.0), mean.value(0));
}
String LuaBindings::UtilityCallbacks::makeUuid() {
return Uuid().hex();
}
void LuaBindings::UtilityCallbacks::logInfo(String const& str, LuaVariadic<LuaValue> const& args) {
Logger::log(LogLevel::Info, formatLua(str, args).utf8Ptr());
}
void LuaBindings::UtilityCallbacks::logWarn(String const& str, LuaVariadic<LuaValue> const& args) {
Logger::log(LogLevel::Warn, formatLua(str, args).utf8Ptr());
}
void LuaBindings::UtilityCallbacks::logError(String const& str, LuaVariadic<LuaValue> const& args) {
Logger::log(LogLevel::Error, formatLua(str, args).utf8Ptr());
}
void LuaBindings::UtilityCallbacks::setLogMap(String const& key, String const& value, LuaVariadic<LuaValue> const& args) {
LogMap::set(key, formatLua(value, args));
}
String LuaBindings::UtilityCallbacks::printJson(Json const& arg, Maybe<int> pretty) {
return arg.repr(pretty.value());
}
String LuaBindings::UtilityCallbacks::print(LuaValue const& value) {
return toString(value);
}
LuaValue LuaBindings::UtilityCallbacks::interpolateSinEase(LuaEngine& engine, double offset, LuaValue const& value1, LuaValue const& value2) {
if (auto floatValue1 = engine.luaMaybeTo<double>(value1)) {
auto floatValue2 = engine.luaMaybeTo<double>(value2);
return sinEase(offset, *floatValue1, *floatValue2);
} else {
return engine.luaFrom<Vec2F>(sinEase(offset, engine.luaTo<Vec2F>(value1), engine.luaTo<Vec2F>(value2)));
}
}
String LuaBindings::UtilityCallbacks::replaceTags(String const& str, StringMap<String> const& tags) {
return str.replaceTags(tags);
}
}

View file

@ -0,0 +1,28 @@
#ifndef STAR_UTILITY_LUA_BINDINGS_HPP
#define STAR_UTILITY_LUA_BINDINGS_HPP
#include "StarLua.hpp"
namespace Star {
namespace LuaBindings {
LuaCallbacks makeUtilityCallbacks();
String formatLua(String const& string, List<LuaValue> const& args);
namespace UtilityCallbacks {
double nrand(Maybe<double> const& stdev, Maybe<double> const& mean);
String makeUuid();
void logInfo(String const& str, LuaVariadic<LuaValue> const& args);
void logWarn(String const& str, LuaVariadic<LuaValue> const& args);
void logError(String const& str, LuaVariadic<LuaValue> const& args);
void setLogMap(String const& key, String const& value, LuaVariadic<LuaValue> const& args);
String printJson(Json const& arg, Maybe<int> pretty);
String print(LuaValue const& arg);
LuaValue interpolateSinEase(LuaEngine& engine, double offset, LuaValue const& value1, LuaValue const& value2);
String replaceTags(String const& str, StringMap<String> const& tags);
}
}
}
#endif

File diff suppressed because it is too large Load diff

View file

@ -0,0 +1,182 @@
#ifndef STAR_LUA_BINDINGS_HPP
#define STAR_LUA_BINDINGS_HPP
#include "StarBiMap.hpp"
#include "StarRect.hpp"
#include "StarPoly.hpp"
#include "StarColor.hpp"
#include "StarGameTypes.hpp"
#include "StarCollisionBlock.hpp"
#include "StarLua.hpp"
#include "StarPlatformerAStar.hpp"
namespace Star {
STAR_CLASS(World);
STAR_CLASS(WorldServer);
STAR_CLASS(WorldClient);
STAR_CLASS(Item);
STAR_CLASS(ScriptedEntity);
namespace LuaBindings {
typedef function<Json(ScriptedEntityPtr const& entity, String const& functionName, JsonArray const& args)> CallEntityScriptFunction;
LuaCallbacks makeWorldCallbacks(World* world);
void addWorldDebugCallbacks(LuaCallbacks& callbacks);
void addWorldEntityCallbacks(LuaCallbacks& callbacks, World* world);
void addWorldEnvironmentCallbacks(LuaCallbacks& callbacks, World* world);
namespace WorldCallbacks {
float magnitude(World* world, Vec2F pos1, Maybe<Vec2F> pos2);
Vec2F distance(World* world, Vec2F const& arg1, Vec2F const& arg2);
bool polyContains(World* world, PolyF const& poly, Vec2F const& pos);
LuaValue xwrap(World* world, LuaEngine& engine, LuaValue const& positionOrX);
LuaValue nearestTo(World* world, LuaEngine& engine, Variant<Vec2F, float> const& sourcePositionOrX, Variant<Vec2F, float> const& targetPositionOrX);
bool rectCollision(World* world, RectF const& arg1, Maybe<CollisionSet> const& arg2);
bool pointTileCollision(World* world, Vec2F const& arg1, Maybe<CollisionSet> const& arg2);
bool lineTileCollision(World* world, Vec2F const& arg1, Vec2F const& arg2, Maybe<CollisionSet> const& arg3);
Maybe<pair<Vec2F, Vec2I>> lineTileCollisionPoint(World* world, Vec2F const& start, Vec2F const& end, Maybe<CollisionSet> const& maybeCollisionSet);
bool rectTileCollision(World* world, RectF const& arg1, Maybe<CollisionSet> const& arg2);
bool pointCollision(World* world, Vec2F const& point, Maybe<CollisionSet> const& collisionSet);
LuaTupleReturn<Maybe<Vec2F>, Maybe<Vec2F>> lineCollision(World* world, Vec2F const& start, Vec2F const& end, Maybe<CollisionSet> const& maybeCollisionSet);
bool polyCollision(World* world, PolyF const& arg1, Maybe<Vec2F> const& arg2, Maybe<CollisionSet> const& arg3);
List<Vec2I> collisionBlocksAlongLine(World* world, Vec2F const& arg1, Vec2F const& arg2, Maybe<CollisionSet> const& arg3, Maybe<int> const& arg4);
List<pair<Vec2I, LiquidLevel>> liquidAlongLine(World* world, Vec2F const& start, Vec2F const& end);
Maybe<Vec2F> resolvePolyCollision(World* world, PolyF poly, Vec2F const& position, float maximumCorrection, Maybe<CollisionSet> const& collisionSet);
bool tileIsOccupied(World* world, Vec2I const& arg1, Maybe<bool> const& arg2, Maybe<bool> const& arg3);
bool placeObject(World* world, String const& arg1, Vec2I const& arg2, Maybe<int> const& arg3, Json const& arg4);
Maybe<EntityId> spawnItem(World* world, Json const& itemType, Vec2F const& worldPosition, Maybe<size_t> const& inputCount, Json const& inputParameters, Maybe<Vec2F> const& initialVelocity, Maybe<float> const& intangibleTime);
List<EntityId> spawnTreasure(World* world, Vec2F const& position, String const& pool, float level, Maybe<uint64_t> seed);
Maybe<EntityId> spawnMonster(World* world, String const& arg1, Vec2F const& arg2, Maybe<JsonObject> const& arg3);
Maybe<EntityId> spawnNpc(World* world, Vec2F const& arg1, String const& arg2, String const& arg3, float arg4, Maybe<uint64_t> arg5, Json const& arg6);
Maybe<EntityId> spawnStagehand(World* world, Vec2F const& spawnPosition, String const& typeName, Json const& overrides);
Maybe<EntityId> spawnProjectile(World* world, String const& arg1, Vec2F const& arg2, Maybe<EntityId> const& arg3, Maybe<Vec2F> const& arg4, bool arg5, Json const& arg6);
Maybe<EntityId> spawnVehicle(World* world, String const& vehicleName, Vec2F const& pos, Json const& extraConfig);
double time(World* world);
uint64_t day(World* world);
double timeOfDay(World* world);
float dayLength(World* world);
Json getProperty(World* world, String const& arg1, Json const& arg2);
void setProperty(World* world, String const& arg1, Json const& arg2);
Maybe<LiquidLevel> liquidAt(World* world, Variant<RectF, Vec2I> boundBoxOrPoint);
float gravity(World* world, Vec2F const& arg1);
bool spawnLiquid(World* world, Vec2F const& arg1, LiquidId arg2, float arg3);
Maybe<LiquidLevel> destroyLiquid(World* world, Vec2F const& position);
bool isTileProtected(World* world, Vec2F const& position);
Maybe<PlatformerAStar::Path> findPlatformerPath(World* world, Vec2F const& start, Vec2F const& end, ActorMovementParameters actorMovementParameters, PlatformerAStar::Parameters searchParameters);
PlatformerAStar::PathFinder platformerPathStart(World* world, Vec2F const& start, Vec2F const& end, ActorMovementParameters actorMovementParameters, PlatformerAStar::Parameters searchParameters);
}
namespace ClientWorldCallbacks {
RectI clientWindow(WorldClient* world);
}
namespace ServerWorldCallbacks {
bool breakObject(WorldServer* world, EntityId arg1, bool arg2);
bool isVisibleToPlayer(WorldServer* world, RectF const& arg1);
bool loadRegion(WorldServer* world, RectF const& arg1);
bool regionActive(WorldServer* world, RectF const& arg1);
void setTileProtection(WorldServer* world, DungeonId arg1, bool arg2);
bool isPlayerModified(WorldServer* world, RectI const& region);
Maybe<LiquidLevel> forceDestroyLiquid(WorldServer* world, Vec2F const& position);
EntityId loadUniqueEntity(WorldServer* world, String const& uniqueId);
void setUniqueId(WorldServer* world, EntityId entityId, Maybe<String> const& uniqueId);
Json takeItemDrop(World* world, EntityId entityId, Maybe<EntityId> const& takenBy);
void setPlayerStart(World* world, Vec2F const& playerStart, Maybe<bool> respawnInWorld);
List<EntityId> players(World* world);
LuaString fidelity(World* world, LuaEngine& engine);
}
namespace WorldDebugCallbacks {
void debugPoint(Vec2F const& arg1, Color const& arg2);
void debugLine(Vec2F const& arg1, Vec2F const& arg2, Color const& arg3);
void debugPoly(PolyF const& poly, Color const& color);
void debugText(LuaEngine& engine, LuaVariadic<LuaValue> const& args);
}
namespace WorldEntityCallbacks {
LuaTable entityQuery(World* world, LuaEngine& engine, Vec2F const& pos1, LuaValue const& pos2, Maybe<LuaTable> options);
LuaTable monsterQuery(World* world, LuaEngine& engine, Vec2F const& pos1, LuaValue const& pos2, Maybe<LuaTable> options);
LuaTable npcQuery(World* world, LuaEngine& engine, Vec2F const& pos1, LuaValue const& pos2, Maybe<LuaTable> options);
LuaTable objectQuery(World* world, LuaEngine& engine, Vec2F const& pos1, LuaValue const& pos2, Maybe<LuaTable> options);
LuaTable itemDropQuery(World* world, LuaEngine& engine, Vec2F const& pos1, LuaValue const& pos2, Maybe<LuaTable> options);
LuaTable playerQuery(World* world, LuaEngine& engine, Vec2F const& pos1, LuaValue const& pos2, Maybe<LuaTable> options);
LuaTable loungeableQuery(World* world, LuaEngine& engine, Vec2F const& pos1, LuaValue const& pos2, Maybe<LuaTable> options);
LuaTable entityLineQuery(World* world, LuaEngine& engine, Vec2F const& pos1, Vec2F const& pos2, Maybe<LuaTable> options);
LuaTable objectLineQuery(World* world, LuaEngine& engine, Vec2F const& pos1, Vec2F const& pos2, Maybe<LuaTable> options);
LuaTable npcLineQuery(World* world, LuaEngine& engine, Vec2F const& pos1, Vec2F const& pos2, Maybe<LuaTable> options);
bool entityExists(World* world, EntityId entityId);
bool entityCanDamage(World* world, EntityId sourceId, EntityId targetId);
Json entityDamageTeam(World* world, EntityId entityId);
bool entityAggressive(World* world, EntityId entityId);
Maybe<LuaString> entityType(World* world, LuaEngine& engine, EntityId entityId);
Maybe<Vec2F> entityPosition(World* world, EntityId entityId);
Maybe<Vec2F> entityVelocity(World* world, EntityId entityId);
Maybe<RectF> entityMetaBoundBox(World* world, EntityId entityId);
Maybe<uint64_t> entityCurrency(World* world, EntityId entityId, String const& currencyType);
Maybe<uint64_t> entityHasCountOfItem(World* world, EntityId entityId, Json descriptor, Maybe<bool> exactMatch);
Maybe<Vec2F> entityHealth(World* world, EntityId entityId);
Maybe<String> entitySpecies(World* world, EntityId entityId);
Maybe<String> entityGender(World* world, EntityId entityId);
Maybe<String> entityName(World* world, EntityId entityId);
Maybe<String> entityDescription(World* world, EntityId entityId, Maybe<String> const& species);
Maybe<JsonArray> entityPortrait(World* world, EntityId entityId, String const& portraitMode);
Maybe<String> entityHandItem(World* world, EntityId entityId, String const& handName);
Json entityHandItemDescriptor(World* world, EntityId entityId, String const& handName);
Maybe<String> entityUniqueId(World* world, EntityId entityId);
Json getObjectParameter(World* world, EntityId entityId, String const& parameterName, Maybe<Json> const& defaultValue);
Json getNpcScriptParameter(World* world, EntityId entityId, String const& parameterName, Maybe<Json> const& defaultValue);
List<Vec2I> objectSpaces(World* world, EntityId entityId);
Maybe<int> farmableStage(World* world, EntityId entityId);
Maybe<int> containerSize(World* world, EntityId entityId);
bool containerClose(World* world, EntityId entityId);
bool containerOpen(World* world, EntityId entityId);
Json containerItems(World* world, EntityId entityId);
Json containerItemAt(World* world, EntityId entityId, size_t offset);
Maybe<bool> containerConsume(World* world, EntityId entityId, Json const& items);
Maybe<bool> containerConsumeAt(World* world, EntityId entityId, size_t offset, int count);
Maybe<size_t> containerAvailable(World* world, EntityId entityId, Json const& items);
Json containerTakeAll(World* world, EntityId entityId);
Json containerTakeAt(World* world, EntityId entityId, size_t offset);
Json containerTakeNumItemsAt(World* world, EntityId entityId, size_t offset, int const& count);
Maybe<size_t> containerItemsCanFit(World* world, EntityId entityId, Json const& items);
Json containerItemsFitWhere(World* world, EntityId entityId, Json const& items);
Json containerAddItems(World* world, EntityId entityId, Json const& items);
Json containerStackItems(World* world, EntityId entityId, Json const& items);
Json containerPutItemsAt(World* world, EntityId entityId, Json const& items, size_t offset);
Json containerSwapItems(World* world, EntityId entityId, Json const& items, size_t offset);
Json containerSwapItemsNoCombine(World* world, EntityId entityId, Json const& items, size_t offset);
Json containerItemApply(World* world, EntityId entityId, Json const& items, size_t offset);
Maybe<LuaValue> callScriptedEntity(World* world, EntityId entityId, String const& function, LuaVariadic<LuaValue> const& args);
RpcPromise<Vec2F> findUniqueEntity(World* world, String const& uniqueId);
RpcPromise<Json> sendEntityMessage(World* world, LuaEngine& engine, LuaValue entityId, String const& message, LuaVariadic<Json> args);
Maybe<bool> loungeableOccupied(World* world, EntityId entityId);
bool isMonster(World* world, EntityId entityId, Maybe<bool> const& aggressive);
Maybe<String> monsterType(World* world, EntityId entityId);
Maybe<String> npcType(World* world, EntityId entityId);
Maybe<String> stagehandType(World* world, EntityId entityId);
bool isNpc(World* world, EntityId entityId, Maybe<int> const& damageTeam);
}
namespace WorldEnvironmentCallbacks {
float lightLevel(World* world, Vec2F const& position);
float windLevel(World* world, Vec2F const& position);
bool breathable(World* world, Vec2F const& position);
bool underground(World* world, Vec2F const& position);
LuaValue material(World* world, LuaEngine& engine, Vec2F const& position, String const& layerName);
LuaValue mod(World* world, LuaEngine& engine, Vec2F const& position, String const& layerName);
float materialHueShift(World* world, Vec2F const& position, String const& layerName);
float modHueShift(World* world, Vec2F const& position, String const& layerName);
MaterialColorVariant materialColor(World* world, Vec2F const& position, String const& layerName);
void setMaterialColor(World* world, Vec2F const& position, String const& layerName, MaterialColorVariant color);
bool damageTiles(World* world, List<Vec2I> const& arg1, String const& arg2, Vec2F const& arg3, String const& arg4, float arg5, Maybe<unsigned> const& arg6, Maybe<EntityId> sourceEntity);
bool damageTileArea(World* world, Vec2F center, float radius, String layer, Vec2F sourcePosition, String damageType, float damage, Maybe<unsigned> const& harvestLevel, Maybe<EntityId> sourceEntity);
bool placeMaterial(World* world, Vec2I const& arg1, String const& arg2, String const& arg3, Maybe<int> const& arg4, bool arg5);
bool placeMod(World* world, Vec2I const& arg1, String const& arg2, String const& arg3, Maybe<int> const& arg4, bool arg5);
}
}
}
#endif