Files
mtgodot-poc/extension/src/proto/proto_node.cpp
T

140 lines
4.1 KiB
C++

#include "proto_node.h"
#include "../asset_io.h"
#include <godot_cpp/core/class_db.hpp>
#include <string>
using namespace godot;
namespace mtgodot {
void Metin2Proto::_bind_methods() {
ClassDB::bind_method(D_METHOD("load_item_proto", "path"), &Metin2Proto::load_item_proto);
ClassDB::bind_method(D_METHOD("load_mob_proto", "path"), &Metin2Proto::load_mob_proto);
ClassDB::bind_method(D_METHOD("item", "vnum"), &Metin2Proto::item);
ClassDB::bind_method(D_METHOD("mob", "vnum"), &Metin2Proto::mob);
ClassDB::bind_method(D_METHOD("item_count"), &Metin2Proto::item_count);
ClassDB::bind_method(D_METHOD("mob_count"), &Metin2Proto::mob_count);
ClassDB::bind_method(D_METHOD("get_last_error"), &Metin2Proto::get_last_error);
}
bool Metin2Proto::load_item_proto(const String &path) {
std::string err;
PackedByteArray bytes = mtgodot::read_file(path);
std::vector<uint8_t> buf(bytes.ptr(), bytes.ptr() + bytes.size());
if (!mtproto::load_proto_bytes(buf, mtproto::ITEM_PROTO_KEY, m_item, &err)) {
last_error = String(err.c_str());
return false;
}
m_item_ix.clear();
m_item_ix.reserve(m_item.elements);
for (uint32_t i = 0; i < m_item.elements; ++i) {
mtproto::ItemRecord r = mtproto::parse_item(m_item.record(i), m_item.stride);
m_item_ix[r.vnum] = i;
}
last_error = "";
return true;
}
bool Metin2Proto::load_mob_proto(const String &path) {
std::string err;
PackedByteArray bytes = mtgodot::read_file(path);
std::vector<uint8_t> buf(bytes.ptr(), bytes.ptr() + bytes.size());
if (!mtproto::load_proto_bytes(buf, mtproto::MOB_PROTO_KEY, m_mob, &err)) {
last_error = String(err.c_str());
return false;
}
m_mob_ix.clear();
m_mob_ix.reserve(m_mob.elements);
for (uint32_t i = 0; i < m_mob.elements; ++i) {
mtproto::MobRecord r = mtproto::parse_mob(m_mob.record(i), m_mob.stride);
m_mob_ix[r.vnum] = i;
}
last_error = "";
return true;
}
Dictionary Metin2Proto::item(int vnum) const {
Dictionary d;
auto it = m_item_ix.find((uint32_t)vnum);
if (it == m_item_ix.end() || m_item.record(it->second) == nullptr) {
return d;
}
mtproto::ItemRecord r = mtproto::parse_item(m_item.record(it->second), m_item.stride);
d["vnum"] = (int)r.vnum;
d["vnum_range"] = (int)r.vnum_range;
d["name"] = String::utf8(r.name.c_str());
d["locale_name"] = String::utf8(r.locale_name.c_str());
d["type"] = (int)r.type;
d["sub_type"] = (int)r.sub_type;
d["weight"] = (int)r.weight;
d["size"] = (int)r.size;
d["anti_flags"] = (int)r.anti_flags;
d["flags"] = (int)r.flags;
d["wear_flags"] = (int)r.wear_flags;
d["buy_price"] = (int)r.buy_price;
d["sell_price"] = (int)r.sell_price;
{
Array limits;
for (const mtproto::ItemLimit &limit : r.limits) {
Dictionary entry;
entry["type"] = (int)limit.type;
entry["value"] = (int)limit.value;
limits.push_back(entry);
}
d["limits"] = limits;
}
{
Array applies;
for (const mtproto::ItemApply &apply : r.applies) {
Dictionary entry;
entry["type"] = (int)apply.type;
entry["value"] = (int)apply.value;
applies.push_back(entry);
}
d["applies"] = applies;
}
{
Array vals;
for (int i = 0; i < 6; ++i) {
vals.push_back((int)r.values[i]);
}
d["values"] = vals; // armor: values[3] = body shape index for the race .msm
}
{
Array sockets;
for (int socket : r.sockets) {
sockets.push_back(socket);
}
d["sockets"] = sockets;
}
d["refined_vnum"] = (int)r.refined_vnum;
d["refine_set"] = (int)r.refine_set;
d["alter_to_magic_pct"] = (int)r.alter_to_magic_pct;
d["specular"] = (int)r.specular;
d["gain_socket_pct"] = (int)r.gain_socket_pct;
return d;
}
Dictionary Metin2Proto::mob(int vnum) const {
Dictionary d;
auto it = m_mob_ix.find((uint32_t)vnum);
if (it == m_mob_ix.end() || m_mob.record(it->second) == nullptr) {
return d;
}
mtproto::MobRecord r = mtproto::parse_mob(m_mob.record(it->second), m_mob.stride);
d["vnum"] = (int)r.vnum;
d["name"] = String::utf8(r.name.c_str());
d["locale_name"] = String::utf8(r.locale_name.c_str());
d["type"] = (int)r.type;
d["rank"] = (int)r.rank;
d["battle_type"] = (int)r.battle_type;
d["level"] = (int)r.level;
d["size"] = (int)r.size;
return d;
}
} // namespace mtgodot