#pragma once #include "APIHelp.h" #include #include #include #include #include class NativeFunction { public: // TypesEnum enum class Types : int { Void, Bool, Char, UnsignedChar, Short, UnsignedShort, Int, UnsignedInt, Long, UnsignedLong, LongLong, UnsignedLongLong, Float, Double, Pointer, }; template static Local getType() { return Number::newNumber((int)T); } // Data Members NativeFunction::Types mReturnVal = NativeFunction::Types::Void; vector mParams = {}; std::string mSymbol = "unknown"; void* mFunction = nullptr; // Dyncall Helper /* get dynamic call signature char for Type*/ static char getTypeSignature(NativeFunction::Types type); /* get NativeFunction::Type from LLVM Ast Node*/ static NativeFunction::Types getNativeType(llvm::ms_demangle::Node* type); /* get dynamic call signature string for this function*/ std::string buildDynCallbackSig(); // Script Helper /* get a script::Function instance for scripts to call*/ Local getCallableFunction(); /* call NativeFunction by using DynamicCallVM, internel api*/ static Local callNativeFunction(DCCallVM* vm, NativeFunction* funcSymbol, const Arguments& args); /* shared Hook Callback function that wrap script callback*/ static char nativeCallbackHandler(DCCallback* cb, DCArgs* args, DCValue* result, void* userdata); // Cache Helper static Concurrency::concurrent_unordered_map parsedSymbol; static NativeFunction getOrParse(const std::string& symbol); /* clone from other NativeFunction instance*/ inline void cloneFrom(const NativeFunction& i) { this->mReturnVal = i.mReturnVal; this->mParams = i.mParams; this->mSymbol = i.mSymbol; this->mFunction = i.mFunction; } }; class ScriptNativeFunction : public NativeFunction, public ScriptClass { public: explicit ScriptNativeFunction(const Local& scriptObj) : ScriptClass(scriptObj) { } explicit ScriptNativeFunction(const Local& scriptObj, const NativeFunction& symbol) : NativeFunction(symbol), ScriptClass(scriptObj) { } /* create NativeFunction instance from mangled symbol * dlsym will be called to query the address * > NativeFunction.fromSymbol(string"?xxx@xxx") */ static Local fromSymbol(const Arguments& args); /* create NativeFunction by describe the arguments * you should set address manually before you call or hook it * > NativeFunction.fromDescribe(RetuenValue: NativeTypes.Void, Params: [NativeType.Int......]) */ static Local fromDescription(const Arguments& args); /* create NativeFunction that wrap Script Function by describe the arguments * > NativeFunction.fromScript(RetuenValue: NativeTypes.Void, Params: [NativeType.Int......], Callback: func(Params...){}) */ static Local fromScript(const Arguments& args); Local setAddress(const Local& value); Local getAddress(); /* Hook current NativeFunction by passing a fuction * > NativeFunction.hook(CallBack: func(a1,a2,a3...){}) */ Local hook(const Arguments& args); }; class DynamicHookData : public ScriptNativeFunction { public: script::ScriptEngine* mEngine = nullptr; DCCallback* mNativeCallack = nullptr; script::Global mScriptCallback; explicit DynamicHookData(const Local& scriptObj) : ScriptNativeFunction(scriptObj) { } explicit DynamicHookData(const Local& scriptObj, const NativeFunction& symbol) : ScriptNativeFunction(scriptObj, symbol) { } }; class NativePointer : public ScriptClass { private: void* mPtr; public: explicit NativePointer(void*); static void* extract(Local v); static Local newNativePointer(void*); void* wrap() { return dAccess(this, 0); } void* unwrap() { return (void*)&(*((int*)mPtr)); } void* get() { return mPtr; } void set(void* ptr) { mPtr = ptr; }; static Local fromAddress(const Arguments& args); static Local fromSymbol(const Arguments& args); static Local mallocMem(const Arguments& args); static Local freeMem(const Arguments& args); Local asRawAddress(const Arguments& args); Local asHexAddress(const Arguments& args); Local offset(const Arguments& args); Local isNull(const Arguments& args); Local asRef(const Arguments& args); Local deRef(const Arguments& args); void setMemByte(const Local& value); void setChar(const Local& value); void setUchar(const Local& value); void setShort(const Local& value); void setUshort(const Local& value); void setInt(const Local& value); void setUint(const Local& value); void setLong(const Local& value); void setUlong(const Local& value); void setLonglong(const Local& value); void setUlonglong(const Local& value); void setFloat(const Local& value); void setDouble(const Local& value); void setString(const Local& value); void setBool(const Local& value); Local getMemByte(); Local getChar(); Local getUchar(); Local getShort(); Local getUshort(); Local getInt(); Local getUint(); Local getLong(); Local getUlong(); Local getLonglong(); Local getUlonglong(); Local getFloat(); Local getDouble(); Local getString(); Local getBool(); Local asStdString(); }; class NativePatch : public ScriptClass { public: explicit NativePatch(const Local& scriptObj) : ScriptClass(scriptObj) { } static Local search(const Arguments& args); static Local patch(const Arguments& args); static Local dump(const Arguments& args); }; class GlobalNativePointer : public ScriptClass { public: explicit GlobalNativePointer(const Local& scriptObj) : ScriptClass(scriptObj) { } static Local getLevelPtr(const Arguments& args); static Local getMinecraftPtr(const Arguments& args); static Local getServerNetworkHandlerPtr(const Arguments& args); static Local getMinecraftCommandsPtr(const Arguments& args); static Local getLevelStoragePtr(const Arguments& args); static Local getDBStoragePtr(const Arguments& args); static Local getRakNetServerLocatorPtr(const Arguments& args); static Local getRakNetRakPeerPtr(const Arguments& args); static Local getScoreboardPtr(const Arguments& args); static Local getAllowListFilePtr(const Arguments& args); static Local getPropertiesSettingsPtr(const Arguments& args); }; // export apis extern ClassDefine NativeTypeEnumBuilder; extern ClassDefine NativeCallBuilder; extern ClassDefine NativeHookBuilder; extern ClassDefine NativePointerBuilder; extern ClassDefine NativePatchBuilder; extern ClassDefine GlobalNativePointerBuilder;