Noise: Create a deep copy of NoiseParams
authorkwolekr <kwolekr@minetest.net>
Wed, 10 Dec 2014 05:37:09 +0000 (00:37 -0500)
committerkwolekr <kwolekr@minetest.net>
Wed, 10 Dec 2014 05:37:09 +0000 (00:37 -0500)
src/mapgen_v5.cpp
src/mapgen_v6.cpp
src/mapgen_v7.cpp
src/mg_ore.cpp
src/mg_ore.h
src/noise.cpp
src/noise.h
src/script/lua_api/l_mapgen.cpp
src/script/lua_api/l_noise.cpp

index 04e9d8c9513f0dcbfdc4c94f782104bc942237cf..f2cb7917904693f61dd4dbfe83daf2fe45bd8418 100644 (file)
@@ -187,12 +187,12 @@ void MapgenV5Params::writeParams(Settings *settings) {
 int MapgenV5::getGroundLevelAtPoint(v2s16 p) {
        //TimeTaker t("getGroundLevelAtPoint", NULL, PRECISION_MICRO);
 
-       float f = 0.55 + NoisePerlin2D(noise_factor->np, p.X, p.Y, seed);
+       float f = 0.55 + NoisePerlin2D(&noise_factor->np, p.X, p.Y, seed);
        if(f < 0.01)
                f = 0.01;
        else if(f >= 1.0)
                f *= 1.6;
-       float h = water_level + NoisePerlin2D(noise_height->np, p.X, p.Y, seed);
+       float h = water_level + NoisePerlin2D(&noise_height->np, p.X, p.Y, seed);
 
        s16 search_top = water_level + 15;
        s16 search_base = water_level;
@@ -202,7 +202,7 @@ int MapgenV5::getGroundLevelAtPoint(v2s16 p) {
 
        s16 level = -31000;
        for (s16 y = search_top; y >= search_base; y--) {
-               float n_ground = NoisePerlin3DEased(noise_ground->np, p.X, y, p.Y, seed);
+               float n_ground = NoisePerlin3DEased(&noise_ground->np, p.X, y, p.Y, seed);
                if(n_ground * f > y - h) {
                        if(y >= search_top - 7)
                                break;
index b8474cb53b73e4272e710ec5119921de6e16ea78..04c3b147eed8cfe00c9cce346216348b25c22105 100644 (file)
@@ -246,13 +246,13 @@ float MapgenV6::baseTerrainLevelFromNoise(v2s16 p) {
        if (flags & MG_FLAT)
                return water_level;
 
-       float terrain_base   = NoisePerlin2DPosOffset(noise_terrain_base->np,
+       float terrain_base   = NoisePerlin2DPosOffset(&noise_terrain_base->np,
                                                        p.X, 0.5, p.Y, 0.5, seed);
-       float terrain_higher = NoisePerlin2DPosOffset(noise_terrain_higher->np,
+       float terrain_higher = NoisePerlin2DPosOffset(&noise_terrain_higher->np,
                                                        p.X, 0.5, p.Y, 0.5, seed);
-       float steepness      = NoisePerlin2DPosOffset(noise_steepness->np,
+       float steepness      = NoisePerlin2DPosOffset(&noise_steepness->np,
                                                        p.X, 0.5, p.Y, 0.5, seed);
-       float height_select  = NoisePerlin2DNoTxfmPosOffset(noise_height_select->np,
+       float height_select  = NoisePerlin2DNoTxfmPosOffset(&noise_height_select->np,
                                                        p.X, 0.5, p.Y, 0.5, seed);
 
        return baseTerrainLevel(terrain_base, terrain_higher,
@@ -550,37 +550,37 @@ void MapgenV6::calculateNoise() {
        // Need to adjust for the original implementation's +.5 offset...
        if (!(flags & MG_FLAT)) {
                noise_terrain_base->perlinMap2D(
-                       x + 0.5 * noise_terrain_base->np->spread.X,
-                       z + 0.5 * noise_terrain_base->np->spread.Z);
+                       x + 0.5 * noise_terrain_base->np.spread.X,
+                       z + 0.5 * noise_terrain_base->np.spread.Z);
                noise_terrain_base->transformNoiseMap();
 
                noise_terrain_higher->perlinMap2D(
-                       x + 0.5 * noise_terrain_higher->np->spread.X,
-                       z + 0.5 * noise_terrain_higher->np->spread.Z);
+                       x + 0.5 * noise_terrain_higher->np.spread.X,
+                       z + 0.5 * noise_terrain_higher->np.spread.Z);
                noise_terrain_higher->transformNoiseMap();
 
                noise_steepness->perlinMap2D(
-                       x + 0.5 * noise_steepness->np->spread.X,
-                       z + 0.5 * noise_steepness->np->spread.Z);
+                       x + 0.5 * noise_steepness->np.spread.X,
+                       z + 0.5 * noise_steepness->np.spread.Z);
                noise_steepness->transformNoiseMap();
 
                noise_height_select->perlinMap2D(
-                       x + 0.5 * noise_height_select->np->spread.X,
-                       z + 0.5 * noise_height_select->np->spread.Z);
+                       x + 0.5 * noise_height_select->np.spread.X,
+                       z + 0.5 * noise_height_select->np.spread.Z);
 
                noise_mud->perlinMap2D(
-                       x + 0.5 * noise_mud->np->spread.X,
-                       z + 0.5 * noise_mud->np->spread.Z);
+                       x + 0.5 * noise_mud->np.spread.X,
+                       z + 0.5 * noise_mud->np.spread.Z);
                noise_mud->transformNoiseMap();
        }
 
        noise_beach->perlinMap2D(
-               x + 0.2 * noise_beach->np->spread.X,
-               z + 0.7 * noise_beach->np->spread.Z);
+               x + 0.2 * noise_beach->np.spread.X,
+               z + 0.7 * noise_beach->np.spread.Z);
 
        noise_biome->perlinMap2D(
-               x + 0.6 * noise_biome->np->spread.X,
-               z + 0.2 * noise_biome->np->spread.Z);
+               x + 0.6 * noise_biome->np.spread.X,
+               z + 0.2 * noise_biome->np.spread.Z);
 }
 
 
index 739efadd8c0137895e6505c756ce51f2e72ad917..be60a2c98ff3ccf73bdc7ec320268c645b2da782 100644 (file)
@@ -173,7 +173,7 @@ int MapgenV7::getGroundLevelAtPoint(v2s16 p) {
 
        // Ridge/river terrain calculation
        float width = 0.3;
-       float uwatern = NoisePerlin2DNoTxfm(noise_ridge_uwater->np, p.X, p.Y, seed) * 2;
+       float uwatern = NoisePerlin2DNoTxfm(&noise_ridge_uwater->np, p.X, p.Y, seed) * 2;
        // actually computing the depth of the ridge is much more expensive;
        // if inside a river, simply guess
        if (uwatern >= -width && uwatern <= width)
@@ -305,8 +305,8 @@ void MapgenV7::calculateNoise() {
 
 
 Biome *MapgenV7::getBiomeAtPoint(v3s16 p) {
-       float heat      = NoisePerlin2D(noise_heat->np, p.X, p.Z, seed);
-       float humidity  = NoisePerlin2D(noise_humidity->np, p.X, p.Z, seed);
+       float heat      = NoisePerlin2D(&noise_heat->np, p.X, p.Z, seed);
+       float humidity  = NoisePerlin2D(&noise_humidity->np, p.X, p.Z, seed);
        s16 groundlevel = baseTerrainLevelAtPoint(p.X, p.Z);
 
        return bmgr->getBiome(heat, humidity, groundlevel);
@@ -314,17 +314,17 @@ Biome *MapgenV7::getBiomeAtPoint(v3s16 p) {
 
 //needs to be updated
 float MapgenV7::baseTerrainLevelAtPoint(int x, int z) {
-       float hselect = NoisePerlin2D(noise_height_select->np, x, z, seed);
+       float hselect = NoisePerlin2D(&noise_height_select->np, x, z, seed);
        hselect = rangelim(hselect, 0.0, 1.0);
 
-       float persist = NoisePerlin2D(noise_terrain_persist->np, x, z, seed);
+       float persist = NoisePerlin2D(&noise_terrain_persist->np, x, z, seed);
        persist = rangelim(persist, 0.4, 0.9);
 
-       noise_terrain_base->np->persist = persist;
-       float height_base = NoisePerlin2D(noise_terrain_base->np, x, z, seed);
+       noise_terrain_base->np.persist = persist;
+       float height_base = NoisePerlin2D(&noise_terrain_base->np, x, z, seed);
 
-       noise_terrain_alt->np->persist = persist;
-       float height_alt = NoisePerlin2D(noise_terrain_alt->np, x, z, seed);
+       noise_terrain_alt->np.persist = persist;
+       float height_alt = NoisePerlin2D(&noise_terrain_alt->np, x, z, seed);
 
        if (height_alt > height_base)
                return height_alt;
@@ -346,9 +346,9 @@ float MapgenV7::baseTerrainLevelFromMap(int index) {
 
 
 bool MapgenV7::getMountainTerrainAtPoint(int x, int y, int z) {
-       float mnt_h_n = NoisePerlin2D(noise_mount_height->np, x, z, seed);
+       float mnt_h_n = NoisePerlin2D(&noise_mount_height->np, x, z, seed);
        float height_modifier = -((float)y / rangelim(mnt_h_n, 80.0, 150.0));
-       float mnt_n = NoisePerlin3D(noise_mountain->np, x, y, z, seed);
+       float mnt_n = NoisePerlin3D(&noise_mountain->np, x, y, z, seed);
 
        return mnt_n + height_modifier >= 0.6;
 }
@@ -373,10 +373,10 @@ void MapgenV7::carveRivers() {
        for (s16 x = node_min.X; x <= node_max.X; x++, index++) {
                float terrain_mod  = noise_terrain_mod->result[index];
                NoiseParams *np = noise_terrain_river->np;
-               np->persist = noise_terrain_persist->result[index];
+               np.persist = noise_terrain_persist->result[index];
                float terrain_river = NoisePerlin2DNoTxfm(np, x, z, seed);
                float height = terrain_river * (1 - abs(terrain_mod)) *
-                                               noise_terrain_river->np->scale;
+                                               noise_terrain_river->np.scale;
                height = log(height * height); //log(h^3) is pretty interesting for terrain
 
                s16 y = heightmap[index];
index 80e86130a1fa61510e5bd6f5dfabb3861f9314b9..1aac59ddb0efe71f9f869e7d43e5c5c685db2da2 100644 (file)
@@ -56,19 +56,6 @@ size_t OreManager::placeAllOres(Mapgen *mg, u32 seed, v3s16 nmin, v3s16 nmax)
 
 ///////////////////////////////////////////////////////////////////////////////
 
-Ore::Ore()
-{
-       c_ore   = CONTENT_IGNORE;
-       np      = NULL;
-       noise   = NULL;
-}
-
-Ore::~Ore()
-{
-       delete np;
-       delete noise;
-}
-
 
 size_t Ore::placeOre(Mapgen *mg, u32 blockseed, v3s16 nmin, v3s16 nmax)
 {
@@ -117,7 +104,8 @@ void OreScatter::generate(ManualMapVoxelManipulator *vm, int seed,
                int y0 = pr.range(nmin.Y, nmax.Y - csize + 1);
                int z0 = pr.range(nmin.Z, nmax.Z - csize + 1);
 
-               if (np && (NoisePerlin3D(np, x0, y0, z0, seed) < nthresh))
+               if ((flags & OREFLAG_USE_NOISE) &&
+                       (NoisePerlin3D(&np, x0, y0, z0, seed) < nthresh))
                        continue;
 
                for (int z1 = 0; z1 != csize; z1++)
@@ -148,7 +136,7 @@ void OreSheet::generate(ManualMapVoxelManipulator *vm, int seed,
        if (!noise) {
                int sx = nmax.X - nmin.X + 1;
                int sz = nmax.Z - nmin.Z + 1;
-               noise = new Noise(np, 0, sx, sz);
+               noise = new Noise(&np, seed, sx, sz);
        }
        noise->seed = seed + y_start;
        noise->perlinMap2D(nmin.X, nmin.Z);
@@ -161,7 +149,7 @@ void OreSheet::generate(ManualMapVoxelManipulator *vm, int seed,
                        continue;
 
                int height = max_height * (1. / pr.range(1, 3));
-               int y0 = y_start + np->scale * noiseval; //pr.range(1, 3) - 1;
+               int y0 = y_start + np.scale * noiseval; //pr.range(1, 3) - 1;
                int y1 = y0 + height;
                for (int y = y0; y != y1; y++) {
                        u32 i = vm->m_area.index(x, y, z);
index 16fb50cd548275443d2159484235da6187979fd5..f3a565050c748457bd8abb66cb6c0d66282ca50d 100644 (file)
@@ -40,6 +40,8 @@ class ManualMapVoxelManipulator;
 // nodes isn't the specified node
 #define OREFLAG_NODEISNT  0x04 // not yet implemented
 
+#define OREFLAG_USE_NOISE 0x08
+
 #define ORE_RANGE_ACTUAL 1
 #define ORE_RANGE_MIRROR 2
 
@@ -54,6 +56,8 @@ extern FlagDesc flagdesc_ore[];
 
 class Ore : public GenElement {
 public:
+       static const bool NEEDS_NOISE = false;
+
        content_t c_ore;                  // the node to place
        std::vector<content_t> c_wherein; // the nodes to be placed in
        u32 clust_scarcity; // ore cluster has a 1-in-clust_scarcity chance of appearing at a node
@@ -64,25 +68,26 @@ public:
        u8 ore_param2;          // to set node-specific attributes
        u32 flags;          // attributes for this ore
        float nthresh;      // threshhold for noise at which an ore is placed
-       NoiseParams *np;    // noise for distribution of clusters (NULL for uniform scattering)
+       NoiseParams np;     // noise for distribution of clusters (NULL for uniform scattering)
        Noise *noise;
 
-       Ore();
-       virtual ~Ore();
-
        size_t placeOre(Mapgen *mg, u32 blockseed, v3s16 nmin, v3s16 nmax);
        virtual void generate(ManualMapVoxelManipulator *vm, int seed,
                                                u32 blockseed, v3s16 nmin, v3s16 nmax) = 0;
 };
 
 class OreScatter : public Ore {
-       virtual ~OreScatter() {}
+public:
+       static const bool NEEDS_NOISE = false;
+
        virtual void generate(ManualMapVoxelManipulator *vm, int seed,
                                                u32 blockseed, v3s16 nmin, v3s16 nmax);
 };
 
 class OreSheet : public Ore {
-       virtual ~OreSheet() {}
+public:
+       static const bool NEEDS_NOISE = true;
+
        virtual void generate(ManualMapVoxelManipulator *vm, int seed,
                                                u32 blockseed, v3s16 nmin, v3s16 nmax);
 };
index 57938bd06f4acf4e797f9a05cb3a665edb4bacb2..0d8b118aa8d88b602089b8192dc24921260653c8 100644 (file)
@@ -317,9 +317,9 @@ float contour(float v)
 ///////////////////////// [ New perlin stuff ] ////////////////////////////
 
 
-Noise::Noise(NoiseParams *np, int seed, int sx, int sy, int sz)
+Noise::Noise(NoiseParams *np_, int seed, int sx, int sy, int sz)
 {
-       this->np   = np;
+       memcpy(&np, np_, sizeof(np));
        this->seed = seed;
        this->sx   = sx;
        this->sy   = sy;
@@ -329,10 +329,10 @@ Noise::Noise(NoiseParams *np, int seed, int sx, int sy, int sz)
        this->gradient_buf = NULL;
        this->result       = NULL;
 
-       if (np->flags & NOISE_FLAG_DEFAULTS) {
+       if (np.flags & NOISE_FLAG_DEFAULTS) {
                // By default, only 2d noise is eased.
                if (sz <= 1)
-                       np->flags |= NOISE_FLAG_EASED;
+                       np.flags |= NOISE_FLAG_EASED;
        }
 
        allocBuffers();
@@ -380,7 +380,7 @@ void Noise::setSize(int sx, int sy, int sz)
 
 void Noise::setSpreadFactor(v3f spread)
 {
-       this->np->spread = spread;
+       this->np.spread = spread;
 
        resizeNoiseBuf(sz > 1);
 }
@@ -388,7 +388,7 @@ void Noise::setSpreadFactor(v3f spread)
 
 void Noise::setOctaves(int octaves)
 {
-       this->np->octaves = octaves;
+       this->np.octaves = octaves;
 
        resizeNoiseBuf(sz > 1);
 }
@@ -400,15 +400,15 @@ void Noise::resizeNoiseBuf(bool is3d)
        float ofactor;
 
        //maximum possible spread value factor
-       ofactor = pow(np->lacunarity, np->octaves - 1);
+       ofactor = pow(np.lacunarity, np.octaves - 1);
 
        //noise lattice point count
        //(int)(sz * spread * ofactor) is # of lattice points crossed due to length
        // + 2 for the two initial endpoints
        // + 1 for potentially crossing a boundary due to offset
-       nlx = (int)ceil(sx * ofactor / np->spread.X) + 3;
-       nly = (int)ceil(sy * ofactor / np->spread.Y) + 3;
-       nlz = is3d ? (int)ceil(sz * ofactor / np->spread.Z) + 3 : 1;
+       nlx = (int)ceil(sx * ofactor / np.spread.X) + 3;
+       nly = (int)ceil(sy * ofactor / np.spread.Y) + 3;
+       nlz = is3d ? (int)ceil(sz * ofactor / np.spread.Z) + 3 : 1;
 
        delete[] noise_buf;
        try {
@@ -440,7 +440,7 @@ void Noise::gradientMap2D(
        int index, i, j, x0, y0, noisex, noisey;
        int nlx, nly;
 
-       Interp2dFxn interpolate = (np->flags & NOISE_FLAG_EASED) ?
+       Interp2dFxn interpolate = (np.flags & NOISE_FLAG_EASED) ?
                biLinearInterpolation : biLinearInterpolationNoEase;
 
        x0 = floor(x);
@@ -504,7 +504,7 @@ void Noise::gradientMap3D(
        int index, i, j, k, x0, y0, z0, noisex, noisey, noisez;
        int nlx, nly, nlz;
 
-       Interp3dFxn interpolate = (np->flags & NOISE_FLAG_EASED) ?
+       Interp3dFxn interpolate = (np.flags & NOISE_FLAG_EASED) ?
                triLinearInterpolation : triLinearInterpolationNoEase;
 
        x0 = floor(x);
@@ -588,8 +588,8 @@ float *Noise::perlinMap2D(float x, float y, float *persistence_map)
        float f = 1.0, g = 1.0;
        size_t bufsize = sx * sy;
 
-       x /= np->spread.X;
-       y /= np->spread.Y;
+       x /= np.spread.X;
+       y /= np.spread.Y;
 
        memset(result, 0, sizeof(float) * bufsize);
 
@@ -600,15 +600,15 @@ float *Noise::perlinMap2D(float x, float y, float *persistence_map)
                        persist_buf[i] = 1.0;
        }
 
-       for (size_t oct = 0; oct < np->octaves; oct++) {
+       for (size_t oct = 0; oct < np.octaves; oct++) {
                gradientMap2D(x * f, y * f,
-                       f / np->spread.X, f / np->spread.Y,
-                       seed + np->seed + oct);
+                       f / np.spread.X, f / np.spread.Y,
+                       seed + np.seed + oct);
 
                updateResults(g, persist_buf, persistence_map, bufsize);
 
-               f *= np->lacunarity;
-               g *= np->persist;
+               f *= np.lacunarity;
+               g *= np.persist;
        }
 
        return result;
@@ -620,9 +620,9 @@ float *Noise::perlinMap3D(float x, float y, float z, float *persistence_map)
        float f = 1.0, g = 1.0;
        size_t bufsize = sx * sy * sz;
 
-       x /= np->spread.X;
-       y /= np->spread.Y;
-       z /= np->spread.Z;
+       x /= np.spread.X;
+       y /= np.spread.Y;
+       z /= np.spread.Z;
 
        memset(result, 0, sizeof(float) * bufsize);
 
@@ -633,15 +633,15 @@ float *Noise::perlinMap3D(float x, float y, float z, float *persistence_map)
                        persist_buf[i] = 1.0;
        }
 
-       for (size_t oct = 0; oct < np->octaves; oct++) {
+       for (size_t oct = 0; oct < np.octaves; oct++) {
                gradientMap3D(x * f, y * f, z * f,
-                       f / np->spread.X, f / np->spread.Y, f / np->spread.Z,
-                       seed + np->seed + oct);
+                       f / np.spread.X, f / np.spread.Y, f / np.spread.Z,
+                       seed + np.seed + oct);
 
                updateResults(g, persist_buf, persistence_map, bufsize);
 
-               f *= np->lacunarity;
-               g *= np->persist;
+               f *= np.lacunarity;
+               g *= np.persist;
        }
 
        return result;
@@ -653,7 +653,7 @@ void Noise::updateResults(float g, float *gmap,
 {
        // This looks very ugly, but it is 50-70% faster than having
        // conditional statements inside the loop
-       if (np->flags & NOISE_FLAG_ABSVALUE) {
+       if (np.flags & NOISE_FLAG_ABSVALUE) {
                if (persistence_map) {
                        for (size_t i = 0; i != bufsize; i++) {
                                result[i] += gmap[i] * fabs(gradient_buf[i]);
@@ -685,6 +685,6 @@ void Noise::transformNoiseMap()
        // slowdown even with -O2.  To prevent this, store the value in a local.
        size_t bufsize = sx * sy * sz;
        for (size_t i = 0; i != bufsize; i++)
-               result[i] = result[i] * np->scale + np->offset;
+               result[i] = result[i] * np.scale + np.offset;
 }
 
index a7212a29837fdcf250ff12e7d82dacd8755dc12b..66be8db93d440cd0d781c58181474e9a8c5ba644 100644 (file)
@@ -122,7 +122,7 @@ struct NoiseParams {
 
 class Noise {
 public:
-       NoiseParams *np;
+       NoiseParams np;
        int seed;
        int sx;
        int sy;
index 0e3d219a4ecf83fdd71d2868d7ee07511249d70f..3176b920cca47b4222d1332c1c1dcc5010d02948 100644 (file)
@@ -546,7 +546,14 @@ int ModApiMapgen::l_register_ore(lua_State *L)
        getflagsfield(L, index, "flags", flagdesc_ore, &ore->flags, NULL);
 
        lua_getfield(L, index, "noise_params");
-       ore->np = get_noiseparams(L, -1);
+       if (read_noiseparams(L, -1, &ore->np)) {
+               ore->flags |= OREFLAG_USE_NOISE;
+       } else if (ore->NEEDS_NOISE) {
+               errorstream << "register_ore: specified ore type requires valid "
+                       "noise parameters" << std::endl;
+               delete ore;
+               return 0;
+       }
        lua_pop(L, 1);
 
        u32 id = oremgr->add(ore);
index 2a57df0f6db8e72ffbc257e51c0df56bf8fdfd9c..c66f54e6f3593553ce8860476403a8aa808ba548 100644 (file)
@@ -161,7 +161,7 @@ int LuaPerlinNoiseMap::l_get2dMap(lua_State *L)
        for (int y = 0; y != n->sy; y++) {
                lua_newtable(L);
                for (int x = 0; x != n->sx; x++) {
-                       float noiseval = n->np->offset + n->np->scale * n->result[i++];
+                       float noiseval = n->np.offset + n->np.scale * n->result[i++];
                        lua_pushnumber(L, noiseval);
                        lua_rawseti(L, -2, x + 1);
                }
@@ -185,7 +185,7 @@ int LuaPerlinNoiseMap::l_get2dMap_flat(lua_State *L)
 
        lua_newtable(L);
        for (int i = 0; i != maplen; i++) {
-               float noiseval = n->np->offset + n->np->scale * n->result[i];
+               float noiseval = n->np.offset + n->np.scale * n->result[i];
                lua_pushnumber(L, noiseval);
                lua_rawseti(L, -2, i + 1);
        }
@@ -210,7 +210,7 @@ int LuaPerlinNoiseMap::l_get3dMap(lua_State *L)
                for (int y = 0; y != n->sy; y++) {
                        lua_newtable(L);
                        for (int x = 0; x != n->sx; x++) {
-                               lua_pushnumber(L, n->np->offset + n->np->scale * n->result[i++]);
+                               lua_pushnumber(L, n->np.offset + n->np.scale * n->result[i++]);
                                lua_rawseti(L, -2, x + 1);
                        }
                        lua_rawseti(L, -2, y + 1);
@@ -236,7 +236,7 @@ int LuaPerlinNoiseMap::l_get3dMap_flat(lua_State *L)
 
        lua_newtable(L);
        for (int i = 0; i != maplen; i++) {
-               float noiseval = n->np->offset + n->np->scale * n->result[i];
+               float noiseval = n->np.offset + n->np.scale * n->result[i];
                lua_pushnumber(L, noiseval);
                lua_rawseti(L, -2, i + 1);
        }