The new mapgen, noise functions, et al.

master
kwolekr 2012-11-25 21:16:48 -05:00 committed by Perttu Ahola
parent 736b386554
commit 11afcbff69
23 changed files with 1892 additions and 1037 deletions

View File

@ -218,6 +218,7 @@ set(common_SRCS
sha1.cpp
base64.cpp
ban.cpp
biome.cpp
clientserver.cpp
staticobject.cpp
util/serialize.cpp

229
src/biome.cpp Normal file
View File

@ -0,0 +1,229 @@
/*
Minetest-c55
Copyright (C) 2010-2011 kwolekr, Ryan Kwolek <kwolekr2@cs.scranton.edu>
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU Lesser General Public License as published by
the Free Software Foundation; either version 2.1 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU Lesser General Public License for more details.
You should have received a copy of the GNU Lesser General Public License along
with this program; if not, write to the Free Software Foundation, Inc.,
51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
*/
#include "biome.h"
#include "nodedef.h"
#include "map.h" //for ManualMapVoxelManipulator
#include "main.h"
#define BT_NONE 0
#define BT_OCEAN 1
#define BT_LAKE 2
#define BT_SBEACH 3
#define BT_GBEACH 4
#define BT_PLAINS 5
#define BT_HILLS 6
#define BT_EXTREMEHILLS 7
#define BT_MOUNTAINS 8
#define BT_DESERT 9
#define BT_DESERTHILLS 10
#define BT_HELL 11
#define BT_AETHER 12
#define BT_BTMASK 0x3F
#define BTF_SNOW 0x40
#define BTF_FOREST 0x80
#define BGFREQ_1 ( 0.40)
#define BGFREQ_2 (BGFREQ_1 + 0.05)
#define BGFREQ_3 (BGFREQ_2 + 0.08)
#define BGFREQ_4 (BGFREQ_3 + 0.35)
#define BGFREQ_5 (BGFREQ_4 + 0.18)
//BGFREQ_5 is not checked as an upper bound; it ought to sum up to 1.00, but it's okay if it doesn't.
/*float bg1_temps[] = {0.0};
int bg1_biomes[] = {BT_OCEAN};
float bg2_temps[] = {10.0};
int bg2_biomes[] = {BT_GBEACH, BT_SBEACH};
float bg3_temps[] = {30.0, 40.0};
int bg3_biomes[] = {BT_HILLS, BT_EXTREMEHILLS, BT_MOUNTAINS};
float bg4_temps[] = {25.0, 30.0, 35.0, 40.0};
int bg4_biomes[] = {BT_HILLS, BT_EXTREMEHILLS, BT_MOUNTAINS, BT_DESERT, BT_DESERTHILLS};
float bg5_temps[] = {5.0, 40.0};
int bg5_biomes[] = {BT_LAKE, BT_PLAINS, BT_DESERT};*/
BiomeDefManager::BiomeDefManager(IGameDef *gamedef) {
this->m_gamedef = gamedef;
this->ndef = gamedef->ndef();
//addDefaultBiomes(); //can't do this in the ctor, too early
}
BiomeDefManager::~BiomeDefManager() {
for (int i = 0; i != bgroups.size(); i++)
delete bgroups[i];
}
void BiomeDefManager::addBiome() {
}
NoiseParams npmtdef = {0.0, 20.0, v3f(250., 250., 250.), 82341, 5, 0.6};
void BiomeDefManager::addDefaultBiomes() {
std::vector<Biome *> *bgroup;
Biome *b;
//bgroup = new std::vector<Biome *>;
b = new Biome;
b->name = "Default";
b->n_top = MapNode(ndef->getId("mapgen_stone"));
b->n_filler = b->n_top;
b->ntopnodes = 0;
b->height_min = -MAP_GENERATION_LIMIT;
b->height_max = MAP_GENERATION_LIMIT;
b->heat_min = FLT_MIN;
b->heat_max = FLT_MAX;
b->humidity_min = FLT_MIN;
b->humidity_max = FLT_MAX;
b->np = &npmtdef;
biome_default = b;
//bgroup->push_back(b);
//bgroups.push_back(bgroup);
}
Biome *BiomeDefManager::getBiome(float bgfreq, float heat, float humidity) {
std::vector<Biome *> 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]);
int nbiomes = bgroup.size();
if (!nbiomes)
return biome_default;
for (i = 0; i != nbiomes - 1; i++) {
b = bgroup[i];
if (heat >= b->heat_min && heat <= b->heat_max &&
humidity >= b->humidity_min && humidity <= b->humidity_max)
return b;
}
return biome_default;
}
//////////////////////////// [ Generic biome ] ////////////////////////////////
int Biome::getSurfaceHeight(float noise_terrain) {
return np->offset + np->scale * 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 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;
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 <= y2; y++, i += mg->ystride)
mg->vmanip->m_data[i] = mg->n_air;
}
///////////////////////////// [ Ocean biome ] /////////////////////////////////
void BiomeOcean::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;
}
///////////////////////////// [ Nether biome ] /////////////////////////////////
int BiomeHell::getSurfaceHeight(float noise_terrain) {
return np->offset + np->scale * 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 ] ////////////////////////////////
/////////////////////////// [ Superflat biome ] ///////////////////////////////
int BiomeSuperflat::getSurfaceHeight(float noise_terrain) {
return ntopnodes;
}
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;
}

79
src/biome.h Normal file
View File

@ -0,0 +1,79 @@
/*
Minetest-c55
Copyright (C) 2010-2011 kwolekr, Ryan Kwolek <kwolekr2@cs.scranton.edu>
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU Lesser General Public License as published by
the Free Software Foundation; either version 2.1 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU Lesser General Public License for more details.
You should have received a copy of the GNU Lesser General Public License along
with this program; if not, write to the Free Software Foundation, Inc.,
51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
*/
#ifndef BIOME_HEADER
#define BIOME_HEADER
#include "nodedef.h"
#include "gamedef.h"
#include "mapnode.h"
#include "noise.h"
#include "mapgen.h"
class Biome {
public:
MapNode n_top;
MapNode n_filler;
s16 ntopnodes;
s16 flags;
s16 height_min;
s16 height_max;
float heat_min;
float heat_max;
float humidity_min;
float humidity_max;
const char *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 {
virtual void genColumn(Mapgen *mg, int x, int z, int y1, int y2);
};
class BiomeHell : 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);
};
class BiomeDefManager {
public:
std::vector<float> bgroup_freqs;
std::vector<std::vector<Biome *> *> bgroups;
Biome *biome_default;
IGameDef *m_gamedef;
INodeDefManager *ndef;
BiomeDefManager(IGameDef *gamedef);
~BiomeDefManager();
Biome *getBiome(float bgfreq, float heat, float humidity);
void addBiome();
void addDefaultBiomes();
};
#endif

View File

@ -163,7 +163,7 @@ void set_default_settings(Settings *settings)
settings->setDefault("max_block_generate_distance", "7");
settings->setDefault("time_send_interval", "5");
settings->setDefault("time_speed", "72");
settings->setDefault("water_level", "1");
settings->setDefault("default_water_level", "1");
settings->setDefault("server_unload_unused_data_timeout", "29");
settings->setDefault("server_map_save_interval", "5.3");
settings->setDefault("full_block_send_enable_min_time_from_building", "2.0");

View File

