diff options
| author | KonAki <konaki@anokonaki.org> | 2026-10-16 07:11:26 +0800 |
|---|---|---|
| committer | KonAki <konaki@anokonaki.org> | 2026-10-16 07:11:26 +0800 |
| commit | 2292abb2d35fda99cc2d4cf8026c64e868d0a835 (patch) | |
| tree | 638f032caa4a6dde1b843de0a783b6d5756e7be2 | |
| parent | 1c1c2aa89920ffcf4d80a29c12a9999188adbaac (diff) | |
add rmplugin: plugin command table with a count of what is missing
| -rw-r--r-- | kon/konrmplugin.c | 98 | ||||
| -rw-r--r-- | kon/konrmplugin.h | 77 |
2 files changed, 175 insertions, 0 deletions
diff --git a/kon/konrmplugin.c b/kon/konrmplugin.c new file mode 100644 index 0000000..175afc1 --- /dev/null +++ b/kon/konrmplugin.c @@ -0,0 +1,98 @@ +/* SPDX-License-Identifier: MIT */ +/* + * konrmplugin.c + * + * Copyright (c) 2026 KonAki + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all + * copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + */ + +#include "konrmplugin.h" + +#include <string.h> + +/*** table ***/ + +void kon_rmPluginsInit(kon_rmPlugins_t *plugins, const kon_rmPluginEntry_t *entries, int count, void *user) +{ + if (!plugins) return; + memset(plugins, 0, sizeof *plugins); + plugins->entries = entries; + plugins->count = entries && count > 0 ? count : 0; + plugins->user = user; +} + +static void miss(kon_rmPlugins_t *plugins, const char *name) +{ + int i; + + plugins->missedTotal++; + for (i = 0; i < plugins->missedCount; i++) { + if (!strcmp(plugins->missed[i].name, name)) { + plugins->missed[i].count++; + return; + } + } + if (plugins->missedCount >= KON_RM_PLUGIN_MISSED) return; + strncpy(plugins->missed[plugins->missedCount].name, name, sizeof plugins->missed[0].name - 1); + plugins->missed[plugins->missedCount].count = 1; + plugins->missedCount++; +} + +/*** commands ***/ + +int kon_rmPluginHost(kon_rmPlugins_t *plugins, int code, const char *text) +{ + char buffer[1024]; + const char *argv[KON_RM_PLUGIN_ARGS]; + char sep = code == 357 ? '\t' : ' '; + int argc = 0, i; + char *s; + + if (!plugins || (code != 356 && code != 357)) return -1; + if (!text) text = ""; + strncpy(buffer, text, sizeof buffer - 1); + buffer[sizeof buffer - 1] = '\0'; + + /* MZ gives the plugin and then the command, they become plugin.command. the rest is split in place */ + if (code == 357 && (s = strchr(buffer, '\t')) != NULL) *s = '.'; + s = buffer; + while (argc < KON_RM_PLUGIN_ARGS) { + argv[argc++] = s; + while (*s && *s != sep) s++; + if (!*s) break; + *s++ = '\0'; + } + for (i = 0; i < plugins->count; i++) { + const kon_rmPluginEntry_t *e = &plugins->entries[i]; + + if (!e->name || strcmp(e->name, argv[0])) continue; + return e->fn ? e->fn(argc, argv, plugins->user) : 0; + } + miss(plugins, argv[0]); + return 0; +} + +int kon_rmPluginMissed(const kon_rmPlugins_t *plugins, int index, const char **name, int *count) +{ + if (!plugins || index < 0 || index >= plugins->missedCount) return 0; + if (name) *name = plugins->missed[index].name; + if (count) *count = plugins->missed[index].count; + return 1; +} diff --git a/kon/konrmplugin.h b/kon/konrmplugin.h new file mode 100644 index 0000000..4b0c3a3 --- /dev/null +++ b/kon/konrmplugin.h @@ -0,0 +1,77 @@ +/* SPDX-License-Identifier: MIT */ +/* + * konrmplugin.h + * + * Copyright (c) 2026 KonAki + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all + * copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + */ + +#ifndef KONRMPLUGIN_H +#define KONRMPLUGIN_H + +#include <stdint.h> + +#ifdef __cplusplus +extern "C" { +#endif + +/*** definition ***/ + +/* plugin commands of RPG Maker games (356 in MV, 357 in MZ), the way mzscript writes them. what a plugin does is its own JavaScript, + which is never run, so each command a game uses is something you answer yourself, by name. you hand over a table of names and + functions. a name with a NULL function is known and does nothing, for the ones that only dress up the original. a command that + is not in the table does nothing too, but is counted, so you can see what a game still needs */ + +#define KON_RM_PLUGIN_ARGS 16 +#define KON_RM_PLUGIN_MISSED 64 + +/* argv[0] is the command and argc counts it, the rest are what came after, apart by spaces in MV and by tabs in MZ (where the + command is the plugin, a dot, then the command). they are only good while the function runs. return 1 when the script is to wait */ +typedef int (*kon_rmPluginFn)(int argc, const char *const *argv, void *user); + +typedef struct kon_rmPluginEntry { + const char *name; + kon_rmPluginFn fn; +} kon_rmPluginEntry_t; + +typedef struct kon_rmPlugins { + const kon_rmPluginEntry_t *entries; + int count; + void *user; + struct { + char name[48]; + int count; + } missed[KON_RM_PLUGIN_MISSED]; + int missedCount; /* kinds written down in missed */ + int missedTotal; /* all of the commands that were not in the table */ +} kon_rmPlugins_t; + +void kon_rmPluginsInit(kon_rmPlugins_t *plugins, const kon_rmPluginEntry_t *entries, int count, void *user); + +/* returns -1 when the code is not 356 or 357, else what the command's function said, or 0 */ +int kon_rmPluginHost(kon_rmPlugins_t *plugins, int code, const char *text); + +/* the commands that were not in the table, in the order they first came, 1 and the name and how often, or 0 past the last */ +int kon_rmPluginMissed(const kon_rmPlugins_t *plugins, int index, const char **name, int *count); + +#ifdef __cplusplus +} +#endif +#endif |
