+// get_version()
+int ModApiUtil::l_get_version(lua_State *L)
+{
+ lua_createtable(L, 0, 3);
+ int table = lua_gettop(L);
+
+ lua_pushstring(L, PROJECT_NAME_C);
+ lua_setfield(L, table, "project");
+
+ lua_pushstring(L, g_version_string);
+ lua_setfield(L, table, "string");
+
+ if (strcmp(g_version_string, g_version_hash) != 0) {
+ lua_pushstring(L, g_version_hash);
+ lua_setfield(L, table, "hash");
+ }
+
+ return 1;
+}
+
+int ModApiUtil::l_sha1(lua_State *L)
+{
+ NO_MAP_LOCK_REQUIRED;
+ size_t size;
+ const char *data = luaL_checklstring(L, 1, &size);
+ bool hex = !lua_isboolean(L, 2) || !readParam<bool>(L, 2);
+
+ // Compute actual checksum of data
+ std::string data_sha1;
+ {
+ SHA1 ctx;
+ ctx.addBytes(data, size);
+ unsigned char *data_tmpdigest = ctx.getDigest();
+ data_sha1.assign((char*) data_tmpdigest, 20);
+ free(data_tmpdigest);
+ }
+
+ if (hex) {
+ std::string sha1_hex = hex_encode(data_sha1);
+ lua_pushstring(L, sha1_hex.c_str());
+ } else {
+ lua_pushlstring(L, data_sha1.data(), data_sha1.size());
+ }
+
+ return 1;
+}
+
+// colorspec_to_colorstring(colorspec)
+int ModApiUtil::l_colorspec_to_colorstring(lua_State *L)
+{
+ NO_MAP_LOCK_REQUIRED;
+
+ video::SColor color(0);
+ if (read_color(L, 1, &color)) {
+ char colorstring[10];
+ snprintf(colorstring, 10, "#%02X%02X%02X%02X",
+ color.getRed(), color.getGreen(), color.getBlue(), color.getAlpha());
+ lua_pushstring(L, colorstring);
+ return 1;
+ }
+
+ return 0;
+}
+
+// colorspec_to_bytes(colorspec)
+int ModApiUtil::l_colorspec_to_bytes(lua_State *L)
+{
+ NO_MAP_LOCK_REQUIRED;
+
+ video::SColor color(0);
+ if (read_color(L, 1, &color)) {
+ u8 colorbytes[4] = {
+ (u8) color.getRed(),
+ (u8) color.getGreen(),
+ (u8) color.getBlue(),
+ (u8) color.getAlpha(),
+ };
+ lua_pushlstring(L, (const char*) colorbytes, 4);
+ return 1;
+ }
+
+ return 0;
+}
+
+// encode_png(w, h, data, level)
+int ModApiUtil::l_encode_png(lua_State *L)
+{
+ NO_MAP_LOCK_REQUIRED;
+
+ // The args are already pre-validated on the lua side.
+ u32 width = readParam<int>(L, 1);
+ u32 height = readParam<int>(L, 2);
+ const char *data = luaL_checklstring(L, 3, NULL);
+ s32 compression = readParam<int>(L, 4);
+
+ std::string out = encodePNG((const u8*)data, width, height, compression);
+
+ lua_pushlstring(L, out.data(), out.size());
+ return 1;
+}
+
+// get_last_run_mod()
+int ModApiUtil::l_get_last_run_mod(lua_State *L)
+{
+ NO_MAP_LOCK_REQUIRED;
+
+ lua_rawgeti(L, LUA_REGISTRYINDEX, CUSTOM_RIDX_CURRENT_MOD_NAME);
+ std::string current_mod = readParam<std::string>(L, -1, "");
+ if (current_mod.empty()) {
+ lua_pop(L, 1);
+ lua_pushstring(L, getScriptApiBase(L)->getOrigin().c_str());
+ }
+ return 1;
+}
+
+// set_last_run_mod(modname)
+int ModApiUtil::l_set_last_run_mod(lua_State *L)
+{
+ NO_MAP_LOCK_REQUIRED;
+
+ const char *mod = luaL_checkstring(L, 1);
+ getScriptApiBase(L)->setOriginDirect(mod);
+ return 0;
+}