@ -1301,6 +1301,7 @@ u16 ServerEnvironment::addActiveObject(ServerActiveObject *object)
return id;
}
#if 0
bool ServerEnvironment::addActiveObjectAsStatic(ServerActiveObject *obj)
{
assert(obj);
@ -1343,6 +1344,7 @@ bool ServerEnvironment::addActiveObjectAsStatic(ServerActiveObject *obj)
return succeeded;
}
#endif
/*
Finds out what new objects have been added to
@ -1563,13 +1565,15 @@ void ServerEnvironment::removeRemovedObjects()
*/
if(obj->m_static_exists && obj->m_removed)
{
MapBlock *block = m_map->emergeBlock(obj->m_static_block);
if(block)
{
MapBlock *block = m_map->emergeBlock(obj->m_static_block, false);
if (block) {
block->m_static_objects.remove(id);
block->raiseModified(MOD_STATE_WRITE_NEEDED,
"removeRemovedObjects");
obj->m_static_exists = false;
} else {
infostream << "failed to emerge block from which "
"an object to be removed was loaded from. id="<<id<<std::endl;
}
}
@ -1717,6 +1721,8 @@ void ServerEnvironment::activateObjects(MapBlock *block, u32 dtime_s)
If force_delete is set, active object is deleted nevertheless. It
shall only be set so in the destructor of the environment.
If block wasn't generated (not in memory or on disk),
*/
void ServerEnvironment::deactivateFarObjects(bool force_delete)
{

View File

@ -241,8 +241,9 @@ public:
MapBlock.
Caller allocates memory, ServerEnvironment frees memory.
Return value: true if succeeded, false if failed.
(note: not used, pending removal from engine)
*/
bool addActiveObjectAsStatic(ServerActiveObject *object);
//bool addActiveObjectAsStatic(ServerActiveObject *object);
/*
Find out what new objects have been added to

View File

@ -120,14 +120,14 @@ HeightPoint ground_height(u64 seed, v2s16 p2d)
if(n)
return n->getValue();
HeightPoint hp;
s16 level = mapgen::find_ground_level_from_noise(seed, p2d, 3);
s16 level = Mapgen::find_ground_level_from_noise(seed, p2d, 3);
hp.gh = (level-4)*BS;
hp.ma = (4)*BS;
/*hp.gh = BS*base_rock_level_2d(seed, p2d);
hp.ma = BS*get_mud_add_amount(seed, p2d);*/
hp.have_sand = mapgen::get_have_beach(seed, p2d);
hp.have_sand = Mapgen::get_have_beach(seed, p2d);
if(hp.gh > BS*WATER_LEVEL)
hp.tree_amount = mapgen::tree_amount_2d(seed, p2d);
hp.tree_amount = Mapgen::tree_amount_2d(seed, p2d);
else
hp.tree_amount = 0;
// No mud has been added if mud amount is less than 1

View File

@ -1994,7 +1994,7 @@ void Map::removeNodeTimer(v3s16 p)
ServerMap
*/
ServerMap::ServerMap(std::string savedir, IGameDef *gamedef):
ServerMap::ServerMap(std::string savedir, IGameDef *gamedef, EmergeManager *emerge):
Map(dout_server, gamedef),
m_seed(0),
m_map_metadata_changed(true),
@ -2004,6 +2004,8 @@ ServerMap::ServerMap(std::string savedir, IGameDef *gamedef):
{
verbosestream<<__FUNCTION_NAME<<std::endl;
m_emerge = emerge;
//m_chunksize = 8; // Takes a few seconds
if (g_settings->get("fixed_map_seed").empty())
@ -2011,12 +2013,15 @@ ServerMap::ServerMap(std::string savedir, IGameDef *gamedef):
m_seed = (((u64)(myrand()%0xffff)<<0)
+ ((u64)(myrand()%0xffff)<<16)
+ ((u64)(myrand()%0xffff)<<32)
+ ((u64)(myrand()%0xffff)<<48));
+ ((u64)(myrand()&0xffff)<<48));
}
else
{
m_seed = g_settings->getU64("fixed_map_seed");
}
emerge->seed = m_seed;
emerge->water_level = g_settings->getS16("default_water_level");
//<set noiseparams here>
/*
Experimental and debug stuff
@ -2136,7 +2141,7 @@ ServerMap::~ServerMap()
#endif
}
void ServerMap::initBlockMake(mapgen::BlockMakeData *data, v3s16 blockpos)
void ServerMap::initBlockMake(BlockMakeData *data, v3s16 blockpos)
{
bool enable_mapgen_debug_info = g_settings->getBool("enable_mapgen_debug_info");
if(enable_mapgen_debug_info)
@ -2208,7 +2213,7 @@ void ServerMap::initBlockMake(mapgen::BlockMakeData *data, v3s16 blockpos)
Refer to the map generator heuristics.
*/
bool ug = mapgen::block_is_underground(data->seed, p);
bool ug = m_emerge->isBlockUnderground(p);
block->setIsUnderground(ug);
}
@ -2243,7 +2248,7 @@ void ServerMap::initBlockMake(mapgen::BlockMakeData *data, v3s16 blockpos)
// Data is ready now.
}
MapBlock* ServerMap::finishBlockMake(mapgen::BlockMakeData *data,
MapBlock* ServerMap::finishBlockMake(BlockMakeData *data,
core::map<v3s16, MapBlock*> &changed_blocks)
{
v3s16 blockpos_min = data->blockpos_min;
@ -2483,6 +2488,7 @@ ServerMapSector * ServerMap::createSector(v2s16 p2d)
return sector;
}
#if 0
/*
This is a quick-hand function for calling makeBlock().
*/
@ -2518,7 +2524,7 @@ MapBlock * ServerMap::generateBlock(
/*
Create block make data
*/
mapgen::BlockMakeData data;
BlockMakeData data;
initBlockMake(&data, p);
/*
@ -2526,7 +2532,8 @@ MapBlock * ServerMap::generateBlock(
*/
{
TimeTaker t("mapgen::make_block()");
mapgen::make_block(&data);
mapgen->makeChunk(&data);
//mapgen::make_block(&data);
if(enable_mapgen_debug_info == false)
t.stop(true); // Hide output
@ -2595,6 +2602,7 @@ MapBlock * ServerMap::generateBlock(
return block;
}
#endif
MapBlock * ServerMap::createBlock(v3s16 p)
{
@ -2656,14 +2664,15 @@ MapBlock * ServerMap::createBlock(v3s16 p)
}
// Create blank
block = sector->createBlankBlock(block_y);
return block;
}
MapBlock * ServerMap::emergeBlock(v3s16 p, bool allow_generate)
MapBlock * ServerMap::emergeBlock(v3s16 p, bool create_blank)
{
DSTACKF("%s: p=(%d,%d,%d), allow_generate=%d",
DSTACKF("%s: p=(%d,%d,%d), create_blank=%d",
__FUNCTION_NAME,
p.X, p.Y, p.Z, allow_generate);
p.X, p.Y, p.Z, create_blank);
{
MapBlock *block = getBlockNoCreateNoEx(p);
@ -2677,7 +2686,13 @@ MapBlock * ServerMap::emergeBlock(v3s16 p, bool allow_generate)
return block;
}
if(allow_generate)
if (create_blank) {
ServerMapSector *sector = createSector(v2s16(p.X, p.Z));
MapBlock *block = sector->createBlankBlock(p.Y);
return block;
}
/*if(allow_generate)
{
core::map<v3s16, MapBlock*> modified_blocks;
MapBlock *block = generateBlock(p, modified_blocks);
@ -2700,7 +2715,7 @@ MapBlock * ServerMap::emergeBlock(v3s16 p, bool allow_generate)
return block;
}
}
}*/
return NULL;
}
@ -2742,7 +2757,7 @@ plan_b:
Determine from map generator noise functions
*/
s16 level = mapgen::find_ground_level_from_noise(m_seed, p2d, 1);
s16 level = m_emerge->getGroundLevelAtPoint(p2d);
return level;
//double level = base_rock_level_2d(m_seed, p2d) + AVERAGE_MUD_AMOUNT;
@ -3062,6 +3077,7 @@ void ServerMap::saveMapMeta()
Settings params;
params.setU64("seed", m_seed);
params.setS16("water_level", m_emerge->water_level);
params.writeLines(os);
@ -3102,6 +3118,9 @@ void ServerMap::loadMapMeta()
}
m_seed = params.getU64("seed");
m_emerge->seed = m_seed;
m_emerge->water_level = params.getS16("water_level");
//m_emerge->np = ;
verbosestream<<"ServerMap::loadMapMeta(): "<<"seed="<<m_seed<<std::endl;
}

View File

