1- #include " api/APIHelp.h"
1+ #include " RemoteCallAPI.h"
2+
3+ #include " api/BaseAPI.h"
4+ #include " api/BlockAPI.h"
5+ #include " api/BlockEntityAPI.h"
6+ #include " api/ContainerAPI.h"
7+ #include " api/EntityAPI.h"
8+ #include " api/ItemAPI.h"
29#include " api/LlAPI.h"
10+ #include " api/NbtAPI.h"
11+ #include " api/PlayerAPI.h"
312#include " engine/GlobalShareData.h"
413#include " engine/MessageSystem.h"
14+ #include " legacyapi/remotecall/RemoteCallAPI.h"
515#include " ll/api/service/ServerInfo.h"
616
17+ #include < map>
718#include < process.h>
19+ #include < sstream>
820#include < string>
921
1022#define DEFAULT_REMOTE_CALL_NAME_SPACE " LLSEGlobal"
23+ #define logger lse::getSelfPluginInstance ().getLogger()
24+
25+ // ////////////////// Remote Call ////////////////////
26+
27+ RemoteCall::ValueType pack(Local<Value> value);
28+ RemoteCall::ValueType pack (Local<Object> value) {
29+ // Player*, Actor*, ItemStack*, Block*, BlockActor*, Container*, Vec3, BlockPos, CompoundTag*
30+ if (IsInstanceOf<PlayerClass>(value)) return PlayerClass::extract (value);
31+ if (IsInstanceOf<EntityClass>(value)) return EntityClass::extract (value);
32+ if (IsInstanceOf<ItemClass>(value)) return ItemClass::extract (value);
33+ if (IsInstanceOf<BlockClass>(value)) {
34+ auto block = EngineScope::currentEngine ()->getNativeInstance <BlockClass>(value);
35+ return block->get ();
36+ }
37+ if (IsInstanceOf<BlockEntityClass>(value)) return BlockEntityClass::extract (value);
38+ if (IsInstanceOf<ContainerClass>(value)) return ContainerClass::extract (value);
39+ if (IsInstanceOf<FloatPos>(value)) {
40+ auto pos = FloatPos::extractPos (value);
41+ return std::make_pair (pos->getVec3 (), pos->getDimensionId ());
42+ }
43+ if (IsInstanceOf<IntPos>(value)) {
44+ auto pos = IntPos::extractPos (value);
45+ return std::make_pair (pos->getBlockPos (), pos->getDimensionId ());
46+ }
47+ if (IsInstanceOf<NbtCompoundClass>(value)) return NbtCompoundClass::extract (value);
48+ std::unordered_map<std::string, RemoteCall::ValueType> result;
49+ for (auto & k : value.getKeyNames ()) result.emplace (k, pack (value.get (k)));
50+ return std::move (result);
51+ }
52+ RemoteCall::ValueType pack (Local<Array> value) {
53+ std::vector<RemoteCall::ValueType> result;
54+ for (size_t index = 0ULL , mEnd = value.size (); index < mEnd ; ++index) {
55+ result.push_back (pack (value.get (index)));
56+ }
57+ return std::move (result);
58+ }
59+
60+ RemoteCall::ValueType pack (Local<Value> value) {
61+ switch (value.getKind ()) {
62+ case script::ValueKind::kNull :
63+ return nullptr ;
64+ break ;
65+ case script::ValueKind::kObject :
66+ return pack (value.asObject ());
67+ break ;
68+ case script::ValueKind::kString :
69+ return value.toStr ();
70+ break ;
71+ case script::ValueKind::kNumber : {
72+ auto num = value.asNumber ();
73+ return RemoteCall::NumberType (num.toInt64 (), num.toDouble ());
74+ break ;
75+ }
76+ case script::ValueKind::kBoolean :
77+ return value.asBoolean ().value ();
78+ break ;
79+ case script::ValueKind::kFunction :
80+ throw std::exception (fmt::format (__FUNCTION__ " - Unsupported Type: kFunction" ).c_str ());
81+ break ;
82+ case script::ValueKind::kArray :
83+ return pack (value.asArray ());
84+ break ;
85+ case script::ValueKind::kByteBuffer :
86+ throw std::exception (fmt::format (__FUNCTION__ " - Unsupported Type: kByteBuffer" ).c_str ());
87+ return value.asByteBuffer ().describeUtf8 ();
88+ break ;
89+ case script::ValueKind::kUnsupported :
90+ throw std::exception (fmt::format (__FUNCTION__ " - Unsupported Type: kUnsupported" ).c_str ());
91+ break ;
92+ default :
93+ throw std::exception (fmt::format (__FUNCTION__ " - Unsupported Type: Unknown" ).c_str ());
94+ break ;
95+ }
96+ return RemoteCall::ValueType ();
97+ }
98+
99+ // Player*, Actor*, ItemStack*, Block*, BlockActor*, Container*, Vec3, BlockPos, CompoundTag*
100+ Local<Value> _extractValue (bool v) { return Boolean::newBoolean (v); };
101+ Local<Value> _extractValue (std::string v) { return String::newString (v); };
102+ Local<Value> _extractValue (std::nullptr_t v) { return Local<Value>(); };
103+ Local<Value> _extractValue (std::string* v) { return Local<Value>(); };
104+ Local<Value> _extractValue (Player* v) { return PlayerClass::newPlayer (v); };
105+ Local<Value> _extractValue (Actor* v) { return EntityClass::newEntity (v); };
106+ Local<Value> _extractValue (Block* v) { return BlockClass::newBlock (v, &BlockPos::ZERO, -1 ); };
107+ Local<Value> _extractValue (BlockActor* const & v) { return BlockEntityClass::newBlockEntity (v, -1 ); };
108+ Local<Value> _extractValue (Container* v) { return ContainerClass::newContainer (v); };
109+ Local<Value> _extractValue (RemoteCall::WorldPosType v) { return FloatPos::newPos (v.pos , v.dimId ); };
110+ Local<Value> _extractValue (RemoteCall::BlockPosType v) { return IntPos::newPos (v.pos , v.dimId ); };
111+ Local<Value> _extractValue (RemoteCall::BlockType v) {
112+ return BlockClass::newBlock (v.get <Block const *>(), &v.blockPos , v.dimension );
113+ };
114+ Local<Value> _extractValue (RemoteCall::NumberType v) { return Number::newNumber (v.get <double >()); };
115+ Local<Value> _extractValue (RemoteCall::ItemType&& v) {
116+ if (v.own ) return ItemClass::newItem (v.tryGetUniquePtr ().release (), false );
117+ else return ItemClass::newItem (const_cast <ItemStack*>(v.ptr ), false );
118+ };
119+ Local<Value> _extractValue (RemoteCall::NbtType&& v) {
120+ if (v.own ) return NbtCompoundClass::pack (v.tryGetUniquePtr ());
121+ else return NbtCompoundClass::pack (const_cast <CompoundTag*>(v.ptr ), false );
122+ };
123+
124+ Local<Value> extract (RemoteCall::ValueType&& val);
125+
126+ Local<Value> extractValue (RemoteCall::Value&& val) {
127+ static_assert (std::variant_size_v<RemoteCall::Value> == 13 );
128+ switch (val.index ()) {
129+ #define Extra (index ) \
130+ case index: \
131+ return _extractValue (std::move (std::get<index>(val)));
132+ Extra (0 );
133+ Extra (1 );
134+ Extra (2 );
135+ Extra (3 );
136+ Extra (4 );
137+ Extra (5 );
138+ Extra (6 );
139+ Extra (7 );
140+ Extra (8 );
141+ Extra (9 );
142+ Extra (10 );
143+ Extra (11 );
144+ Extra (12 );
145+ default :
146+ throw std::exception (" Unsupported Type!" );
147+ break ;
148+ }
149+ };
150+ Local<Value> extractValue (std::vector<RemoteCall::ValueType>&& val) {
151+ auto arr = Array::newArray ();
152+ for (auto & v : val) arr.add (extract (std::move (v)));
153+ return arr;
154+ };
155+ Local<Value> extractValue (std::unordered_map<std::string, RemoteCall::ValueType>&& val) {
156+ auto obj = Object::newObject ();
157+ for (auto & [k, v] : val) {
158+ obj.set (k, extract (std::move (v)));
159+ }
160+ return obj;
161+ };
162+
163+ Local<Value> extract (RemoteCall::ValueType&& val) {
164+ static_assert (std::variant_size_v<RemoteCall::ValueType::Type> == 3 );
165+ switch (val.value .index ()) {
166+ case 0 :
167+ return extractValue (std::move (std::get<0 >(val.value )));
168+ case 1 :
169+ return extractValue (std::move (std::get<1 >(val.value )));
170+ case 2 :
171+ return extractValue (std::move (std::get<2 >(val.value )));
172+ default :
173+ throw std::exception (" Unsupported Type" );
174+ return Local<Value>();
175+ break ;
176+ }
177+ }
11178
12179Local<Value> MakeRemoteCall (const string& nameSpace, const string& funcName, const Arguments& args) {
13- auto data = globalShareData->exportedFuncs .find (nameSpace + " :" + funcName);
14- if (data == globalShareData->exportedFuncs .end ()) {
15- lse::getSelfPluginInstance ().getLogger ().error (
16- " Fail to import! Function [{}::{}] has not been exported!" ,
17- nameSpace,
18- funcName
19- );
20- lse::getSelfPluginInstance ().getLogger ().error (" In plugin <{}>" , ENGINE_OWN_DATA ()->pluginName );
180+ auto & func = RemoteCall::importFunc (nameSpace, funcName);
181+ if (!func) {
182+ logger.error (" Fail to import! Function [{}::{}] has not been exported!" , nameSpace, funcName);
183+ logger.error (" In plugin <{}>" , ENGINE_OWN_DATA ()->pluginName );
21184 return Local<Value>();
22185 }
23186
24- std::vector<std::string > params;
187+ std::vector<RemoteCall::ValueType > params;
25188 for (int i = 0 ; i < args.size (); ++i) {
26- params.emplace_back (ValueToJson (args[i]));
189+ params.emplace_back (pack (args[i]));
27190 }
28- return JsonToValue (data-> second . callback (std::move (params)));
191+ return extract ( func (std::move (params)));
29192}
30193
31194bool LLSEExportFunc (
@@ -34,35 +197,52 @@ bool LLSEExportFunc(
34197 const string& nameSpace,
35198 const string& funcName
36199) {
37- std::string exportName = nameSpace + " :" + funcName;
38- ExportedFuncData* funcData = &(globalShareData->exportedFuncs )[exportName];
39- if (funcData->engine ) return false ;
40- funcData->engine = engine;
41- funcData->func = script::Global<Function>(func);
42- funcData->fromEngineType = LLSE_MODULE_TYPE;
43- funcData->callback = [exportName](std::vector<std::string> params) -> std::string {
44- auto data = globalShareData->exportedFuncs .find (exportName);
45- if (data == globalShareData->exportedFuncs .end ()) {
46- lse::getSelfPluginInstance ().getLogger ().error (" Exported function \" {}\" not found" , exportName);
47- return " " ;
48- }
49- auto engine = data->second .engine ;
50- if ((ll::getServerStatus () != ll::ServerStatus::Running) || !EngineManager::isValid (engine)
200+ // Putting script::Global value into lambda capture list may cause crash
201+ // script::Global<Function> callback = script::Global<Function>(func);
202+ std::string identifier = nameSpace + " ::" + funcName;
203+ RemoteCall::CallbackFn cb = [engine, identifier /* , scriptCallback = std::move(callback)*/ ](
204+ std::vector<RemoteCall::ValueType> params
205+ ) -> RemoteCall::ValueType {
206+ if (ll::getServerStatus () != ll::ServerStatus::Stopping || !EngineManager::isValid (engine)
51207 || engine->isDestroying ())
52208 return " " ;
53- EngineScope enter (data->second .engine );
54- std::vector<script::Local<Value>> scriptParams;
55- for (auto & param : params) {
56- scriptParams.emplace_back (JsonToValue (param));
209+ EngineScope enter (engine);
210+ try {
211+ auto iter = ENGINE_GET_DATA (engine)->exportFuncs .find (identifier);
212+ if (iter == ENGINE_GET_DATA (engine)->exportFuncs .end ()) {
213+ logger.debug (" " );
214+ return " " ;
215+ }
216+ auto scriptCallback = iter->second .callback .get ();
217+ std::vector<script::Local<Value>> scriptParams;
218+ for (auto & param : params) {
219+ scriptParams.emplace_back (extract (std::move (param)));
220+ }
221+ return pack (scriptCallback.call ({}, scriptParams));
57222 }
58- return ValueToJson (data->second .func .get ().call ({}, scriptParams));
223+ CATCH_WITHOUT_RETURN (" Fail in Remote Call" );
224+ return " " ;
59225 };
60- return true ;
226+ if (RemoteCall::exportFunc (nameSpace, funcName, std::move (cb))) {
227+ ENGINE_GET_DATA (engine)->exportFuncs .emplace (
228+ identifier,
229+ RemoteCallData{nameSpace, funcName, script::Global<Function>(func)}
230+ );
231+ return true ;
232+ }
233+ return false ;
61234}
62235
63236bool LLSERemoveAllExportedFuncs (ScriptEngine* engine) {
64- globalShareData->exportedFuncs .clear ();
65- return true ;
237+ // enter scope to prevent crash in script::Global::~Global()
238+ EngineScope enter (engine);
239+ std::vector<std::pair<std::string, std::string>> funcs;
240+ for (auto & [key, data] : ENGINE_GET_DATA (engine)->exportFuncs ) {
241+ funcs.emplace_back (data.nameSpace , data.funcName );
242+ }
243+ int count = RemoteCall::removeFuncs (std::move (funcs));
244+ ENGINE_GET_DATA (engine)->exportFuncs .clear ();
245+ return count;
66246}
67247
68248// ////////////////// APIs ////////////////////
@@ -130,9 +310,8 @@ Local<Value> LlClass::hasFuncExported(const Arguments& args) {
130310 funcName = args[0 ].toStr ();
131311 }
132312
133- return Boolean::newBoolean (
134- globalShareData->exportedFuncs .find (nameSpace + " :" + funcName) != globalShareData->exportedFuncs .end ()
135- );
313+ // 远程调用
314+ return Boolean::newBoolean (RemoteCall::hasFunc (nameSpace, funcName));
136315 }
137316 CATCH (" Fail in LLSEHasExported!" )
138317}
0 commit comments