Merge remote-tracking branch 'upstream/master'
commit
3156ae1e8c
|
@ -18,10 +18,11 @@ function VoxelArea:new(o)
|
|||
end
|
||||
|
||||
function VoxelArea:getExtent()
|
||||
local MaxEdge, MinEdge = self.MaxEdge, self.MinEdge
|
||||
return {
|
||||
x = self.MaxEdge.x - self.MinEdge.x + 1,
|
||||
y = self.MaxEdge.y - self.MinEdge.y + 1,
|
||||
z = self.MaxEdge.z - self.MinEdge.z + 1,
|
||||
x = MaxEdge.x - MinEdge.x + 1,
|
||||
y = MaxEdge.y - MinEdge.y + 1,
|
||||
z = MaxEdge.z - MinEdge.z + 1,
|
||||
}
|
||||
end
|
||||
|
||||
|
@ -31,45 +32,50 @@ function VoxelArea:getVolume()
|
|||
end
|
||||
|
||||
function VoxelArea:index(x, y, z)
|
||||
local i = (z - self.MinEdge.z) * self.zstride +
|
||||
(y - self.MinEdge.y) * self.ystride +
|
||||
(x - self.MinEdge.x) + 1
|
||||
local MinEdge = self.MinEdge
|
||||
local i = (z - MinEdge.z) * self.zstride +
|
||||
(y - MinEdge.y) * self.ystride +
|
||||
(x - MinEdge.x) + 1
|
||||
return math.floor(i)
|
||||
end
|
||||
|
||||
function VoxelArea:indexp(p)
|
||||
local i = (p.z - self.MinEdge.z) * self.zstride +
|
||||
(p.y - self.MinEdge.y) * self.ystride +
|
||||
(p.x - self.MinEdge.x) + 1
|
||||
local MinEdge = self.MinEdge
|
||||
local i = (p.z - MinEdge.z) * self.zstride +
|
||||
(p.y - MinEdge.y) * self.ystride +
|
||||
(p.x - MinEdge.x) + 1
|
||||
return math.floor(i)
|
||||
end
|
||||
|
||||
function VoxelArea:position(i)
|
||||
local p = {}
|
||||
local MinEdge = self.MinEdge
|
||||
|
||||
i = i - 1
|
||||
|
||||
p.z = math.floor(i / self.zstride) + self.MinEdge.z
|
||||
p.z = math.floor(i / self.zstride) + MinEdge.z
|
||||
i = i % self.zstride
|
||||
|
||||
p.y = math.floor(i / self.ystride) + self.MinEdge.y
|
||||
p.y = math.floor(i / self.ystride) + MinEdge.y
|
||||
i = i % self.ystride
|
||||
|
||||
p.x = math.floor(i) + self.MinEdge.x
|
||||
p.x = math.floor(i) + MinEdge.x
|
||||
|
||||
return p
|
||||
end
|
||||
|
||||
function VoxelArea:contains(x, y, z)
|
||||
return (x >= self.MinEdge.x) and (x <= self.MaxEdge.x) and
|
||||
(y >= self.MinEdge.y) and (y <= self.MaxEdge.y) and
|
||||
(z >= self.MinEdge.z) and (z <= self.MaxEdge.z)
|
||||
local MaxEdge, MinEdge = self.MaxEdge, self.MinEdge
|
||||
return (x >= MinEdge.x) and (x <= MaxEdge.x) and
|
||||
(y >= MinEdge.y) and (y <= MaxEdge.y) and
|
||||
(z >= MinEdge.z) and (z <= MaxEdge.z)
|
||||
end
|
||||
|
||||
function VoxelArea:containsp(p)
|
||||
return (p.x >= self.MinEdge.x) and (p.x <= self.MaxEdge.x) and
|
||||
(p.y >= self.MinEdge.y) and (p.y <= self.MaxEdge.y) and
|
||||
(p.z >= self.MinEdge.z) and (p.z <= self.MaxEdge.z)
|
||||
local MaxEdge, MinEdge = self.MaxEdge, self.MinEdge
|
||||
return (p.x >= MinEdge.x) and (p.x <= MaxEdge.x) and
|
||||
(p.y >= MinEdge.y) and (p.y <= MaxEdge.y) and
|
||||
(p.z >= MinEdge.z) and (p.z <= MaxEdge.z)
|
||||
end
|
||||
|
||||
function VoxelArea:containsi(i)
|
||||
|
|
|
@ -2796,3 +2796,16 @@ ParticleSpawner definition (add_particlespawner)
|
|||
playername = "singleplayer"
|
||||
^ Playername is optional, if specified spawns particle only on the player's client
|
||||
}
|
||||
|
||||
NoiseParams definition (PerlinNoiseMap)
|
||||
{
|
||||
offset = 0,
|
||||
scale = 0,
|
||||
spread = 0,
|
||||
seed = 0,
|
||||
octaves = 0,
|
||||
^ A higher value will result in more details, this means more operations
|
||||
persist = 0,
|
||||
eased = false
|
||||
^ Whether it should create curves in 3D perlin maps
|
||||
}
|
||||
|
|
|
@ -425,15 +425,17 @@
|
|||
# Perlin noise attributes for different map generation parameters
|
||||
# Offset, scale, spread factor, seed offset, number of octaves, persistence
|
||||
|
||||
#mgv5_spflags = blobs
|
||||
#mgv5_np_filler_depth = 0, 1, (150, 150, 150), 261, 4, 0.7
|
||||
#mgv5_np_factor = 0, 1, (250, 250, 250), 920381, 3, 0.45
|
||||
#mgv5_np_height = 0, 10, (250, 250, 250), 84174, 4, 0.5
|
||||
#mgv5_np_cave1 = 0, 7.5, (50, 50, 50), 52534, 4, 0.5
|
||||
#mgv5_np_cave2 = 0, 7.5, (50, 50, 50), 10325, 4, 0.5
|
||||
#mgv5_np_cave1 = 0, 6, (50, 50, 50), 52534, 4, 0.5
|
||||
#mgv5_np_cave2 = 0, 6, (50, 50, 50), 10325, 4, 0.5
|
||||
#mgv5_np_ground = 0, 40, (80, 80, 80), 983240, 4, 0.55
|
||||
#mgv5_np_crumble = 0, 1, (20, 20, 20), 34413, 3, 1.3
|
||||
#mgv5_np_wetness = 0, 1, (40, 40, 40), 32474, 4, 1.1
|
||||
|
||||
#mgv6_spflags = biomeblend, jungles, mudflow
|
||||
#mgv6_np_terrain_base = -4, 20, (250, 250, 250), 82341, 5, 0.6
|
||||
#mgv6_np_terrain_higher = 20, 16, (500, 500, 500), 85039, 5, 0.6
|
||||
#mgv6_np_steepness = 0.85, 0.5, (125, 125, 125), -932, 5, 0.7
|
||||
|
|
|
@ -251,9 +251,13 @@ collisionMoveResult collisionMoveSimple(Environment *env, IGameDef *gamedef,
|
|||
for(s16 z = min_z; z <= max_z; z++)
|
||||
{
|
||||
v3s16 p(x,y,z);
|
||||
try{
|
||||
|
||||
bool is_position_valid;
|
||||
MapNode n = map->getNodeNoEx(p, &is_position_valid);
|
||||
|
||||
if (is_position_valid) {
|
||||
// Object collides into walkable nodes
|
||||
MapNode n = map->getNode(p);
|
||||
|
||||
const ContentFeatures &f = gamedef->getNodeDefManager()->get(n);
|
||||
if(f.walkable == false)
|
||||
continue;
|
||||
|
@ -275,8 +279,7 @@ collisionMoveResult collisionMoveSimple(Environment *env, IGameDef *gamedef,
|
|||
is_object.push_back(false);
|
||||
}
|
||||
}
|
||||
catch(InvalidPositionException &e)
|
||||
{
|
||||
else {
|
||||
// Collide with unloaded nodes
|
||||
aabb3f box = getNodeBox(p, BS);
|
||||
cboxes.push_back(box);
|
||||
|
|
|
@ -60,13 +60,12 @@ public:
|
|||
m_spritenode->setVisible(true);
|
||||
m_spritenode->setSize(size);
|
||||
/* Update brightness */
|
||||
u8 light = 64;
|
||||
try{
|
||||
MapNode n = env->getMap().getNode(floatToInt(pos, BS));
|
||||
light = decode_light(n.getLightBlend(env->getDayNightRatio(),
|
||||
env->getGameDef()->ndef()));
|
||||
}
|
||||
catch(InvalidPositionException &e){}
|
||||
u8 light;
|
||||
bool pos_ok;
|
||||
MapNode n = env->getMap().getNodeNoEx(floatToInt(pos, BS), &pos_ok);
|
||||
light = pos_ok ? decode_light(n.getLightBlend(env->getDayNightRatio(),
|
||||
env->getGameDef()->ndef()))
|
||||
: 64;
|
||||
video::SColor color(255,light,light,light);
|
||||
m_spritenode->setColor(color);
|
||||
}
|
||||
|
|
|
@ -40,8 +40,9 @@ with this program; if not, write to the Free Software Foundation, Inc.,
|
|||
#include "log.h"
|
||||
#include "nodedef.h"
|
||||
#include "mg_biome.h"
|
||||
#include "mg_decoration.h"
|
||||
#include "mg_ore.h"
|
||||
#include "mg_decoration.h"
|
||||
#include "mg_schematic.h"
|
||||
#include "mapgen_v5.h"
|
||||
#include "mapgen_v6.h"
|
||||
#include "mapgen_v7.h"
|
||||
|
@ -88,8 +89,11 @@ EmergeManager::EmergeManager(IGameDef *gamedef) {
|
|||
registerMapgen("v7", new MapgenFactoryV7());
|
||||
registerMapgen("singlenode", new MapgenFactorySinglenode());
|
||||
|
||||
this->ndef = gamedef->getNodeDefManager();
|
||||
this->biomedef = new BiomeDefManager(gamedef->getNodeDefManager()->getResolver());
|
||||
this->ndef = gamedef->getNodeDefManager();
|
||||
this->biomemgr = new BiomeManager(gamedef);
|
||||
this->oremgr = new OreManager(gamedef);
|
||||
this->decomgr = new DecorationManager(gamedef);
|
||||
this->schemmgr = new SchematicManager(gamedef);
|
||||
this->gennotify = 0;
|
||||
|
||||
// Note that accesses to this variable are not synchronized.
|
||||
|
@ -141,21 +145,15 @@ EmergeManager::~EmergeManager() {
|
|||
emergethread.clear();
|
||||
mapgen.clear();
|
||||
|
||||
for (unsigned int i = 0; i < ores.size(); i++)
|
||||
delete ores[i];
|
||||
ores.clear();
|
||||
|
||||
for (unsigned int i = 0; i < decorations.size(); i++)
|
||||
delete decorations[i];
|
||||
decorations.clear();
|
||||
|
||||
for (std::map<std::string, MapgenFactory *>::iterator it = mglist.begin();
|
||||
it != mglist.end(); ++it) {
|
||||
std::map<std::string, MapgenFactory *>::iterator it;
|
||||
for (it = mglist.begin(); it != mglist.end(); ++it)
|
||||
delete it->second;
|
||||
}
|
||||
mglist.clear();
|
||||
|
||||
delete biomedef;
|
||||
delete biomemgr;
|
||||
delete oremgr;
|
||||
delete decomgr;
|
||||
delete schemmgr;
|
||||
|
||||
if (params.sparams) {
|
||||
delete params.sparams;
|
||||
|
|
31
src/emerge.h
31
src/emerge.h
|
@ -23,8 +23,8 @@ with this program; if not, write to the Free Software Foundation, Inc.,
|
|||
#include <map>
|
||||
#include "irr_v3d.h"
|
||||
#include "util/container.h"
|
||||
#include "map.h" // for ManualMapVoxelManipulator
|
||||
#include "mapgen.h" // for MapgenParams
|
||||
#include "map.h"
|
||||
|
||||
#define MGPARAMS_SET_MGNAME 1
|
||||
#define MGPARAMS_SET_SEED 2
|
||||
|
@ -34,17 +34,20 @@ with this program; if not, write to the Free Software Foundation, Inc.,
|
|||
#define BLOCK_EMERGE_ALLOWGEN (1<<0)
|
||||
|
||||
#define EMERGE_DBG_OUT(x) \
|
||||
{ if (enable_mapgen_debug_info) \
|
||||
infostream << "EmergeThread: " x << std::endl; }
|
||||
do { \
|
||||
if (enable_mapgen_debug_info) \
|
||||
infostream << "EmergeThread: " x << std::endl; \
|
||||
} while (0)
|
||||
|
||||
class EmergeThread;
|
||||
class Biome;
|
||||
class BiomeDefManager;
|
||||
class Decoration;
|
||||
class Ore;
|
||||
class INodeDefManager;
|
||||
class Settings;
|
||||
|
||||
class BiomeManager;
|
||||
class OreManager;
|
||||
class DecorationManager;
|
||||
class SchematicManager;
|
||||
|
||||
struct BlockMakeData {
|
||||
ManualMapVoxelManipulator *vmanip;
|
||||
u64 seed;
|
||||
|
@ -88,16 +91,18 @@ public:
|
|||
|
||||
u32 gennotify;
|
||||
|
||||
//block emerge queue data structures
|
||||
//// Block emerge queue data structures
|
||||
JMutex queuemutex;
|
||||
std::map<v3s16, BlockEmergeData *> blocks_enqueued;
|
||||
std::map<u16, u16> peer_queue_count;
|
||||
|
||||
//Mapgen-related structures
|
||||
BiomeDefManager *biomedef;
|
||||
std::vector<Ore *> ores;
|
||||
std::vector<Decoration *> decorations;
|
||||
//// Managers of map generation-related components
|
||||
BiomeManager *biomemgr;
|
||||
OreManager *oremgr;
|
||||
DecorationManager *decomgr;
|
||||
SchematicManager *schemmgr;
|
||||
|
||||
//// Methods
|
||||
EmergeManager(IGameDef *gamedef);
|
||||
~EmergeManager();
|
||||
|
||||
|
@ -105,7 +110,7 @@ public:
|
|||
void initMapgens();
|
||||
Mapgen *getCurrentMapgen();
|
||||
Mapgen *createMapgen(std::string mgname, int mgid,
|
||||
MapgenParams *mgparams);
|
||||
MapgenParams *mgparams);
|
||||
MapgenSpecificParams *createMapgenParams(std::string mgname);
|
||||
void startThreads();
|
||||
void stopThreads();
|
||||
|
|
|
@ -2342,10 +2342,8 @@ void ClientEnvironment::step(float dtime)
|
|||
// (day: LIGHT_SUN, night: 0)
|
||||
MapNode node_at_lplayer(CONTENT_AIR, 0x0f, 0);
|
||||
|
||||
try {
|
||||
v3s16 p = lplayer->getLightPosition();
|
||||
node_at_lplayer = m_map->getNode(p);
|
||||
} catch (InvalidPositionException &e) {}
|
||||
v3s16 p = lplayer->getLightPosition();
|
||||
node_at_lplayer = m_map->getNodeNoEx(p);
|
||||
|
||||
u16 light = getInteriorLight(node_at_lplayer, 0, m_gamedef->ndef());
|
||||
u8 day = light & 0xff;
|
||||
|
@ -2371,15 +2369,16 @@ void ClientEnvironment::step(float dtime)
|
|||
{
|
||||
// Update lighting
|
||||
u8 light = 0;
|
||||
try{
|
||||
// Get node at head
|
||||
v3s16 p = obj->getLightPosition();
|
||||
MapNode n = m_map->getNode(p);
|
||||
bool pos_ok;
|
||||
|
||||
// Get node at head
|
||||
v3s16 p = obj->getLightPosition();
|
||||
MapNode n = m_map->getNodeNoEx(p, &pos_ok);
|
||||
if (pos_ok)
|
||||
light = n.getLightBlend(day_night_ratio, m_gamedef->ndef());
|
||||
}
|
||||
catch(InvalidPositionException &e){
|
||||
else
|
||||
light = blend_light(day_night_ratio, LIGHT_SUN, 0);
|
||||
}
|
||||
|
||||
obj->updateLight(light);
|
||||
}
|
||||
}
|
||||
|
@ -2470,15 +2469,16 @@ u16 ClientEnvironment::addActiveObject(ClientActiveObject *object)
|
|||
object->addToScene(m_smgr, m_texturesource, m_irr);
|
||||
{ // Update lighting immediately
|
||||
u8 light = 0;
|
||||
try{
|
||||
// Get node at head
|
||||
v3s16 p = object->getLightPosition();
|
||||
MapNode n = m_map->getNode(p);
|
||||
bool pos_ok;
|
||||
|
||||
// Get node at head
|
||||
v3s16 p = object->getLightPosition();
|
||||
MapNode n = m_map->getNodeNoEx(p, &pos_ok);
|
||||
if (pos_ok)
|
||||
light = n.getLightBlend(getDayNightRatio(), m_gamedef->ndef());
|
||||
}
|
||||
catch(InvalidPositionException &e){
|
||||
else
|
||||
light = blend_light(getDayNightRatio(), LIGHT_SUN, 0);
|
||||
}
|
||||
|
||||
object->updateLight(light);
|
||||
}
|
||||
return object->getId();
|
||||
|
|
310
src/game.cpp
310
src/game.cpp
|
@ -360,12 +360,11 @@ PointedThing getPointedThing(Client *client, v3f player_position,
|
|||
for (s16 z = zstart; z <= zend; z++)
|
||||
for (s16 x = xstart; x <= xend; x++) {
|
||||
MapNode n;
|
||||
bool is_valid_position;
|
||||
|
||||
try {
|
||||
n = map.getNode(v3s16(x, y, z));
|
||||
} catch (InvalidPositionException &e) {
|
||||
n = map.getNodeNoEx(v3s16(x, y, z), &is_valid_position);
|
||||
if (!is_valid_position)
|
||||
continue;
|
||||
}
|
||||
|
||||
if (!isPointableNode(n, client, liquids_pointable))
|
||||
continue;
|
||||
|
@ -873,22 +872,31 @@ bool nodePlacementPrediction(Client &client,
|
|||
std::string prediction = playeritem_def.node_placement_prediction;
|
||||
INodeDefManager *nodedef = client.ndef();
|
||||
ClientMap &map = client.getEnv().getClientMap();
|
||||
MapNode node;
|
||||
bool is_valid_position;
|
||||
|
||||
if (prediction != "" && !nodedef->get(map.getNode(nodepos)).rightclickable) {
|
||||
node = map.getNodeNoEx(nodepos, &is_valid_position);
|
||||
if (!is_valid_position)
|
||||
return false;
|
||||
|
||||
if (prediction != "" && !nodedef->get(node).rightclickable) {
|
||||
verbosestream << "Node placement prediction for "
|
||||
<< playeritem_def.name << " is "
|
||||
<< prediction << std::endl;
|
||||
v3s16 p = neighbourpos;
|
||||
|
||||
// Place inside node itself if buildable_to
|
||||
try {
|
||||
MapNode n_under = map.getNode(nodepos);
|
||||
|
||||
MapNode n_under = map.getNodeNoEx(nodepos, &is_valid_position);
|
||||
if (is_valid_position)
|
||||
{
|
||||
if (nodedef->get(n_under).buildable_to)
|
||||
p = nodepos;
|
||||
else if (!nodedef->get(map.getNode(p)).buildable_to)
|
||||
return false;
|
||||
} catch (InvalidPositionException &e) {}
|
||||
else {
|
||||
node = map.getNodeNoEx(p, &is_valid_position);
|
||||
if (is_valid_position &&!nodedef->get(node).buildable_to)
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
// Find id of predicted node
|
||||
content_t id;
|
||||
|
@ -946,7 +954,7 @@ bool nodePlacementPrediction(Client &client,
|
|||
else
|
||||
pp = p + v3s16(0, -1, 0);
|
||||
|
||||
if (!nodedef->get(map.getNode(pp)).walkable)
|
||||
if (!nodedef->get(map.getNodeNoEx(pp)).walkable)
|
||||
return false;
|
||||
}
|
||||
|
||||
|
@ -1181,9 +1189,119 @@ static void updateChat(Client &client, f32 dtime, bool show_debug,
|
|||
}
|
||||
|
||||
|
||||
/****************************************************************************
|
||||
Fast key cache for main game loop
|
||||
****************************************************************************/
|
||||
|
||||
/* This is faster than using getKeySetting with the tradeoff that functions
|
||||
* using it must make sure that it's initialised before using it and there is
|
||||
* no error handling (for example bounds checking). This is really intended for
|
||||
* use only in the main running loop of the client (the_game()) where the faster
|
||||
* (up to 10x faster) key lookup is an asset. Other parts of the codebase
|
||||
* (e.g. formspecs) should continue using getKeySetting().
|
||||
*/
|
||||
struct KeyCache {
|
||||
|
||||
KeyCache() { populate(); }
|
||||
|
||||
enum {
|
||||
// Player movement
|
||||
KEYMAP_ID_FORWARD,
|
||||
KEYMAP_ID_BACKWARD,
|
||||
KEYMAP_ID_LEFT,
|
||||
KEYMAP_ID_RIGHT,
|
||||
KEYMAP_ID_JUMP,
|
||||
KEYMAP_ID_SPECIAL1,
|
||||
KEYMAP_ID_SNEAK,
|
||||
|
||||
// Other
|
||||
KEYMAP_ID_DROP,
|
||||
KEYMAP_ID_INVENTORY,
|
||||
KEYMAP_ID_CHAT,
|
||||
KEYMAP_ID_CMD,
|
||||
KEYMAP_ID_CONSOLE,
|
||||
KEYMAP_ID_FREEMOVE,
|
||||
KEYMAP_ID_FASTMOVE,
|
||||
KEYMAP_ID_NOCLIP,
|
||||
KEYMAP_ID_SCREENSHOT,
|
||||
KEYMAP_ID_TOGGLE_HUD,
|
||||
KEYMAP_ID_TOGGLE_CHAT,
|
||||
KEYMAP_ID_TOGGLE_FORCE_FOG_OFF,
|
||||
KEYMAP_ID_TOGGLE_UPDATE_CAMERA,
|
||||
KEYMAP_ID_TOGGLE_DEBUG,
|
||||
KEYMAP_ID_TOGGLE_PROFILER,
|
||||
KEYMAP_ID_CAMERA_MODE,
|
||||
KEYMAP_ID_INCREASE_VIEWING_RANGE,
|
||||
KEYMAP_ID_DECREASE_VIEWING_RANGE,
|
||||
KEYMAP_ID_RANGESELECT,
|
||||
|
||||
KEYMAP_ID_QUICKTUNE_NEXT,
|
||||
KEYMAP_ID_QUICKTUNE_PREV,
|
||||
KEYMAP_ID_QUICKTUNE_INC,
|
||||
KEYMAP_ID_QUICKTUNE_DEC,
|
||||
|
||||
KEYMAP_ID_DEBUG_STACKS,
|
||||
|
||||
// Fake keycode for array size and internal checks
|
||||
KEYMAP_INTERNAL_ENUM_COUNT
|
||||
|
||||
|
||||
};
|
||||
|
||||
void populate();
|
||||
|
||||
KeyPress key[KEYMAP_INTERNAL_ENUM_COUNT];
|
||||
};
|
||||
|
||||
void KeyCache::populate()
|
||||
{
|
||||
key[KEYMAP_ID_FORWARD] = getKeySetting("keymap_forward");
|
||||
key[KEYMAP_ID_BACKWARD] = getKeySetting("keymap_backward");
|
||||
key[KEYMAP_ID_LEFT] = getKeySetting("keymap_left");
|
||||
key[KEYMAP_ID_RIGHT] = getKeySetting("keymap_right");
|
||||
key[KEYMAP_ID_JUMP] = getKeySetting("keymap_jump");
|
||||
key[KEYMAP_ID_SPECIAL1] = getKeySetting("keymap_special1");
|
||||
key[KEYMAP_ID_SNEAK] = getKeySetting("keymap_sneak");
|
||||
|
||||
key[KEYMAP_ID_DROP] = getKeySetting("keymap_drop");
|
||||
key[KEYMAP_ID_INVENTORY] = getKeySetting("keymap_inventory");
|
||||
key[KEYMAP_ID_CHAT] = getKeySetting("keymap_chat");
|
||||
key[KEYMAP_ID_CMD] = getKeySetting("keymap_cmd");
|
||||
key[KEYMAP_ID_CONSOLE] = getKeySetting("keymap_console");
|
||||
key[KEYMAP_ID_FREEMOVE] = getKeySetting("keymap_freemove");
|
||||
key[KEYMAP_ID_FASTMOVE] = getKeySetting("keymap_fastmove");
|
||||
key[KEYMAP_ID_NOCLIP] = getKeySetting("keymap_noclip");
|
||||
key[KEYMAP_ID_SCREENSHOT] = getKeySetting("keymap_screenshot");
|
||||
key[KEYMAP_ID_TOGGLE_HUD] = getKeySetting("keymap_toggle_hud");
|
||||
key[KEYMAP_ID_TOGGLE_CHAT] = getKeySetting("keymap_toggle_chat");
|
||||
key[KEYMAP_ID_TOGGLE_FORCE_FOG_OFF]
|
||||
= getKeySetting("keymap_toggle_force_fog_off");
|
||||
key[KEYMAP_ID_TOGGLE_UPDATE_CAMERA]
|
||||
= getKeySetting("keymap_toggle_update_camera");
|
||||
key[KEYMAP_ID_TOGGLE_DEBUG]
|
||||
= getKeySetting("keymap_toggle_debug");
|
||||
key[KEYMAP_ID_TOGGLE_PROFILER]
|
||||
= getKeySetting("keymap_toggle_profiler");
|
||||
key[KEYMAP_ID_CAMERA_MODE]
|
||||
= getKeySetting("keymap_camera_mode");
|
||||
key[KEYMAP_ID_INCREASE_VIEWING_RANGE]
|
||||
= getKeySetting("keymap_increase_viewing_range_min");
|
||||
key[KEYMAP_ID_DECREASE_VIEWING_RANGE]
|
||||
= getKeySetting("keymap_decrease_viewing_range_min");
|
||||
key[KEYMAP_ID_RANGESELECT]
|
||||
= getKeySetting("keymap_rangeselect");
|
||||
|
||||
key[KEYMAP_ID_QUICKTUNE_NEXT] = getKeySetting("keymap_quicktune_next");
|
||||
key[KEYMAP_ID_QUICKTUNE_PREV] = getKeySetting("keymap_quicktune_prev");
|
||||
key[KEYMAP_ID_QUICKTUNE_INC] = getKeySetting("keymap_quicktune_inc");
|
||||
key[KEYMAP_ID_QUICKTUNE_DEC] = getKeySetting("keymap_quicktune_dec");
|
||||
|
||||
key[KEYMAP_ID_DEBUG_STACKS] = getKeySetting("keymap_print_debug_stacks");
|
||||
}
|
||||
|
||||
|
||||
/****************************************************************************
|
||||
THE GAME
|
||||
|
||||
****************************************************************************/
|
||||
|
||||
const float object_hit_delay = 0.2;
|
||||
|
@ -1264,6 +1382,10 @@ struct VolatileRunFlags {
|
|||
};
|
||||
|
||||
|
||||
/****************************************************************************
|
||||
THE GAME
|
||||
****************************************************************************/
|
||||
|
||||
/* This is not intended to be a public class. If a public class becomes
|
||||
* desirable then it may be better to create another 'wrapper' class that
|
||||
* hides most of the stuff in this class (nothing in this class is required
|
||||
|
@ -1324,6 +1446,8 @@ protected:
|
|||
bool checkConnection();
|
||||
bool handleCallbacks();
|
||||
void processQueues();
|
||||
void updateProfilers(const GameRunData &run_data, const RunStats &stats,
|
||||
const FpsControl &draw_times, f32 dtime);
|
||||
void addProfilerGraphs(const RunStats &stats, const FpsControl &draw_times,
|
||||
f32 dtime);
|
||||
void updateStats(RunStats *stats, const FpsControl &draw_times, f32 dtime);
|
||||
|
@ -1458,6 +1582,10 @@ private:
|
|||
|
||||
std::wstring infotext;
|
||||
std::wstring statustext;
|
||||
|
||||
KeyCache keycache;
|
||||
|
||||
IntervalLimiter profiler_interval;
|
||||
};
|
||||
|
||||
Game::Game() :
|
||||
|
@ -1606,7 +1734,8 @@ void Game::run()
|
|||
|
||||
infotext = L"";
|
||||
hud->resizeHotbar();
|
||||
addProfilerGraphs(stats, draw_times, dtime);
|
||||
|
||||
updateProfilers(runData, stats, draw_times, dtime);
|
||||
processUserInput(&flags, &runData, dtime);
|
||||
// Update camera before player movement to avoid camera lag of one frame
|
||||
updateCameraDirection(&cam_view, &flags);
|
||||
|
@ -2186,6 +2315,11 @@ inline bool Game::handleCallbacks()
|
|||
g_gamecallback->keyconfig_requested = false;
|
||||
}
|
||||
|
||||
if (g_gamecallback->keyconfig_changed) {
|
||||
keycache.populate(); // update the cache with new settings
|
||||
g_gamecallback->keyconfig_changed = false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
|
@ -2198,6 +2332,34 @@ void Game::processQueues()
|
|||
}
|
||||
|
||||
|
||||
void Game::updateProfilers(const GameRunData &run_data, const RunStats &stats,
|
||||
const FpsControl &draw_times, f32 dtime)
|
||||
{
|
||||
float profiler_print_interval =
|
||||
g_settings->getFloat("profiler_print_interval");
|
||||
bool print_to_log = true;
|
||||
|
||||
if (profiler_print_interval == 0) {
|
||||
print_to_log = false;
|
||||
profiler_print_interval = 5;
|
||||
}
|
||||
|
||||
if (profiler_interval.step(dtime, profiler_print_interval)) {
|
||||
if (print_to_log) {
|
||||
infostream << "Profiler:" << std::endl;
|
||||
g_profiler->print(infostream);
|
||||
}
|
||||
|
||||
update_profiler_gui(guitext_profiler, font, text_height,
|
||||
run_data.profiler_current_page, run_data.profiler_max_page);
|
||||
|
||||
g_profiler->clear();
|
||||
}
|
||||
|
||||
addProfilerGraphs(stats, draw_times, dtime);
|
||||
}
|
||||
|
||||
|
||||
void Game::addProfilerGraphs(const RunStats &stats,
|
||||
const FpsControl &draw_times, f32 dtime)
|
||||
{
|
||||
|
@ -2322,70 +2484,63 @@ void Game::processKeyboardInput(VolatileRunFlags *flags,
|
|||
u32 *profiler_current_page,
|
||||
u32 profiler_max_page)
|
||||
{
|
||||
if (input->wasKeyDown(getKeySetting("keymap_drop"))) {
|
||||
|
||||
//TimeTaker tt("process kybd input", NULL, PRECISION_NANO);
|
||||
|
||||
if (input->wasKeyDown(keycache.key[KeyCache::KEYMAP_ID_DROP])) {
|
||||
dropSelectedItem();
|
||||
} else if (input->wasKeyDown(getKeySetting("keymap_inventory"))) {
|
||||
} else if (input->wasKeyDown(keycache.key[KeyCache::KEYMAP_ID_INVENTORY])) {
|
||||
openInventory();
|
||||
} else if (input->wasKeyDown(EscapeKey) || input->wasKeyDown(CancelKey)) {
|
||||
show_pause_menu(¤t_formspec, client, gamedef, texture_src, device,
|
||||
simple_singleplayer_mode);
|
||||
} else if (input->wasKeyDown(getKeySetting("keymap_chat"))) {
|
||||
} else if (input->wasKeyDown(keycache.key[KeyCache::KEYMAP_ID_CHAT])) {
|
||||
show_chat_menu(¤t_formspec, client, gamedef, texture_src, device,
|
||||
client, "");
|
||||
} else if (input->wasKeyDown(getKeySetting("keymap_cmd"))) {
|
||||
} else if (input->wasKeyDown(keycache.key[KeyCache::KEYMAP_ID_CMD])) {
|
||||
show_chat_menu(¤t_formspec, client, gamedef, texture_src, device,
|
||||
client, "/");
|
||||
} else if (input->wasKeyDown(getKeySetting("keymap_console"))) {
|
||||
} else if (input->wasKeyDown(keycache.key[KeyCache::KEYMAP_ID_CONSOLE])) {
|
||||
openConsole();
|
||||
} else if (input->wasKeyDown(getKeySetting("keymap_freemove"))) {
|
||||
} else if (input->wasKeyDown(keycache.key[KeyCache::KEYMAP_ID_FREEMOVE])) {
|
||||
toggleFreeMove(statustext_time);
|
||||
} else if (input->wasKeyDown(getKeySetting("keymap_jump"))) {
|
||||
} else if (input->wasKeyDown(keycache.key[KeyCache::KEYMAP_ID_JUMP])) {
|
||||
toggleFreeMoveAlt(statustext_time, jump_timer);
|
||||
*reset_jump_timer = true;
|
||||
} else if (input->wasKeyDown(getKeySetting("keymap_fastmove"))) {
|
||||
} else if (input->wasKeyDown(keycache.key[KeyCache::KEYMAP_ID_FASTMOVE])) {
|
||||
toggleFast(statustext_time);
|
||||
} else if (input->wasKeyDown(getKeySetting("keymap_noclip"))) {
|
||||
} else if (input->wasKeyDown(keycache.key[KeyCache::KEYMAP_ID_NOCLIP])) {
|
||||
toggleNoClip(statustext_time);
|
||||
} else if (input->wasKeyDown(getKeySetting("keymap_screenshot"))) {
|
||||
} else if (input->wasKeyDown(keycache.key[KeyCache::KEYMAP_ID_SCREENSHOT])) {
|
||||
client->makeScreenshot(device);
|
||||
} else if (input->wasKeyDown(getKeySetting("keymap_toggle_hud"))) {
|
||||
} else if (input->wasKeyDown(keycache.key[KeyCache::KEYMAP_ID_TOGGLE_HUD])) {
|
||||
toggleHud(statustext_time, &flags->show_hud);
|
||||
} else if (input->wasKeyDown(getKeySetting("keymap_toggle_chat"))) {
|
||||
} else if (input->wasKeyDown(keycache.key[KeyCache::KEYMAP_ID_TOGGLE_CHAT])) {
|
||||
toggleChat(statustext_time, &flags->show_chat);
|
||||
} else if (input->wasKeyDown(getKeySetting("keymap_toggle_force_fog_off"))) {
|
||||
} else if (input->wasKeyDown(keycache.key[KeyCache::KEYMAP_ID_TOGGLE_FORCE_FOG_OFF])) {
|
||||
toggleFog(statustext_time, &flags->force_fog_off);
|
||||
} else if (input->wasKeyDown(getKeySetting("keymap_toggle_update_camera"))) {
|
||||
} else if (input->wasKeyDown(keycache.key[KeyCache::KEYMAP_ID_TOGGLE_UPDATE_CAMERA])) {
|
||||
toggleUpdateCamera(statustext_time, &flags->disable_camera_update);
|
||||
} else if (input->wasKeyDown(getKeySetting("keymap_toggle_debug"))) {
|
||||
} else if (input->wasKeyDown(keycache.key[KeyCache::KEYMAP_ID_TOGGLE_DEBUG])) {
|
||||
toggleDebug(statustext_time, &flags->show_debug, &flags->show_profiler_graph);
|
||||
} else if (input->wasKeyDown(getKeySetting("keymap_toggle_profiler"))) {
|
||||
} else if (input->wasKeyDown(keycache.key[KeyCache::KEYMAP_ID_TOGGLE_PROFILER])) {
|
||||
toggleProfiler(statustext_time, profiler_current_page, profiler_max_page);
|
||||
} else if (input->wasKeyDown(getKeySetting("keymap_increase_viewing_range_min"))) {
|
||||
} else if (input->wasKeyDown(keycache.key[KeyCache::KEYMAP_ID_INCREASE_VIEWING_RANGE])) {
|
||||
increaseViewRange(statustext_time);
|
||||
} else if (input->wasKeyDown(getKeySetting("keymap_decrease_viewing_range_min"))) {
|
||||
} else if (input->wasKeyDown(keycache.key[KeyCache::KEYMAP_ID_DECREASE_VIEWING_RANGE])) {
|
||||
decreaseViewRange(statustext_time);
|
||||
} else if (input->wasKeyDown(getKeySetting("keymap_rangeselect"))) {
|
||||
} else if (input->wasKeyDown(keycache.key[KeyCache::KEYMAP_ID_RANGESELECT])) {
|
||||
toggleFullViewRange(statustext_time);
|
||||
}
|
||||
|
||||
// Handle QuicktuneShortcutter
|
||||
if (input->wasKeyDown(getKeySetting("keymap_quicktune_next")))
|
||||
} else if (input->wasKeyDown(keycache.key[KeyCache::KEYMAP_ID_QUICKTUNE_NEXT]))
|
||||
quicktune->next();
|
||||
else if (input->wasKeyDown(getKeySetting("keymap_quicktune_prev")))
|
||||
else if (input->wasKeyDown(keycache.key[KeyCache::KEYMAP_ID_QUICKTUNE_PREV]))
|
||||
quicktune->prev();
|
||||
else if (input->wasKeyDown(getKeySetting("keymap_quicktune_inc")))
|
||||
else if (input->wasKeyDown(keycache.key[KeyCache::KEYMAP_ID_QUICKTUNE_INC]))
|
||||
quicktune->inc();
|
||||
else if (input->wasKeyDown(getKeySetting("keymap_quicktune_dec")))
|
||||
else if (input->wasKeyDown(keycache.key[KeyCache::KEYMAP_ID_QUICKTUNE_DEC]))
|
||||
quicktune->dec();
|
||||
|
||||
std::string msg = quicktune->getMessage();
|
||||
if (msg != "") {
|
||||
statustext = narrow_to_wide(msg);
|
||||
*statustext_time = 0;
|
||||
}
|
||||
|
||||
// Print debug stacks
|
||||
if (input->wasKeyDown(getKeySetting("keymap_print_debug_stacks"))) {
|
||||
else if (input->wasKeyDown(keycache.key[KeyCache::KEYMAP_ID_DEBUG_STACKS])) {
|
||||
// Print debug stacks
|
||||
dstream << "-----------------------------------------"
|
||||
<< std::endl;
|
||||
dstream << DTIME << "Printing debug stacks:" << std::endl;
|
||||
|
@ -2398,6 +2553,14 @@ void Game::processKeyboardInput(VolatileRunFlags *flags,
|
|||
*reset_jump_timer = false;
|
||||
*jump_timer = 0.0;
|
||||
}
|
||||
|
||||
//tt.stop();
|
||||
|
||||
if (quicktune->hasMessage()) {
|
||||
std::string msg = quicktune->getMessage();
|
||||
statustext = narrow_to_wide(msg);
|
||||
*statustext_time = 0;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
@ -2730,14 +2893,16 @@ void Game::updateCameraDirection(CameraOrientation *cam,
|
|||
|
||||
void Game::updatePlayerControl(const CameraOrientation &cam)
|
||||
{
|
||||
//TimeTaker tt("update player control", NULL, PRECISION_NANO);
|
||||
|
||||
PlayerControl control(
|
||||
input->isKeyDown(getKeySetting("keymap_forward")),
|
||||
input->isKeyDown(getKeySetting("keymap_backward")),
|
||||
input->isKeyDown(getKeySetting("keymap_left")),
|
||||
input->isKeyDown(getKeySetting("keymap_right")),
|
||||
input->isKeyDown(getKeySetting("keymap_jump")),
|
||||
input->isKeyDown(getKeySetting("keymap_special1")),
|
||||
input->isKeyDown(getKeySetting("keymap_sneak")),
|
||||
input->isKeyDown(keycache.key[KeyCache::KEYMAP_ID_FORWARD]),
|
||||
input->isKeyDown(keycache.key[KeyCache::KEYMAP_ID_BACKWARD]),
|
||||
input->isKeyDown(keycache.key[KeyCache::KEYMAP_ID_LEFT]),
|
||||
input->isKeyDown(keycache.key[KeyCache::KEYMAP_ID_RIGHT]),
|
||||
input->isKeyDown(keycache.key[KeyCache::KEYMAP_ID_JUMP]),
|
||||
input->isKeyDown(keycache.key[KeyCache::KEYMAP_ID_SPECIAL1]),
|
||||
input->isKeyDown(keycache.key[KeyCache::KEYMAP_ID_SNEAK]),
|
||||
input->getLeftState(),
|
||||
input->getRightState(),
|
||||
cam.camera_pitch,
|
||||
|
@ -2746,17 +2911,18 @@ void Game::updatePlayerControl(const CameraOrientation &cam)
|
|||
client->setPlayerControl(control);
|
||||
LocalPlayer *player = client->getEnv().getLocalPlayer();
|
||||
player->keyPressed =
|
||||
( (u32)(input->isKeyDown(getKeySetting("keymap_forward")) & 0x1) << 0) |
|
||||
( (u32)(input->isKeyDown(getKeySetting("keymap_backward")) & 0x1) << 1) |
|
||||
( (u32)(input->isKeyDown(getKeySetting("keymap_left")) & 0x1) << 2) |
|
||||
( (u32)(input->isKeyDown(getKeySetting("keymap_right")) & 0x1) << 3) |
|
||||
( (u32)(input->isKeyDown(getKeySetting("keymap_jump")) & 0x1) << 4) |
|
||||
( (u32)(input->isKeyDown(getKeySetting("keymap_special1")) & 0x1) << 5) |
|
||||
( (u32)(input->isKeyDown(getKeySetting("keymap_sneak")) & 0x1) << 6) |
|
||||
( (u32)(input->getLeftState() & 0x1) << 7) |
|
||||
( (u32)(input->getRightState() & 0x1) << 8
|
||||
( (u32)(input->isKeyDown(keycache.key[KeyCache::KEYMAP_ID_FORWARD]) & 0x1) << 0) |
|
||||
( (u32)(input->isKeyDown(keycache.key[KeyCache::KEYMAP_ID_BACKWARD]) & 0x1) << 1) |
|
||||
( (u32)(input->isKeyDown(keycache.key[KeyCache::KEYMAP_ID_LEFT]) & 0x1) << 2) |
|
||||
( (u32)(input->isKeyDown(keycache.key[KeyCache::KEYMAP_ID_RIGHT]) & 0x1) << 3) |
|
||||
( (u32)(input->isKeyDown(keycache.key[KeyCache::KEYMAP_ID_JUMP]) & 0x1) << 4) |
|
||||
( (u32)(input->isKeyDown(keycache.key[KeyCache::KEYMAP_ID_SPECIAL1]) & 0x1) << 5) |
|
||||
( (u32)(input->isKeyDown(keycache.key[KeyCache::KEYMAP_ID_SNEAK]) & 0x1) << 6) |
|
||||
( (u32)(input->getLeftState() & 0x1) << 7) |
|
||||
( (u32)(input->getRightState() & 0x1) << 8
|
||||
);
|
||||
|
||||
//tt.stop();
|
||||
}
|
||||
|
||||
|
||||
|
@ -3042,7 +3208,7 @@ void Game::updateCamera(VolatileRunFlags *flags, u32 busy_time,
|
|||
|
||||
v3s16 old_camera_offset = camera->getOffset();
|
||||
|
||||
if (input->wasKeyDown(getKeySetting("keymap_camera_mode"))) {
|
||||
if (input->wasKeyDown(keycache.key[KeyCache::KEYMAP_ID_CAMERA_MODE])) {
|
||||
camera->toggleCameraMode();
|
||||
GenericCAO *playercao = player->getCAO();
|
||||
|
||||
|
@ -3273,7 +3439,7 @@ void Game::handlePointingAtNode(GameRunData *runData,
|
|||
if (meta) {
|
||||
infotext = narrow_to_wide(meta->getString("infotext"));
|
||||
} else {
|
||||
MapNode n = map.getNode(nodepos);
|
||||
MapNode n = map.getNodeNoEx(nodepos);
|
||||
|
||||
if (nodedef_manager->get(n).tiledef[0].name == "unknown_node.png") {
|
||||
infotext = L"Unknown node: ";
|
||||
|
@ -3331,7 +3497,7 @@ void Game::handlePointingAtNode(GameRunData *runData,
|
|||
}
|
||||
|
||||
if (playeritem_def.node_placement_prediction == "" ||
|
||||
nodedef_manager->get(map.getNode(nodepos)).rightclickable)
|
||||
nodedef_manager->get(map.getNodeNoEx(nodepos)).rightclickable)
|
||||
client->interact(3, pointed); // Report to server
|
||||
}
|
||||
}
|
||||
|
@ -3400,7 +3566,7 @@ void Game::handleDigging(GameRunData *runData,
|
|||
|
||||
LocalPlayer *player = client->getEnv().getLocalPlayer();
|
||||
ClientMap &map = client->getEnv().getClientMap();
|
||||
MapNode n = client->getEnv().getClientMap().getNode(nodepos);
|
||||
MapNode n = client->getEnv().getClientMap().getNodeNoEx(nodepos);
|
||||
|
||||
// NOTE: Similar piece of code exists on the server side for
|
||||
// cheat detection.
|
||||
|
@ -3465,8 +3631,10 @@ void Game::handleDigging(GameRunData *runData,
|
|||
infostream << "Digging completed" << std::endl;
|
||||
client->interact(2, pointed);
|
||||
client->setCrack(-1, v3s16(0, 0, 0));
|
||||
MapNode wasnode = map.getNode(nodepos);
|
||||
client->removeNode(nodepos);
|
||||
bool is_valid_position;
|
||||
MapNode wasnode = map.getNodeNoEx(nodepos, &is_valid_position);
|
||||
if (is_valid_position)
|
||||
client->removeNode(nodepos);
|
||||
|
||||
if (g_settings->getBool("enable_particles")) {
|
||||
const ContentFeatures &features =
|
||||
|
|
|
@ -32,8 +32,12 @@
|
|||
#include "settings.h"
|
||||
#include <algorithm>
|
||||
|
||||
#include "mainmenumanager.h" // for g_gamecallback
|
||||
|
||||
#define KMaxButtonPerColumns 12
|
||||
|
||||
extern MainGameCallback *g_gamecallback;
|
||||
|
||||
enum
|
||||
{
|
||||
GUI_ID_BACK_BUTTON = 101, GUI_ID_ABORT_BUTTON, GUI_ID_SCROLL_BAR,
|
||||
|
@ -234,7 +238,11 @@ bool GUIKeyChangeMenu::acceptInput()
|
|||
if(e != NULL && e->getType() == gui::EGUIET_CHECK_BOX)
|
||||
g_settings->setBool("doubletap_jump", ((gui::IGUICheckBox*)e)->isChecked());
|
||||
}
|
||||
|
||||
clearKeyCache();
|
||||
|
||||
g_gamecallback->signalKeyConfigChange();
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
|
|
|
@ -101,39 +101,48 @@ void LocalPlayer::move(f32 dtime, Environment *env, f32 pos_max_d,
|
|||
Collision detection
|
||||
*/
|
||||
|
||||
bool is_valid_position;
|
||||
MapNode node;
|
||||
v3s16 pp;
|
||||
|
||||
/*
|
||||
Check if player is in liquid (the oscillating value)
|
||||
*/
|
||||
try{
|
||||
// If in liquid, the threshold of coming out is at higher y
|
||||
if(in_liquid)
|
||||
{
|
||||
v3s16 pp = floatToInt(position + v3f(0,BS*0.1,0), BS);
|
||||
in_liquid = nodemgr->get(map->getNode(pp).getContent()).isLiquid();
|
||||
liquid_viscosity = nodemgr->get(map->getNode(pp).getContent()).liquid_viscosity;
|
||||
}
|
||||
// If not in liquid, the threshold of going in is at lower y
|
||||
else
|
||||
{
|
||||
v3s16 pp = floatToInt(position + v3f(0,BS*0.5,0), BS);
|
||||
in_liquid = nodemgr->get(map->getNode(pp).getContent()).isLiquid();
|
||||
liquid_viscosity = nodemgr->get(map->getNode(pp).getContent()).liquid_viscosity;
|
||||
}
|
||||
}
|
||||
catch(InvalidPositionException &e)
|
||||
|
||||
// If in liquid, the threshold of coming out is at higher y
|
||||
if (in_liquid)
|
||||
{
|
||||
in_liquid = false;
|
||||
pp = floatToInt(position + v3f(0,BS*0.1,0), BS);
|
||||
node = map->getNodeNoEx(pp, &is_valid_position);
|
||||
if (is_valid_position) {
|
||||
in_liquid = nodemgr->get(node.getContent()).isLiquid();
|
||||
liquid_viscosity = nodemgr->get(node.getContent()).liquid_viscosity;
|
||||
} else {
|
||||
in_liquid = false;
|
||||
}
|
||||
}
|
||||
// If not in liquid, the threshold of going in is at lower y
|
||||
else
|
||||
{
|
||||
pp = floatToInt(position + v3f(0,BS*0.5,0), BS);
|
||||
node = map->getNodeNoEx(pp, &is_valid_position);
|
||||
if (is_valid_position) {
|
||||
in_liquid = nodemgr->get(node.getContent()).isLiquid();
|
||||
liquid_viscosity = nodemgr->get(node.getContent()).liquid_viscosity;
|
||||
} else {
|
||||
in_liquid = false;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
Check if player is in liquid (the stable value)
|
||||
*/
|
||||
try{
|
||||
v3s16 pp = floatToInt(position + v3f(0,0,0), BS);
|
||||
in_liquid_stable = nodemgr->get(map->getNode(pp).getContent()).isLiquid();
|
||||
}
|
||||
catch(InvalidPositionException &e)
|
||||
{
|
||||
pp = floatToInt(position + v3f(0,0,0), BS);
|
||||
node = map->getNodeNoEx(pp, &is_valid_position);
|
||||
if (is_valid_position) {
|
||||
in_liquid_stable = nodemgr->get(node.getContent()).isLiquid();
|
||||
} else {
|
||||
in_liquid_stable = false;
|
||||
}
|
||||
|
||||
|
@ -141,17 +150,21 @@ void LocalPlayer::move(f32 dtime, Environment *env, f32 pos_max_d,
|
|||
Check if player is climbing
|
||||
*/
|
||||
|
||||
try {
|
||||
v3s16 pp = floatToInt(position + v3f(0,0.5*BS,0), BS);
|
||||
v3s16 pp2 = floatToInt(position + v3f(0,-0.2*BS,0), BS);
|
||||
is_climbing = ((nodemgr->get(map->getNode(pp).getContent()).climbable ||
|
||||
nodemgr->get(map->getNode(pp2).getContent()).climbable) && !free_move);
|
||||
}
|
||||
catch(InvalidPositionException &e)
|
||||
{
|
||||
|
||||
pp = floatToInt(position + v3f(0,0.5*BS,0), BS);
|
||||
v3s16 pp2 = floatToInt(position + v3f(0,-0.2*BS,0), BS);
|
||||
node = map->getNodeNoEx(pp, &is_valid_position);
|
||||
bool is_valid_position2;
|
||||
MapNode node2 = map->getNodeNoEx(pp2, &is_valid_position2);
|
||||
|
||||
if (!(is_valid_position && is_valid_position2)) {
|
||||
is_climbing = false;
|
||||
} else {
|
||||
is_climbing = (nodemgr->get(node.getContent()).climbable
|
||||
|| nodemgr->get(node2.getContent()).climbable) && !free_move;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
Collision uncertainty radius
|
||||
Make it a bit larger than the maximum distance of movement
|
||||
|
@ -264,22 +277,20 @@ void LocalPlayer::move(f32 dtime, Environment *env, f32 pos_max_d,
|
|||
max_axis_distance_f > 0.5*BS + sneak_max + 0.1*BS)
|
||||
continue;
|
||||
|
||||
try{
|
||||
// The node to be sneaked on has to be walkable
|
||||
if(nodemgr->get(map->getNode(p)).walkable == false)
|
||||
continue;
|
||||
// And the node above it has to be nonwalkable
|
||||
if(nodemgr->get(map->getNode(p+v3s16(0,1,0))).walkable == true) {
|
||||
continue;
|
||||
}
|
||||
if (!physics_override_sneak_glitch) {
|
||||
if (nodemgr->get(map->getNode(p+v3s16(0,2,0))).walkable)
|
||||
continue;
|
||||
}
|
||||
}
|
||||
catch(InvalidPositionException &e)
|
||||
{
|
||||
|
||||
// The node to be sneaked on has to be walkable
|
||||
node = map->getNodeNoEx(p, &is_valid_position);
|
||||
if (!is_valid_position || nodemgr->get(node).walkable == false)
|
||||
continue;
|
||||
// And the node above it has to be nonwalkable
|
||||
node = map->getNodeNoEx(p + v3s16(0,1,0), &is_valid_position);
|
||||
if (!is_valid_position || nodemgr->get(node).walkable) {
|
||||
continue;
|
||||
}
|
||||
if (!physics_override_sneak_glitch) {
|
||||
node =map->getNodeNoEx(p + v3s16(0,2,0), &is_valid_position);
|
||||
if (!is_valid_position || nodemgr->get(node).walkable)
|
||||
continue;
|
||||
}
|
||||
|
||||
min_distance_f = distance_f;
|
||||
|
|
|
@ -35,6 +35,8 @@ public:
|
|||
virtual void disconnect() = 0;
|
||||
virtual void changePassword() = 0;
|
||||
virtual void changeVolume() = 0;
|
||||
|
||||
virtual void signalKeyConfigChange() = 0;
|
||||
};
|
||||
|
||||
extern gui::IGUIEnvironment* guienv;
|
||||
|
@ -127,6 +129,7 @@ public:
|
|||
changevolume_requested(false),
|
||||
keyconfig_requested(false),
|
||||
shutdown_requested(false),
|
||||
keyconfig_changed(false),
|
||||
device(a_device)
|
||||
{
|
||||
}
|
||||
|
@ -159,12 +162,20 @@ public:
|
|||
keyconfig_requested = true;
|
||||
}
|
||||
|
||||
virtual void signalKeyConfigChange()
|
||||
{
|
||||
keyconfig_changed = true;
|
||||
}
|
||||
|
||||
|
||||
bool disconnect_requested;
|
||||
bool changepassword_requested;
|
||||
bool changevolume_requested;
|
||||
bool keyconfig_requested;
|
||||
bool shutdown_requested;
|
||||
|
||||
bool keyconfig_changed;
|
||||
|
||||
IrrlichtDevice *device;
|
||||
};
|
||||
|
||||
|
|
434
src/map.cpp
434
src/map.cpp
|
@ -186,26 +186,42 @@ bool Map::isValidPosition(v3s16 p)
|
|||
}
|
||||
|
||||
// Returns a CONTENT_IGNORE node if not found
|
||||
MapNode Map::getNodeNoEx(v3s16 p)
|
||||
MapNode Map::getNodeNoEx(v3s16 p, bool *is_valid_position)
|
||||
{
|
||||
v3s16 blockpos = getNodeBlockPos(p);
|
||||
MapBlock *block = getBlockNoCreateNoEx(blockpos);
|
||||
if(block == NULL)
|
||||
if (block == NULL) {
|
||||
if (is_valid_position != NULL)
|
||||
*is_valid_position = false;
|
||||
return MapNode(CONTENT_IGNORE);
|
||||
}
|
||||
|
||||
v3s16 relpos = p - blockpos*MAP_BLOCKSIZE;
|
||||
return block->getNodeNoCheck(relpos);
|
||||
bool is_valid_p;
|
||||
MapNode node = block->getNodeNoCheck(relpos, &is_valid_p);
|
||||
if (is_valid_position != NULL)
|
||||
*is_valid_position = is_valid_p;
|
||||
return node;
|
||||
}
|
||||
|
||||
#if 0
|
||||
// Deprecated
|
||||
// throws InvalidPositionException if not found
|
||||
// TODO: Now this is deprecated, getNodeNoEx should be renamed
|
||||
MapNode Map::getNode(v3s16 p)
|
||||
{
|
||||
v3s16 blockpos = getNodeBlockPos(p);
|
||||
MapBlock *block = getBlockNoCreateNoEx(blockpos);
|
||||
if(block == NULL)
|
||||
if (block == NULL)
|
||||
throw InvalidPositionException();
|
||||
v3s16 relpos = p - blockpos*MAP_BLOCKSIZE;
|
||||
return block->getNodeNoCheck(relpos);
|
||||
bool is_valid_position;
|
||||
MapNode node = block->getNodeNoCheck(relpos, &is_valid_position);
|
||||
if (!is_valid_position)
|
||||
throw InvalidPositionException();
|
||||
return node;
|
||||
}
|
||||
#endif
|
||||
|
||||
// throws InvalidPositionException if not found
|
||||
void Map::setNode(v3s16 p, MapNode & n)
|
||||
|
@ -215,9 +231,10 @@ void Map::setNode(v3s16 p, MapNode & n)
|
|||
v3s16 relpos = p - blockpos*MAP_BLOCKSIZE;
|
||||
// Never allow placing CONTENT_IGNORE, it fucks up stuff
|
||||
if(n.getContent() == CONTENT_IGNORE){
|
||||
bool temp_bool;
|
||||
errorstream<<"Map::setNode(): Not allowing to place CONTENT_IGNORE"
|
||||
<<" while trying to replace \""
|
||||
<<m_gamedef->ndef()->get(block->getNodeNoCheck(relpos)).name
|
||||
<<m_gamedef->ndef()->get(block->getNodeNoCheck(relpos, &temp_bool)).name
|
||||
<<"\" at "<<PP(p)<<" (block "<<PP(blockpos)<<")"<<std::endl;
|
||||
debug_stacks_print_to(infostream);
|
||||
return;
|
||||
|
@ -315,89 +332,84 @@ void Map::unspreadLight(enum LightBank bank,
|
|||
// Get the block where the node is located
|
||||
v3s16 blockpos = getNodeBlockPos(n2pos);
|
||||
|
||||
try
|
||||
{
|
||||
// Only fetch a new block if the block position has changed
|
||||
try{
|
||||
if(block == NULL || blockpos != blockpos_last){
|
||||
block = getBlockNoCreate(blockpos);
|
||||
blockpos_last = blockpos;
|
||||
// Only fetch a new block if the block position has changed
|
||||
try {
|
||||
if(block == NULL || blockpos != blockpos_last){
|
||||
block = getBlockNoCreate(blockpos);
|
||||
blockpos_last = blockpos;
|
||||
|
||||
block_checked_in_modified = false;
|
||||
blockchangecount++;
|
||||
}
|
||||
}
|
||||
catch(InvalidPositionException &e)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
// Calculate relative position in block
|
||||
v3s16 relpos = n2pos - blockpos * MAP_BLOCKSIZE;
|
||||
// Get node straight from the block
|
||||
MapNode n2 = block->getNode(relpos);
|
||||
|
||||
bool changed = false;
|
||||
|
||||
//TODO: Optimize output by optimizing light_sources?
|
||||
|
||||
/*
|
||||
If the neighbor is dimmer than what was specified
|
||||
as oldlight (the light of the previous node)
|
||||
*/
|
||||
if(n2.getLight(bank, nodemgr) < oldlight)
|
||||
{
|
||||
/*
|
||||
And the neighbor is transparent and it has some light
|
||||
*/
|
||||
if(nodemgr->get(n2).light_propagates
|
||||
&& n2.getLight(bank, nodemgr) != 0)
|
||||
{
|
||||
/*
|
||||
Set light to 0 and add to queue
|
||||
*/
|
||||
|
||||
u8 current_light = n2.getLight(bank, nodemgr);
|
||||
n2.setLight(bank, 0, nodemgr);
|
||||
block->setNode(relpos, n2);
|
||||
|
||||
unlighted_nodes[n2pos] = current_light;
|
||||
changed = true;
|
||||
|
||||
/*
|
||||
Remove from light_sources if it is there
|
||||
NOTE: This doesn't happen nearly at all
|
||||
*/
|
||||
/*if(light_sources.find(n2pos))
|
||||
{
|
||||
infostream<<"Removed from light_sources"<<std::endl;
|
||||
light_sources.remove(n2pos);
|
||||
}*/
|
||||
}
|
||||
|
||||
/*// DEBUG
|
||||
if(light_sources.find(n2pos) != NULL)
|
||||
light_sources.remove(n2pos);*/
|
||||
}
|
||||
else{
|
||||
light_sources.insert(n2pos);
|
||||
}
|
||||
|
||||
// Add to modified_blocks
|
||||
if(changed == true && block_checked_in_modified == false)
|
||||
{
|
||||
// If the block is not found in modified_blocks, add.
|
||||
if(modified_blocks.find(blockpos) == modified_blocks.end())
|
||||
{
|
||||
modified_blocks[blockpos] = block;
|
||||
}
|
||||
block_checked_in_modified = true;
|
||||
block_checked_in_modified = false;
|
||||
blockchangecount++;
|
||||
}
|
||||
}
|
||||
catch(InvalidPositionException &e)
|
||||
{
|
||||
catch(InvalidPositionException &e) {
|
||||
continue;
|
||||
}
|
||||
|
||||
// Calculate relative position in block
|
||||
v3s16 relpos = n2pos - blockpos * MAP_BLOCKSIZE;
|
||||
// Get node straight from the block
|
||||
bool is_valid_position;
|
||||
MapNode n2 = block->getNode(relpos, &is_valid_position);
|
||||
if (!is_valid_position)
|
||||
continue;
|
||||
|
||||
bool changed = false;
|
||||
|
||||
//TODO: Optimize output by optimizing light_sources?
|
||||
|
||||
/*
|
||||
If the neighbor is dimmer than what was specified
|
||||
as oldlight (the light of the previous node)
|
||||
*/
|
||||
if(n2.getLight(bank, nodemgr) < oldlight)
|
||||
{
|
||||
/*
|
||||
And the neighbor is transparent and it has some light
|
||||
*/
|
||||
if(nodemgr->get(n2).light_propagates
|
||||
&& n2.getLight(bank, nodemgr) != 0)
|
||||
{
|
||||
/*
|
||||
Set light to 0 and add to queue
|
||||
*/
|
||||
|
||||
u8 current_light = n2.getLight(bank, nodemgr);
|
||||
n2.setLight(bank, 0, nodemgr);
|
||||
block->setNode(relpos, n2);
|
||||
|
||||
unlighted_nodes[n2pos] = current_light;
|
||||
changed = true;
|
||||
|
||||
/*
|
||||
Remove from light_sources if it is there
|
||||
NOTE: This doesn't happen nearly at all
|
||||
*/
|
||||
/*if(light_sources.find(n2pos))
|
||||
{
|
||||
infostream<<"Removed from light_sources"<<std::endl;
|
||||
light_sources.remove(n2pos);
|
||||
}*/
|
||||
}
|
||||
|
||||
/*// DEBUG
|
||||
if(light_sources.find(n2pos) != NULL)
|
||||
light_sources.remove(n2pos);*/
|
||||
}
|
||||
else{
|
||||
light_sources.insert(n2pos);
|
||||
}
|
||||
|
||||
// Add to modified_blocks
|
||||
if(changed == true && block_checked_in_modified == false)
|
||||
{
|
||||
// If the block is not found in modified_blocks, add.
|
||||
if(modified_blocks.find(blockpos) == modified_blocks.end())
|
||||
{
|
||||
modified_blocks[blockpos] = block;
|
||||
}
|
||||
block_checked_in_modified = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -465,7 +477,7 @@ void Map::spreadLight(enum LightBank bank,
|
|||
v3s16 blockpos = getNodeBlockPos(pos);
|
||||
|
||||
// Only fetch a new block if the block position has changed
|
||||
try{
|
||||
try {
|
||||
if(block == NULL || blockpos != blockpos_last){
|
||||
block = getBlockNoCreate(blockpos);
|
||||
blockpos_last = blockpos;
|
||||
|
@ -474,8 +486,7 @@ void Map::spreadLight(enum LightBank bank,
|
|||
blockchangecount++;
|
||||
}
|
||||
}
|
||||
catch(InvalidPositionException &e)
|
||||
{
|
||||
catch(InvalidPositionException &e) {
|
||||
continue;
|
||||
}
|
||||
|
||||
|
@ -486,9 +497,10 @@ void Map::spreadLight(enum LightBank bank,
|
|||
v3s16 relpos = pos - blockpos_last * MAP_BLOCKSIZE;
|
||||
|
||||
// Get node straight from the block
|
||||
MapNode n = block->getNode(relpos);
|
||||
bool is_valid_position;
|
||||
MapNode n = block->getNode(relpos, &is_valid_position);
|
||||
|
||||
u8 oldlight = n.getLight(bank, nodemgr);
|
||||
u8 oldlight = is_valid_position ? n.getLight(bank, nodemgr) : 0;
|
||||
u8 newlight = diminish_light(oldlight);
|
||||
|
||||
// Loop through 6 neighbors
|
||||
|
@ -499,67 +511,61 @@ void Map::spreadLight(enum LightBank bank,
|
|||
// Get the block where the node is located
|
||||
v3s16 blockpos = getNodeBlockPos(n2pos);
|
||||
|
||||
try
|
||||
// Only fetch a new block if the block position has changed
|
||||
try {
|
||||
if(block == NULL || blockpos != blockpos_last){
|
||||
block = getBlockNoCreate(blockpos);
|
||||
blockpos_last = blockpos;
|
||||
|
||||
block_checked_in_modified = false;
|
||||
blockchangecount++;
|
||||
}
|
||||
}
|
||||
catch(InvalidPositionException &e) {
|
||||
continue;
|
||||
}
|
||||
|
||||
// Calculate relative position in block
|
||||
v3s16 relpos = n2pos - blockpos * MAP_BLOCKSIZE;
|
||||
// Get node straight from the block
|
||||
MapNode n2 = block->getNode(relpos, &is_valid_position);
|
||||
if (!is_valid_position)
|
||||
continue;
|
||||
|
||||
bool changed = false;
|
||||
/*
|
||||
If the neighbor is brighter than the current node,
|
||||
add to list (it will light up this node on its turn)
|
||||
*/
|
||||
if(n2.getLight(bank, nodemgr) > undiminish_light(oldlight))
|
||||
{
|
||||
// Only fetch a new block if the block position has changed
|
||||
try{
|
||||
if(block == NULL || blockpos != blockpos_last){
|
||||
block = getBlockNoCreate(blockpos);
|
||||
blockpos_last = blockpos;
|
||||
|
||||
block_checked_in_modified = false;
|
||||
blockchangecount++;
|
||||
}
|
||||
}
|
||||
catch(InvalidPositionException &e)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
// Calculate relative position in block
|
||||
v3s16 relpos = n2pos - blockpos * MAP_BLOCKSIZE;
|
||||
// Get node straight from the block
|
||||
MapNode n2 = block->getNode(relpos);
|
||||
|
||||
bool changed = false;
|
||||
/*
|
||||
If the neighbor is brighter than the current node,
|
||||
add to list (it will light up this node on its turn)
|
||||
*/
|
||||
if(n2.getLight(bank, nodemgr) > undiminish_light(oldlight))
|
||||
lighted_nodes.insert(n2pos);
|
||||
changed = true;
|
||||
}
|
||||
/*
|
||||
If the neighbor is dimmer than how much light this node
|
||||
would spread on it, add to list
|
||||
*/
|
||||
if(n2.getLight(bank, nodemgr) < newlight)
|
||||
{
|
||||
if(nodemgr->get(n2).light_propagates)
|
||||
{
|
||||
n2.setLight(bank, newlight, nodemgr);
|
||||
block->setNode(relpos, n2);
|
||||
lighted_nodes.insert(n2pos);
|
||||
changed = true;
|
||||
}
|
||||
/*
|
||||
If the neighbor is dimmer than how much light this node
|
||||
would spread on it, add to list
|
||||
*/
|
||||
if(n2.getLight(bank, nodemgr) < newlight)
|
||||
{
|
||||
if(nodemgr->get(n2).light_propagates)
|
||||
{
|
||||
n2.setLight(bank, newlight, nodemgr);
|
||||
block->setNode(relpos, n2);
|
||||
lighted_nodes.insert(n2pos);
|
||||
changed = true;
|
||||
}
|
||||
}
|
||||
|
||||
// Add to modified_blocks
|
||||
if(changed == true && block_checked_in_modified == false)
|
||||
{
|
||||
// If the block is not found in modified_blocks, add.
|
||||
if(modified_blocks.find(blockpos) == modified_blocks.end())
|
||||
{
|
||||
modified_blocks[blockpos] = block;
|
||||
}
|
||||
block_checked_in_modified = true;
|
||||
}
|
||||
}
|
||||
catch(InvalidPositionException &e)
|
||||
|
||||
// Add to modified_blocks
|
||||
if(changed == true && block_checked_in_modified == false)
|
||||
{
|
||||
continue;
|
||||
// If the block is not found in modified_blocks, add.
|
||||
if(modified_blocks.find(blockpos) == modified_blocks.end())
|
||||
{
|
||||
modified_blocks[blockpos] = block;
|
||||
}
|
||||
block_checked_in_modified = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -607,13 +613,11 @@ v3s16 Map::getBrightestNeighbour(enum LightBank bank, v3s16 p)
|
|||
// Get the position of the neighbor node
|
||||
v3s16 n2pos = p + dirs[i];
|
||||
MapNode n2;
|
||||
try{
|
||||
n2 = getNode(n2pos);
|
||||
}
|
||||
catch(InvalidPositionException &e)
|
||||
{
|
||||
bool is_valid_position;
|
||||
n2 = getNodeNoEx(n2pos, &is_valid_position);
|
||||
if (!is_valid_position)
|
||||
continue;
|
||||
}
|
||||
|
||||
if(n2.getLight(bank, nodemgr) > brightest_light || found_something == false){
|
||||
brightest_light = n2.getLight(bank, nodemgr);
|
||||
brightest_pos = n2pos;
|
||||
|
@ -656,7 +660,10 @@ s16 Map::propagateSunlight(v3s16 start,
|
|||
}
|
||||
|
||||
v3s16 relpos = pos - blockpos*MAP_BLOCKSIZE;
|
||||
MapNode n = block->getNode(relpos);
|
||||
bool is_valid_position;
|
||||
MapNode n = block->getNode(relpos, &is_valid_position);
|
||||
if (!is_valid_position)
|
||||
break;
|
||||
|
||||
if(nodemgr->get(n).sunlight_propagates)
|
||||
{
|
||||
|
@ -723,39 +730,37 @@ void Map::updateLighting(enum LightBank bank,
|
|||
for(s16 x=0; x<MAP_BLOCKSIZE; x++)
|
||||
for(s16 y=0; y<MAP_BLOCKSIZE; y++)
|
||||
{
|
||||
|
||||
try{
|
||||
v3s16 p(x,y,z);
|
||||
MapNode n = block->getNode(p);
|
||||
u8 oldlight = n.getLight(bank, nodemgr);
|
||||
n.setLight(bank, 0, nodemgr);
|
||||
block->setNode(p, n);
|
||||
|
||||
// If node sources light, add to list
|
||||
u8 source = nodemgr->get(n).light_source;
|
||||
if(source != 0)
|
||||
light_sources.insert(p + posnodes);
|
||||
|
||||
// Collect borders for unlighting
|
||||
if((x==0 || x == MAP_BLOCKSIZE-1
|
||||
|| y==0 || y == MAP_BLOCKSIZE-1
|
||||
|| z==0 || z == MAP_BLOCKSIZE-1)
|
||||
&& oldlight != 0)
|
||||
{
|
||||
v3s16 p_map = p + posnodes;
|
||||
unlight_from[p_map] = oldlight;
|
||||
}
|
||||
}
|
||||
catch(InvalidPositionException &e)
|
||||
{
|
||||
/*
|
||||
This would happen when dealing with a
|
||||
dummy block.
|
||||
v3s16 p(x,y,z);
|
||||
bool is_valid_position;
|
||||
MapNode n = block->getNode(p, &is_valid_position);
|
||||
if (!is_valid_position) {
|
||||
/* This would happen when dealing with a
|
||||
dummy block.
|
||||
*/
|
||||
//assert(0);
|
||||
infostream<<"updateLighting(): InvalidPositionException"
|
||||
<<std::endl;
|
||||
continue;
|
||||
}
|
||||
u8 oldlight = n.getLight(bank, nodemgr);
|
||||
n.setLight(bank, 0, nodemgr);
|
||||
block->setNode(p, n);
|
||||
|
||||
// If node sources light, add to list
|
||||
u8 source = nodemgr->get(n).light_source;
|
||||
if(source != 0)
|
||||
light_sources.insert(p + posnodes);
|
||||
|
||||
// Collect borders for unlighting
|
||||
if((x==0 || x == MAP_BLOCKSIZE-1
|
||||
|| y==0 || y == MAP_BLOCKSIZE-1
|
||||
|| z==0 || z == MAP_BLOCKSIZE-1)
|
||||
&& oldlight != 0)
|
||||
{
|
||||
v3s16 p_map = p + posnodes;
|
||||
unlight_from[p_map] = oldlight;
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
if(bank == LIGHTBANK_DAY)
|
||||
|
@ -965,15 +970,12 @@ void Map::addNodeAndUpdate(v3s16 p, MapNode n,
|
|||
|
||||
Otherwise there probably is.
|
||||
*/
|
||||
try{
|
||||
MapNode topnode = getNode(toppos);
|
||||
|
||||
if(topnode.getLight(LIGHTBANK_DAY, ndef) != LIGHT_SUN)
|
||||
node_under_sunlight = false;
|
||||
}
|
||||
catch(InvalidPositionException &e)
|
||||
{
|
||||
}
|
||||
bool is_valid_position;
|
||||
MapNode topnode = getNodeNoEx(toppos, &is_valid_position);
|
||||
|
||||
if(is_valid_position && topnode.getLight(LIGHTBANK_DAY, ndef) != LIGHT_SUN)
|
||||
node_under_sunlight = false;
|
||||
|
||||
/*
|
||||
Remove all light that has come out of this node
|
||||
|
@ -988,7 +990,7 @@ void Map::addNodeAndUpdate(v3s16 p, MapNode n,
|
|||
{
|
||||
enum LightBank bank = banks[i];
|
||||
|
||||
u8 lightwas = getNode(p).getLight(bank, ndef);
|
||||
u8 lightwas = getNodeNoEx(p).getLight(bank, ndef);
|
||||
|
||||
// Add the block of the added node to modified_blocks
|
||||
v3s16 blockpos = getNodeBlockPos(p);
|
||||
|
@ -1045,13 +1047,10 @@ void Map::addNodeAndUpdate(v3s16 p, MapNode n,
|
|||
v3s16 n2pos(p.X, y, p.Z);
|
||||
|
||||
MapNode n2;
|
||||
try{
|
||||
n2 = getNode(n2pos);
|
||||
}
|
||||
catch(InvalidPositionException &e)
|
||||
{
|
||||
|
||||
n2 = getNodeNoEx(n2pos, &is_valid_position);
|
||||
if (!is_valid_position)
|
||||
break;
|
||||
}
|
||||
|
||||
if(n2.getLight(LIGHTBANK_DAY, ndef) == LIGHT_SUN)
|
||||
{
|
||||
|
@ -1112,20 +1111,14 @@ void Map::addNodeAndUpdate(v3s16 p, MapNode n,
|
|||
};
|
||||
for(u16 i=0; i<7; i++)
|
||||
{
|
||||
try
|
||||
{
|
||||
|
||||
v3s16 p2 = p + dirs[i];
|
||||
|
||||
MapNode n2 = getNode(p2);
|
||||
if(ndef->get(n2).isLiquid() || n2.getContent() == CONTENT_AIR)
|
||||
MapNode n2 = getNodeNoEx(p2, &is_valid_position);
|
||||
if(is_valid_position
|
||||
&& (ndef->get(n2).isLiquid() || n2.getContent() == CONTENT_AIR))
|
||||
{
|
||||
m_transforming_liquid.push_back(p2);
|
||||
}
|
||||
|
||||
}catch(InvalidPositionException &e)
|
||||
{
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -1156,15 +1149,11 @@ void Map::removeNodeAndUpdate(v3s16 p,
|
|||
If there is a node at top and it doesn't have sunlight,
|
||||
there will be no sunlight going down.
|
||||
*/
|
||||
try{
|
||||
MapNode topnode = getNode(toppos);
|
||||
bool is_valid_position;
|
||||
MapNode topnode = getNodeNoEx(toppos, &is_valid_position);
|
||||
|
||||
if(topnode.getLight(LIGHTBANK_DAY, ndef) != LIGHT_SUN)
|
||||
node_under_sunlight = false;
|
||||
}
|
||||
catch(InvalidPositionException &e)
|
||||
{
|
||||
}
|
||||
if(is_valid_position && topnode.getLight(LIGHTBANK_DAY, ndef) != LIGHT_SUN)
|
||||
node_under_sunlight = false;
|
||||
|
||||
std::set<v3s16> light_sources;
|
||||
|
||||
|
@ -1181,7 +1170,7 @@ void Map::removeNodeAndUpdate(v3s16 p,
|
|||
Unlight neighbors (in case the node is a light source)
|
||||
*/
|
||||
unLightNeighbors(bank, p,
|
||||
getNode(p).getLight(bank, ndef),
|
||||
getNodeNoEx(p).getLight(bank, ndef),
|
||||
light_sources, modified_blocks);
|
||||
}
|
||||
|
||||
|
@ -1241,13 +1230,11 @@ void Map::removeNodeAndUpdate(v3s16 p,
|
|||
{
|
||||
// Set the lighting of this node to 0
|
||||
// TODO: Is this needed? Lighting is cleared up there already.
|
||||
try{
|
||||
MapNode n = getNode(p);
|
||||
MapNode n = getNodeNoEx(p, &is_valid_position);
|
||||
if (is_valid_position) {
|
||||
n.setLight(LIGHTBANK_DAY, 0, ndef);
|
||||
setNode(p, n);
|
||||
}
|
||||
catch(InvalidPositionException &e)
|
||||
{
|
||||
} else {
|
||||
assert(0);
|
||||
}
|
||||
}
|
||||
|
@ -1303,20 +1290,15 @@ void Map::removeNodeAndUpdate(v3s16 p,
|
|||
};
|
||||
for(u16 i=0; i<7; i++)
|
||||
{
|
||||
try
|
||||
{
|
||||
|
||||
v3s16 p2 = p + dirs[i];
|
||||
|
||||
MapNode n2 = getNode(p2);
|
||||
if(ndef->get(n2).isLiquid() || n2.getContent() == CONTENT_AIR)
|
||||
bool is_position_valid;
|
||||
MapNode n2 = getNodeNoEx(p2, &is_position_valid);
|
||||
if (is_position_valid
|
||||
&& (ndef->get(n2).isLiquid() || n2.getContent() == CONTENT_AIR))
|
||||
{
|
||||
m_transforming_liquid.push_back(p2);
|
||||
}
|
||||
|
||||
}catch(InvalidPositionException &e)
|
||||
{
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -197,14 +197,13 @@ public:
|
|||
|
||||
bool isValidPosition(v3s16 p);
|
||||
|
||||
// throws InvalidPositionException if not found
|
||||
MapNode getNode(v3s16 p);
|
||||
|
||||
// throws InvalidPositionException if not found
|
||||
void setNode(v3s16 p, MapNode & n);
|
||||
|
||||
// Returns a CONTENT_IGNORE node if not found
|
||||
MapNode getNodeNoEx(v3s16 p);
|
||||
// If is_valid_position is not NULL then this will be set to true if the
|
||||
// position is valid, otherwise false
|
||||
MapNode getNodeNoEx(v3s16 p, bool *is_valid_position = NULL);
|
||||
|
||||
void unspreadLight(enum LightBank bank,
|
||||
std::map<v3s16, u8> & from_nodes,
|
||||
|
|
106
src/mapblock.cpp
106
src/mapblock.cpp
|
@ -97,54 +97,19 @@ bool MapBlock::isValidPositionParent(v3s16 p)
|
|||
}
|
||||
}
|
||||
|
||||
MapNode MapBlock::getNodeParent(v3s16 p)
|
||||
MapNode MapBlock::getNodeParent(v3s16 p, bool *is_valid_position)
|
||||
{
|
||||
if(isValidPosition(p) == false)
|
||||
{
|
||||
return m_parent->getNode(getPosRelative() + p);
|
||||
}
|
||||
else
|
||||
{
|
||||
if(data == NULL)
|
||||
throw InvalidPositionException();
|
||||
return data[p.Z*MAP_BLOCKSIZE*MAP_BLOCKSIZE + p.Y*MAP_BLOCKSIZE + p.X];
|
||||
}
|
||||
}
|
||||
if (isValidPosition(p) == false)
|
||||
return m_parent->getNodeNoEx(getPosRelative() + p, is_valid_position);
|
||||
|
||||
void MapBlock::setNodeParent(v3s16 p, MapNode & n)
|
||||
{
|
||||
if(isValidPosition(p) == false)
|
||||
{
|
||||
m_parent->setNode(getPosRelative() + p, n);
|
||||
}
|
||||
else
|
||||
{
|
||||
if(data == NULL)
|
||||
throw InvalidPositionException();
|
||||
data[p.Z*MAP_BLOCKSIZE*MAP_BLOCKSIZE + p.Y*MAP_BLOCKSIZE + p.X] = n;
|
||||
}
|
||||
}
|
||||
|
||||
MapNode MapBlock::getNodeParentNoEx(v3s16 p)
|
||||
{
|
||||
if(isValidPosition(p) == false)
|
||||
{
|
||||
try{
|
||||
return m_parent->getNode(getPosRelative() + p);
|
||||
}
|
||||
catch(InvalidPositionException &e)
|
||||
{
|
||||
return MapNode(CONTENT_IGNORE);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
if(data == NULL)
|
||||
{
|
||||
return MapNode(CONTENT_IGNORE);
|
||||
}
|
||||
return data[p.Z*MAP_BLOCKSIZE*MAP_BLOCKSIZE + p.Y*MAP_BLOCKSIZE + p.X];
|
||||
if (data == NULL) {
|
||||
if (is_valid_position)
|
||||
*is_valid_position = false;
|
||||
return MapNode(CONTENT_IGNORE);
|
||||
}
|
||||
if (is_valid_position)
|
||||
*is_valid_position = true;
|
||||
return data[p.Z*MAP_BLOCKSIZE*MAP_BLOCKSIZE + p.Y*MAP_BLOCKSIZE + p.X];
|
||||
}
|
||||
|
||||
/*
|
||||
|
@ -183,9 +148,14 @@ bool MapBlock::propagateSunlight(std::set<v3s16> & light_sources,
|
|||
#if 1
|
||||
bool no_sunlight = false;
|
||||
bool no_top_block = false;
|
||||
|
||||
// Check if node above block has sunlight
|
||||
try{
|
||||
MapNode n = getNodeParent(v3s16(x, MAP_BLOCKSIZE, z));
|
||||
|
||||
bool is_valid_position;
|
||||
MapNode n = getNodeParent(v3s16(x, MAP_BLOCKSIZE, z),
|
||||
&is_valid_position);
|
||||
if (is_valid_position)
|
||||
{
|
||||
if(n.getContent() == CONTENT_IGNORE)
|
||||
{
|
||||
// Trust heuristics
|
||||
|
@ -196,7 +166,7 @@ bool MapBlock::propagateSunlight(std::set<v3s16> & light_sources,
|
|||
no_sunlight = true;
|
||||
}
|
||||
}
|
||||
catch(InvalidPositionException &e)
|
||||
else
|
||||
{
|
||||
no_top_block = true;
|
||||
|
||||
|
@ -208,7 +178,7 @@ bool MapBlock::propagateSunlight(std::set<v3s16> & light_sources,
|
|||
}
|
||||
else
|
||||
{
|
||||
MapNode n = getNode(v3s16(x, MAP_BLOCKSIZE-1, z));
|
||||
MapNode n = getNodeNoEx(v3s16(x, MAP_BLOCKSIZE-1, z));
|
||||
if(m_gamedef->ndef()->get(n).sunlight_propagates == false)
|
||||
{
|
||||
no_sunlight = true;
|
||||
|
@ -308,27 +278,27 @@ bool MapBlock::propagateSunlight(std::set<v3s16> & light_sources,
|
|||
|
||||
Ignore non-transparent nodes as they always have no light
|
||||
*/
|
||||
try
|
||||
{
|
||||
|
||||
if(block_below_is_valid)
|
||||
{
|
||||
MapNode n = getNodeParent(v3s16(x, -1, z));
|
||||
if(nodemgr->get(n).light_propagates)
|
||||
{
|
||||
if(n.getLight(LIGHTBANK_DAY, nodemgr) == LIGHT_SUN
|
||||
&& sunlight_should_go_down == false)
|
||||
block_below_is_valid = false;
|
||||
else if(n.getLight(LIGHTBANK_DAY, nodemgr) != LIGHT_SUN
|
||||
&& sunlight_should_go_down == true)
|
||||
block_below_is_valid = false;
|
||||
MapNode n = getNodeParent(v3s16(x, -1, z), &is_valid_position);
|
||||
if (is_valid_position) {
|
||||
if(nodemgr->get(n).light_propagates)
|
||||
{
|
||||
if(n.getLight(LIGHTBANK_DAY, nodemgr) == LIGHT_SUN
|
||||
&& sunlight_should_go_down == false)
|
||||
block_below_is_valid = false;
|
||||
else if(n.getLight(LIGHTBANK_DAY, nodemgr) != LIGHT_SUN
|
||||
&& sunlight_should_go_down == true)
|
||||
block_below_is_valid = false;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
/*std::cout<<"InvalidBlockException for bottom block node"
|
||||
<<std::endl;*/
|
||||
// Just no block below, no need to panic.
|
||||
}
|
||||
}//if
|
||||
}//try
|
||||
catch(InvalidPositionException &e)
|
||||
{
|
||||
/*std::cout<<"InvalidBlockException for bottom block node"
|
||||
<<std::endl;*/
|
||||
// Just no block below, no need to panic.
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -1070,7 +1040,7 @@ std::string analyze_block(MapBlock *block)
|
|||
for(s16 x0=0; x0<MAP_BLOCKSIZE; x0++)
|
||||
{
|
||||
v3s16 p(x0,y0,z0);
|
||||
MapNode n = block->getNode(p);
|
||||
MapNode n = block->getNodeNoEx(p);
|
||||
content_t c = n.getContent();
|
||||
if(c == CONTENT_IGNORE)
|
||||
some_ignore = true;
|
||||
|
|
|
@ -251,37 +251,39 @@ public:
|
|||
Regular MapNode get-setters
|
||||
*/
|
||||
|
||||
bool isValidPosition(v3s16 p)
|
||||
bool isValidPosition(s16 x, s16 y, s16 z)
|
||||
{
|
||||
if(data == NULL)
|
||||
return false;
|
||||
return (p.X >= 0 && p.X < MAP_BLOCKSIZE
|
||||
&& p.Y >= 0 && p.Y < MAP_BLOCKSIZE
|
||||
&& p.Z >= 0 && p.Z < MAP_BLOCKSIZE);
|
||||
return data != NULL
|
||||
&& x >= 0 && x < MAP_BLOCKSIZE
|
||||
&& y >= 0 && y < MAP_BLOCKSIZE
|
||||
&& z >= 0 && z < MAP_BLOCKSIZE;
|
||||
}
|
||||
|
||||
MapNode getNode(s16 x, s16 y, s16 z)
|
||||
bool isValidPosition(v3s16 p)
|
||||
{
|
||||
if(data == NULL)
|
||||
throw InvalidPositionException();
|
||||
if(x < 0 || x >= MAP_BLOCKSIZE) throw InvalidPositionException();
|
||||
if(y < 0 || y >= MAP_BLOCKSIZE) throw InvalidPositionException();
|
||||
if(z < 0 || z >= MAP_BLOCKSIZE) throw InvalidPositionException();
|
||||
return isValidPosition(p.X, p.Y, p.Z);
|
||||
}
|
||||
|
||||
MapNode getNode(s16 x, s16 y, s16 z, bool *valid_position)
|
||||
{
|
||||
*valid_position = isValidPosition(x, y, z);
|
||||
|
||||
if (!*valid_position)
|
||||
return MapNode(CONTENT_IGNORE);
|
||||
|
||||
return data[z*MAP_BLOCKSIZE*MAP_BLOCKSIZE + y*MAP_BLOCKSIZE + x];
|
||||
}
|
||||
|
||||
MapNode getNode(v3s16 p)
|
||||
MapNode getNode(v3s16 p, bool *valid_position)
|
||||
{
|
||||
return getNode(p.X, p.Y, p.Z);
|
||||
return getNode(p.X, p.Y, p.Z, valid_position);
|
||||
}
|
||||
|
||||
MapNode getNodeNoEx(v3s16 p)
|
||||
{
|
||||
try{
|
||||
return getNode(p.X, p.Y, p.Z);
|
||||
}catch(InvalidPositionException &e){
|
||||
return MapNode(CONTENT_IGNORE);
|
||||
}
|
||||
bool is_valid;
|
||||
MapNode node = getNode(p.X, p.Y, p.Z, &is_valid);
|
||||
return is_valid ? node : MapNode(CONTENT_IGNORE);
|
||||
}
|
||||
|
||||
void setNode(s16 x, s16 y, s16 z, MapNode & n)
|
||||
|
@ -304,16 +306,18 @@ public:
|
|||
Non-checking variants of the above
|
||||
*/
|
||||
|
||||
MapNode getNodeNoCheck(s16 x, s16 y, s16 z)
|
||||
MapNode getNodeNoCheck(s16 x, s16 y, s16 z, bool *valid_position)
|
||||
{
|
||||
if(data == NULL)
|
||||
throw InvalidPositionException();
|
||||
*valid_position = data != NULL;
|
||||
if(!valid_position)
|
||||
return MapNode(CONTENT_IGNORE);
|
||||
|
||||
return data[z*MAP_BLOCKSIZE*MAP_BLOCKSIZE + y*MAP_BLOCKSIZE + x];
|
||||
}
|
||||
|
||||
MapNode getNodeNoCheck(v3s16 p)
|
||||
MapNode getNodeNoCheck(v3s16 p, bool *valid_position)
|
||||
{
|
||||
return getNodeNoCheck(p.X, p.Y, p.Z);
|
||||
return getNodeNoCheck(p.X, p.Y, p.Z, valid_position);
|
||||
}
|
||||
|
||||
void setNodeNoCheck(s16 x, s16 y, s16 z, MapNode & n)
|
||||
|
@ -334,9 +338,8 @@ public:
|
|||
is not valid on this MapBlock.
|
||||
*/
|
||||
bool isValidPositionParent(v3s16 p);
|
||||
MapNode getNodeParent(v3s16 p);
|
||||
MapNode getNodeParent(v3s16 p, bool *is_valid_position = NULL);
|
||||
void setNodeParent(v3s16 p, MapNode & n);
|
||||
MapNode getNodeParentNoEx(v3s16 p);
|
||||
|
||||
void drawbox(s16 x0, s16 y0, s16 z0, s16 w, s16 h, s16 d, MapNode node)
|
||||
{
|
||||
|
|
|
@ -37,6 +37,7 @@ with this program; if not, write to the Free Software Foundation, Inc.,
|
|||
#include "filesys.h"
|
||||
#include "log.h"
|
||||
|
||||
const char *GenElementManager::ELEMENT_TITLE = "element";
|
||||
|
||||
FlagDesc flagdesc_mapgen[] = {
|
||||
{"trees", MG_TREES},
|
||||
|
@ -57,16 +58,10 @@ FlagDesc flagdesc_gennotify[] = {
|
|||
{NULL, 0}
|
||||
};
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
|
||||
|
||||
Mapgen::Mapgen() {
|
||||
seed = 0;
|
||||
water_level = 0;
|
||||
|
@ -283,10 +278,85 @@ void Mapgen::calcLightingOld(v3s16 nmin, v3s16 nmax) {
|
|||
std::map<v3s16, u8> unlight_from;
|
||||
|
||||
voxalgo::clearLightAndCollectSources(*vm, a, bank, ndef,
|
||||
light_sources, unlight_from);
|
||||
light_sources, unlight_from);
|
||||
voxalgo::propagateSunlight(*vm, a, sunlight, light_sources, ndef);
|
||||
|
||||
vm->unspreadLight(bank, unlight_from, light_sources, ndef);
|
||||
vm->spreadLight(bank, light_sources, ndef);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
|
||||
GenElementManager::~GenElementManager()
|
||||
{
|
||||
for (size_t i = 0; i != m_elements.size(); i++)
|
||||
delete m_elements[i];
|
||||
}
|
||||
|
||||
|
||||
u32 GenElementManager::add(GenElement *elem)
|
||||
{
|
||||
size_t nelem = m_elements.size();
|
||||
|
||||
for (size_t i = 0; i != nelem; i++) {
|
||||
if (m_elements[i] == NULL) {
|
||||
elem->id = i;
|
||||
m_elements[i] = elem;
|
||||
return i;
|
||||
}
|
||||
}
|
||||
|
||||
if (nelem >= this->ELEMENT_LIMIT)
|
||||
return -1;
|
||||
|
||||
elem->id = nelem;
|
||||
m_elements.push_back(elem);
|
||||
|
||||
verbosestream << "GenElementManager: added " << this->ELEMENT_TITLE
|
||||
<< " element '" << elem->name << "'" << std::endl;
|
||||
|
||||
return nelem;
|
||||
}
|
||||
|
||||
|
||||
GenElement *GenElementManager::get(u32 id)
|
||||
{
|
||||
return (id < m_elements.size()) ? m_elements[id] : NULL;
|
||||
}
|
||||
|
||||
|
||||
GenElement *GenElementManager::getByName(const char *name)
|
||||
{
|
||||
for (size_t i = 0; i != m_elements.size(); i++) {
|
||||
GenElement *elem = m_elements[i];
|
||||
if (elem && !strcmp(elem->name.c_str(), name))
|
||||
return elem;
|
||||
}
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
GenElement *GenElementManager::getByName(std::string &name)
|
||||
{
|
||||
return getByName(name.c_str());
|
||||
}
|
||||
|
||||
|
||||
GenElement *GenElementManager::update(u32 id, GenElement *elem)
|
||||
{
|
||||
if (id >= m_elements.size())
|
||||
return NULL;
|
||||
|
||||
GenElement *old_elem = m_elements[id];
|
||||
m_elements[id] = elem;
|
||||
return old_elem;
|
||||
}
|
||||
|
||||
|
||||
GenElement *GenElementManager::remove(u32 id)
|
||||
{
|
||||
return update(id, NULL);
|
||||
}
|
||||
|
|
44
src/mapgen.h
44
src/mapgen.h
|
@ -20,13 +20,10 @@ with this program; if not, write to the Free Software Foundation, Inc.,
|
|||
#ifndef MAPGEN_HEADER
|
||||
#define MAPGEN_HEADER
|
||||
|
||||
#include "irrlichttypes_bloated.h"
|
||||
#include "util/container.h" // UniqueQueue
|
||||
#include "gamedef.h"
|
||||
#include "nodedef.h"
|
||||
#include "mapnode.h"
|
||||
#include "noise.h"
|
||||
#include "settings.h"
|
||||
#include "util/string.h"
|
||||
#include "util/container.h"
|
||||
|
||||
#define DEFAULT_MAPGEN "v6"
|
||||
|
||||
|
@ -39,11 +36,13 @@ with this program; if not, write to the Free Software Foundation, Inc.,
|
|||
|
||||
#define NUM_GEN_NOTIFY 6
|
||||
|
||||
class Settings;
|
||||
class ManualMapVoxelManipulator;
|
||||
class INodeDefManager;
|
||||
|
||||
extern FlagDesc flagdesc_mapgen[];
|
||||
extern FlagDesc flagdesc_gennotify[];
|
||||
|
||||
class BiomeDefManager;
|
||||
class Biome;
|
||||
class EmergeManager;
|
||||
class MapBlock;
|
||||
|
@ -53,7 +52,6 @@ struct BlockMakeData;
|
|||
class VoxelArea;
|
||||
class Map;
|
||||
|
||||
|
||||
enum MapgenObject {
|
||||
MGOBJ_VMANIP,
|
||||
MGOBJ_HEIGHTMAP,
|
||||
|
@ -131,10 +129,38 @@ public:
|
|||
|
||||
struct MapgenFactory {
|
||||
virtual Mapgen *createMapgen(int mgid, MapgenParams *params,
|
||||
EmergeManager *emerge) = 0;
|
||||
EmergeManager *emerge) = 0;
|
||||
virtual MapgenSpecificParams *createMapgenParams() = 0;
|
||||
virtual ~MapgenFactory() {}
|
||||
};
|
||||
|
||||
#endif
|
||||
class GenElement {
|
||||
public:
|
||||
virtual ~GenElement() {}
|
||||
u32 id;
|
||||
std::string name;
|
||||
};
|
||||
|
||||
class GenElementManager {
|
||||
public:
|
||||
static const char *ELEMENT_TITLE;
|
||||
static const size_t ELEMENT_LIMIT = -1;
|
||||
|
||||
GenElementManager() {}
|
||||
virtual ~GenElementManager();
|
||||
|
||||
virtual GenElement *create(int type) = 0;
|
||||
|
||||
virtual u32 add(GenElement *elem);
|
||||
virtual GenElement *get(u32 id);
|
||||
virtual GenElement *update(u32 id, GenElement *elem);
|
||||
virtual GenElement *remove(u32 id);
|
||||
|
||||
virtual GenElement *getByName(const char *name);
|
||||
virtual GenElement *getByName(std::string &name);
|
||||
|
||||
protected:
|
||||
std::vector<GenElement *> m_elements;
|
||||
};
|
||||
|
||||
#endif
|
||||
|
|
|
@ -42,7 +42,7 @@ with this program; if not, write to the Free Software Foundation, Inc.,
|
|||
|
||||
|
||||
FlagDesc flagdesc_mapgen_v5[] = {
|
||||
//{"blobs", MGV5_BLOBS},
|
||||
{"blobs", MGV5_BLOBS},
|
||||
{NULL, 0}
|
||||
};
|
||||
|
||||
|
@ -51,7 +51,7 @@ MapgenV5::MapgenV5(int mapgenid, MapgenParams *params, EmergeManager *emerge_) {
|
|||
this->generating = false;
|
||||
this->id = mapgenid;
|
||||
this->emerge = emerge_;
|
||||
this->bmgr = emerge->biomedef;
|
||||
this->bmgr = emerge->biomemgr;
|
||||
|
||||
this->seed = (int)params->seed;
|
||||
this->water_level = params->water_level;
|
||||
|
@ -70,6 +70,8 @@ MapgenV5::MapgenV5(int mapgenid, MapgenParams *params, EmergeManager *emerge_) {
|
|||
|
||||
MapgenV5Params *sp = (MapgenV5Params *)params->sparams;
|
||||
|
||||
this->spflags = sp->spflags;
|
||||
|
||||
// Terrain noise
|
||||
noise_filler_depth = new Noise(&sp->np_filler_depth, seed, csize.X, csize.Z);
|
||||
noise_factor = new Noise(&sp->np_factor, seed, csize.X, csize.Z);
|
||||
|
@ -134,31 +136,32 @@ MapgenV5::~MapgenV5() {
|
|||
|
||||
|
||||
MapgenV5Params::MapgenV5Params() {
|
||||
//spflags = MGV5_BLOBS;
|
||||
spflags = 0;
|
||||
spflags = MGV5_BLOBS;
|
||||
|
||||
np_filler_depth = NoiseParams(0, 1, v3f(150, 150, 150), 261, 4, 0.7);
|
||||
np_factor = NoiseParams(0, 1, v3f(250, 250, 250), 920381, 3, 0.45);
|
||||
np_height = NoiseParams(0, 10, v3f(250, 250, 250), 84174, 4, 0.5);
|
||||
np_cave1 = NoiseParams(0, 7.5, v3f(50, 50, 50), 52534, 4, 0.5);
|
||||
np_cave2 = NoiseParams(0, 7.5, v3f(50, 50, 50), 10325, 4, 0.5);
|
||||
np_ground = NoiseParams(0, 40, v3f(80, 80, 80), 983240, 4, 0.55);
|
||||
np_crumble = NoiseParams(0, 1, v3f(20, 20, 20), 34413, 3, 1.3);
|
||||
np_wetness = NoiseParams(0, 1, v3f(40, 40, 40), 32474, 4, 1.1);
|
||||
np_filler_depth = NoiseParams(0, 1, v3f(150, 150, 150), 261, 4, 0.7);
|
||||
np_factor = NoiseParams(0, 1, v3f(250, 250, 250), 920381, 3, 0.45);
|
||||
np_height = NoiseParams(0, 10, v3f(250, 250, 250), 84174, 4, 0.5);
|
||||
np_cave1 = NoiseParams(0, 6, v3f(50, 50, 50), 52534, 4, 0.5);
|
||||
np_cave2 = NoiseParams(0, 6, v3f(50, 50, 50), 10325, 4, 0.5);
|
||||
np_ground = NoiseParams(0, 40, v3f(80, 80, 80), 983240, 4, 0.55);
|
||||
np_crumble = NoiseParams(0, 1, v3f(20, 20, 20), 34413, 3, 1.3);
|
||||
np_wetness = NoiseParams(0, 1, v3f(40, 40, 40), 32474, 4, 1.1);
|
||||
}
|
||||
|
||||
|
||||
// Current caves noise scale default is 6 to compensate for new eased 3d noise amplitude
|
||||
|
||||
// Scaling the output of the noise function affects the overdrive of the
|
||||
// contour function, which affects the shape of the output considerably.
|
||||
|
||||
//#define CAVE_NOISE_SCALE 12.0 < original default
|
||||
//#define CAVE_NOISE_SCALE 10.0
|
||||
//#define CAVE_NOISE_SCALE 7.5 < current default to compensate for new eased 3d noise
|
||||
//#define CAVE_NOISE_SCALE 7.5
|
||||
//#define CAVE_NOISE_SCALE 5.0
|
||||
//#define CAVE_NOISE_SCALE 1.0
|
||||
|
||||
//#define CAVE_NOISE_THRESHOLD (2.5/CAVE_NOISE_SCALE)
|
||||
//#define CAVE_NOISE_THRESHOLD (1.5/CAVE_NOISE_SCALE) < original and current default
|
||||
//#define CAVE_NOISE_THRESHOLD (1.5/CAVE_NOISE_SCALE) < original and current code
|
||||
|
||||
|
||||
void MapgenV5Params::readParams(Settings *settings) {
|
||||
|
@ -222,17 +225,13 @@ void MapgenV5::makeChunk(BlockMakeData *data) {
|
|||
updateHeightmap(node_min, node_max);
|
||||
|
||||
// Generate underground dirt, sand, gravel and lava blobs
|
||||
//if (spflags & MGV5_BLOBS) {
|
||||
if (spflags & MGV5_BLOBS) {
|
||||
generateBlobs();
|
||||
//}
|
||||
}
|
||||
|
||||
// Calculate biomes
|
||||
BiomeNoiseInput binput;
|
||||
binput.mapsize = v2s16(csize.X, csize.Z);
|
||||
binput.heat_map = noise_heat->result;
|
||||
binput.humidity_map = noise_humidity->result;
|
||||
binput.height_map = heightmap;
|
||||
bmgr->calcBiomes(&binput, biomemap);
|
||||
bmgr->calcBiomes(csize.X, csize.Z, noise_heat->result,
|
||||
noise_humidity->result, heightmap, biomemap);
|
||||
|
||||
// Actually place the biome-specific nodes
|
||||
generateBiomes();
|
||||
|
@ -244,16 +243,10 @@ void MapgenV5::makeChunk(BlockMakeData *data) {
|
|||
}
|
||||
|
||||
// Generate the registered decorations
|
||||
for (size_t i = 0; i != emerge->decorations.size(); i++) {
|
||||
Decoration *deco = emerge->decorations[i];
|
||||
deco->placeDeco(this, blockseed + i, node_min, node_max);
|
||||
}
|
||||
emerge->decomgr->placeAllDecos(this, blockseed, node_min, node_max);
|
||||
|
||||
// Generate the registered ores
|
||||
for (unsigned int i = 0; i != emerge->ores.size(); i++) {
|
||||
Ore *ore = emerge->ores[i];
|
||||
ore->placeOre(this, blockseed + i, node_min, node_max);
|
||||
}
|
||||
emerge->oremgr->placeAllOres(this, blockseed, node_min, node_max);
|
||||
|
||||
// Sprinkle some dust on top after everything else was generated
|
||||
dustTopNodes();
|
||||
|
@ -290,10 +283,10 @@ void MapgenV5::calculateNoise() {
|
|||
noise_ground->perlinMap3D(x, y, z, true);
|
||||
noise_ground->transformNoiseMap();
|
||||
|
||||
//if (spflags & MGV5_BLOBS) {
|
||||
if (spflags & MGV5_BLOBS) {
|
||||
noise_crumble->perlinMap3D(x, y, z, true);
|
||||
noise_wetness->perlinMap3D(x, y, z, false);
|
||||
//}
|
||||
}
|
||||
|
||||
noise_heat->perlinMap2D(x, z);
|
||||
noise_humidity->perlinMap2D(x, z);
|
||||
|
@ -402,7 +395,7 @@ void MapgenV5::generateBiomes() {
|
|||
|
||||
for (s16 z = node_min.Z; z <= node_max.Z; z++)
|
||||
for (s16 x = node_min.X; x <= node_max.X; x++, index++) {
|
||||
Biome *biome = bmgr->biomes[biomemap[index]];
|
||||
Biome *biome = (Biome *)bmgr->get(biomemap[index]);
|
||||
s16 dfiller = biome->depth_filler + noise_filler_depth->result[index];
|
||||
s16 y0_top = biome->depth_top;
|
||||
s16 y0_filler = biome->depth_filler + biome->depth_top + dfiller;
|
||||
|
@ -415,11 +408,11 @@ void MapgenV5::generateBiomes() {
|
|||
|
||||
for (s16 y = node_max.Y; y >= node_min.Y; y--) {
|
||||
content_t c = vm->m_data[i].getContent();
|
||||
if ((c == c_stone || c == c_dirt_with_grass
|
||||
|| c == c_dirt
|
||||
|| c == c_sand
|
||||
|| c == c_lava_source
|
||||
|| c == c_gravel) && have_air) {
|
||||
bool is_replaceable_content =
|
||||
c == c_stone || c == c_dirt_with_grass || c == c_dirt ||
|
||||
c == c_sand || c == c_lava_source || c == c_gravel;
|
||||
|
||||
if (is_replaceable_content && have_air) {
|
||||
content_t c_below = vm->m_data[i - em.X].getContent();
|
||||
|
||||
if (c_below != CONTENT_AIR) {
|
||||
|
@ -464,7 +457,7 @@ void MapgenV5::dustTopNodes() {
|
|||
|
||||
for (s16 z = node_min.Z; z <= node_max.Z; z++)
|
||||
for (s16 x = node_min.X; x <= node_max.X; x++, index++) {
|
||||
Biome *biome = bmgr->biomes[biomemap[index]];
|
||||
Biome *biome = (Biome *)bmgr->get(biomemap[index]);
|
||||
|
||||
if (biome->c_dust == CONTENT_IGNORE)
|
||||
continue;
|
||||
|
|
|
@ -23,7 +23,7 @@ with this program; if not, write to the Free Software Foundation, Inc.,
|
|||
#include "mapgen.h"
|
||||
|
||||
/////////////////// Mapgen V5 flags
|
||||
//#define MGV5_BLOBS 0x01
|
||||
#define MGV5_BLOBS 0x01
|
||||
|
||||
extern FlagDesc flagdesc_mapgen_v5[];
|
||||
|
||||
|
@ -50,7 +50,7 @@ struct MapgenV5Params : public MapgenSpecificParams {
|
|||
class MapgenV5 : public Mapgen {
|
||||
public:
|
||||
EmergeManager *emerge;
|
||||
BiomeDefManager *bmgr;
|
||||
BiomeManager *bmgr;
|
||||
|
||||
int ystride;
|
||||
int zstride;
|
||||
|
|
|
@ -312,7 +312,7 @@ bool MapgenV6::getHaveBeach(v2s16 p) {
|
|||
}
|
||||
|
||||
|
||||
BiomeType MapgenV6::getBiome(v2s16 p) {
|
||||
BiomeV6Type MapgenV6::getBiome(v2s16 p) {
|
||||
int index = (p.Y - node_min.Z) * ystride + (p.X - node_min.X);
|
||||
return getBiome(index, p);
|
||||
}
|
||||
|
@ -387,7 +387,7 @@ bool MapgenV6::getHaveBeach(int index)
|
|||
}
|
||||
|
||||
|
||||
BiomeType MapgenV6::getBiome(int index, v2s16 p)
|
||||
BiomeV6Type MapgenV6::getBiome(int index, v2s16 p)
|
||||
{
|
||||
// Just do something very simple as for now
|
||||
/*double d = noise2d_perlin(
|
||||
|
@ -537,16 +537,10 @@ void MapgenV6::makeChunk(BlockMakeData *data) {
|
|||
placeTreesAndJungleGrass();
|
||||
|
||||
// Generate the registered decorations
|
||||
for (unsigned int i = 0; i != emerge->decorations.size(); i++) {
|
||||
Decoration *deco = emerge->decorations[i];
|
||||
deco->placeDeco(this, blockseed + i, node_min, node_max);
|
||||
}
|
||||
emerge->decomgr->placeAllDecos(this, blockseed, node_min, node_max);
|
||||
|
||||
// Generate the registered ores
|
||||
for (unsigned int i = 0; i != emerge->ores.size(); i++) {
|
||||
Ore *ore = emerge->ores[i];
|
||||
ore->placeOre(this, blockseed + i, node_min, node_max);
|
||||
}
|
||||
emerge->oremgr->placeAllOres(this, blockseed, node_min, node_max);
|
||||
|
||||
// Calculate lighting
|
||||
if (flags & MG_LIGHT)
|
||||
|
@ -614,7 +608,7 @@ int MapgenV6::generateGround() {
|
|||
if (surface_y > stone_surface_max_y)
|
||||
stone_surface_max_y = surface_y;
|
||||
|
||||
BiomeType bt = getBiome(index, v2s16(x, z));
|
||||
BiomeV6Type bt = getBiome(index, v2s16(x, z));
|
||||
|
||||
// Fill ground with stone
|
||||
v3s16 em = vm->m_area.getExtent();
|
||||
|
@ -658,7 +652,7 @@ void MapgenV6::addMud() {
|
|||
if (surface_y == vm->m_area.MinEdge.Y - 1)
|
||||
continue;
|
||||
|
||||
BiomeType bt = getBiome(index, v2s16(x, z));
|
||||
BiomeV6Type bt = getBiome(index, v2s16(x, z));
|
||||
addnode = (bt == BT_DESERT) ? n_desert_sand : n_dirt;
|
||||
|
||||
if (bt == BT_DESERT && surface_y + mud_add_amount <= water_level + 1) {
|
||||
|
|
|
@ -21,6 +21,7 @@ with this program; if not, write to the Free Software Foundation, Inc.,
|
|||
#define MAPGENV6_HEADER
|
||||
|
||||
#include "mapgen.h"
|
||||
#include "noise.h"
|
||||
|
||||
#define AVERAGE_MUD_AMOUNT 4
|
||||
|
||||
|
@ -33,7 +34,7 @@ with this program; if not, write to the Free Software Foundation, Inc.,
|
|||
extern FlagDesc flagdesc_mapgen_v6[];
|
||||
|
||||
|
||||
enum BiomeType
|
||||
enum BiomeV6Type
|
||||
{
|
||||
BT_NORMAL,
|
||||
BT_DESERT
|
||||
|
@ -131,8 +132,8 @@ public:
|
|||
virtual float getMudAmount(int index);
|
||||
bool getHaveBeach(v2s16 p);
|
||||
bool getHaveBeach(int index);
|
||||
BiomeType getBiome(v2s16 p);
|
||||
BiomeType getBiome(int index, v2s16 p);
|
||||
BiomeV6Type getBiome(v2s16 p);
|
||||
BiomeV6Type getBiome(int index, v2s16 p);
|
||||
|
||||
u32 get_blockseed(u64 seed, v3s16 p);
|
||||
|
||||
|
|
|
@ -53,7 +53,7 @@ MapgenV7::MapgenV7(int mapgenid, MapgenParams *params, EmergeManager *emerge) {
|
|||
this->generating = false;
|
||||
this->id = mapgenid;
|
||||
this->emerge = emerge;
|
||||
this->bmgr = emerge->biomedef;
|
||||
this->bmgr = emerge->biomemgr;
|
||||
|
||||
this->seed = (int)params->seed;
|
||||
this->water_level = params->water_level;
|
||||
|
@ -72,6 +72,7 @@ MapgenV7::MapgenV7(int mapgenid, MapgenParams *params, EmergeManager *emerge) {
|
|||
this->ridge_heightmap = new s16[csize.X * csize.Z];
|
||||
|
||||
MapgenV7Params *sp = (MapgenV7Params *)params->sparams;
|
||||
this->spflags = sp->spflags;
|
||||
|
||||
//// Terrain noise
|
||||
noise_terrain_base = new Noise(&sp->np_terrain_base, seed, csize.X, csize.Z);
|
||||
|
@ -232,12 +233,8 @@ void MapgenV7::makeChunk(BlockMakeData *data) {
|
|||
updateHeightmap(node_min, node_max);
|
||||
|
||||
// Calculate biomes
|
||||
BiomeNoiseInput binput;
|
||||
binput.mapsize = v2s16(csize.X, csize.Z);
|
||||
binput.heat_map = noise_heat->result;
|
||||
binput.humidity_map = noise_humidity->result;
|
||||
binput.height_map = heightmap;
|
||||
bmgr->calcBiomes(&binput, biomemap);
|
||||
bmgr->calcBiomes(csize.X, csize.Z, noise_heat->result,
|
||||
noise_humidity->result, heightmap, biomemap);
|
||||
|
||||
// Actually place the biome-specific nodes and what not
|
||||
generateBiomes();
|
||||
|
@ -250,16 +247,12 @@ void MapgenV7::makeChunk(BlockMakeData *data) {
|
|||
dgen.generate(blockseed, full_node_min, full_node_max);
|
||||
}
|
||||
|
||||
for (size_t i = 0; i != emerge->decorations.size(); i++) {
|
||||
Decoration *deco = emerge->decorations[i];
|
||||
deco->placeDeco(this, blockseed + i, node_min, node_max);
|
||||
}
|
||||
// Generate the registered decorations
|
||||
emerge->decomgr->placeAllDecos(this, blockseed, node_min, node_max);
|
||||
|
||||
// Generate the registered ores
|
||||
emerge->oremgr->placeAllOres(this, blockseed, node_min, node_max);
|
||||
|
||||
for (size_t i = 0; i != emerge->ores.size(); i++) {
|
||||
Ore *ore = emerge->ores[i];
|
||||
ore->placeOre(this, blockseed + i, node_min, node_max);
|
||||
}
|
||||
|
||||
// Sprinkle some dust on top after everything else was generated
|
||||
dustTopNodes();
|
||||
|
||||
|
@ -538,11 +531,11 @@ void MapgenV7::generateBiomes() {
|
|||
|
||||
for (s16 z = node_min.Z; z <= node_max.Z; z++)
|
||||
for (s16 x = node_min.X; x <= node_max.X; x++, index++) {
|
||||
Biome *biome = bmgr->biomes[biomemap[index]];
|
||||
Biome *biome = (Biome *)bmgr->get(biomemap[index]);
|
||||
s16 dfiller = biome->depth_filler + noise_filler_depth->result[index];
|
||||
s16 y0_top = biome->depth_top;
|
||||
s16 y0_filler = biome->depth_filler + biome->depth_top + dfiller;
|
||||
|
||||
|
||||
s16 nplaced = 0;
|
||||
u32 i = vm->m_area.index(x, node_max.Y, z);
|
||||
|
||||
|
@ -607,7 +600,7 @@ void MapgenV7::dustTopNodes() {
|
|||
|
||||
for (s16 z = node_min.Z; z <= node_max.Z; z++)
|
||||
for (s16 x = node_min.X; x <= node_max.X; x++, index++) {
|
||||
Biome *biome = bmgr->biomes[biomemap[index]];
|
||||
Biome *biome = (Biome *)bmgr->get(biomemap[index]);
|
||||
|
||||
if (biome->c_dust == CONTENT_IGNORE)
|
||||
continue;
|
||||
|
|
|
@ -26,6 +26,7 @@ with this program; if not, write to the Free Software Foundation, Inc.,
|
|||
#define MGV7_MOUNTAINS 0x01
|
||||
#define MGV7_RIDGES 0x02
|
||||
|
||||
class BiomeManager;
|
||||
|
||||
extern FlagDesc flagdesc_mapgen_v7[];
|
||||
|
||||
|
@ -52,7 +53,7 @@ struct MapgenV7Params : public MapgenSpecificParams {
|
|||
class MapgenV7 : public Mapgen {
|
||||
public:
|
||||
EmergeManager *emerge;
|
||||
BiomeDefManager *bmgr;
|
||||
BiomeManager *bmgr;
|
||||
|
||||
int ystride;
|
||||
int zstride;
|
||||
|
|
|
@ -18,6 +18,7 @@ with this program; if not, write to the Free Software Foundation, Inc.,
|
|||
*/
|
||||
|
||||
#include "mg_biome.h"
|
||||
#include "gamedef.h"
|
||||
#include "nodedef.h"
|
||||
#include "map.h" //for ManualMapVoxelManipulator
|
||||
#include "log.h"
|
||||
|
@ -26,19 +27,25 @@ with this program; if not, write to the Free Software Foundation, Inc.,
|
|||
#include "util/mathconstants.h"
|
||||
#include "porting.h"
|
||||
|
||||
const char *BiomeManager::ELEMENT_TITLE = "biome";
|
||||
|
||||
NoiseParams nparams_biome_def_heat(50, 50, v3f(500.0, 500.0, 500.0), 5349, 3, 0.70);
|
||||
NoiseParams nparams_biome_def_humidity(50, 50, v3f(500.0, 500.0, 500.0), 842, 3, 0.55);
|
||||
|
||||
|
||||
BiomeDefManager::BiomeDefManager(NodeResolver *resolver)
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
|
||||
BiomeManager::BiomeManager(IGameDef *gamedef)
|
||||
{
|
||||
biome_registration_finished = false;
|
||||
NodeResolver *resolver = gamedef->getNodeDefManager()->getResolver();
|
||||
|
||||
np_heat = &nparams_biome_def_heat;
|
||||
np_humidity = &nparams_biome_def_humidity;
|
||||
|
||||
// Create default biome to be used in case none exist
|
||||
Biome *b = new Biome;
|
||||
|
||||
|
||||
b->id = 0;
|
||||
b->name = "Default";
|
||||
b->flags = 0;
|
||||
|
@ -55,84 +62,42 @@ BiomeDefManager::BiomeDefManager(NodeResolver *resolver)
|
|||
resolver->addNode("air", "", CONTENT_AIR, &b->c_dust);
|
||||
resolver->addNode("mapgen_water_source", "", CONTENT_AIR, &b->c_dust_water);
|
||||
|
||||
biomes.push_back(b);
|
||||
add(b);
|
||||
}
|
||||
|
||||
|
||||
BiomeDefManager::~BiomeDefManager()
|
||||
|
||||
BiomeManager::~BiomeManager()
|
||||
{
|
||||
//if (biomecache)
|
||||
// delete[] biomecache;
|
||||
|
||||
for (size_t i = 0; i != biomes.size(); i++)
|
||||
delete biomes[i];
|
||||
}
|
||||
|
||||
|
||||
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 BiomeSky;
|
||||
case BIOME_TERRAIN_FLAT:
|
||||
return new BiomeSuperflat;
|
||||
}
|
||||
return NULL;*/
|
||||
return new Biome;
|
||||
}
|
||||
|
||||
|
||||
// just a PoC, obviously needs optimization later on (precalculate this)
|
||||
void BiomeDefManager::calcBiomes(BiomeNoiseInput *input, u8 *biomeid_map)
|
||||
void BiomeManager::calcBiomes(s16 sx, s16 sy, float *heat_map,
|
||||
float *humidity_map, s16 *height_map, u8 *biomeid_map)
|
||||
{
|
||||
int i = 0;
|
||||
for (int y = 0; y != input->mapsize.Y; y++) {
|
||||
for (int x = 0; x != input->mapsize.X; x++, i++) {
|
||||
float heat = (input->heat_map[i] + 1) * 50;
|
||||
float humidity = (input->humidity_map[i] + 1) * 50;
|
||||
biomeid_map[i] = getBiome(heat, humidity, input->height_map[i])->id;
|
||||
for (int y = 0; y != sy; y++) {
|
||||
for (int x = 0; x != sx; x++, i++) {
|
||||
float heat = (heat_map[i] + 1) * 50;
|
||||
float humidity = (humidity_map[i] + 1) * 50;
|
||||
biomeid_map[i] = getBiome(heat, humidity, height_map[i])->id;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
bool BiomeDefManager::addBiome(Biome *b)
|
||||
{
|
||||
if (biome_registration_finished) {
|
||||
errorstream << "BiomeDefManager: biome registration already "
|
||||
"finished, dropping " << b->name << std::endl;
|
||||
return false;
|
||||
}
|
||||
|
||||
size_t nbiomes = biomes.size();
|
||||
if (nbiomes >= 0xFF) {
|
||||
errorstream << "BiomeDefManager: too many biomes, dropping "
|
||||
<< b->name << std::endl;
|
||||
return false;
|
||||
}
|
||||
|
||||
b->id = (u8)nbiomes;
|
||||
biomes.push_back(b);
|
||||
verbosestream << "BiomeDefManager: added biome " << b->name << std::endl;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
Biome *BiomeDefManager::getBiome(float heat, float humidity, s16 y)
|
||||
Biome *BiomeManager::getBiome(float heat, float humidity, s16 y)
|
||||
{
|
||||
Biome *b, *biome_closest = NULL;
|
||||
float dist_min = FLT_MAX;
|
||||
|
||||
for (size_t i = 1; i < biomes.size(); i++) {
|
||||
b = biomes[i];
|
||||
if (y > b->height_max || y < b->height_min)
|
||||
for (size_t i = 1; i < m_elements.size(); i++) {
|
||||
b = (Biome *)m_elements[i];
|
||||
if (!b || y > b->height_max || y < b->height_min)
|
||||
continue;
|
||||
|
||||
float d_heat = heat - b->heat_point;
|
||||
|
@ -145,16 +110,5 @@ Biome *BiomeDefManager::getBiome(float heat, float humidity, s16 y)
|
|||
}
|
||||
}
|
||||
|
||||
return biome_closest ? biome_closest : biomes[0];
|
||||
}
|
||||
|
||||
|
||||
u8 BiomeDefManager::getBiomeIdByName(const char *name)
|
||||
{
|
||||
for (size_t i = 0; i != biomes.size(); i++) {
|
||||
if (!strcasecmp(name, biomes[i]->name.c_str()))
|
||||
return i;
|
||||
}
|
||||
|
||||
return 0;
|
||||
return biome_closest ? biome_closest : (Biome *)m_elements[0];
|
||||
}
|
||||
|
|
|
@ -20,29 +20,24 @@ with this program; if not, write to the Free Software Foundation, Inc.,
|
|||
#ifndef MG_BIOME_HEADER
|
||||
#define MG_BIOME_HEADER
|
||||
|
||||
#include <string>
|
||||
#include "nodedef.h"
|
||||
#include "gamedef.h"
|
||||
#include "mapnode.h"
|
||||
#include "noise.h"
|
||||
#include "mapgen.h"
|
||||
#include "noise.h"
|
||||
|
||||
enum BiomeTerrainType
|
||||
enum BiomeType
|
||||
{
|
||||
BIOME_TERRAIN_NORMAL,
|
||||
BIOME_TERRAIN_LIQUID,
|
||||
BIOME_TERRAIN_NETHER,
|
||||
BIOME_TERRAIN_AETHER,
|
||||
BIOME_TERRAIN_FLAT
|
||||
BIOME_TYPE_NORMAL,
|
||||
BIOME_TYPE_LIQUID,
|
||||
BIOME_TYPE_NETHER,
|
||||
BIOME_TYPE_AETHER,
|
||||
BIOME_TYPE_FLAT
|
||||
};
|
||||
|
||||
extern NoiseParams nparams_biome_def_heat;
|
||||
extern NoiseParams nparams_biome_def_humidity;
|
||||
|
||||
class Biome {
|
||||
|
||||
class Biome : public GenElement {
|
||||
public:
|
||||
u8 id;
|
||||
std::string name;
|
||||
u32 flags;
|
||||
|
||||
content_t c_top;
|
||||
|
@ -60,33 +55,25 @@ public:
|
|||
float humidity_point;
|
||||
};
|
||||
|
||||
struct BiomeNoiseInput {
|
||||
v2s16 mapsize;
|
||||
float *heat_map;
|
||||
float *humidity_map;
|
||||
s16 *height_map;
|
||||
};
|
||||
|
||||
class BiomeDefManager {
|
||||
class BiomeManager : public GenElementManager {
|
||||
public:
|
||||
std::vector<Biome *> biomes;
|
||||
static const char *ELEMENT_TITLE;
|
||||
static const size_t ELEMENT_LIMIT = 0x100;
|
||||
|
||||
bool biome_registration_finished;
|
||||
NoiseParams *np_heat;
|
||||
NoiseParams *np_humidity;
|
||||
|
||||
BiomeDefManager(NodeResolver *resolver);
|
||||
~BiomeDefManager();
|
||||
BiomeManager(IGameDef *gamedef);
|
||||
~BiomeManager();
|
||||
|
||||
Biome *createBiome(BiomeTerrainType btt);
|
||||
void calcBiomes(BiomeNoiseInput *input, u8 *biomeid_map);
|
||||
Biome *create(int btt)
|
||||
{
|
||||
return new Biome;
|
||||
}
|
||||
|
||||
void calcBiomes(s16 sx, s16 sy, float *heat_map, float *humidity_map,
|
||||
s16 *height_map, u8 *biomeid_map);
|
||||
Biome *getBiome(float heat, float humidity, s16 y);
|
||||
|
||||
bool addBiome(Biome *b);
|
||||
u8 getBiomeIdByName(const char *name);
|
||||
|
||||
s16 calcBlockHeat(v3s16 p, u64 seed, float timeofday, float totaltime);
|
||||
s16 calcBlockHumidity(v3s16 p, u64 seed, float timeofday, float totaltime);
|
||||
};
|
||||
|
||||
#endif
|
||||
|
|
|
@ -20,28 +20,44 @@ with this program; if not, write to the Free Software Foundation, Inc.,
|
|||
#include "mg_decoration.h"
|
||||
#include "mg_schematic.h"
|
||||
#include "mapgen.h"
|
||||
#include "noise.h"
|
||||
#include "map.h"
|
||||
#include "log.h"
|
||||
#include "util/numeric.h"
|
||||
|
||||
const char *DecorationManager::ELEMENT_TITLE = "decoration";
|
||||
|
||||
FlagDesc flagdesc_deco_schematic[] = {
|
||||
{"place_center_x", DECO_PLACE_CENTER_X},
|
||||
{"place_center_y", DECO_PLACE_CENTER_Y},
|
||||
{"place_center_z", DECO_PLACE_CENTER_Z},
|
||||
{NULL, 0}
|
||||
};
|
||||
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
|
||||
Decoration *createDecoration(DecorationType type)
|
||||
size_t DecorationManager::placeAllDecos(Mapgen *mg, u32 seed, v3s16 nmin, v3s16 nmax)
|
||||
{
|
||||
switch (type) {
|
||||
case DECO_SIMPLE:
|
||||
return new DecoSimple;
|
||||
case DECO_SCHEMATIC:
|
||||
return new DecoSchematic;
|
||||
//case DECO_LSYSTEM:
|
||||
// return new DecoLSystem;
|
||||
default:
|
||||
return NULL;
|
||||
size_t nplaced = 0;
|
||||
|
||||
for (size_t i = 0; i != m_elements.size(); i++) {
|
||||
Decoration *deco = (Decoration *)m_elements[i];
|
||||
if (!deco)
|
||||
continue;
|
||||
|
||||
nplaced += deco->placeDeco(mg, seed, nmin, nmax);
|
||||
seed++;
|
||||
}
|
||||
|
||||
return nplaced;
|
||||
}
|
||||
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
|
||||
Decoration::Decoration()
|
||||
{
|
||||
mapseed = 0;
|
||||
|
@ -57,7 +73,7 @@ Decoration::~Decoration()
|
|||
}
|
||||
|
||||
|
||||
void Decoration::placeDeco(Mapgen *mg, u32 blockseed, v3s16 nmin, v3s16 nmax)
|
||||
size_t Decoration::placeDeco(Mapgen *mg, u32 blockseed, v3s16 nmin, v3s16 nmax)
|
||||
{
|
||||
PseudoRandom ps(blockseed + 53);
|
||||
int carea_size = nmax.X - nmin.X + 1;
|
||||
|
@ -131,6 +147,8 @@ void Decoration::placeDeco(Mapgen *mg, u32 blockseed, v3s16 nmin, v3s16 nmax)
|
|||
generate(mg, &ps, max_y, v3s16(x, y, z));
|
||||
}
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
|
@ -190,6 +208,7 @@ void Decoration::placeCutoffs(Mapgen *mg, u32 blockseed, v3s16 nmin, v3s16 nmax)
|
|||
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
|
||||
bool DecoSimple::canPlaceDecoration(ManualMapVoxelManipulator *vm, v3s16 p)
|
||||
{
|
||||
// Don't bother if there aren't any decorations to place
|
||||
|
@ -269,7 +288,33 @@ int DecoSimple::getHeight()
|
|||
}
|
||||
|
||||
|
||||
std::string DecoSimple::getName()
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
|
||||
void DecoSchematic::generate(Mapgen *mg, PseudoRandom *pr, s16 max_y, v3s16 p)
|
||||
{
|
||||
return "";
|
||||
ManualMapVoxelManipulator *vm = mg->vm;
|
||||
|
||||
if (flags & DECO_PLACE_CENTER_X)
|
||||
p.X -= (schematic->size.X + 1) / 2;
|
||||
if (flags & DECO_PLACE_CENTER_Y)
|
||||
p.Y -= (schematic->size.Y + 1) / 2;
|
||||
if (flags & DECO_PLACE_CENTER_Z)
|
||||
p.Z -= (schematic->size.Z + 1) / 2;
|
||||
|
||||
u32 vi = vm->m_area.index(p);
|
||||
content_t c = vm->m_data[vi].getContent();
|
||||
if (!CONTAINS(c_place_on, c))
|
||||
return;
|
||||
|
||||
Rotation rot = (rotation == ROTATE_RAND) ?
|
||||
(Rotation)pr->range(ROTATE_0, ROTATE_270) : rotation;
|
||||
|
||||
schematic->blitToVManip(p, vm, rot, false, mg->ndef);
|
||||
}
|
||||
|
||||
|
||||
int DecoSchematic::getHeight()
|
||||
{
|
||||
return schematic->size.Y;
|
||||
}
|
||||
|
|
|
@ -21,12 +21,13 @@ with this program; if not, write to the Free Software Foundation, Inc.,
|
|||
#define MG_DECORATION_HEADER
|
||||
|
||||
#include <set>
|
||||
#include "mapnode.h"
|
||||
#include "mapgen.h"
|
||||
|
||||
class NoiseParams;
|
||||
class Mapgen;
|
||||
class ManualMapVoxelManipulator;
|
||||
class PseudoRandom;
|
||||
class Schematic;
|
||||
|
||||
enum DecorationType {
|
||||
DECO_SIMPLE,
|
||||
|
@ -34,6 +35,13 @@ enum DecorationType {
|
|||
DECO_LSYSTEM
|
||||
};
|
||||
|
||||
#define DECO_PLACE_CENTER_X 0x01
|
||||
#define DECO_PLACE_CENTER_Y 0x02
|
||||
#define DECO_PLACE_CENTER_Z 0x04
|
||||
|
||||
extern FlagDesc flagdesc_deco_schematic[];
|
||||
|
||||
|
||||
#if 0
|
||||
struct CutoffData {
|
||||
VoxelArea a;
|
||||
|
@ -49,7 +57,7 @@ struct CutoffData {
|
|||
};
|
||||
#endif
|
||||
|
||||
class Decoration {
|
||||
class Decoration : public GenElement {
|
||||
public:
|
||||
INodeDefManager *ndef;
|
||||
|
||||
|
@ -66,12 +74,11 @@ public:
|
|||
Decoration();
|
||||
virtual ~Decoration();
|
||||
|
||||
void placeDeco(Mapgen *mg, u32 blockseed, v3s16 nmin, v3s16 nmax);
|
||||
void placeCutoffs(Mapgen *mg, u32 blockseed, v3s16 nmin, v3s16 nmax);
|
||||
size_t placeDeco(Mapgen *mg, u32 blockseed, v3s16 nmin, v3s16 nmax);
|
||||
size_t placeCutoffs(Mapgen *mg, u32 blockseed, v3s16 nmin, v3s16 nmax);
|
||||
|
||||
virtual void generate(Mapgen *mg, PseudoRandom *pr, s16 max_y, v3s16 p) = 0;
|
||||
virtual int getHeight() = 0;
|
||||
virtual std::string getName() = 0;
|
||||
};
|
||||
|
||||
class DecoSimple : public Decoration {
|
||||
|
@ -87,9 +94,22 @@ public:
|
|||
bool canPlaceDecoration(ManualMapVoxelManipulator *vm, v3s16 p);
|
||||
virtual void generate(Mapgen *mg, PseudoRandom *pr, s16 max_y, v3s16 p);
|
||||
virtual int getHeight();
|
||||
virtual std::string getName();
|
||||
};
|
||||
|
||||
class DecoSchematic : public Decoration {
|
||||
public:
|
||||
u32 flags;
|
||||
Rotation rotation;
|
||||
Schematic *schematic;
|
||||
std::string filename;
|
||||
|
||||
~DecoSchematic() {}
|
||||
|
||||
void generate(Mapgen *mg, PseudoRandom *pr, s16 max_y, v3s16 p);
|
||||
virtual int getHeight();
|
||||
};
|
||||
|
||||
|
||||
/*
|
||||
class DecoLSystem : public Decoration {
|
||||
public:
|
||||
|
@ -97,6 +117,29 @@ public:
|
|||
};
|
||||
*/
|
||||
|
||||
Decoration *createDecoration(DecorationType type);
|
||||
class DecorationManager : public GenElementManager {
|
||||
public:
|
||||
static const char *ELEMENT_TITLE;
|
||||
static const size_t ELEMENT_LIMIT = 0x10000;
|
||||
|
||||
DecorationManager(IGameDef *gamedef) {}
|
||||
~DecorationManager() {}
|
||||
|
||||
Decoration *create(int type)
|
||||
{
|
||||
switch (type) {
|
||||
case DECO_SIMPLE:
|
||||
return new DecoSimple;
|
||||
case DECO_SCHEMATIC:
|
||||
return new DecoSchematic;
|
||||
//case DECO_LSYSTEM:
|
||||
// return new DecoLSystem;
|
||||
default:
|
||||
return NULL;
|
||||
}
|
||||
}
|
||||
|
||||
size_t placeAllDecos(Mapgen *mg, u32 seed, v3s16 nmin, v3s16 nmax);
|
||||
};
|
||||
|
||||
#endif
|
||||
|
|
|
@ -19,10 +19,12 @@ with this program; if not, write to the Free Software Foundation, Inc.,
|
|||
|
||||
#include "mg_ore.h"
|
||||
#include "mapgen.h"
|
||||
#include "noise.h"
|
||||
#include "util/numeric.h"
|
||||
#include "map.h"
|
||||
#include "log.h"
|
||||
|
||||
const char *OreManager::ELEMENT_TITLE = "ore";
|
||||
|
||||
FlagDesc flagdesc_ore[] = {
|
||||
{"absheight", OREFLAG_ABSHEIGHT},
|
||||
|
@ -31,24 +33,36 @@ FlagDesc flagdesc_ore[] = {
|
|||
{NULL, 0}
|
||||
};
|
||||
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
|
||||
Ore *createOre(OreType type)
|
||||
size_t OreManager::placeAllOres(Mapgen *mg, u32 seed, v3s16 nmin, v3s16 nmax)
|
||||
{
|
||||
switch (type) {
|
||||
case ORE_SCATTER:
|
||||
return new OreScatter;
|
||||
case ORE_SHEET:
|
||||
return new OreSheet;
|
||||
//case ORE_CLAYLIKE: //TODO: implement this!
|
||||
// return new OreClaylike;
|
||||
default:
|
||||
return NULL;
|
||||
size_t nplaced = 0;
|
||||
|
||||
for (size_t i = 0; i != m_elements.size(); i++) {
|
||||
Ore *ore = (Ore *)m_elements[i];
|
||||
if (!ore)
|
||||
continue;
|
||||
|
||||
nplaced += ore->placeOre(mg, seed, nmin, nmax);
|
||||
seed++;
|
||||
}
|
||||
|
||||
return nplaced;
|
||||
}
|
||||
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
Ore::Ore()
|
||||
{
|
||||
c_ore = CONTENT_IGNORE;
|
||||
np = NULL;
|
||||
noise = NULL;
|
||||
}
|
||||
|
||||
Ore::~Ore()
|
||||
{
|
||||
delete np;
|
||||
|
@ -56,7 +70,7 @@ Ore::~Ore()
|
|||
}
|
||||
|
||||
|
||||
void Ore::placeOre(Mapgen *mg, u32 blockseed, v3s16 nmin, v3s16 nmax)
|
||||
size_t Ore::placeOre(Mapgen *mg, u32 blockseed, v3s16 nmin, v3s16 nmax)
|
||||
{
|
||||
int in_range = 0;
|
||||
|
||||
|
@ -64,7 +78,7 @@ void Ore::placeOre(Mapgen *mg, u32 blockseed, v3s16 nmin, v3s16 nmax)
|
|||
if (flags & OREFLAG_ABSHEIGHT)
|
||||
in_range |= (nmin.Y >= -height_max && nmax.Y <= -height_min) << 1;
|
||||
if (!in_range)
|
||||
return;
|
||||
return 0;
|
||||
|
||||
int ymin, ymax;
|
||||
if (in_range & ORE_RANGE_MIRROR) {
|
||||
|
@ -75,11 +89,13 @@ void Ore::placeOre(Mapgen *mg, u32 blockseed, v3s16 nmin, v3s16 nmax)
|
|||
ymax = MYMIN(nmax.Y, height_max);
|
||||
}
|
||||
if (clust_size >= ymax - ymin + 1)
|
||||
return;
|
||||
return 0;
|
||||
|
||||
nmin.Y = ymin;
|
||||
nmax.Y = ymax;
|
||||
generate(mg->vm, mg->seed, blockseed, nmin, nmax);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
|
|
47
src/mg_ore.h
47
src/mg_ore.h
|
@ -21,7 +21,7 @@ with this program; if not, write to the Free Software Foundation, Inc.,
|
|||
#define MG_ORE_HEADER
|
||||
|
||||
#include "util/string.h"
|
||||
#include "mapnode.h"
|
||||
#include "mapgen.h"
|
||||
|
||||
class NoiseParams;
|
||||
class Noise;
|
||||
|
@ -29,10 +29,13 @@ class Mapgen;
|
|||
class ManualMapVoxelManipulator;
|
||||
|
||||
/////////////////// Ore generation flags
|
||||
|
||||
// Use absolute value of height to determine ore placement
|
||||
#define OREFLAG_ABSHEIGHT 0x01
|
||||
|
||||
// Use 3d noise to get density of ore placement, instead of just the position
|
||||
#define OREFLAG_DENSITY 0x02 // not yet implemented
|
||||
|
||||
// For claylike ore types, place ore if the number of surrounding
|
||||
// nodes isn't the specified node
|
||||
#define OREFLAG_NODEISNT 0x04 // not yet implemented
|
||||
|
@ -40,7 +43,6 @@ class ManualMapVoxelManipulator;
|
|||
#define ORE_RANGE_ACTUAL 1
|
||||
#define ORE_RANGE_MIRROR 2
|
||||
|
||||
extern FlagDesc flagdesc_ore[];
|
||||
|
||||
enum OreType {
|
||||
ORE_SCATTER,
|
||||
|
@ -48,7 +50,9 @@ enum OreType {
|
|||
ORE_CLAYLIKE
|
||||
};
|
||||
|
||||
class Ore {
|
||||
extern FlagDesc flagdesc_ore[];
|
||||
|
||||
class Ore : public GenElement {
|
||||
public:
|
||||
content_t c_ore; // the node to place
|
||||
std::vector<content_t> c_wherein; // the nodes to be placed in
|
||||
|
@ -63,32 +67,49 @@ public:
|
|||
NoiseParams *np; // noise for distribution of clusters (NULL for uniform scattering)
|
||||
Noise *noise;
|
||||
|
||||
Ore() {
|
||||
c_ore = CONTENT_IGNORE;
|
||||
np = NULL;
|
||||
noise = NULL;
|
||||
}
|
||||
|
||||
Ore();
|
||||
virtual ~Ore();
|
||||
|
||||
void placeOre(Mapgen *mg, u32 blockseed, v3s16 nmin, v3s16 nmax);
|
||||
size_t placeOre(Mapgen *mg, u32 blockseed, v3s16 nmin, v3s16 nmax);
|
||||
virtual void generate(ManualMapVoxelManipulator *vm, int seed,
|
||||
u32 blockseed, v3s16 nmin, v3s16 nmax) = 0;
|
||||
};
|
||||
|
||||
class OreScatter : public Ore {
|
||||
~OreScatter() {}
|
||||
virtual ~OreScatter() {}
|
||||
virtual void generate(ManualMapVoxelManipulator *vm, int seed,
|
||||
u32 blockseed, v3s16 nmin, v3s16 nmax);
|
||||
};
|
||||
|
||||
class OreSheet : public Ore {
|
||||
~OreSheet() {}
|
||||
virtual ~OreSheet() {}
|
||||
virtual void generate(ManualMapVoxelManipulator *vm, int seed,
|
||||
u32 blockseed, v3s16 nmin, v3s16 nmax);
|
||||
};
|
||||
|
||||
Ore *createOre(OreType type);
|
||||
class OreManager : public GenElementManager {
|
||||
public:
|
||||
static const char *ELEMENT_TITLE;
|
||||
static const size_t ELEMENT_LIMIT = 0x10000;
|
||||
|
||||
OreManager(IGameDef *gamedef) {}
|
||||
~OreManager() {}
|
||||
|
||||
Ore *create(int type)
|
||||
{
|
||||
switch (type) {
|
||||
case ORE_SCATTER:
|
||||
return new OreScatter;
|
||||
case ORE_SHEET:
|
||||
return new OreSheet;
|
||||
//case ORE_CLAYLIKE: //TODO: implement this!
|
||||
// return new OreClaylike;
|
||||
default:
|
||||
return NULL;
|
||||
}
|
||||
}
|
||||
|
||||
size_t placeAllOres(Mapgen *mg, u32 seed, v3s16 nmin, v3s16 nmax);
|
||||
};
|
||||
|
||||
#endif
|
||||
|
|
|
@ -28,79 +28,42 @@ with this program; if not, write to the Free Software Foundation, Inc.,
|
|||
#include "serialization.h"
|
||||
#include "filesys.h"
|
||||
|
||||
FlagDesc flagdesc_deco_schematic[] = {
|
||||
{"place_center_x", DECO_PLACE_CENTER_X},
|
||||
{"place_center_y", DECO_PLACE_CENTER_Y},
|
||||
{"place_center_z", DECO_PLACE_CENTER_Z},
|
||||
{NULL, 0}
|
||||
};
|
||||
const char *SchematicManager::ELEMENT_TITLE = "schematic";
|
||||
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
|
||||
DecoSchematic::DecoSchematic()
|
||||
Schematic::Schematic()
|
||||
{
|
||||
schematic = NULL;
|
||||
schemdata = NULL;
|
||||
slice_probs = NULL;
|
||||
flags = 0;
|
||||
size = v3s16(0, 0, 0);
|
||||
}
|
||||
|
||||
|
||||
DecoSchematic::~DecoSchematic()
|
||||
Schematic::~Schematic()
|
||||
{
|
||||
delete []schematic;
|
||||
delete []schemdata;
|
||||
delete []slice_probs;
|
||||
}
|
||||
|
||||
|
||||
void DecoSchematic::updateContentIds()
|
||||
void Schematic::updateContentIds()
|
||||
{
|
||||
if (flags & DECO_SCHEM_CIDS_UPDATED)
|
||||
if (flags & SCHEM_CIDS_UPDATED)
|
||||
return;
|
||||
|
||||
flags |= DECO_SCHEM_CIDS_UPDATED;
|
||||
flags |= SCHEM_CIDS_UPDATED;
|
||||
|
||||
for (int i = 0; i != size.X * size.Y * size.Z; i++)
|
||||
schematic[i].setContent(c_nodes[schematic[i].getContent()]);
|
||||
schemdata[i].setContent(c_nodes[schemdata[i].getContent()]);
|
||||
}
|
||||
|
||||
|
||||
void DecoSchematic::generate(Mapgen *mg, PseudoRandom *pr, s16 max_y, v3s16 p)
|
||||
{
|
||||
ManualMapVoxelManipulator *vm = mg->vm;
|
||||
|
||||
if (flags & DECO_PLACE_CENTER_X)
|
||||
p.X -= (size.X + 1) / 2;
|
||||
if (flags & DECO_PLACE_CENTER_Y)
|
||||
p.Y -= (size.Y + 1) / 2;
|
||||
if (flags & DECO_PLACE_CENTER_Z)
|
||||
p.Z -= (size.Z + 1) / 2;
|
||||
|
||||
u32 vi = vm->m_area.index(p);
|
||||
content_t c = vm->m_data[vi].getContent();
|
||||
if (!CONTAINS(c_place_on, c))
|
||||
return;
|
||||
|
||||
Rotation rot = (rotation == ROTATE_RAND) ?
|
||||
(Rotation)pr->range(ROTATE_0, ROTATE_270) : rotation;
|
||||
|
||||
blitToVManip(p, vm, rot, false);
|
||||
}
|
||||
|
||||
|
||||
int DecoSchematic::getHeight() {
|
||||
return size.Y;
|
||||
}
|
||||
|
||||
|
||||
std::string DecoSchematic::getName() {
|
||||
return filename;
|
||||
}
|
||||
|
||||
|
||||
void DecoSchematic::blitToVManip(v3s16 p, ManualMapVoxelManipulator *vm,
|
||||
Rotation rot, bool force_placement)
|
||||
void Schematic::blitToVManip(v3s16 p, ManualMapVoxelManipulator *vm,
|
||||
Rotation rot, bool force_placement, INodeDefManager *ndef)
|
||||
{
|
||||
int xstride = 1;
|
||||
int ystride = size.X;
|
||||
|
@ -150,10 +113,10 @@ void DecoSchematic::blitToVManip(v3s16 p, ManualMapVoxelManipulator *vm,
|
|||
if (!vm->m_area.contains(vi))
|
||||
continue;
|
||||
|
||||
if (schematic[i].getContent() == CONTENT_IGNORE)
|
||||
if (schemdata[i].getContent() == CONTENT_IGNORE)
|
||||
continue;
|
||||
|
||||
if (schematic[i].param1 == MTSCHEM_PROB_NEVER)
|
||||
if (schemdata[i].param1 == MTSCHEM_PROB_NEVER)
|
||||
continue;
|
||||
|
||||
if (!force_placement) {
|
||||
|
@ -162,11 +125,11 @@ void DecoSchematic::blitToVManip(v3s16 p, ManualMapVoxelManipulator *vm,
|
|||
continue;
|
||||
}
|
||||
|
||||
if (schematic[i].param1 != MTSCHEM_PROB_ALWAYS &&
|
||||
myrand_range(1, 255) > schematic[i].param1)
|
||||
if (schemdata[i].param1 != MTSCHEM_PROB_ALWAYS &&
|
||||
myrand_range(1, 255) > schemdata[i].param1)
|
||||
continue;
|
||||
|
||||
vm->m_data[vi] = schematic[i];
|
||||
vm->m_data[vi] = schemdata[i];
|
||||
vm->m_data[vi].param1 = 0;
|
||||
|
||||
if (rot)
|
||||
|
@ -178,13 +141,14 @@ void DecoSchematic::blitToVManip(v3s16 p, ManualMapVoxelManipulator *vm,
|
|||
}
|
||||
|
||||
|
||||
void DecoSchematic::placeStructure(Map *map, v3s16 p, bool force_placement)
|
||||
void Schematic::placeStructure(Map *map, v3s16 p, u32 flags,
|
||||
Rotation rot, bool force_placement, INodeDefManager *ndef)
|
||||
{
|
||||
assert(schematic != NULL);
|
||||
assert(schemdata != NULL);
|
||||
ManualMapVoxelManipulator *vm = new ManualMapVoxelManipulator(map);
|
||||
|
||||
Rotation rot = (rotation == ROTATE_RAND) ?
|
||||
(Rotation)myrand_range(ROTATE_0, ROTATE_270) : rotation;
|
||||
if (rot == ROTATE_RAND)
|
||||
rot = (Rotation)myrand_range(ROTATE_0, ROTATE_270);
|
||||
|
||||
v3s16 s = (rot == ROTATE_90 || rot == ROTATE_270) ?
|
||||
v3s16(size.Z, size.Y, size.X) : size;
|
||||
|
@ -200,7 +164,7 @@ void DecoSchematic::placeStructure(Map *map, v3s16 p, bool force_placement)
|
|||
v3s16 bp2 = getNodeBlockPos(p + s - v3s16(1,1,1));
|
||||
vm->initialEmerge(bp1, bp2);
|
||||
|
||||
blitToVManip(p, vm, rot, force_placement);
|
||||
blitToVManip(p, vm, rot, force_placement, ndef);
|
||||
|
||||
std::map<v3s16, MapBlock *> lighting_modified_blocks;
|
||||
std::map<v3s16, MapBlock *> modified_blocks;
|
||||
|
@ -221,13 +185,14 @@ void DecoSchematic::placeStructure(Map *map, v3s16 p, bool force_placement)
|
|||
}
|
||||
|
||||
|
||||
bool DecoSchematic::loadSchematicFile(NodeResolver *resolver,
|
||||
bool Schematic::loadSchematicFromFile(const char *filename,
|
||||
NodeResolver *resolver,
|
||||
std::map<std::string, std::string> &replace_names)
|
||||
{
|
||||
content_t cignore = CONTENT_IGNORE;
|
||||
bool have_cignore = false;
|
||||
|
||||
std::ifstream is(filename.c_str(), std::ios_base::binary);
|
||||
std::ifstream is(filename, std::ios_base::binary);
|
||||
|
||||
u32 signature = readU32(is);
|
||||
if (signature != MTSCHEM_FILE_SIGNATURE) {
|
||||
|
@ -247,13 +212,8 @@ bool DecoSchematic::loadSchematicFile(NodeResolver *resolver,
|
|||
|
||||
delete []slice_probs;
|
||||
slice_probs = new u8[size.Y];
|
||||
if (version >= 3) {
|
||||
for (int y = 0; y != size.Y; y++)
|
||||
slice_probs[y] = readU8(is);
|
||||
} else {
|
||||
for (int y = 0; y != size.Y; y++)
|
||||
slice_probs[y] = MTSCHEM_PROB_ALWAYS;
|
||||
}
|
||||
for (int y = 0; y != size.Y; y++)
|
||||
slice_probs[y] = (version >= 3) ? readU8(is) : MTSCHEM_PROB_ALWAYS;
|
||||
|
||||
int nodecount = size.X * size.Y * size.Z;
|
||||
|
||||
|
@ -268,7 +228,6 @@ bool DecoSchematic::loadSchematicFile(NodeResolver *resolver,
|
|||
}
|
||||
|
||||
std::map<std::string, std::string>::iterator it;
|
||||
|
||||
it = replace_names.find(name);
|
||||
if (it != replace_names.end())
|
||||
name = it->second;
|
||||
|
@ -276,17 +235,17 @@ bool DecoSchematic::loadSchematicFile(NodeResolver *resolver,
|
|||
resolver->addNodeList(name.c_str(), &c_nodes);
|
||||
}
|
||||
|
||||
delete []schematic;
|
||||
schematic = new MapNode[nodecount];
|
||||
MapNode::deSerializeBulk(is, SER_FMT_VER_HIGHEST_READ, schematic,
|
||||
delete []schemdata;
|
||||
schemdata = new MapNode[nodecount];
|
||||
MapNode::deSerializeBulk(is, SER_FMT_VER_HIGHEST_READ, schemdata,
|
||||
nodecount, 2, 2, true);
|
||||
|
||||
if (version == 1) { // fix up the probability values
|
||||
for (int i = 0; i != nodecount; i++) {
|
||||
if (schematic[i].param1 == 0)
|
||||
schematic[i].param1 = MTSCHEM_PROB_ALWAYS;
|
||||
if (have_cignore && schematic[i].getContent() == cignore)
|
||||
schematic[i].param1 = MTSCHEM_PROB_NEVER;
|
||||
if (schemdata[i].param1 == 0)
|
||||
schemdata[i].param1 = MTSCHEM_PROB_ALWAYS;
|
||||
if (have_cignore && schemdata[i].getContent() == cignore)
|
||||
schemdata[i].param1 = MTSCHEM_PROB_NEVER;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -324,7 +283,7 @@ bool DecoSchematic::loadSchematicFile(NodeResolver *resolver,
|
|||
2 - Fixed messy never/always place; 0 probability is now never, 0xFF is always
|
||||
3 - Added y-slice probabilities; this allows for variable height structures
|
||||
*/
|
||||
void DecoSchematic::saveSchematicFile(INodeDefManager *ndef)
|
||||
void Schematic::saveSchematicToFile(const char *filename, INodeDefManager *ndef)
|
||||
{
|
||||
std::ostringstream ss(std::ios_base::binary);
|
||||
|
||||
|
@ -337,7 +296,7 @@ void DecoSchematic::saveSchematicFile(INodeDefManager *ndef)
|
|||
|
||||
std::vector<content_t> usednodes;
|
||||
int nodecount = size.X * size.Y * size.Z;
|
||||
build_nnlist_and_update_ids(schematic, nodecount, &usednodes);
|
||||
build_nnlist_and_update_ids(schemdata, nodecount, &usednodes);
|
||||
|
||||
u16 numids = usednodes.size();
|
||||
writeU16(ss, numids); // name count
|
||||
|
@ -345,7 +304,7 @@ void DecoSchematic::saveSchematicFile(INodeDefManager *ndef)
|
|||
ss << serializeString(ndef->get(usednodes[i]).name); // node names
|
||||
|
||||
// compressed bulk node data
|
||||
MapNode::serializeBulk(ss, SER_FMT_VER_HIGHEST_WRITE, schematic,
|
||||
MapNode::serializeBulk(ss, SER_FMT_VER_HIGHEST_WRITE, schemdata,
|
||||
nodecount, 2, 2, true);
|
||||
|
||||
fs::safeWriteToFile(filename, ss.str());
|
||||
|
@ -377,7 +336,7 @@ void build_nnlist_and_update_ids(MapNode *nodes, u32 nodecount,
|
|||
}
|
||||
|
||||
|
||||
bool DecoSchematic::getSchematicFromMap(Map *map, v3s16 p1, v3s16 p2)
|
||||
bool Schematic::getSchematicFromMap(Map *map, v3s16 p1, v3s16 p2)
|
||||
{
|
||||
ManualMapVoxelManipulator *vm = new ManualMapVoxelManipulator(map);
|
||||
|
||||
|
@ -391,15 +350,15 @@ bool DecoSchematic::getSchematicFromMap(Map *map, v3s16 p1, v3s16 p2)
|
|||
for (s16 y = 0; y != size.Y; y++)
|
||||
slice_probs[y] = MTSCHEM_PROB_ALWAYS;
|
||||
|
||||
schematic = new MapNode[size.X * size.Y * size.Z];
|
||||
schemdata = new MapNode[size.X * size.Y * size.Z];
|
||||
|
||||
u32 i = 0;
|
||||
for (s16 z = p1.Z; z <= p2.Z; z++)
|
||||
for (s16 y = p1.Y; y <= p2.Y; y++) {
|
||||
u32 vi = vm->m_area.index(p1.X, y, z);
|
||||
for (s16 x = p1.X; x <= p2.X; x++, i++, vi++) {
|
||||
schematic[i] = vm->m_data[vi];
|
||||
schematic[i].param1 = MTSCHEM_PROB_ALWAYS;
|
||||
schemdata[i] = vm->m_data[vi];
|
||||
schemdata[i].param1 = MTSCHEM_PROB_ALWAYS;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -408,7 +367,7 @@ bool DecoSchematic::getSchematicFromMap(Map *map, v3s16 p1, v3s16 p2)
|
|||
}
|
||||
|
||||
|
||||
void DecoSchematic::applyProbabilities(v3s16 p0,
|
||||
void Schematic::applyProbabilities(v3s16 p0,
|
||||
std::vector<std::pair<v3s16, u8> > *plist,
|
||||
std::vector<std::pair<s16, u8> > *splist)
|
||||
{
|
||||
|
@ -417,11 +376,11 @@ void DecoSchematic::applyProbabilities(v3s16 p0,
|
|||
int index = p.Z * (size.Y * size.X) + p.Y * size.X + p.X;
|
||||
if (index < size.Z * size.Y * size.X) {
|
||||
u8 prob = (*plist)[i].second;
|
||||
schematic[index].param1 = prob;
|
||||
schemdata[index].param1 = prob;
|
||||
|
||||
// trim unnecessary node names from schematic
|
||||
if (prob == MTSCHEM_PROB_NEVER)
|
||||
schematic[index].setContent(CONTENT_AIR);
|
||||
schemdata[index].setContent(CONTENT_AIR);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -30,11 +30,8 @@ class ManualMapVoxelManipulator;
|
|||
class PseudoRandom;
|
||||
class NodeResolver;
|
||||
|
||||
/////////////////// Decoration flags
|
||||
#define DECO_PLACE_CENTER_X 1
|
||||
#define DECO_PLACE_CENTER_Y 2
|
||||
#define DECO_PLACE_CENTER_Z 4
|
||||
#define DECO_SCHEM_CIDS_UPDATED 8
|
||||
/////////////////// Schematic flags
|
||||
#define SCHEM_CIDS_UPDATED 0x08
|
||||
|
||||
|
||||
#define MTSCHEM_FILE_SIGNATURE 0x4d54534d // 'MTSM'
|
||||
|
@ -44,42 +41,50 @@ class NodeResolver;
|
|||
#define MTSCHEM_PROB_NEVER 0x00
|
||||
#define MTSCHEM_PROB_ALWAYS 0xFF
|
||||
|
||||
extern FlagDesc flagdesc_deco_schematic[];
|
||||
|
||||
class DecoSchematic : public Decoration {
|
||||
class Schematic : public GenElement {
|
||||
public:
|
||||
std::string filename;
|
||||
|
||||
std::vector<content_t> c_nodes;
|
||||
|
||||
u32 flags;
|
||||
Rotation rotation;
|
||||
v3s16 size;
|
||||
MapNode *schematic;
|
||||
MapNode *schemdata;
|
||||
u8 *slice_probs;
|
||||
|
||||
DecoSchematic();
|
||||
~DecoSchematic();
|
||||
Schematic();
|
||||
~Schematic();
|
||||
|
||||
void updateContentIds();
|
||||
virtual void generate(Mapgen *mg, PseudoRandom *pr, s16 max_y, v3s16 p);
|
||||
virtual int getHeight();
|
||||
virtual std::string getName();
|
||||
|
||||
void blitToVManip(v3s16 p, ManualMapVoxelManipulator *vm,
|
||||
Rotation rot, bool force_placement);
|
||||
Rotation rot, bool force_placement, INodeDefManager *ndef);
|
||||
|
||||
bool loadSchematicFile(NodeResolver *resolver,
|
||||
bool loadSchematicFromFile(const char *filename, NodeResolver *resolver,
|
||||
std::map<std::string, std::string> &replace_names);
|
||||
void saveSchematicFile(INodeDefManager *ndef);
|
||||
|
||||
void saveSchematicToFile(const char *filename, INodeDefManager *ndef);
|
||||
bool getSchematicFromMap(Map *map, v3s16 p1, v3s16 p2);
|
||||
void placeStructure(Map *map, v3s16 p, bool force_placement);
|
||||
|
||||
void placeStructure(Map *map, v3s16 p, u32 flags,
|
||||
Rotation rot, bool force_placement, INodeDefManager *nef);
|
||||
void applyProbabilities(v3s16 p0,
|
||||
std::vector<std::pair<v3s16, u8> > *plist,
|
||||
std::vector<std::pair<s16, u8> > *splist);
|
||||
};
|
||||
|
||||
class SchematicManager : public GenElementManager {
|
||||
public:
|
||||
static const char *ELEMENT_TITLE;
|
||||
static const size_t ELEMENT_LIMIT = 0x10000;
|
||||
|
||||
SchematicManager(IGameDef *gamedef) {}
|
||||
~SchematicManager() {}
|
||||
|
||||
Schematic *create(int type)
|
||||
{
|
||||
return new Schematic;
|
||||
}
|
||||
};
|
||||
|
||||
void build_nnlist_and_update_ids(MapNode *nodes, u32 nodecount,
|
||||
std::vector<content_t> *usednodes);
|
||||
|
||||
|
|
|
@ -215,7 +215,7 @@ float noise2d_gradient(float x, float y, int seed)
|
|||
}
|
||||
|
||||
|
||||
float noise3d_gradient(float x, float y, float z, int seed)
|
||||
float noise3d_gradient(float x, float y, float z, int seed, bool eased)
|
||||
{
|
||||
// Calculate the integer coordinates
|
||||
int x0 = myfloor(x);
|
||||
|
@ -235,10 +235,17 @@ float noise3d_gradient(float x, float y, float z, int seed)
|
|||
float v011 = noise3d(x0, y0 + 1, z0 + 1, seed);
|
||||
float v111 = noise3d(x0 + 1, y0 + 1, z0 + 1, seed);
|
||||
// Interpolate
|
||||
return triLinearInterpolationNoEase(
|
||||
v000, v100, v010, v110,
|
||||
v001, v101, v011, v111,
|
||||
xl, yl, zl);
|
||||
if (eased) {
|
||||
return triLinearInterpolation(
|
||||
v000, v100, v010, v110,
|
||||
v001, v101, v011, v111,
|
||||
xl, yl, zl);
|
||||
} else {
|
||||
return triLinearInterpolationNoEase(
|
||||
v000, v100, v010, v110,
|
||||
v001, v101, v011, v111,
|
||||
xl, yl, zl);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
@ -275,14 +282,14 @@ float noise2d_perlin_abs(float x, float y, int seed,
|
|||
|
||||
|
||||
float noise3d_perlin(float x, float y, float z, int seed,
|
||||
int octaves, float persistence)
|
||||
int octaves, float persistence, bool eased)
|
||||
{
|
||||
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, eased);
|
||||
f *= 2.0;
|
||||
g *= persistence;
|
||||
}
|
||||
|
@ -291,14 +298,14 @@ float noise3d_perlin(float x, float y, float z, int seed,
|
|||
|
||||
|
||||
float noise3d_perlin_abs(float x, float y, float z, int seed,
|
||||
int octaves, float persistence)
|
||||
int octaves, float persistence, bool eased)
|
||||
{
|
||||
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, eased));
|
||||
f *= 2.0;
|
||||
g *= persistence;
|
||||
}
|
||||
|
|
15
src/noise.h
15
src/noise.h
|
@ -73,11 +73,12 @@ struct NoiseParams {
|
|||
int seed;
|
||||
int octaves;
|
||||
float persist;
|
||||
bool eased;
|
||||
|
||||
NoiseParams() {}
|
||||
|
||||
NoiseParams(float offset_, float scale_, v3f spread_,
|
||||
int seed_, int octaves_, float persist_)
|
||||
int seed_, int octaves_, float persist_, bool eased_=false)
|
||||
{
|
||||
offset = offset_;
|
||||
scale = scale_;
|
||||
|
@ -85,6 +86,7 @@ struct NoiseParams {
|
|||
seed = seed_;
|
||||
octaves = octaves_;
|
||||
persist = persist_;
|
||||
eased = eased_;
|
||||
}
|
||||
};
|
||||
|
||||
|
@ -134,7 +136,7 @@ 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 noise3d_gradient(float x, float y, float z, int seed, bool eased=false);
|
||||
|
||||
float noise2d_perlin(float x, float y, int seed,
|
||||
int octaves, float persistence);
|
||||
|
@ -143,10 +145,10 @@ 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);
|
||||
int octaves, float persistence, bool eased=false);
|
||||
|
||||
float noise3d_perlin_abs(float x, float y, float z, int seed,
|
||||
int octaves, float persistence);
|
||||
int octaves, float persistence, bool eased=false);
|
||||
|
||||
inline float easeCurve(float t) {
|
||||
return t * t * t * (t * (6.f * t - 15.f) + 10.f);
|
||||
|
@ -182,5 +184,10 @@ float contour(float v);
|
|||
noise3d_perlin((float)(x) / (np)->spread.X, (float)(y) / (np)->spread.Y, \
|
||||
(float)(z) / (np)->spread.Z, (s) + (np)->seed, (np)->octaves, (np)->persist))
|
||||
|
||||
#define NoisePerlin3DEased(np, x, y, z, s) ((np)->offset + (np)->scale * \
|
||||
noise3d_perlin((float)(x) / (np)->spread.X, (float)(y) / (np)->spread.Y, \
|
||||
(float)(z) / (np)->spread.Z, (s) + (np)->seed, (np)->octaves, \
|
||||
(np)->persist, true))
|
||||
|
||||
#endif
|
||||
|
||||
|
|
|
@ -168,18 +168,19 @@ void Particle::step(float dtime)
|
|||
void Particle::updateLight()
|
||||
{
|
||||
u8 light = 0;
|
||||
try{
|
||||
v3s16 p = v3s16(
|
||||
floor(m_pos.X+0.5),
|
||||
floor(m_pos.Y+0.5),
|
||||
floor(m_pos.Z+0.5)
|
||||
);
|
||||
MapNode n = m_env->getClientMap().getNode(p);
|
||||
bool pos_ok;
|
||||
|
||||
v3s16 p = v3s16(
|
||||
floor(m_pos.X+0.5),
|
||||
floor(m_pos.Y+0.5),
|
||||
floor(m_pos.Z+0.5)
|
||||
);
|
||||
MapNode n = m_env->getClientMap().getNodeNoEx(p, &pos_ok);
|
||||
if (pos_ok)
|
||||
light = n.getLightBlend(m_env->getDayNightRatio(), m_gamedef->ndef());
|
||||
}
|
||||
catch(InvalidPositionException &e){
|
||||
else
|
||||
light = blend_light(m_env->getDayNightRatio(), LIGHT_SUN, 0);
|
||||
}
|
||||
|
||||
m_light = decode_light(light);
|
||||
}
|
||||
|
||||
|
|
|
@ -29,6 +29,11 @@ private:
|
|||
u32 m_selected_i;
|
||||
std::string m_message;
|
||||
public:
|
||||
bool hasMessage()
|
||||
{
|
||||
return m_message != "";
|
||||
}
|
||||
|
||||
std::string getMessage()
|
||||
{
|
||||
std::string s = m_message;
|
||||
|
|
|
@ -1000,6 +1000,7 @@ bool read_noiseparams_nc(lua_State *L, int index, NoiseParams *np)
|
|||
np->persist = getfloatfield_default(L, index, "persist", 0.0);
|
||||
np->seed = getintfield_default(L, index, "seed", 0);
|
||||
np->octaves = getintfield_default(L, index, "octaves", 0);
|
||||
np->eased = getboolfield_default(L, index, "eased", false);
|
||||
|
||||
lua_getfield(L, index, "spread");
|
||||
np->spread = read_v3f(L, -1);
|
||||
|
@ -1009,86 +1010,98 @@ bool read_noiseparams_nc(lua_State *L, int index, NoiseParams *np)
|
|||
}
|
||||
|
||||
/******************************************************************************/
|
||||
bool read_schematic(lua_State *L, int index, DecoSchematic *dschem, Server *server) {
|
||||
|
||||
bool get_schematic(lua_State *L, int index, Schematic *schem,
|
||||
INodeDefManager *ndef, std::map<std::string, std::string> &replace_names)
|
||||
{
|
||||
if (index < 0)
|
||||
index = lua_gettop(L) + 1 + index;
|
||||
|
||||
INodeDefManager *ndef = server->getNodeDefManager();
|
||||
|
||||
if (lua_istable(L, index)) {
|
||||
lua_getfield(L, index, "size");
|
||||
v3s16 size = read_v3s16(L, -1);
|
||||
lua_pop(L, 1);
|
||||
|
||||
int numnodes = size.X * size.Y * size.Z;
|
||||
MapNode *schemdata = new MapNode[numnodes];
|
||||
int i = 0;
|
||||
|
||||
// Get schematic data
|
||||
lua_getfield(L, index, "data");
|
||||
luaL_checktype(L, -1, LUA_TTABLE);
|
||||
|
||||
lua_pushnil(L);
|
||||
while (lua_next(L, -2)) {
|
||||
if (i < numnodes) {
|
||||
// same as readnode, except param1 default is MTSCHEM_PROB_CONST
|
||||
lua_getfield(L, -1, "name");
|
||||
const char *name = luaL_checkstring(L, -1);
|
||||
lua_pop(L, 1);
|
||||
|
||||
u8 param1;
|
||||
lua_getfield(L, -1, "param1");
|
||||
param1 = !lua_isnil(L, -1) ? lua_tonumber(L, -1) : MTSCHEM_PROB_ALWAYS;
|
||||
lua_pop(L, 1);
|
||||
|
||||
u8 param2;
|
||||
lua_getfield(L, -1, "param2");
|
||||
param2 = !lua_isnil(L, -1) ? lua_tonumber(L, -1) : 0;
|
||||
lua_pop(L, 1);
|
||||
|
||||
schemdata[i] = MapNode(ndef, name, param1, param2);
|
||||
}
|
||||
|
||||
i++;
|
||||
lua_pop(L, 1);
|
||||
}
|
||||
|
||||
if (i != numnodes) {
|
||||
errorstream << "read_schematic: incorrect number of "
|
||||
"nodes provided in raw schematic data (got " << i <<
|
||||
", expected " << numnodes << ")." << std::endl;
|
||||
return false;
|
||||
}
|
||||
|
||||
u8 *sliceprobs = new u8[size.Y];
|
||||
for (i = 0; i != size.Y; i++)
|
||||
sliceprobs[i] = MTSCHEM_PROB_ALWAYS;
|
||||
|
||||
// Get Y-slice probability values (if present)
|
||||
lua_getfield(L, index, "yslice_prob");
|
||||
if (lua_istable(L, -1)) {
|
||||
lua_pushnil(L);
|
||||
while (lua_next(L, -2)) {
|
||||
if (getintfield(L, -1, "ypos", i) && i >= 0 && i < size.Y) {
|
||||
sliceprobs[i] = getintfield_default(L, -1,
|
||||
"prob", MTSCHEM_PROB_ALWAYS);
|
||||
}
|
||||
lua_pop(L, 1);
|
||||
}
|
||||
}
|
||||
|
||||
dschem->size = size;
|
||||
dschem->schematic = schemdata;
|
||||
dschem->slice_probs = sliceprobs;
|
||||
|
||||
return read_schematic(L, index, schem, ndef, replace_names);
|
||||
} else if (lua_isstring(L, index)) {
|
||||
dschem->filename = std::string(lua_tostring(L, index));
|
||||
NodeResolver *resolver = ndef->getResolver();
|
||||
const char *filename = lua_tostring(L, index);
|
||||
return schem->loadSchematicFromFile(filename, resolver, replace_names);
|
||||
} else {
|
||||
errorstream << "read_schematic: missing schematic "
|
||||
"filename or raw schematic data" << std::endl;
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
bool read_schematic(lua_State *L, int index, Schematic *schem,
|
||||
INodeDefManager *ndef, std::map<std::string, std::string> &replace_names)
|
||||
{
|
||||
//// Get schematic size
|
||||
lua_getfield(L, index, "size");
|
||||
v3s16 size = read_v3s16(L, -1);
|
||||
lua_pop(L, 1);
|
||||
|
||||
//// Get schematic data
|
||||
lua_getfield(L, index, "data");
|
||||
luaL_checktype(L, -1, LUA_TTABLE);
|
||||
|
||||
int numnodes = size.X * size.Y * size.Z;
|
||||
MapNode *schemdata = new MapNode[numnodes];
|
||||
int i = 0;
|
||||
|
||||
lua_pushnil(L);
|
||||
while (lua_next(L, -2)) {
|
||||
if (i < numnodes) {
|
||||
// same as readnode, except param1 default is MTSCHEM_PROB_CONST
|
||||
lua_getfield(L, -1, "name");
|
||||
std::string name = luaL_checkstring(L, -1);
|
||||
lua_pop(L, 1);
|
||||
|
||||
u8 param1;
|
||||
lua_getfield(L, -1, "param1");
|
||||
param1 = !lua_isnil(L, -1) ? lua_tonumber(L, -1) : MTSCHEM_PROB_ALWAYS;
|
||||
lua_pop(L, 1);
|
||||
|
||||
u8 param2;
|
||||
lua_getfield(L, -1, "param2");
|
||||
param2 = !lua_isnil(L, -1) ? lua_tonumber(L, -1) : 0;
|
||||
lua_pop(L, 1);
|
||||
|
||||
std::map<std::string, std::string>::iterator it;
|
||||
it = replace_names.find(name);
|
||||
if (it != replace_names.end())
|
||||
name = it->second;
|
||||
|
||||
schemdata[i] = MapNode(ndef, name, param1, param2);
|
||||
}
|
||||
|
||||
i++;
|
||||
lua_pop(L, 1);
|
||||
}
|
||||
|
||||
if (i != numnodes) {
|
||||
errorstream << "read_schematic: incorrect number of "
|
||||
"nodes provided in raw schematic data (got " << i <<
|
||||
", expected " << numnodes << ")." << std::endl;
|
||||
return false;
|
||||
}
|
||||
|
||||
//// Get Y-slice probability values (if present)
|
||||
u8 *slice_probs = new u8[size.Y];
|
||||
for (i = 0; i != size.Y; i++)
|
||||
slice_probs[i] = MTSCHEM_PROB_ALWAYS;
|
||||
|
||||
lua_getfield(L, index, "yslice_prob");
|
||||
if (lua_istable(L, -1)) {
|
||||
lua_pushnil(L);
|
||||
while (lua_next(L, -2)) {
|
||||
if (getintfield(L, -1, "ypos", i) && i >= 0 && i < size.Y) {
|
||||
slice_probs[i] = getintfield_default(L, -1,
|
||||
"prob", MTSCHEM_PROB_ALWAYS);
|
||||
}
|
||||
lua_pop(L, 1);
|
||||
}
|
||||
}
|
||||
|
||||
schem->flags = 0;
|
||||
schem->size = size;
|
||||
schem->schemdata = schemdata;
|
||||
schem->slice_probs = slice_probs;
|
||||
return true;
|
||||
}
|
||||
|
||||
|
|
|
@ -59,7 +59,7 @@ struct DigParams;
|
|||
struct HitParams;
|
||||
struct EnumString;
|
||||
struct NoiseParams;
|
||||
class DecoSchematic;
|
||||
class Schematic;
|
||||
|
||||
|
||||
ContentFeatures read_content_features (lua_State *L, int index);
|
||||
|
@ -151,10 +151,14 @@ NoiseParams* read_noiseparams (lua_State *L, int index);
|
|||
|
||||
bool read_noiseparams_nc (lua_State *L, int index,
|
||||
NoiseParams *np);
|
||||
|
||||
bool get_schematic (lua_State *L, int index,
|
||||
Schematic *schem,
|
||||
INodeDefManager *ndef,
|
||||
std::map<std::string, std::string> &replace_names);
|
||||
bool read_schematic (lua_State *L, int index,
|
||||
DecoSchematic *dschem,
|
||||
Server *server);
|
||||
Schematic *dschem,
|
||||
INodeDefManager *ndef,
|
||||
std::map<std::string, std::string> &replace_names);
|
||||
|
||||
void luaentity_get (lua_State *L,u16 id);
|
||||
|
||||
|
|
|
@ -159,16 +159,15 @@ int ModApiEnvMod::l_get_node_or_nil(lua_State *L)
|
|||
// pos
|
||||
v3s16 pos = read_v3s16(L, 1);
|
||||
// Do it
|
||||
try{
|
||||
MapNode n = env->getMap().getNode(pos);
|
||||
bool pos_ok;
|
||||
MapNode n = env->getMap().getNodeNoEx(pos, &pos_ok);
|
||||
if (pos_ok) {
|
||||
// Return node
|
||||
pushnode(L, n, env->getGameDef()->ndef());
|
||||
return 1;
|
||||
} catch(InvalidPositionException &e)
|
||||
{
|
||||
} else {
|
||||
lua_pushnil(L);
|
||||
return 1;
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
|
||||
// get_node_light(pos, timeofday)
|
||||
|
@ -185,16 +184,16 @@ int ModApiEnvMod::l_get_node_light(lua_State *L)
|
|||
time_of_day = 24000.0 * lua_tonumber(L, 2);
|
||||
time_of_day %= 24000;
|
||||
u32 dnr = time_to_daynight_ratio(time_of_day, true);
|
||||
try{
|
||||
MapNode n = env->getMap().getNode(pos);
|
||||
|
||||
bool is_position_ok;
|
||||
MapNode n = env->getMap().getNodeNoEx(pos, &is_position_ok);
|
||||
if (is_position_ok) {
|
||||
INodeDefManager *ndef = env->getGameDef()->ndef();
|
||||
lua_pushinteger(L, n.getLightBlend(dnr, ndef));
|
||||
return 1;
|
||||
} catch(InvalidPositionException &e)
|
||||
{
|
||||
} else {
|
||||
lua_pushnil(L);
|
||||
return 1;
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
|
||||
// place_node(pos, node)
|
||||
|
|
|
@ -25,24 +25,24 @@ with this program; if not, write to the Free Software Foundation, Inc.,
|
|||
#include "util/serialize.h"
|
||||
#include "server.h"
|
||||
#include "environment.h"
|
||||
#include "mg_biome.h"
|
||||
#include "emerge.h"
|
||||
#include "mg_biome.h"
|
||||
#include "mg_ore.h"
|
||||
#include "mg_decoration.h"
|
||||
#include "mg_schematic.h"
|
||||
#include "mapgen_v7.h"
|
||||
#include "settings.h"
|
||||
#include "main.h"
|
||||
#include "log.h"
|
||||
|
||||
|
||||
struct EnumString ModApiMapgen::es_BiomeTerrainType[] =
|
||||
{
|
||||
{BIOME_TERRAIN_NORMAL, "normal"},
|
||||
{BIOME_TERRAIN_LIQUID, "liquid"},
|
||||
{BIOME_TERRAIN_NETHER, "nether"},
|
||||
{BIOME_TERRAIN_AETHER, "aether"},
|
||||
{BIOME_TERRAIN_FLAT, "flat"},
|
||||
{BIOME_TYPE_NORMAL, "normal"},
|
||||
{BIOME_TYPE_LIQUID, "liquid"},
|
||||
{BIOME_TYPE_NETHER, "nether"},
|
||||
{BIOME_TYPE_AETHER, "aether"},
|
||||
{BIOME_TYPE_FLAT, "flat"},
|
||||
{0, NULL},
|
||||
};
|
||||
|
||||
|
@ -85,7 +85,7 @@ struct EnumString ModApiMapgen::es_Rotation[] =
|
|||
|
||||
|
||||
static void read_schematic_replacements(lua_State *L,
|
||||
std::map<std::string, std::string> replace_names, int index)
|
||||
std::map<std::string, std::string> &replace_names, int index)
|
||||
{
|
||||
lua_pushnil(L);
|
||||
while (lua_next(L, index)) {
|
||||
|
@ -310,13 +310,13 @@ int ModApiMapgen::l_register_biome(lua_State *L)
|
|||
luaL_checktype(L, index, LUA_TTABLE);
|
||||
|
||||
NodeResolver *resolver = getServer(L)->getNodeDefManager()->getResolver();
|
||||
BiomeDefManager *bmgr = getServer(L)->getEmergeManager()->biomedef;
|
||||
BiomeManager *bmgr = getServer(L)->getEmergeManager()->biomemgr;
|
||||
|
||||
enum BiomeTerrainType terrain = (BiomeTerrainType)getenumfield(L, index,
|
||||
"terrain_type", es_BiomeTerrainType, BIOME_TERRAIN_NORMAL);
|
||||
Biome *b = bmgr->createBiome(terrain);
|
||||
enum BiomeType biometype = (BiomeType)getenumfield(L, index, "type",
|
||||
es_BiomeTerrainType, BIOME_TYPE_NORMAL);
|
||||
Biome *b = bmgr->create(biometype);
|
||||
|
||||
b->name = getstringfield_default(L, index, "name", "<no name>");
|
||||
b->name = getstringfield_default(L, index, "name", "");
|
||||
b->depth_top = getintfield_default(L, index, "depth_top", 1);
|
||||
b->depth_filler = getintfield_default(L, index, "depth_filler", 3);
|
||||
b->height_min = getintfield_default(L, index, "height_min", 0);
|
||||
|
@ -325,7 +325,8 @@ int ModApiMapgen::l_register_biome(lua_State *L)
|
|||
b->humidity_point = getfloatfield_default(L, index, "humidity_point", 0.);
|
||||
b->flags = 0; //reserved
|
||||
|
||||
if (!bmgr->addBiome(b)) {
|
||||
u32 id = bmgr->add(b);
|
||||
if (id == (u32)-1) {
|
||||
delete b;
|
||||
return 0;
|
||||
}
|
||||
|
@ -344,7 +345,8 @@ int ModApiMapgen::l_register_biome(lua_State *L)
|
|||
|
||||
verbosestream << "register_biome: " << b->name << std::endl;
|
||||
|
||||
return 0;
|
||||
lua_pushinteger(L, id);
|
||||
return 1;
|
||||
}
|
||||
|
||||
// register_decoration({lots of stuff})
|
||||
|
@ -353,20 +355,22 @@ int ModApiMapgen::l_register_decoration(lua_State *L)
|
|||
int index = 1;
|
||||
luaL_checktype(L, index, LUA_TTABLE);
|
||||
|
||||
EmergeManager *emerge = getServer(L)->getEmergeManager();
|
||||
BiomeDefManager *bdef = emerge->biomedef;
|
||||
NodeResolver *resolver = getServer(L)->getNodeDefManager()->getResolver();
|
||||
INodeDefManager *ndef = getServer(L)->getNodeDefManager();
|
||||
NodeResolver *resolver = getServer(L)->getNodeDefManager()->getResolver();
|
||||
DecorationManager *decomgr = getServer(L)->getEmergeManager()->decomgr;
|
||||
BiomeManager *biomemgr = getServer(L)->getEmergeManager()->biomemgr;
|
||||
|
||||
enum DecorationType decotype = (DecorationType)getenumfield(L, index,
|
||||
"deco_type", es_DecorationType, -1);
|
||||
|
||||
Decoration *deco = createDecoration(decotype);
|
||||
Decoration *deco = decomgr->create(decotype);
|
||||
if (!deco) {
|
||||
errorstream << "register_decoration: decoration placement type "
|
||||
<< decotype << " not implemented";
|
||||
return 0;
|
||||
}
|
||||
|
||||
deco->name = getstringfield_default(L, index, "name", "");
|
||||
deco->fill_ratio = getfloatfield_default(L, index, "fill_ratio", 0.02);
|
||||
deco->sidelen = getintfield_default(L, index, "sidelen", 8);
|
||||
if (deco->sidelen <= 0) {
|
||||
|
@ -391,9 +395,11 @@ int ModApiMapgen::l_register_decoration(lua_State *L)
|
|||
std::vector<const char *> biome_list;
|
||||
getstringlistfield(L, index, "biomes", biome_list);
|
||||
for (size_t i = 0; i != biome_list.size(); i++) {
|
||||
u8 biomeid = bdef->getBiomeIdByName(biome_list[i]);
|
||||
if (biomeid)
|
||||
deco->biomes.insert(biomeid);
|
||||
Biome *b = (Biome *)biomemgr->getByName(biome_list[i]);
|
||||
if (!b)
|
||||
continue;
|
||||
|
||||
deco->biomes.insert(b->id);
|
||||
}
|
||||
|
||||
//// Handle decoration type-specific parameters
|
||||
|
@ -403,7 +409,7 @@ int ModApiMapgen::l_register_decoration(lua_State *L)
|
|||
success = regDecoSimple(L, resolver, (DecoSimple *)deco);
|
||||
break;
|
||||
case DECO_SCHEMATIC:
|
||||
success = regDecoSchematic(L, resolver, (DecoSchematic *)deco);
|
||||
success = regDecoSchematic(L, ndef, (DecoSchematic *)deco);
|
||||
break;
|
||||
case DECO_LSYSTEM:
|
||||
break;
|
||||
|
@ -414,12 +420,14 @@ int ModApiMapgen::l_register_decoration(lua_State *L)
|
|||
return 0;
|
||||
}
|
||||
|
||||
emerge->decorations.push_back(deco);
|
||||
u32 id = decomgr->add(deco);
|
||||
if (id == (u32)-1) {
|
||||
delete deco;
|
||||
return 0;
|
||||
}
|
||||
|
||||
verbosestream << "register_decoration: decoration '" << deco->getName()
|
||||
<< "' registered" << std::endl;
|
||||
|
||||
return 0;
|
||||
lua_pushinteger(L, id);
|
||||
return 1;
|
||||
}
|
||||
|
||||
bool ModApiMapgen::regDecoSimple(lua_State *L,
|
||||
|
@ -461,8 +469,8 @@ bool ModApiMapgen::regDecoSimple(lua_State *L,
|
|||
return true;
|
||||
}
|
||||
|
||||
bool ModApiMapgen::regDecoSchematic(lua_State *L,
|
||||
NodeResolver *resolver, DecoSchematic *deco)
|
||||
bool ModApiMapgen::regDecoSchematic(lua_State *L, INodeDefManager *ndef,
|
||||
DecoSchematic *deco)
|
||||
{
|
||||
int index = 1;
|
||||
|
||||
|
@ -478,19 +486,16 @@ bool ModApiMapgen::regDecoSchematic(lua_State *L,
|
|||
read_schematic_replacements(L, replace_names, lua_gettop(L));
|
||||
lua_pop(L, 1);
|
||||
|
||||
Schematic *schem = new Schematic;
|
||||
lua_getfield(L, index, "schematic");
|
||||
if (!read_schematic(L, -1, deco, getServer(L))) {
|
||||
if (!get_schematic(L, -1, schem, ndef, replace_names)) {
|
||||
lua_pop(L, 1);
|
||||
delete schem;
|
||||
return false;
|
||||
}
|
||||
lua_pop(L, 1);
|
||||
|
||||
if (!deco->filename.empty() &&
|
||||
!deco->loadSchematicFile(resolver, replace_names)) {
|
||||
errorstream << "register_decoration: failed to load schematic"
|
||||
" file '" << deco->filename << "'" << std::endl;
|
||||
return false;
|
||||
}
|
||||
deco->schematic = schem;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
@ -501,25 +506,25 @@ int ModApiMapgen::l_register_ore(lua_State *L)
|
|||
int index = 1;
|
||||
luaL_checktype(L, index, LUA_TTABLE);
|
||||
|
||||
EmergeManager *emerge = getServer(L)->getEmergeManager();
|
||||
NodeResolver *resolver = getServer(L)->getNodeDefManager()->getResolver();
|
||||
OreManager *oremgr = getServer(L)->getEmergeManager()->oremgr;
|
||||
|
||||
enum OreType oretype = (OreType)getenumfield(L, index,
|
||||
"ore_type", es_OreType, ORE_SCATTER);
|
||||
Ore *ore = createOre(oretype);
|
||||
Ore *ore = oremgr->create(oretype);
|
||||
if (!ore) {
|
||||
errorstream << "register_ore: ore_type "
|
||||
<< oretype << " not implemented";
|
||||
errorstream << "register_ore: ore_type " << oretype << " not implemented";
|
||||
return 0;
|
||||
}
|
||||
|
||||
ore->name = getstringfield_default(L, index, "name", "");
|
||||
ore->ore_param2 = (u8)getintfield_default(L, index, "ore_param2", 0);
|
||||
ore->clust_scarcity = getintfield_default(L, index, "clust_scarcity", 1);
|
||||
ore->clust_num_ores = getintfield_default(L, index, "clust_num_ores", 1);
|
||||
ore->clust_size = getintfield_default(L, index, "clust_size", 0);
|
||||
ore->height_min = getintfield_default(L, index, "height_min", 0);
|
||||
ore->height_max = getintfield_default(L, index, "height_max", 0);
|
||||
ore->nthresh = getfloatfield_default(L, index, "noise_threshhold", 0.);
|
||||
ore->nthresh = getfloatfield_default(L, index, "noise_threshhold", 0);
|
||||
ore->noise = NULL;
|
||||
ore->flags = 0;
|
||||
|
||||
|
@ -536,6 +541,12 @@ int ModApiMapgen::l_register_ore(lua_State *L)
|
|||
ore->np = read_noiseparams(L, -1);
|
||||
lua_pop(L, 1);
|
||||
|
||||
u32 id = oremgr->add(ore);
|
||||
if (id == (u32)-1) {
|
||||
delete ore;
|
||||
return 0;
|
||||
}
|
||||
|
||||
std::vector<const char *> wherein_names;
|
||||
getstringlistfield(L, index, "wherein", wherein_names);
|
||||
for (size_t i = 0; i != wherein_names.size(); i++)
|
||||
|
@ -544,17 +555,14 @@ int ModApiMapgen::l_register_ore(lua_State *L)
|
|||
resolver->addNode(getstringfield_default(L, index, "ore", ""),
|
||||
"", CONTENT_AIR, &ore->c_ore);
|
||||
|
||||
emerge->ores.push_back(ore);
|
||||
|
||||
//verbosestream << "register_ore: ore '" << ore->ore_name
|
||||
// << "' registered" << std::endl;
|
||||
return 0;
|
||||
lua_pushinteger(L, id);
|
||||
return 1;
|
||||
}
|
||||
|
||||
// create_schematic(p1, p2, probability_list, filename)
|
||||
int ModApiMapgen::l_create_schematic(lua_State *L)
|
||||
{
|
||||
DecoSchematic dschem;
|
||||
Schematic schem;
|
||||
|
||||
Map *map = &(getEnv(L)->getMap());
|
||||
INodeDefManager *ndef = getServer(L)->getNodeDefManager();
|
||||
|
@ -594,20 +602,19 @@ int ModApiMapgen::l_create_schematic(lua_State *L)
|
|||
}
|
||||
}
|
||||
|
||||
const char *s = lua_tostring(L, 4);
|
||||
dschem.filename = std::string(s ? s : "");
|
||||
const char *filename = luaL_checkstring(L, 4);
|
||||
|
||||
if (!dschem.getSchematicFromMap(map, p1, p2)) {
|
||||
if (!schem.getSchematicFromMap(map, p1, p2)) {
|
||||
errorstream << "create_schematic: failed to get schematic "
|
||||
"from map" << std::endl;
|
||||
return 0;
|
||||
}
|
||||
|
||||
dschem.applyProbabilities(p1, &prob_list, &slice_prob_list);
|
||||
schem.applyProbabilities(p1, &prob_list, &slice_prob_list);
|
||||
|
||||
dschem.saveSchematicFile(ndef);
|
||||
schem.saveSchematicToFile(filename, ndef);
|
||||
actionstream << "create_schematic: saved schematic file '"
|
||||
<< dschem.filename << "'." << std::endl;
|
||||
<< filename << "'." << std::endl;
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
@ -615,38 +622,36 @@ int ModApiMapgen::l_create_schematic(lua_State *L)
|
|||
// place_schematic(p, schematic, rotation, replacement)
|
||||
int ModApiMapgen::l_place_schematic(lua_State *L)
|
||||
{
|
||||
DecoSchematic dschem;
|
||||
Schematic schem;
|
||||
|
||||
Map *map = &(getEnv(L)->getMap());
|
||||
NodeResolver *resolver = getServer(L)->getNodeDefManager()->getResolver();
|
||||
INodeDefManager *ndef = getServer(L)->getNodeDefManager();
|
||||
|
||||
//// Read position
|
||||
v3s16 p = read_v3s16(L, 1);
|
||||
if (!read_schematic(L, 2, &dschem, getServer(L)))
|
||||
return 0;
|
||||
|
||||
//// Read rotation
|
||||
int rot = ROTATE_0;
|
||||
if (lua_isstring(L, 3))
|
||||
string_to_enum(es_Rotation, rot, std::string(lua_tostring(L, 3)));
|
||||
|
||||
dschem.rotation = (Rotation)rot;
|
||||
|
||||
std::map<std::string, std::string> replace_names;
|
||||
if (lua_istable(L, 4))
|
||||
read_schematic_replacements(L, replace_names, 4);
|
||||
|
||||
//// Read force placement
|
||||
bool force_placement = true;
|
||||
if (lua_isboolean(L, 5))
|
||||
force_placement = lua_toboolean(L, 5);
|
||||
|
||||
if (!dschem.filename.empty()) {
|
||||
if (!dschem.loadSchematicFile(resolver, replace_names)) {
|
||||
errorstream << "place_schematic: failed to load schematic file '"
|
||||
<< dschem.filename << "'" << std::endl;
|
||||
return 0;
|
||||
}
|
||||
//// Read node replacements
|
||||
std::map<std::string, std::string> replace_names;
|
||||
if (lua_istable(L, 4))
|
||||
read_schematic_replacements(L, replace_names, 4);
|
||||
|
||||
//// Read schematic
|
||||
if (!get_schematic(L, 2, &schem, ndef, replace_names)) {
|
||||
errorstream << "place_schematic: failed to get schematic" << std::endl;
|
||||
return 0;
|
||||
}
|
||||
|
||||
dschem.placeStructure(map, p, force_placement);
|
||||
schem.placeStructure(map, p, 0, (Rotation)rot, force_placement, ndef);
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
|
|
@ -22,6 +22,7 @@ with this program; if not, write to the Free Software Foundation, Inc.,
|
|||
|
||||
#include "lua_api/l_base.h"
|
||||
|
||||
class INodeDefManager;
|
||||
class NodeResolver;
|
||||
class DecoSimple;
|
||||
class DecoSchematic;
|
||||
|
@ -60,7 +61,7 @@ private:
|
|||
static bool regDecoSimple(lua_State *L,
|
||||
NodeResolver *resolver, DecoSimple *deco);
|
||||
static bool regDecoSchematic(lua_State *L,
|
||||
NodeResolver *resolver, DecoSchematic *deco);
|
||||
INodeDefManager *ndef, DecoSchematic *deco);
|
||||
|
||||
static struct EnumString es_BiomeTerrainType[];
|
||||
static struct EnumString es_DecorationType[];
|
||||
|
|
|
@ -190,7 +190,7 @@ int LuaPerlinNoiseMap::l_get3dMap(lua_State *L)
|
|||
v3f p = read_v3f(L, 2);
|
||||
|
||||
Noise *n = o->noise;
|
||||
n->perlinMap3D(p.X, p.Y, p.Z);
|
||||
n->perlinMap3D(p.X, p.Y, p.Z, n->np->eased);
|
||||
|
||||
lua_newtable(L);
|
||||
for (int z = 0; z != n->sz; z++) {
|
||||
|
@ -216,7 +216,7 @@ int LuaPerlinNoiseMap::l_get3dMap_flat(lua_State *L)
|
|||
v3f p = read_v3f(L, 2);
|
||||
|
||||
Noise *n = o->noise;
|
||||
n->perlinMap3D(p.X, p.Y, p.Z);
|
||||
n->perlinMap3D(p.X, p.Y, p.Z, n->np->eased);
|
||||
|
||||
|
||||
int maplen = n->sx * n->sy * n->sz;
|
||||
|
|
|
@ -687,6 +687,7 @@ void Server::AsyncRunStep(bool initial_step)
|
|||
m_env->getGameTime(),
|
||||
m_lag,
|
||||
m_gamespec.id,
|
||||
m_emerge->params.mg_name,
|
||||
m_mods);
|
||||
counter = 0.01;
|
||||
}
|
||||
|
@ -2423,17 +2424,18 @@ void Server::ProcessData(u8 *data, u32 datasize, u16 peer_id)
|
|||
somebody is cheating, by checking the timing.
|
||||
*/
|
||||
MapNode n(CONTENT_IGNORE);
|
||||
try
|
||||
{
|
||||
n = m_env->getMap().getNode(p_under);
|
||||
}
|
||||
catch(InvalidPositionException &e)
|
||||
{
|
||||
bool pos_ok;
|
||||
n = m_env->getMap().getNodeNoEx(p_under, &pos_ok);
|
||||
if (pos_ok)
|
||||
n = m_env->getMap().getNodeNoEx(p_under, &pos_ok);
|
||||
|
||||
if (!pos_ok) {
|
||||
infostream<<"Server: Not punching: Node not found."
|
||||
<<" Adding block to emerge queue."
|
||||
<<std::endl;
|
||||
m_emerge->enqueueBlockEmerge(peer_id, getNodeBlockPos(p_above), false);
|
||||
}
|
||||
|
||||
if(n.getContent() != CONTENT_IGNORE)
|
||||
m_script->node_on_punch(p_under, n, playersao, pointed);
|
||||
// Cheat prevention
|
||||
|
@ -2478,16 +2480,12 @@ void Server::ProcessData(u8 *data, u32 datasize, u16 peer_id)
|
|||
// Only digging of nodes
|
||||
if(pointed.type == POINTEDTHING_NODE)
|
||||
{
|
||||
MapNode n(CONTENT_IGNORE);
|
||||
try
|
||||
{
|
||||
n = m_env->getMap().getNode(p_under);
|
||||
}
|
||||
catch(InvalidPositionException &e)
|
||||
{
|
||||
infostream<<"Server: Not finishing digging: Node not found."
|
||||
<<" Adding block to emerge queue."
|
||||
<<std::endl;
|
||||
bool pos_ok;
|
||||
MapNode n = m_env->getMap().getNodeNoEx(p_under, &pos_ok);
|
||||
if (!pos_ok) {
|
||||
infostream << "Server: Not finishing digging: Node not found."
|
||||
<< " Adding block to emerge queue."
|
||||
<< std::endl;
|
||||
m_emerge->enqueueBlockEmerge(peer_id, getNodeBlockPos(p_above), false);
|
||||
}
|
||||
|
||||
|
|
|
@ -194,6 +194,7 @@ void sendAnnounce(const std::string &action,
|
|||
const u32 game_time,
|
||||
const float lag,
|
||||
const std::string &gameid,
|
||||
const std::string &mg_name,
|
||||
const std::vector<ModSpec> &mods)
|
||||
{
|
||||
Json::Value server;
|
||||
|
@ -227,7 +228,7 @@ void sendAnnounce(const std::string &action,
|
|||
if (action == "start") {
|
||||
server["dedicated"] = g_settings->getBool("server_dedicated");
|
||||
server["rollback"] = g_settings->getBool("enable_rollback_recording");
|
||||
server["mapgen"] = g_settings->get("mg_name");
|
||||
server["mapgen"] = mg_name;
|
||||
server["privs"] = g_settings->get("default_privs");
|
||||
server["can_see_far_names"] = g_settings->getS16("player_transfer_distance") <= 0;
|
||||
server["mods"] = Json::Value(Json::arrayValue);
|
||||
|
|
|
@ -42,6 +42,7 @@ namespace ServerList
|
|||
const std::vector<std::string> &clients_names = std::vector<std::string>(),
|
||||
const double uptime = 0, const u32 game_time = 0,
|
||||
const float lag = 0, const std::string &gameid = "",
|
||||
const std::string &mg_name = "",
|
||||
const std::vector<ModSpec> &mods = std::vector<ModSpec>());
|
||||
#endif
|
||||
} // ServerList namespace
|
||||
|
|
|
@ -17,12 +17,15 @@ with this program; if not, write to the Free Software Foundation, Inc.,
|
|||
51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
*/
|
||||
|
||||
#include "main.h"
|
||||
#include "settings.h"
|
||||
#include "wieldmesh.h"
|
||||
#include "inventory.h"
|
||||
#include "gamedef.h"
|
||||
#include "itemdef.h"
|
||||
#include "nodedef.h"
|
||||
#include "mesh.h"
|
||||
#include "mapblock_mesh.h"
|
||||
#include "tile.h"
|
||||
#include "log.h"
|
||||
#include "util/numeric.h"
|
||||
|
@ -107,17 +110,6 @@ static scene::IMesh* createExtrusionMesh(int resolution_x, int resolution_y)
|
|||
buf->append(vertices, 8, indices, 12);
|
||||
}
|
||||
|
||||
// Define default material
|
||||
video::SMaterial *material = &buf->getMaterial();
|
||||
material->MaterialType = video::EMT_TRANSPARENT_ALPHA_CHANNEL_REF;
|
||||
material->BackfaceCulling = true;
|
||||
material->setFlag(video::EMF_LIGHTING, false);
|
||||
material->setFlag(video::EMF_BILINEAR_FILTER, false);
|
||||
material->setFlag(video::EMF_TRILINEAR_FILTER, false);
|
||||
// anisotropic filtering removes "thin black line" artifacts
|
||||
material->setFlag(video::EMF_ANISOTROPIC_FILTER, true);
|
||||
material->setFlag(video::EMF_TEXTURE_WRAP, false);
|
||||
|
||||
// Create mesh object
|
||||
scene::SMesh *mesh = new scene::SMesh();
|
||||
mesh->addMeshBuffer(buf);
|
||||
|
@ -209,9 +201,14 @@ WieldMeshSceneNode::WieldMeshSceneNode(
|
|||
):
|
||||
scene::ISceneNode(parent, mgr, id),
|
||||
m_meshnode(NULL),
|
||||
m_material_type(video::EMT_TRANSPARENT_ALPHA_CHANNEL_REF),
|
||||
m_lighting(lighting),
|
||||
m_bounding_box(0.0, 0.0, 0.0, 0.0, 0.0, 0.0)
|
||||
{
|
||||
m_enable_shaders = g_settings->getBool("enable_shaders");
|
||||
m_bilinear_filter = g_settings->getBool("bilinear_filter");
|
||||
m_trilinear_filter = g_settings->getBool("trilinear_filter");
|
||||
|
||||
// If this is the first wield mesh scene node, create a cache
|
||||
// for extrusion meshes (and a cube mesh), otherwise reuse it
|
||||
if (g_extrusion_mesh_cache == NULL)
|
||||
|
@ -251,7 +248,12 @@ void WieldMeshSceneNode::setCube(const TileSpec tiles[6],
|
|||
for (u32 i = 0; i < m_meshnode->getMaterialCount(); ++i) {
|
||||
assert(i < 6);
|
||||
video::SMaterial &material = m_meshnode->getMaterial(i);
|
||||
material.setTexture(0, tiles[i].texture);
|
||||
if (tiles[i].animation_frame_count == 1) {
|
||||
material.setTexture(0, tiles[i].texture);
|
||||
} else {
|
||||
FrameSpec animation_frame = tiles[i].frames.find(0)->second;
|
||||
material.setTexture(0, animation_frame.texture);
|
||||
}
|
||||
tiles[i].applyMaterialOptions(material);
|
||||
}
|
||||
}
|
||||
|
@ -264,37 +266,55 @@ void WieldMeshSceneNode::setExtruded(const std::string &imagename,
|
|||
changeToMesh(NULL);
|
||||
return;
|
||||
}
|
||||
|
||||
scene::IMesh *mesh = g_extrusion_mesh_cache->create(texture->getSize());
|
||||
core::dimension2d<u32> dim = texture->getSize();
|
||||
scene::IMesh *mesh = g_extrusion_mesh_cache->create(dim);
|
||||
changeToMesh(mesh);
|
||||
mesh->drop();
|
||||
|
||||
m_meshnode->setScale(wield_scale * WIELD_SCALE_FACTOR_EXTRUDED);
|
||||
|
||||
// Customize material
|
||||
assert(m_meshnode->getMaterialCount() == 1);
|
||||
video::SMaterial &material = m_meshnode->getMaterial(0);
|
||||
material.setTexture(0, texture);
|
||||
material.MaterialType = m_material_type;
|
||||
material.setFlag(video::EMF_BACK_FACE_CULLING, true);
|
||||
// Enable filtering only for high resolution texures
|
||||
if (dim.Width > 32) {
|
||||
material.setFlag(video::EMF_BILINEAR_FILTER, m_bilinear_filter);
|
||||
material.setFlag(video::EMF_TRILINEAR_FILTER, m_trilinear_filter);
|
||||
} else {
|
||||
material.setFlag(video::EMF_BILINEAR_FILTER, false);
|
||||
material.setFlag(video::EMF_TRILINEAR_FILTER, false);
|
||||
}
|
||||
// anisotropic filtering removes "thin black line" artifacts
|
||||
material.setFlag(video::EMF_ANISOTROPIC_FILTER, true);
|
||||
if (m_enable_shaders)
|
||||
material.setTexture(2, tsrc->getTexture("disable_img.png"));
|
||||
}
|
||||
|
||||
void WieldMeshSceneNode::setItem(const ItemStack &item, IGameDef *gamedef)
|
||||
{
|
||||
ITextureSource *tsrc = gamedef->getTextureSource();
|
||||
IItemDefManager *idef = gamedef->getItemDefManager();
|
||||
|
||||
IShaderSource *shdrsrc = gamedef->getShaderSource();
|
||||
INodeDefManager *ndef = gamedef->getNodeDefManager();
|
||||
const ItemDefinition &def = item.getDefinition(idef);
|
||||
const ContentFeatures &f = ndef->get(def.name);
|
||||
content_t id = ndef->getId(def.name);
|
||||
|
||||
if (m_enable_shaders) {
|
||||
u32 shader_id = shdrsrc->getShader("nodes_shader", TILE_MATERIAL_BASIC, NDT_NORMAL);
|
||||
m_material_type = shdrsrc->getShaderInfo(shader_id).material;
|
||||
}
|
||||
|
||||
// If wield_image is defined, it overrides everything else
|
||||
if (def.wield_image != "") {
|
||||
setExtruded(def.wield_image, def.wield_scale, tsrc);
|
||||
return;
|
||||
}
|
||||
|
||||
// Handle nodes
|
||||
// See also CItemDefManager::createClientCached()
|
||||
if (def.type == ITEM_NODE) {
|
||||
INodeDefManager *ndef = gamedef->getNodeDefManager();
|
||||
const ContentFeatures &f = ndef->get(def.name);
|
||||
else if (def.type == ITEM_NODE) {
|
||||
if (f.mesh_ptr[0]) {
|
||||
// e.g. mesh nodes and nodeboxes
|
||||
changeToMesh(f.mesh_ptr[0]);
|
||||
|
@ -302,33 +322,54 @@ void WieldMeshSceneNode::setItem(const ItemStack &item, IGameDef *gamedef)
|
|||
m_meshnode->setScale(
|
||||
def.wield_scale * WIELD_SCALE_FACTOR
|
||||
/ (BS * f.visual_scale));
|
||||
// Customize materials
|
||||
for (u32 i = 0; i < m_meshnode->getMaterialCount(); ++i) {
|
||||
assert(i < 6);
|
||||
video::SMaterial &material = m_meshnode->getMaterial(i);
|
||||
material.setTexture(0, f.tiles[i].texture);
|
||||
f.tiles[i].applyMaterialOptions(material);
|
||||
}
|
||||
return;
|
||||
} else if (f.drawtype == NDT_NORMAL || f.drawtype == NDT_ALLFACES) {
|
||||
setCube(f.tiles, def.wield_scale, tsrc);
|
||||
return;
|
||||
} else if (f.drawtype == NDT_AIRLIKE) {
|
||||
changeToMesh(NULL);
|
||||
return;
|
||||
} else if (f.drawtype == NDT_PLANTLIKE) {
|
||||
setExtruded(tsrc->getTextureName(f.tiles[0].texture_id), def.wield_scale, tsrc);
|
||||
} else if (f.drawtype == NDT_NORMAL || f.drawtype == NDT_ALLFACES) {
|
||||
setCube(f.tiles, def.wield_scale, tsrc);
|
||||
} else {
|
||||
MeshMakeData mesh_make_data(gamedef);
|
||||
MapNode mesh_make_node(id, 255, 0);
|
||||
mesh_make_data.fillSingleNode(&mesh_make_node);
|
||||
MapBlockMesh mapblock_mesh(&mesh_make_data, v3s16(0, 0, 0));
|
||||
changeToMesh(mapblock_mesh.getMesh());
|
||||
translateMesh(m_meshnode->getMesh(), v3f(-BS, -BS, -BS));
|
||||
m_meshnode->setScale(
|
||||
def.wield_scale * WIELD_SCALE_FACTOR
|
||||
/ (BS * f.visual_scale));
|
||||
}
|
||||
|
||||
// If none of the above standard cases worked, use the wield mesh from ClientCached
|
||||
scene::IMesh *mesh = idef->getWieldMesh(item.name, gamedef);
|
||||
if (mesh) {
|
||||
changeToMesh(mesh);
|
||||
m_meshnode->setScale(def.wield_scale * WIELD_SCALE_FACTOR);
|
||||
return;
|
||||
for (u32 i = 0; i < m_meshnode->getMaterialCount(); ++i) {
|
||||
assert(i < 6);
|
||||
video::SMaterial &material = m_meshnode->getMaterial(i);
|
||||
material.setFlag(video::EMF_BACK_FACE_CULLING, true);
|
||||
material.setFlag(video::EMF_BILINEAR_FILTER, m_bilinear_filter);
|
||||
material.setFlag(video::EMF_TRILINEAR_FILTER, m_trilinear_filter);
|
||||
bool animated = (f.tiles[i].animation_frame_count > 1);
|
||||
if (animated) {
|
||||
FrameSpec animation_frame = f.tiles[i].frames.find(0)->second;
|
||||
material.setTexture(0, animation_frame.texture);
|
||||
} else {
|
||||
material.setTexture(0, f.tiles[i].texture);
|
||||
}
|
||||
material.MaterialType = m_material_type;
|
||||
if (m_enable_shaders) {
|
||||
if (f.tiles[i].normal_texture) {
|
||||
if (animated) {
|
||||
FrameSpec animation_frame = f.tiles[i].frames.find(0)->second;
|
||||
material.setTexture(1, animation_frame.normal_texture);
|
||||
} else {
|
||||
material.setTexture(1, f.tiles[i].normal_texture);
|
||||
}
|
||||
material.setTexture(2, tsrc->getTexture("enable_img.png"));
|
||||
} else {
|
||||
material.setTexture(2, tsrc->getTexture("disable_img.png"));
|
||||
}
|
||||
}
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
// default to inventory_image
|
||||
if (def.inventory_image != "") {
|
||||
else if (def.inventory_image != "") {
|
||||
setExtruded(def.inventory_image, def.wield_scale, tsrc);
|
||||
return;
|
||||
}
|
||||
|
@ -376,5 +417,4 @@ void WieldMeshSceneNode::changeToMesh(scene::IMesh *mesh)
|
|||
// need to normalize normals when lighting is enabled (because of setScale())
|
||||
m_meshnode->setMaterialFlag(video::EMF_NORMALIZE_NORMALS, m_lighting);
|
||||
m_meshnode->setVisible(true);
|
||||
|
||||
}
|
||||
|
|
|
@ -58,10 +58,15 @@ private:
|
|||
|
||||
// Child scene node with the current wield mesh
|
||||
scene::IMeshSceneNode *m_meshnode;
|
||||
video::E_MATERIAL_TYPE m_material_type;
|
||||
|
||||
// True if EMF_LIGHTING should be enabled.
|
||||
bool m_lighting;
|
||||
|
||||
bool m_enable_shaders;
|
||||
bool m_bilinear_filter;
|
||||
bool m_trilinear_filter;
|
||||
|
||||
// Bounding box culling is disabled for this type of scene node,
|
||||
// so this variable is just required so we can implement
|
||||
// getBoundingBox() and is set to an empty box.
|
||||
|
|
Loading…
Reference in New Issue