@ -30,6 +30,7 @@ with this program; if not, write to the Free Software Foundation, Inc.,
#include "mapnode.h"
#include "constants.h"
#include "voxel.h"
#include "mapgen.h" //for BlockMakeData and EmergeManager
#include "modifiedstate.h"
#include "util/container.h"
#include "nodetimer.h"
@ -46,9 +47,6 @@ class NodeMetadata;
class IGameDef;
class IRollbackReportSink;
namespace mapgen{
struct BlockMakeData;
};
/*
MapEditEvent
@ -360,7 +358,7 @@ public:
/*
savedir: directory to which map data should be saved
*/
ServerMap(std::string savedir, IGameDef *gamedef);
ServerMap(std::string savedir, IGameDef *gamedef, EmergeManager *emerge);
~ServerMap();
s32 mapType() const
@ -379,15 +377,15 @@ public:
/*
Blocks are generated by using these and makeBlock().
*/
void initBlockMake(mapgen::BlockMakeData *data, v3s16 blockpos);
MapBlock* finishBlockMake(mapgen::BlockMakeData *data,
void initBlockMake(BlockMakeData *data, v3s16 blockpos);
MapBlock* finishBlockMake(BlockMakeData *data,
core::map<v3s16, MapBlock*> &changed_blocks);
// A non-threaded wrapper to the above
MapBlock * generateBlock(
// A non-threaded wrapper to the above - DEFUNCT
/* MapBlock * generateBlock(
v3s16 p,
core::map<v3s16, MapBlock*> &modified_blocks
);
);*/
/*
Get a block from somewhere.
@ -400,9 +398,10 @@ public:
Forcefully get a block from somewhere.
- Memory
- Load from disk
- Generate
- Create blank filled with CONTENT_IGNORE
*/
MapBlock * emergeBlock(v3s16 p, bool allow_generate=true);
MapBlock * emergeBlock(v3s16 p, bool create_blank=true);
// Helper for placing objects on ground level
s16 findGroundLevel(v2s16 p2d);
@ -479,6 +478,7 @@ public:
u64 getSeed(){ return m_seed; }
EmergeManager *m_emerge;
private:
// Seed used for all kinds of randomness in generation
u64 m_seed;

View File

@ -20,7 +20,9 @@ with this program; if not, write to the Free Software Foundation, Inc.,
#include "mapgen.h"
#include "voxel.h"
#include "noise.h"
#include "biome.h"
#include "mapblock.h"
#include "mapnode.h"
#include "map.h"
//#include "serverobject.h"
#include "content_sao.h"
@ -28,9 +30,296 @@ with this program; if not, write to the Free Software Foundation, Inc.,
#include "content_mapnode.h" // For content_mapnode_get_new_name
#include "voxelalgorithms.h"
#include "profiler.h"
#include "settings.h" // For g_settings
#include "main.h" // For g_profiler
#include "treegen.h"
NoiseParams nparams_mtdefault =
{0.0, 20.0, v3f(250., 250., 250.), 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
NoiseParams nparams_def_heat =
{25.0, 50.0, v3f(500., 500., 500.), 35293, 1, 0.00}; //-25 to 75
NoiseParams nparams_def_humidity =
{50, 100/(2*1.6), v3f(750., 750., 750.), 12094, 2, 0.60}; //0 to 100
///////////////////////////////////////////////////////////////////////////////
/*
Mapgen::Mapgen(BiomeDefManager *biomedef) {
Mapgen(0, 0, biomedef);
}*/
Mapgen::Mapgen(BiomeDefManager *biomedef, int mapgenid, u64 seed) {
initMapgen(biomedef, mapgenid, seed,
&nparams_mtdefault, &nparams_def_bgroup,
&nparams_def_heat, &nparams_def_humidity);
}
Mapgen::Mapgen(BiomeDefManager *biomedef, int mapgenid, u64 seed,
NoiseParams *np_terrain, NoiseParams *np_bgroup,
NoiseParams *np_heat, NoiseParams *np_humidity) {
initMapgen(biomedef, mapgenid, seed,
np_terrain, np_bgroup, np_heat, np_humidity);
}
void Mapgen::initMapgen(BiomeDefManager *biomedef, int mapgenid, u64 seed,
NoiseParams *np_terrain, NoiseParams *np_bgroup,
NoiseParams *np_heat, NoiseParams *np_humidity) {
this->generating = false;
this->id = mapgenid;
this->seed = (int)seed;
this->biomedef = biomedef;
this->csize = v3s16(5, 5, 5) * MAP_BLOCKSIZE; /////////////////get this from config!
this->water_level = g_settings->getS16("default_water_level"); ////fix this!
this->np_terrain = np_terrain;
this->np_bgroup = np_bgroup;
this->np_heat = np_heat;
this->np_humidity = np_humidity;
noise_terrain = new Noise(np_terrain, seed, csize.X, csize.Y);
noise_bgroup = new Noise(np_bgroup, seed, csize.X, csize.Y);
noise_heat = new Noise(np_heat, seed, csize.X, csize.Y);
noise_humidity = new Noise(np_humidity, seed, csize.X, csize.Y);
this->ndef = biomedef->ndef;
n_air = MapNode(ndef->getId("mapgen_air"));
n_water = MapNode(ndef->getId("mapgen_water_source"));
n_lava = MapNode(ndef->getId("mapgen_lava_source"));
}
Mapgen::~Mapgen() {
delete noise_terrain;
delete noise_bgroup;
delete noise_heat;
delete noise_humidity;
}
void Mapgen::makeChunk(BlockMakeData *data) {
if (data->no_op)
return;
//printf("generating...\n");//////////////
assert(data->vmanip);
assert(data->nodedef);
assert(data->blockpos_requested.X >= data->blockpos_min.X &&
data->blockpos_requested.Y >= data->blockpos_min.Y &&
data->blockpos_requested.Z >= data->blockpos_min.Z);
assert(data->blockpos_requested.X <= data->blockpos_max.X &&
data->blockpos_requested.Y <= data->blockpos_max.Y &&
data->blockpos_requested.Z <= data->blockpos_max.Z);
this->generating = true;
this->data = data;
this->vmanip = data->vmanip;
v3s16 em = vmanip->m_area.getExtent();
this->ystride = em.X;
this->zstride = em.Y * em.X;
node_min = (data->blockpos_min) * MAP_BLOCKSIZE;
node_max = (data->blockpos_max + v3s16(1, 1, 1)) * MAP_BLOCKSIZE - v3s16(1, 1, 1);
v3s16 full_node_min = (data->blockpos_min - 1) * MAP_BLOCKSIZE;
v3s16 full_node_max = (data->blockpos_max + 2) * MAP_BLOCKSIZE - v3s16(1,1,1);
int y1 = node_min.Y;
int y2 = node_max.Y;
int x = node_min.X;
int z = node_min.Z;
//printf("full_node_min.X: %d | full_node_min.Z: %d | MinEdge: %d | MaxEdge: %d\n", node_min.X, node_min.Z, vmanip->m_area.MinEdge.X, vmanip->m_area.MinEdge.Z);
TimeTaker timer("Generating terrain");
map_terrain = noise_terrain->perlinMap2D(x, z);
map_bgroup = noise_bgroup->perlinMap2D(x, z);
map_heat = noise_heat->perlinMap2D(x, z);
map_humidity = noise_humidity->perlinMap2D(x, z);
int i = 0;
for (x = node_min.X; x <= node_max.X; x++) {
for (z = node_min.Z; z <= node_max.Z; z++) {
Biome *biome = biomedef->getBiome(map_bgroup[i], map_heat[i], map_humidity[i]);
biome->genColumn(this, x, z, y1, y2);
i++;
}
}
timer.stop();
//genCave();
//genDungeon();
//add blobs of dirt and gravel underground
//decorateChunk();
//updateLiquid(full_node_min, full_node_max);
updateLighting(node_min, node_max);
this->generating = false;
//printf("generated block (%d, %d) to (%d, %d)\n", node_min.X, node_min.Y, node_max.X, node_max.Y);//////////
}
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++) {
v2s16 p2d(x, z);
wasliquid = true;
v3s16 em = vmanip->m_area.getExtent();
i = vmanip->m_area.index(v3s16(p2d.X, node_max.Y, p2d.Y));
for (s16 y = node_max.Y; y >= node_min.Y; y--) {
isliquid = ndef->get(vmanip->m_data[i]).isLiquid();
//there was a change between liquid and nonliquid, add to queue
if (isliquid != wasliquid)
data->transforming_liquid.push_back(v3s16(p2d.X, y, p2d.Y));
wasliquid = isliquid;
vmanip->m_area.add_y(em, i, -1);
}
}
}
}
void Mapgen::updateLighting(v3s16 node_min, v3s16 node_max) {
enum LightBank banks[2] = {LIGHTBANK_DAY, LIGHTBANK_NIGHT};
VoxelArea a(node_min - v3s16(1,0,1) * MAP_BLOCKSIZE,
node_max + v3s16(1,0,1) * MAP_BLOCKSIZE);
bool block_is_underground = (water_level > node_max.Y);
bool sunlight = !block_is_underground;
ScopeProfiler sp(g_profiler, "EmergeThread: mapgen lighting update", SPT_AVG);
for (int i = 0; i < 2; i++) {
enum LightBank bank = banks[i];
core::map<v3s16, bool> light_sources;
core::map<v3s16, u8> unlight_from;
voxalgo::clearLightAndCollectSources(*vmanip, a, bank, ndef,
light_sources, unlight_from);
voxalgo::propagateSunlight(*vmanip, a, sunlight, light_sources, ndef);
printf("light_sources: %d\t\tunlight_from: %d\n", light_sources.size(), unlight_from.size());
vmanip->unspreadLight(bank, unlight_from, light_sources, ndef);
vmanip->spreadLight(bank, light_sources, ndef);
}
}
/*class EmergeManager {
public:
int seed;
int water_level;
BiomeDefManager *biomedef;
//mapgen objects here
void addBlockToQueue();
//mapgen helper methods
int getGroundLevelAtPoint(u64 mseed, v2s16 p);
bool isBlockUnderground(u64 mseed, v3s16 blockpos);
u32 getBlockSeed(u64 mseed, v3s16 p);
};*/
EmergeManager::EmergeManager(IGameDef *gamedef) {
this->seed = 0;
this->water_level = 0;
this->np_terrain = &nparams_mtdefault;
this->np_bgroup = &nparams_def_bgroup;
this->np_heat = &nparams_def_heat;
this->np_humidity = &nparams_def_humidity;
this->biomedef = new BiomeDefManager(gamedef);
}
EmergeManager::~EmergeManager() {
delete biomedef;
}
void EmergeManager::addBlockToQueue() {
}
Biome *EmergeManager::getBiomeAtPoint(v3s16 p) {
float bgroup = NoisePerlin2D(np_bgroup, p.X, p.Y, seed);
float heat = NoisePerlin2D(np_heat, p.X, p.Y, seed);
float humidity = NoisePerlin2D(np_humidity, p.X, p.Y, seed);
return biomedef->getBiome(bgroup, heat, humidity);
}
//FIXME: This assumes y == 0, that is, always in a non-hell/non-sky biome
int EmergeManager::getGroundLevelAtPoint(v2s16 p) {
float terrain = NoisePerlin2D(np_terrain, p.X, p.Y, seed);
Biome *biome = getBiomeAtPoint(v3s16(p.X, p.Y, 0));
return biome->getSurfaceHeight(terrain);
}
bool EmergeManager::isBlockUnderground(v3s16 blockpos) {
/*
v2s16 p = v2s16((blockpos.X * MAP_BLOCKSIZE) + MAP_BLOCKSIZE / 2,
(blockpos.Y * MAP_BLOCKSIZE) + MAP_BLOCKSIZE / 2);
int ground_level = getGroundLevelAtPoint(p);
return blockpos.Y * (MAP_BLOCKSIZE + 1) <= min(water_level, ground_level);
*/
//yuck, but then again, should i bother being accurate?
//the height of the nodes in a single block is quite variable
return false; //blockpos.Y * (MAP_BLOCKSIZE + 1) <= water_level;
}
u32 EmergeManager::getBlockSeed(v3s16 p) {
return (u32)(seed & 0xFFFFFFFF) +
p.Z * 38134234 +
p.Y * 42123 +
p.Y * 23;
}
/////////////////////////////////// legacy static functions for farmesh
s16 Mapgen::find_ground_level_from_noise(u64 seed, v2s16 p2d, s16 precision) {
//just need to return something
s16 level = 5;
return level;
}
bool Mapgen::get_have_beach(u64 seed, v2s16 p2d) {
double sandnoise = noise2d_perlin(
0.2+(float)p2d.X/250, 0.7+(float)p2d.Y/250,
seed+59420, 3, 0.50);
return (sandnoise > 0.15);
}
double Mapgen::tree_amount_2d(u64 seed, v2s16 p) {
double noise = noise2d_perlin(
0.5+(float)p.X/125, 0.5+(float)p.Y/125,
seed+2, 4, 0.66);
double zeroval = -0.39;
if(noise < zeroval)
return 0;
else
return 0.04 * (noise-zeroval) / (1.0-zeroval);
}
#if 0 /// BIG COMMENT
namespace mapgen
{
@ -121,6 +410,7 @@ static s16 find_stone_level(VoxelManipulator &vmanip, v2s16 p2d,
}
#endif
#if 0
static void make_papyrus(VoxelManipulator &vmanip, v3s16 p0,
@ -2756,6 +3046,8 @@ void make_block(BlockMakeData *data)
}
}
#endif ///BIG COMMENT
BlockMakeData::BlockMakeData():
no_op(false),
vmanip(NULL),
@ -2768,6 +3060,6 @@ BlockMakeData::~BlockMakeData()
delete vmanip;
}
}; // namespace mapgen
//}; // namespace mapgen

