mirror of
https://github.com/Dingo-Shenanigans/ReSkate.git
synced 2026-10-24 05:26:13 +02:00
Plugins: prop hunt APIs, and plugin commands in the console lookup
- reskate.entities.blueprints lists the game's object blueprints (meshes only if asked), and reskate.entities.bounds gives a blueprint's box, so a mod can pick a prop by list or at random - Attached objects take upright, turn and ground (a floor found within reach below), the "root" joint, and a 6th options argument with solid; spawned props' bodies are found and ghosted - reskate.skater.hide, reskate.world.pick, and skater.get gives right and switch - reskate.console.command takes an optional 4th table of subcommands; the console lookup suggests plugin commands word by word, and plugin commands lists the subcommands - objbody: a test command for finding which body setter takes a prop out of collision
This commit is contained in:
1 parent
c35e9a357b
commit
45346b122c
26 files changed
+1238
-36
No files matched your search
@@ -412,8 +412,36 @@ struct ApiFunctions {
|
||||
if (plugin.commands_.contains(name)) luaL_error(L, "the command \"%s\" is registered already", name.c_str());
|
||||
if (const auto refusal = plugin.services_.claim_command(plugin.id(), name); !refusal.empty())
|
||||
luaL_error(L, "%s", refusal.c_str());
|
||||
// subcommands = {{name = "random", args = "[start]", help = "..."}, ...}: what the console's
|
||||
// lookup and `plugin commands` show after the name. The function still runs them all.
|
||||
std::vector<Plugin::Subcommand> subcommands;
|
||||
if (!lua_isnoneornil(L, 4)) {
|
||||
luaL_checktype(L, 4, LUA_TTABLE);
|
||||
const int count = static_cast<int>(lua_objlen(L, 4));
|
||||
if (count > 32) luaL_error(L, "at most 32 subcommands");
|
||||
for (int i = 1; i <= count; ++i) {
|
||||
lua_rawgeti(L, 4, i);
|
||||
if (!lua_istable(L, -1)) luaL_error(L, "subcommand %d is not a table {name = ..., args = ..., help = ...}", i);
|
||||
Plugin::Subcommand sub;
|
||||
const auto field = [&](const char* key, std::size_t most) {
|
||||
lua_getfield(L, -1, key);
|
||||
std::string value = lua_isnil(L, -1) ? std::string{} : std::string(luaL_checkstring(L, -1));
|
||||
lua_pop(L, 1);
|
||||
if (value.size() > most) luaL_error(L, "a subcommand's %s is at most %d characters", key, static_cast<int>(most));
|
||||
return value;
|
||||
};
|
||||
sub.name = field("name", maximum_command);
|
||||
sub.args = field("args", 80);
|
||||
sub.help = field("help", 200);
|
||||
bool word = !sub.name.empty();
|
||||
for (const char c : sub.name) word = word && ((c >= 'a' && c <= 'z') || (c >= '0' && c <= '9') || c == '_' || c == '-');
|
||||
if (!word) luaL_error(L, "subcommand %d's name is not one lowercase word of a-z, 0-9, _ and -", i);
|
||||
subcommands.push_back(std::move(sub));
|
||||
lua_pop(L, 1);
|
||||
}
|
||||
}
|
||||
lua_pushvalue(L, 3);
|
||||
plugin.commands_[name] = {help.substr(0, 200), lua_ref(L, -1)};
|
||||
plugin.commands_[name] = {help.substr(0, 200), lua_ref(L, -1), std::move(subcommands)};
|
||||
lua_pop(L, 1);
|
||||
return 0;
|
||||
}
|
||||
|
||||
Reference in new issue
Block a user