Merge Minetest commits

This commit is contained in:
Maksim Gamarnik 2016-02-11 22:35:23 +02:00
commit ae66c6a782
61 changed files with 561 additions and 356 deletions

View File

@ -848,14 +848,25 @@ core.register_chatcommand("kick", {
})
core.register_chatcommand("clearobjects", {
params = "[full|quick]",
description = "clear all objects in world",
privs = {server=true},
func = function(name, param)
core.log("action", name .. " clears all objects.")
options = {}
if param == "" or param == "full" then
options.mode = "full"
elseif param == "quick" then
options.mode = "quick"
else
return false, "Invalid usage, see /help clearobjects."
end
core.log("action", name .. " clears all objects ("
.. options.mode .. " mode).")
core.chat_send_all("Clearing all objects. This may take long."
.. " You may experience a timeout. (by "
.. name .. ")")
core.clear_objects()
core.clear_objects(options)
core.log("action", "Object clearing done.")
core.chat_send_all("*** Cleared all objects.")
end,

View File

@ -88,25 +88,26 @@ function core.dir_to_facedir(dir, is6d)
end
end
function core.facedir_to_dir(facedir)
--a table of possible dirs
return ({{x=0, y=0, z=1},
{x=1, y=0, z=0},
{x=0, y=0, z=-1},
{x=-1, y=0, z=0},
{x=0, y=-1, z=0},
{x=0, y=1, z=0}})
--indexed into by a table of correlating facedirs
[({[0]=1, 2, 3, 4,
-- Table of possible dirs
local facedir_to_dir = {
{x= 0, y=0, z= 1},
{x= 1, y=0, z= 0},
{x= 0, y=0, z=-1},
{x=-1, y=0, z= 0},
{x= 0, y=-1, z= 0},
{x= 0, y=1, z= 0},
}
-- Mapping from facedir value to index in facedir_to_dir.
local facedir_to_dir_map = {
[0]=1, 2, 3, 4,
5, 2, 6, 4,
6, 2, 5, 4,
1, 5, 3, 6,
1, 6, 3, 5,
1, 4, 3, 2})
--indexed into by the facedir in question
[facedir]]
1, 4, 3, 2,
}
function core.facedir_to_dir(facedir)
return facedir_to_dir[facedir_to_dir_map[facedir]]
end
function core.dir_to_wallmounted(dir)
@ -131,17 +132,17 @@ function core.dir_to_wallmounted(dir)
end
end
function core.wallmounted_to_dir(wallmounted)
-- table of dirs in wallmounted order
return ({[0] = {x = 0, y = 1, z = 0},
-- table of dirs in wallmounted order
local wallmounted_to_dir = {
[0] = {x = 0, y = 1, z = 0},
{x = 0, y = -1, z = 0},
{x = 1, y = 0, z = 0},
{x = -1, y = 0, z = 0},
{x = 0, y = 0, z = 1},
{x = 0, y = 0, z = -1}})
--indexed into by the wallmounted in question
[wallmounted]
{x = 0, y = 0, z = -1},
}
function core.wallmounted_to_dir(wallmounted)
return wallmounted_to_dir[wallmounted]
end
function core.get_node_drops(nodename, toolname)

View File

@ -326,6 +326,11 @@ fsaa (FSAA) enum 0 0,1,2,4,8,16
# Thy only work with the OpenGL video backend.
enable_shaders (Shaders) bool true
[****Tone Mapping]
# Enables filmic tone mapping
tone_mapping (Filmic tone mapping) bool false
[****Bumpmapping]
# Enables bumpmapping for textures. Normalmaps need to be supplied by the texture pack
@ -697,12 +702,6 @@ enable_pvp (Player versus Player) bool true
# If this is set, players will always (re)spawn at the given position.
static_spawnpoint (Static spawnpoint) string
# Maximum distance above water level for player spawn.
# Larger values result in spawn points closer to (x = 0, z = 0).
# Smaller values may result in a suitable spawn point not being found,
# resulting in a spawn at (0, 0, 0) possibly buried underground.
vertical_spawn_range (Vertical spawn range) int 16
# If enabled, new players cannot join with an empty password.
disallow_empty_password (Disallow empty passwords) bool false

View File

@ -20,6 +20,38 @@ bool normalTexturePresent = false;
const float e = 2.718281828459;
const float BS = 10.0;
#ifdef ENABLE_TONE_MAPPING
/* Hable's UC2 Tone mapping parameters
A = 0.22;
B = 0.30;
C = 0.10;
D = 0.20;
E = 0.01;
F = 0.30;
W = 11.2;
equation used: ((x * (A * x + C * B) + D * E) / (x * (A * x + B) + D * F)) - E / F
*/
vec3 uncharted2Tonemap(vec3 x)
{
return ((x * (0.22 * x + 0.03) + 0.002) / (x * (0.22 * x + 0.3) + 0.06)) - 0.03334;
}
vec4 applyToneMapping(vec4 color)
{
color = vec4(pow(color.rgb, vec3(2.2)), color.a);
const float gamma = 1.6;
const float exposureBias = 5.5;
color.rgb = uncharted2Tonemap(exposureBias * color.rgb);
// Precalculated white_scale from
//vec3 whiteScale = 1.0 / uncharted2Tonemap(vec3(W));
vec3 whiteScale = vec3(1.036015346);
color.rgb *= whiteScale;
return vec4(pow(color.rgb, vec3(1.0 / gamma)), color.a);
}
#endif
void get_texture_flags()
{
vec4 flags = texture2D(textureFlags, vec2(0.0, 0.0));
@ -160,22 +192,26 @@ void main(void)
color = base.rgb;
#endif
vec4 col = vec4(color.rgb * gl_Color.rgb, 1.0);
#if MATERIAL_TYPE == TILE_MATERIAL_LIQUID_TRANSPARENT || MATERIAL_TYPE == TILE_MATERIAL_LIQUID_OPAQUE
float alpha = gl_Color.a;
vec4 col = vec4(color.rgb, alpha);
col *= gl_Color;
if (fogDistance != 0.0) {
float d = max(0.0, min(vPosition.z / fogDistance * 1.5 - 0.6, 1.0));
alpha = mix(alpha, 0.0, d);
}
gl_FragColor = vec4(col.rgb, alpha);
col = vec4(col.rgb, alpha);
#else
vec4 col = vec4(color.rgb, base.a);
col *= gl_Color;
if (fogDistance != 0.0) {
float d = max(0.0, min(vPosition.z / fogDistance * 1.5 - 0.6, 1.0));
col = mix(col, skyBgColor, d);
}
gl_FragColor = vec4(col.rgb, base.a);
col = vec4(col.rgb, base.a);
#endif
#ifdef ENABLE_TONE_MAPPING
gl_FragColor = applyToneMapping(col);
#else
gl_FragColor = col;
#endif
}

View File

@ -22,6 +22,38 @@ bool texSeamless = false;
const float e = 2.718281828459;
const float BS = 10.0;
#ifdef ENABLE_TONE_MAPPING
/* Hable's UC2 Tone mapping parameters
A = 0.22;
B = 0.30;
C = 0.10;
D = 0.20;
E = 0.01;
F = 0.30;
W = 11.2;
equation used: ((x * (A * x + C * B) + D * E) / (x * (A * x + B) + D * F)) - E / F
*/
vec3 uncharted2Tonemap(vec3 x)
{
return ((x * (0.22 * x + 0.03) + 0.002) / (x * (0.22 * x + 0.3) + 0.06)) - 0.03334;
}
vec4 applyToneMapping(vec4 color)
{
color = vec4(pow(color.rgb, vec3(2.2)), color.a);
const float gamma = 1.6;
const float exposureBias = 5.5;
color.rgb = uncharted2Tonemap(exposureBias * color.rgb);
// Precalculated white_scale from
//vec3 whiteScale = 1.0 / uncharted2Tonemap(vec3(W));
vec3 whiteScale = vec3(1.036015346);
color.rgb *= whiteScale;
return vec4(pow(color.rgb, vec3(1.0 / gamma)), color.a);
}
#endif
void get_texture_flags()
{
vec4 flags = texture2D(textureFlags, vec2(0.0, 0.0));
@ -116,22 +148,26 @@ vec4 base = texture2D(baseTexture, uv).rgba;
color = base.rgb;
#endif
vec4 col = vec4(color.rgb * gl_Color.rgb, 1.0);
#if MATERIAL_TYPE == TILE_MATERIAL_LIQUID_TRANSPARENT || MATERIAL_TYPE == TILE_MATERIAL_LIQUID_OPAQUE
float alpha = gl_Color.a;
vec4 col = vec4(color.rgb, alpha);
col *= gl_Color;
if(fogDistance != 0.0){
if (fogDistance != 0.0) {
float d = max(0.0, min(vPosition.z / fogDistance * 1.5 - 0.6, 1.0));
alpha = mix(alpha, 0.0, d);
}
gl_FragColor = vec4(col.rgb, alpha);
col = vec4(col.rgb, alpha);
#else
vec4 col = vec4(color.rgb, base.a);
col *= gl_Color;
if(fogDistance != 0.0){
if (fogDistance != 0.0) {
float d = max(0.0, min(vPosition.z / fogDistance * 1.5 - 0.6, 1.0));
col = mix(col, skyBgColor, d);
}
gl_FragColor = vec4(col.rgb, base.a);
col = vec4(col.rgb, base.a);
#endif
#ifdef ENABLE_TONE_MAPPING
gl_FragColor = applyToneMapping(col);
#else
gl_FragColor = col;
#endif
}

View File

@ -2046,8 +2046,12 @@ and `minetest.auth_reload` call the authetification handler.
* `minetest.generate_decorations(vm, pos1, pos2)`
* Generate all registered decorations within the VoxelManip `vm` and in the area from `pos1` to `pos2`.
* `pos1` and `pos2` are optional and default to mapchunk minp and maxp.
* `minetest.clear_objects()`
* clear all objects in the environments
* `minetest.clear_objects([options])`
* Clear all objects in the environment
* Takes an optional table as an argument with the field `mode`.
* mode = `"full"`: Load and go through every mapblock, clearing objects (default).
* mode = `"quick"`: Clear objects immediately in loaded mapblocks;
clear objects in unloaded mapblocks only when the mapblocks are next activated.
* `minetest.emerge_area(pos1, pos2, [callback], [param])`
* Queue all blocks in the area from `pos1` to `pos2`, inclusive, to be asynchronously
* fetched from memory, loaded from disk, or if inexistent, generates them.
@ -2149,6 +2153,8 @@ and `minetest.auth_reload` call the authetification handler.
* Convert a facedir back into a vector aimed directly out the "back" of a node
* `minetest.dir_to_wallmounted(dir)`
* Convert a vector to a wallmounted value, used for `paramtype2="wallmounted"`
* `minetest.wallmounted_to_dir(wallmounted)`
* Convert a wallmounted value back into a vector aimed directly out the "back" of a node
* `minetest.get_node_drops(nodename, toolname)`
* Returns list of item names.
* **Note**: This will be removed or modified in a future version.

View File

@ -353,6 +353,12 @@
# type: bool
# enable_shaders = true
##### Tone mapping
# Enables filmic tone mapping.
# Requires shaders to be enabled.
# type: bool
# tone_mapping = false
##### Bumpmapping
# Enables bumpmapping for textures. Normalmaps need to be supplied by the texture pack
@ -833,13 +839,6 @@
# type: string
# static_spawnpoint =
# Maximum distance above water level for player spawn.
# Larger values result in spawn points closer to (x = 0, z = 0).
# Smaller values may result in a suitable spawn point not being found,
# resulting in a spawn at (0, 0, 0) possibly buried underground.
# type: int
# vertical_spawn_range = 16
# If enabled, new players cannot join with an empty password.
# type: bool
# disallow_empty_password = false

View File

@ -1471,13 +1471,13 @@ ClientActiveObject * Client::getSelectedActiveObject(
{
ClientActiveObject *obj = objects[i].obj;
core::aabbox3d<f32> *selection_box = obj->getSelectionBox();
aabb3f *selection_box = obj->getSelectionBox();
if(selection_box == NULL)
continue;
v3f pos = obj->getPosition();
core::aabbox3d<f32> offsetted_box(
aabb3f offsetted_box(
selection_box->MinEdge + pos,
selection_box->MaxEdge + pos
);

View File

@ -21,7 +21,6 @@ with this program; if not, write to the Free Software Foundation, Inc.,
#define TILE_HEADER
#include "irrlichttypes.h"
#include "irr_v2d.h"
#include "irr_v3d.h"
#include <ITexture.h>
#include <IrrlichtDevice.h>

View File

@ -50,7 +50,7 @@ ClientMap::ClientMap(
m_camera_direction(0,0,1),
m_camera_fov(M_PI)
{
m_box = core::aabbox3d<f32>(-BS*1000000,-BS*1000000,-BS*1000000,
m_box = aabb3f(-BS*1000000,-BS*1000000,-BS*1000000,
BS*1000000,BS*1000000,BS*1000000);
/* TODO: Add a callback function so these can be updated when a setting
@ -157,12 +157,9 @@ void ClientMap::updateDrawList(video::IVideoDriver* driver)
}
m_drawlist.clear();
m_camera_mutex.lock();
v3f camera_position = m_camera_position;
v3f camera_direction = m_camera_direction;
f32 camera_fov = m_camera_fov;
//v3s16 camera_offset = m_camera_offset;
m_camera_mutex.unlock();
// Use a higher fov to accomodate faster camera movements.
// Blocks are cropped better when they are drawn.
@ -433,11 +430,9 @@ void ClientMap::renderMap(video::IVideoDriver* driver, s32 pass)
int crack = m_client->getCrackLevel();
u32 daynight_ratio = m_client->getEnv().getDayNightRatio();
m_camera_mutex.lock();
v3f camera_position = m_camera_position;
v3f camera_direction = m_camera_direction;
f32 camera_fov = m_camera_fov;
m_camera_mutex.unlock();
/*
Get all blocks and draw all visible ones
@ -799,11 +794,7 @@ void ClientMap::renderPostFx(CameraMode cam_mode)
// Sadly ISceneManager has no "post effects" render pass, in that case we
// could just register for that and handle it in renderMap().
m_camera_mutex.lock();
v3f camera_position = m_camera_position;
m_camera_mutex.unlock();
MapNode n = getNodeNoEx(floatToInt(camera_position, BS));
MapNode n = getNodeNoEx(floatToInt(m_camera_position, BS));
// - If the player is in a solid node, make everything black.
// - If the player is in liquid, draw a semi-transparent overlay.

View File

@ -89,7 +89,6 @@ public:
void updateCamera(v3f pos, v3f dir, f32 fov, v3s16 offset)
{
MutexAutoLock lock(m_camera_mutex);
m_camera_position = pos;
m_camera_direction = dir;
m_camera_fov = fov;
@ -116,7 +115,7 @@ public:
renderMap(driver, SceneManager->getSceneNodeRenderPass());
}
virtual const core::aabbox3d<f32>& getBoundingBox() const
virtual const aabb3f &getBoundingBox() const
{
return m_box;
}
@ -141,7 +140,7 @@ public:
private:
Client *m_client;
core::aabbox3d<f32> m_box;
aabb3f m_box;
MapDrawControl &m_control;
@ -149,7 +148,6 @@ private:
v3f m_camera_direction;
f32 m_camera_fov;
v3s16 m_camera_offset;
Mutex m_camera_mutex;
std::map<v3s16, MapBlock*> m_drawlist;

View File

@ -56,7 +56,7 @@ public:
virtual void updateLight(u8 light_at_pos){}
virtual void updateLightNoCheck(u8 light_at_pos){}
virtual v3s16 getLightPosition(){return v3s16(0,0,0);}
virtual core::aabbox3d<f32>* getSelectionBox(){return NULL;}
virtual aabb3f *getSelectionBox() { return NULL; }
virtual bool getCollisionBox(aabb3f *toset){return false;}
virtual bool collideWithObjects(){return false;}
virtual v3f getPosition(){return v3f(0,0,0);}

View File

@ -62,7 +62,7 @@ Clouds::Clouds(
g_settings->registerChangedCallback("enable_3d_clouds",
&cloud_3d_setting_changed, this);
m_box = core::aabbox3d<f32>(-BS*1000000,m_cloud_y-BS,-BS*1000000,
m_box = aabb3f(-BS*1000000,m_cloud_y-BS,-BS*1000000,
BS*1000000,m_cloud_y+BS,BS*1000000);
}

View File

@ -53,7 +53,7 @@ public:
virtual void render();
virtual const core::aabbox3d<f32>& getBoundingBox() const
virtual const aabb3f &getBoundingBox() const
{
return m_box;
}
@ -79,7 +79,7 @@ public:
void updateCameraOffset(v3s16 camera_offset)
{
m_camera_offset = camera_offset;
m_box = core::aabbox3d<f32>(-BS * 1000000, m_cloud_y - BS - BS * camera_offset.Y, -BS * 1000000,
m_box = aabb3f(-BS * 1000000, m_cloud_y - BS - BS * camera_offset.Y, -BS * 1000000,
BS * 1000000, m_cloud_y + BS - BS * camera_offset.Y, BS * 1000000);
}
@ -87,7 +87,7 @@ public:
private:
video::SMaterial m_material;
core::aabbox3d<f32> m_box;
aabb3f m_box;
s16 m_passed_cloud_y;
float m_cloud_y;
u16 m_cloud_radius_i;

View File

@ -309,7 +309,7 @@ public:
void initialize(const std::string &data);
core::aabbox3d<f32>* getSelectionBox()
aabb3f *getSelectionBox()
{return &m_selection_box;}
v3f getPosition()
{return m_position;}
@ -319,7 +319,7 @@ public:
bool getCollisionBox(aabb3f *toset) { return false; }
private:
core::aabbox3d<f32> m_selection_box;
aabb3f m_selection_box;
scene::IMeshSceneNode *m_node;
v3f m_position;
std::string m_itemstring;
@ -674,7 +674,7 @@ GenericCAO::~GenericCAO()
removeFromScene(true);
}
core::aabbox3d<f32>* GenericCAO::getSelectionBox()
aabb3f *GenericCAO::getSelectionBox()
{
if(!m_prop.is_visible || !m_is_visible || m_is_local_player || getParent() != NULL)
return NULL;
@ -1185,7 +1185,7 @@ void GenericCAO::step(float dtime, ClientEnvironment *env)
if(m_prop.physical)
{
core::aabbox3d<f32> box = m_prop.collisionbox;
aabb3f box = m_prop.collisionbox;
box.MinEdge *= BS;
box.MaxEdge *= BS;
collisionMoveResult moveresult;

View File

@ -65,7 +65,7 @@ private:
//
scene::ISceneManager *m_smgr;
IrrlichtDevice *m_irr;
core::aabbox3d<f32> m_selection_box;
aabb3f m_selection_box;
scene::IMeshSceneNode *m_meshnode;
scene::IAnimatedMeshSceneNode *m_animated_meshnode;
WieldMeshSceneNode *m_wield_meshnode;
@ -127,7 +127,7 @@ public:
bool collideWithObjects();
core::aabbox3d<f32>* getSelectionBox();
aabb3f *getSelectionBox();
v3f getPosition();

View File

@ -259,7 +259,7 @@ void LuaEntitySAO::step(float dtime, bool send_recommended)
else
{
if(m_prop.physical){
core::aabbox3d<f32> box = m_prop.collisionbox;
aabb3f box = m_prop.collisionbox;
box.MinEdge *= BS;
box.MaxEdge *= BS;
collisionMoveResult moveresult;
@ -786,7 +786,7 @@ PlayerSAO::PlayerSAO(ServerEnvironment *env_, Player *player_, u16 peer_id_,
m_prop.hp_max = PLAYER_MAX_HP;
m_prop.physical = false;
m_prop.weight = 75;
m_prop.collisionbox = core::aabbox3d<f32>(-1/3.,-1.0,-1/3., 1/3.,1.0,1/3.);
m_prop.collisionbox = aabb3f(-1/3.,-1.0,-1/3., 1/3.,1.0,1/3.);
// start of default appearance, this should be overwritten by LUA
m_prop.visual = "upright_sprite";
m_prop.visual_size = v2f(1, 2);

View File

@ -159,6 +159,7 @@ void set_default_settings(Settings *settings)
settings->setDefault("texture_clean_transparent", "false");
settings->setDefault("texture_min_size", "32");
settings->setDefault("preload_item_visuals", "false");
settings->setDefault("tone_mapping", "false");
settings->setDefault("enable_bumpmapping", "false");
settings->setDefault("enable_parallax_occlusion", "false");
settings->setDefault("generate_normalmaps", "false");
@ -246,7 +247,6 @@ void set_default_settings(Settings *settings)
settings->setDefault("default_privs", "interact, shout");
settings->setDefault("player_transfer_distance", "0");
settings->setDefault("enable_pvp", "true");
settings->setDefault("vertical_spawn_range", "128");
settings->setDefault("disallow_empty_password", "false");
settings->setDefault("disable_anticheat", "false");
settings->setDefault("enable_rollback_recording", "false");

View File

@ -334,6 +334,18 @@ v3s16 EmergeManager::getContainingChunk(v3s16 blockpos, s16 chunksize)
}
int EmergeManager::getSpawnLevelAtPoint(v2s16 p)
{
if (m_mapgens.size() == 0 || !m_mapgens[0]) {
errorstream << "EmergeManager: getSpawnLevelAtPoint() called"
" before mapgen init" << std::endl;
return 0;
}
return m_mapgens[0]->getSpawnLevelAtPoint(p);
}
int EmergeManager::getGroundLevelAtPoint(v2s16 p)
{
if (m_mapgens.size() == 0 || !m_mapgens[0]) {

View File

@ -136,6 +136,7 @@ public:
// Mapgen helpers methods
Biome *getBiomeAtPoint(v3s16 p);
int getSpawnLevelAtPoint(v2s16 p);
int getGroundLevelAtPoint(v2s16 p);
bool isBlockUnderground(v3s16 blockpos);

View File

@ -354,6 +354,7 @@ ServerEnvironment::ServerEnvironment(ServerMap *map,
m_active_block_interval_overload_skip(0),
m_game_time(0),
m_game_time_fraction_counter(0),
m_last_clear_objects_time(0),
m_recommended_send_interval(0.1),
m_max_lag_estimate(0.1)
{
@ -503,6 +504,7 @@ void ServerEnvironment::saveMeta()
Settings args;
args.setU64("game_time", m_game_time);
args.setU64("time_of_day", getTimeOfDay());
args.setU64("last_clear_objects_time", m_last_clear_objects_time);
args.writeLines(ss);
ss<<"EnvArgsEnd\n";
@ -546,6 +548,13 @@ void ServerEnvironment::loadMeta()
// This is not as important
setTimeOfDay(9000);
}
try {
m_last_clear_objects_time = args.getU64("last_clear_objects_time");
} catch (SettingNotFoundException &e) {
// If missing, do as if clearObjects was never called
m_last_clear_objects_time = 0;
}
}
struct ActiveABM
@ -739,13 +748,19 @@ void ServerEnvironment::activateBlock(MapBlock *block, u32 additional_dtime)
// Get time difference
u32 dtime_s = 0;
u32 stamp = block->getTimestamp();
if(m_game_time > stamp && stamp != BLOCK_TIMESTAMP_UNDEFINED)
dtime_s = m_game_time - block->getTimestamp();
if (m_game_time > stamp && stamp != BLOCK_TIMESTAMP_UNDEFINED)
dtime_s = m_game_time - stamp;
dtime_s += additional_dtime;
/*infostream<<"ServerEnvironment::activateBlock(): block timestamp: "
<<stamp<<", game time: "<<m_game_time<<std::endl;*/
// Remove stored static objects if clearObjects was called since block's timestamp
if (stamp == BLOCK_TIMESTAMP_UNDEFINED || stamp < m_last_clear_objects_time) {
block->m_static_objects.m_stored.clear();
// do not set changed flag to avoid unnecessary mapblock writes
}
// Set current time as timestamp
block->setTimestampNoChangedFlag(m_game_time);
@ -858,22 +873,22 @@ void ServerEnvironment::getObjectsInsideRadius(std::vector<u16> &objects, v3f po
}
}
void ServerEnvironment::clearAllObjects()
void ServerEnvironment::clearObjects(ClearObjectsMode mode)
{
infostream<<"ServerEnvironment::clearAllObjects(): "
<<"Removing all active objects"<<std::endl;
infostream << "ServerEnvironment::clearObjects(): "
<< "Removing all active objects" << std::endl;
std::vector<u16> objects_to_remove;
for(std::map<u16, ServerActiveObject*>::iterator
for (std::map<u16, ServerActiveObject*>::iterator
i = m_active_objects.begin();
i != m_active_objects.end(); ++i) {
ServerActiveObject* obj = i->second;
if(obj->getType() == ACTIVEOBJECT_TYPE_PLAYER)
if (obj->getType() == ACTIVEOBJECT_TYPE_PLAYER)
continue;
u16 id = i->first;
// Delete static object if block is loaded
if(obj->m_static_exists){
if (obj->m_static_exists) {
MapBlock *block = m_map->getBlockNoCreateNoEx(obj->m_static_block);
if(block){
if (block) {
block->m_static_objects.remove(id);
block->raiseModified(MOD_STATE_WRITE_NEEDED,
MOD_REASON_CLEAR_ALL_OBJECTS);
@ -881,7 +896,7 @@ void ServerEnvironment::clearAllObjects()
}
}
// If known by some client, don't delete immediately
if(obj->m_known_by_count > 0){
if (obj->m_known_by_count > 0) {
obj->m_pending_deactivation = true;
obj->m_removed = true;
continue;
@ -893,39 +908,46 @@ void ServerEnvironment::clearAllObjects()
m_script->removeObjectReference(obj);
// Delete active object
if(obj->environmentDeletes())
if (obj->environmentDeletes())
delete obj;
// Id to be removed from m_active_objects
objects_to_remove.push_back(id);
}
// Remove references from m_active_objects
for(std::vector<u16>::iterator i = objects_to_remove.begin();
for (std::vector<u16>::iterator i = objects_to_remove.begin();
i != objects_to_remove.end(); ++i) {
m_active_objects.erase(*i);
}
// Get list of loaded blocks
std::vector<v3s16> loaded_blocks;
infostream<<"ServerEnvironment::clearAllObjects(): "
<<"Listing all loaded blocks"<<std::endl;
infostream << "ServerEnvironment::clearObjects(): "
<< "Listing all loaded blocks" << std::endl;
m_map->listAllLoadedBlocks(loaded_blocks);
infostream<<"ServerEnvironment::clearAllObjects(): "
<<"Done listing all loaded blocks: "
<<loaded_blocks.size()<<std::endl;
infostream << "ServerEnvironment::clearObjects(): "
<< "Done listing all loaded blocks: "
<< loaded_blocks.size()<<std::endl;
// Get list of loadable blocks
std::vector<v3s16> loadable_blocks;
infostream<<"ServerEnvironment::clearAllObjects(): "
<<"Listing all loadable blocks"<<std::endl;
if (mode == CLEAR_OBJECTS_MODE_FULL) {
infostream << "ServerEnvironment::clearObjects(): "
<< "Listing all loadable blocks" << std::endl;
m_map->listAllLoadableBlocks(loadable_blocks);
infostream<<"ServerEnvironment::clearAllObjects(): "
<<"Done listing all loadable blocks: "
<<loadable_blocks.size()
<<", now clearing"<<std::endl;
infostream << "ServerEnvironment::clearObjects(): "
<< "Done listing all loadable blocks: "
<< loadable_blocks.size() << std::endl;
} else {
loadable_blocks = loaded_blocks;
}
infostream << "ServerEnvironment::clearObjects(): "
<< "Now clearing objects in " << loadable_blocks.size()
<< " blocks" << std::endl;
// Grab a reference on each loaded block to avoid unloading it
for(std::vector<v3s16>::iterator i = loaded_blocks.begin();
for (std::vector<v3s16>::iterator i = loaded_blocks.begin();
i != loaded_blocks.end(); ++i) {
v3s16 p = *i;
MapBlock *block = m_map->getBlockNoCreateNoEx(p);
@ -934,24 +956,27 @@ void ServerEnvironment::clearAllObjects()
}
// Remove objects in all loadable blocks
u32 unload_interval = g_settings->getS32("max_clearobjects_extra_loaded_blocks");
u32 unload_interval = U32_MAX;
if (mode == CLEAR_OBJECTS_MODE_FULL) {
unload_interval = g_settings->getS32("max_clearobjects_extra_loaded_blocks");
unload_interval = MYMAX(unload_interval, 1);
}
u32 report_interval = loadable_blocks.size() / 10;
u32 num_blocks_checked = 0;
u32 num_blocks_cleared = 0;
u32 num_objs_cleared = 0;
for(std::vector<v3s16>::iterator i = loadable_blocks.begin();
for (std::vector<v3s16>::iterator i = loadable_blocks.begin();
i != loadable_blocks.end(); ++i) {
v3s16 p = *i;
MapBlock *block = m_map->emergeBlock(p, false);
if(!block){
errorstream<<"ServerEnvironment::clearAllObjects(): "
<<"Failed to emerge block "<<PP(p)<<std::endl;
if (!block) {
errorstream << "ServerEnvironment::clearObjects(): "
<< "Failed to emerge block " << PP(p) << std::endl;
continue;
}
u32 num_stored = block->m_static_objects.m_stored.size();
u32 num_active = block->m_static_objects.m_active.size();
if(num_stored != 0 || num_active != 0){
if (num_stored != 0 || num_active != 0) {
block->m_static_objects.m_stored.clear();
block->m_static_objects.m_active.clear();
block->raiseModified(MOD_STATE_WRITE_NEEDED,
@ -961,23 +986,23 @@ void ServerEnvironment::clearAllObjects()
}
num_blocks_checked++;
if(report_interval != 0 &&
num_blocks_checked % report_interval == 0){
if (report_interval != 0 &&
num_blocks_checked % report_interval == 0) {
float percent = 100.0 * (float)num_blocks_checked /
loadable_blocks.size();
infostream<<"ServerEnvironment::clearAllObjects(): "
<<"Cleared "<<num_objs_cleared<<" objects"
<<" in "<<num_blocks_cleared<<" blocks ("
<<percent<<"%)"<<std::endl;
infostream << "ServerEnvironment::clearObjects(): "
<< "Cleared " << num_objs_cleared << " objects"
<< " in " << num_blocks_cleared << " blocks ("
<< percent << "%)" << std::endl;
}
if(num_blocks_checked % unload_interval == 0){
if (num_blocks_checked % unload_interval == 0) {
m_map->unloadUnreferencedBlocks();
}
}
m_map->unloadUnreferencedBlocks();
// Drop references that were added above
for(std::vector<v3s16>::iterator i = loaded_blocks.begin();
for (std::vector<v3s16>::iterator i = loaded_blocks.begin();
i != loaded_blocks.end(); ++i) {
v3s16 p = *i;
MapBlock *block = m_map->getBlockNoCreateNoEx(p);
@ -985,9 +1010,11 @@ void ServerEnvironment::clearAllObjects()
block->refDrop();
}
infostream<<"ServerEnvironment::clearAllObjects(): "
<<"Finished: Cleared "<<num_objs_cleared<<" objects"
<<" in "<<num_blocks_cleared<<" blocks"<<std::endl;
m_last_clear_objects_time = m_game_time;
infostream << "ServerEnvironment::clearObjects(): "
<< "Finished: Cleared " << num_objs_cleared << " objects"
<< " in " << num_blocks_cleared << " blocks" << std::endl;
}
void ServerEnvironment::step(float dtime)

View File

@ -203,6 +203,18 @@ public:
private:
};
/*
Operation mode for ServerEnvironment::clearObjects()
*/
enum ClearObjectsMode {
// Load and go through every mapblock, clearing objects
CLEAR_OBJECTS_MODE_FULL,
// Clear objects immediately in loaded mapblocks;
// clear objects in unloaded mapblocks only when the mapblocks are next activated.
CLEAR_OBJECTS_MODE_QUICK,
};
/*
The server-side environment.
@ -319,8 +331,8 @@ public:
// Find all active objects inside a radius around a point
void getObjectsInsideRadius(std::vector<u16> &objects, v3f pos, float radius);
// Clear all objects, loading and going through every MapBlock
void clearAllObjects();
// Clear objects, loading and going through every MapBlock
void clearObjects(ClearObjectsMode mode);
// This makes stuff happen
void step(f32 dtime);
@ -410,6 +422,10 @@ private:
u32 m_game_time;
// A helper variable for incrementing the latter
float m_game_time_fraction_counter;
// Time of last clearObjects call (game time).
// When a mapblock older than this is loaded, its objects are cleared.
u32 m_last_clear_objects_time;
// Active block modifiers
std::vector<ABMWithState> m_abms;
// An interval for generally sending object positions and stuff
float m_recommended_send_interval;

View File

@ -1497,7 +1497,7 @@ void GUIFormSpecMenu::parseItemImageButton(parserData* data,std::string element)
258 + m_fields.size()
);
gui::IGUIButton *e = Environment->addButton(rect, this, spec.fid, spec.flabel.c_str());
gui::IGUIButton *e = Environment->addButton(rect, this, spec.fid, L"");
if (spec.fname == data->focused_fieldname) {
Environment->setFocus(e);
@ -1515,6 +1515,12 @@ void GUIFormSpecMenu::parseItemImageButton(parserData* data,std::string element)
pos.X += stof(v_pos[0]) * (float) spacing.X;
pos.Y += stof(v_pos[1]) * (float) spacing.Y;
m_itemimages.push_back(ImageDrawSpec("", item_name, pos, geom));
StaticTextSpec label_spec(
utf8_to_wide(label),
rect
);
m_static_texts.push_back(label_spec);
return;
}
errorstream<< "Invalid ItemImagebutton element(" << parts.size() << "): '" << element << "'" << std::endl;
@ -1883,6 +1889,7 @@ void GUIFormSpecMenu::regenerateGui(v2u32 screensize)
m_boxes.clear();
m_tooltips.clear();
m_inventory_rings.clear();
m_static_texts.clear();
// Set default values (fits old formspec values)
m_bgcolor = video::SColor(140,0,0,0);
@ -2462,6 +2469,15 @@ void GUIFormSpecMenu::drawMenu()
m_pointer = m_device->getCursorControl()->getPosition();
#endif
/*
Draw static text elements
*/
for (u32 i = 0; i < m_static_texts.size(); i++) {
const StaticTextSpec &spec = m_static_texts[i];
video::SColor color(255, 255, 255, 255);
m_font->draw(spec.text.c_str(), spec.rect, color, true, true, &spec.rect);
}
/*
Draw fields/buttons tooltips
*/

View File

@ -228,6 +228,20 @@ class GUIFormSpecMenu : public GUIModalMenu
irr::video::SColor color;
};
struct StaticTextSpec {
StaticTextSpec()
{
}
StaticTextSpec(const std::wstring &a_text,
const core::rect<s32> &a_rect):
text(a_text),
rect(a_rect)
{
}
std::wstring text;
core::rect<s32> rect;
};
public:
GUIFormSpecMenu(irr::IrrlichtDevice* dev,
gui::IGUIElement* parent, s32 id,
@ -339,6 +353,7 @@ protected:
std::vector<ImageDrawSpec> m_itemimages;
std::vector<BoxDrawSpec> m_boxes;
std::vector<FieldSpec> m_fields;
std::vector<StaticTextSpec> m_static_texts;
std::vector<std::pair<FieldSpec,GUITable*> > m_tables;
std::vector<std::pair<FieldSpec,gui::IGUICheckBox*> > m_checkboxes;
std::map<std::string, TooltipSpec> m_tooltips;

View File

@ -84,6 +84,8 @@ Hud::Hud(video::IVideoDriver *driver, scene::ISceneManager* smgr,
m_selection_mesh = NULL;
m_selection_boxes.clear();
m_halo_boxes.clear();
m_selection_pos = v3f(0.0, 0.0, 0.0);
std::string mode = g_settings->get("node_highlighting");
m_selection_material.Lighting = false;
@ -574,10 +576,23 @@ void Hud::updateSelectionMesh(const v3s16 &camera_offset)
0,0,1,1
};
m_selection_mesh = convertNodeboxesToMesh(m_selection_boxes, texture_uv);
// Use single halo box instead of multiple overlapping boxes.
// Temporary solution - problem can be solved with multiple
// rendering targets, or some method to remove inner surfaces.
// Thats because of halo transparency.
// scale final halo mesh
scaleMesh(m_selection_mesh, v3f(1.08, 1.08, 1.08));
aabb3f halo_box(100.0, 100.0, 100.0, -100.0, -100.0, -100.0);
m_halo_boxes.clear();
for (std::vector<aabb3f>::iterator
i = m_selection_boxes.begin();
i != m_selection_boxes.end(); ++i) {
halo_box.addInternalBox(*i);
}
m_halo_boxes.push_back(halo_box);
m_selection_mesh = convertNodeboxesToMesh(
m_halo_boxes, texture_uv, 0.5);
}
void Hud::resizeHotbar() {

View File

@ -162,6 +162,7 @@ private:
video::SColor hbar_colors[4];
std::vector<aabb3f> m_selection_boxes;
std::vector<aabb3f> m_halo_boxes;
v3f m_selection_pos;
v3f m_selection_pos_with_offset;

View File

@ -1,30 +0,0 @@
/*
Minetest
Copyright (C) 2013 celeron55, Perttu Ahola <celeron55@gmail.com>
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU Lesser General Public License as published by
the Free Software Foundation; either version 3.0 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU Lesser General Public License for more details.
You should have received a copy of the GNU Lesser General Public License along
with this program; if not, write to the Free Software Foundation, Inc.,
51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
*/
#ifndef LUAENTITY_COMMON_HEADER
#define LUAENTITY_COMMON_HEADER
#define LUAENTITY_CMD_UPDATE_POSITION 0
#define LUAENTITY_CMD_SET_TEXTURE_MOD 1
#define LUAENTITY_CMD_SET_SPRITE 2
#define LUAENTITY_CMD_PUNCHED 3
#define LUAENTITY_CMD_UPDATE_ARMOR_GROUPS 4
#endif

View File

@ -181,6 +181,13 @@ public:
virtual void makeChunk(BlockMakeData *data) {}
virtual int getGroundLevelAtPoint(v2s16 p) { return 0; }
// getSpawnLevelAtPoint() is a function within each mapgen that returns a
// suitable y co-ordinate for player spawn ('suitable' usually meaning
// within 16 nodes of water_level). If a suitable spawn level cannot be
// found at the specified (X, Z) 'MAX_MAP_GENERATION_LIMIT' is returned to
// signify this and to cause Server::findSpawnPos() to try another (X, Z).
virtual int getSpawnLevelAtPoint(v2s16 p) { return 0; }
private:
DISABLE_CLASS_COPY(Mapgen);
};

View File

@ -192,18 +192,25 @@ void MapgenFlatParams::writeParams(Settings *settings) const
/////////////////////////////////////////////////////////////////
int MapgenFlat::getGroundLevelAtPoint(v2s16 p)
int MapgenFlat::getSpawnLevelAtPoint(v2s16 p)
{
s16 level_at_point = ground_level;
float n_terrain = NoisePerlin2D(&noise_terrain->np, p.X, p.Y, seed);
if ((spflags & MGFLAT_LAKES) && n_terrain < lake_threshold) {
s16 depress = (lake_threshold - n_terrain) * lake_steepness;
return ground_level - depress;
level_at_point = ground_level -
(lake_threshold - n_terrain) * lake_steepness;
} else if ((spflags & MGFLAT_HILLS) && n_terrain > hill_threshold) {
s16 rise = (n_terrain - hill_threshold) * hill_steepness;
return ground_level + rise;
} else {
return ground_level;
level_at_point = ground_level +
(n_terrain - hill_threshold) * hill_steepness;
}
if (ground_level < water_level) // Ocean world, allow spawn in water
return MYMAX(level_at_point, water_level);
else if (level_at_point > water_level)
return level_at_point; // Spawn on land
else
return MAX_MAP_GENERATION_LIMIT; // Unsuitable spawn point
}

View File

@ -102,7 +102,7 @@ public:
~MapgenFlat();
virtual void makeChunk(BlockMakeData *data);
int getGroundLevelAtPoint(v2s16 p);
int getSpawnLevelAtPoint(v2s16 p);
void calculateNoise();
s16 generateTerrain();
MgStoneType generateBiomes(float *heat_map, float *humidity_map);

View File

@ -209,17 +209,28 @@ void MapgenFractalParams::writeParams(Settings *settings) const
/////////////////////////////////////////////////////////////////
int MapgenFractal::getGroundLevelAtPoint(v2s16 p)
int MapgenFractal::getSpawnLevelAtPoint(v2s16 p)
{
s16 search_start = 128;
s16 search_end = -128;
bool solid_below = false; // Dry solid node is present below to spawn on
u8 air_count = 0; // Consecutive air nodes above the dry solid node
s16 seabed_level = NoisePerlin2D(&noise_seabed->np, p.X, p.Y, seed);
// Seabed can rise above water_level or might be raised to create dry land
s16 search_start = MYMAX(seabed_level, water_level + 1);
if (seabed_level > water_level)
solid_below = true;
for (s16 y = search_start; y >= search_end; y--) {
if (getFractalAtPoint(p.X, y, p.Y))
return y;
for (s16 y = search_start; y <= search_start + 128; y++) {
if (getFractalAtPoint(p.X, y, p.Y)) { // Fractal node
solid_below = true;
air_count = 0;
} else if (solid_below) { // Air above solid node
air_count++;
if (air_count == 2)
return y - 2;
}
}
return -MAX_MAP_GENERATION_LIMIT;
return MAX_MAP_GENERATION_LIMIT; // Unsuitable spawn point
}

View File

@ -114,7 +114,7 @@ public:
~MapgenFractal();
virtual void makeChunk(BlockMakeData *data);
int getGroundLevelAtPoint(v2s16 p);
int getSpawnLevelAtPoint(v2s16 p);
void calculateNoise();
bool getFractalAtPoint(s16 x, s16 y, s16 z);
s16 generateTerrain();

View File

@ -99,7 +99,7 @@ void MapgenSinglenode::makeChunk(BlockMakeData *data)
}
int MapgenSinglenode::getGroundLevelAtPoint(v2s16 p)
int MapgenSinglenode::getSpawnLevelAtPoint(v2s16 p)
{
return 0;
}

View File

@ -41,7 +41,7 @@ public:
~MapgenSinglenode();
void makeChunk(BlockMakeData *data);
int getGroundLevelAtPoint(v2s16 p);
int getSpawnLevelAtPoint(v2s16 p);
};
struct MapgenFactorySinglenode : public MapgenFactory {

View File

@ -171,7 +171,7 @@ void MapgenV5Params::writeParams(Settings *settings) const
}
int MapgenV5::getGroundLevelAtPoint(v2s16 p)
int MapgenV5::getSpawnLevelAtPoint(v2s16 p)
{
//TimeTaker t("getGroundLevelAtPoint", NULL, PRECISION_MICRO);
@ -182,24 +182,25 @@ int MapgenV5::getGroundLevelAtPoint(v2s16 p)
f *= 1.6;
float h = NoisePerlin2D(&noise_height->np, p.X, p.Y, seed);
s16 search_start = 128; // Only bother searching this range, actual
s16 search_end = -128; // ground level is rarely higher or lower.
for (s16 y = search_start; y >= search_end; y--) {
for (s16 y = 128; y >= -128; y--) {
float n_ground = NoisePerlin3D(&noise_ground->np, p.X, y, p.Y, seed);
// If solid
if (n_ground * f > y - h) {
if (n_ground * f > y - h) { // If solid
// If either top 2 nodes of search are solid this is inside a
// mountain or floatland with no space for the player to spawn.
if (y >= search_start - 1)
return MAX_MAP_GENERATION_LIMIT;
// mountain or floatland with possibly no space for the player to spawn.
if (y >= 127) {
return MAX_MAP_GENERATION_LIMIT; // Unsuitable spawn point
} else { // Ground below at least 2 nodes of empty space
if (y <= water_level || y > water_level + 16)
return MAX_MAP_GENERATION_LIMIT; // Unsuitable spawn point
else
return y; // Ground below at least 2 nodes of space
return y;
}
}
}
//printf("getGroundLevelAtPoint: %dus\n", t.stop());
return -MAX_MAP_GENERATION_LIMIT;
return MAX_MAP_GENERATION_LIMIT; // Unsuitable spawn position, no ground found
}

View File

@ -90,7 +90,7 @@ public:
~MapgenV5();
virtual void makeChunk(BlockMakeData *data);
int getGroundLevelAtPoint(v2s16 p);
int getSpawnLevelAtPoint(v2s16 p);
void calculateNoise();
int generateBaseTerrain();
MgStoneType generateBiomes(float *heat_map, float *humidity_map);

View File

@ -318,6 +318,17 @@ int MapgenV6::getGroundLevelAtPoint(v2s16 p)
}
int MapgenV6::getSpawnLevelAtPoint(v2s16 p)
{
s16 level_at_point = baseTerrainLevelFromNoise(p) + MGV6_AVERAGE_MUD_AMOUNT;
if (level_at_point <= water_level ||
level_at_point > water_level + 16)
return MAX_MAP_GENERATION_LIMIT; // Unsuitable spawn point
else
return level_at_point;
}
//////////////////////// Noise functions
float MapgenV6::getMudAmount(v2s16 p)

View File

@ -129,6 +129,7 @@ public:
void makeChunk(BlockMakeData *data);
int getGroundLevelAtPoint(v2s16 p);
int getSpawnLevelAtPoint(v2s16 p);
float baseTerrainLevel(float terrain_base, float terrain_higher,
float steepness, float height_select);

View File

@ -202,7 +202,7 @@ void MapgenV7Params::writeParams(Settings *settings) const
///////////////////////////////////////
int MapgenV7::getGroundLevelAtPoint(v2s16 p)
int MapgenV7::getSpawnLevelAtPoint(v2s16 p)
{
// Base terrain calculation
s16 y = baseTerrainLevelAtPoint(p.X, p.Y);
@ -210,22 +210,24 @@ int MapgenV7::getGroundLevelAtPoint(v2s16 p)
// Ridge/river terrain calculation
float width = 0.2;
float uwatern = NoisePerlin2D(&noise_ridge_uwater->np, p.X, p.Y, seed) * 2;
// actually computing the depth of the ridge is much more expensive;
// if inside a river, simply guess
// if inside a river this is an unsuitable spawn point
if (fabs(uwatern) <= width)
return water_level - 10;
return MAX_MAP_GENERATION_LIMIT;
// Mountain terrain calculation
int iters = 128; // don't even bother iterating more than 128 times..
int iters = 128;
while (iters--) {
//current point would have been air
if (!getMountainTerrainAtPoint(p.X, y, p.Y))
if (!getMountainTerrainAtPoint(p.X, y + 1, p.Y)) { // Air, y is ground level
if (y <= water_level || y > water_level + 16)
return MAX_MAP_GENERATION_LIMIT; // Unsuitable spawn point
else
return y;
}
y++;
}
return y;
// Unsuitable spawn point, no ground surface found
return MAX_MAP_GENERATION_LIMIT;
}

View File

@ -103,7 +103,7 @@ public:
~MapgenV7();
virtual void makeChunk(BlockMakeData *data);
int getGroundLevelAtPoint(v2s16 p);
int getSpawnLevelAtPoint(v2s16 p);
Biome *getBiomeAtPoint(v3s16 p);
float baseTerrainLevelAtPoint(s16 x, s16 z);

View File

@ -56,8 +56,8 @@ with this program; if not, write to the Free Software Foundation, Inc.,
//Profiler *mapgen_profiler = &mapgen_prof;
static FlagDesc flagdesc_mapgen_valleys[] = {
{"altitude_chill", MG_VALLEYS_ALT_CHILL},
{"humid_rivers", MG_VALLEYS_HUMID_RIVERS},
{"altitude_chill", MGVALLEYS_ALT_CHILL},
{"humid_rivers", MGVALLEYS_HUMID_RIVERS},
{NULL, 0}
};
@ -86,8 +86,8 @@ MapgenValleys::MapgenValleys(int mapgenid, MapgenParams *params, EmergeManager *
MapgenValleysParams *sp = (MapgenValleysParams *)params->sparams;
this->spflags = sp->spflags;
this->humid_rivers = (spflags & MG_VALLEYS_HUMID_RIVERS);
this->use_altitude_chill = (spflags & MG_VALLEYS_ALT_CHILL);
this->humid_rivers = (spflags & MGVALLEYS_HUMID_RIVERS);
this->use_altitude_chill = (spflags & MGVALLEYS_ALT_CHILL);
this->altitude_chill = sp->altitude_chill;
this->humidity_adjust = params->np_biome_humidity.offset - 50.f;
@ -181,7 +181,7 @@ MapgenValleys::~MapgenValleys()
MapgenValleysParams::MapgenValleysParams()
{
spflags = MG_VALLEYS_HUMID_RIVERS | MG_VALLEYS_ALT_CHILL;
spflags = MGVALLEYS_HUMID_RIVERS | MGVALLEYS_ALT_CHILL;
altitude_chill = 90; // The altitude at which temperature drops by 20C.
large_cave_depth = -33;
@ -513,24 +513,19 @@ float MapgenValleys::adjustedTerrainLevelFromNoise(TerrainNoise *tn)
}
int MapgenValleys::getGroundLevelAtPoint(v2s16 p)
int MapgenValleys::getSpawnLevelAtPoint(v2s16 p)
{
// ***********************************
// This method (deliberately) does not
// return correct terrain values.
// ***********************************
// Since MT doesn't normally deal with rivers, check
// to make sure this isn't a request for a location
// in a river.
// Check to make sure this isn't a request for a location in a river.
float rivers = NoisePerlin2D(&noise_rivers->np, p.X, p.Y, seed);
// If it's wet, return an unusable number.
if (fabs(rivers) < river_size_factor)
return MAX_MAP_GENERATION_LIMIT;
return MAX_MAP_GENERATION_LIMIT; // Unsuitable spawn point
// Otherwise, return the real result.
return terrainLevelAtPoint(p.X, p.Y);
s16 level_at_point = terrainLevelAtPoint(p.X, p.Y);
if (level_at_point <= water_level ||
level_at_point > water_level + 16)
return MAX_MAP_GENERATION_LIMIT; // Unsuitable spawn point
else
return level_at_point;
}

View File

@ -30,9 +30,9 @@ with this program; if not, write to the Free Software Foundation, Inc.,
#include "mapgen.h"
/////////////////// Mapgen Valleys flags
#define MG_VALLEYS_ALT_CHILL 0x01
#define MG_VALLEYS_HUMID_RIVERS 0x02
////////////// Mapgen Valleys flags
#define MGVALLEYS_ALT_CHILL 0x01
#define MGVALLEYS_HUMID_RIVERS 0x02
// Feed only one variable into these.
#define MYSQUARE(x) (x) * (x)
@ -96,7 +96,7 @@ public:
~MapgenValleys();
virtual void makeChunk(BlockMakeData *data);
int getGroundLevelAtPoint(v2s16 p);
int getSpawnLevelAtPoint(v2s16 p);
s16 large_cave_depth;

View File

@ -104,7 +104,7 @@ void scaleMesh(scene::IMesh *mesh, v3f scale)
if (mesh == NULL)
return;
core::aabbox3d<f32> bbox;
aabb3f bbox;
bbox.reset(0, 0, 0);
u32 mc = mesh->getMeshBufferCount();
@ -132,7 +132,7 @@ void translateMesh(scene::IMesh *mesh, v3f vec)
if (mesh == NULL)
return;
core::aabbox3d<f32> bbox;
aabb3f bbox;
bbox.reset(0, 0, 0);
u32 mc = mesh->getMeshBufferCount();
@ -346,7 +346,7 @@ void rotateMeshBy6dFacedir(scene::IMesh *mesh, int facedir)
void recalculateBoundingBox(scene::IMesh *src_mesh)
{
core::aabbox3d<f32> bbox;
aabb3f bbox;
bbox.reset(0,0,0);
for (u16 j = 0; j < src_mesh->getMeshBufferCount(); j++) {
scene::IMeshBuffer *buf = src_mesh->getMeshBuffer(j);
@ -406,7 +406,7 @@ scene::IMesh* cloneMesh(scene::IMesh *src_mesh)
}
scene::IMesh* convertNodeboxesToMesh(const std::vector<aabb3f> &boxes,
const f32 *uv_coords)
const f32 *uv_coords, float expand)
{
scene::SMesh* dst_mesh = new scene::SMesh();
@ -421,31 +421,19 @@ scene::IMesh* convertNodeboxesToMesh(const std::vector<aabb3f> &boxes,
video::SColor c(255,255,255,255);
for(std::vector<aabb3f>::const_iterator
for (std::vector<aabb3f>::const_iterator
i = boxes.begin();
i != boxes.end(); ++i)
{
aabb3f box = *i;
box.repair();
f32 temp;
if (box.MinEdge.X > box.MaxEdge.X)
{
temp=box.MinEdge.X;
box.MinEdge.X=box.MaxEdge.X;
box.MaxEdge.X=temp;
}
if (box.MinEdge.Y > box.MaxEdge.Y)
{
temp=box.MinEdge.Y;
box.MinEdge.Y=box.MaxEdge.Y;
box.MaxEdge.Y=temp;
}
if (box.MinEdge.Z > box.MaxEdge.Z)
{
temp=box.MinEdge.Z;
box.MinEdge.Z=box.MaxEdge.Z;
box.MaxEdge.Z=temp;
}
box.MinEdge.X -= expand;
box.MinEdge.Y -= expand;
box.MinEdge.Z -= expand;
box.MaxEdge.X += expand;
box.MaxEdge.Y += expand;
box.MaxEdge.Z += expand;
// Compute texture UV coords
f32 tx1 = (box.MinEdge.X / BS) + 0.5;

View File

@ -86,9 +86,10 @@ scene::IMesh* cloneMesh(scene::IMesh *src_mesh);
Convert nodeboxes to mesh.
boxes - set of nodeboxes to be converted into cuboids
uv_coords[24] - table of texture uv coords for each cuboid face
expand - factor by which cuboids will be resized
*/
scene::IMesh* convertNodeboxesToMesh(const std::vector<aabb3f> &boxes,
const f32 *uv_coords = NULL);
const f32 *uv_coords = NULL, float expand = 0);
/*
Update bounding box for a mesh.

View File

@ -139,7 +139,7 @@ void TileDef::serialize(std::ostream &os, u16 protocol_version) const
}
}
void TileDef::deSerialize(std::istream &is, bool culling_ignore)
void TileDef::deSerialize(std::istream &is, const u8 contenfeatures_version, const NodeDrawType drawtype)
{
int version = readU8(is);
name = deSerializeString(is);
@ -153,10 +153,12 @@ void TileDef::deSerialize(std::istream &is, bool culling_ignore)
tileable_horizontal = readU8(is);
tileable_vertical = readU8(is);
}
// when connecting to old servers - do not use
// provided values here since culling needs to be
// disabled by default for these drawtypes
if (culling_ignore)
if ((contenfeatures_version < 8) &&
((drawtype == NDT_MESH) ||
(drawtype == NDT_FIRELIKE) ||
(drawtype == NDT_LIQUID) ||
(drawtype == NDT_PLANTLIKE)))
backface_culling = false;
}
@ -268,7 +270,8 @@ void ContentFeatures::serialize(std::ostream &os, u16 protocol_version) const
return;
}
writeU8(os, 7); // version
writeU8(os, protocol_version < 27 ? 7 : 8);
os<<serializeString(name);
writeU16(os, groups.size());
for(ItemGroupList::const_iterator
@ -330,9 +333,11 @@ void ContentFeatures::serialize(std::ostream &os, u16 protocol_version) const
void ContentFeatures::deSerialize(std::istream &is)
{
int version = readU8(is);
if(version != 7){
if (version < 7) {
deSerializeOld(is, version);
return;
} else if (version > 8) {
throw SerializationError("unsupported ContentFeatures version");
}
name = deSerializeString(is);
@ -345,21 +350,15 @@ void ContentFeatures::deSerialize(std::istream &is)
}
drawtype = (enum NodeDrawType)readU8(is);
bool ignore_culling = ((version <= 26) &&
((drawtype == NDT_MESH) ||
(drawtype == NDT_PLANTLIKE) ||
(drawtype == NDT_FIRELIKE) ||
(drawtype == NDT_LIQUID)));
visual_scale = readF1000(is);
if(readU8(is) != 6)
throw SerializationError("unsupported tile count");
for(u32 i = 0; i < 6; i++)
tiledef[i].deSerialize(is, ignore_culling);
tiledef[i].deSerialize(is, version, drawtype);
if(readU8(is) != CF_SPECIAL_COUNT)
throw SerializationError("unsupported CF_SPECIAL_COUNT");
for(u32 i = 0; i < CF_SPECIAL_COUNT; i++)
tiledef_special[i].deSerialize(is, ignore_culling);
tiledef_special[i].deSerialize(is, version, drawtype);
alpha = readU8(is);
post_effect_color.setAlpha(readU8(is));
post_effect_color.setRed(readU8(is));
@ -1284,21 +1283,15 @@ void ContentFeatures::deSerializeOld(std::istream &is, int version)
}
drawtype = (enum NodeDrawType)readU8(is);
bool ignore_culling = ((version <= 26) &&
((drawtype == NDT_MESH) ||
(drawtype == NDT_PLANTLIKE) ||
(drawtype == NDT_FIRELIKE) ||
(drawtype == NDT_LIQUID)));
visual_scale = readF1000(is);
if (readU8(is) != 6)
throw SerializationError("unsupported tile count");
for (u32 i = 0; i < 6; i++)
tiledef[i].deSerialize(is, ignore_culling);
tiledef[i].deSerialize(is, version, drawtype);
if (readU8(is) != CF_SPECIAL_COUNT)
throw SerializationError("unsupported CF_SPECIAL_COUNT");
for (u32 i = 0; i < CF_SPECIAL_COUNT; i++)
tiledef_special[i].deSerialize(is, ignore_culling);
tiledef_special[i].deSerialize(is, version, drawtype);
alpha = readU8(is);
post_effect_color.setAlpha(readU8(is));
post_effect_color.setRed(readU8(is));
@ -1342,12 +1335,12 @@ void ContentFeatures::deSerializeOld(std::istream &is, int version)
if (readU8(is) != 6)
throw SerializationError("unsupported tile count");
for (u32 i = 0; i < 6; i++)
tiledef[i].deSerialize(is, drawtype);
tiledef[i].deSerialize(is, version, drawtype);
// CF_SPECIAL_COUNT in version 6 = 2
if (readU8(is) != 2)
throw SerializationError("unsupported CF_SPECIAL_COUNT");
for (u32 i = 0; i < 2; i++)
tiledef_special[i].deSerialize(is, drawtype);
tiledef_special[i].deSerialize(is, version, drawtype);
alpha = readU8(is);
post_effect_color.setAlpha(readU8(is));
post_effect_color.setRed(readU8(is));

View File

@ -104,6 +104,30 @@ struct NodeBox
struct MapNode;
class NodeMetadata;
enum NodeDrawType
{
NDT_NORMAL, // A basic solid block
NDT_AIRLIKE, // Nothing is drawn
NDT_LIQUID, // Do not draw face towards same kind of flowing/source liquid
NDT_FLOWINGLIQUID, // A very special kind of thing
NDT_GLASSLIKE, // Glass-like, don't draw faces towards other glass
NDT_ALLFACES, // Leaves-like, draw all faces no matter what
NDT_ALLFACES_OPTIONAL, // Fancy -> allfaces, fast -> normal
NDT_TORCHLIKE,
NDT_SIGNLIKE,
NDT_PLANTLIKE,
NDT_FENCELIKE,
NDT_RAILLIKE,
NDT_NODEBOX,
NDT_GLASSLIKE_FRAMED, // Glass-like, draw connected frames and all all
// visible faces
// uses 2 textures, one for frames, second for faces
NDT_FIRELIKE, // Draw faces slightly rotated and only on connecting nodes,
NDT_GLASSLIKE_FRAMED_OPTIONAL, // enabled -> connected, disabled -> Glass-like
// uses 2 textures, one for frames, second for faces
NDT_MESH, // Uses static meshes
};
/*
Stand-alone definition of a TileSpec (basically a server-side TileSpec)
*/
@ -137,31 +161,7 @@ struct TileDef
}
void serialize(std::ostream &os, u16 protocol_version) const;
void deSerialize(std::istream &is, bool culling_ignore);
};
enum NodeDrawType
{
NDT_NORMAL, // A basic solid block
NDT_AIRLIKE, // Nothing is drawn
NDT_LIQUID, // Do not draw face towards same kind of flowing/source liquid
NDT_FLOWINGLIQUID, // A very special kind of thing
NDT_GLASSLIKE, // Glass-like, don't draw faces towards other glass
NDT_ALLFACES, // Leaves-like, draw all faces no matter what
NDT_ALLFACES_OPTIONAL, // Fancy -> allfaces, fast -> normal
NDT_TORCHLIKE,
NDT_SIGNLIKE,
NDT_PLANTLIKE,
NDT_FENCELIKE,
NDT_RAILLIKE,
NDT_NODEBOX,
NDT_GLASSLIKE_FRAMED, // Glass-like, draw connected frames and all all
// visible faces
// uses 2 textures, one for frames, second for faces
NDT_FIRELIKE, // Draw faces slightly rotated and only on connecting nodes,
NDT_GLASSLIKE_FRAMED_OPTIONAL, // enabled -> connected, disabled -> Glass-like
// uses 2 textures, one for frames, second for faces
NDT_MESH, // Uses static meshes
void deSerialize(std::istream &is, const u8 contentfeatures_version, const NodeDrawType drawtype);
};
#define CF_SPECIAL_COUNT 6

View File

@ -33,7 +33,7 @@ struct ObjectProperties
bool physical;
bool collideWithObjects;
float weight;
core::aabbox3d<f32> collisionbox;
aabb3f collisionbox;
std::string visual;
std::string mesh;
v2f visual_size;

View File

@ -88,7 +88,7 @@ Particle::Particle(
m_vertical = vertical;
// Irrlicht stuff
m_collisionbox = core::aabbox3d<f32>
m_collisionbox = aabb3f
(-size/2,-size/2,-size/2,size/2,size/2,size/2);
this->setAutomaticCulling(scene::EAC_OFF);
@ -128,7 +128,7 @@ void Particle::step(float dtime)
m_time += dtime;
if (m_collisiondetection)
{
core::aabbox3d<f32> box = m_collisionbox;
aabb3f box = m_collisionbox;
v3f p_pos = m_pos*BS;
v3f p_velocity = m_velocity*BS;
collisionMoveSimple(m_env, m_gamedef,

View File

@ -52,7 +52,7 @@ class Particle : public scene::ISceneNode
);
~Particle();
virtual const core::aabbox3d<f32>& getBoundingBox() const
virtual const aabb3f &getBoundingBox() const
{
return m_box;
}
@ -85,8 +85,8 @@ private:
ClientEnvironment *m_env;
IGameDef *m_gamedef;
core::aabbox3d<f32> m_box;
core::aabbox3d<f32> m_collisionbox;
aabb3f m_box;
aabb3f m_collisionbox;
video::SMaterial m_material;
v2f m_texpos;
v2f m_texsize;

View File

@ -198,7 +198,7 @@ public:
return m_name;
}
core::aabbox3d<f32> getCollisionbox()
aabb3f getCollisionbox()
{
return m_collisionbox;
}
@ -398,7 +398,7 @@ protected:
f32 m_yaw;
v3f m_speed;
v3f m_position;
core::aabbox3d<f32> m_collisionbox;
aabb3f m_collisionbox;
bool m_dirty;

View File

@ -22,6 +22,7 @@ with this program; if not, write to the Free Software Foundation, Inc.,
#include "lua_api/l_internal.h"
#include "common/c_converter.h"
#include "cpp_api/s_security.h"
#include "irr_v3d.h"
#include "areastore.h"
#include "filesys.h"
#ifndef ANDROID

View File

@ -21,7 +21,6 @@ with this program; if not, write to the Free Software Foundation, Inc.,
#define L_AREASTORE_H_
#include "lua_api/l_base.h"
#include "irr_v3d.h"
#include "areastore.h"
/*

View File

@ -36,6 +36,13 @@ with this program; if not, write to the Free Software Foundation, Inc.,
#include "emerge.h"
#include "pathfinder.h"
struct EnumString ModApiEnvMod::es_ClearObjectsMode[] =
{
{CLEAR_OBJECTS_MODE_FULL, "full"},
{CLEAR_OBJECTS_MODE_QUICK, "quick"},
{0, NULL},
};
///////////////////////////////////////////////////////////////////////////////
@ -727,13 +734,20 @@ int ModApiEnvMod::l_get_voxel_manip(lua_State *L)
return 1;
}
// clear_objects()
// clear_objects([options])
// clear all objects in the environment
// where options = {mode = "full" or "quick"}
int ModApiEnvMod::l_clear_objects(lua_State *L)
{
GET_ENV_PTR;
env->clearAllObjects();
ClearObjectsMode mode = CLEAR_OBJECTS_MODE_FULL;
if (lua_istable(L, 1)) {
mode = (ClearObjectsMode)getenumfield(L, 1, "mode",
ModApiEnvMod::es_ClearObjectsMode, mode);
}
env->clearObjects(mode);
return 0;
}

View File

@ -170,6 +170,8 @@ private:
public:
static void Initialize(lua_State *L, int top);
static struct EnumString es_ClearObjectsMode[];
};
class LuaABM : public ActiveBlockModifier {

View File

@ -3376,26 +3376,24 @@ v3f Server::findSpawnPos()
return nodeposf * BS;
}
s16 water_level = map.getWaterLevel();
s16 vertical_spawn_range = g_settings->getS16("vertical_spawn_range");
bool is_good = false;
// Try to find a good place a few times
for(s32 i = 0; i < 1000 && !is_good; i++) {
for(s32 i = 0; i < 4000 && !is_good; i++) {
s32 range = 1 + i;
// We're going to try to throw the player to this position
v2s16 nodepos2d = v2s16(
-range + (myrand() % (range * 2)),
-range + (myrand() % (range * 2)));
// Get ground height at point
s16 groundheight = map.findGroundLevel(nodepos2d);
// Don't go underwater or to high places
if (groundheight <= water_level ||
groundheight > water_level + vertical_spawn_range)
// Get spawn level at point
s16 spawn_level = m_emerge->getSpawnLevelAtPoint(nodepos2d);
// Continue if MAX_MAP_GENERATION_LIMIT was returned by
// the mapgen to signify an unsuitable spawn position
if (spawn_level == MAX_MAP_GENERATION_LIMIT)
continue;
v3s16 nodepos(nodepos2d.X, groundheight, nodepos2d.Y);
v3s16 nodepos(nodepos2d.X, spawn_level, nodepos2d.Y);
s32 air_count = 0;
for (s32 i = 0; i < 10; i++) {

View File

@ -764,22 +764,25 @@ ShaderInfo generate_shader(std::string name, u8 material_type, u8 drawtype,
else
shaders_header += "0\n";
if(pixel_program != "")
pixel_program = shaders_header + pixel_program;
if(vertex_program != "")
vertex_program = shaders_header + vertex_program;
if(geometry_program != "")
geometry_program = shaders_header + geometry_program;
if (g_settings->getBool("tone_mapping"))
shaders_header += "#define ENABLE_TONE_MAPPING\n";
// Call addHighLevelShaderMaterial() or addShaderMaterial()
const c8* vertex_program_ptr = 0;
const c8* pixel_program_ptr = 0;
const c8* geometry_program_ptr = 0;
if(vertex_program != "")
if (!vertex_program.empty()) {
vertex_program = shaders_header + vertex_program;
vertex_program_ptr = vertex_program.c_str();
if(pixel_program != "")
}
if (!pixel_program.empty()) {
pixel_program = shaders_header + pixel_program;
pixel_program_ptr = pixel_program.c_str();
if(geometry_program != "")
}
if (!geometry_program.empty()) {
geometry_program = shaders_header + geometry_program;
geometry_program_ptr = geometry_program.c_str();
}
s32 shadermat = -1;
if(is_highlevel){
infostream<<"Compiling high level shaders for "<<name<<std::endl;
@ -789,7 +792,7 @@ ShaderInfo generate_shader(std::string name, u8 material_type, u8 drawtype,
video::EVST_VS_1_1, // Vertex shader version
pixel_program_ptr, // Pixel shader program
"pixelMain", // Pixel shader entry point
video::EPST_PS_1_1, // Pixel shader version
video::EPST_PS_1_2, // Pixel shader version
geometry_program_ptr, // Geometry shader program
"geometryMain", // Geometry shader entry point
video::EGST_GS_4_0, // Geometry shader version
@ -805,6 +808,9 @@ ShaderInfo generate_shader(std::string name, u8 material_type, u8 drawtype,
"failed to generate \""<<name<<"\", "
"addHighLevelShaderMaterial failed."
<<std::endl;
dumpShaderProgram(warningstream, "Vertex", vertex_program);
dumpShaderProgram(warningstream, "Pixel", pixel_program);
dumpShaderProgram(warningstream, "Geometry", geometry_program);
return shaderinfo;
}
}
@ -823,6 +829,8 @@ ShaderInfo generate_shader(std::string name, u8 material_type, u8 drawtype,
"failed to generate \""<<name<<"\", "
"addShaderMaterial failed."
<<std::endl;
dumpShaderProgram(warningstream, "Vertex", vertex_program);
dumpShaderProgram(warningstream,"Pixel", pixel_program);
return shaderinfo;
}
}
@ -868,3 +876,21 @@ void load_shaders(std::string name, SourceShaderCache *sourcecache,
}
}
void dumpShaderProgram(std::ostream &output_stream,
const std::string &program_type, const std::string &program)
{
output_stream << program_type << " shader program:" << std::endl <<
"----------------------------------" << std::endl;
size_t pos = 0;
size_t prev = 0;
s16 line = 1;
while ((pos = program.find("\n", prev)) != std::string::npos) {
output_stream << line++ << ": "<< program.substr(prev, pos - prev) <<
std::endl;
prev = pos + 1;
}
output_stream << line << ": " << program.substr(prev) << std::endl <<
"End of " << program_type << " shader program." << std::endl <<
" " << std::endl;
}

View File

@ -110,4 +110,7 @@ public:
IWritableShaderSource* createShaderSource(IrrlichtDevice *device);
void dumpShaderProgram(std::ostream &output_stream,
const std::string &program_type, const std::string &program);
#endif

View File

@ -25,8 +25,8 @@ Sky::Sky(scene::ISceneNode* parent, scene::ISceneManager* mgr, s32 id,
m_cloudcolor_bright_f(1,1,1,1)
{
setAutomaticCulling(scene::EAC_OFF);
Box.MaxEdge.set(0,0,0);
Box.MinEdge.set(0,0,0);
m_box.MaxEdge.set(0,0,0);
m_box.MinEdge.set(0,0,0);
// create material
@ -94,11 +94,6 @@ void Sky::OnRegisterSceneNode()
scene::ISceneNode::OnRegisterSceneNode();
}
const core::aabbox3d<f32>& Sky::getBoundingBox() const
{
return Box;
}
//! renders the node.
void Sky::render()
{

View File

@ -42,7 +42,8 @@ public:
//! renders the node.
virtual void render();
virtual const core::aabbox3d<f32>& getBoundingBox() const;
virtual const aabb3f &getBoundingBox() const
{ return m_box; }
// Used by Irrlicht for optimizing rendering
virtual video::SMaterial& getMaterial(u32 i)
@ -74,7 +75,7 @@ public:
}
private:
core::aabbox3d<f32> Box;
aabb3f m_box;
video::SMaterial m_materials[SKY_MATERIAL_COUNT];
// How much sun & moon transition should affect horizon color

View File

@ -310,9 +310,9 @@ inline v3f intToFloat(v3s16 p, f32 d)
}
// Random helper. Usually d=BS
inline core::aabbox3d<f32> getNodeBox(v3s16 p, float d)
inline aabb3f getNodeBox(v3s16 p, float d)
{
return core::aabbox3d<f32>(
return aabb3f(
(float)p.X * d - 0.5*d,
(float)p.Y * d - 0.5*d,
(float)p.Z * d - 0.5*d,

View File

@ -53,7 +53,7 @@ public:
virtual void render();
virtual const core::aabbox3d<f32>& getBoundingBox() const
virtual const aabb3f &getBoundingBox() const
{ return m_bounding_box; }
private:
@ -74,7 +74,7 @@ private:
// 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.
core::aabbox3d<f32> m_bounding_box;
aabb3f m_bounding_box;
};
scene::IMesh *getItemMesh(IGameDef *gamedef, const ItemStack &item);