Commit 25a635c0 authored by nanahira's avatar nanahira

add metadata methods

parent c06a0867
......@@ -12,6 +12,7 @@
#include "effectset.h"
#include "card_data.h"
#include "sort.h"
#include "metadata.h"
#include <set>
#include <map>
#include <unordered_set>
......@@ -146,6 +147,7 @@ public:
int32_t ref_handle{};
duel* pduel{};
metadata meta;
card_data data;
card_state previous;
card_state temp;
......
......@@ -16,6 +16,17 @@ inline bool check_playerid(int32_t playerid) {
return playerid >= 0 && playerid <= 1;
}
enum LuaParamType : int32_t {
PARAM_TYPE_INT = 0x01,
PARAM_TYPE_STRING = 0x02,
PARAM_TYPE_CARD = 0x04,
PARAM_TYPE_GROUP = 0x08,
PARAM_TYPE_EFFECT = 0x10,
PARAM_TYPE_FUNCTION = 0x20,
PARAM_TYPE_BOOLEAN = 0x40,
PARAM_TYPE_INDEX = 0x80,
};
#define MATCH_ALL(x,y) (((x)&(y))==(y))
#define MATCH_ANY(x,y) ((x)&(y))
#define ADD_BIT(x,y) ((x)|=(y))
......
......@@ -11,6 +11,7 @@
#include "common.h"
#include "sort.h"
#include "mtrandom.h"
#include "metadata.h"
#include <set>
#include <unordered_set>
#include <vector>
......@@ -30,6 +31,7 @@ public:
interpreter* lua;
field* game_field;
mtrandom random;
metadata meta;
std::vector<byte> message_buffer;
std::unordered_set<card*> cards;
......
......@@ -11,6 +11,7 @@
#include "common.h"
#include "field.h"
#include "effectset.h"
#include "metadata.h"
#include <vector>
class card;
......@@ -65,6 +66,7 @@ public:
uint8_t cost_checked{ FALSE };
effect_set required_handorset_effects;
LuaParamType object_type{ PARAM_TYPE_INT };
metadata meta;
explicit effect(duel* pd);
~effect() = default;
......
......@@ -72,6 +72,7 @@ struct chain {
opmap opinfos;
uint32_t flag{ 0 };
effect_set required_handorset_effects;
metadata meta;
static bool chain_operation_sort(const chain& c1, const chain& c2);
void set_triggering_state(card* pcard);
......
......@@ -10,6 +10,7 @@
#include "common.h"
#include "sort.h"
#include "metadata.h"
#include <set>
#include <list>
......@@ -27,6 +28,7 @@ public:
int32_t ref_handle{ 0 };
uint32_t is_readonly{ GTYPE_DEFAULT };
duel* pduel;
metadata meta;
card_set container;
card_set::iterator it;
bool is_iterator_dirty{ true };
......
......@@ -23,17 +23,6 @@ class effect;
class group;
class duel;
enum LuaParamType : int32_t {
PARAM_TYPE_INT = 0x01,
PARAM_TYPE_STRING = 0x02,
PARAM_TYPE_CARD = 0x04,
PARAM_TYPE_GROUP = 0x08,
PARAM_TYPE_EFFECT = 0x10,
PARAM_TYPE_FUNCTION = 0x20,
PARAM_TYPE_BOOLEAN = 0x40,
PARAM_TYPE_INDEX = 0x80,
};
class interpreter {
public:
union lua_param {
......
......@@ -3418,6 +3418,36 @@ int32_t scriptlib::card_set_spsummon_once(lua_State *L) {
pcard->pduel->game_field->core.global_flag |= GLOBALFLAG_SPSUMMON_ONCE;
return 0;
}
int32_t scriptlib::card_get_meta_value(lua_State *L) {
check_param_count(L, 2);
check_param(L, PARAM_TYPE_CARD, 1);
card* pcard = *(card**) lua_touserdata(L, 1);
return pcard->meta.luaop_get(L, 1);
}
int32_t scriptlib::card_set_meta_value(lua_State *L) {
check_param_count(L, 3);
check_param(L, PARAM_TYPE_CARD, 1);
card* pcard = *(card**) lua_touserdata(L, 1);
return pcard->meta.luaop_set(L, 1);
}
int32_t scriptlib::card_has_meta_value(lua_State *L) {
check_param_count(L, 2);
check_param(L, PARAM_TYPE_CARD, 1);
card* pcard = *(card**) lua_touserdata(L, 1);
return pcard->meta.luaop_has(L, 1);
}
int32_t scriptlib::card_get_meta_keys(lua_State *L) {
check_param_count(L, 1);
check_param(L, PARAM_TYPE_CARD, 1);
card* pcard = *(card**) lua_touserdata(L, 1);
return pcard->meta.luaop_keys(L);
}
int32_t scriptlib::card_clear_meta(lua_State *L) {
check_param_count(L, 1);
check_param(L, PARAM_TYPE_CARD, 1);
card* pcard = *(card**) lua_touserdata(L, 1);
return pcard->meta.luaop_clear();
}
static const struct luaL_Reg cardlib[] = {
{ "GetCode", scriptlib::card_get_code },
......@@ -3696,6 +3726,11 @@ static const struct luaL_Reg cardlib[] = {
{ "ResetNegateEffect", scriptlib::card_reset_negate_effect },
{ "AssumeProperty", scriptlib::card_assume_prop },
{ "SetSPSummonOnce", scriptlib::card_set_spsummon_once },
{ "GetMetaValue", scriptlib::card_get_meta_value },
{ "SetMetaValue", scriptlib::card_set_meta_value },
{ "HasMetaValue", scriptlib::card_has_meta_value },
{ "ClearMeta", scriptlib::card_clear_meta },
{ "GetMetaKeys", scriptlib::card_get_meta_keys },
{ nullptr, nullptr }
};
void scriptlib::open_cardlib(lua_State *L) {
......
......@@ -4841,6 +4841,86 @@ int32_t scriptlib::duel_majestic_copy(lua_State *L) {
}
return 0;
}
int32_t scriptlib::duel_get_meta_value(lua_State *L) {
auto pduel = interpreter::get_duel_info(L);
return pduel->meta.luaop_get(L);
}
int32_t scriptlib::duel_set_meta_value(lua_State *L) {
auto pduel = interpreter::get_duel_info(L);
return pduel->meta.luaop_set(L);
}
int32_t scriptlib::duel_has_meta_value(lua_State *L) {
auto pduel = interpreter::get_duel_info(L);
return pduel->meta.luaop_has(L);
}
int32_t scriptlib::duel_get_meta_keys(lua_State *L) {
auto pduel = interpreter::get_duel_info(L);
return pduel->meta.luaop_keys(L);
}
int32_t scriptlib::duel_clear_meta(lua_State *L) {
auto pduel = interpreter::get_duel_info(L);
return pduel->meta.luaop_clear();
}
int32_t scriptlib::duel_get_chain_meta_value(lua_State *L) {
check_param_count(L, 2);
check_param(L, PARAM_TYPE_INT, 1);
auto pduel = interpreter::get_duel_info(L);
auto c = (uint32_t)lua_tointeger(L, 1);
auto ch = pduel->game_field->get_chain(c);
if(!ch) {
lua_pushnil(L);
return 1;
}
return ch->meta.luaop_get(L, 1);
}
int32_t scriptlib::duel_set_chain_meta_value(lua_State *L) {
check_param_count(L, 3);
check_param(L, PARAM_TYPE_INT, 1);
auto pduel = interpreter::get_duel_info(L);
auto c = (uint32_t)lua_tointeger(L, 1);
auto ch = pduel->game_field->get_chain(c);
if(!ch) {
lua_pushnil(L);
return 1;
}
return ch->meta.luaop_set(L, 1);
}
int32_t scriptlib::duel_has_chain_meta_value(lua_State *L) {
check_param_count(L, 2);
check_param(L, PARAM_TYPE_INT, 1);
auto pduel = interpreter::get_duel_info(L);
auto c = (uint32_t)lua_tointeger(L, 1);
auto ch = pduel->game_field->get_chain(c);
if(!ch) {
lua_pushnil(L);
return 1;
}
return ch->meta.luaop_has(L, 1);
}
int32_t scriptlib::duel_get_chain_meta_keys(lua_State *L) {
check_param_count(L, 1);
check_param(L, PARAM_TYPE_INT, 1);
auto pduel = interpreter::get_duel_info(L);
auto c = (uint32_t)lua_tointeger(L, 1);
auto ch = pduel->game_field->get_chain(c);
if(!ch) {
lua_pushnil(L);
return 1;
}
return ch->meta.luaop_keys(L);
}
int32_t scriptlib::duel_clear_chain_meta(lua_State *L) {
check_param_count(L, 1);
check_param(L, PARAM_TYPE_INT, 1);
auto pduel = interpreter::get_duel_info(L);
auto c = (uint32_t)lua_tointeger(L, 1);
auto ch = pduel->game_field->get_chain(c);
if(!ch) {
lua_pushnil(L);
return 1;
}
return ch->meta.luaop_clear();
}
static const struct luaL_Reg duellib[] = {
{ "EnableGlobalFlag", scriptlib::duel_enable_global_flag },
......@@ -5072,6 +5152,16 @@ static const struct luaL_Reg duellib[] = {
{ "IsAbleToEnterBP", scriptlib::duel_is_able_to_enter_bp },
{ "SwapDeckAndGrave", scriptlib::duel_swap_deck_and_grave },
{ "MajesticCopy", scriptlib::duel_majestic_copy },
{ "GetMetaValue", scriptlib::duel_get_meta_value },
{ "SetMetaValue", scriptlib::duel_set_meta_value },
{ "HasMetaValue", scriptlib::duel_has_meta_value },
{ "ClearMeta", scriptlib::duel_clear_meta },
{ "GetMetaKeys", scriptlib::duel_get_meta_keys },
{ "GetChainMetaValue", scriptlib::duel_get_chain_meta_value },
{ "SetChainMetaValue", scriptlib::duel_set_chain_meta_value },
{ "HasChainMetaValue", scriptlib::duel_has_chain_meta_value },
{ "ClearChainMeta", scriptlib::duel_clear_chain_meta },
{ "GetChainMetaKeys", scriptlib::duel_get_chain_meta_keys },
{ nullptr, nullptr }
};
void scriptlib::open_duellib(lua_State *L) {
......
......@@ -602,6 +602,36 @@ int32_t scriptlib::effect_use_count_limit(lua_State *L) {
}
return 0;
}
int32_t scriptlib::effect_get_meta_value(lua_State *L) {
check_param_count(L, 2);
check_param(L, PARAM_TYPE_EFFECT, 1);
effect* peffect = *(effect**) lua_touserdata(L, 1);
return peffect->meta.luaop_get(L, 1);
}
int32_t scriptlib::effect_set_meta_value(lua_State *L) {
check_param_count(L, 3);
check_param(L, PARAM_TYPE_EFFECT, 1);
effect* peffect = *(effect**) lua_touserdata(L, 1);
return peffect->meta.luaop_set(L, 1);
}
int32_t scriptlib::effect_has_meta_value(lua_State *L) {
check_param_count(L, 2);
check_param(L, PARAM_TYPE_EFFECT, 1);
effect* peffect = *(effect**) lua_touserdata(L, 1);
return peffect->meta.luaop_has(L, 1);
}
int32_t scriptlib::effect_get_meta_keys(lua_State *L) {
check_param_count(L, 1);
check_param(L, PARAM_TYPE_EFFECT, 1);
effect* peffect = *(effect**) lua_touserdata(L, 1);
return peffect->meta.luaop_keys(L);
}
int32_t scriptlib::effect_clear_meta(lua_State *L) {
check_param_count(L, 1);
check_param(L, PARAM_TYPE_EFFECT, 1);
effect* peffect = *(effect**) lua_touserdata(L, 1);
return peffect->meta.luaop_clear();
}
static const struct luaL_Reg effectlib[] = {
{ "CreateEffect", scriptlib::effect_new },
......@@ -659,6 +689,11 @@ static const struct luaL_Reg effectlib[] = {
{ "GetActivateSequence", scriptlib::effect_get_activate_sequence },
{ "CheckCountLimit", scriptlib::effect_check_count_limit },
{ "UseCountLimit", scriptlib::effect_use_count_limit },
{ "GetMetaValue", scriptlib::effect_get_meta_value },
{ "SetMetaValue", scriptlib::effect_set_meta_value },
{ "HasMetaValue", scriptlib::effect_has_meta_value },
{ "ClearMeta", scriptlib::effect_clear_meta },
{ "GetMetaKeys", scriptlib::effect_get_meta_keys },
{ nullptr, nullptr }
};
void scriptlib::open_effectlib(lua_State *L) {
......
......@@ -777,6 +777,36 @@ int32_t scriptlib::group_get_bin_class_count(lua_State *L) {
lua_pushinteger(L, ans);
return 1;
}
int32_t scriptlib::group_get_meta_value(lua_State *L) {
check_param_count(L, 2);
check_param(L, PARAM_TYPE_GROUP, 1);
group* pgroup = *(group**) lua_touserdata(L, 1);
return pgroup->meta.luaop_get(L, 1);
}
int32_t scriptlib::group_set_meta_value(lua_State *L) {
check_param_count(L, 3);
check_param(L, PARAM_TYPE_GROUP, 1);
group* pgroup = *(group**) lua_touserdata(L, 1);
return pgroup->meta.luaop_set(L, 1);
}
int32_t scriptlib::group_has_meta_value(lua_State *L) {
check_param_count(L, 2);
check_param(L, PARAM_TYPE_GROUP, 1);
group* pgroup = *(group**) lua_touserdata(L, 1);
return pgroup->meta.luaop_has(L, 1);
}
int32_t scriptlib::group_get_meta_keys(lua_State *L) {
check_param_count(L, 1);
check_param(L, PARAM_TYPE_GROUP, 1);
group* pgroup = *(group**) lua_touserdata(L, 1);
return pgroup->meta.luaop_keys(L);
}
int32_t scriptlib::group_clear_meta(lua_State *L) {
check_param_count(L, 1);
check_param(L, PARAM_TYPE_GROUP, 1);
group* pgroup = *(group**) lua_touserdata(L, 1);
return pgroup->meta.luaop_clear();
}
int32_t scriptlib::group_meta_add(lua_State* L) {
check_param_count(L, 2);
if(!check_param(L, PARAM_TYPE_CARD, 1, TRUE) && !check_param(L, PARAM_TYPE_GROUP, 1, TRUE))
......@@ -931,6 +961,11 @@ static const struct luaL_Reg grouplib[] = {
{ "IsContains", scriptlib::group_is_contains },
{ "SearchCard", scriptlib::group_search_card },
{ "GetBinClassCount", scriptlib::group_get_bin_class_count },
{ "GetMetaValue", scriptlib::group_get_meta_value },
{ "SetMetaValue", scriptlib::group_set_meta_value },
{ "HasMetaValue", scriptlib::group_has_meta_value },
{ "ClearMeta", scriptlib::group_clear_meta },
{ "GetMetaKeys", scriptlib::group_get_meta_keys },
{ "__add", scriptlib::group_meta_add },
{ "__bor", scriptlib::group_meta_add },
{ "__sub", scriptlib::group_meta_sub },
......
#include "metadata.h"
#include "interpreter.h"
#include "scriptlib.h"
#include <cstring>
metadata_entry::metadata_entry() {
type = PARAM_TYPE_INT;
value = 0;
}
metadata_entry::~metadata_entry() {
reset();
}
metadata_entry::metadata_entry(metadata_entry&& other) noexcept {
type = other.type;
value = other.value;
other.type = PARAM_TYPE_INT;
other.value = 0;
}
metadata_entry& metadata_entry::operator=(metadata_entry&& other) noexcept {
if (this != &other) {
reset();
type = other.type;
value = other.value;
other.type = PARAM_TYPE_INT;
other.value = 0;
}
return *this;
}
int32_t metadata_entry::luaop_get(lua_State *L) {
if (type == PARAM_TYPE_INT) {
lua_pushinteger(L, static_cast<int32_t>(value));
return 1;
}
if (type == PARAM_TYPE_INDEX) {
lua_pushnumber(L, *reinterpret_cast<double*>(value));
return 1;
}
if (type == PARAM_TYPE_STRING) {
lua_pushstring(L, reinterpret_cast<const char*>(value));
return 1;
}
if (type == PARAM_TYPE_BOOLEAN) {
lua_pushboolean(L, value != 0);
return 1;
}
if (type == PARAM_TYPE_CARD) {
interpreter::card2value(L, reinterpret_cast<card*>(value));
return 1;
}
if (type == PARAM_TYPE_GROUP) {
interpreter::group2value(L, reinterpret_cast<group*>(value));
return 1;
}
if (type == PARAM_TYPE_EFFECT) {
interpreter::effect2value(L, reinterpret_cast<effect*>(value));
return 1;
}
if (type == PARAM_TYPE_FUNCTION) {
interpreter::function2value(L, value);
return 1;
}
lua_pushnil(L);
return 1;
}
int32_t metadata_entry::luaop_set(lua_State *L, int32_t index) {
reset();
if (lua_isnil(L, index)) {
// should never reach here because nil would remove the entry
value = 0;
type = PARAM_TYPE_INT;
return 0;
}
if (lua_isboolean(L, index)) {
value = lua_toboolean(L, index);
type = PARAM_TYPE_BOOLEAN;
return 0;
}
if (lua_isinteger(L, index)) {
value = lua_tointeger(L, index);
type = PARAM_TYPE_INT;
return 0;
}
if (lua_isnumber(L, index)) {
auto num = lua_tonumber(L, index);
auto saved_num = new double(num);
value = reinterpret_cast<intptr_t>(saved_num);
type = PARAM_TYPE_INDEX;
return 0;
}
if (lua_isstring(L, index)) {
auto str = lua_tostring(L, index);
auto saved_str = new char[strlen(str) + 1];
strcpy(saved_str, str);
value = reinterpret_cast<intptr_t>(saved_str);
type = PARAM_TYPE_STRING;
return 0;
}
if(lua_isfunction(L, index)) {
value = interpreter::get_function_handle(L, index);
type = PARAM_TYPE_FUNCTION;
return 0;
}
if (lua_isuserdata(L, index)) {
void* raw_ud = lua_touserdata(L, index);
void* obj = *(void**)raw_ud;
LuaParamType type_list[] = {
PARAM_TYPE_CARD,
PARAM_TYPE_GROUP,
PARAM_TYPE_EFFECT
};
for (auto t : type_list) {
if (scriptlib::check_param(L, t, index, TRUE)) {
value = reinterpret_cast<intptr_t>(obj);
type = t;
return 0;
}
}
return luaL_error(L, "Unsupported userdata for metadata entry.");
}
return luaL_error(L, "Unsupported type for metadata entry.");
}
void metadata_entry::copy_from(const metadata_entry& other) {
type = other.type;
switch (type) {
case PARAM_TYPE_STRING: {
const char* str = reinterpret_cast<const char*>(other.value);
char* dup = new char[strlen(str) + 1];
strcpy(dup, str);
value = reinterpret_cast<intptr_t>(dup);
break;
}
case PARAM_TYPE_INDEX: {
const double* pd = reinterpret_cast<const double*>(other.value);
value = reinterpret_cast<intptr_t>(new double(*pd));
break;
}
default:
// for int, bool, function handle, and userdata pointer types
value = other.value;
break;
}
}
metadata_entry::metadata_entry(const metadata_entry& other) {
copy_from(other);
}
metadata_entry& metadata_entry::operator=(const metadata_entry& other) {
if (this != &other) {
reset();
copy_from(other);
}
return *this;
}
void metadata_entry::reset() {
if (type == PARAM_TYPE_STRING) {
delete[] reinterpret_cast<char*>(value);
} else if (type == PARAM_TYPE_INDEX) {
delete reinterpret_cast<double*>(value);
}
value = 0;
type = PARAM_TYPE_INT;
}
int32_t metadata::luaop_clear() {
entries.clear();
return 0;
}
int32_t metadata::luaop_get(lua_State *L, int32_t offset) {
scriptlib::check_param_count(L, 1 + offset);
scriptlib::check_param(L, PARAM_TYPE_STRING, 1 + offset);
auto key = lua_tostring(L, 1 + offset);
auto it = entries.find(key);
if (it == entries.end()) {
lua_pushnil(L);
return 1;
}
return it->second.luaop_get(L);
}
int32_t metadata::luaop_set(lua_State *L, int32_t offset) {
scriptlib::check_param_count(L, 2 + offset);
scriptlib::check_param(L, PARAM_TYPE_STRING, 1 + offset);
auto key = lua_tostring(L, 1 + offset);
if(lua_isnil(L, 2 + offset)) {
entries.erase(key);
return 0;
}
auto existing = entries.find(key);
if (existing != entries.end()) {
return existing->second.luaop_set(L, 2 + offset);
}
entries[key] = metadata_entry();
return entries[key].luaop_set(L, 2 + offset);
}
int32_t metadata::luaop_has(lua_State *L, int32_t offset) {
scriptlib::check_param_count(L, 1 + offset);
scriptlib::check_param(L, PARAM_TYPE_STRING, 1 + offset);
auto key = lua_tostring(L, 1 + offset);
lua_pushboolean(L, entries.find(key) != entries.end());
return 1;
}
int32_t metadata::luaop_keys(lua_State *L) {
if(entries.empty()) {
lua_pushnil(L);
return 1;
}
int32_t count = 0;
for (const auto& pair : entries) {
lua_pushstring(L, pair.first.c_str());
++count;
}
return count;
}
#ifndef METADATA_H_
#define METADATA_H_
#include "common.h"
#include <unordered_map>
#include <string>
#include <lua.h>
class metadata_entry {
public:
metadata_entry();
~metadata_entry();
metadata_entry(const metadata_entry& other);
metadata_entry& operator=(const metadata_entry& other);
metadata_entry(metadata_entry&& other) noexcept;
metadata_entry& operator=(metadata_entry&& other) noexcept;
int32_t luaop_get(lua_State *L);
int32_t luaop_set(lua_State *L, int32_t index);
private:
void reset();
void copy_from(const metadata_entry& other);
LuaParamType type;
intptr_t value;
};
using metadata_entry_map = std::unordered_map<std::string, metadata_entry>;
class metadata {
public:
int32_t luaop_clear();
int32_t luaop_get(lua_State *L, int32_t offset = 0);
int32_t luaop_set(lua_State *L, int32_t offset = 0);
int32_t luaop_has(lua_State *L, int32_t offset = 0);
int32_t luaop_keys(lua_State *L);
private:
metadata_entry_map entries;
};
#endif /* METADATA_H_ */
......@@ -651,6 +651,33 @@ public:
static int32_t group_meta_band(lua_State *L);
static int32_t group_meta_bxor(lua_State *L);
//meta-related methods
static int32_t duel_get_meta_value(lua_State *L);
static int32_t duel_set_meta_value(lua_State *L);
static int32_t duel_has_meta_value(lua_State *L);
static int32_t duel_get_meta_keys(lua_State *L);
static int32_t duel_clear_meta(lua_State *L);
static int32_t duel_get_chain_meta_value(lua_State *L);
static int32_t duel_set_chain_meta_value(lua_State *L);
static int32_t duel_has_chain_meta_value(lua_State *L);
static int32_t duel_get_chain_meta_keys(lua_State *L);
static int32_t duel_clear_chain_meta(lua_State *L);
static int32_t card_get_meta_value(lua_State *L);
static int32_t card_set_meta_value(lua_State *L);
static int32_t card_has_meta_value(lua_State *L);
static int32_t card_get_meta_keys(lua_State *L);
static int32_t card_clear_meta(lua_State *L);
static int32_t group_get_meta_value(lua_State *L);
static int32_t group_set_meta_value(lua_State *L);
static int32_t group_has_meta_value(lua_State *L);
static int32_t group_get_meta_keys(lua_State *L);
static int32_t group_clear_meta(lua_State *L);
static int32_t effect_get_meta_value(lua_State *L);
static int32_t effect_set_meta_value(lua_State *L);
static int32_t effect_has_meta_value(lua_State *L);
static int32_t effect_get_meta_keys(lua_State *L);
static int32_t effect_clear_meta(lua_State *L);
//preload
static int32_t debug_message(lua_State *L);
static int32_t debug_add_card(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