Commit 7e4dcb52 authored by nanahira's avatar nanahira

add registry api

parent ee1548f7
......@@ -15,6 +15,7 @@
#include <unordered_set>
#include <cstring>
#include <vector>
#include <unordered_map>
class card;
class group;
......@@ -38,6 +39,8 @@ public:
std::unordered_set<effect*> effects;
std::unordered_set<effect*> uncopy;
std::unordered_map<std::string, std::string> registry;
duel();
~duel();
void clear();
......
......@@ -228,6 +228,147 @@ int32_t scriptlib::duel_get_random_number(lua_State * L) {
lua_pushinteger(L, pduel->get_next_integer(min, max));
return 1;
}
int32_t scriptlib::duel_get_registry_value(lua_State* L) {
check_param_count(L, 1);
duel* pduel = interpreter::get_duel_info(L);
// 对参数 1 调用 tostring
lua_getglobal(L, "tostring");
lua_pushvalue(L, 1);
lua_call(L, 1, 1); // 调用 tostring(key)
const char* key = lua_tostring(L, -1);
if (!key) {
lua_pop(L, 1); // 清理 tostring 返回值
lua_pushnil(L); // 无效 key,返回 nil
return 1;
}
auto it = pduel->registry.find(key);
if (it != pduel->registry.end()) {
lua_pushstring(L, it->second.c_str());
} else {
lua_pushnil(L);
}
lua_remove(L, -2); // 移除 key 的 tostring 结果,保持栈只返回一个结果
return 1;
}
int32_t scriptlib::duel_set_registry_value(lua_State* L) {
check_param_count(L, 2);
duel* pduel = interpreter::get_duel_info(L);
// 对参数 1(key)调用 tostring
lua_getglobal(L, "tostring");
lua_pushvalue(L, 1);
lua_call(L, 1, 1); // 调用 tostring(key)
const char* key = lua_tostring(L, -1); // key 字符串结果在栈顶
if (!key) {
lua_pop(L, 1); // 清理 key tostring 结果
return luaL_error(L, "invalid key for registry");
}
if (lua_isnil(L, 2)) {
// 删除 key
pduel->registry.erase(key);
lua_pop(L, 1); // 清理 key
return 0;
}
// 对参数 2(value)调用 tostring
lua_getglobal(L, "tostring");
lua_pushvalue(L, 2);
lua_call(L, 1, 1); // 调用 tostring(value)
const char* value = lua_tostring(L, -1); // value 字符串在栈顶
if (value) {
pduel->registry[key] = value;
}
lua_pop(L, 2); // 清理 key 和 value 的 tostring 结果
return 0;
}
int32_t scriptlib::duel_get_registry_keys(lua_State* L) {
duel* pduel = interpreter::get_duel_info(L);
if (pduel->registry.empty()) {
lua_pushnil(L);
return 1;
}
int count = 0;
for (const auto& pair : pduel->registry) {
lua_pushstring(L, pair.first.c_str());
++count;
}
return count; // 返回 n 个字符串(key)
}
int32_t scriptlib::duel_get_registry(lua_State* L) {
duel* pduel = interpreter::get_duel_info(L);
lua_newtable(L); // 创建返回表
for (const auto& pair : pduel->registry) {
lua_pushstring(L, pair.first.c_str());
lua_pushstring(L, pair.second.c_str());
lua_settable(L, -3); // table[key] = value
}
return 1; // 返回这个 table
}
int32_t scriptlib::duel_set_registry(lua_State* L) {
check_param_count(L, 1); // 至少要 table 参数
if (!lua_istable(L, 1)) {
return luaL_error(L, "first argument must be a table");
}
bool override = false;
if (lua_gettop(L) >= 2 && lua_isboolean(L, 2)) {
override = lua_toboolean(L, 2);
}
duel* pduel = interpreter::get_duel_info(L);
if (override) {
pduel->registry.clear();
}
// 遍历 Lua 表
lua_pushnil(L); // 初始 key for lua_next
while (lua_next(L, 1)) {
// 栈: [-1]=value, [-2]=key
// 对 key 调用 tostring
lua_getglobal(L, "tostring");
lua_pushvalue(L, -3); // key
lua_call(L, 1, 1); // -> [tostring_key]
const char* kstr = lua_tostring(L, -1);
lua_remove(L, -1); // pop tostring_key
// 对 value 调用 tostring
lua_getglobal(L, "tostring");
lua_pushvalue(L, -2); // value
lua_call(L, 1, 1); // -> [tostring_value]
const char* vstr = lua_tostring(L, -1);
lua_remove(L, -1); // pop tostring_value
if (kstr && vstr) {
pduel->registry[kstr] = vstr;
}
lua_pop(L, 1); // 移除 value,保留 key 以继续迭代
}
return 0;
}
int32_t scriptlib::duel_clear_registry(lua_State *L) {
duel* pduel = interpreter::get_duel_info(L);
pduel->registry.clear();
return 0;
}
int32_t scriptlib::duel_enable_global_flag(lua_State *L) {
check_param_count(L, 1);
......@@ -5105,6 +5246,12 @@ static const struct luaL_Reg duellib[] = {
{ "ResetTimeLimit", scriptlib::duel_reset_time_limit },
{ "SetSummonCancelable", scriptlib::duel_set_summon_cancelable },
{ "GetRandomNumber", scriptlib::duel_get_random_number },
{ "GetRegistryValue", scriptlib::duel_get_registry_value },
{ "SetRegistryValue", scriptlib::duel_set_registry_value },
{ "GetRegistryKeys", scriptlib::duel_get_registry_keys },
{ "SetRegistry", scriptlib::duel_set_registry },
{ "GetRegistry", scriptlib::duel_get_registry },
{ "ClearRegistry", scriptlib::duel_clear_registry },
{ "EnableGlobalFlag", scriptlib::duel_enable_global_flag },
{ "GetLP", scriptlib::duel_get_lp },
......
......@@ -370,3 +370,102 @@ OCGCORE_API void set_responseb(intptr_t pduel, byte* buf) {
OCGCORE_API int32_t preload_script(intptr_t pduel, const char* script_name) {
return ((duel*)pduel)->lua->load_script(script_name);
}
OCGCORE_API int32_t get_registry_value(intptr_t pduel, const char* key, byte* out_buf) {
if (!pduel || !key || !out_buf) return -1;
duel* d = (duel*)pduel;
auto it = d->registry.find(key);
if (it == d->registry.end())
return -1;
const std::string& val = it->second;
std::memcpy(out_buf, val.c_str(), val.size());
return static_cast<int32_t>(val.size());
}
OCGCORE_API void set_registry_value(intptr_t pduel, const char* key, const char* value) {
if (!pduel || !key) return;
duel* d = (duel*)pduel;
if (value) {
d->registry[key] = value;
} else {
d->registry.erase(key);
}
}
OCGCORE_API int32_t get_registry_keys(intptr_t pduel, byte* out_buf) {
if (!pduel || !out_buf) return -1;
duel* d = (duel*)pduel;
byte* ptr = out_buf;
for (const auto& pair : d->registry) {
const std::string& key = pair.first;
uint16_t len = static_cast<uint16_t>(std::min<size_t>(key.size(), 0xFFFF));
// 写入长度(2字节,小端序)
buffer_write(ptr, len);
std::memcpy(ptr, key.data(), len);
ptr += len;
}
return ptr - out_buf;
}
OCGCORE_API void clear_registry(intptr_t pduel) {
if (!pduel) return;
duel* d = (duel*)pduel;
d->registry.clear();
}
OCGCORE_API int32_t dump_registry(intptr_t pduel, byte* out_buf) {
if (!pduel || !out_buf) return -1;
duel* d = (duel*)pduel;
byte* ptr = out_buf;
for (const auto& pair : d->registry) {
const std::string& key = pair.first;
const std::string& value = pair.second;
uint16_t key_len = static_cast<uint16_t>(std::min<size_t>(key.size(), 0xFFFF));
uint16_t val_len = static_cast<uint16_t>(std::min<size_t>(value.size(), 0xFFFF));
// 写入 key_len 和 val_len(每次调用后 ptr 自动推进)
buffer_write(ptr, key_len);
buffer_write(ptr, val_len);
// 写入 key 内容
std::memcpy(ptr, key.data(), key_len);
ptr += key_len;
// 写入 value 内容
std::memcpy(ptr, value.data(), val_len);
ptr += val_len;
}
return ptr - out_buf; // 返回写入的总字节数
}
OCGCORE_API void load_registry(intptr_t pduel, const byte* in_buf, int32_t in_len) {
if (!pduel || !in_buf || in_len <= 0) return;
duel* d = (duel*)pduel;
byte* ptr = const_cast<byte*>(in_buf); // buffer_read 要求非 const
byte* end = ptr + in_len;
while (ptr + 4 <= end) { // 至少要读取 key_len 和 val_len(2 + 2 字节)
uint16_t key_len = buffer_read<uint16_t>(ptr);
uint16_t val_len = buffer_read<uint16_t>(ptr);
if (ptr + key_len + val_len > end) {
break; // 数据不完整,退出
}
std::string key(reinterpret_cast<const char*>(ptr), key_len);
ptr += key_len;
std::string value(reinterpret_cast<const char*>(ptr), val_len);
ptr += val_len;
d->registry[std::move(key)] = std::move(value);
}
}
......@@ -64,4 +64,12 @@ OCGCORE_API void set_responseb(intptr_t pduel, byte* buf);
OCGCORE_API int32_t preload_script(intptr_t pduel, const char* script_name);
OCGCORE_API byte* default_script_reader(const char* script_name, int* len);
// koishi specific
OCGCORE_API int32_t get_registry_value(intptr_t pduel, const char* key, byte* out_buf);
OCGCORE_API void set_registry_value(intptr_t pduel, const char* key, const char* value);
OCGCORE_API int32_t get_registry_keys(intptr_t pduel, byte* out_buf);
OCGCORE_API void clear_registry(intptr_t pduel);
OCGCORE_API int32_t dump_registry(intptr_t pduel, byte* out_buf);
OCGCORE_API void load_registry(intptr_t pduel, const byte* in_buf, int32_t in_len);
#endif /* OCGAPI_H_ */
......@@ -51,6 +51,12 @@ public:
static int32_t duel_reset_time_limit(lua_State *L);
static int32_t duel_set_summon_cancelable(lua_State *L);
static int32_t duel_get_random_number(lua_State *L);
static int32_t duel_get_registry_value(lua_State *L);
static int32_t duel_set_registry_value(lua_State *L);
static int32_t duel_get_registry_keys(lua_State *L);
static int32_t duel_set_registry(lua_State *L);
static int32_t duel_get_registry(lua_State *L);
static int32_t duel_clear_registry(lua_State *L);
//card lib
static int32_t card_get_code(lua_State *L);
static int32_t card_get_origin_code(lua_State *L);
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment