diff --git a/games/minimal/mods/default/init.lua b/games/minimal/mods/default/init.lua index 9900b98a..15cc5a0b 100644 --- a/games/minimal/mods/default/init.lua +++ b/games/minimal/mods/default/init.lua @@ -1586,6 +1586,82 @@ minetest.register_alias("mapgen_stone_with_coal", "default:stone_with_coal") minetest.register_alias("mapgen_stone_with_iron", "default:stone_with_iron") minetest.register_alias("mapgen_mese", "default:mese") +minetest.register_biome_groups({ +0.35, 0.30, 0.20 +}) + +-- +-- Register the biomes for the map generator +-- +minetest.register_biome({ + group_id = 0, + name = "Ocean", + terrain_type = "liquid", + node_top = "default:gravel", + node_filler = "default:stone", + num_top_nodes = 4, + height_min = -3000, + height_max = 3000, + heat_min = -20.0, + heat_max = 100.0, + humidity_min = 0.0, + humidity_max = 100.0, + scale = 10.0, + offset = -10.0, +}) + +minetest.register_biome({ + group_id = 1, + name = "Beach", + terrain_type = "normal", + node_top = "default:sand", + node_filler = "default:stone", + num_top_nodes = 5, + height_min = -3000, + height_max = 3000, + heat_min = 60.0, + heat_max = 100.0, + humidity_min = 0.0, + humidity_max = 100.0, + scale = 5.0, + offset = 5.0, +}) + +minetest.register_biome({ + group_id = 2, + name = "Land", + terrain_type = "normal", + node_top = "default:dirt_with_grass", + node_filler = "default:stone", + num_top_nodes = 5, + height_min = -3000, + height_max = 3000, + heat_min = -50.0, + heat_max = 100.0, + humidity_min = 0.0, + humidity_max = 100.0, + scale = 12.0, + offset = 10.0, +}) + +minetest.register_biome({ + group_id = 3, + name = "Hills", + terrain_type = "normal", + node_top = "default:dirt", + node_filler = "default:stone", + num_top_nodes = 3, + height_min = -3000, + height_max = 3000, + heat_min = -50.0, + heat_max = 100.0, + humidity_min = 0.0, + humidity_max = 100.0, + scale = 70.0, + offset = 30.0, +}) + + -- Support old code function default.spawn_falling_node(p, nodename) spawn_falling_node(p, nodename) diff --git a/src/biome.cpp b/src/biome.cpp index 4b240d5a..c66c2494 100644 --- a/src/biome.cpp +++ b/src/biome.cpp @@ -64,11 +64,14 @@ int bg4_biomes[] = {BT_HILLS, BT_EXTREMEHILLS, BT_MOUNTAINS, BT_DESERT, BT_DESE float bg5_temps[] = {5.0, 40.0}; int bg5_biomes[] = {BT_LAKE, BT_PLAINS, BT_DESERT};*/ +NoiseParams np_default = {0.0, 20.0, v3f(250., 250., 250.), 82341, 5, 0.6}; + BiomeDefManager::BiomeDefManager(IGameDef *gamedef) { this->m_gamedef = gamedef; this->ndef = gamedef->ndef(); + bgroups.push_back(new std::vector); //the initial biome group //addDefaultBiomes(); //can't do this in the ctor, too early } @@ -79,19 +82,51 @@ BiomeDefManager::~BiomeDefManager() { } -void BiomeDefManager::addBiome() { - +Biome *BiomeDefManager::createBiome(BiomeTerrainType btt) { + switch (btt) { + case BIOME_TERRAIN_NORMAL: + return new Biome; + case BIOME_TERRAIN_LIQUID: + return new BiomeLiquid; + case BIOME_TERRAIN_NETHER: + return new BiomeHell; + case BIOME_TERRAIN_AETHER: + return new BiomeAether; + case BIOME_TERRAIN_FLAT: + return new BiomeSuperflat; + } } -NoiseParams npmtdef = {0.0, 20.0, v3f(250., 250., 250.), 82341, 5, 0.6}; +void BiomeDefManager::addBiomeGroup(float freq) { + int size = bgroup_freqs.size(); + float newfreq = freq; + + if (size) + newfreq += bgroup_freqs[size - 1]; + bgroup_freqs.push_back(newfreq); + bgroups.push_back(new std::vector); + printf("added biome with freq %f\n", newfreq); +} + + +void BiomeDefManager::addBiome(int groupid, Biome *b) { + std::vector *bgroup; + + if (groupid >= bgroups.size()) { + printf("blahblahblah"); + return; + } + + bgroup = bgroups[groupid]; + bgroup->push_back(b); +} + void BiomeDefManager::addDefaultBiomes() { std::vector *bgroup; Biome *b; - //bgroup = new std::vector; - b = new Biome; b->name = "Default"; b->n_top = MapNode(ndef->getId("mapgen_stone")); @@ -103,30 +138,25 @@ void BiomeDefManager::addDefaultBiomes() { b->heat_max = FLT_MAX; b->humidity_min = FLT_MIN; b->humidity_max = FLT_MAX; - b->np = &npmtdef; + b->np = &np_default; biome_default = b; - - //bgroup->push_back(b); - //bgroups.push_back(bgroup); } Biome *BiomeDefManager::getBiome(float bgfreq, float heat, float humidity) { - std::vector bgroup; + std::vector *bgroup; Biome *b; int i; int ngroups = bgroup_freqs.size(); if (!ngroups) return biome_default; - for (i = 0; (i != ngroups - 1) && (bgfreq > bgroup_freqs[i]); i++); - bgroup = *(bgroups[i]); + for (i = 0; (i != ngroups) && (bgfreq > bgroup_freqs[i]); i++); + bgroup = bgroups[i]; - int nbiomes = bgroup.size(); - if (!nbiomes) - return biome_default; - for (i = 0; i != nbiomes - 1; i++) { - b = bgroup[i]; + int nbiomes = bgroup->size(); + for (i = 0; i != nbiomes; i++) { + b = bgroup->operator[](i);/////////////////////////// if (heat >= b->heat_min && heat <= b->heat_max && humidity >= b->humidity_min && humidity <= b->humidity_max) return b; @@ -145,13 +175,11 @@ int Biome::getSurfaceHeight(float noise_terrain) { void Biome::genColumn(Mapgen *mg, int x, int z, int y1, int y2) { - //printf("(%d, %d): %f\n", x, z, mg->map_terrain[z * mg->ystride + x]); - - //int surfaceh = 4; - int surfaceh = np->offset + np->scale * mg->map_terrain[(z - mg->node_min.Z) * 80 /*THIS IS TEMPORARY mg->ystride*/ + (x - mg->node_min.X)]; - //printf("gen column %f\n", ); + int i = (z - mg->node_min.Z) * mg->csize.Z + (x - mg->node_min.X); + int surfaceh = np->offset + np->scale * mg->map_terrain[i]; int y = y1; - int i = mg->vmanip->m_area.index(x, y, z); //z * mg->zstride + x + (y - mg->vmanip->m_area.MinEdge.Y) * mg->ystride; + + i = mg->vmanip->m_area.index(x, y, z); for (; y <= surfaceh - ntopnodes && y <= y2; y++, i += mg->ystride) mg->vmanip->m_data[i] = n_filler; for (; y <= surfaceh && y <= y2; y++, i += mg->ystride) @@ -166,16 +194,18 @@ void Biome::genColumn(Mapgen *mg, int x, int z, int y1, int y2) { -void BiomeOcean::genColumn(Mapgen *mg, int x, int z, int y1, int y2) { - int y, i = 0; +void BiomeLiquid::genColumn(Mapgen *mg, int x, int z, int y1, int y2) { + int i = (z - mg->node_min.Z) * mg->csize.Z + (x - mg->node_min.X); + int surfaceh = np->offset + np->scale * mg->map_terrain[i]; + int y = y1; - int surfaceh = np->offset + np->scale * mg->map_terrain[z * mg->ystride + x]; - - i = z * mg->zstride + x; - for (y = y1; y <= surfaceh - ntopnodes && y <= y2; y++, i += mg->ystride) + i = mg->vmanip->m_area.index(x, y, z); + for (; y <= surfaceh - ntopnodes && y <= y2; y++, i += mg->ystride) mg->vmanip->m_data[i] = n_filler; for (; y <= surfaceh && y <= y2; y++, i += mg->ystride) mg->vmanip->m_data[i] = n_top; + for (; y <= mg->water_level && y <= y2; y++, i += mg->ystride) + mg->vmanip->m_data[i] = mg->n_water; for (; y <= y2; y++, i += mg->ystride) mg->vmanip->m_data[i] = mg->n_air; } @@ -190,22 +220,23 @@ int BiomeHell::getSurfaceHeight(float noise_terrain) { void BiomeHell::genColumn(Mapgen *mg, int x, int z, int y1, int y2) { - int y, i = 0; - int surfaceh = np->offset + np->scale * mg->map_terrain[z * mg->ystride + x]; - - i = z * mg->zstride + x; - for (y = y1; y <= surfaceh - ntopnodes && y <= y2; y++, i += mg->ystride) - mg->vmanip->m_data[i] = n_filler; - for (; y <= surfaceh && y <= y2; y++, i += mg->ystride) - mg->vmanip->m_data[i] = n_top; - for (; y <= y2; y++, i += mg->ystride) - mg->vmanip->m_data[i] = mg->n_air; } ///////////////////////////// [ Aether biome ] //////////////////////////////// + +int BiomeAether::getSurfaceHeight(float noise_terrain) { + return np->offset + np->scale * noise_terrain; +} + + +void BiomeAether::genColumn(Mapgen *mg, int x, int z, int y1, int y2) { + +} + + /////////////////////////// [ Superflat biome ] /////////////////////////////// @@ -215,15 +246,5 @@ int BiomeSuperflat::getSurfaceHeight(float noise_terrain) { void BiomeSuperflat::genColumn(Mapgen *mg, int x, int z, int y1, int y2) { - int y, i = 0; - int surfaceh = ntopnodes; - - i = z * mg->zstride + x; - for (y = y1; y <= surfaceh - ntopnodes && y <= y2; y++, i += mg->ystride) - mg->vmanip->m_data[i] = n_filler; - for (; y <= surfaceh && y <= y2; y++, i += mg->ystride) - mg->vmanip->m_data[i] = n_top; - for (; y <= y2; y++, i += mg->ystride) - mg->vmanip->m_data[i] = mg->n_air; } diff --git a/src/biome.h b/src/biome.h index 5e43ab6d..bb35dd1c 100644 --- a/src/biome.h +++ b/src/biome.h @@ -20,12 +20,23 @@ with this program; if not, write to the Free Software Foundation, Inc., #ifndef BIOME_HEADER #define BIOME_HEADER +#include #include "nodedef.h" #include "gamedef.h" #include "mapnode.h" #include "noise.h" #include "mapgen.h" + +enum BiomeTerrainType +{ + BIOME_TERRAIN_NORMAL, + BIOME_TERRAIN_LIQUID, + BIOME_TERRAIN_NETHER, + BIOME_TERRAIN_AETHER, + BIOME_TERRAIN_FLAT +}; + class Biome { public: MapNode n_top; @@ -38,14 +49,14 @@ class Biome { float heat_max; float humidity_min; float humidity_max; - const char *name; + std::string name; NoiseParams *np; virtual void genColumn(Mapgen *mg, int x, int z, int y1, int y2); virtual int getSurfaceHeight(float noise_terrain); }; -class BiomeOcean : public Biome { +class BiomeLiquid : public Biome { virtual void genColumn(Mapgen *mg, int x, int z, int y1, int y2); }; @@ -54,6 +65,11 @@ class BiomeHell : public Biome { virtual int getSurfaceHeight(float noise_terrain); }; +class BiomeAether : public Biome { + virtual void genColumn(Mapgen *mg, int x, int z, int y1, int y2); + virtual int getSurfaceHeight(float noise_terrain); +}; + class BiomeSuperflat : public Biome { virtual void genColumn(Mapgen *mg, int x, int z, int y1, int y2); virtual int getSurfaceHeight(float noise_terrain); @@ -70,9 +86,11 @@ class BiomeDefManager { BiomeDefManager(IGameDef *gamedef); ~BiomeDefManager(); + Biome *createBiome(BiomeTerrainType btt); Biome *getBiome(float bgfreq, float heat, float humidity); - void addBiome(); + void addBiomeGroup(float freq); + void addBiome(int groupid, Biome *b); void addDefaultBiomes(); }; diff --git a/src/mapgen.cpp b/src/mapgen.cpp index 7271b765..f9c27ac1 100644 --- a/src/mapgen.cpp +++ b/src/mapgen.cpp @@ -35,9 +35,9 @@ with this program; if not, write to the Free Software Foundation, Inc., #include "treegen.h" NoiseParams nparams_mtdefault = - {0.0, 20.0, v3f(250., 250., 250.), 82341, 5, 0.6}; //terrain + {10.0, 12.0, v3f(350., 350., 350.), 82341, 5, 0.6}; //terrain NoiseParams nparams_def_bgroup = - {0.5, 1/(2*1.6), v3f(250., 250., 250.), 5923, 2, 0.60}; //0 to 1 + {0.5, 1/(2*1.6), v3f(350., 350., 350.), 5923, 2, 0.60}; //0 to 1 NoiseParams nparams_def_heat = {25.0, 50.0, v3f(500., 500., 500.), 35293, 1, 0.00}; //-25 to 75 NoiseParams nparams_def_humidity = @@ -139,9 +139,13 @@ void Mapgen::makeChunk(BlockMakeData *data) { map_heat = noise_heat->perlinMap2D(x, z); map_humidity = noise_humidity->perlinMap2D(x, z); + noise_bgroup->transformNoiseMap(); + noise_heat->transformNoiseMap(); + noise_humidity->transformNoiseMap(); + int i = 0; - for (x = node_min.X; x <= node_max.X; x++) { - for (z = node_min.Z; z <= node_max.Z; z++) { + for (z = node_min.Z; z <= node_max.Z; z++) { + for (x = node_min.X; x <= node_max.X; x++) { Biome *biome = biomedef->getBiome(map_bgroup[i], map_heat[i], map_humidity[i]); biome->genColumn(this, x, z, y1, y2); i++; @@ -153,7 +157,7 @@ void Mapgen::makeChunk(BlockMakeData *data) { //genDungeon(); //add blobs of dirt and gravel underground //decorateChunk(); - //updateLiquid(full_node_min, full_node_max); + updateLiquid(full_node_min, full_node_max); updateLighting(node_min, node_max); this->generating = false; @@ -164,7 +168,6 @@ void Mapgen::makeChunk(BlockMakeData *data) { void Mapgen::updateLiquid(v3s16 node_min, v3s16 node_max) { bool isliquid, wasliquid; u32 i; - content_t c; for (s16 z = node_min.Z; z <= node_max.Z; z++) { for (s16 x = node_min.X; x <= node_max.X; x++) { diff --git a/src/noise.cpp b/src/noise.cpp index 5cb4be29..3874848a 100644 --- a/src/noise.cpp +++ b/src/noise.cpp @@ -287,7 +287,7 @@ Noise::Noise(NoiseParams *np, int seed, int sx, int sy) { this->seed = seed; this->sx = sx; this->sy = sy; - this->sz = 0; + this->sz = 1; this->noisebuf = new float[nlx * nly]; this->buf = new float[sx * sy]; this->result = new float[sx * sy]; @@ -538,3 +538,16 @@ float *Noise::perlinMap3D(float x, float y, float z) { return result; } + + +void Noise::transformNoiseMap() { + int i = 0; + for (int z = 0; z != sz; z++) { + for (int y = 0; y != sy; y++) { + for (int x = 0; x != sx; x++) { + result[i] = result[i] * np->scale + np->offset; + i++; + } + } + } +} diff --git a/src/noise.h b/src/noise.h index 6e512000..0ab162b7 100644 --- a/src/noise.h +++ b/src/noise.h @@ -95,6 +95,7 @@ class Noise { int seed); float *perlinMap2D(float x, float y); float *perlinMap3D(float x, float y, float z); + void transformNoiseMap(); }; // Return value: -1 ... 1 diff --git a/src/scriptapi.cpp b/src/scriptapi.cpp index 69ee48a7..27f48be2 100644 --- a/src/scriptapi.cpp +++ b/src/scriptapi.cpp @@ -37,6 +37,7 @@ extern "C" { #include "content_sao.h" // For LuaEntitySAO and PlayerSAO #include "itemdef.h" #include "nodedef.h" +#include "biome.h" #include "craftdef.h" #include "main.h" // For g_settings #include "settings.h" // For accessing g_settings @@ -436,6 +437,16 @@ struct EnumString es_TileAnimationType[] = {0, NULL}, }; +struct EnumString es_BiomeTerrainType[] = +{ + {BIOME_TERRAIN_NORMAL, "normal"}, + {BIOME_TERRAIN_LIQUID, "liquid"}, + {BIOME_TERRAIN_NETHER, "nether"}, + {BIOME_TERRAIN_AETHER, "aether"}, + {BIOME_TERRAIN_FLAT, "flat"}, + {0, NULL}, +}; + /* C struct <-> Lua table converter functions */ @@ -988,7 +999,7 @@ static void read_object_properties(lua_State *L, int index, if(lua_istable(L, -1)) prop->initial_sprite_basepos = read_v2s16(L, -1); lua_pop(L, 1); - + getboolfield(L, -1, "is_visible", prop->is_visible); getboolfield(L, -1, "makes_footstep_sound", prop->makes_footstep_sound); getfloatfield(L, -1, "automatic_rotate", prop->automatic_rotate); @@ -1032,7 +1043,7 @@ static ItemDefinition read_item_definition(lua_State *L, int index, warn_if_field_exists(L, index, "tool_digging_properties", "deprecated: use tool_capabilities"); - + lua_getfield(L, index, "tool_capabilities"); if(lua_istable(L, -1)){ def.tool_capabilities = new ToolCapabilities( @@ -1067,7 +1078,7 @@ static TileDef read_tiledef(lua_State *L, int index) { if(index < 0) index = lua_gettop(L) + 1 + index; - + TileDef tiledef; // key at index -2 and value at index @@ -1113,7 +1124,7 @@ static ContentFeatures read_content_features(lua_State *L, int index) index = lua_gettop(L) + 1 + index; ContentFeatures f; - + /* Cache existence of some callbacks */ lua_getfield(L, index, "on_construct"); if(!lua_isnil(L, -1)) f.has_on_construct = true; @@ -1138,7 +1149,7 @@ static ContentFeatures read_content_features(lua_State *L, int index) f.drawtype = (NodeDrawType)getenumfield(L, index, "drawtype", es_DrawType, NDT_NORMAL); getfloatfield(L, index, "visual_scale", f.visual_scale); - + // tiles = {} lua_getfield(L, index, "tiles"); // If nil, try the deprecated name "tile_images" instead @@ -1173,7 +1184,7 @@ static ContentFeatures read_content_features(lua_State *L, int index) } } lua_pop(L, 1); - + // special_tiles = {} lua_getfield(L, index, "special_tiles"); // If nil, try the deprecated name "special_materials" instead @@ -1204,7 +1215,7 @@ static ContentFeatures read_content_features(lua_State *L, int index) f.alpha = getintfield_default(L, index, "alpha", 255); /* Other stuff */ - + lua_getfield(L, index, "post_effect_color"); if(!lua_isnil(L, -1)) f.post_effect_color = readARGB8(L, -1); @@ -1228,7 +1239,7 @@ static ContentFeatures read_content_features(lua_State *L, int index) "deprecated: use 'drop' field"); warn_if_field_exists(L, index, "metadata_name", "deprecated: use on_add and metadata callbacks"); - + // True for all ground-like things like stone and mud, false for eg. trees getboolfield(L, index, "is_ground_content", f.is_ground_content); f.light_propagates = (f.param_type == CPT_LIGHT); @@ -1264,7 +1275,7 @@ static ContentFeatures read_content_features(lua_State *L, int index) "light_source", f.light_source); f.damage_per_second = getintfield_default(L, index, "damage_per_second", f.damage_per_second); - + lua_getfield(L, index, "node_box"); if(lua_istable(L, -1)) f.node_box = read_nodebox(L, -1); @@ -1279,7 +1290,7 @@ static ContentFeatures read_content_features(lua_State *L, int index) getboolfield(L, index, "legacy_facedir_simple", f.legacy_facedir_simple); // Set to true if wall_mounted used to be set to true getboolfield(L, index, "legacy_wallmounted", f.legacy_wallmounted); - + // Sound table lua_getfield(L, index, "sounds"); if(lua_istable(L, -1)){ @@ -1368,7 +1379,7 @@ class LuaItemStack static const luaL_reg methods[]; // Exported functions - + // garbage collector static int gc_object(lua_State *L) { @@ -1621,7 +1632,7 @@ class LuaItemStack { return m_stack; } - + // LuaItemStack(itemstack or itemstring or table or nil) // Creates an LuaItemStack and leaves it on top of stack static int create_object(lua_State *L) @@ -1810,7 +1821,7 @@ class InvRef if(!ud) luaL_typerror(L, narg, className); return *(InvRef**)ud; // unbox pointer } - + static Inventory* getinv(lua_State *L, InvRef *ref) { return get_server(L)->getInventory(ref->m_loc); @@ -1830,9 +1841,9 @@ class InvRef // Inform other things that the inventory has changed get_server(L)->setInventoryModified(ref->m_loc); } - + // Exported functions - + // garbage collector static int gc_object(lua_State *L) { InvRef *o = *(InvRef **)(lua_touserdata(L, 1)); @@ -2185,7 +2196,7 @@ class NodeMetaRef if(!ud) luaL_typerror(L, narg, className); return *(NodeMetaRef**)ud; // unbox pointer } - + static NodeMetadata* getmeta(NodeMetaRef *ref, bool auto_create) { NodeMetadata *meta = ref->m_env->getMap().getNodeMetadata(ref->m_p); @@ -2212,9 +2223,9 @@ class NodeMetaRef block->raiseModified(MOD_STATE_WRITE_NEEDED, "NodeMetaRef::reportMetadataChange"); } - + // Exported functions - + // garbage collector static int gc_object(lua_State *L) { NodeMetaRef *o = *(NodeMetaRef **)(lua_touserdata(L, 1)); @@ -2327,7 +2338,7 @@ class NodeMetaRef InvRef::createNodeMeta(L, ref->m_p); return 1; } - + // to_table(self) static int l_to_table(lua_State *L) { @@ -2373,7 +2384,7 @@ class NodeMetaRef { NodeMetaRef *ref = checkobject(L, 1); int base = 2; - + if(lua_isnil(L, base)){ // No metadata ref->m_env->getMap().removeNodeMetadata(ref->m_p); @@ -2497,7 +2508,7 @@ class ObjectRef if(!ud) luaL_typerror(L, narg, className); return *(ObjectRef**)ud; // unbox pointer } - + static ServerActiveObject* getobject(ObjectRef *ref) { ServerActiveObject *co = ref->m_object; @@ -2513,7 +2524,7 @@ class ObjectRef return NULL; return (LuaEntitySAO*)obj; } - + static PlayerSAO* getplayersao(ObjectRef *ref) { ServerActiveObject *obj = getobject(ref); @@ -2523,7 +2534,7 @@ class ObjectRef return NULL; return (PlayerSAO*)obj; } - + static Player* getplayer(ObjectRef *ref) { PlayerSAO *playersao = getplayersao(ref); @@ -2531,9 +2542,9 @@ class ObjectRef return NULL; return playersao->getPlayer(); } - + // Exported functions - + // garbage collector static int gc_object(lua_State *L) { ObjectRef *o = *(ObjectRef **)(lua_touserdata(L, 1)); @@ -2552,7 +2563,7 @@ class ObjectRef co->m_removed = true; return 0; } - + // getpos(self) // returns: {x=num, y=num, z=num} static int l_getpos(lua_State *L) @@ -2570,7 +2581,7 @@ class ObjectRef lua_setfield(L, -2, "z"); return 1; } - + // setpos(self, pos) static int l_setpos(lua_State *L) { @@ -2584,7 +2595,7 @@ class ObjectRef co->setPos(pos); return 0; } - + // moveto(self, pos, continuous=false) static int l_moveto(lua_State *L) { @@ -2856,7 +2867,7 @@ class ObjectRef co->setVelocity(pos); return 0; } - + // getvelocity(self) static int l_getvelocity(lua_State *L) { @@ -2868,7 +2879,7 @@ class ObjectRef pushFloatPos(L, v); return 1; } - + // setacceleration(self, {x=num, y=num, z=num}) static int l_setacceleration(lua_State *L) { @@ -2881,7 +2892,7 @@ class ObjectRef co->setAcceleration(pos); return 0; } - + // getacceleration(self) static int l_getacceleration(lua_State *L) { @@ -2893,7 +2904,7 @@ class ObjectRef pushFloatPos(L, v); return 1; } - + // setyaw(self, radians) static int l_setyaw(lua_State *L) { @@ -2905,7 +2916,7 @@ class ObjectRef co->setYaw(yaw); return 0; } - + // getyaw(self) static int l_getyaw(lua_State *L) { @@ -2917,7 +2928,7 @@ class ObjectRef lua_pushnumber(L, yaw); return 1; } - + // settexturemod(self, mod) static int l_settexturemod(lua_State *L) { @@ -2929,7 +2940,7 @@ class ObjectRef co->setTextureMod(mod); return 0; } - + // setsprite(self, p={x=0,y=0}, num_frames=1, framelength=0.2, // select_horiz_by_yawpitch=false) static int l_setsprite(lua_State *L) @@ -2966,7 +2977,7 @@ class ObjectRef lua_pushstring(L, name.c_str()); return 1; } - + // get_luaentity(self) static int l_get_luaentity(lua_State *L) { @@ -2977,7 +2988,7 @@ class ObjectRef luaentity_get(L, co->getId()); return 1; } - + /* Player-only */ // is_player(self) @@ -2988,7 +2999,7 @@ class ObjectRef lua_pushboolean(L, (player != NULL)); return 1; } - + // get_player_name(self) static int l_get_player_name(lua_State *L) { @@ -3002,7 +3013,7 @@ class ObjectRef lua_pushstring(L, player->getName()); return 1; } - + // get_look_dir(self) static int l_get_look_dir(lua_State *L) { @@ -3144,7 +3155,7 @@ class ObjectRef ObjectRef *o = checkobject(L, -1); o->m_object = NULL; } - + static void Register(lua_State *L) { lua_newtable(L); @@ -3370,7 +3381,7 @@ class NodeTimerRef if(!ud) luaL_typerror(L, narg, className); return *(NodeTimerRef**)ud; // unbox pointer } - + static int l_set(lua_State *L) { NodeTimerRef *o = checkobject(L, 1); @@ -3381,7 +3392,7 @@ class NodeTimerRef env->getMap().setNodeTimer(o->m_p,NodeTimer(t,e)); return 0; } - + static int l_start(lua_State *L) { NodeTimerRef *o = checkobject(L, 1); @@ -3391,7 +3402,7 @@ class NodeTimerRef env->getMap().setNodeTimer(o->m_p,NodeTimer(t,0)); return 0; } - + static int l_stop(lua_State *L) { NodeTimerRef *o = checkobject(L, 1); @@ -3400,7 +3411,7 @@ class NodeTimerRef env->getMap().removeNodeTimer(o->m_p); return 0; } - + static int l_is_started(lua_State *L) { NodeTimerRef *o = checkobject(L, 1); @@ -3411,7 +3422,7 @@ class NodeTimerRef lua_pushboolean(L,(t.timeout != 0)); return 1; } - + static int l_get_timeout(lua_State *L) { NodeTimerRef *o = checkobject(L, 1); @@ -3422,7 +3433,7 @@ class NodeTimerRef lua_pushnumber(L,t.timeout); return 1; } - + static int l_get_elapsed(lua_State *L) { NodeTimerRef *o = checkobject(L, 1); @@ -3460,7 +3471,7 @@ class NodeTimerRef NodeTimerRef *o = checkobject(L, -1); o->m_env = NULL; } - + static void Register(lua_State *L) { lua_newtable(L); @@ -3525,7 +3536,7 @@ class EnvRef if(!ud) luaL_typerror(L, narg, className); return *(EnvRef**)ud; // unbox pointer } - + // Exported functions // EnvRef:set_node(pos, node) @@ -3969,7 +3980,7 @@ class EnvRef lua_getglobal(L, "table"); lua_getfield(L, -1, "insert"); int table_insert = lua_gettop(L); - + lua_newtable(L); int table = lua_gettop(L); for(s16 x=minp.X; x<=maxp.X; x++) @@ -4094,7 +4105,7 @@ class EnvRef EnvRef *o = checkobject(L, -1); o->m_env = NULL; } - + static void Register(lua_State *L) { lua_newtable(L); @@ -4147,6 +4158,8 @@ const luaL_reg EnvRef::methods[] = { method(EnvRef, find_node_near), method(EnvRef, find_nodes_in_area), method(EnvRef, get_perlin), + //method{EnvRef, get_perlin_map_2d}, + //method{EnvRef, get_perlin_map_3d}, method(EnvRef, clear_objects), method(EnvRef, spawn_tree), {0,0} @@ -4166,7 +4179,7 @@ class LuaPseudoRandom static const luaL_reg methods[]; // Exported functions - + // garbage collector static int gc_object(lua_State *L) { @@ -4217,7 +4230,7 @@ class LuaPseudoRandom { return m_pseudo; } - + // LuaPseudoRandom(seed) // Creates an LuaPseudoRandom and leaves it on top of stack static int create_object(lua_State *L) @@ -4321,7 +4334,7 @@ class LuaABM : public ActiveBlockModifier u32 active_object_count, u32 active_object_count_wider) { lua_State *L = m_lua; - + realitycheck(L); assert(lua_checkstack(L, 20)); StackUnroller stack_unroller(L); @@ -4337,7 +4350,7 @@ class LuaABM : public ActiveBlockModifier lua_gettable(L, registered_abms); if(lua_isnil(L, -1)) assert(0); - + // Call action luaL_checktype(L, -1, LUA_TTABLE); lua_getfield(L, -1, "action"); @@ -4442,6 +4455,77 @@ static int l_get_server_status(lua_State *L) return 1; } +// register_biome_groups({frequencies}) +static int l_register_biome_groups(lua_State *L) +{ + luaL_checktype(L, 1, LUA_TTABLE); + int index = 1; + if (!lua_istable(L, index)) { + + return 0; + } + + BiomeDefManager *bmgr = get_server(L)->getEmergeManager()->biomedef; + + lua_pushnil(L); + for (int i = 1; lua_next(L, index) != 0; i++) { + bmgr->addBiomeGroup(lua_tonumber(L, -1)); + lua_pop(L, 1); + } + lua_pop(L, 1); + + return 0; +} + +// register_biome({lots of stuff}) +static int l_register_biome(lua_State *L) +{ + luaL_checktype(L, 1, LUA_TTABLE); + int index = 1, groupid; + std::string nodename; + + IWritableNodeDefManager *ndef = get_server(L)->getWritableNodeDefManager(); + BiomeDefManager *bmgr = get_server(L)->getEmergeManager()->biomedef; + + groupid = getintfield_default(L, index, "group_id", 0); + + enum BiomeTerrainType terrain = (BiomeTerrainType)getenumfield(L, index, + "terrain_type", es_BiomeTerrainType, BIOME_TERRAIN_NORMAL); + Biome *b = bmgr->createBiome(terrain); + + b->name = getstringfield_default(L, index, "name", ""); + + if (getstringfield(L, index, "node_top", nodename)) + b->n_top = MapNode(ndef->getId(nodename)); + else + b->n_top = MapNode(CONTENT_IGNORE); + + if (getstringfield(L, index, "node_filler", nodename)) + b->n_filler = MapNode(ndef->getId(nodename)); + else + b->n_filler = b->n_top; + + b->ntopnodes = getintfield_default(L, index, "num_top_nodes", 0); + + b->height_min = getintfield_default(L, index, "height_min", 0); + b->height_max = getintfield_default(L, index, "height_max", 0); + b->heat_min = getfloatfield_default(L, index, "heat_min", 0.); + b->heat_max = getfloatfield_default(L, index, "heat_max", 0.); + b->humidity_min = getfloatfield_default(L, index, "humidity_min", 0.); + b->humidity_max = getfloatfield_default(L, index, "humidity_max", 0.); + +//////hrm, what to do about the noiseparams... + b->np = new NoiseParams; /////just a hacky solution + getfloatfield(L, index, "scale", b->np->scale); + getfloatfield(L, index, "offset", b->np->offset); + //TODO: add configurable spread factor and octaves!? + //I'd have to create a Noise for every Biome... + bmgr->addBiome(groupid, b); + printf(" - added biome '%s' - %d %d\n", b->name.c_str(), b->n_top.param0, b->n_filler.param0); + + return 0; +} + // register_item_raw({lots of stuff}) static int l_register_item_raw(lua_State *L) { @@ -4481,7 +4565,7 @@ static int l_register_item_raw(lua_State *L) else def.node_placement_prediction = ""; } - + // Register item definition idef->registerItem(def); @@ -4504,9 +4588,9 @@ static int l_register_alias_raw(lua_State *L) // Get the writable item definition manager from the server IWritableItemDefManager *idef = get_server(L)->getWritableItemDefManager(); - + idef->registerAlias(name, convert_to); - + return 0; /* number of results */ } @@ -4615,7 +4699,7 @@ static int l_register_craft(lua_State *L) // Get the writable craft definition manager from the server IWritableCraftDefManager *craftdef = get_server(L)->getWritableCraftDefManager(); - + std::string type = getstringfield_default(L, table, "type", "shaped"); /* @@ -4899,7 +4983,7 @@ static int l_get_inventory(lua_State *L) std::string name = checkstringfield(L, 1, "name"); loc.setDetached(name); } - + if(get_server(L)->getInventory(loc) != NULL) InvRef::create(L, loc); else @@ -5116,7 +5200,7 @@ static int l_get_craft_result(lua_State *L) lua_getfield(L, input_i, "items"); std::vector items = read_items(L, -1); lua_pop(L, 1); // items - + IGameDef *gdef = get_server(L); ICraftDefManager *cdef = gdef->cdef(); CraftInput input(method, width, items); @@ -5151,7 +5235,7 @@ static int l_get_craft_recipe(lua_State *L) char tmp[20]; int input_i = 1; std::string o_item = luaL_checkstring(L,input_i); - + IGameDef *gdef = get_server(L); ICraftDefManager *cdef = gdef->cdef(); CraftInput input; @@ -5254,6 +5338,8 @@ static const struct luaL_Reg minetest_f [] = { {"register_item_raw", l_register_item_raw}, {"register_alias_raw", l_register_alias_raw}, {"register_craft", l_register_craft}, + {"register_biome", l_register_biome}, + {"register_biome_groups", l_register_biome_groups}, {"setting_set", l_setting_set}, {"setting_get", l_setting_get}, {"setting_getbool", l_setting_getbool}, @@ -5304,7 +5390,7 @@ void scriptapi_export(lua_State *L, Server *server) lua_newtable(L); luaL_register(L, NULL, minetest_f); lua_setglobal(L, "minetest"); - + // Get the main minetest table lua_getglobal(L, "minetest"); @@ -5337,7 +5423,7 @@ bool scriptapi_loadmod(lua_State *L, const std::string &scriptpath, <<"Only chararacters [a-z0-9_] are allowed."<addActiveBlockModifier(abm); // removes value, keeps key for next iteration @@ -5476,7 +5562,7 @@ void scriptapi_add_object_reference(lua_State *L, ServerActiveObject *cobj) lua_getfield(L, -1, "object_refs"); luaL_checktype(L, -1, LUA_TTABLE); int objectstable = lua_gettop(L); - + // object_refs[id] = object lua_pushnumber(L, cobj->getId()); // Push id lua_pushvalue(L, object); // Copy object to top of stack @@ -5495,7 +5581,7 @@ void scriptapi_rm_object_reference(lua_State *L, ServerActiveObject *cobj) lua_getfield(L, -1, "object_refs"); luaL_checktype(L, -1, LUA_TTABLE); int objectstable = lua_gettop(L); - + // Get object_refs[id] lua_pushnumber(L, cobj->getId()); // Push id lua_gettable(L, objectstable); @@ -5759,7 +5845,7 @@ bool scriptapi_get_auth(lua_State *L, const std::string &playername, realitycheck(L); assert(lua_checkstack(L, 20)); StackUnroller stack_unroller(L); - + get_auth_handler(L); lua_getfield(L, -1, "get_auth"); if(lua_type(L, -1) != LUA_TFUNCTION) @@ -5767,12 +5853,12 @@ bool scriptapi_get_auth(lua_State *L, const std::string &playername, lua_pushstring(L, playername.c_str()); if(lua_pcall(L, 1, 1, 0)) script_error(L, "error: %s", lua_tostring(L, -1)); - + // nil = login not allowed if(lua_isnil(L, -1)) return false; luaL_checktype(L, -1, LUA_TTABLE); - + std::string password; bool found = getstringfield(L, -1, "password", password); if(!found) @@ -5787,7 +5873,7 @@ bool scriptapi_get_auth(lua_State *L, const std::string &playername, if(dst_privs) read_privileges(L, -1, *dst_privs); lua_pop(L, 1); - + return true; } @@ -5797,7 +5883,7 @@ void scriptapi_create_auth(lua_State *L, const std::string &playername, realitycheck(L); assert(lua_checkstack(L, 20)); StackUnroller stack_unroller(L); - + get_auth_handler(L); lua_getfield(L, -1, "create_auth"); if(lua_type(L, -1) != LUA_TFUNCTION) @@ -5814,7 +5900,7 @@ bool scriptapi_set_password(lua_State *L, const std::string &playername, realitycheck(L); assert(lua_checkstack(L, 20)); StackUnroller stack_unroller(L); - + get_auth_handler(L); lua_getfield(L, -1, "set_password"); if(lua_type(L, -1) != LUA_TFUNCTION) @@ -5830,7 +5916,7 @@ bool scriptapi_set_password(lua_State *L, const std::string &playername, player */ -void scriptapi_on_player_receive_fields(lua_State *L, +void scriptapi_on_player_receive_fields(lua_State *L, ServerActiveObject *player, const std::string &formname, const std::map &fields) @@ -6097,7 +6183,7 @@ bool scriptapi_node_on_timer(lua_State *L, v3s16 p, MapNode node, f32 dtime) script_error(L, "error: %s", lua_tostring(L, -1)); if((bool)lua_isboolean(L,-1) && (bool)lua_toboolean(L,-1) == true) return true; - + return false; } @@ -6111,7 +6197,7 @@ void scriptapi_node_on_receive_fields(lua_State *L, v3s16 p, StackUnroller stack_unroller(L); INodeDefManager *ndef = get_server(L)->ndef(); - + // If node doesn't exist, we don't know what callback to call MapNode node = get_env(L)->getMap().getNodeNoEx(p); if(node.getContent() == CONTENT_IGNORE) @@ -6679,7 +6765,7 @@ bool scriptapi_luaentity_add(lua_State *L, u16 id, const char *name) verbosestream<<"scriptapi_luaentity_add: id="<hp_max = 10; - + /* Read stuff */ - + prop->hp_max = getintfield_default(L, -1, "hp_max", 10); getboolfield(L, -1, "physical", prop->physical); @@ -6829,10 +6915,10 @@ void scriptapi_luaentity_get_properties(lua_State *L, u16 id, getstringfield(L, -1, "visual", prop->visual); getstringfield(L, -1, "mesh", prop->mesh); - + // Deprecated: read object properties directly read_object_properties(L, -1, prop); - + // Read initial_properties lua_getfield(L, -1, "initial_properties"); read_object_properties(L, -1, prop); diff --git a/src/server.h b/src/server.h index a60be2c0..34515faf 100644 --- a/src/server.h +++ b/src/server.h @@ -103,14 +103,14 @@ class BlockEmergeQueue delete q; } } - + /* peer_id=0 adds with nobody to send to */ void addBlock(u16 peer_id, v3s16 pos, u8 flags) { DSTACK(__FUNCTION_NAME); - + JMutexAutoLock lock(m_mutex); if(peer_id != 0) @@ -130,7 +130,7 @@ class BlockEmergeQueue } } } - + /* Add the block */ @@ -160,7 +160,7 @@ class BlockEmergeQueue JMutexAutoLock lock(m_mutex); return m_queue.size(); } - + u32 peerItemCount(u16 peer_id) { JMutexAutoLock lock(m_mutex); @@ -238,7 +238,7 @@ struct PlayerInfo /* Used for queueing and sorting block transfers in containers - + Lower priority number means higher priority. */ struct PrioritySortedBlockTransfer @@ -303,7 +303,7 @@ struct ServerSoundParams max_hear_distance(32*BS), loop(false) {} - + v3f getPos(ServerEnvironment *env, bool *pos_exists) const; }; @@ -347,7 +347,7 @@ class RemoteClient ~RemoteClient() { } - + /* Finds block that should be sent next to the client. Environment should be locked when this is called. @@ -367,7 +367,7 @@ class RemoteClient { return m_blocks_sending.size(); } - + // Increments timeouts and removes timed-out blocks from list // NOTE: This doesn't fix the server-not-sending-block bug // because it is related to emerging, not sending. @@ -386,13 +386,13 @@ class RemoteClient // Time from last placing or removing blocks float m_time_from_building; - + /*JMutex m_dig_mutex; float m_dig_time_remaining; // -1 = not digging s16 m_dig_tool_item; v3s16 m_dig_position;*/ - + /* List of active objects that the client knows of. Value is dummy. @@ -405,7 +405,7 @@ class RemoteClient - These don't have to be sent again. - A block is cleared from here when client says it has deleted it from it's memory - + Key is position, value is dummy. No MapBlock* is stored here because the blocks can get deleted. */ @@ -413,7 +413,7 @@ class RemoteClient s16 m_nearest_unsent_d; v3s16 m_last_center; float m_nearest_unsent_reset_timer; - + /* Blocks that are currently on the line. This is used for throttling the sending of blocks. @@ -432,7 +432,7 @@ class RemoteClient This is resetted by PrintInfo() */ u32 m_excess_gotblocks; - + // CPU usage optimization u32 m_nothing_to_send_counter; float m_nothing_to_send_pause_timer; @@ -446,7 +446,7 @@ class Server : public con::PeerHandler, public MapEventReceiver, /* NOTE: Every public method should be thread-safe */ - + Server( const std::string &path_world, const std::string &path_config, @@ -477,7 +477,7 @@ class Server : public con::PeerHandler, public MapEventReceiver, { return m_shutdown_requested; } - + /* Shall be called with the environment locked. This is accessed by the map, which is inside the environment, @@ -503,7 +503,7 @@ class Server : public con::PeerHandler, public MapEventReceiver, // Envlock + conlock s32 playSound(const SimpleSoundSpec &spec, const ServerSoundParams ¶ms); void stopSound(s32 handle); - + // Envlock + conlock std::set getPlayerEffectivePrivs(const std::string &name); bool checkPriv(const std::string &name, const std::string &priv); @@ -534,26 +534,30 @@ class Server : public con::PeerHandler, public MapEventReceiver, { return m_con.GetPeerAddress(peer_id); } - + // Envlock and conlock should be locked when calling this void notifyPlayer(const char *name, const std::wstring msg); void notifyPlayers(const std::wstring msg); void queueBlockEmerge(v3s16 blockpos, bool allow_generate); - + // Creates or resets inventory Inventory* createDetachedInventory(const std::string &name); - + // Envlock and conlock should be locked when using Lua lua_State *getLua(){ return m_lua; } // Envlock should be locked when using the rollback manager IRollbackManager *getRollbackManager(){ return m_rollback; } + + //TODO: determine what should be locked when accessing the emerge manager + EmergeManager *getEmergeManager(){ return m_emerge; } + // actions: time-reversed list // Return value: success/failure bool rollbackRevertActions(const std::list &actions, std::list *log); - + // IGameDef interface // Under envlock virtual IItemDefManager* getItemDefManager(); @@ -565,7 +569,7 @@ class Server : public con::PeerHandler, public MapEventReceiver, virtual ISoundManager* getSoundManager(); virtual MtEventManager* getEventManager(); virtual IRollbackReportSink* getRollbackReportSink(); - + IWritableItemDefManager* getWritableItemDefManager(); IWritableNodeDefManager* getWritableNodeDefManager(); IWritableCraftDefManager* getWritableCraftDefManager(); @@ -573,7 +577,7 @@ class Server : public con::PeerHandler, public MapEventReceiver, const ModSpec* getModSpec(const std::string &modname); void getModNames(core::list &modlist); std::string getBuiltinLuaPath(); - + std::string getWorldPath(){ return m_path_world; } bool isSingleplayer(){ return m_simple_singleplayer_mode; } @@ -591,11 +595,11 @@ class Server : public con::PeerHandler, public MapEventReceiver, // As of now, these create and remove clients and players. void peerAdded(con::Peer *peer); void deletingPeer(con::Peer *peer, bool timeout); - + /* Static send methods */ - + static void SendHP(con::Connection &con, u16 peer_id, u8 hp); static void SendAccessDenied(con::Connection &con, u16 peer_id, const std::wstring &reason); @@ -605,7 +609,7 @@ class Server : public con::PeerHandler, public MapEventReceiver, IItemDefManager *itemdef); static void SendNodeDef(con::Connection &con, u16 peer_id, INodeDefManager *nodedef, u16 protocol_version); - + /* Non-static send methods. Conlock should be always used. @@ -633,18 +637,18 @@ class Server : public con::PeerHandler, public MapEventReceiver, void sendAddNode(v3s16 p, MapNode n, u16 ignore_id=0, core::list *far_players=NULL, float far_d_nodes=100); void setBlockNotSent(v3s16 p); - + // Environment and Connection must be locked when called void SendBlockNoLock(u16 peer_id, MapBlock *block, u8 ver); - + // Sends blocks to clients (locks env and con on its own) void SendBlocks(float dtime); - + void fillMediaCache(); void sendMediaAnnouncement(u16 peer_id); void sendRequestedMedia(u16 peer_id, const core::list &tosend); - + void sendDetachedInventory(const std::string &name, u16 peer_id); void sendDetachedInventoryToAll(const std::string &name); void sendDetachedInventories(u16 peer_id); @@ -652,15 +656,15 @@ class Server : public con::PeerHandler, public MapEventReceiver, /* Something random */ - + void DiePlayer(u16 peer_id); void RespawnPlayer(u16 peer_id); - + void UpdateCrafting(u16 peer_id); - + // When called, connection mutex should be locked RemoteClient* getClient(u16 peer_id); - + // When called, environment mutex should be locked std::string getPlayerName(u16 peer_id) { @@ -687,7 +691,7 @@ class Server : public con::PeerHandler, public MapEventReceiver, Call with env and con locked. */ PlayerSAO *emergePlayer(const char *name, u16 peer_id); - + // Locks environment and connection by its own struct PeerChange; void handlePeerChange(PeerChange &c); @@ -696,7 +700,7 @@ class Server : public con::PeerHandler, public MapEventReceiver, /* Variables */ - + // World directory std::string m_path_world; // Path to user's configuration file ("" = no configuration file) @@ -709,7 +713,7 @@ class Server : public con::PeerHandler, public MapEventReceiver, // Thread can set; step() will throw as ServerError MutexedVariable m_async_fatal_error; - + // Some timers float m_liquid_transform_timer; float m_print_info_timer; @@ -717,14 +721,14 @@ class Server : public con::PeerHandler, public MapEventReceiver, float m_emergethread_trigger_timer; float m_savemap_timer; IntervalLimiter m_map_timer_and_unload_interval; - + // NOTE: If connection and environment are both to be locked, // environment shall be locked first. // Environment ServerEnvironment *m_env; JMutex m_env_mutex; - + // Connection con::Connection m_con; JMutex m_con_mutex; @@ -748,23 +752,23 @@ class Server : public con::PeerHandler, public MapEventReceiver, // Item definition manager IWritableItemDefManager *m_itemdef; - + // Node definition manager IWritableNodeDefManager *m_nodedef; - + // Craft definition manager IWritableCraftDefManager *m_craftdef; - + // Event manager EventManager *m_event; - + // Mods std::vector m_mods; - + /* Threads */ - + // A buffer for time steps // step() increments and AsyncRunStep() run by m_thread reads it. float m_step_dtime; @@ -776,7 +780,7 @@ class Server : public con::PeerHandler, public MapEventReceiver, EmergeThread m_emergethread; // Queue of block coordinates to be processed by the emerge thread BlockEmergeQueue m_emerge_queue; - + /* Time related stuff */ @@ -785,7 +789,7 @@ class Server : public con::PeerHandler, public MapEventReceiver, float m_time_of_day_send_timer; // Uptime of server in seconds MutexedVariable m_uptime; - + /* Peer change queue. Queues stuff from peerAdded() and deletingPeer() to @@ -807,7 +811,7 @@ class Server : public con::PeerHandler, public MapEventReceiver, /* Random stuff */ - + // Mod parent directory paths core::list m_modspaths;