- Joined
- Jul 16, 2013
- Messages
- 43
- Reaction score
- 21
- First Language
- Greek
- Primarily Uses
- RMMV
Correct me if I'm wrong, but with a quick look at "Community_Basic" plugin, I think it's actually "var parameters = PluginManager.parameters(pluginname);
Then you can do parameters.parametername to get the individual values and do whatever you need to with them.
Note that all parameters are stored as strings regardless of type setting, so you need to parse them as numbers, eval booleans, or JSON.parse object arrays to use them properly.
parameters['parameter name']
", unless I'm missing something?You only need to do it that way if the parameter has a space in it. It can be accessed as a property otherwise.Correct me if I'm wrong, but with a quick look at "Community_Basic" plugin, I think it's actually "parameters['parameter name']
", unless I'm missing something?
parameters["parameter name"]
instead of parameters.parameterName
. The reason is, normally you should define your parameter like this:@param paramName
@text Parameter Name
parameters.paramName
// or
parameters["paramName"]
@param
and translate the @text
@text Parameter Name
). As a result, pretty much every plugin (mine included) is written in following style:@param Parameter Name
parameters["Parameter Name"]
["property name"]
is because their name includes characters that are not allowed for property/variable names. These characters include (but are not limited to):.
, ,
, ;
, :
, etc.)()
, []
, {}
, etc.)"
, '
, ´
)3d
)// Strings
const paramString = parameters["String parameter"] || "default value";
// if default value is not empty, but empty values are allowed
const paramString2 = parameters["String parameter"] === "" ? "" : (parameters["String parameter"] || "default value");
// Numbers
// defaults to 42
const paramNumber = Number(parameters["Number parameter"]) || 42;
// if default value is not 0, but 0 is allowed
const paramNumber2 = parameters["Number parameter"] === "0" ? 0 : (Number(parameters["Number parameter"]) || 42);
// Booleans
// defaults to true
const paramBool_trueDefault = parameters["Boolean parameter"]) !== "false";
// defaults to false
const paramBool_falseDefault = parameters["Boolean parameter"]) === "true";
Boolean()
function for boolean parameters. That's because both Boolean("true")
and Boolean("false")
both evaluate to true
@type actor
, @type switch
, @type variable
, @type common_event
, etc.) are basically numbers (they represent the ID of the object). Since you most likely won't be doing any mathematical operations on those, there's no real need to convert them to a number using the Number()
function. I'd still recommend doing it to avoid picking up bad habits, but the decision lies with you.@type file
is basically a string (the path to the file). @type select
can be a string or a number, depending on what you need (for booleans, just use a boolean instead). For numbers I'd recommend using @type number
with @min
and @max
instead of @type select
, unless you have a very strict and limited set of valid values.@type note
, arrays (e.g. @type number[]
), and structs (e.g. @type struct<customStruct>
) all require JSON.parse()
. If they are nested (e.g. an array of structs), you'll need multiple calls to JSON.parse()
.JSON.parse()
can crash if the input can not be parsed by JSON.parse()
. This means that you'll either need to trust that the user won't corrupt the parameter, or you'll need to wrap the parameter in try-catch:let paramNote;
try {
paramNote = JSON.parse(parameters["Note parameter"]);
} catch() {
paramNote = "default value";
}
JSON.parse("null")
gives us null
, which can cause the game to crash depending on the code). And since it's the plugin user's responsibility to avoid code injections, I wouldn't bother trying to sanitize parameters against that. Might as well not bother with try-catches either.const paramStructArray = parseStructArray(JSON.parse(parameters["Struct array parameter"]));
function parseStructArray(arr) {
return arr.map(function(struct) { return JSON.parse(struct); });
}
JSON.parse()
to get the array, and for each element in the array, you'd need another JSON.parse()
to get the struct object itself. Things get even more complex when your struct itself contains arrays or structs. I'm still figuring out if there isn't a better way to handle this case.I personally only useparameters["parameter name"]
instead ofparameters.parameterName
. The reason is, normally you should define your parameter like this:
and in your code you would access your parameter like this:Code:@param paramName @text Parameter Name
JavaScript:parameters.paramName // or parameters["paramName"]
Whoever uses your plugin will see "Parameter Name" instead of "paramName". This is particularly useful if you intend to translate your plugin, since you'd keep the@param
and translate the@text
But in reality, nobody does this (at least I've never seen a plugin that does), because it means writing an extra line of metadata (@text Parameter Name
). As a result, pretty much every plugin (mine included) is written in following style:
and accessed like this:Code:@param Parameter Name
JavaScript:parameters["Parameter Name"]
The reason why the parameters have to be retrieved using the dictionary indexer["property name"]
is because their name includes characters that are not allowed for property/variable names. These characters include (but are not limited to):
- whitespace
- any mathematical operator (+, -, *, /, etc.)
- any punctuation (
.
,,
,;
,:
, etc.)- any type of bracket (
()
,[]
,{}
, etc.)- any type of quote marks (
"
,'
,´
)- the name starts with a number (e.g.
3d
)
One (very important) thing to keep in mind: Plugin parameters are always stored as string.
At some point, you might create a plugin that expects a parameter that isn't a string (e.g. a boolean, a number, or even a custom structure). You might also want to have some default parameters, in case the user doesn't enter their own, or they somehow manage to corrupt the parameter.
Here's how to handle different types of parameters, including default values:
JavaScript:// Strings const paramString = parameters["String parameter"] || "default value"; // if default value is not empty, but empty values are allowed const paramString2 = parameters["String parameter"] === "" ? "" : (parameters["String parameter"] || "default value"); // Numbers // defaults to 42 const paramNumber = Number(parameters["Number parameter"]) || 42; // if default value is not 0, but 0 is allowed const paramNumber2 = parameters["Number parameter"] === "0" ? 0 : (Number(parameters["Number parameter"]) || 42); // Booleans // defaults to true const paramBool_trueDefault = parameters["Boolean parameter"]) !== "false"; // defaults to false const paramBool_falseDefault = parameters["Boolean parameter"]) === "true";
You've probably noticed how I didn't use theBoolean()
function for boolean parameters. That's because bothBoolean("true")
andBoolean("false")
both evaluate totrue
Object selector types (such as@type actor
,@type switch
,@type variable
,@type common_event
, etc.) are basically numbers (they represent the ID of the object). Since you most likely won't be doing any mathematical operations on those, there's no real need to convert them to a number using theNumber()
function. I'd still recommend doing it to avoid picking up bad habits, but the decision lies with you.
@type file
is basically a string (the path to the file).@type select
can be a string or a number, depending on what you need (for booleans, just use a boolean instead). For numbers I'd recommend using@type number
with@min
and@max
instead of@type select
, unless you have a very strict and limited set of valid values.
Finally,@type note
, arrays (e.g.@type number[]
), and structs (e.g.@type struct<customStruct>
) all requireJSON.parse()
. If they are nested (e.g. an array of structs), you'll need multiple calls toJSON.parse()
.
Note thatJSON.parse()
can crash if the input can not be parsed byJSON.parse()
. This means that you'll either need to trust that the user won't corrupt the parameter, or you'll need to wrap the parameter in try-catch:
Honestly, at this point sanitizing the input becomes a huge pain (for instance,JavaScript:let paramNote; try { paramNote = JSON.parse(parameters["Note parameter"]); } catch() { paramNote = "default value"; }
JSON.parse("null")
gives usnull
, which can cause the game to crash depending on the code). And since it's the plugin user's responsibility to avoid code injections, I wouldn't bother trying to sanitize parameters against that. Might as well not bother with try-catches either.
Arrays of structs might be worth mentioning:
You'll need the firstJavaScript:const paramStructArray = parseStructArray(JSON.parse(parameters["Struct array parameter"])); function parseStructArray(arr) { return arr.map(function(struct) { return JSON.parse(struct); }); }
JSON.parse()
to get the array, and for each element in the array, you'd need anotherJSON.parse()
to get the struct object itself. Things get even more complex when your struct itself contains arrays or structs. I'm still figuring out if there isn't a better way to handle this case.
But wouldn't the || operator return a boolean?// Strings
const paramString = parameters["String parameter"] || "default value";
// if default value is not empty, but empty values are allowed
const paramString2 = parameters["String parameter"] === "" ? "" : (parameters["String parameter"] || "default value");
But wouldn't the || operator return a boolean?
||
operator (boolean OR) returns what's on the left side if it's true, or the right side otherwise.Boolean("false")
even though you can do Number("13")
.false
(boolean)0
, -0
, 0.0
, -0.0
, 0b0
, 0o0
, 0x0
, 0n
, etc. (number)NaN
, -NaN
(number)""
, ''
, ``
(emtpy string)null
undefined
document.all
document.all
is a bit of a special case. It was originally introduced by IE (Internet Explorer), and later added to the official specs to prevent other browsers from breaking if they visited sites written for IE. if (document.all)
used to be a popular way to detect if the browser was IE, so browsers nowadays just consider document.all
to be falsey (except maybe for some versions of IE).Number(bla)
returns NaN
(because bla
wasn't a valid number), the ||
operator will allow us to fall back to a default. The same applies to strings, though only for empty strings.Boolean(x)
, it just tells you if x
is truthy or falsey. Since "false"
isn't an empty string, it's truthy, thus Boolean("false")
returns true
. It's confusing, but that's just how JavaScript is.