From d537c8d79fdcfa154f4262d75406aafd2a8ad5a5 Mon Sep 17 00:00:00 2001 From: twoone3 <3197653242@qq.com> Date: Thu, 3 Feb 2022 15:26:04 +0800 Subject: [PATCH] =?UTF-8?q?1.9.6=E6=9B=B4=E6=96=B0=20-=20=E4=BF=AE?= =?UTF-8?q?=E5=A4=8DgetPlayerList=E7=9A=84=E5=86=85=E5=AD=98=E6=B3=84?= =?UTF-8?q?=E9=9C=B2=20-=20=E4=BF=AE=E5=A4=8DregisterCommand=E5=87=BD?= =?UTF-8?q?=E6=95=B0=E5=9B=9E=E8=B0=83=20-=20=E6=96=B0=E5=A2=9EPyEntity::g?= =?UTF-8?q?etGameMode=E5=87=BD=E6=95=B0=20-=20=E6=96=B0=E5=A2=9EPyBlockIns?= =?UTF-8?q?tance::getPos/getDimensionId=E5=87=BD=E6=95=B0=20-=20=E4=BF=AE?= =?UTF-8?q?=E5=A4=8DPyEntity=E5=9C=A8MobHurtEvent=E4=B8=AD=E7=A9=BA?= =?UTF-8?q?=E6=8C=87=E9=92=88=E8=8E=B7=E5=8F=96=E5=AD=97=E7=AC=A6=E4=B8=B2?= =?UTF-8?q?=E4=B8=BA=E7=A9=BA=E6=8C=87=E9=92=88=E7=9A=84=E9=97=AE=E9=A2=98?= =?UTF-8?q?=20-=20=E4=BF=AE=E6=94=B9=E9=83=A8=E5=88=86=E6=BA=90=E6=96=87?= =?UTF-8?q?=E4=BB=B6?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- BDSpyrunner.vcxproj | 12 ++-- BDSpyrunner.vcxproj.filters | 18 ++---- mod/CPython.cpp | 87 --------------------------- mod/{Tool.h => Common.h} | 15 +++-- mod/Event.cpp | 87 +++++++++------------------ mod/Main.cpp | 32 +++++++++- mod/Main.h | 7 +++ mod/Module.cpp | 23 ++++--- mod/Module.h | 4 +- mod/NBT.h | 5 +- mod/PyBlockInstance.cpp | 94 +++++++++++++++-------------- mod/PyBlockInstance.h | 5 -- mod/PyEntity.cpp | 113 ++++++++++++++--------------------- mod/PyEntity.h | 5 -- mod/PyItemStack.cpp | 55 ++++++----------- mod/PyItemStack.h | 5 -- mod/PyUtils.cpp | 90 ++++++++++++++++++++++++++++ mod/{CPython.h => PyUtils.h} | 90 +++++++++++++++++++++++----- mod/Tool.cpp | 18 ------ mod/Version.h | 4 +- 20 files changed, 379 insertions(+), 390 deletions(-) delete mode 100644 mod/CPython.cpp rename mod/{Tool.h => Common.h} (83%) create mode 100644 mod/Main.h delete mode 100644 mod/PyBlockInstance.h delete mode 100644 mod/PyEntity.h delete mode 100644 mod/PyItemStack.h create mode 100644 mod/PyUtils.cpp rename mod/{CPython.h => PyUtils.h} (51%) delete mode 100644 mod/Tool.cpp diff --git a/BDSpyrunner.vcxproj b/BDSpyrunner.vcxproj index 51d30517..b8c8381b 100644 --- a/BDSpyrunner.vcxproj +++ b/BDSpyrunner.vcxproj @@ -71,19 +71,17 @@ copy $(OutputPath)$(ProjectName).pdb ..\BDS\plugins\$(ProjectName).pdb - - + + - - - - - + + + diff --git a/BDSpyrunner.vcxproj.filters b/BDSpyrunner.vcxproj.filters index 464a5808..90106a4e 100644 --- a/BDSpyrunner.vcxproj.filters +++ b/BDSpyrunner.vcxproj.filters @@ -39,39 +39,33 @@ 源文件 - - 源文件 - - + 源文件 - + 头文件 头文件 - - 头文件 - 头文件 - + 头文件 头文件 - + 头文件 - + 头文件 - + 头文件 diff --git a/mod/CPython.cpp b/mod/CPython.cpp deleted file mode 100644 index 54d7748f..00000000 --- a/mod/CPython.cpp +++ /dev/null @@ -1,87 +0,0 @@ -#include "CPython.h" -#include "Tool.h" - -std::string PyObjectToStr(PyObject* obj) { - return PyUnicode_AsUTF8(PyObject_Repr(obj)); -} - -std::string PyUnicodeToStr(PyObject* obj) { - return PyUnicode_AsUTF8(obj); -} - -PyObject* StrToPyUnicode(std::string_view str) { - //检测是否有相同字符串 return PyUnicode_InternFromString(str.data()); - return PyUnicode_FromStringAndSize(str.data(), str.size()); -} - -//list转vector -std::vector ToStrArray(PyObject* list) { - std::vector arr; - if (PyList_Check(list)) { - for (Py_ssize_t i = 0; i < PyList_Size(list); i++) { - arr.push_back(PyUnicode_AsUTF8(PyList_GetItem(list, i))); - } - } - return arr; -} - -//Vec3转list -PyObject* ToList(const Vec3& vec) { - PyObject* list = PyList_New(3); - PyList_SetItem(list, 0, PyFloat_FromDouble(vec.x)); - PyList_SetItem(list, 1, PyFloat_FromDouble(vec.y)); - PyList_SetItem(list, 2, PyFloat_FromDouble(vec.z)); - return list; -} - -//方块坐标转list -PyObject* ToList(const BlockPos& bp) { - PyObject* list = PyList_New(3); - PyList_SetItem(list, 0, PyLong_FromLong(bp.x)); - PyList_SetItem(list, 1, PyLong_FromLong(bp.y)); - PyList_SetItem(list, 2, PyLong_FromLong(bp.z)); - return list; -} - -//打印错误信息 -void Py_PrintErrors() { - if (PyErr_Occurred()) { - //PyObject* type; - //PyObject* value; - //PyObject* traceback; - //PyErr_Fetch(&type, &value, &traceback); - //if (PyUnicode_Check(value)) { - // logger.error("{}", PyUnicodeToStr(value)); - //} - //else if (PyTuple_Check(value)) { - // PyObject* info = reinterpret_cast(value)->args; - // auto size = PyTuple_Size(info); - // if (size == 1) { - // logger.error("{}: {}", Py_TYPE(value)->tp_name, PyUnicodeToStr(PyTuple_GetItem(info, 0))); - // } - // else if (size == 2) { - // logger.error("{}: {}", Py_TYPE(value)->tp_name, PyUnicodeToStr(PyTuple_GetItem(info, 0))); - // PyObject* location = PyTuple_GetItem(info, 1); - // logger.error("File: {} Line: {} Column: {}", - // PyUnicodeToStr(PyTuple_GetItem(location, 0)), - // PyObjectToStr(PyTuple_GetItem(location, 1)), - // PyObjectToStr(PyTuple_GetItem(location, 2)) - // ); - // logger.error(" {}", PyObjectToStr(PyTuple_GetItem(location, 3))); - // } - //} - //logger.info("{}", PyObjectToStr(traceback)); - //PyObject_Print(type, stdout, 0); - //PyObject_Print(value, stdout, 0); - //PyErr_Restore(type, value, traceback); - PyErr_Print(); - } -} - -PyGILGuard::PyGILGuard() { - gil_ = PyGILState_Ensure(); -} - -PyGILGuard::~PyGILGuard() { - PyGILState_Release(gil_); -} diff --git a/mod/Tool.h b/mod/Common.h similarity index 83% rename from mod/Tool.h rename to mod/Common.h index 0e9f292c..d2195549 100644 --- a/mod/Tool.h +++ b/mod/Common.h @@ -43,15 +43,14 @@ #include #include #include -/*JSON*/ -#include -using json_t = nlohmann::detail::value_t; - -//字符串转JSON,本插件采用 https://json.nlohmann.me 的JSON库 -fifo_json CompoundTagToJson(std::string_view str); - -bool IsPlayer(Actor* ptr); +inline bool IsPlayer(Actor* ptr) { + if (ptr == nullptr) + return false; + if (ptr->getEntityTypeId() != 319) + return false; + return true; +} inline Logger logger("BDSpyrunner"); diff --git a/mod/Event.cpp b/mod/Event.cpp index 58f96199..3c3a61ef 100644 --- a/mod/Event.cpp +++ b/mod/Event.cpp @@ -1,82 +1,37 @@ #include "Event.h" -#include "Tool.h" +#include "Common.h" #include "Module.h" using namespace std; //事件回调助手,初始化对象将申请GIL class Callbacker { public: - Callbacker(EventCode t) : - type_(t), arg_(nullptr), gil_() { + Callbacker(EventCode t) { + type_ = t; + arg_ = nullptr; } ~Callbacker() { - //if (arg_ == nullptr) - // logger.error("意外的空指针"); - //logger.info("{}", PyObjectToStr(arg_)); - //Py_XDECREF(arg_); } //事件回调 bool callback() { - bool intercept = true; + bool pass = true; //如果没有则跳过 auto& cbs = g_callback_functions[type_]; for (auto cb : cbs) { - PyObject* result = _PyObject_FastCall(cb, &arg_, 1); - Py_PrintErrors(); - if (result == Py_False) - intercept = false; - Py_XDECREF(result); + PyCaller pc; + pass = pc.call(cb, arg_) != Py_False; } - //Py_XDECREF(arg_); - return intercept; + return pass; } - Callbacker& setArg(PyObject* arg) { - arg_ = arg; - return *this; - } - Callbacker& insert(string_view key, PyObject* item) { + template + Callbacker& insert(string_view key, Arg item) { if (arg_ == nullptr) arg_ = PyDict_New(); - PyDict_SetItemString(arg_, key.data(), item); - Py_DECREF(item); + PyObject* obj = ToPyObject(item); + PyDict_SetItemString(arg_, key.data(), obj); + Py_DECREF(obj); return *this; } - Callbacker& insert(string_view key, string_view item) { - return insert(key, StrToPyUnicode(item)); - } - Callbacker& insert(string_view key, Actor* item) { - return insert(key, ToPyEntity(item)); - } - Callbacker& insert(string_view key, ItemStack* item) { - return insert(key, ToPyItemStack(item)); - } - Callbacker& insert(string_view key, const BlockPos& item) { - return insert(key, ToList(item)); - } - Callbacker& insert(string_view key, BlockInstance& item) { - return insert(key, ToPyBlockInstance(&item)); - } - Callbacker& insert(string_view key, const Vec3& item) { - return insert(key, ToList(item)); - } - Callbacker& insert(string_view key, short item) { - return insert(key, PyLong_FromLong(item)); - } - Callbacker& insert(string_view key, int item) { - return insert(key, PyLong_FromLong(item)); - } - Callbacker& insert(string_view key, unsigned item) { - return insert(key, PyLong_FromUnsignedLong(item)); - } - Callbacker& insert(string_view key, long long item) { - return insert(key, PyLong_FromLongLong(item)); - } - Callbacker& insert(string_view key, unsigned long long item) { - return insert(key, PyLong_FromUnsignedLongLong(item)); - } - Callbacker& insert(string_view key, float item) { - return insert(key, PyLong_FromDouble(item)); - } private: EventCode type_; PyObject* arg_; @@ -254,6 +209,9 @@ void EnableEventListener(EventCode code) { EVENT_END; break; case EventCode::onWitherBossDestroy: + EVENT_BEGIN(WitherBossDestroyEvent); + //TODO: AABB and WitherBoss + EVENT_END; break; case EventCode::onPlaceBlock: EVENT_BEGIN(PlayerPlaceBlockEvent); @@ -265,19 +223,28 @@ void EnableEventListener(EventCode code) { break; case EventCode::onOpenContainer: EVENT_BEGIN(PlayerOpenContainerEvent); - //TODO: container EVENT_INSERT(BlockInstance); + //TODO: EVENT_INSERT(Container); EVENT_INSERT(Player); EVENT_END; break; case EventCode::onCloseContainer: EVENT_BEGIN(PlayerCloseContainerEvent); - //TODO: container EVENT_INSERT(BlockInstance); + //TODO: EVENT_INSERT(Container); EVENT_INSERT(Player); EVENT_END; break; case EventCode::onContainerChange: + EVENT_BEGIN(ContainerChangeEvent); + EVENT_INSERT(Actor); + EVENT_INSERT(BlockInstance); + //TODO: EVENT_INSERT(Container); + EVENT_INSERT(NewItemStack); + EVENT_INSERT(Player); + EVENT_INSERT(PreviousItemStack); + EVENT_INSERT(Slot); + EVENT_END; break; case EventCode::onOpenContainerScreen: break; diff --git a/mod/Main.cpp b/mod/Main.cpp index 22eb52de..fa21c609 100644 --- a/mod/Main.cpp +++ b/mod/Main.cpp @@ -1,4 +1,6 @@ -#include "Module.h" +#include "Main.h" +#include "Common.h" +#include "Module.h" #include "NBT.h" #include "Version.h" @@ -8,6 +10,15 @@ using namespace std; namespace fs = filesystem; +//字符串转JSON,本插件采用 https://json.nlohmann.me 的JSON库 +fifo_json StrToJson(std::string_view str) { + try { return fifo_json::parse(str); } + catch (const std::exception& e) { + logger.error("Parsing JSON failed! {}", e.what()); + return nullptr; + } +} + //初始化Python类 void PyClassInit() { if (PyType_Ready(&PyEntity_Type) < 0) @@ -74,6 +85,23 @@ THook(int, "main", int argc, char* argv[], char* envp[]) { return true; } ); + //命令监听 + Event::PlayerCmdEvent::subscribe( + [](Event::PlayerCmdEvent e) { + for (auto& [cmd, data] : g_commands) { + if (e.mCommand == cmd) { + PyGILGuard _gil; + PyObject* p = ToPyObject(e.mPlayer); + PyObject* result = _PyObject_FastCall(data.second, &p, 1); + Py_PrintErrors(); + Py_DECREF(p); + Py_XDECREF(result); + return false; + } + } + return true; + } + ); return original(argc, argv, envp); } //Dll主函数 @@ -167,7 +195,7 @@ static Json AccessUrlForJson(const wchar_t* url) { } while (size); InternetCloseHandle(handle2); InternetCloseHandle(hSession); - return CompoundTagToJson(data); + return StrToJson(data); } //访问url static void AccessUrlForFile(const wchar_t* url, string_view filename) { diff --git a/mod/Main.h b/mod/Main.h new file mode 100644 index 00000000..40384e37 --- /dev/null +++ b/mod/Main.h @@ -0,0 +1,7 @@ +#pragma once +#include + +using json_t = nlohmann::detail::value_t; + +//字符串转JSON,本插件采用 https://json.nlohmann.me 的JSON库 +fifo_json StrToJson(std::string_view str); diff --git a/mod/Module.cpp b/mod/Module.cpp index bf9ecda7..fcf64258 100644 --- a/mod/Module.cpp +++ b/mod/Module.cpp @@ -21,7 +21,7 @@ constexpr int IsSlimeChunk(unsigned x, unsigned z) { } //获取BDS版本 static PyObject* getBDSVersion(PyObject*, PyObject*) { - return StrToPyUnicode(Common::getGameVersionString()); + return ToPyObject(Common::getGameVersionString()); } //指令输出 static PyObject* logout(PyObject*, PyObject* args) { @@ -75,17 +75,16 @@ static PyObject* getPlayerByXuid(PyObject*, PyObject* args) { Player* p = Level::getPlayer(xuid); if (p == nullptr) Py_RETURN_ERROR("Failed to find player"); - return ToPyEntity(p); + return ToPyObject(p); } //获取玩家列表 static PyObject* getPlayerList(PyObject*, PyObject* args) { PyObject* list = PyList_New(0); - Level::forEachPlayer( - [list](Player& p)->bool { - PyList_Append(list, ToPyEntity(&p)); - return true; - } - ); + for (auto p : Level::getAllPlayers()) { + PyObject* player = ToPyObject(p); + PyList_Append(list, player); + Py_DECREF(player); + } return list; } static PyObject* setServerMotd(PyObject*, PyObject* args) { @@ -94,7 +93,7 @@ static PyObject* setServerMotd(PyObject*, PyObject* args) { if (Global == nullptr) Py_RETURN_ERROR("Server did not finish loading"); SymCall("?allowIncomingConnections@ServerNetworkHandler@@QEAAXAEBV?$basic_string@DU?$char_traits@D@std@@V?$allocator@D@2@@std@@_N@Z", - uintptr_t, ServerNetworkHandler*, const string&, bool)(Global, name, true); + uintptr_t, ServerNetworkHandler*, const string&, bool)(Global, name, true); Py_RETURN_NONE; } //根据坐标设置方块 @@ -109,7 +108,7 @@ static PyObject* getBlock(PyObject*, PyObject* args) { auto bi = BlockInstance::createBlockInstance(b, bp, did); auto ubi = make_unique(bi); - return ToPyBlockInstance(ubi.get()); + return ToPyObject(ubi.get()); } static PyObject* setBlock(PyObject*, PyObject* args) { const char* name = ""; @@ -137,7 +136,7 @@ static PyObject* getStructure(PyObject*, PyObject* args) { &ignore_entities, &ignore_blocks ); auto st = StructureTemplate::fromWorld("name", did, pos1, pos2, ignore_entities, ignore_blocks); - return StrToPyUnicode(CompoundTagToJson(*st.save()).dump(4)); + return ToPyObject(CompoundTagToJson(*st.save()).dump(4)); } //从JSON字符串NBT结构数据导出结构到指定地点 static PyObject* setStructure(PyObject*, PyObject* args) { @@ -150,7 +149,7 @@ static PyObject* setStructure(PyObject*, PyObject* args) { &data, &pos.x, &pos.y, &pos.z, &did, &mir, &rot ); - StructureTemplate::fromTag("name", *ToCompoundTag(CompoundTagToJson(data))) + StructureTemplate::fromTag("name", *ToCompoundTag(StrToJson(data))) .toWorld(did, pos, mir, rot); /*for (int x = 0; x != size.x; ++x) { for (int y = 0; y != size.y; ++y) { diff --git a/mod/Module.h b/mod/Module.h index 01dd16be..f502c8dc 100644 --- a/mod/Module.h +++ b/mod/Module.h @@ -1,7 +1,5 @@ #pragma once -#include "PyEntity.h" -#include "PyItemStack.h" -#include "PyBlockInstance.h" +#include "PyUtils.h" #include "Event.h" //Py函数表 diff --git a/mod/NBT.h b/mod/NBT.h index b2aa38fa..228b2ebc 100644 --- a/mod/NBT.h +++ b/mod/NBT.h @@ -1,5 +1,6 @@ #pragma once -#include "Tool.h" +#include "Common.h" +#include "Main.h" template class serialize { @@ -14,7 +15,7 @@ std::unique_ptr ToListTag(const fifo_json& value); std::unique_ptr ToCompoundTag(const fifo_json& value); inline ItemStack LoadItemFromString(std::string_view str) { - return ItemStack::fromTag(*ToCompoundTag(CompoundTagToJson(str))); + return ItemStack::fromTag(*ToCompoundTag(StrToJson(str))); } inline ItemStack LoadItemFromJson(fifo_json data) { return ItemStack::fromTag(*ToCompoundTag(data)); diff --git a/mod/PyBlockInstance.cpp b/mod/PyBlockInstance.cpp index 1f95245b..d8322fc5 100644 --- a/mod/PyBlockInstance.cpp +++ b/mod/PyBlockInstance.cpp @@ -1,74 +1,70 @@ -#include "PyBlockInstance.h" -#include "Tool.h" +#include "PyUtils.h" #include "NBT.h" -#define Py_GET_BLOCKINSTANCE Py_GET_BLOCKINSTANCE2(nullptr) -#define Py_GET_BLOCKINSTANCE2(ret) BlockInstance* bi = getBlock(self);if (bi == nullptr)return ret +#define Py_GET_BLOCK auto block = reinterpret_cast(self)->block +#define Py_GET_BLOCKPOS auto pos = reinterpret_cast(self)->pos +#define Py_GET_DIMENSIONID auto dim = reinterpret_cast(self)->dim using namespace std; struct PyBlockInstance { PyObject_HEAD; - BlockInstance* value; + Block* block; + BlockPos pos; + int dim; - static BlockInstance* getBlock(PyObject* self) { - if (reinterpret_cast(self)->value) - return reinterpret_cast(self)->value; - else - Py_RETURN_ERROR("This value pointer is nullptr"); - } static int print(PyObject* self, FILE* file, int) { - Py_GET_BLOCKINSTANCE2(-1); - fputs(bi->getBlock()->getName().c_str(), file); + Py_GET_BLOCK; + fputs(block->getName().c_str(), file); return 0; } static PyObject* repr(PyObject* self) { - Py_GET_BLOCKINSTANCE2(StrToPyUnicode("")); - return StrToPyUnicode(bi->getBlock()->getName().getString()); + Py_GET_BLOCK; + return ToPyObject(block->getName().getString()); } static Py_hash_t hash(PyObject* self) { return reinterpret_cast(self); } static PyObject* str(PyObject* self) { - Py_GET_BLOCKINSTANCE2(StrToPyUnicode("")); - return StrToPyUnicode(bi->getBlock()->getName().getString()); + Py_GET_BLOCK; + return ToPyObject(block->getName().getString()); } static PyObject* rich_compare(PyObject* self, PyObject* other, int op) { switch (op) { - //< - case Py_LT:break; - //<= - case Py_LE:break; - //== - case Py_EQ: - if (getBlock(self) == getBlock(other)) - Py_RETURN_TRUE; - else - Py_RETURN_FALSE; + case Py_LT:// < + break; + case Py_LE:// <= + break; + case Py_EQ:// == break; - //!= - case Py_NE: - if (getBlock(self) != getBlock(other)) - Py_RETURN_TRUE; - else - Py_RETURN_FALSE; + case Py_NE:// != + break; + case Py_GT:// > + break; + case Py_GE:// >= break; - //> - case Py_GT:break; - //>= - case Py_GE:break; } Py_RETURN_NOTIMPLEMENTED; } - static PyObject* getName(PyObject* self, PyObject*) { - Py_GET_BLOCKINSTANCE; - return StrToPyUnicode(bi->getBlock()->getName().getString()); + Py_METHOD_DEFINE(getName) { + Py_GET_BLOCK; + return ToPyObject(block->getName().getString()); + } + Py_METHOD_DEFINE(getPos) { + Py_GET_BLOCKPOS; + return ToPyObject(pos); + } + Py_METHOD_DEFINE(getDimensionId) { + Py_GET_DIMENSIONID; + return ToPyObject(dim); } inline static PyMethodDef Methods[]{ - { "getName", getName, METH_NOARGS, nullptr }, - { nullptr } + Py_METHOD_NOARGS(getName), + Py_METHOD_NOARGS(getPos), + Py_METHOD_NOARGS(getDimensionId), + Py_METHOD_END }; }; @@ -123,8 +119,18 @@ PyTypeObject PyBlockInstance_Type{ nullptr, /* tp_finalize */ }; -PyObject* ToPyBlockInstance(BlockInstance* ptr) { +PyObject* ToPyObject(BlockInstance* ptr) { + PyBlockInstance* obj = PyObject_New(PyBlockInstance, &PyBlockInstance_Type); + obj->block = ptr->getBlock(); + obj->pos = ptr->getPosition(); + obj->dim = ptr->getDimensionId(); + return reinterpret_cast(obj); +} + +PyObject* ToPyObject(BlockInstance& bi) { PyBlockInstance* obj = PyObject_New(PyBlockInstance, &PyBlockInstance_Type); - obj->value = ptr; + obj->block = bi.getBlock(); + obj->pos = bi.getPosition(); + obj->dim = bi.getDimensionId(); return reinterpret_cast(obj); } diff --git a/mod/PyBlockInstance.h b/mod/PyBlockInstance.h deleted file mode 100644 index 52ce57a3..00000000 --- a/mod/PyBlockInstance.h +++ /dev/null @@ -1,5 +0,0 @@ -#pragma once -#include "CPython.h" - -extern PyTypeObject PyBlockInstance_Type; -PyObject* ToPyBlockInstance(class BlockInstance* ptr); diff --git a/mod/PyEntity.cpp b/mod/PyEntity.cpp index dff2e104..fa962664 100644 --- a/mod/PyEntity.cpp +++ b/mod/PyEntity.cpp @@ -1,98 +1,77 @@ -#include "PyEntity.h" -#include "Tool.h" +#include "PyUtils.h" #include "NBT.h" #define Py_GET_PLAYER Py_GET_PLAYER2(nullptr) -#define Py_GET_PLAYER2(ret) Player* p = getPlayer(self);if (p == nullptr)return ret +#define Py_GET_PLAYER2(ret) auto p = reinterpret_cast(reinterpret_cast(self)->value);if (p == nullptr)return ret #define Py_GET_ACTOR Py_GET_ACTOR2(nullptr) -#define Py_GET_ACTOR2(ret) Actor* a = getActor(self);if (a == nullptr)return ret +#define Py_GET_ACTOR2(ret) auto a = reinterpret_cast(self)->value;if (a == nullptr)return ret using namespace std; + struct PyEntity { PyObject_HEAD; Actor* value; - static Actor* getActor(PyObject* self) { - if (reinterpret_cast(self)->value) - return reinterpret_cast(self)->value; - else - Py_RETURN_ERROR("This entity pointer is nullptr"); - } - static Player* getPlayer(PyObject* self) { - if (IsPlayer(reinterpret_cast(self)->value)) - return reinterpret_cast(reinterpret_cast(self)->value); - else - Py_RETURN_ERROR("This entity pointer is nullptr or is not player pointer"); - } static int print(PyObject* self, FILE* file, int) { Py_GET_ACTOR2(-1); fputs(a->getNameTag().c_str(), file); return 0; } static PyObject* repr(PyObject* self) { - Py_GET_ACTOR2(StrToPyUnicode("")); - return StrToPyUnicode(a->getNameTag()); + Py_GET_ACTOR2(ToPyObject("")); + return ToPyObject(a->getNameTag()); } static Py_hash_t hash(PyObject* self) { return reinterpret_cast(self); } static PyObject* str(PyObject* self) { - Py_GET_ACTOR2(StrToPyUnicode("")); - return StrToPyUnicode(a->getNameTag()); + Py_GET_ACTOR2(ToPyObject("")); + return ToPyObject(a->getNameTag()); } static PyObject* rich_compare(PyObject* self, PyObject* other, int op) { switch (op) { - //< - case Py_LT:break; - //<= - case Py_LE:break; - //== - case Py_EQ: - if (getActor(self) == getActor(other)) - Py_RETURN_TRUE; - else - Py_RETURN_FALSE; + case Py_LT:// < + break; + case Py_LE:// <= break; - //!= - case Py_NE: - if (getActor(self) != getActor(other)) - Py_RETURN_TRUE; - else - Py_RETURN_FALSE; + case Py_EQ:// == + return ToPyObject(reinterpret_cast(self)->value == reinterpret_cast(other)->value); + case Py_NE:// != + return ToPyObject(reinterpret_cast(self)->value != reinterpret_cast(other)->value); + case Py_GT:// > + break; + case Py_GE:// >= break; - //> - case Py_GT:break; - //>= - case Py_GE:break; } Py_RETURN_NOTIMPLEMENTED; } //获取名字 Py_METHOD_DEFINE(getName) { - Py_GET_ACTOR; - return StrToPyUnicode(a->getNameTag()); + Py_GET_ACTOR2(ToPyObject("")); + return ToPyObject(a->getNameTag()); } Py_METHOD_DEFINE(setName) { const char* name = ""; Py_PARSE("s", &name); Py_GET_PLAYER; p->setName(name); + Py_RETURN_NONE; } //获取UUID Py_METHOD_DEFINE(getUuid) { Py_GET_PLAYER; - return StrToPyUnicode(p->getUuid()); + return ToPyObject(p->getUuid()); } //获取XUID Py_METHOD_DEFINE(getXuid) { Py_GET_PLAYER; - return StrToPyUnicode(p->getXuid()); + return ToPyObject(p->getXuid()); } //获取坐标 Py_METHOD_DEFINE(getPos) { Py_GET_ACTOR; - return ToList(a->getPos()); + return ToPyObject(a->getPos()); } //获取维度ID Py_METHOD_DEFINE(getDimensionId) { @@ -126,14 +105,14 @@ struct PyEntity { //string type; //SymCall("?EntityTypeToString@@YA?AV?$basic_string@DU?$char_traits@D@std@@V?$allocator@D@2@@std@@W4ActorType@@W4ActorTypeNamespaceRules@@@Z", // &type, a->getEntityTypeId()); - return StrToPyUnicode(a->getTypeName()); + return ToPyObject(a->getTypeName()); } //获取nbt数据 Py_METHOD_DEFINE(getNBT) { Py_GET_ACTOR; auto t = CompoundTag::create(); a->save(*t); - return StrToPyUnicode(CompoundTagToJson(*t).dump(4)); + return ToPyObject(CompoundTagToJson(*t).dump(4)); } //获取生命值 Py_METHOD_DEFINE(getHealth) { @@ -160,7 +139,7 @@ struct PyEntity { //获取设备id Py_METHOD_DEFINE(getPlatformOnlineId) { Py_GET_PLAYER; - return StrToPyUnicode(p->getPlatformOnlineId()); + return ToPyObject(p->getPlatformOnlineId()); } //获取设备类型 Py_METHOD_DEFINE(getPlatform) { @@ -171,7 +150,7 @@ struct PyEntity { Py_METHOD_DEFINE(getIP) { Py_GET_PLAYER; auto ni = p->getNetworkIdentifier(); - return StrToPyUnicode(Global->getAdr(*ni).ToString(false, ':')); + return ToPyObject(Global->getAdr(*ni).ToString(false, ':')); } //获取玩家所有物品 Py_METHOD_DEFINE(getAllItem) { @@ -191,14 +170,14 @@ struct PyEntity { } items_json["OffHand"] = CompoundTagToJson(*p->getOffhandSlot().save()); items_json["Hand"] = CompoundTagToJson(*p->getSelectedItem().save()); - return StrToPyUnicode(items_json.dump(4)); + return ToPyObject(items_json.dump(4)); } //设置玩家所有物品 Py_METHOD_DEFINE(setAllItem) { const char* items_data = ""; Py_PARSE("s", &items_data); Py_GET_PLAYER; - fifo_json items_json(CompoundTagToJson(items_data)); + fifo_json items_json(StrToJson(items_data)); if (items_json.contains("Inventory")) { auto& items = p->getInventory(); fifo_json& inventory = items_json["Inventory"]; @@ -361,10 +340,8 @@ struct PyEntity { return nullptr; p->sendCustomFormPacket(str, [p, callback](string arg) { - PyGILGuard gil; - PyObject* result = PyObject_CallFunction(callback, "Os", ToPyEntity(p), arg.c_str()); - Py_PrintErrors(); - Py_XDECREF(result); + PyCaller pc; + pc.call(callback, p, arg); } ); Py_RETURN_NONE; @@ -385,10 +362,8 @@ struct PyEntity { Py_RETURN_ERROR("The number of buttons is not equal to the number of images"); p->sendSimpleFormPacket(title, content, buttons, images, [p, callback](int arg) { - PyGILGuard gil; - PyObject* result = PyObject_CallFunction(callback, "Oi", ToPyEntity(p), arg); - Py_PrintErrors(); - Py_XDECREF(result); + PyCaller pc; + pc.call(callback, p, arg); } ); Py_RETURN_NONE; @@ -405,10 +380,8 @@ struct PyEntity { return nullptr; p->sendModalFormPacket(title, content, button1, button2, [p, callback](bool arg) { - PyGILGuard gil; - PyObject* result = PyObject_CallFunction(callback, "OO", ToPyEntity(p), arg ? Py_True : Py_False); - Py_PrintErrors(); - Py_XDECREF(result); + PyCaller pc; + pc.call(callback, p, arg); } ); Py_RETURN_NONE; @@ -421,7 +394,7 @@ struct PyEntity { Py_PARSE("ss|i", &title, &side_data, &order); Py_GET_PLAYER; vector> data; - fifo_json value = CompoundTagToJson(side_data); + fifo_json value = StrToJson(side_data); if (value.is_object()) for (auto& [key, val] : value.items()) { data.push_back({ key, val }); @@ -470,7 +443,7 @@ struct PyEntity { auto tags = a->getTags(); PyObject* list = PyList_New(0); for (size_t i = 0; i < tags.size(); i++) { - PyList_Append(list, StrToPyUnicode(tags[i])); + PyList_Append(list, ToPyObject(tags[i])); } return list; } @@ -480,6 +453,11 @@ struct PyEntity { a->kill(); Py_RETURN_NONE; } + //获取游戏模式 + Py_METHOD_DEFINE(getGameMode) { + Py_GET_PLAYER; + return PyLong_FromLong(p->getPlayerGameType()); + } inline static PyMethodDef Methods[]{ Py_METHOD_NOARGS(getName), @@ -528,10 +506,11 @@ struct PyEntity { Py_METHOD_VARARGS(removeTag), Py_METHOD_NOARGS(getTags), Py_METHOD_NOARGS(kill), + Py_METHOD_NOARGS(getGameMode), Py_METHOD_END }; }; -//Entity类型 + PyTypeObject PyEntity_Type{ PyVarObject_HEAD_INIT(nullptr, 0) "Entity", /* tp_name */ @@ -583,7 +562,7 @@ PyTypeObject PyEntity_Type{ nullptr, /* tp_finalize */ }; -PyObject* ToPyEntity(Actor* ptr) { +PyObject* ToPyObject(Actor* ptr) { PyEntity* obj = PyObject_New(PyEntity, &PyEntity_Type); obj->value = ptr; return reinterpret_cast(obj); diff --git a/mod/PyEntity.h b/mod/PyEntity.h deleted file mode 100644 index ba40f5d4..00000000 --- a/mod/PyEntity.h +++ /dev/null @@ -1,5 +0,0 @@ -#pragma once -#include "CPython.h" - -extern PyTypeObject PyEntity_Type; -PyObject* ToPyEntity(class Actor* ptr); diff --git a/mod/PyItemStack.cpp b/mod/PyItemStack.cpp index 466209c5..51203195 100644 --- a/mod/PyItemStack.cpp +++ b/mod/PyItemStack.cpp @@ -1,9 +1,8 @@ -#include "PyItemStack.h" -#include "Tool.h" +#include "PyUtils.h" #include "NBT.h" #define Py_GET_ITEMSTACK Py_GET_ITEMSTACK2(nullptr) -#define Py_GET_ITEMSTACK2(ret) ItemStack* i = getItemStack(self);if (i == nullptr)return ret +#define Py_GET_ITEMSTACK2(ret) auto i = reinterpret_cast(self)->value;if (i == nullptr)return ret using namespace std; @@ -11,63 +10,47 @@ struct PyItemStack { PyObject_HEAD; ItemStack* value; - static ItemStack* getItemStack(PyObject* self) { - if (reinterpret_cast(self)->value) - return reinterpret_cast(self)->value; - else - Py_RETURN_ERROR("This value pointer is nullptr"); - } static int print(PyObject* self, FILE* file, int) { Py_GET_ITEMSTACK2(-1); fputs(i->getName().c_str(), file); return 0; } static PyObject* repr(PyObject* self) { - Py_GET_ITEMSTACK2(StrToPyUnicode("")); - return StrToPyUnicode(i->getName()); + Py_GET_ITEMSTACK2(ToPyObject("")); + return ToPyObject(i->getName()); } static Py_hash_t hash(PyObject* self) { return reinterpret_cast(self); } static PyObject* str(PyObject* self) { - Py_GET_ITEMSTACK2(StrToPyUnicode("")); - return StrToPyUnicode(i->getName()); + Py_GET_ITEMSTACK2(ToPyObject("")); + return ToPyObject(i->getName()); } static PyObject* rich_compare(PyObject* self, PyObject* other, int op) { switch (op) { - //< - case Py_LT:break; - //<= - case Py_LE:break; - //== - case Py_EQ: - if (getItemStack(self) == getItemStack(other)) - Py_RETURN_TRUE; - else - Py_RETURN_FALSE; + case Py_LT:// < + break; + case Py_LE:// <= + break; + case Py_EQ:// == + return ToPyObject(reinterpret_cast(self)->value == reinterpret_cast(other)->value); + case Py_NE:// != + return ToPyObject(reinterpret_cast(self)->value != reinterpret_cast(other)->value); + case Py_GT:// > break; - //!= - case Py_NE: - if (getItemStack(self) != getItemStack(other)) - Py_RETURN_TRUE; - else - Py_RETURN_FALSE; + case Py_GE:// >= break; - //> - case Py_GT:break; - //>= - case Py_GE:break; } Py_RETURN_NOTIMPLEMENTED; } Py_METHOD_DEFINE(getName) { Py_GET_ITEMSTACK; - return StrToPyUnicode(i->getName()); + return ToPyObject(i->getName()); } Py_METHOD_DEFINE(getNBT) { Py_GET_ITEMSTACK; - return StrToPyUnicode(CompoundTagToJson(*i->getNbt())); + return ToPyObject(CompoundTagToJson(*i->getNbt()).dump(4)); } inline static PyMethodDef Methods[]{ @@ -128,7 +111,7 @@ PyTypeObject PyItemStack_Type{ nullptr, /* tp_finalize */ }; -PyObject* ToPyItemStack(ItemStack* ptr) { +PyObject* ToPyObject(ItemStack* ptr) { PyItemStack* obj = PyObject_New(PyItemStack, &PyItemStack_Type); obj->value = ptr; return reinterpret_cast(obj); diff --git a/mod/PyItemStack.h b/mod/PyItemStack.h deleted file mode 100644 index 1cbad45f..00000000 --- a/mod/PyItemStack.h +++ /dev/null @@ -1,5 +0,0 @@ -#pragma once -#include "CPython.h" - -extern PyTypeObject PyItemStack_Type; -PyObject* ToPyItemStack(class ItemStack* ptr); diff --git a/mod/PyUtils.cpp b/mod/PyUtils.cpp new file mode 100644 index 00000000..540b5e40 --- /dev/null +++ b/mod/PyUtils.cpp @@ -0,0 +1,90 @@ +#include "PyUtils.h" +#include "Common.h" + + +//打印错误信息 +void Py_PrintErrors() { + if (PyErr_Occurred()) { + PyErr_Print(); + } +} + +//PyObject转string +std::string PyObjectToStr(PyObject* obj) { + return PyUnicode_AsUTF8(PyObject_Repr(obj)); +} + +//PyObject转string +std::string PyUnicodeToStr(PyObject* obj) { + return PyUnicode_AsUTF8(obj); +} + +//list转vector +std::vector ToStrArray(PyObject* list) { + std::vector arr; + if (PyList_Check(list)) { + for (Py_ssize_t i = 0; i < PyList_Size(list); i++) { + arr.push_back(PyUnicode_AsUTF8(PyList_GetItem(list, i))); + } + } + return arr; +} + +PyObject* ToPyObject(PyObject* obj) { + return obj; +} + +PyObject* ToPyObject(std::string_view str) { + return PyUnicode_FromStringAndSize(str.data(), str.size()); +} + +//string转Unicode +PyObject* ToPyObject(const std::string& str) { + return PyUnicode_FromStringAndSize(str.data(), str.size()); +} + +PyObject* ToPyObject(const char* str) { + return PyUnicode_FromString(str); +} + +//Vec3转list +PyObject* ToPyObject(const Vec3& vec) { + PyObject* list = PyList_New(3); + PyList_SetItem(list, 0, PyFloat_FromDouble(vec.x)); + PyList_SetItem(list, 1, PyFloat_FromDouble(vec.y)); + PyList_SetItem(list, 2, PyFloat_FromDouble(vec.z)); + return list; +} + +//方块坐标转list +PyObject* ToPyObject(const BlockPos& bp) { + PyObject* list = PyList_New(3); + PyList_SetItem(list, 0, PyLong_FromLong(bp.x)); + PyList_SetItem(list, 1, PyLong_FromLong(bp.y)); + PyList_SetItem(list, 2, PyLong_FromLong(bp.z)); + return list; +} + +PyObject* ToPyObject(bool b) { + if (b) + Py_RETURN_TRUE; + else + Py_RETURN_FALSE; +} + +PyObject* ToPyObject(short s) { + return PyLong_FromLong(s); +} + +PyObject* ToPyObject(int i) { + return PyLong_FromLong(i); +} + +PyObject* ToPyObject(long long l) { + return PyLong_FromLongLong(l); +} + +PyObject* ToPyObject(double d) { + return PyFloat_FromDouble(d); +} + diff --git a/mod/CPython.h b/mod/PyUtils.h similarity index 51% rename from mod/CPython.h rename to mod/PyUtils.h index e1f4c93b..8c3a2d1b 100644 --- a/mod/CPython.h +++ b/mod/PyUtils.h @@ -1,7 +1,7 @@ #pragma once #define PY_SSIZE_T_CLEAN #include "../include/Python.h" -#include +#include "Common.h" #define Py_PARSE(format,...) if (!PyArg_ParseTuple(args, format ":" __FUNCTION__, __VA_ARGS__))return nullptr #define Py_KERWORDS_LIST(...) static const char* kwlist[]{ __VA_ARGS__,nullptr } @@ -28,23 +28,83 @@ // Py_END_ALLOW_THREADS;\ // if (!_has_gil)PyGILState_Release(_gil_state) +//打印错误信息 +void Py_PrintErrors(); +//PyObject转string +std::string PyObjectToStr(PyObject* obj); +//PyObject转string +std::string PyUnicodeToStr(PyObject* obj); +//list转vector +std::vector ToStrArray(PyObject* list); +//PyObject转PyObject +PyObject* ToPyObject(PyObject* obj); +//string转PyUnicode +PyObject* ToPyObject(std::string_view str); +//string转PyUnicode +PyObject* ToPyObject(const std::string& str); +//string转PyUnicode +PyObject* ToPyObject(const char* str); +//Vec3转list +PyObject* ToPyObject(const Vec3& vec); +//BlockPos转list +PyObject* ToPyObject(const BlockPos& bp); +//bool转PyObject +PyObject* ToPyObject(bool b); +//short转PyObject +PyObject* ToPyObject(short s); +//int转PyObject +PyObject* ToPyObject(int i); +//long long转PyObject +PyObject* ToPyObject(long long l); +//double转PyObject +PyObject* ToPyObject(double d); + +extern PyTypeObject PyBlockInstance_Type; +PyObject* ToPyObject(BlockInstance* ptr); +PyObject* ToPyObject(BlockInstance& bi); + +extern PyTypeObject PyEntity_Type; +PyObject* ToPyObject(Actor* ptr); + +extern PyTypeObject PyItemStack_Type; +PyObject* ToPyObject(ItemStack* ptr); + class PyGILGuard { public: - PyGILGuard(); - ~PyGILGuard(); + PyGILGuard() { + gil_ = PyGILState_Ensure(); + } + ~PyGILGuard() { + PyGILState_Release(gil_); + } private: PyGILState_STATE gil_; }; -std::string PyObjectToStr(PyObject* obj); -std::string PyUnicodeToStr(PyObject* obj); -//字符串转Unicode -PyObject* StrToPyUnicode(std::string_view str); -//list转vector -std::vector ToStrArray(PyObject* list); -//Vec3转list -PyObject* ToList(const Vec3& vec); -//方块坐标转list -PyObject* ToList(const BlockPos& bp); -//打印错误信息 -void Py_PrintErrors(); \ No newline at end of file +class PyCaller { +public: + PyCaller() { + } + ~PyCaller() { + Py_DECREF(result_); + } + PyObject* callVector(PyObject* func, const vector& args) { + return result_ = _PyObject_FastCall(func, args.data(), args.size()); + } + template + PyObject* call(PyObject* func, Args... args) { + vector vargs; + (vargs.push_back(ToPyObject(args)), ...); + callVector(func, vargs); + Py_PrintErrors(); + for (auto arg : vargs) { + Py_DECREF(arg); + } + return result_; + } + +private: + PyGILGuard gil_; + vector args_; + PyObject* result_; +}; diff --git a/mod/Tool.cpp b/mod/Tool.cpp deleted file mode 100644 index 064c8524..00000000 --- a/mod/Tool.cpp +++ /dev/null @@ -1,18 +0,0 @@ -#include "Tool.h" - -//字符串转JSON,本插件采用 https://json.nlohmann.me 的JSON库 -fifo_json CompoundTagToJson(std::string_view str) { - try { return fifo_json::parse(str); } - catch (const std::exception& e) { - logger.error("Parsing JSON failed! {}", e.what()); - return nullptr; - } -} - -bool IsPlayer(Actor* ptr) { - if (ptr == nullptr) - return false; - if (ptr->getEntityTypeId() != 319) - return false; - return true; -} diff --git a/mod/Version.h b/mod/Version.h index 5c64fba2..9d7c365f 100644 --- a/mod/Version.h +++ b/mod/Version.h @@ -1,5 +1,5 @@ #pragma once constexpr unsigned PYR_VERSION_MAJOR = 1; constexpr unsigned PYR_VERSION_MINOR = 9; -constexpr unsigned PYR_VERSION_MICRO = 5; -constexpr const char* PYR_VERSION = "v1.9.5"; \ No newline at end of file +constexpr unsigned PYR_VERSION_MICRO = 6; +constexpr const char* PYR_VERSION = "v1.9.6"; \ No newline at end of file