View File

@ -22,12 +22,121 @@ with this program; if not, write to the Free Software Foundation, Inc.,
#include "irrlichttypes_extrabloated.h"
#include "util/container.h" // UniqueQueue
#include "gamedef.h"
#include "mapnode.h"
#include "noise.h"
struct BlockMakeData;
class BiomeDefManager;
class Biome;
//struct BlockMakeData;
class MapBlock;
class ManualMapVoxelManipulator;
class INodeDefManager;
struct BlockMakeData {
bool no_op;
ManualMapVoxelManipulator *vmanip;
u64 seed;
v3s16 blockpos_min;
v3s16 blockpos_max;
v3s16 blockpos_requested;
UniqueQueue<v3s16> transforming_liquid;
INodeDefManager *nodedef;
BlockMakeData();
~BlockMakeData();
};
class Mapgen {
public:
BlockMakeData *data;
ManualMapVoxelManipulator *vmanip;
INodeDefManager *ndef;
BiomeDefManager *biomedef;
int ystride;
int zstride;
v3s16 csize;
int seed;
int water_level;
Noise *noise_terrain;
Noise *noise_bgroup;
Noise *noise_heat;
Noise *noise_humidity;
v3s16 node_min;
v3s16 node_max;
float *map_terrain;
float *map_bgroup;
float *map_heat;
float *map_humidity;
bool generating;
int id;
NoiseParams *np_terrain;
NoiseParams *np_bgroup;
NoiseParams *np_heat;
NoiseParams *np_humidity;
//should these be broken off into a "commonly used nodes" class?
MapNode n_air;
MapNode n_water;
MapNode n_lava;
Mapgen(BiomeDefManager *biomedef, int mapgenid=0, u64 seed=0);
Mapgen(BiomeDefManager *biomedef, int mapgenid, u64 seed,
NoiseParams *np_terrain, NoiseParams *np_bgroup,
NoiseParams *np_heat, NoiseParams *np_humidity);
void initMapgen(BiomeDefManager *biomedef, int mapgenid, u64 seed,
NoiseParams *np_terrain, NoiseParams *np_bgroup,
NoiseParams *np_heat, NoiseParams *np_humidity);
~Mapgen();
void makeChunk(BlockMakeData *data);
void updateLiquid(v3s16 node_min, v3s16 node_max);
void updateLighting(v3s16 node_min, v3s16 node_max);
//Legacy functions for Farmesh (pending removal)
static bool get_have_beach(u64 seed, v2s16 p2d);
static double tree_amount_2d(u64 seed, v2s16 p);
static s16 find_ground_level_from_noise(u64 seed, v2s16 p2d, s16 precision);
};
class EmergeManager {
public:
//settings
u64 seed;
int water_level;
NoiseParams *np_terrain;
NoiseParams *np_bgroup;
NoiseParams *np_heat;
NoiseParams *np_humidity;
//biome manager
BiomeDefManager *biomedef;
//mapgen objects here
EmergeManager(IGameDef *gamedef);
~EmergeManager();
void addBlockToQueue();
//mapgen helper methods
Biome *getBiomeAtPoint(v3s16 p);
int getGroundLevelAtPoint(v2s16 p);
bool isBlockUnderground(v3s16 blockpos);
u32 getBlockSeed(v3s16 p);
};
/*
namespace mapgen
{
// Finds precise ground level at any position
@ -42,9 +151,8 @@ namespace mapgen
// Main map generation routine
void make_block(BlockMakeData *data);
/*
These are used by FarMesh
*/
//These are used by FarMesh
bool get_have_beach(u64 seed, v2s16 p2d);
double tree_amount_2d(u64 seed, v2s16 p);
@ -64,6 +172,6 @@ namespace mapgen
};
}; // namespace mapgen
*/
#endif

View File

