客户端修改
之前发现 Minetest 的引擎代码是和 easyrpg 一样是 cpp,那么也就意味着它也同样有机会可以使用 emscripten 编译到浏览器中运行。
网上搜了一圈,发现还真有人已经做了这件事。。。
https://blog.minetest.net/2022/03/27/March/
那么现在转账命令就非常容易实现了,可以先写在 js 里,然后直接调用对应的 js 方法即可。
不考虑安全问题。。我们先做一个简易且泛用的实作。。用邪恶的 Dr.Eval 大法,执行任何脚本。。。
void escape_EM_ASM(const std::wstring &message) {
std::wstring m = translate_string(message);
std::string s(m.length(), 0);
std::transform(m.begin(), m.end(), s.begin(), [] (wchar_t c) {
return (char)c;
});
MAIN_THREAD_ASYNC_EM_ASM(console.log("Msg: " + UTF8ToString($0)), s.c_str());
std::string c;
c = ".EM_ASM ";
if (s.find(c) != std::string::npos) {
s = s.substr(s.find(c) + c.size());
MAIN_THREAD_ASYNC_EM_ASM(eval(UTF8ToString($0)), s.c_str());
return;
}
}
注意这里我踩了一个坑。。。https://github.com/paradust7/minetest-wasm/issues/3
简单来说就是最好用这个命令。。MAIN_THREAD_ASYNC_EM_ASM。。。
上面的代码如果换成 EM_ASM,那么发消息的时候用这个还是能 trigger 里面的 js 代码,
但是如果经过一次服务器收到消息的时候进行解析就无效了,而模组里的 minetest.chat_send_player(name, text) API 是会经过一次服务器的。
模组修改
模组第一个要求就是我们需要有一个动作能够 trigger 右击玩家这个事件。。。on_rightclick 什么的。。
搜了一圈发现没有现成的 API。。。
但是有一个现成的 mod 里有这个功能。。。所以我们从那个模组开始入手。。。
首先添加 right_click 的事件,我们创建一个菜单。。。
https://rubenwardy.com/minetest_modding_book/en/players/formspecs.html
minetest.register_on_rightclickplayer(function(player, clicker)
local s = clicker:get_player_name()
local t = player:get_player_name()
local controls = clicker:get_player_control()
if not(check_distance(clicker, player)) then
minetest.chat_send_player(s, S("Target too far."))
return
end
local context = get_context(s)
context.target = t
local formspec = {
"formspec_version[4]",
"size[4.5,5.25]",
"label[0.375,0.5;", minetest.formspec_escape("This is " .. t .. "."), "]",
"button_exit[0.5,1;3.5,0.8;profile;Profile]",
"button_exit[0.5,2;3.5,0.8;transfer;Transfer]",
"button_exit[0.5,3;3.5,0.8;follow;Follow]",
"button_exit[0.5,4;3.5,0.8;cancel;Cancel]"
}
minetest.show_formspec(s, "player:interact", table.concat(formspec, ""))
end)
上面的代码里我们开了一个状态 context.target 用来记录当前交互的对象。。
然后再处理菜单的回执即可。。。
minetest.register_on_player_receive_fields(function(player, formname, fields)
if formname == "player:interact" then
local s = player:get_player_name()
local t = get_context(s).target
if fields.profile then
minetest.chat_send_player(s, ".EM_ASM window.open(\"https://" .. t .. ".test.w3itch.io/zh-CN\", \"new\")")
end
if fields.transfer then
minetest.chat_send_player(s, ".EM_ASM alert(feature not implement yet...)")
end
if fields.follow then
minetest.chat_send_player(s, ".EM_ASM alert(feature not implement yet...)")
end
return true
end
end)





Alca
Amber
Belleve Invis
Chensiting123
Edward_mj
Fotile96
Hlworld
Kuangbin
Liyaos
Lwins
LYPenny
Mato 完整版
Mikeni2006
Mzry
Nagatsuki
Neko13
Oneplus
Rukata
Seter
Sevenkplus
Sevenzero
Shirleycrow
Vfleaking
wangzhpp
Watashi
WJMZBMR
Wywcgs
XadillaX
Yangzhe
三途川玉子
About.me
Vijos
