Add patch and first version of mod
parent
49bc6f209c
commit
24f0146f0d
|
@ -0,0 +1,151 @@
|
|||
commit bb973c7d07e6b901f86695935c6936adb24a393f
|
||||
Author: Pedro Gimeno <pgimeno@users.noreply.notabug.org>
|
||||
Date: Mon Apr 22 03:11:55 2019 +0200
|
||||
|
||||
Add FFI pointer and size retrieval and sanity check functions
|
||||
|
||||
diff --git a/src/mapnode.cpp b/src/mapnode.cpp
|
||||
index 9761a661..ce9e1bbd 100644
|
||||
--- a/src/mapnode.cpp
|
||||
+++ b/src/mapnode.cpp
|
||||
@@ -30,6 +30,7 @@ with this program; if not, write to the Free Software Foundation, Inc.,
|
||||
#include "util/numeric.h"
|
||||
#include <string>
|
||||
#include <sstream>
|
||||
+#include <cstddef>
|
||||
|
||||
static const Rotation wallmounted_to_rot[] = {
|
||||
ROTATE_0, ROTATE_180, ROTATE_90, ROTATE_270
|
||||
@@ -44,6 +45,18 @@ static const u8 rot_to_wallmounted[] = {
|
||||
MapNode
|
||||
*/
|
||||
|
||||
+#if USE_LUAJIT
|
||||
+
|
||||
+extern "C" int get_mapnode_version(void)
|
||||
+{
|
||||
+ if (sizeof(MapNode) == 4 && offsetof(MapNode, param0) == 0
|
||||
+ && offsetof(MapNode, param1) == 2 && offsetof(MapNode, param2) == 3)
|
||||
+ return 1;
|
||||
+ return 0;
|
||||
+}
|
||||
+
|
||||
+#endif
|
||||
+
|
||||
void MapNode::getColor(const ContentFeatures &f, video::SColor *color) const
|
||||
{
|
||||
if (f.palette) {
|
||||
diff --git a/src/script/lua_api/l_noise.cpp b/src/script/lua_api/l_noise.cpp
|
||||
index e38d319f..c1f2b710 100644
|
||||
--- a/src/script/lua_api/l_noise.cpp
|
||||
+++ b/src/script/lua_api/l_noise.cpp
|
||||
@@ -17,6 +17,7 @@ with this program; if not, write to the Free Software Foundation, Inc.,
|
||||
51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
*/
|
||||
|
||||
+#include "config.h"
|
||||
#include "lua_api/l_noise.h"
|
||||
#include "lua_api/l_internal.h"
|
||||
#include "common/c_converter.h"
|
||||
@@ -401,6 +402,53 @@ luaL_Reg LuaPerlinNoiseMap::methods[] = {
|
||||
{0,0}
|
||||
};
|
||||
|
||||
+#if USE_LUAJIT
|
||||
+
|
||||
+extern "C" {
|
||||
+
|
||||
+size_t PerlinNoiseMap_get_area(void **pnmp)
|
||||
+{
|
||||
+ NO_MAP_LOCK_REQUIRED;
|
||||
+
|
||||
+ if (pnmp == nullptr)
|
||||
+ throw ModError("Nil pointer in C call");
|
||||
+
|
||||
+ LuaPerlinNoiseMap *o = *(LuaPerlinNoiseMap **)pnmp;
|
||||
+
|
||||
+ Noise *n = o->getNoise();
|
||||
+
|
||||
+ return n->sx * n->sy;
|
||||
+}
|
||||
+
|
||||
+size_t PerlinNoiseMap_get_volume(void **pnmp)
|
||||
+{
|
||||
+ NO_MAP_LOCK_REQUIRED;
|
||||
+
|
||||
+ if (pnmp == nullptr)
|
||||
+ throw ModError("Nil pointer in C call");
|
||||
+
|
||||
+ LuaPerlinNoiseMap *o = *(LuaPerlinNoiseMap **)pnmp;
|
||||
+
|
||||
+ Noise *n = o->getNoise();
|
||||
+
|
||||
+ return n->sx * n->sy * n->sz;
|
||||
+}
|
||||
+
|
||||
+void PerlinNoiseMap_get_pointer(void **pnmp, void **ptr)
|
||||
+{
|
||||
+ NO_MAP_LOCK_REQUIRED;
|
||||
+
|
||||
+ if (pnmp == nullptr || ptr == nullptr)
|
||||
+ throw ModError("Nil pointer in C call");
|
||||
+
|
||||
+ LuaPerlinNoiseMap *o = *(LuaPerlinNoiseMap **)pnmp;
|
||||
+ *ptr = o->getNoise();
|
||||
+}
|
||||
+
|
||||
+} // extern "C"
|
||||
+
|
||||
+#endif // USE_LUAJIT
|
||||
+
|
||||
///////////////////////////////////////
|
||||
/*
|
||||
LuaPseudoRandom
|
||||
diff --git a/src/script/lua_api/l_noise.h b/src/script/lua_api/l_noise.h
|
||||
index 9f50dfd3..49a7ec6e 100644
|
||||
--- a/src/script/lua_api/l_noise.h
|
||||
+++ b/src/script/lua_api/l_noise.h
|
||||
@@ -91,6 +91,8 @@ class LuaPerlinNoiseMap : public ModApiBase
|
||||
static LuaPerlinNoiseMap *checkobject(lua_State *L, int narg);
|
||||
|
||||
static void Register(lua_State *L);
|
||||
+
|
||||
+ Noise *getNoise() const { return noise; }
|
||||
};
|
||||
|
||||
/*
|
||||
diff --git a/src/script/lua_api/l_vmanip.cpp b/src/script/lua_api/l_vmanip.cpp
|
||||
index c92983bd..2a205ff2 100644
|
||||
--- a/src/script/lua_api/l_vmanip.cpp
|
||||
+++ b/src/script/lua_api/l_vmanip.cpp
|
||||
@@ -30,6 +30,30 @@ with this program; if not, write to the Free Software Foundation, Inc.,
|
||||
#include "mapgen/mapgen.h"
|
||||
#include "voxelalgorithms.h"
|
||||
|
||||
+#if USE_LUAJIT
|
||||
+
|
||||
+extern "C" {
|
||||
+
|
||||
+void VoxelManip_get_pointer(void **lvmp, void **ptr)
|
||||
+{
|
||||
+ if (lvmp == nullptr || ptr == nullptr)
|
||||
+ throw ModError("Nil pointer in C call");
|
||||
+
|
||||
+ *ptr = (*(LuaVoxelManip **)lvmp)->vm->m_data;
|
||||
+}
|
||||
+
|
||||
+s32 VoxelManip_get_volume(void **lvmp)
|
||||
+{
|
||||
+ if (lvmp == nullptr)
|
||||
+ throw ModError("Nil pointer in C call");
|
||||
+
|
||||
+ return (*(LuaVoxelManip **)lvmp)->vm->m_area.getVolume();
|
||||
+}
|
||||
+
|
||||
+} // extern "C"
|
||||
+
|
||||
+#endif
|
||||
+
|
||||
// garbage collector
|
||||
int LuaVoxelManip::gc_object(lua_State *L)
|
||||
{
|
|
@ -0,0 +1,279 @@
|
|||
--[===================================================================[--
|
||||
ffi_accel - Mod for Minetest to accelerate handling of LuaVoxelManip
|
||||
and PerlinNoiseMap through the foreign function interface
|
||||
|
||||
Copyright © 2019 Pedro Gimeno Fortea. All rights reserved.
|
||||
|
||||
Permission is hereby granted to everyone to copy, modify, distribute
|
||||
and use this file, for any purpose, in whole or in part, free of
|
||||
charge, under the sole condition that the above copyright notice,
|
||||
together with this permission grant and the disclaimer below, are
|
||||
included in all copies of this software or of a substantial portion
|
||||
of it.
|
||||
|
||||
THIS SOFTWARE COMES WITHOUT ANY WARRANTY, EXPRESS OR IMPLIED.
|
||||
--]===================================================================]--
|
||||
|
||||
-- Based on an idea of EvidenceBKidsCode.
|
||||
-- This mod needs to apply a patch to the engine in order to work; see
|
||||
--
|
||||
|
||||
local modname = "Mod ffi_accel"
|
||||
|
||||
local err_prefix = modname .. " won't have any effect because "
|
||||
|
||||
local ie = minetest.request_insecure_environment()
|
||||
if not ie then
|
||||
minetest.log("warning", err_prefix .. "it's not declared in secure.trusted_mods")
|
||||
return
|
||||
end
|
||||
|
||||
local ok, ffi = pcall(ie.require, 'ffi')
|
||||
if not ok or not ffi then
|
||||
minetest.log("warning", err_prefix .. "FFI is not available in this system")
|
||||
return
|
||||
end
|
||||
|
||||
ffi.cdef[[
|
||||
typedef uint8_t u8;
|
||||
typedef uint16_t u16;
|
||||
typedef int32_t s32;
|
||||
typedef struct {
|
||||
u16 nodeid;
|
||||
u8 light;
|
||||
u8 param2;
|
||||
} MapNode;
|
||||
|
||||
int get_mapnode_version(void);
|
||||
void VoxelManip_get_pointer(void **lvmp, void **ptr);
|
||||
s32 VoxelManip_get_volume(void **lvmp);
|
||||
void PerlinNoiseMap_get_pointer(void **pnmp, void **ptr);
|
||||
size_t PerlinNoiseMap_get_area(void **pnmp);
|
||||
size_t PerlinNoiseMap_get_volume(void **pnmp);
|
||||
]]
|
||||
|
||||
local ffiC = ffi.C
|
||||
local ffinew = ffi.new
|
||||
local VoidPtrPtr = ffi.typeof('void*[1]')
|
||||
local MapNodePtr = ffi.typeof('MapNode *')
|
||||
|
||||
local mt_set_data, mt_set_light_data, mt_set_param2_data
|
||||
|
||||
if not pcall(function ()
|
||||
assert(ffiC.get_mapnode_version and ffiC.VoxelManip_get_pointer
|
||||
and ffiC.VoxelManip_get_volume and ffiC.PerlinNoiseMap_get_pointer)
|
||||
end)
|
||||
then
|
||||
minetest.log("warning", err_prefix .. "your Minetest executable has not been patched to support FFI")
|
||||
return
|
||||
end
|
||||
|
||||
if ffiC.get_mapnode_version() ~= 1 then
|
||||
minetest.log("warning", err_prefix .. "of incompatible map node structure")
|
||||
return
|
||||
end
|
||||
|
||||
|
||||
-- Table of pointers (keys are weak refs)
|
||||
local ptrtable = setmetatable({}, {__mode = 'k'})
|
||||
-- Table of sizes (keys are weak refs)
|
||||
local sizetable = setmetatable({}, {__mode = 'k'})
|
||||
|
||||
|
||||
-- Metamethod: get a value
|
||||
local function mm_get(t, idx)
|
||||
return idx >= 1 and idx <= sizetable[t] and ptrtable[t][idx - 1] or rawget(t, idx)
|
||||
end
|
||||
|
||||
|
||||
-- Metamethod: set a value
|
||||
local function mm_set(t, idx, value)
|
||||
if idx >= 1 and idx <= sizetable[t] then
|
||||
ptrtable[t][idx - 1] = value
|
||||
else
|
||||
rawset(t, idx, value)
|
||||
end
|
||||
end
|
||||
|
||||
-- Metamethod: get the nodeid of an index
|
||||
local function mm_get_nodeid(t, idx)
|
||||
return idx >= 1 and idx <= sizetable[t] and ptrtable[t][idx - 1].nodeid or rawget(t, idx)
|
||||
end
|
||||
|
||||
-- Metamethod: set the nodeid of an index to a value
|
||||
local function mm_set_nodeid(t, idx, value)
|
||||
if idx >= 1 and idx <= sizetable[t] then
|
||||
ptrtable[t][idx - 1].nodeid = value
|
||||
else
|
||||
rawset(t, idx, value)
|
||||
end
|
||||
end
|
||||
|
||||
-- Metamethod: get the light of an index
|
||||
local function mm_get_light(t, idx)
|
||||
return idx >= 1 and idx <= sizetable[t] and ptrtable[t][idx - 1].light or rawget(t, idx)
|
||||
end
|
||||
|
||||
-- Metamethod: set the light of an index to a value
|
||||
local function mm_set_light(t, idx, value)
|
||||
if idx >= 1 and idx <= sizetable[t] then
|
||||
ptrtable[t][idx - 1].light = value
|
||||
else
|
||||
rawset(t, idx, value)
|
||||
end
|
||||
end
|
||||
|
||||
-- Metamethod: get the param2 of an index
|
||||
local function mm_get_param2(t, idx)
|
||||
return idx >= 1 and idx <= sizetable[t] and ptrtable[t][idx - 1].param2 or rawget(t, idx)
|
||||
end
|
||||
|
||||
-- Metamethod: set the param2 of an index to a value
|
||||
local function mm_set_param2(t, idx, value)
|
||||
if idx >= 1 and idx <= sizetable[t] then
|
||||
ptrtable[t][idx - 1].param2 = value
|
||||
else
|
||||
rawset(t, idx, value)
|
||||
end
|
||||
end
|
||||
|
||||
|
||||
-- Metatables for VoxelManip nodeid, light and param2
|
||||
local VoxelManip_nodeid_mt = { __index = mm_get_nodeid, __newindex = mm_set_nodeid }
|
||||
local VoxelManip_light_mt = { __index = mm_get_light, __newindex = mm_set_light }
|
||||
local VoxelManip_param2_mt = { __index = mm_get_param2, __newindex = mm_set_param2 }
|
||||
|
||||
|
||||
-- Replacement VoxelManip.get_data and VoxelManip.set_data methods
|
||||
local function VoxelManip_get_data(self, buffer)
|
||||
-- Set up the metatable and pointer
|
||||
buffer = setmetatable(buffer or {}, VoxelManip_nodeid_mt)
|
||||
do
|
||||
local ptr = VoidPtrPtr()
|
||||
ffiC.VoxelManip_get_pointer(self, ptr)
|
||||
ptrtable[buffer] = MapNodePtr(ptr[0])
|
||||
end
|
||||
sizetable[buffer] = ffiC.VoxelManip_get_volume(self)
|
||||
return buffer
|
||||
end
|
||||
|
||||
local function VoxelManip_set_data(self, buffer)
|
||||
-- Call the original set_data method if the metatable is not
|
||||
-- the one we've set
|
||||
if getmetatable(buffer) ~= VoxelManip_nodeid_mt then
|
||||
mt_set_data(self, buffer)
|
||||
end
|
||||
end
|
||||
|
||||
|
||||
-- Replacement VoxelManip.get/set_light_data methods
|
||||
local function VoxelManip_get_light_data(self, buffer)
|
||||
-- Set up the metatable and pointer
|
||||
buffer = setmetatable(buffer or {}, VoxelManip_light_mt)
|
||||
do
|
||||
local ptr = VoidPtrPtr()
|
||||
ffiC.VoxelManip_get_pointer(self, ptr)
|
||||
ptrtable[buffer] = MapNodePtr(ptr[0])
|
||||
end
|
||||
sizetable[buffer] = ffiC.VoxelManip_get_volume(self)
|
||||
return buffer
|
||||
end
|
||||
|
||||
local function VoxelManip_set_light_data(self, buffer)
|
||||
-- Call the original set_light_data method if the metatable is not
|
||||
-- the one we've set
|
||||
if getmetatable(buffer) ~= VoxelManip_light_mt then
|
||||
mt_set_light_data(self, buffer)
|
||||
end
|
||||
end
|
||||
|
||||
|
||||
-- Replacement VoxelManip.get/set_param2_data methods
|
||||
local function VoxelManip_get_param2_data(self, buffer)
|
||||
-- Set up the metatable and pointer
|
||||
buffer = setmetatable(buffer or {}, VoxelManip_param2_mt)
|
||||
do
|
||||
local ptr = VoidPtrPtr()
|
||||
ffiC.VoxelManip_get_pointer(self, ptr)
|
||||
ptrtable[buffer] = MapNodePtr(ptr[0])
|
||||
end
|
||||
sizetable[buffer] = ffiC.VoxelManip_get_volume(self)
|
||||
return buffer
|
||||
end
|
||||
|
||||
local function VoxelManip_set_param2_data(self, buffer)
|
||||
-- Call the original set_param2_data method if the metatable is not
|
||||
-- the one we've set
|
||||
if getmetatable(buffer) ~= VoxelManip_param2_mt then
|
||||
mt_set_param2_data(self, buffer)
|
||||
end
|
||||
end
|
||||
|
||||
|
||||
-- Metatable for PerlinNoiseMap
|
||||
local PerlinNoiseMap_mt = { __index = mm_get }
|
||||
|
||||
-- Replacement methods for PerlinNoiseMap.*
|
||||
local function PerlinNoiseMap_get_2d_map_flat(self, pos, buffer)
|
||||
-- Calculate the noise
|
||||
self:calc_2d_map(pos)
|
||||
|
||||
-- Prepare the metatable for direct access to the data
|
||||
buffer = setmetatable(buffer or {}, PerlinNoiseMap_mt)
|
||||
do
|
||||
local ptr = VoidPtrPtr()
|
||||
ffiC.PerlinNoiseMap_get_pointer(self, ptr)
|
||||
ptrtable[buffer] = MapNodePtr(ptr[0])
|
||||
end
|
||||
sizetable[buffer] = ffiC.PerlinNoiseMap_get_area(self)
|
||||
return buffer
|
||||
end
|
||||
|
||||
local function PerlinNoiseMap_get_3d_map_flat(self, pos, buffer)
|
||||
-- Calculate the noise
|
||||
self:calc_3d_map(pos)
|
||||
|
||||
-- Prepare the metatable for direct access to the data
|
||||
buffer = setmetatable(buffer or {}, PerlinNoiseMap_mt)
|
||||
do
|
||||
local ptr = VoidPtrPtr()
|
||||
ffiC.PerlinNoiseMap_get_pointer(self, ptr)
|
||||
ptrtable[buffer] = MapNodePtr(ptr[0])
|
||||
end
|
||||
sizetable[buffer] = ffiC.PerlinNoiseMap_get_volume(self)
|
||||
return buffer
|
||||
end
|
||||
|
||||
--[[
|
||||
local function PerlinNoiseMap_get_map_slice(slice_offset, slice_size, buffer)
|
||||
-- TODO
|
||||
end
|
||||
--]]
|
||||
|
||||
-- Monkey-patch VoxelManip and PerlinNoiseMap
|
||||
minetest.after(0, function()
|
||||
-- VoxelManip buffer-intensive methods
|
||||
local mt = getmetatable(minetest.get_voxel_manip())
|
||||
mt.get_data = VoxelManip_get_data
|
||||
mt_set_data = mt.set_data
|
||||
mt.set_data = VoxelManip_set_data
|
||||
mt.get_light_data = VoxelManip_get_light_data
|
||||
mt_set_light_data = mt.set_light_data
|
||||
mt.set_light_data = VoxelManip_set_light_data
|
||||
mt.get_param2_data = VoxelManip_get_param2_data
|
||||
mt_set_param2_data = mt.set_param2_data
|
||||
mt.set_param2_data = VoxelManip_set_param2_data
|
||||
|
||||
-- PerlinNoiseMap buffer-intensive methods
|
||||
mt = getmetatable(minetest.get_perlin_map({spread = {x=100, y=100, z=100}}, {x=1, y=1, z=1}))
|
||||
mt.get_2d_map_flat = PerlinNoiseMap_get_2d_map_flat
|
||||
mt.get_3d_map_flat = PerlinNoiseMap_get_3d_map_flat
|
||||
-- mt.get_map_slice = PerlinNoiseMap_get_map_slice
|
||||
|
||||
-- Aliases
|
||||
mt.get2DMap_flat = mt.get_2d_map_flat
|
||||
mt.get3DMap_flat = mt.get_3d_map_flat
|
||||
-- mt.getMapSlice = mt.get_map_slice
|
||||
end)
|
||||
|
||||
minetest.log("action", modname .. " activated!")
|
Loading…
Reference in New Issue