@ -21,89 +21,116 @@ with this program; if not, write to the Free Software Foundation, Inc.,
#include "noise.h"
#include <iostream>
#include "debug.h"
#include "util/numeric.h"
#define NOISE_MAGIC_X 1619
#define NOISE_MAGIC_Y 31337
#define NOISE_MAGIC_Z 52591
#define NOISE_MAGIC_SEED 1013
double cos_lookup[16] = {
1.0,0.9238,0.7071,0.3826,0,-0.3826,-0.7071,-0.9238,
1.0,-0.9238,-0.7071,-0.3826,0,0.3826,0.7071,0.9238
float cos_lookup[16] = {
1.0, 0.9238, 0.7071, 0.3826, 0, -0.3826, -0.7071, -0.9238,
1.0, -0.9238, -0.7071, -0.3826, 0, 0.3826, 0.7071, 0.9238
};
double dotProduct(double vx, double vy, double wx, double wy){
return vx*wx+vy*wy;
}
double easeCurve(double t){
return t * t * t * (6. * t * t - 15. * t + 10.);
}
///////////////////////////////////////////////////////////////////////////////
double linearInterpolation(double x0, double x1, double t){
return x0+(x1-x0)*t;
}
double biLinearInterpolation(double x0y0, double x1y0, double x0y1, double x1y1, double x, double y){
double tx = easeCurve(x);
double ty = easeCurve(y);
/*double tx = x;
double ty = y;*/
double u = linearInterpolation(x0y0,x1y0,tx);
double v = linearInterpolation(x0y1,x1y1,tx);
return linearInterpolation(u,v,ty);
}
double triLinearInterpolation(
double v000, double v100, double v010, double v110,
double v001, double v101, double v011, double v111,
double x, double y, double z)
{
/*double tx = easeCurve(x);
double ty = easeCurve(y);
double tz = easeCurve(z);*/
double tx = x;
double ty = y;
double tz = z;
return(
v000*(1-tx)*(1-ty)*(1-tz) +
v100*tx*(1-ty)*(1-tz) +
v010*(1-tx)*ty*(1-tz) +
v110*tx*ty*(1-tz) +
v001*(1-tx)*(1-ty)*tz +
v101*tx*(1-ty)*tz +
v011*(1-tx)*ty*tz +
v111*tx*ty*tz
);
}
double noise2d(int x, int y, int seed)
{
//noise poly: p(n) = 60493n^3 + 19990303n + 137612589
float noise2d(int x, int y, int seed) {
int n = (NOISE_MAGIC_X * x + NOISE_MAGIC_Y * y
+ NOISE_MAGIC_SEED * seed) & 0x7fffffff;
n = (n>>13)^n;
n = (n * (n*n*60493+19990303) + 1376312589) & 0x7fffffff;
return 1.0 - (double)n/1073741824;
n = (n >> 13) ^ n;
n = (n * (n * n * 60493 + 19990303) + 1376312589) & 0x7fffffff;
return 1.f - (float)n / 0x40000000;
}
double noise3d(int x, int y, int z, int seed)
{
float noise3d(int x, int y, int z, int seed) {
int n = (NOISE_MAGIC_X * x + NOISE_MAGIC_Y * y + NOISE_MAGIC_Z * z
+ NOISE_MAGIC_SEED * seed) & 0x7fffffff;
n = (n>>13)^n;
n = (n * (n*n*60493+19990303) + 1376312589) & 0x7fffffff;
return 1.0 - (double)n/1073741824;
n = (n >> 13) ^ n;
n = (n * (n * n * 60493 + 19990303) + 1376312589) & 0x7fffffff;
return 1.f - (float)n / 0x40000000;
}
float dotProduct(float vx, float vy, float wx, float wy) {
return vx * wx + vy * wy;
}
inline float linearInterpolation(float v0, float v1, float t) {
return v0 + (v1 - v0) * t;
}
float biLinearInterpolation(float v00, float v10,
float v01, float v11,
float x, float y) {
float tx = easeCurve(x);
float ty = easeCurve(y);
float u = linearInterpolation(v00, v10, tx);
float v = linearInterpolation(v01, v11, tx);
return linearInterpolation(u, v, ty);
}
float biLinearInterpolationNoEase(float x0y0, float x1y0,
float x0y1, float x1y1,
float x, float y) {
float u = linearInterpolation(x0y0, x1y0, x);
float v = linearInterpolation(x0y1, x1y1, x);
return linearInterpolation(u, v, y);
}
float triLinearInterpolation(
float v000, float v100, float v010, float v110,
float v001, float v101, float v011, float v111,
float x, float y, float z) {
float u = biLinearInterpolationNoEase(v000, v100, v010, v110, x, y);
float v = biLinearInterpolationNoEase(v001, v101, v011, v111, x, y);
return linearInterpolation(u, v, z);
}
#if 0
double noise2d_gradient(double x, double y, int seed)
float triLinearInterpolation(
float v000, float v100, float v010, float v110,
float v001, float v101, float v011, float v111,
float x, float y, float z)
{
/*float tx = easeCurve(x);
float ty = easeCurve(y);
float tz = easeCurve(z);*/
float tx = x;
float ty = y;
float tz = z;
return(
v000 * (1 - tx) * (1 - ty) * (1 - tz) +
v100 * tx * (1 - ty) * (1 - tz) +
v010 * (1 - tx) * ty * (1 - tz) +
v110 * tx * ty * (1 - tz) +
v001 * (1 - tx) * (1 - ty) * tz +
v101 * tx * (1 - ty) * tz +
v011 * (1 - tx) * ty * tz +
v111 * tx * ty * tz
);
}
#endif
#if 0
float noise2d_gradient(float x, float y, int seed)
{
// Calculate the integer coordinates
int x0 = (x > 0.0 ? (int)x : (int)x - 1);
int y0 = (y > 0.0 ? (int)y : (int)y - 1);
// Calculate the remaining part of the coordinates
double xl = x - (double)x0;
double yl = y - (double)y0;
float xl = x - (float)x0;
float yl = y - (float)y0;
// Calculate random cosine lookup table indices for the integer corners.
// They are looked up as unit vector gradients from the lookup table.
int n00 = (int)((noise2d(x0, y0, seed)+1)*8);
@ -111,119 +138,126 @@ double noise2d_gradient(double x, double y, int seed)
int n01 = (int)((noise2d(x0, y0+1, seed)+1)*8);
int n11 = (int)((noise2d(x0+1, y0+1, seed)+1)*8);
// Make a dot product for the gradients and the positions, to get the values
double s = dotProduct(cos_lookup[n00], cos_lookup[(n00+12)%16], xl, yl);
double u = dotProduct(-cos_lookup[n10], cos_lookup[(n10+12)%16], 1.-xl, yl);
double v = dotProduct(cos_lookup[n01], -cos_lookup[(n01+12)%16], xl, 1.-yl);
double w = dotProduct(-cos_lookup[n11], -cos_lookup[(n11+12)%16], 1.-xl, 1.-yl);
float s = dotProduct(cos_lookup[n00], cos_lookup[(n00+12)%16], xl, yl);
float u = dotProduct(-cos_lookup[n10], cos_lookup[(n10+12)%16], 1.-xl, yl);
float v = dotProduct(cos_lookup[n01], -cos_lookup[(n01+12)%16], xl, 1.-yl);
float w = dotProduct(-cos_lookup[n11], -cos_lookup[(n11+12)%16], 1.-xl, 1.-yl);
// Interpolate between the values
return biLinearInterpolation(s,u,v,w,xl,yl);
}
#endif
#if 1
double noise2d_gradient(double x, double y, int seed)
float noise2d_gradient(float x, float y, int seed)
{
// Calculate the integer coordinates
int x0 = (x > 0.0 ? (int)x : (int)x - 1);
int y0 = (y > 0.0 ? (int)y : (int)y - 1);
int x0 = myfloor(x);
int y0 = myfloor(y);
// Calculate the remaining part of the coordinates
double xl = x - (double)x0;
double yl = y - (double)y0;
// Get values for corners of cube
double v00 = noise2d(x0, y0, seed);
double v10 = noise2d(x0+1, y0, seed);
double v01 = noise2d(x0, y0+1, seed);
double v11 = noise2d(x0+1, y0+1, seed);
float xl = x - (float)x0;
float yl = y - (float)y0;
// Get values for corners of square
float v00 = noise2d(x0, y0, seed);
float v10 = noise2d(x0+1, y0, seed);
float v01 = noise2d(x0, y0+1, seed);
float v11 = noise2d(x0+1, y0+1, seed);
// Interpolate
return biLinearInterpolation(v00,v10,v01,v11,xl,yl);
}
#endif
double noise3d_gradient(double x, double y, double z, int seed)
float noise3d_gradient(float x, float y, float z, int seed)
{
// Calculate the integer coordinates
int x0 = (x > 0.0 ? (int)x : (int)x - 1);
int y0 = (y > 0.0 ? (int)y : (int)y - 1);
int z0 = (z > 0.0 ? (int)z : (int)z - 1);
int x0 = myfloor(x);
int y0 = myfloor(y);
int z0 = myfloor(z);
// Calculate the remaining part of the coordinates
double xl = x - (double)x0;
double yl = y - (double)y0;
double zl = z - (double)z0;
float xl = x - (float)x0;
float yl = y - (float)y0;
float zl = z - (float)z0;
// Get values for corners of cube
double v000 = noise3d(x0, y0, z0, seed);
double v100 = noise3d(x0+1, y0, z0, seed);
double v010 = noise3d(x0, y0+1, z0, seed);
double v110 = noise3d(x0+1, y0+1, z0, seed);
double v001 = noise3d(x0, y0, z0+1, seed);
double v101 = noise3d(x0+1, y0, z0+1, seed);
double v011 = noise3d(x0, y0+1, z0+1, seed);
double v111 = noise3d(x0+1, y0+1, z0+1, seed);
float v000 = noise3d(x0, y0, z0, seed);
float v100 = noise3d(x0 + 1, y0, z0, seed);
float v010 = noise3d(x0, y0 + 1, z0, seed);
float v110 = noise3d(x0 + 1, y0 + 1, z0, seed);
float v001 = noise3d(x0, y0, z0 + 1, seed);
float v101 = noise3d(x0 + 1, y0, z0 + 1, seed);
float v011 = noise3d(x0, y0 + 1, z0 + 1, seed);
float v111 = noise3d(x0 + 1, y0 + 1, z0 + 1, seed);
// Interpolate
return triLinearInterpolation(v000,v100,v010,v110,v001,v101,v011,v111,xl,yl,zl);
return triLinearInterpolation(v000, v100, v010, v110,
v001, v101, v011, v111,
xl, yl, zl);
}
double noise2d_perlin(double x, double y, int seed,
int octaves, double persistence)
float noise2d_perlin(float x, float y, int seed,
int octaves, float persistence)
{
double a = 0;
double f = 1.0;
double g = 1.0;
for(int i=0; i<octaves; i++)
float a = 0;
float f = 1.0;
float g = 1.0;
for (int i = 0; i < octaves; i++)
{
a += g * noise2d_gradient(x*f, y*f, seed+i);
a += g * noise2d_gradient(x * f, y * f, seed + i);
f *= 2.0;
g *= persistence;
}
return a;
}
double noise2d_perlin_abs(double x, double y, int seed,
int octaves, double persistence)
float noise2d_perlin_abs(float x, float y, int seed,
int octaves, float persistence)
{
double a = 0;
double f = 1.0;
double g = 1.0;
for(int i=0; i<octaves; i++)
float a = 0;
float f = 1.0;
float g = 1.0;
for (int i = 0; i < octaves; i++)
{
a += g * fabs(noise2d_gradient(x*f, y*f, seed+i));
a += g * fabs(noise2d_gradient(x * f, y * f, seed + i));
f *= 2.0;
g *= persistence;
}
return a;
}
double noise3d_perlin(double x, double y, double z, int seed,
int octaves, double persistence)
float noise3d_perlin(float x, float y, float z, int seed,
int octaves, float persistence)
{
double a = 0;
double f = 1.0;
double g = 1.0;
for(int i=0; i<octaves; i++)
float a = 0;
float f = 1.0;
float g = 1.0;
for (int i = 0; i < octaves; i++)
{
a += g * noise3d_gradient(x*f, y*f, z*f, seed+i);
a += g * noise3d_gradient(x * f, y * f, z * f, seed + i);
f *= 2.0;
g *= persistence;
}
return a;
}
double noise3d_perlin_abs(double x, double y, double z, int seed,
int octaves, double persistence)
float noise3d_perlin_abs(float x, float y, float z, int seed,
int octaves, float persistence)
{
double a = 0;
double f = 1.0;
double g = 1.0;
for(int i=0; i<octaves; i++)
float a = 0;
float f = 1.0;
float g = 1.0;
for (int i = 0; i < octaves; i++)
{
a += g * fabs(noise3d_gradient(x*f, y*f, z*f, seed+i));
a += g * fabs(noise3d_gradient(x * f, y * f, z * f, seed + i));
f *= 2.0;
g *= persistence;
}
return a;
}
// -1->0, 0->1, 1->0
double contour(double v)
float contour(float v)
{
v = fabs(v);
if(v >= 1.0)
@ -231,195 +265,276 @@ double contour(double v)
return (1.0-v);
}
double noise3d_param(const NoiseParams &param, double x, double y, double z)
{
double s = param.pos_scale;
x /= s;
y /= s;
z /= s;
if(param.type == NOISE_CONSTANT_ONE)
{
return 1.0;
}
else if(param.type == NOISE_PERLIN)
{
return param.noise_scale*noise3d_perlin(x,y,z, param.seed,
param.octaves,
param.persistence);
}
else if(param.type == NOISE_PERLIN_ABS)
{
return param.noise_scale*noise3d_perlin_abs(x,y,z, param.seed,
param.octaves,
param.persistence);
}
else if(param.type == NOISE_PERLIN_CONTOUR)
{
return contour(param.noise_scale*noise3d_perlin(x,y,z,
param.seed, param.octaves,
param.persistence));
}
else if(param.type == NOISE_PERLIN_CONTOUR_FLIP_YZ)
{
return contour(param.noise_scale*noise3d_perlin(x,z,y,
param.seed, param.octaves,
param.persistence));
}
else assert(0);
///////////////////////// [ New perlin stuff ] ////////////////////////////
Noise::Noise(NoiseParams *np, int seed, int sx, int sy) {
int nlx, nly;
float ofactor;
//maximum possible spread value factor
ofactor = (float)(1 << (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)(sx * ofactor / np->spread.X) + 3;
nly = (int)(sy * ofactor / np->spread.Y) + 3;
this->np = np;
this->seed = seed;
this->sx = sx;
this->sy = sy;
this->sz = 0;
this->noisebuf = new float[nlx * nly];
this->buf = new float[sx * sy];
this->result = new float[sx * sy];
}
Noise::Noise(NoiseParams *np, int seed, int sx, int sy, int sz) {
int nlx, nly, nlz;
float ofactor;
ofactor = (float)(1 << (np->octaves - 1));
nlx = (int)(sx * ofactor / np->spread.X) + 3;
nly = (int)(sy * ofactor / np->spread.Y) + 3;
nlz = (int)(sz * ofactor / np->spread.Z) + 3;
this->np = np;
this->seed = seed;
this->sx = sx;
this->sy = sy;
this->sz = sz;
this->noisebuf = new float[nlx * nly * nlz];
this->buf = new float[sx * sy * sz];
this->result = new float[sx * sy * sz];
}
Noise::~Noise() {
delete[] buf;
delete[] result;
delete[] noisebuf;
}
/*
NoiseBuffer
*/
* NB: This algorithm is not optimal in terms of space complexity. The entire
* integer lattice of noise points could be done as 2 lines instead, and for 3D,
* 2 lines + 2 planes.
* However, this would require the noise calls to be interposed with the
* interpolation loops, which may trash the icache, leading to lower overall
* performance.
* Another optimization that could save half as many noise calls is to carry over
* values from the previous noise lattice as midpoints in the new lattice for the
* next octave.
*/
void Noise::gradientMap2D(float x, float y, float step_x, float step_y, int seed) {
float v00, v01, v10, v11, u, v, orig_u;
int index, i, j, x0, y0, noisex, noisey;
int nlx, nly;
NoiseBuffer::NoiseBuffer():
m_data(NULL)
{
}
x0 = floor(x);
y0 = floor(y);
u = x - (float)x0;
v = y - (float)y0;
orig_u = u;
NoiseBuffer::~NoiseBuffer()
{
clear();
}
//calculate noise point lattice
void NoiseBuffer::clear()
{
if(m_data)
delete[] m_data;
m_data = NULL;
m_size_x = 0;
m_size_y = 0;
m_size_z = 0;
}
nlx = (int)(u + sx * step_x) + 2;
nly = (int)(v + sy * step_y) + 2;
index = 0;
for (j = 0; j != nly; j++)
for (i = 0; i != nlx; i++)
noisebuf[index++] = noise2d(x0 + i, y0 + j, seed);
void NoiseBuffer::create(const NoiseParams &param,
double first_x, double first_y, double first_z,
double last_x, double last_y, double last_z,
double samplelength_x, double samplelength_y, double samplelength_z)
{
clear();
//calculate interpolations
noisey = 0;
for (j = 0; j != sy; j++) {
v00 = noisebuf[noisey * nlx];
v10 = noisebuf[noisey * nlx + 1];
v01 = noisebuf[(noisey + 1) * nlx];
v11 = noisebuf[(noisey + 1) * nlx + 1];
m_start_x = first_x - samplelength_x;
m_start_y = first_y - samplelength_y;
m_start_z = first_z - samplelength_z;
m_samplelength_x = samplelength_x;
m_samplelength_y = samplelength_y;
m_samplelength_z = samplelength_z;
u = orig_u;
noisex = 0;
for (i = 0; i != sx; i++) {
buf[j * sx + i] = biLinearInterpolation(v00, v10, v01, v11, u, v);
u += step_x;
if (u >= 1.0) {
u -= 1.0;
noisex++;
v00 = v10;
v01 = v11;
v10 = noisebuf[noisey * nlx + noisex + 1];
v11 = noisebuf[(noisey + 1) * nlx + noisex + 1];
}
}
m_size_x = (last_x - m_start_x)/samplelength_x + 2;
m_size_y = (last_y - m_start_y)/samplelength_y + 2;
m_size_z = (last_z - m_start_z)/samplelength_z + 2;
m_data = new double[m_size_x*m_size_y*m_size_z];
for(int x=0; x<m_size_x; x++)
for(int y=0; y<m_size_y; y++)
for(int z=0; z<m_size_z; z++)
{
double xd = (m_start_x + (double)x*m_samplelength_x);
double yd = (m_start_y + (double)y*m_samplelength_y);
double zd = (m_start_z + (double)z*m_samplelength_z);
double a = noise3d_param(param, xd,yd,zd);
intSet(x,y,z, a);
v += step_y;
if (v >= 1.0) {
v -= 1.0;
noisey++;
}
}
}
void NoiseBuffer::multiply(const NoiseParams &param)
{
assert(m_data != NULL);
for(int x=0; x<m_size_x; x++)
for(int y=0; y<m_size_y; y++)
for(int z=0; z<m_size_z; z++)
{
double xd = (m_start_x + (double)x*m_samplelength_x);
double yd = (m_start_y + (double)y*m_samplelength_y);
double zd = (m_start_z + (double)z*m_samplelength_z);
double a = noise3d_param(param, xd,yd,zd);
intMultiply(x,y,z, a);
void Noise::gradientMap3D(float x, float y, float z,
float step_x, float step_y, float step_z,
int seed) {
float v000, v010, v100, v110;
float v001, v011, v101, v111;
float u, v, w, orig_u, orig_w;
int index, i, j, k, x0, y0, z0, noisex, noisey, noisez;
int nlx, nly, nlz;
x0 = floor(x);
y0 = floor(y);
z0 = floor(z);
u = x - (float)x0;
v = y - (float)y0;
w = z - (float)z0;
orig_u = u;
orig_w = w;
//calculate noise point lattice
nlx = (int)(u + sx * step_x) + 2;
nly = (int)(v + sy * step_y) + 2;
nlz = (int)(v + sy * step_z) + 2;
index = 0;
for (k = 0; k != nlz; k++)
for (j = 0; j != nly; j++)
for (i = 0; i != nlx; i++)
noisebuf[index++] = noise3d(x0 + i, y0 + j, z0 + k, seed);
#define index(x, y, z) ((z) * nly * nlx + (y) * nlx + (x))
//calculate interpolations
noisey = 0;
noisez = 0;
for (k = 0; k != sz; k++) {
v000 = noisebuf[index(0, noisey, noisez)];
v100 = noisebuf[index(1, noisey, noisez)];
v010 = noisebuf[index(0, noisey + 1, noisez)];
v110 = noisebuf[index(1, noisey + 1, noisez)];
v001 = noisebuf[index(0, noisey, noisez + 1)];
v101 = noisebuf[index(1, noisey, noisez + 1)];
v011 = noisebuf[index(0, noisey + 1, noisez + 1)];
v111 = noisebuf[index(1, noisey + 1, noisez + 1)];
w = orig_w;
noisey = 0;
for (j = 0; j != sy; j++) {
v000 = noisebuf[index(0, noisey, noisez)];
v100 = noisebuf[index(1, noisey, noisez)];
v010 = noisebuf[index(0, noisey + 1, noisez)];
v110 = noisebuf[index(1, noisey + 1, noisez)];
v001 = noisebuf[index(0, noisey, noisez + 1)];
v101 = noisebuf[index(1, noisey, noisez + 1)];
v011 = noisebuf[index(0, noisey + 1, noisez + 1)];
v111 = noisebuf[index(1, noisey + 1, noisez + 1)];
u = orig_u;
noisex = 0;
for (i = 0; i != sx; i++) {
buf[j * sx + i] = triLinearInterpolation(
v000, v100, v010, v110,
v001, v101, v011, v111,
u, v, w);
u += step_x;
if (u >= 1.0) {
u -= 1.0;
noisex++;
v000 = v100;
v010 = v110;
v100 = noisebuf[index(noisex + 1, noisey, noisez)];
v110 = noisebuf[index(noisex + 1, noisey + 1, noisez)];
v001 = v101;
v011 = v111;
v101 = noisebuf[index(noisex + 1, noisey, noisez + 1)];
v111 = noisebuf[index(noisex + 1, noisey + 1, noisez + 1)];
}
}
v += step_y;
if (v >= 1.0) {
v -= 1.0;
noisey++;
}
}
w += step_z;
if (w >= 1.0) {
w -= 1.0;
noisez++;
}
}
}
// Deprecated
void NoiseBuffer::create(int seed, int octaves, double persistence,
bool abs,
double first_x, double first_y, double first_z,
double last_x, double last_y, double last_z,
double samplelength_x, double samplelength_y, double samplelength_z)
{
NoiseParams param;
param.type = abs ? NOISE_PERLIN_ABS : NOISE_PERLIN;
param.seed = seed;
param.octaves = octaves;
param.persistence = persistence;
create(param, first_x, first_y, first_z,
last_x, last_y, last_z,
samplelength_x, samplelength_y, samplelength_z);
float *Noise::perlinMap2D(float x, float y) {
float a = 0.0, f = 1.0, g = 1.0;
int i, j, index, oct;
x /= np->spread.X;
y /= np->spread.Y;
memset(result, 0, sizeof(float) * sx * sy);
for (oct = 0; oct < np->octaves; oct++) {
gradientMap2D(x * f, y * f,
f / np->spread.X, f / np->spread.Y,
seed + np->seed + oct);
index = 0;
for (j = 0; j != sy; j++) {
for (i = 0; i != sx; i++) {
result[index] += g * buf[index];
index++;
}
}
f *= 2.0;
g *= np->persist;
}
return result;
}
void NoiseBuffer::intSet(int x, int y, int z, double d)
{
int i = m_size_x*m_size_y*z + m_size_x*y + x;
assert(i >= 0);
assert(i < m_size_x*m_size_y*m_size_z);
m_data[i] = d;
float *Noise::perlinMap3D(float x, float y, float z) {
float a = 0.0, f = 1.0, g = 1.0;
int i, j, k, index, oct;
x /= np->spread.X;
y /= np->spread.Y;
z /= np->spread.Z;
memset(result, 0, sizeof(float) * sx * sy * sz);
for (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);
index = 0;
for (k = 0; k != sz; k++) {
for (j = 0; j != sy; j++) {
for (i = 0; i != sx; i++) {
result[index] += g * buf[index];
index++;
}
}
}
f *= 2.0;
g *= np->persist;
}
return result;
}
void NoiseBuffer::intMultiply(int x, int y, int z, double d)
{
int i = m_size_x*m_size_y*z + m_size_x*y + x;
assert(i >= 0);
assert(i < m_size_x*m_size_y*m_size_z);
m_data[i] = m_data[i] * d;
}
double NoiseBuffer::intGet(int x, int y, int z)
{
int i = m_size_x*m_size_y*z + m_size_x*y + x;
assert(i >= 0);
assert(i < m_size_x*m_size_y*m_size_z);
return m_data[i];
}
double NoiseBuffer::get(double x, double y, double z)
{
x -= m_start_x;
y -= m_start_y;
z -= m_start_z;
x /= m_samplelength_x;
y /= m_samplelength_y;
z /= m_samplelength_z;
// Calculate the integer coordinates
int x0 = (x > 0.0 ? (int)x : (int)x - 1);
int y0 = (y > 0.0 ? (int)y : (int)y - 1);
int z0 = (z > 0.0 ? (int)z : (int)z - 1);
// Calculate the remaining part of the coordinates
double xl = x - (double)x0;
double yl = y - (double)y0;
double zl = z - (double)z0;
// Get values for corners of cube
double v000 = intGet(x0, y0, z0);
double v100 = intGet(x0+1, y0, z0);
double v010 = intGet(x0, y0+1, z0);
double v110 = intGet(x0+1, y0+1, z0);
double v001 = intGet(x0, y0, z0+1);
double v101 = intGet(x0+1, y0, z0+1);
double v011 = intGet(x0, y0+1, z0+1);
double v111 = intGet(x0+1, y0+1, z0+1);
// Interpolate
return triLinearInterpolation(v000,v100,v010,v110,v001,v101,v011,v111,xl,yl,zl);
}
/*bool NoiseBuffer::contains(double x, double y, double z)
{
x -= m_start_x;
y -= m_start_y;
z -= m_start_z;
x /= m_samplelength_x;
y /= m_samplelength_y;
z /= m_samplelength_z;
if(x <= 0.0 || x >= m_size_x)
}*/

View File

@ -21,6 +21,7 @@ with this program; if not, write to the Free Software Foundation, Inc.,
#define NOISE_HEADER
#include "debug.h"
#include "irr_v3d.h"
class PseudoRandom
{
@ -59,91 +60,69 @@ private:
int m_next;
};
double easeCurve(double t);
// Return value: -1 ... 1
double noise2d(int x, int y, int seed);
double noise3d(int x, int y, int z, int seed);
double noise2d_gradient(double x, double y, int seed);
double noise3d_gradient(double x, double y, double z, int seed);
double noise2d_perlin(double x, double y, int seed,
int octaves, double persistence);
double noise2d_perlin_abs(double x, double y, int seed,
int octaves, double persistence);
double noise3d_perlin(double x, double y, double z, int seed,
int octaves, double persistence);
double noise3d_perlin_abs(double x, double y, double z, int seed,
int octaves, double persistence);
enum NoiseType
{
NOISE_CONSTANT_ONE,
NOISE_PERLIN,
NOISE_PERLIN_ABS,
NOISE_PERLIN_CONTOUR,
NOISE_PERLIN_CONTOUR_FLIP_YZ,
};
struct NoiseParams
{
NoiseType type;
struct NoiseParams {
float offset;
float scale;
v3f spread;
int seed;
int octaves;
double persistence;
double pos_scale;
double noise_scale; // Useful for contour noises
NoiseParams(NoiseType type_=NOISE_PERLIN, int seed_=0,
int octaves_=3, double persistence_=0.5,
double pos_scale_=100.0, double noise_scale_=1.0):
type(type_),
seed(seed_),
octaves(octaves_),
persistence(persistence_),
pos_scale(pos_scale_),
noise_scale(noise_scale_)
{
}
float persist;
};
double noise3d_param(const NoiseParams &param, double x, double y, double z);
class NoiseBuffer
{
class Noise {
public:
NoiseBuffer();
~NoiseBuffer();
NoiseParams *np;
int seed;
int sx;
int sy;
int sz;
float *noisebuf;
float *buf;
float *result;
void clear();
void create(const NoiseParams &param,
double first_x, double first_y, double first_z,
double last_x, double last_y, double last_z,
double samplelength_x, double samplelength_y, double samplelength_z);
void multiply(const NoiseParams &param);
// Deprecated
void create(int seed, int octaves, double persistence,
bool abs,
double first_x, double first_y, double first_z,
double last_x, double last_y, double last_z,
double samplelength_x, double samplelength_y, double samplelength_z);
Noise(NoiseParams *np, int seed, int sx, int sy);
Noise(NoiseParams *np, int seed, int sx, int sy, int sz);
~Noise();
void intSet(int x, int y, int z, double d);
void intMultiply(int x, int y, int z, double d);
double intGet(int x, int y, int z);
double get(double x, double y, double z);
//bool contains(double x, double y, double z);
private:
double *m_data;
double m_start_x, m_start_y, m_start_z;
double m_samplelength_x, m_samplelength_y, m_samplelength_z;
int m_size_x, m_size_y, m_size_z;
void gradientMap2D(
float x, float y,
float step_x, float step_y,
int seed);
void gradientMap3D(
float x, float y, float z,
float step_x, float step_y, float step_z,
int seed);
float *perlinMap2D(float x, float y);
float *perlinMap3D(float x, float y, float z);
};
// Return value: -1 ... 1
float noise2d(int x, int y, int seed);
float noise3d(int x, int y, int z, int seed);
float noise2d_gradient(float x, float y, int seed);
float noise3d_gradient(float x, float y, float z, int seed);
float noise2d_perlin(float x, float y, int seed,
int octaves, float persistence);
float noise2d_perlin_abs(float x, float y, int seed,
int octaves, float persistence);
float noise3d_perlin(float x, float y, float z, int seed,
int octaves, float persistence);
float noise3d_perlin_abs(float x, float y, float z, int seed,
int octaves, float persistence);
inline float easeCurve(float t) {
return t * t * t * (t * (6.f * t - 15.f) + 10.f);
}
#define NoisePerlin2D(np, x, y, s) ((np)->offset + (np)->scale * \
noise2d_perlin((float)(x) * (np)->spread.X, (float)(y) * (np)->spread.Y, \
(s) + (np)->seed, (np)->octaves, (np)->persist))
#endif

View File

@ -3240,8 +3240,8 @@ class LuaPerlinNoise
private:
int seed;
int octaves;
double persistence;
double scale;
float persistence;
float scale;
static const char className[];
static const luaL_reg methods[];
@ -3273,8 +3273,8 @@ private:
}
public:
LuaPerlinNoise(int a_seed, int a_octaves, double a_persistence,
double a_scale):
LuaPerlinNoise(int a_seed, int a_octaves, float a_persistence,
float a_scale):
seed(a_seed),
octaves(a_octaves),
persistence(a_persistence),
@ -3292,8 +3292,8 @@ public:
{
int seed = luaL_checkint(L, 1);
int octaves = luaL_checkint(L, 2);
double persistence = luaL_checknumber(L, 3);
double scale = luaL_checknumber(L, 4);
float persistence = luaL_checknumber(L, 3);
float scale = luaL_checknumber(L, 4);
LuaPerlinNoise *o = new LuaPerlinNoise(seed, octaves, persistence, scale);
*(void **)(lua_newuserdata(L, sizeof(void *))) = o;
luaL_getmetatable(L, className);
@ -3999,8 +3999,8 @@ private:
int seeddiff = luaL_checkint(L, 2);
int octaves = luaL_checkint(L, 3);
double persistence = luaL_checknumber(L, 4);
double scale = luaL_checknumber(L, 5);
float persistence = luaL_checknumber(L, 4);
float scale = luaL_checknumber(L, 5);
LuaPerlinNoise *n = new LuaPerlinNoise(seeddiff + int(env->getServerMap().getSeed()), octaves, persistence, scale);
*(void **)(lua_newuserdata(L, sizeof(void *))) = n;

View File

@ -39,6 +39,7 @@ with this program; if not, write to the Free Software Foundation, Inc.,
#include "itemdef.h"
#include "craftdef.h"
#include "mapgen.h"
#include "biome.h"
#include "content_mapnode.h"
#include "content_nodemeta.h"
#include "content_abm.h"
@ -169,6 +170,10 @@ void * EmergeThread::Thread()
v3s16 last_tried_pos(-32768,-32768,-32768); // For error output
ServerMap &map = ((ServerMap&)m_server->m_env->getMap());
EmergeManager *emerge = m_server->m_emerge;
Mapgen *mapgen = new Mapgen( m_server->m_emerge->biomedef,/*mapgenid*/ 0, map.getSeed()); ////////fix this...!
/*
Get block info from queue, emerge them and send them
to clients.
@ -233,7 +238,7 @@ void * EmergeThread::Thread()
<<"("<<p.X<<","<<p.Y<<","<<p.Z<<") "
<<"only_from_disk="<<only_from_disk<<std::endl;
ServerMap &map = ((ServerMap&)m_server->m_env->getMap());
MapBlock *block = NULL;
bool got_block = true;
@ -245,7 +250,7 @@ void * EmergeThread::Thread()
*/
bool started_generate = false;
mapgen::BlockMakeData data;
BlockMakeData data;
{
JMutexAutoLock envlock(m_server->m_env_mutex);
@ -287,7 +292,8 @@ void * EmergeThread::Thread()
SPT_AVG);
TimeTaker t("mapgen::make_block()");
mapgen::make_block(&data);
mapgen->makeChunk(&data);
//mapgen::make_block(&data);
if(enable_mapgen_debug_info == false)
t.stop(true); // Hide output
@ -332,7 +338,7 @@ void * EmergeThread::Thread()
{
TimeTaker timer("on_generated");
scriptapi_environment_on_generated(m_server->m_lua,
minp, maxp, mapgen::get_blockseed(data.seed, minp));
minp, maxp, emerge->getBlockSeed(minp));
/*int t = timer.stop(true);
dstream<<"on_generated took "<<t<<"ms"<<std::endl;*/
}
@ -937,6 +943,7 @@ Server::Server(
m_rollback(NULL),
m_rollback_sink_enabled(true),
m_enable_rollback_recording(false),
m_emerge(NULL),
m_lua(NULL),
m_itemdef(createItemDefManager()),
m_nodedef(createNodeDefManager()),
@ -976,6 +983,9 @@ Server::Server(
infostream<<"- config: "<<m_path_config<<std::endl;
infostream<<"- game: "<<m_gamespec.path<<std::endl;
// Create emerge manager
m_emerge = new EmergeManager(this);
// Create rollback manager
std::string rollback_path = m_path_world+DIR_DELIM+"rollback.txt";
m_rollback = createRollbackManager(rollback_path, this);
@ -1082,9 +1092,12 @@ Server::Server(
// Apply item aliases in the node definition manager
m_nodedef->updateAliases(m_itemdef);
// Add default biomes after nodedef had its aliases added
m_emerge->biomedef->addDefaultBiomes();
// Initialize Environment
m_env = new ServerEnvironment(new ServerMap(path_world, this), m_lua,
m_env = new ServerEnvironment(new ServerMap(path_world, this, m_emerge), m_lua,
this, this);
// Give environment reference to scripting api
@ -1184,6 +1197,7 @@ Server::~Server()
i = m_clients.getIterator();
i.atEnd() == false; i++)
{
// Delete client
delete i.getNode()->getValue();
}
@ -1192,6 +1206,7 @@ Server::~Server()
// Delete things in the reverse order of creation
delete m_env;
delete m_rollback;
delete m_emerge;
delete m_event;
delete m_itemdef;
delete m_nodedef;
@ -4832,7 +4847,7 @@ v3f findSpawnPos(ServerMap &map)
#endif
#if 1
s16 water_level = g_settings->getS16("water_level");
s16 water_level = map.m_emerge->water_level; //g_settings->getS16("default_water_level");
// Try to find a good place a few times
for(s32 i=0; i<1000; i++)

View File

@ -739,6 +739,9 @@ private:
bool m_rollback_sink_enabled;
bool m_enable_rollback_recording; // Updated once in a while
// Emerge manager
EmergeManager *m_emerge;
// Scripting
// Envlock and conlock should be locked when using Lua
lua_State *m_lua;

View File

@ -574,10 +574,7 @@ public:
set(name, "false");
}
void setS32(std::string name, s32 value)
{
set(name, itos(value));
}
void setFloat(std::string name, float value)
{
@ -598,6 +595,16 @@ public:
set(name, os.str());
}
void setS16(std::string name, s16 value)
{
set(name, itos(value));
}
void setS32(std::string name, s32 value)
{
set(name, itos(value));
}
void setU64(std::string name, u64 value)
{
std::ostringstream os;

View File

@ -120,6 +120,7 @@ inline s16 rangelim(s16 i, s16 max)
}
#define rangelim(d, min, max) ((d) < (min) ? (min) : ((d)>(max)?(max):(d)))
#define myfloor(x) ((x) > 0.0 ? (int)(x) : (int)(x) - 1)
inline v3s16 arealim(v3s16 p, s16 d)
{