Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add possibility for pure Lua logic #80

Draft
wants to merge 2 commits into
base: master
Choose a base branch
from
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 6 additions & 0 deletions doc/PACKS.md
Original file line number Diff line number Diff line change
Expand Up @@ -329,6 +329,7 @@ Locations define drops on maps, rules to have them accessible as well as the loo
{
"name": "Area name",
"short_name": "Area", // shorter version of name. currently unused
"access_resolver": "$func", // optional method to resolve access. overrides access_rules
"access_rules": [
"<rule1>,<rule2>",
"<rule3>,<rule4>",
Expand Down Expand Up @@ -399,6 +400,11 @@ Locations define drops on maps, rules to have them accessible as well as the loo
Each `map_location` is a square on the map and shows a popup with individual chests.

**Rules:**
If access_resolver if provided or inherited for a section and starts with `$`, access_rules are ignored and the
provided global Lua function is called for each section instead of resolving access_rules. Useful for pure Lua logic.
The Lua function has to return one of AccessibilityLevel values.
If access_resolver is `""` (default), access_rules are resolved internally as described below.

Rules starting with `$` will call the lua function with that name, `@<location>/<section>` will use the result of a different access rule, other rules will just look at items' `code` (runs ProviderCountForCode(rule)).

For `$` rules, arguments can be supplied with `|`. `$test|a|b` will call `test("a","b")`.
Expand Down
8 changes: 8 additions & 0 deletions schema/packs/locations.json
Original file line number Diff line number Diff line change
Expand Up @@ -37,6 +37,10 @@
"description": "Short version of name. Currently unused.",
"type": "string"
},
"access_resolver": {
"description": "Optional method to resolve access. Use \"$func\" to call a Lua function with Section as argument that returns an AccessibilityLevel.",
"type": "string"
},
"access_rules": {
"example": [
"rule1,rule2",
Expand Down Expand Up @@ -146,6 +150,10 @@
"description": "Short version of name. Currently unused.",
"type": "string"
},
"access_resolver": {
"description": "Optional method to resolve access for each section. Use \"$func\" to call a Lua function with Section as argument that returns an AccessibilityLevel. This value is inherited by children, empty string resets to default behavior.",
"type": "string"
},
"access_rules": {
"example": [
"rule1,rule2",
Expand Down
8 changes: 8 additions & 0 deletions schema/packs/strict/locations.json
Original file line number Diff line number Diff line change
Expand Up @@ -36,6 +36,10 @@
"description": "Short version of name. Currently unused.",
"type": "string"
},
"access_resolver": {
"description": "Optional method to resolve access. Use \"$func\" to call a Lua function with Section as argument that returns an AccessibilityLevel.",
"type": "string"
},
"access_rules": {
"example": [
"rule1,rule2",
Expand Down Expand Up @@ -128,6 +132,10 @@
"description": "Short version of name. Currently unused.",
"type": "string"
},
"access_resolver": {
"description": "Optional method to resolve access for each section. Use \"$func\" to call a Lua function with Section as argument that returns an AccessibilityLevel. This value is inherited by children, empty string resets to default behavior.",
"type": "string"
},
"access_rules": {
"example": [
"rule1,rule2",
Expand Down
15 changes: 10 additions & 5 deletions src/core/location.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -113,14 +113,14 @@ static bool parseRule(const json& v, std::list<std::string>& rule,
}


std::list<Location> Location::FromJSON(json& j, const std::list<Location>& parentLookup, const std::list< std::list<std::string> >& prevAccessRules, const std::list< std::list<std::string> >& prevVisibilityRules, const std::string& parentName, const std::string& closedImgR, const std::string& openedImgR, const std::string& overlayBackgroundR)
std::list<Location> Location::FromJSON(json& j, const std::list<Location>& parentLookup, const std::string& prevAccessResolver, const std::list< std::list<std::string> >& prevAccessRules, const std::list< std::list<std::string> >& prevVisibilityRules, const std::string& parentName, const std::string& closedImgR, const std::string& openedImgR, const std::string& overlayBackgroundR)
{
// TODO: sine we store all intermediate locations now, we could pass a parent to FromJSON instead of all arguments
std::list<Location> locs;

if (j.type() == json::value_t::array) {
for (auto& v : j) {
for (auto& loc : FromJSON(v, parentLookup, prevAccessRules, prevVisibilityRules, parentName, closedImgR, openedImgR, overlayBackgroundR)) {
for (auto& loc : FromJSON(v, parentLookup, prevAccessResolver, prevAccessRules, prevVisibilityRules, parentName, closedImgR, openedImgR, overlayBackgroundR)) {
locs.push_back(std::move(loc)); // TODO: move constructor
}
}
Expand Down Expand Up @@ -159,9 +159,12 @@ std::list<Location> Location::FromJSON(json& j, const std::list<Location>& paren
}
}

const auto& parentAccesResolver = parentLocation ? parentLocation->getAccessResolver() : prevAccessResolver;
const auto& parentAccessRules = parentLocation ? parentLocation->getAccessRules() : prevAccessRules;
const auto& parentVisibilityRules = parentLocation ? parentLocation->getVisibilityRules() : prevVisibilityRules;

std::string accessResolver = to_string(j, "access_resolver", parentAccesResolver);

std::list< std::list<std::string> > accessRules;
if (j["access_rules"].is_array() && !j["access_rules"].empty()) {
// TODO: merge code with Section's access rules
Expand Down Expand Up @@ -220,6 +223,7 @@ std::list<Location> Location::FromJSON(json& j, const std::list<Location>& paren
loc._name = name;
loc._parentName = parentName;
loc._id = loc._parentName.empty() ? loc._name : (loc._parentName + "/" + loc._name);
loc._accessResolver = accessResolver;
loc._accessRules = accessRules;
loc._visibilityRules = visibilityRules;
if (j["map_locations"].is_array()) {
Expand All @@ -239,7 +243,7 @@ std::list<Location> Location::FromJSON(json& j, const std::list<Location>& paren
fprintf(stderr, "Location: bad section\n");
continue;
}
loc._sections.push_back(LocationSection::FromJSON(v, loc._id, accessRules, visibilityRules, closedImg, openedImg, overlayBackground));
loc._sections.push_back(LocationSection::FromJSON(v, loc._id, accessResolver, accessRules, visibilityRules, closedImg, openedImg, overlayBackground));
}
} else if (!j["sections"].is_null()) {
fprintf(stderr, "Location: invalid sections\n");
Expand All @@ -249,7 +253,7 @@ std::list<Location> Location::FromJSON(json& j, const std::list<Location>& paren

if (j["children"].type() == json::value_t::array) {
std::string fullname = parentName.empty() ? name : (parentName + "/" + name);
for (auto& loc : Location::FromJSON(j["children"], parentLookup, accessRules, visibilityRules, fullname, closedImg, openedImg, overlayBackground)) {
for (auto& loc : Location::FromJSON(j["children"], parentLookup, accessResolver, accessRules, visibilityRules, fullname, closedImg, openedImg, overlayBackground)) {
locs.push_back(std::move(loc));
}
} else if (j["children"].type() != json::value_t::null) {
Expand Down Expand Up @@ -300,7 +304,7 @@ Location::MapLocation Location::MapLocation::FromJSON(json& j)
}


LocationSection LocationSection::FromJSON(json& j, const std::string parentId, const std::list< std::list<std::string> >& parentAccessRules, const std::list< std::list<std::string> >& parentVisibilityRules, const std::string& closedImg, const std::string& openedImg, const std::string& overlayBackground)
LocationSection LocationSection::FromJSON(json& j, const std::string parentId, const std::string& parentAccessResolver, const std::list< std::list<std::string> >& parentAccessRules, const std::list< std::list<std::string> >& parentVisibilityRules, const std::string& closedImg, const std::string& openedImg, const std::string& overlayBackground)
{
// TODO: pass inherited values as parent instead
LocationSection sec;
Expand All @@ -316,6 +320,7 @@ LocationSection LocationSection::FromJSON(json& j, const std::string parentId, c
sec._itemCount = sec._hostedItems.empty() && sec._ref.empty() ? 1 : 0;
sec._itemCount = to_int(j["item_count"], sec._itemCount);
bool nonEmpty = sec._itemCount > 0 || !sec._hostedItems.empty();
sec._accessResolver = to_string(j, "access_resolver", parentAccessResolver);

if (j["access_rules"].is_array() && !j["access_rules"].empty()) {
// TODO: merge code with Location's access rules
Expand Down
6 changes: 6 additions & 0 deletions src/core/location.h
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,7 @@ class LocationSection final : public LuaInterface<LocationSection> {
public:
static LocationSection FromJSON(nlohmann::json& j,
const std::string parentId,
const std::string& parentAccessResolver="",
const std::list< std::list<std::string> >& parentAccessRules={},
const std::list< std::list<std::string> >& parentVisibilityRules={},
const std::string& closedImg="", const std::string& openedImg="",
Expand All @@ -37,13 +38,15 @@ class LocationSection final : public LuaInterface<LocationSection> {
int _itemCount=0;
int _itemCleared=0;
std::list<std::string> _hostedItems;
std::string _accessResolver;
std::list< std::list<std::string> > _accessRules;
std::list< std::list<std::string> > _visibilityRules;
std::string _overlayBackground;
std::string _ref; // path to actual section if it's just a reference
public:
// getters
const std::string& getName() const { return _name; }
const std::string& getAccessResolver() const { return _accessResolver; }
const std::list< std::list<std::string> > getAccessRules() const { return _accessRules; }
const std::list< std::list<std::string> > getVisibilityRules() const { return _visibilityRules; }
int getItemCount() const { return _itemCount; }
Expand Down Expand Up @@ -95,6 +98,7 @@ class Location final : public LuaInterface<Location> {

static std::list<Location> FromJSON(nlohmann::json& j,
const std::list<Location>& parentLookup,
const std::string& parentAccessResolver="",
const std::list< std::list<std::string> >& parentAccessRules={},
const std::list< std::list<std::string> >& parentVisibilityRules={},
const std::string& parentName="", const std::string& closedImg="",
Expand All @@ -106,6 +110,7 @@ class Location final : public LuaInterface<Location> {
std::string _id;
std::list<MapLocation> _mapLocations;
std::list<LocationSection> _sections;
std::string _accessResolver; // this is only used if referenced through @-RUles
std::list< std::list<std::string> > _accessRules; // this is only used if referenced through @-Rules
std::list< std::list<std::string> > _visibilityRules;
public:
Expand All @@ -115,6 +120,7 @@ class Location final : public LuaInterface<Location> {
const std::list<MapLocation>& getMapLocations() const { return _mapLocations; }
std::list<LocationSection>& getSections() { return _sections; }
const std::list<LocationSection>& getSections() const { return _sections; }
const std::string& getAccessResolver() const { return _accessResolver; }
std::list< std::list<std::string> >& getAccessRules() { return _accessRules; }
const std::list< std::list<std::string> >& getAccessRules() const { return _accessRules; }
std::list< std::list<std::string> >& getVisibilityRules() { return _visibilityRules; }
Expand Down