master
Maksim Gamarnik 2016-04-12 21:28:50 +03:00
commit 6d3bdc5a7d
32 changed files with 897 additions and 778 deletions

View File

@ -147,7 +147,7 @@ end
-- Some common functions -- Some common functions
-- --
function nodeupdate_single(p, delay) function nodeupdate_single(p)
local n = core.get_node(p) local n = core.get_node(p)
if core.get_item_group(n.name, "falling_node") ~= 0 then if core.get_item_group(n.name, "falling_node") ~= 0 then
local p_bottom = {x = p.x, y = p.y - 1, z = p.z} local p_bottom = {x = p.x, y = p.y - 1, z = p.z}
@ -160,36 +160,84 @@ function nodeupdate_single(p, delay)
core.get_node_level(p_bottom) < core.get_node_max_level(p_bottom))) and core.get_node_level(p_bottom) < core.get_node_max_level(p_bottom))) and
(not core.registered_nodes[n_bottom.name].walkable or (not core.registered_nodes[n_bottom.name].walkable or
core.registered_nodes[n_bottom.name].buildable_to) then core.registered_nodes[n_bottom.name].buildable_to) then
if delay then n.level = core.get_node_level(p)
core.after(0.1, nodeupdate_single, p, false) core.remove_node(p)
else spawn_falling_node(p, n)
n.level = core.get_node_level(p) return true
core.remove_node(p)
spawn_falling_node(p, n)
nodeupdate(p)
end
end end
end end
if core.get_item_group(n.name, "attached_node") ~= 0 then if core.get_item_group(n.name, "attached_node") ~= 0 then
if not check_attached_node(p, n) then if not check_attached_node(p, n) then
drop_attached_node(p) drop_attached_node(p)
nodeupdate(p) return true
end end
end end
return false
end end
function nodeupdate(p, delay) -- This table is specifically ordered.
-- Round p to prevent falling entities to get stuck -- We don't walk diagonals, only our direct neighbors, and self.
-- Down first as likely case, but always before self. The same with sides.
-- Up must come last, so that things above self will also fall all at once.
local nodeupdate_neighbors = {
{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},
{x = 0, y = 0, z = 0},
{x = 0, y = 1, z = 0},
}
function nodeupdate(p)
-- Round p to prevent falling entities to get stuck.
p = vector.round(p) p = vector.round(p)
for x = -1, 1 do -- We make a stack, and manually maintain size for performance.
for y = -1, 1 do -- Stored in the stack, we will maintain tables with pos, and
for z = -1, 1 do -- last neighbor visited. This way, when we get back to each
local d = vector.new(x, y, z) -- node, we know which directions we have already walked, and
nodeupdate_single(vector.add(p, d), delay or not (x == 0 and y == 0 and z == 0)) -- which direction is the next to walk.
end local s = {}
end local n = 0
-- The neighbor order we will visit from our table.
local v = 1
while true do
-- Push current pos onto the stack.
n = n + 1
s[n] = {p = p, v = v}
-- Select next node from neighbor list.
p = vector.add(p, nodeupdate_neighbors[v])
-- Now we check out the node. If it is in need of an update,
-- it will let us know in the return value (true = updated).
if not nodeupdate_single(p) then
-- If we don't need to "recurse" (walk) to it then pop
-- our previous pos off the stack and continue from there,
-- with the v value we were at when we last were at that
-- node
repeat
local pop = s[n]
p = pop.p
v = pop.v
s[n] = nil
n = n - 1
-- If there's nothing left on the stack, and no
-- more sides to walk to, we're done and can exit
if n == 0 and v == 7 then
return
end
until v < 7
-- The next round walk the next neighbor in list.
v = v + 1
else
-- If we did need to walk the neighbor, then
-- start walking it from the walk order start (1),
-- and not the order we just pushed up the stack.
v = 1
end
end end
end end

View File

@ -12,7 +12,7 @@ if core.print then
-- Override native print and use -- Override native print and use
-- terminal if that's turned on -- terminal if that's turned on
function print(...) function print(...)
local n, t = select("#", ...), { ... } local n, t = select("#", ...), {...}
for i = 1, n do for i = 1, n do
t[i] = tostring(t[i]) t[i] = tostring(t[i])
end end
@ -25,26 +25,26 @@ os.setlocale("C", "numeric")
minetest = core minetest = core
-- Load other files -- Load other files
local scriptdir = core.get_builtin_path()..DIR_DELIM local scriptdir = core.get_builtin_path() .. DIR_DELIM
local gamepath = scriptdir.."game"..DIR_DELIM local gamepath = scriptdir .. "game" .. DIR_DELIM
local commonpath = scriptdir.."common"..DIR_DELIM local commonpath = scriptdir .. "common" .. DIR_DELIM
local asyncpath = scriptdir.."async"..DIR_DELIM local asyncpath = scriptdir .. "async" .. DIR_DELIM
dofile(commonpath.."strict.lua") dofile(commonpath .. "strict.lua")
dofile(commonpath.."serialize.lua") dofile(commonpath .. "serialize.lua")
dofile(commonpath.."misc_helpers.lua") dofile(commonpath .. "misc_helpers.lua")
if INIT == "game" then if INIT == "game" then
dofile(gamepath.."init.lua") dofile(gamepath .. "init.lua")
elseif INIT == "mainmenu" then elseif INIT == "mainmenu" then
local mainmenuscript = core.setting_get("main_menu_script") local mainmenuscript = core.setting_get("main_menu_script")
if mainmenuscript ~= nil and mainmenuscript ~= "" then if mainmenuscript ~= nil and mainmenuscript ~= "" then
dofile(mainmenuscript) dofile(mainmenuscript)
else else
dofile(core.get_mainmenu_path()..DIR_DELIM.."init.lua") dofile(core.get_mainmenu_path() .. DIR_DELIM .. "init.lua")
end end
elseif INIT == "async" then elseif INIT == "async" then
dofile(asyncpath.."init.lua") dofile(asyncpath .. "init.lua")
else else
error(("Unrecognized builtin initialization type %s!"):format(tostring(INIT))) error(("Unrecognized builtin initialization type %s!"):format(tostring(INIT)))
end end

View File

@ -35,24 +35,31 @@ dofile(basepath .. DIR_DELIM .. "fstk" .. DIR_DELIM .. "tabview.lua")
dofile(basepath .. DIR_DELIM .. "fstk" .. DIR_DELIM .. "ui.lua") dofile(basepath .. DIR_DELIM .. "fstk" .. DIR_DELIM .. "ui.lua")
dofile(menupath .. DIR_DELIM .. "common.lua") dofile(menupath .. DIR_DELIM .. "common.lua")
dofile(menupath .. DIR_DELIM .. "gamemgr.lua") dofile(menupath .. DIR_DELIM .. "gamemgr.lua")
dofile(menupath .. DIR_DELIM .. "store.lua") if PLATFORM ~= "Android" then
dofile(menupath .. DIR_DELIM .. "dlg_config_world.lua")
dofile(menupath .. DIR_DELIM .. "tab_credits.lua")
if not (PLATFORM == "Android") then
dofile(menupath .. DIR_DELIM .. "modmgr.lua") dofile(menupath .. DIR_DELIM .. "modmgr.lua")
dofile(menupath .. DIR_DELIM .. "tab_settings.lua") dofile(menupath .. DIR_DELIM .. "store.lua")
dofile(menupath .. DIR_DELIM .. "dlg_settings_advanced.lua")
dofile(menupath .. DIR_DELIM .. "tab_texturepacks.lua")
dofile(menupath .. DIR_DELIM .. "tab_mods.lua")
dofile(menupath .. DIR_DELIM .. "dlg_rename_modpack.lua")
dofile(menupath .. DIR_DELIM .. "dlg_delete_mod.lua")
end end
dofile(menupath .. DIR_DELIM .. "dlg_create_world.lua") dofile(menupath .. DIR_DELIM .. "dlg_create_world.lua")
--dofile(menupath .. DIR_DELIM .. "dlg_delete_mod.lua")
dofile(menupath .. DIR_DELIM .. "dlg_delete_world.lua") dofile(menupath .. DIR_DELIM .. "dlg_delete_world.lua")
dofile(menupath .. DIR_DELIM .. "tab_multiplayer.lua") --dofile(menupath .. DIR_DELIM .. "dlg_rename_modpack.lua")
dofile(menupath .. DIR_DELIM .. "tab_server.lua") dofile(menupath .. DIR_DELIM .. "dlg_config_world.lua")
dofile(menupath .. DIR_DELIM .. "tab_singleplayer.lua") if PLATFORM ~= "Android" then
dofile(menupath .. DIR_DELIM .. "textures.lua") dofile(menupath .. DIR_DELIM .. "dlg_settings_advanced.lua")
dofile(menupath .. DIR_DELIM .. "textures.lua")
end
local tabs = {}
--tabs.mods = dofile(menupath .. DIR_DELIM .. "tab_mods.lua")
tabs.credits = dofile(menupath .. DIR_DELIM .. "tab_credits.lua")
tabs.singleplayer = dofile(menupath .. DIR_DELIM .. "tab_singleplayer.lua")
tabs.multiplayer = dofile(menupath .. DIR_DELIM .. "tab_multiplayer.lua")
tabs.server = dofile(menupath .. DIR_DELIM .. "tab_server.lua")
if PLATFORM ~= "Android" then
tabs.settings = dofile(menupath .. DIR_DELIM .. "tab_settings.lua")
tabs.texturepacks = dofile(menupath .. DIR_DELIM .. "tab_texturepacks.lua")
end
-------------------------------------------------------------------------------- --------------------------------------------------------------------------------
local function main_event_handler(tabview, event) local function main_event_handler(tabview, event)
@ -67,66 +74,64 @@ local function init_globals()
-- Init gamedata -- Init gamedata
gamedata.worldindex = 0 gamedata.worldindex = 0
menudata.worldlist = filterlist.create(
core.get_worlds,
compare_worlds,
-- Unique id comparison function
function(element, uid)
return element.name == uid
end,
-- Filter function
function(element, gameid)
return element.gameid == gameid
end
)
menudata.worldlist = filterlist.create( menudata.worldlist:add_sort_mechanism("alphabetic", sort_worlds_alphabetic)
core.get_worlds, menudata.worldlist:set_sortmode("alphabetic")
compare_worlds,
-- Unique id comparison function
function(element, uid)
return element.name == uid
end,
-- Filter function
function(element, gameid)
return element.gameid == gameid
end
)
menudata.worldlist:add_sort_mechanism("alphabetic", sort_worlds_alphabetic) core.setting_set("menu_last_game", "default")
menudata.worldlist:set_sortmode("alphabetic")
core.setting_set("menu_last_game", "default") mm_texture.init()
mm_texture.init()
-- Create main tabview -- Create main tabview
local tv_main = tabview_create("maintab",{x=12,y=5.2},{x=0,y=0}) local tv_main = tabview_create("maintab", {x = 12, y = 5.2}, {x = 0, y = 0})
--tv_main:set_autosave_tab(true)
tv_main:add(tabs.singleplayer)
tv_main:add(tabs.multiplayer)
tv_main:add(tabs.server)
if PLATFORM ~= "Android" then if PLATFORM ~= "Android" then
tv_main:set_autosave_tab(true) tv_main:add(tabs.settings)
tv_main:add(tabs.texturepacks)
end end
tv_main:add(tab_singleplayer)
tv_main:add(tab_multiplayer) --tv_main:add(tabs.mods)
tv_main:add(tab_server) tv_main:add(tabs.credits)
if PLATFORM ~= "Android" then
tv_main:add(tab_settings)
tv_main:add(tab_texturepacks)
--tv_main:add(tab_mods)
end
tv_main:add(tab_credits)
tv_main:set_global_event_handler(main_event_handler) tv_main:set_global_event_handler(main_event_handler)
tv_main:set_fixed_size(false) tv_main:set_fixed_size(false)
if not (PLATFORM == "Android") then --if PLATFORM ~= "Android" then
tv_main:set_tab(core.setting_get("maintab_LAST")) -- tv_main:set_tab(core.setting_get("maintab_LAST"))
end --end
ui.set_default("maintab") ui.set_default("maintab")
tv_main:show() tv_main:show()
-- Create modstore ui -- Create modstore ui
if PLATFORM == "Android" then if PLATFORM == "Android" then
modstore.init({x=12, y=6}, 3, 2) modstore.init({x = 12, y = 6}, 3, 2)
else else
modstore.init({x=12, y=8}, 4, 3) modstore.init({x = 12, y = 8}, 4, 3)
end end
ui.update() ui.update()
core.sound_play("main_menu", false) core.sound_play("main_menu", false)
minetest.set_clouds(false) minetest.set_clouds(false)
core.set_background("background", defaulttexturedir .. "background.jpg"); core.set_background("background", defaulttexturedir .. "background.jpg");
end end
init_globals() init_globals()

View File

@ -74,7 +74,7 @@ local previous_contributors = {
"Zefram <zefram@fysh.org>", "Zefram <zefram@fysh.org>",
} }
tab_credits = { return {
name = "credits", name = "credits",
caption = fgettext("Credits"), caption = fgettext("Credits"),
cbf_formspec = function(tabview, name, tabdata) cbf_formspec = function(tabview, name, tabdata)

View File

@ -163,7 +163,7 @@ local function handle_buttons(tabview, fields, tabname, tabdata)
end end
-------------------------------------------------------------------------------- --------------------------------------------------------------------------------
tab_mods = { return {
name = "mods", name = "mods",
caption = fgettext("Mods"), caption = fgettext("Mods"),
cbf_formspec = get_formspec, cbf_formspec = get_formspec,

View File

@ -256,10 +256,10 @@ local function on_change(type,old_tab,new_tab)
end end
-------------------------------------------------------------------------------- --------------------------------------------------------------------------------
tab_multiplayer = { return {
name = "multiplayer", name = "multiplayer",
caption = fgettext("Multi Player"), caption = fgettext("Multi Player"),
cbf_formspec = get_formspec, cbf_formspec = get_formspec,
cbf_button_handler = main_button_handler, cbf_button_handler = main_button_handler,
on_change = on_change on_change = on_change
} }

View File

@ -186,10 +186,10 @@ local function main_button_handler(this, fields, name, tabdata)
end end
-------------------------------------------------------------------------------- --------------------------------------------------------------------------------
tab_server = { return {
name = "server", name = "server",
caption = fgettext("Create Server"), caption = fgettext("Create Server"),
cbf_formspec = get_formspec, cbf_formspec = get_formspec,
cbf_button_handler = main_button_handler, cbf_button_handler = main_button_handler,
on_change = nil on_change = nil
} }

View File

@ -384,7 +384,7 @@ local function handle_settings_buttons(this, fields, tabname, tabdata)
return ddhandled return ddhandled
end end
tab_settings = { return {
name = "settings", name = "settings",
caption = fgettext("Settings"), caption = fgettext("Settings"),
cbf_formspec = formspec, cbf_formspec = formspec,

View File

@ -145,9 +145,10 @@ end
-------------------------------------------------------------------------------- --------------------------------------------------------------------------------
tab_singleplayer = { return {
name = "singleplayer", name = "singleplayer",
caption = fgettext("Single Player"), caption = fgettext("Single Player"),
cbf_formspec = get_formspec, cbf_formspec = get_formspec,
cbf_button_handler = main_button_handler, cbf_button_handler = main_button_handler,
} on_change = on_change
}

View File

@ -123,10 +123,10 @@ local function main_button_handler(tabview, fields, name, tabdata)
end end
-------------------------------------------------------------------------------- --------------------------------------------------------------------------------
tab_texturepacks = { return {
name = "texturepacks", name = "texturepacks",
caption = fgettext("Texturepacks"), caption = fgettext("Texturepacks"),
cbf_formspec = get_formspec, cbf_formspec = get_formspec,
cbf_button_handler = main_button_handler, cbf_button_handler = main_button_handler,
on_change = nil on_change = nil
} }

View File

@ -147,6 +147,21 @@ if(CURSES_USE_NCURSESW)
set(CURSES_HAVE_NCURSESW_CURSES_H "CURSES_HAVE_NCURSESW_CURSES_H-NOTFOUND") set(CURSES_HAVE_NCURSESW_CURSES_H "CURSES_HAVE_NCURSESW_CURSES_H-NOTFOUND")
endif() endif()
endif() endif()
if(NOT DEFINED CURSES_HAVE_NCURSES_H)
if(EXISTS "${CURSES_INCLUDE_PATH}/ncurses.h")
set(CURSES_HAVE_NCURSES_H "${CURSES_INCLUDE_PATH}/ncurses.h")
else()
set(CURSES_HAVE_NCURSES_H "CURSES_HAVE_NCURSES_H-NOTFOUND")
endif()
endif()
if(NOT DEFINED CURSES_HAVE_CURSES_H)
if(EXISTS "${CURSES_INCLUDE_PATH}/curses.h")
set(CURSES_HAVE_CURSES_H "${CURSES_INCLUDE_PATH}/curses.h")
else()
set(CURSES_HAVE_CURSES_H "CURSES_HAVE_CURSES_H-NOTFOUND")
endif()
endif()
find_library(CURSES_FORM_LIBRARY form HINTS "${_cursesLibDir}" find_library(CURSES_FORM_LIBRARY form HINTS "${_cursesLibDir}"
DOC "Path to libform.so or .lib or .a") DOC "Path to libform.so or .lib or .a")

View File

@ -357,8 +357,13 @@ The mask is applied using binary AND.
#### `[colorize:<color>:<ratio>` #### `[colorize:<color>:<ratio>`
Colorize the textures with the given color. Colorize the textures with the given color.
`<color>` is specified as a `ColorString`. `<color>` is specified as a `ColorString`.
`<ratio>` is an int ranging from 0 to 255, and specifies how much of the `<ratio>` is an int ranging from 0 to 255 or the word "`alpha`". If
color to apply. If ommitted, the alpha will be used. it is an int, then it specifies how far to interpolate between the
colors where 0 is only the texture color and 255 is only `<color>`. If
omitted, the alpha of `<color>` will be used as the ratio. If it is
the word "`alpha`", then each texture pixel will contain the RGB of
`<color>` and the alpha of `<color>` multiplied by the alpha of the
texture pixel.
Sounds Sounds
------ ------
@ -940,6 +945,7 @@ Displays a horizontal bar made up of half-images.
* `number`: Number of items in the inventory to be displayed. * `number`: Number of items in the inventory to be displayed.
* `item`: Position of item that is selected. * `item`: Position of item that is selected.
* `direction` * `direction`
* `offset`: offset in pixels from position.
### `waypoint` ### `waypoint`
Displays distance to selected world position. Displays distance to selected world position.
@ -1865,6 +1871,7 @@ Call these functions only at load time!
* `modifier`: when true, the function should return the actual hp_change. * `modifier`: when true, the function should return the actual hp_change.
Note: modifiers only get a temporary hp_change that can be modified by later modifiers. Note: modifiers only get a temporary hp_change that can be modified by later modifiers.
modifiers can return true as a second argument to stop the execution of further functions. modifiers can return true as a second argument to stop the execution of further functions.
Non-modifiers receive the final hp change calculated by the modifiers.
* `minetest.register_on_respawnplayer(func(ObjectRef))` * `minetest.register_on_respawnplayer(func(ObjectRef))`
* Called when player is to be respawned * Called when player is to be respawned
* Called _before_ repositioning of player occurs * Called _before_ repositioning of player occurs

View File

@ -540,6 +540,12 @@ void Camera::drawNametags()
i = m_nametags.begin(); i = m_nametags.begin();
i != m_nametags.end(); ++i) { i != m_nametags.end(); ++i) {
Nametag *nametag = *i; Nametag *nametag = *i;
if (nametag->nametag_color.getAlpha() == 0) {
// Enforce hiding nametag,
// because if freetype is enabled, a grey
// shadow can remain.
continue;
}
v3f pos = nametag->parent_node->getPosition() + v3f(0.0, 1.1 * BS, 0.0); v3f pos = nametag->parent_node->getPosition() + v3f(0.0, 1.1 * BS, 0.0);
f32 transformed_pos[4] = { pos.X, pos.Y, pos.Z, 1.0f }; f32 transformed_pos[4] = { pos.X, pos.Y, pos.Z, 1.0f };
trans.multiplyWith1x4Matrix(transformed_pos); trans.multiplyWith1x4Matrix(transformed_pos);

View File

@ -265,7 +265,7 @@ Client::Client(
m_cache_smooth_lighting = g_settings->getBool("smooth_lighting"); m_cache_smooth_lighting = g_settings->getBool("smooth_lighting");
m_cache_enable_shaders = g_settings->getBool("enable_shaders"); m_cache_enable_shaders = g_settings->getBool("enable_shaders");
m_cache_use_tangent_vertices = m_cache_enable_shaders && ( m_cache_use_tangent_vertices = m_cache_enable_shaders && (
g_settings->getBool("enable_bumpmapping") || g_settings->getBool("enable_bumpmapping") ||
g_settings->getBool("enable_parallax_occlusion")); g_settings->getBool("enable_parallax_occlusion"));
} }

View File

@ -553,10 +553,12 @@ static void blit_with_alpha(video::IImage *src, video::IImage *dst,
static void blit_with_alpha_overlay(video::IImage *src, video::IImage *dst, static void blit_with_alpha_overlay(video::IImage *src, video::IImage *dst,
v2s32 src_pos, v2s32 dst_pos, v2u32 size); v2s32 src_pos, v2s32 dst_pos, v2u32 size);
// Like blit_with_alpha overlay, but uses an int to calculate the ratio // Apply a color to an image. Uses an int (0-255) to calculate the ratio.
// and modifies any destination pixels that are not fully transparent // If the ratio is 255 or -1 and keep_alpha is true, then it multiples the
static void blit_with_interpolate_overlay(video::IImage *src, video::IImage *dst, // color alpha with the destination alpha.
v2s32 src_pos, v2s32 dst_pos, v2u32 size, int ratio); // Otherwise, any pixels that are not fully transparent get the color alpha.
static void apply_colorize(video::IImage *dst, v2u32 dst_pos, v2u32 size,
video::SColor color, int ratio, bool keep_alpha);
// Apply a mask to an image // Apply a mask to an image
static void apply_mask(video::IImage *mask, video::IImage *dst, static void apply_mask(video::IImage *mask, video::IImage *dst,
@ -1643,27 +1645,17 @@ bool TextureSource::generateImagePart(std::string part_of_name,
video::SColor color; video::SColor color;
int ratio = -1; int ratio = -1;
bool keep_alpha = false;
if (!parseColorString(color_str, color, false)) if (!parseColorString(color_str, color, false))
return false; return false;
if (is_number(ratio_str)) if (is_number(ratio_str))
ratio = mystoi(ratio_str, 0, 255); ratio = mystoi(ratio_str, 0, 255);
else if (ratio_str == "alpha")
keep_alpha = true;
core::dimension2d<u32> dim = baseimg->getDimension(); apply_colorize(baseimg, v2u32(0, 0), baseimg->getDimension(), color, ratio, keep_alpha);
video::IImage *img = driver->createImage(video::ECF_A8R8G8B8, dim);
if (!img) {
errorstream << "generateImagePart(): Could not create image "
<< "for part_of_name=\"" << part_of_name
<< "\", cancelling." << std::endl;
return false;
}
img->fill(video::SColor(color));
// Overlay the colored image
blit_with_interpolate_overlay(img, baseimg, v2s32(0,0), v2s32(0,0), dim, ratio);
img->drop();
} }
else if (str_starts_with(part_of_name, "[applyfiltersformesh")) else if (str_starts_with(part_of_name, "[applyfiltersformesh"))
{ {
@ -1760,6 +1752,9 @@ static void blit_with_alpha_overlay(video::IImage *src, video::IImage *dst,
} }
} }
// This function has been disabled because it is currently unused.
// Feel free to re-enable if you find it handy.
#if 0
/* /*
Draw an image on top of an another one, using the specified ratio Draw an image on top of an another one, using the specified ratio
modify all partially-opaque pixels in the destination. modify all partially-opaque pixels in the destination.
@ -1786,6 +1781,45 @@ static void blit_with_interpolate_overlay(video::IImage *src, video::IImage *dst
} }
} }
} }
#endif
/*
Apply color to destination
*/
static void apply_colorize(video::IImage *dst, v2u32 dst_pos, v2u32 size,
video::SColor color, int ratio, bool keep_alpha)
{
u32 alpha = color.getAlpha();
video::SColor dst_c;
if ((ratio == -1 && alpha == 255) || ratio == 255) { // full replacement of color
if (keep_alpha) { // replace the color with alpha = dest alpha * color alpha
dst_c = color;
for (u32 y = dst_pos.Y; y < dst_pos.Y + size.Y; y++)
for (u32 x = dst_pos.X; x < dst_pos.X + size.X; x++) {
u32 dst_alpha = dst->getPixel(x, y).getAlpha();
if (dst_alpha > 0) {
dst_c.setAlpha(dst_alpha * alpha / 255);
dst->setPixel(x, y, dst_c);
}
}
} else { // replace the color including the alpha
for (u32 y = dst_pos.Y; y < dst_pos.Y + size.Y; y++)
for (u32 x = dst_pos.X; x < dst_pos.X + size.X; x++)
if (dst->getPixel(x, y).getAlpha() > 0)
dst->setPixel(x, y, color);
}
} else { // interpolate between the color and destination
float interp = (ratio == -1 ? color.getAlpha() / 255.0f : ratio / 255.0f);
for (u32 y = dst_pos.Y; y < dst_pos.Y + size.Y; y++)
for (u32 x = dst_pos.X; x < dst_pos.X + size.X; x++) {
dst_c = dst->getPixel(x, y);
if (dst_c.getAlpha() > 0) {
dst_c = color.getInterpolated(dst_c, interp);
dst->setPixel(x, y, dst_c);
}
}
}
}
/* /*
Apply mask to destination Apply mask to destination

View File

@ -332,8 +332,10 @@ collisionMoveResult collisionMoveSimple(Environment *env, IGameDef *gamedef,
// Do not move if world has not loaded yet, since custom node boxes // Do not move if world has not loaded yet, since custom node boxes
// are not available for collision detection. // are not available for collision detection.
if (!any_position_valid) if (!any_position_valid) {
*speed_f = v3f(0, 0, 0);
return result; return result;
}
} // tt2 } // tt2

View File

@ -44,7 +44,7 @@ DungeonGen::DungeonGen(Mapgen *mapgen, DungeonParams *dparams)
this->vm = mapgen->vm; this->vm = mapgen->vm;
#ifdef DGEN_USE_TORCHES #ifdef DGEN_USE_TORCHES
c_torch = ndef->getId("default:torch"); c_torch = mg->ndef->getId("default:torch");
#endif #endif
if (dparams) { if (dparams) {

View File

@ -41,7 +41,8 @@ with this program; if not, write to the Free Software Foundation, Inc.,
Hud::Hud(video::IVideoDriver *driver, scene::ISceneManager* smgr, Hud::Hud(video::IVideoDriver *driver, scene::ISceneManager* smgr,
gui::IGUIEnvironment* guienv, IGameDef *gamedef, LocalPlayer *player, gui::IGUIEnvironment* guienv, IGameDef *gamedef, LocalPlayer *player,
Inventory *inventory) { Inventory *inventory)
{
this->driver = driver; this->driver = driver;
this->smgr = smgr; this->smgr = smgr;
this->guienv = guienv; this->guienv = guienv;
@ -49,16 +50,15 @@ Hud::Hud(video::IVideoDriver *driver, scene::ISceneManager* smgr,
this->player = player; this->player = player;
this->inventory = inventory; this->inventory = inventory;
m_hud_scaling = g_settings->getFloat("hud_scaling");
m_screensize = v2u32(0, 0); m_screensize = v2u32(0, 0);
m_displaycenter = v2s32(0, 0); m_displaycenter = v2s32(0, 0);
m_hotbar_imagesize = floor(HOTBAR_IMAGE_SIZE * porting::getDisplayDensity() + 0.5); m_hotbar_imagesize = floor(HOTBAR_IMAGE_SIZE * porting::getDisplayDensity() + 0.5);
m_hotbar_imagesize *= g_settings->getFloat("hud_scaling"); m_hotbar_imagesize *= m_hud_scaling;
m_padding = m_hotbar_imagesize / 12; m_padding = m_hotbar_imagesize / 12;
const video::SColor hbar_color(255, 255, 255, 255); for (unsigned int i = 0; i < 4; i++)
for (unsigned int i=0; i < 4; i++ ){ hbar_colors[i] = video::SColor(255, 255, 255, 255);
hbar_colors[i] = hbar_color;
}
tsrc = gamedef->getTextureSource(); tsrc = gamedef->getTextureSource();
@ -102,7 +102,7 @@ Hud::Hud(video::IVideoDriver *driver, scene::ISceneManager* smgr,
if (mode == "box") { if (mode == "box") {
m_use_selection_mesh = false; m_use_selection_mesh = false;
m_selection_material.Thickness = m_selection_material.Thickness =
rangelim(g_settings->getS16("selectionbox_width"), 1, 5); rangelim(g_settings->getS16("selectionbox_width"), 1, 5);
} else if (mode == "halo") { } else if (mode == "halo") {
m_use_selection_mesh = true; m_use_selection_mesh = true;
m_selection_material.setTexture(0, tsrc->getTextureForMesh("halo.png")); m_selection_material.setTexture(0, tsrc->getTextureForMesh("halo.png"));
@ -196,25 +196,30 @@ void Hud::drawItem(const ItemStack &item, const core::rect<s32>& rect,
} }
//NOTE: selectitem = 0 -> no selected; selectitem 1-based //NOTE: selectitem = 0 -> no selected; selectitem 1-based
void Hud::drawItems(v2s32 upperleftpos, s32 itemcount, s32 offset, void Hud::drawItems(v2s32 upperleftpos, v2s32 screen_offset, s32 itemcount,
InventoryList *mainlist, u16 selectitem, u16 direction) s32 inv_offset, InventoryList *mainlist, u16 selectitem, u16 direction)
{ {
#ifdef HAVE_TOUCHSCREENGUI #ifdef HAVE_TOUCHSCREENGUI
if ( (g_touchscreengui) && (offset == 0)) if (g_touchscreengui && inv_offset == 0)
g_touchscreengui->resetHud(); g_touchscreengui->resetHud();
#endif #endif
s32 height = m_hotbar_imagesize + m_padding * 2; s32 height = m_hotbar_imagesize + m_padding * 2;
s32 width = (itemcount - offset) * (m_hotbar_imagesize + m_padding * 2); s32 width = (itemcount - inv_offset) * (m_hotbar_imagesize + m_padding * 2);
if (direction == HUD_DIR_TOP_BOTTOM || direction == HUD_DIR_BOTTOM_TOP) { if (direction == HUD_DIR_TOP_BOTTOM || direction == HUD_DIR_BOTTOM_TOP) {
width = m_hotbar_imagesize + m_padding * 2; s32 tmp = height;
height = (itemcount - offset) * (m_hotbar_imagesize + m_padding * 2); height = width;
width = tmp;
} }
// Position of upper left corner of bar // Position of upper left corner of bar
v2s32 pos = upperleftpos; v2s32 pos = screen_offset;
pos.X *= m_hud_scaling * porting::getDisplayDensity();
pos.Y *= m_hud_scaling * porting::getDisplayDensity();
pos += upperleftpos;
// Store hotbar_image in member variable, used by drawItem()
if (hotbar_image != player->hotbar_image) { if (hotbar_image != player->hotbar_image) {
hotbar_image = player->hotbar_image; hotbar_image = player->hotbar_image;
if (hotbar_image != "") if (hotbar_image != "")
@ -223,6 +228,7 @@ void Hud::drawItems(v2s32 upperleftpos, s32 itemcount, s32 offset,
use_hotbar_image = false; use_hotbar_image = false;
} }
// Store hotbar_selected_image in member variable, used by drawItem()
if (hotbar_selected_image != player->hotbar_selected_image) { if (hotbar_selected_image != player->hotbar_selected_image) {
hotbar_selected_image = player->hotbar_selected_image; hotbar_selected_image = player->hotbar_selected_image;
if (hotbar_selected_image != "") if (hotbar_selected_image != "")
@ -231,10 +237,10 @@ void Hud::drawItems(v2s32 upperleftpos, s32 itemcount, s32 offset,
use_hotbar_selected_image = false; use_hotbar_selected_image = false;
} }
/* draw customized item background */ // draw customized item background
if (use_hotbar_image) { if (use_hotbar_image) {
core::rect<s32> imgrect2(-m_padding/2, -m_padding/2, core::rect<s32> imgrect2(-m_padding/2, -m_padding/2,
width+m_padding/2, height+m_padding/2); width+m_padding/2, height+m_padding/2);
core::rect<s32> rect2 = imgrect2 + pos; core::rect<s32> rect2 = imgrect2 + pos;
video::ITexture *texture = tsrc->getTexture(hotbar_image); video::ITexture *texture = tsrc->getTexture(hotbar_image);
core::dimension2di imgsize(texture->getOriginalSize()); core::dimension2di imgsize(texture->getOriginalSize());
@ -243,29 +249,28 @@ void Hud::drawItems(v2s32 upperleftpos, s32 itemcount, s32 offset,
NULL, hbar_colors, true); NULL, hbar_colors, true);
} }
for (s32 i = offset; i < itemcount && (size_t)i < mainlist->getSize(); i++) // Draw items
{ core::rect<s32> imgrect(0, 0, m_hotbar_imagesize, m_hotbar_imagesize);
v2s32 steppos; for (s32 i = inv_offset; i < itemcount && (size_t)i < mainlist->getSize(); i++) {
s32 fullimglen = m_hotbar_imagesize + m_padding * 2; s32 fullimglen = m_hotbar_imagesize + m_padding * 2;
core::rect<s32> imgrect(0, 0, m_hotbar_imagesize, m_hotbar_imagesize); v2s32 steppos;
switch (direction) { switch (direction) {
case HUD_DIR_RIGHT_LEFT: case HUD_DIR_RIGHT_LEFT:
steppos = v2s32(-(m_padding + (i - offset) * fullimglen), m_padding); steppos = v2s32(-(m_padding + (i - inv_offset) * fullimglen), m_padding);
break; break;
case HUD_DIR_TOP_BOTTOM: case HUD_DIR_TOP_BOTTOM:
steppos = v2s32(m_padding, m_padding + (i - offset) * fullimglen); steppos = v2s32(m_padding, m_padding + (i - inv_offset) * fullimglen);
break; break;
case HUD_DIR_BOTTOM_TOP: case HUD_DIR_BOTTOM_TOP:
steppos = v2s32(m_padding, -(m_padding + (i - offset) * fullimglen)); steppos = v2s32(m_padding, -(m_padding + (i - inv_offset) * fullimglen));
break; break;
default: default:
steppos = v2s32(m_padding + (i - offset) * fullimglen, m_padding); steppos = v2s32(m_padding + (i - inv_offset) * fullimglen, m_padding);
break; break;
} }
drawItem(mainlist->getItem(i), (imgrect + pos + steppos), (i +1) == selectitem ); drawItem(mainlist->getItem(i), (imgrect + pos + steppos), (i + 1) == selectitem);
#ifdef HAVE_TOUCHSCREENGUI #ifdef HAVE_TOUCHSCREENGUI
if (g_touchscreengui) if (g_touchscreengui)
@ -275,7 +280,8 @@ void Hud::drawItems(v2s32 upperleftpos, s32 itemcount, s32 offset,
} }
void Hud::drawLuaElements(const v3s16 &camera_offset) { void Hud::drawLuaElements(const v3s16 &camera_offset)
{
u32 text_height = g_fontengine->getTextHeight(); u32 text_height = g_fontengine->getTextHeight();
irr::gui::IGUIFont* font = g_fontengine->getFont(); irr::gui::IGUIFont* font = g_fontengine->getFont();
for (size_t i = 0; i != player->maxHudId(); i++) { for (size_t i = 0; i != player->maxHudId(); i++) {
@ -326,7 +332,8 @@ void Hud::drawLuaElements(const v3s16 &camera_offset) {
break; } break; }
case HUD_ELEM_INVENTORY: { case HUD_ELEM_INVENTORY: {
InventoryList *inv = inventory->getList(e->text); InventoryList *inv = inventory->getList(e->text);
drawItems(pos, e->number, 0, inv, e->item, e->dir); drawItems(pos, v2s32(e->offset.X, e->offset.Y), e->number, 0,
inv, e->item, e->dir);
break; } break; }
case HUD_ELEM_WAYPOINT: { case HUD_ELEM_WAYPOINT: {
v3f p_pos = player->getPosition() / BS; v3f p_pos = player->getPosition() / BS;
@ -379,8 +386,7 @@ void Hud::drawStatbar(v2s32 pos, u16 corner, u16 drawdir, std::string texture,
if (size == v2s32()) { if (size == v2s32()) {
dstd = srcd; dstd = srcd;
} else { } else {
double size_factor = g_settings->getFloat("hud_scaling") * float size_factor = m_hud_scaling * porting::getDisplayDensity();
porting::getDisplayDensity();
dstd.Height = size.Y * size_factor; dstd.Height = size.Y * size_factor;
dstd.Width = size.X * size_factor; dstd.Width = size.X * size_factor;
offset.X *= size_factor; offset.X *= size_factor;
@ -448,25 +454,26 @@ void Hud::drawHotbar(u16 playeritem) {
if ( (float) width / (float) porting::getWindowSize().X <= if ( (float) width / (float) porting::getWindowSize().X <=
g_settings->getFloat("hud_hotbar_max_width")) { g_settings->getFloat("hud_hotbar_max_width")) {
if (player->hud_flags & HUD_FLAG_HOTBAR_VISIBLE) { if (player->hud_flags & HUD_FLAG_HOTBAR_VISIBLE) {
drawItems(pos, hotbar_itemcount, 0, mainlist, playeritem + 1, 0); drawItems(pos, v2s32(0, 0), hotbar_itemcount, 0, mainlist, playeritem + 1, 0);
} }
} } else {
else {
pos.X += width/4; pos.X += width/4;
v2s32 secondpos = pos; v2s32 secondpos = pos;
pos = pos - v2s32(0, m_hotbar_imagesize + m_padding); pos = pos - v2s32(0, m_hotbar_imagesize + m_padding);
if (player->hud_flags & HUD_FLAG_HOTBAR_VISIBLE) { if (player->hud_flags & HUD_FLAG_HOTBAR_VISIBLE) {
drawItems(pos, hotbar_itemcount/2, 0, mainlist, playeritem + 1, 0); drawItems(pos, v2s32(0, 0), hotbar_itemcount / 2, 0,
drawItems(secondpos, hotbar_itemcount, hotbar_itemcount/2, mainlist, playeritem + 1, 0); mainlist, playeritem + 1, 0);
drawItems(secondpos, v2s32(0, 0), hotbar_itemcount,
hotbar_itemcount / 2, mainlist, playeritem + 1, 0);
} }
} }
} }
void Hud::drawCrosshair() { void Hud::drawCrosshair()
{
if (use_crosshair_image) { if (use_crosshair_image) {
video::ITexture *crosshair = tsrc->getTexture("crosshair.png"); video::ITexture *crosshair = tsrc->getTexture("crosshair.png");
v2u32 size = crosshair->getOriginalSize(); v2u32 size = crosshair->getOriginalSize();
@ -489,9 +496,9 @@ void Hud::setSelectionPos(const v3f &pos, const v3s16 &camera_offset)
m_selection_pos = pos; m_selection_pos = pos;
m_selection_pos_with_offset = pos - intToFloat(camera_offset, BS); m_selection_pos_with_offset = pos - intToFloat(camera_offset, BS);
} }
void Hud::drawSelectionMesh() void Hud::drawSelectionMesh()
{ {
if (!m_use_selection_mesh) { if (!m_use_selection_mesh) {
// Draw 3D selection boxes // Draw 3D selection boxes
video::SMaterial oldmaterial = driver->getMaterial2D(); video::SMaterial oldmaterial = driver->getMaterial2D();
@ -502,9 +509,9 @@ void Hud::drawSelectionMesh()
aabb3f box = aabb3f( aabb3f box = aabb3f(
i->MinEdge + m_selection_pos_with_offset, i->MinEdge + m_selection_pos_with_offset,
i->MaxEdge + m_selection_pos_with_offset); i->MaxEdge + m_selection_pos_with_offset);
u32 r = (selectionbox_argb.getRed() * u32 r = (selectionbox_argb.getRed() *
m_selection_mesh_color.getRed() / 255); m_selection_mesh_color.getRed() / 255);
u32 g = (selectionbox_argb.getGreen() * u32 g = (selectionbox_argb.getGreen() *
m_selection_mesh_color.getGreen() / 255); m_selection_mesh_color.getGreen() / 255);
u32 b = (selectionbox_argb.getBlue() * u32 b = (selectionbox_argb.getBlue() *
@ -579,7 +586,7 @@ void Hud::updateSelectionMesh(const v3s16 &camera_offset)
void Hud::resizeHotbar() { void Hud::resizeHotbar() {
if (m_screensize != porting::getWindowSize()) { if (m_screensize != porting::getWindowSize()) {
m_hotbar_imagesize = floor(HOTBAR_IMAGE_SIZE * porting::getDisplayDensity() + 0.5); m_hotbar_imagesize = floor(HOTBAR_IMAGE_SIZE * porting::getDisplayDensity() + 0.5);
m_hotbar_imagesize *= g_settings->getFloat("hud_scaling"); m_hotbar_imagesize *= m_hud_scaling;
m_padding = m_hotbar_imagesize / 12; m_padding = m_hotbar_imagesize / 12;
m_screensize = porting::getWindowSize(); m_screensize = porting::getWindowSize();
m_displaycenter = v2s32(m_screensize.X/2,m_screensize.Y/2); m_displaycenter = v2s32(m_screensize.X/2,m_screensize.Y/2);

View File

@ -130,7 +130,7 @@ public:
void drawCrosshair(); void drawCrosshair();
void drawSelectionMesh(); void drawSelectionMesh();
void updateSelectionMesh(const v3s16 &camera_offset); void updateSelectionMesh(const v3s16 &camera_offset);
std::vector<aabb3f> *getSelectionBoxes() std::vector<aabb3f> *getSelectionBoxes()
{ return &m_selection_boxes; } { return &m_selection_boxes; }
@ -148,17 +148,18 @@ private:
void drawStatbar(v2s32 pos, u16 corner, u16 drawdir, std::string texture, void drawStatbar(v2s32 pos, u16 corner, u16 drawdir, std::string texture,
s32 count, v2s32 offset, v2s32 size=v2s32()); s32 count, v2s32 offset, v2s32 size=v2s32());
void drawItems(v2s32 upperleftpos, s32 itemcount, s32 offset, void drawItems(v2s32 upperleftpos, v2s32 screen_offset, s32 itemcount,
InventoryList *mainlist, u16 selectitem, u16 direction); s32 inv_offset, InventoryList *mainlist, u16 selectitem, u16 direction);
void drawItem(const ItemStack &item, const core::rect<s32>& rect, void drawItem(const ItemStack &item, const core::rect<s32>& rect,
bool selected); bool selected);
float m_hud_scaling; // cached minetest setting
v3s16 m_camera_offset; v3s16 m_camera_offset;
v2u32 m_screensize; v2u32 m_screensize;
v2s32 m_displaycenter; v2s32 m_displaycenter;
s32 m_hotbar_imagesize; s32 m_hotbar_imagesize; // Takes hud_scaling into account, updated by resizeHotbar()
s32 m_padding; s32 m_padding; // Takes hud_scaling into account, updated by resizeHotbar()
video::SColor hbar_colors[4]; video::SColor hbar_colors[4];
std::vector<aabb3f> m_selection_boxes; std::vector<aabb3f> m_selection_boxes;

View File

@ -58,7 +58,8 @@ MapgenFlat::MapgenFlat(int mapgenid, MapgenParams *params, EmergeManager *emerge
//// amount of elements to skip for the next index //// amount of elements to skip for the next index
//// for noise/height/biome maps (not vmanip) //// for noise/height/biome maps (not vmanip)
this->ystride = csize.X; this->ystride = csize.X;
this->zstride = csize.X * (csize.Y + 2); // 1-down overgeneration
this->zstride_1d = csize.X * (csize.Y + 1);
this->biomemap = new u8[csize.X * csize.Z]; this->biomemap = new u8[csize.X * csize.Z];
this->heightmap = new s16[csize.X * csize.Z]; this->heightmap = new s16[csize.X * csize.Z];
@ -80,8 +81,9 @@ MapgenFlat::MapgenFlat(int mapgenid, MapgenParams *params, EmergeManager *emerge
noise_filler_depth = new Noise(&sp->np_filler_depth, seed, csize.X, csize.Z); noise_filler_depth = new Noise(&sp->np_filler_depth, seed, csize.X, csize.Z);
//// 3D noise //// 3D noise
noise_cave1 = new Noise(&sp->np_cave1, seed, csize.X, csize.Y + 2, csize.Z); // 1-down overgeneraion
noise_cave2 = new Noise(&sp->np_cave2, seed, csize.X, csize.Y + 2, csize.Z); noise_cave1 = new Noise(&sp->np_cave1, seed, csize.X, csize.Y + 1, csize.Z);
noise_cave2 = new Noise(&sp->np_cave2, seed, csize.X, csize.Y + 1, csize.Z);
//// Biome noise //// Biome noise
noise_heat = new Noise(&params->np_biome_heat, seed, csize.X, csize.Z); noise_heat = new Noise(&params->np_biome_heat, seed, csize.X, csize.Z);
@ -566,19 +568,19 @@ void MapgenFlat::generateCaves(s16 max_stone_y)
for (s16 x = node_min.X; x <= node_max.X; x++, index2d++) { for (s16 x = node_min.X; x <= node_max.X; x++, index2d++) {
bool column_is_open = false; // Is column open to overground bool column_is_open = false; // Is column open to overground
bool is_tunnel = false; // Is tunnel or tunnel floor bool is_tunnel = false; // Is tunnel or tunnel floor
u32 vi = vm->m_area.index(x, node_max.Y + 1, z); u32 vi = vm->m_area.index(x, node_max.Y, z);
u32 index3d = (z - node_min.Z) * zstride + (csize.Y + 1) * ystride + u32 index3d = (z - node_min.Z) * zstride_1d + csize.Y * ystride +
(x - node_min.X); (x - node_min.X);
// Biome of column // Biome of column
Biome *biome = (Biome *)bmgr->getRaw(biomemap[index2d]); Biome *biome = (Biome *)bmgr->getRaw(biomemap[index2d]);
for (s16 y = node_max.Y + 1; y >= node_min.Y - 1; // Don't excavate the overgenerated stone at node_max.Y + 1,
y--, index3d -= ystride, vm->m_area.add_y(em, vi, -1)) { // this creates a 'roof' over the tunnel, preventing light in
// Don't excavate the overgenerated stone at node_max.Y + 1, // tunnels at mapchunk borders when generating mapchunks upwards.
// this creates a 'roof' over the tunnel, preventing light in // This 'roof' is removed when the mapchunk above is generated.
// tunnels at mapchunk borders when generating mapchunks upwards. for (s16 y = node_max.Y; y >= node_min.Y - 1; y--,
if (y > node_max.Y) index3d -= ystride,
continue; vm->m_area.add_y(em, vi, -1)) {
content_t c = vm->m_data[vi].getContent(); content_t c = vm->m_data[vi].getContent();
if (c == CONTENT_AIR || c == biome->c_water_top || if (c == CONTENT_AIR || c == biome->c_water_top ||
@ -589,17 +591,18 @@ void MapgenFlat::generateCaves(s16 max_stone_y)
// Ground // Ground
float d1 = contour(noise_cave1->result[index3d]); float d1 = contour(noise_cave1->result[index3d]);
float d2 = contour(noise_cave2->result[index3d]); float d2 = contour(noise_cave2->result[index3d]);
if (d1 * d2 > 0.3f && ndef->get(c).is_ground_content) { if (d1 * d2 > 0.3f && ndef->get(c).is_ground_content) {
// In tunnel and ground content, excavate // In tunnel and ground content, excavate
vm->m_data[vi] = MapNode(CONTENT_AIR); vm->m_data[vi] = MapNode(CONTENT_AIR);
is_tunnel = true; is_tunnel = true;
} else if (is_tunnel && column_is_open &&
(c == biome->c_filler || c == biome->c_stone)) {
// Tunnel entrance floor
vm->m_data[vi] = MapNode(biome->c_top);
column_is_open = false;
is_tunnel = false;
} else { } else {
// Not in tunnel or not ground content
if (is_tunnel && column_is_open &&
(c == biome->c_filler || c == biome->c_stone))
// Tunnel entrance floor
vm->m_data[vi] = MapNode(biome->c_top);
column_is_open = false; column_is_open = false;
is_tunnel = false; is_tunnel = false;
} }

View File

@ -60,7 +60,7 @@ public:
BiomeManager *bmgr; BiomeManager *bmgr;
int ystride; int ystride;
int zstride; int zstride_1d;
u32 spflags; u32 spflags;
v3s16 node_min; v3s16 node_min;

View File

@ -56,7 +56,8 @@ MapgenFractal::MapgenFractal(int mapgenid, MapgenParams *params, EmergeManager *
//// amount of elements to skip for the next index //// amount of elements to skip for the next index
//// for noise/height/biome maps (not vmanip) //// for noise/height/biome maps (not vmanip)
this->ystride = csize.X; this->ystride = csize.X;
this->zstride = csize.X * (csize.Y + 2); // 1-down overgeneration
this->zstride_1d = csize.X * (csize.Y + 1);
this->biomemap = new u8[csize.X * csize.Z]; this->biomemap = new u8[csize.X * csize.Z];
this->heightmap = new s16[csize.X * csize.Z]; this->heightmap = new s16[csize.X * csize.Z];
@ -85,8 +86,9 @@ MapgenFractal::MapgenFractal(int mapgenid, MapgenParams *params, EmergeManager *
noise_filler_depth = new Noise(&sp->np_filler_depth, seed, csize.X, csize.Z); noise_filler_depth = new Noise(&sp->np_filler_depth, seed, csize.X, csize.Z);
//// 3D terrain noise //// 3D terrain noise
noise_cave1 = new Noise(&sp->np_cave1, seed, csize.X, csize.Y + 2, csize.Z); // 1-down overgeneraion
noise_cave2 = new Noise(&sp->np_cave2, seed, csize.X, csize.Y + 2, csize.Z); noise_cave1 = new Noise(&sp->np_cave1, seed, csize.X, csize.Y + 1, csize.Z);
noise_cave2 = new Noise(&sp->np_cave2, seed, csize.X, csize.Y + 1, csize.Z);
//// Biome noise //// Biome noise
noise_heat = new Noise(&params->np_biome_heat, seed, csize.X, csize.Z); noise_heat = new Noise(&params->np_biome_heat, seed, csize.X, csize.Z);
@ -694,19 +696,19 @@ void MapgenFractal::generateCaves(s16 max_stone_y)
for (s16 x = node_min.X; x <= node_max.X; x++, index2d++) { for (s16 x = node_min.X; x <= node_max.X; x++, index2d++) {
bool column_is_open = false; // Is column open to overground bool column_is_open = false; // Is column open to overground
bool is_tunnel = false; // Is tunnel or tunnel floor bool is_tunnel = false; // Is tunnel or tunnel floor
u32 vi = vm->m_area.index(x, node_max.Y + 1, z); u32 vi = vm->m_area.index(x, node_max.Y, z);
u32 index3d = (z - node_min.Z) * zstride + (csize.Y + 1) * ystride + u32 index3d = (z - node_min.Z) * zstride_1d + csize.Y * ystride +
(x - node_min.X); (x - node_min.X);
// Biome of column // Biome of column
Biome *biome = (Biome *)bmgr->getRaw(biomemap[index2d]); Biome *biome = (Biome *)bmgr->getRaw(biomemap[index2d]);
for (s16 y = node_max.Y + 1; y >= node_min.Y - 1; // Don't excavate the overgenerated stone at node_max.Y + 1,
y--, index3d -= ystride, vm->m_area.add_y(em, vi, -1)) { // this creates a 'roof' over the tunnel, preventing light in
// Don't excavate the overgenerated stone at node_max.Y + 1, // tunnels at mapchunk borders when generating mapchunks upwards.
// this creates a 'roof' over the tunnel, preventing light in // This 'roof' is removed when the mapchunk above is generated.
// tunnels at mapchunk borders when generating mapchunks upwards. for (s16 y = node_max.Y; y >= node_min.Y - 1; y--,
if (y > node_max.Y) index3d -= ystride,
continue; vm->m_area.add_y(em, vi, -1)) {
content_t c = vm->m_data[vi].getContent(); content_t c = vm->m_data[vi].getContent();
if (c == CONTENT_AIR || c == biome->c_water_top || if (c == CONTENT_AIR || c == biome->c_water_top ||
@ -717,17 +719,18 @@ void MapgenFractal::generateCaves(s16 max_stone_y)
// Ground // Ground
float d1 = contour(noise_cave1->result[index3d]); float d1 = contour(noise_cave1->result[index3d]);
float d2 = contour(noise_cave2->result[index3d]); float d2 = contour(noise_cave2->result[index3d]);
if (d1 * d2 > 0.3f && ndef->get(c).is_ground_content) { if (d1 * d2 > 0.3f && ndef->get(c).is_ground_content) {
// In tunnel and ground content, excavate // In tunnel and ground content, excavate
vm->m_data[vi] = MapNode(CONTENT_AIR); vm->m_data[vi] = MapNode(CONTENT_AIR);
is_tunnel = true; is_tunnel = true;
} else if (is_tunnel && column_is_open &&
(c == biome->c_filler || c == biome->c_stone)) {
// Tunnel entrance floor
vm->m_data[vi] = MapNode(biome->c_top);
column_is_open = false;
is_tunnel = false;
} else { } else {
// Not in tunnel or not ground content
if (is_tunnel && column_is_open &&
(c == biome->c_filler || c == biome->c_stone))
// Tunnel entrance floor
vm->m_data[vi] = MapNode(biome->c_top);
column_is_open = false; column_is_open = false;
is_tunnel = false; is_tunnel = false;
} }

View File

@ -65,7 +65,7 @@ public:
BiomeManager *bmgr; BiomeManager *bmgr;
int ystride; int ystride;
int zstride; int zstride_1d;
u16 formula; u16 formula;
bool julia; bool julia;

View File

@ -54,7 +54,8 @@ MapgenV5::MapgenV5(int mapgenid, MapgenParams *params, EmergeManager *emerge)
// amount of elements to skip for the next index // amount of elements to skip for the next index
// for noise/height/biome maps (not vmanip) // for noise/height/biome maps (not vmanip)
this->ystride = csize.X; this->ystride = csize.X;
this->zstride = csize.X * (csize.Y + 2); // 1-down overgeneration
this->zstride_1d = csize.X * (csize.Y + 1);
this->biomemap = new u8[csize.X * csize.Z]; this->biomemap = new u8[csize.X * csize.Z];
this->heightmap = new s16[csize.X * csize.Z]; this->heightmap = new s16[csize.X * csize.Z];
@ -70,9 +71,11 @@ MapgenV5::MapgenV5(int mapgenid, MapgenParams *params, EmergeManager *emerge)
noise_height = new Noise(&sp->np_height, seed, csize.X, csize.Z); noise_height = new Noise(&sp->np_height, seed, csize.X, csize.Z);
// 3D terrain noise // 3D terrain noise
noise_cave1 = new Noise(&sp->np_cave1, seed, csize.X, csize.Y + 2, csize.Z); // 1-up 1-down overgeneration
noise_cave2 = new Noise(&sp->np_cave2, seed, csize.X, csize.Y + 2, csize.Z);
noise_ground = new Noise(&sp->np_ground, seed, csize.X, csize.Y + 2, csize.Z); noise_ground = new Noise(&sp->np_ground, seed, csize.X, csize.Y + 2, csize.Z);
// 1-down overgeneraion
noise_cave1 = new Noise(&sp->np_cave1, seed, csize.X, csize.Y + 1, csize.Z);
noise_cave2 = new Noise(&sp->np_cave2, seed, csize.X, csize.Y + 1, csize.Z);
// Biome noise // Biome noise
noise_heat = new Noise(&params->np_biome_heat, seed, csize.X, csize.Z); noise_heat = new Noise(&params->np_biome_heat, seed, csize.X, csize.Z);
@ -505,50 +508,6 @@ MgStoneType MapgenV5::generateBiomes(float *heat_map, float *humidity_map)
} }
void MapgenV5::generateCaves(int max_stone_y)
{
if (max_stone_y < node_min.Y)
return;
noise_cave1->perlinMap3D(node_min.X, node_min.Y - 1, node_min.Z);
noise_cave2->perlinMap3D(node_min.X, node_min.Y - 1, node_min.Z);
u32 index = 0;
for (s16 z = node_min.Z; z <= node_max.Z; z++)
for (s16 y = node_min.Y - 1; y <= node_max.Y + 1; y++) {
u32 vi = vm->m_area.index(node_min.X, y, z);
for (s16 x = node_min.X; x <= node_max.X; x++, vi++, index++) {
// Don't excavate the overgenerated stone at node_max.Y + 1,
// this creates a 'roof' over the tunnel, preventing light in
// tunnels at mapchunk borders when generating mapchunks upwards.
if (y > node_max.Y)
continue;
float d1 = contour(noise_cave1->result[index]);
float d2 = contour(noise_cave2->result[index]);
if (d1 * d2 > 0.125f) {
content_t c = vm->m_data[vi].getContent();
if (!ndef->get(c).is_ground_content || c == CONTENT_AIR)
continue;
vm->m_data[vi] = MapNode(CONTENT_AIR);
}
}
}
if (node_max.Y > MGV5_LARGE_CAVE_DEPTH)
return;
PseudoRandom ps(blockseed + 21343);
u32 bruises_count = ps.range(0, 2);
for (u32 i = 0; i < bruises_count; i++) {
CaveV5 cave(this, &ps);
cave.makeCave(node_min, node_max, max_stone_y);
}
}
void MapgenV5::dustTopNodes() void MapgenV5::dustTopNodes()
{ {
if (node_max.Y < water_level) if (node_max.Y < water_level)
@ -597,3 +556,72 @@ void MapgenV5::dustTopNodes()
} }
} }
} }
void MapgenV5::generateCaves(int max_stone_y)
{
if (max_stone_y < node_min.Y)
return;
noise_cave1->perlinMap3D(node_min.X, node_min.Y - 1, node_min.Z);
noise_cave2->perlinMap3D(node_min.X, node_min.Y - 1, node_min.Z);
v3s16 em = vm->m_area.getExtent();
u32 index2d = 0;
for (s16 z = node_min.Z; z <= node_max.Z; z++)
for (s16 x = node_min.X; x <= node_max.X; x++, index2d++) {
bool column_is_open = false; // Is column open to overground
bool is_tunnel = false; // Is tunnel or tunnel floor
// Indexes at column top (node_max.Y)
u32 vi = vm->m_area.index(x, node_max.Y, z);
u32 index3d = (z - node_min.Z) * zstride_1d + csize.Y * ystride +
(x - node_min.X);
// Biome of column
Biome *biome = (Biome *)bmgr->getRaw(biomemap[index2d]);
// Don't excavate the overgenerated stone at node_max.Y + 1,
// this creates a 'roof' over the tunnel, preventing light in
// tunnels at mapchunk borders when generating mapchunks upwards.
// This 'roof' is removed when the mapchunk above is generated.
for (s16 y = node_max.Y; y >= node_min.Y - 1; y--,
index3d -= ystride,
vm->m_area.add_y(em, vi, -1)) {
content_t c = vm->m_data[vi].getContent();
if (c == CONTENT_AIR || c == biome->c_water_top ||
c == biome->c_water) {
column_is_open = true;
continue;
}
// Ground
float d1 = contour(noise_cave1->result[index3d]);
float d2 = contour(noise_cave2->result[index3d]);
if (d1 * d2 > 0.125f && ndef->get(c).is_ground_content) {
// In tunnel and ground content, excavate
vm->m_data[vi] = MapNode(CONTENT_AIR);
is_tunnel = true;
} else {
// Not in tunnel or not ground content
if (is_tunnel && column_is_open &&
(c == biome->c_filler || c == biome->c_stone))
// Tunnel entrance floor
vm->m_data[vi] = MapNode(biome->c_top);
column_is_open = false;
is_tunnel = false;
}
}
}
if (node_max.Y > MGV5_LARGE_CAVE_DEPTH)
return;
PseudoRandom ps(blockseed + 21343);
u32 bruises_count = ps.range(0, 2);
for (u32 i = 0; i < bruises_count; i++) {
CaveV5 cave(this, &ps);
cave.makeCave(node_min, node_max, max_stone_y);
}
}

View File

@ -53,7 +53,7 @@ public:
BiomeManager *bmgr; BiomeManager *bmgr;
int ystride; int ystride;
int zstride; int zstride_1d;
u32 spflags; u32 spflags;
v3s16 node_min; v3s16 node_min;

View File

@ -59,7 +59,8 @@ MapgenV7::MapgenV7(int mapgenid, MapgenParams *params, EmergeManager *emerge)
//// amount of elements to skip for the next index //// amount of elements to skip for the next index
//// for noise/height/biome maps (not vmanip) //// for noise/height/biome maps (not vmanip)
this->ystride = csize.X; this->ystride = csize.X;
this->zstride = csize.X * (csize.Y + 2); // 1-down overgeneration
this->zstride_1d = csize.X * (csize.Y + 1);
this->biomemap = new u8[csize.X * csize.Z]; this->biomemap = new u8[csize.X * csize.Z];
this->heightmap = new s16[csize.X * csize.Z]; this->heightmap = new s16[csize.X * csize.Z];
@ -80,10 +81,12 @@ MapgenV7::MapgenV7(int mapgenid, MapgenParams *params, EmergeManager *emerge)
noise_ridge_uwater = new Noise(&sp->np_ridge_uwater, seed, csize.X, csize.Z); noise_ridge_uwater = new Noise(&sp->np_ridge_uwater, seed, csize.X, csize.Z);
//// 3d terrain noise //// 3d terrain noise
// 1-up 1-down overgeneration
noise_mountain = new Noise(&sp->np_mountain, seed, csize.X, csize.Y + 2, csize.Z); noise_mountain = new Noise(&sp->np_mountain, seed, csize.X, csize.Y + 2, csize.Z);
noise_ridge = new Noise(&sp->np_ridge, seed, csize.X, csize.Y + 2, csize.Z); noise_ridge = new Noise(&sp->np_ridge, seed, csize.X, csize.Y + 2, csize.Z);
noise_cave1 = new Noise(&sp->np_cave1, seed, csize.X, csize.Y + 2, csize.Z); // 1-down overgeneraion
noise_cave2 = new Noise(&sp->np_cave2, seed, csize.X, csize.Y + 2, csize.Z); noise_cave1 = new Noise(&sp->np_cave1, seed, csize.X, csize.Y + 1, csize.Z);
noise_cave2 = new Noise(&sp->np_cave2, seed, csize.X, csize.Y + 1, csize.Z);
//// Biome noise //// Biome noise
noise_heat = new Noise(&params->np_biome_heat, seed, csize.X, csize.Z); noise_heat = new Noise(&params->np_biome_heat, seed, csize.X, csize.Z);
@ -199,7 +202,7 @@ void MapgenV7Params::writeParams(Settings *settings) const
} }
/////////////////////////////////////// ///////////////////////////////////////////////////////////////////////////////
int MapgenV7::getSpawnLevelAtPoint(v2s16 p) int MapgenV7::getSpawnLevelAtPoint(v2s16 p)
@ -451,41 +454,6 @@ bool MapgenV7::getMountainTerrainFromMap(int idx_xyz, int idx_xz, s16 y)
} }
#if 0
void MapgenV7::carveRivers() {
MapNode n_air(CONTENT_AIR), n_water_source(c_water_source);
MapNode n_stone(c_stone);
u32 index = 0;
int river_depth = 4;
for (s16 z = node_min.Z; z <= node_max.Z; z++)
for (s16 x = node_min.X; x <= node_max.X; x++, index++) {
float terrain_mod = noise_terrain_mod->result[index];
NoiseParams *np = noise_terrain_river->np;
np.persist = noise_terrain_persist->result[index];
float terrain_river = NoisePerlin2DNoTxfm(np, x, z, seed);
float height = terrain_river * (1 - abs(terrain_mod)) *
noise_terrain_river->np.scale;
height = log(height * height); //log(h^3) is pretty interesting for terrain
s16 y = heightmap[index];
if (height < 1.0 && y > river_depth &&
y - river_depth >= node_min.Y && y <= node_max.Y) {
for (s16 ry = y; ry != y - river_depth; ry--) {
u32 vi = vm->m_area.index(x, ry, z);
vm->m_data[vi] = n_air;
}
u32 vi = vm->m_area.index(x, y - river_depth, z);
vm->m_data[vi] = n_water_source;
}
}
}
#endif
int MapgenV7::generateTerrain() int MapgenV7::generateTerrain()
{ {
s16 stone_surface_min_y; s16 stone_surface_min_y;
@ -765,6 +733,113 @@ void MapgenV7::dustTopNodes()
} }
void MapgenV7::generateCaves(s16 max_stone_y)
{
if (max_stone_y < node_min.Y)
return;
noise_cave1->perlinMap3D(node_min.X, node_min.Y - 1, node_min.Z);
noise_cave2->perlinMap3D(node_min.X, node_min.Y - 1, node_min.Z);
v3s16 em = vm->m_area.getExtent();
u32 index2d = 0;
for (s16 z = node_min.Z; z <= node_max.Z; z++)
for (s16 x = node_min.X; x <= node_max.X; x++, index2d++) {
bool column_is_open = false; // Is column open to overground
bool is_tunnel = false; // Is tunnel or tunnel floor
// Indexes at column top (node_max.Y)
u32 vi = vm->m_area.index(x, node_max.Y, z);
u32 index3d = (z - node_min.Z) * zstride_1d + csize.Y * ystride +
(x - node_min.X);
// Biome of column
Biome *biome = (Biome *)bmgr->getRaw(biomemap[index2d]);
// Don't excavate the overgenerated stone at node_max.Y + 1,
// this creates a 'roof' over the tunnel, preventing light in
// tunnels at mapchunk borders when generating mapchunks upwards.
// This 'roof' is removed when the mapchunk above is generated.
for (s16 y = node_max.Y; y >= node_min.Y - 1; y--,
index3d -= ystride,
vm->m_area.add_y(em, vi, -1)) {
content_t c = vm->m_data[vi].getContent();
if (c == CONTENT_AIR || c == biome->c_water_top ||
c == biome->c_water) {
column_is_open = true;
continue;
}
// Ground
float d1 = contour(noise_cave1->result[index3d]);
float d2 = contour(noise_cave2->result[index3d]);
if (d1 * d2 > 0.3f && ndef->get(c).is_ground_content) {
// In tunnel and ground content, excavate
vm->m_data[vi] = MapNode(CONTENT_AIR);
is_tunnel = true;
} else {
// Not in tunnel or not ground content
if (is_tunnel && column_is_open &&
(c == biome->c_filler || c == biome->c_stone))
// Tunnel entrance floor
vm->m_data[vi] = MapNode(biome->c_top);
column_is_open = false;
is_tunnel = false;
}
}
}
if (node_min.Y >= water_level)
return;
PseudoRandom ps(blockseed + 21343);
u32 bruises_count = ps.range(0, 2);
for (u32 i = 0; i < bruises_count; i++) {
CaveV7 cave(this, &ps);
cave.makeCave(node_min, node_max, max_stone_y);
}
}
///////////////////////////////////////////////////////////////
#if 0
void MapgenV7::carveRivers() {
MapNode n_air(CONTENT_AIR), n_water_source(c_water_source);
MapNode n_stone(c_stone);
u32 index = 0;
int river_depth = 4;
for (s16 z = node_min.Z; z <= node_max.Z; z++)
for (s16 x = node_min.X; x <= node_max.X; x++, index++) {
float terrain_mod = noise_terrain_mod->result[index];
NoiseParams *np = noise_terrain_river->np;
np.persist = noise_terrain_persist->result[index];
float terrain_river = NoisePerlin2DNoTxfm(np, x, z, seed);
float height = terrain_river * (1 - abs(terrain_mod)) *
noise_terrain_river->np.scale;
height = log(height * height); //log(h^3) is pretty interesting for terrain
s16 y = heightmap[index];
if (height < 1.0 && y > river_depth &&
y - river_depth >= node_min.Y && y <= node_max.Y) {
for (s16 ry = y; ry != y - river_depth; ry--) {
u32 vi = vm->m_area.index(x, ry, z);
vm->m_data[vi] = n_air;
}
u32 vi = vm->m_area.index(x, y - river_depth, z);
vm->m_data[vi] = n_water_source;
}
}
}
#endif
#if 0 #if 0
void MapgenV7::addTopNodes() void MapgenV7::addTopNodes()
{ {
@ -859,70 +934,3 @@ void MapgenV7::addTopNodes()
} }
} }
#endif #endif
void MapgenV7::generateCaves(s16 max_stone_y)
{
if (max_stone_y < node_min.Y)
return;
noise_cave1->perlinMap3D(node_min.X, node_min.Y - 1, node_min.Z);
noise_cave2->perlinMap3D(node_min.X, node_min.Y - 1, node_min.Z);
v3s16 em = vm->m_area.getExtent();
u32 index2d = 0;
for (s16 z = node_min.Z; z <= node_max.Z; z++)
for (s16 x = node_min.X; x <= node_max.X; x++, index2d++) {
bool column_is_open = false; // Is column open to overground
bool is_tunnel = false; // Is tunnel or tunnel floor
u32 vi = vm->m_area.index(x, node_max.Y + 1, z);
u32 index3d = (z - node_min.Z) * zstride + (csize.Y + 1) * ystride +
(x - node_min.X);
// Biome of column
Biome *biome = (Biome *)bmgr->getRaw(biomemap[index2d]);
for (s16 y = node_max.Y + 1; y >= node_min.Y - 1;
y--, index3d -= ystride, vm->m_area.add_y(em, vi, -1)) {
// Don't excavate the overgenerated stone at node_max.Y + 1,
// this creates a 'roof' over the tunnel, preventing light in
// tunnels at mapchunk borders when generating mapchunks upwards.
if (y > node_max.Y)
continue;
content_t c = vm->m_data[vi].getContent();
if (c == CONTENT_AIR || c == biome->c_water_top ||
c == biome->c_water) {
column_is_open = true;
continue;
}
// Ground
float d1 = contour(noise_cave1->result[index3d]);
float d2 = contour(noise_cave2->result[index3d]);
if (d1 * d2 > 0.3f && ndef->get(c).is_ground_content) {
// In tunnel and ground content, excavate
vm->m_data[vi] = MapNode(CONTENT_AIR);
is_tunnel = true;
} else if (is_tunnel && column_is_open &&
(c == biome->c_filler || c == biome->c_stone)) {
// Tunnel entrance floor
vm->m_data[vi] = MapNode(biome->c_top);
column_is_open = false;
is_tunnel = false;
} else {
column_is_open = false;
is_tunnel = false;
}
}
}
if (node_min.Y >= water_level)
return;
PseudoRandom ps(blockseed + 21343);
u32 bruises_count = ps.range(0, 2);
for (u32 i = 0; i < bruises_count; i++) {
CaveV7 cave(this, &ps);
cave.makeCave(node_min, node_max, max_stone_y);
}
}

View File

@ -59,7 +59,7 @@ public:
BiomeManager *bmgr; BiomeManager *bmgr;
int ystride; int ystride;
int zstride; int zstride_1d;
u32 spflags; u32 spflags;
v3s16 node_min; v3s16 node_min;

View File

@ -74,6 +74,8 @@ MapgenValleys::MapgenValleys(int mapgenid, MapgenParams *params, EmergeManager *
//// for noise/height/biome maps (not vmanip) //// for noise/height/biome maps (not vmanip)
this->ystride = csize.X; this->ystride = csize.X;
this->zstride = csize.X * (csize.Y + 2); this->zstride = csize.X * (csize.Y + 2);
// 1-down overgeneration
this->zstride_1d = csize.X * (csize.Y + 1);
this->biomemap = new u8[csize.X * csize.Z]; this->biomemap = new u8[csize.X * csize.Z];
this->heightmap = new s16[csize.X * csize.Z]; this->heightmap = new s16[csize.X * csize.Z];
@ -113,10 +115,12 @@ MapgenValleys::MapgenValleys(int mapgenid, MapgenParams *params, EmergeManager *
noise_valley_profile = new Noise(&sp->np_valley_profile, seed, csize.X, csize.Z); noise_valley_profile = new Noise(&sp->np_valley_profile, seed, csize.X, csize.Z);
//// 3D Terrain noise //// 3D Terrain noise
noise_cave1 = new Noise(&sp->np_cave1, seed, csize.X, csize.Y + 2, csize.Z); // 1-up 1-down overgeneration
noise_cave2 = new Noise(&sp->np_cave2, seed, csize.X, csize.Y + 2, csize.Z);
noise_inter_valley_fill = new Noise(&sp->np_inter_valley_fill, seed, csize.X, csize.Y + 2, csize.Z); noise_inter_valley_fill = new Noise(&sp->np_inter_valley_fill, seed, csize.X, csize.Y + 2, csize.Z);
noise_massive_caves = new Noise(&sp->np_massive_caves, seed, csize.X, csize.Y + 2, csize.Z); // 1-down overgeneraion
noise_cave1 = new Noise(&sp->np_cave1, seed, csize.X, csize.Y + 1, csize.Z);
noise_cave2 = new Noise(&sp->np_cave2, seed, csize.X, csize.Y + 1, csize.Z);
noise_massive_caves = new Noise(&sp->np_massive_caves, seed, csize.X, csize.Y + 1, csize.Z);
//// Biome noise //// Biome noise
noise_heat_blend = new Noise(&params->np_biome_heat_blend, seed, csize.X, csize.Z); noise_heat_blend = new Noise(&params->np_biome_heat_blend, seed, csize.X, csize.Z);
@ -885,7 +889,7 @@ void MapgenValleys::generateCaves(s16 max_stone_y)
if (node_max.Y <= massive_cave_depth) { if (node_max.Y <= massive_cave_depth) {
noise_massive_caves->perlinMap3D(node_min.X, node_min.Y - 1, node_min.Z); noise_massive_caves->perlinMap3D(node_min.X, node_min.Y - 1, node_min.Z);
for (s16 y = node_min.Y - 1; y <= node_max.Y + 1; y++) { for (s16 y = node_min.Y - 1; y <= node_max.Y; y++) {
float tcave = massive_cave_threshold; float tcave = massive_cave_threshold;
if (y < yblmin) { if (y < yblmin) {
@ -917,35 +921,30 @@ void MapgenValleys::generateCaves(s16 max_stone_y)
} }
u32 index_2d = 0; u32 index_2d = 0;
u32 index_3d = 0;
for (s16 z = node_min.Z; z <= node_max.Z; z++) for (s16 z = node_min.Z; z <= node_max.Z; z++)
for (s16 x = node_min.X; x <= node_max.X; x++, index_2d++) { for (s16 x = node_min.X; x <= node_max.X; x++, index_2d++) {
Biome *biome = (Biome *)bmgr->getRaw(biomemap[index_2d]); Biome *biome = (Biome *)bmgr->getRaw(biomemap[index_2d]);
bool air_above = false; bool tunnel_air_above = false;
bool underground = false; bool underground = false;
u32 index_data = vm->m_area.index(x, node_max.Y + 1, z); u32 index_data = vm->m_area.index(x, node_max.Y, z);
u32 index_3d = (z - node_min.Z) * zstride_1d + csize.Y * ystride + (x - node_min.X);
index_3d = (z - node_min.Z) * zstride + (csize.Y + 1) * ystride + (x - node_min.X);
// Dig caves on down loop to check for air above. // Dig caves on down loop to check for air above.
for (s16 y = node_max.Y + 1; // Don't excavate the overgenerated stone at node_max.Y + 1,
y >= node_min.Y - 1; // this creates a 'roof' over the tunnel, preventing light in
y--, index_3d -= ystride, vm->m_area.add_y(em, index_data, -1)) { // tunnels at mapchunk borders when generating mapchunks upwards.
// Don't excavate the overgenerated stone at node_max.Y + 1, // This 'roof' is removed when the mapchunk above is generated.
// this creates a 'roof' over the tunnel, preventing light in for (s16 y = node_max.Y; y >= node_min.Y - 1; y--,
// tunnels at mapchunk borders when generating mapchunks upwards. index_3d -= ystride,
if (y > node_max.Y) vm->m_area.add_y(em, index_data, -1)) {
continue;
float terrain = noise_terrain_height->result[index_2d]; float terrain = noise_terrain_height->result[index_2d];
// Saves some time. // Saves some time.
if (y > terrain + 10) { if (y > terrain + 10)
air_above = true;
continue; continue;
} else if (y < terrain - 40) { else if (y < terrain - 40)
underground = true; underground = true;
}
// Dig massive caves. // Dig massive caves.
if (node_max.Y <= massive_cave_depth if (node_max.Y <= massive_cave_depth
@ -953,6 +952,7 @@ void MapgenValleys::generateCaves(s16 max_stone_y)
> tcave_cache[y - node_min.Y + 1]) { > tcave_cache[y - node_min.Y + 1]) {
vm->m_data[index_data] = n_air; vm->m_data[index_data] = n_air;
made_a_big_one = true; made_a_big_one = true;
continue;
} }
content_t c = vm->m_data[index_data].getContent(); content_t c = vm->m_data[index_data].getContent();
@ -961,54 +961,51 @@ void MapgenValleys::generateCaves(s16 max_stone_y)
// River water is not set as ground content // River water is not set as ground content
// in the default game. This can produce strange results // in the default game. This can produce strange results
// when a cave undercuts a river. However, that's not for // when a tunnel undercuts a river. However, that's not for
// the mapgen to correct. Fix it in lua. // the mapgen to correct. Fix it in lua.
if (c == CONTENT_AIR) { if (d1 * d2 > 0.3f && ndef->get(c).is_ground_content) {
air_above = true; // in a tunnel
} else if (d1 * d2 > 0.3f && ndef->get(c).is_ground_content) {
// in a cave
vm->m_data[index_data] = n_air; vm->m_data[index_data] = n_air;
air_above = true; tunnel_air_above = true;
} else if (air_above && (c == biome->c_filler || c == biome->c_stone)) { } else if (c == biome->c_filler || c == biome->c_stone) {
// at the cave floor if (tunnel_air_above) {
s16 sr = ps.range(0,39); // at the tunnel floor
u32 j = index_data; s16 sr = ps.range(0, 39);
vm->m_area.add_y(em, j, 1); u32 j = index_data;
vm->m_area.add_y(em, j, 1);
if (sr > terrain - y) { if (sr > terrain - y) {
// Put dirt in caves near the surface. // Put dirt in tunnels near the surface.
if (underground) if (underground)
vm->m_data[index_data] = MapNode(biome->c_filler); vm->m_data[index_data] = MapNode(biome->c_filler);
else else
vm->m_data[index_data] = MapNode(biome->c_top); vm->m_data[index_data] = MapNode(biome->c_top);
} else if (sr < 3 && underground) { } else if (sr < 3 && underground) {
sr = abs(ps.next()); sr = abs(ps.next());
if (lava_features_lim > 0 && y <= lava_max_height if (lava_features_lim > 0 && y <= lava_max_height
&& c == biome->c_stone && sr < lava_chance) && c == biome->c_stone && sr < lava_chance)
vm->m_data[j] = n_lava; vm->m_data[j] = n_lava;
sr -= lava_chance; sr -= lava_chance;
// If sr < 0 then we should have already placed lava -- // If sr < 0 then we should have already placed lava --
// don't immediately dump water on it. // don't immediately dump water on it.
if (water_features_lim > 0 && y <= cave_water_max_height if (water_features_lim > 0 && y <= cave_water_max_height
&& sr >= 0 && sr < water_chance) && sr >= 0 && sr < water_chance)
vm->m_data[j] = n_water; vm->m_data[j] = n_water;
}
} }
air_above = false; tunnel_air_above = false;
underground = true;
} else if (c == biome->c_filler || c == biome->c_stone) {
air_above = false;
underground = true; underground = true;
} else { } else {
air_above = false; tunnel_air_above = false;
} }
} }
} }
if (node_max.Y <= large_cave_depth && (!made_a_big_one)) { if (node_max.Y <= large_cave_depth && !made_a_big_one) {
u32 bruises_count = ps.range(0, 2); u32 bruises_count = ps.range(0, 2);
for (u32 i = 0; i < bruises_count; i++) { for (u32 i = 0; i < bruises_count; i++) {
CaveV5 cave(this, &ps); CaveV5 cave(this, &ps);

View File

@ -106,6 +106,7 @@ private:
int ystride; int ystride;
int zstride; int zstride;
int zstride_1d;
float map_gen_limit; float map_gen_limit;

File diff suppressed because it is too large Load Diff

View File

@ -56,12 +56,10 @@
#ifndef SRP_H #ifndef SRP_H
#define SRP_H #define SRP_H
struct SRPVerifier; struct SRPVerifier;
struct SRPUser; struct SRPUser;
typedef enum typedef enum {
{
SRP_NG_1024, SRP_NG_1024,
SRP_NG_2048, SRP_NG_2048,
SRP_NG_4096, SRP_NG_4096,
@ -69,8 +67,7 @@ typedef enum
SRP_NG_CUSTOM SRP_NG_CUSTOM
} SRP_NGType; } SRP_NGType;
typedef enum typedef enum {
{
/*SRP_SHA1,*/ /*SRP_SHA1,*/
/*SRP_SHA224,*/ /*SRP_SHA224,*/
SRP_SHA256, SRP_SHA256,
@ -78,12 +75,13 @@ typedef enum
SRP_SHA512*/ SRP_SHA512*/
} SRP_HashAlgorithm; } SRP_HashAlgorithm;
typedef enum typedef enum {
{
SRP_OK,
SRP_ERR, SRP_ERR,
SRP_OK,
} SRP_Result; } SRP_Result;
// clang-format off
/* Sets the memory functions used by srp. /* Sets the memory functions used by srp.
* Note: this doesn't set the memory functions used by gmp, * Note: this doesn't set the memory functions used by gmp,
* but it is supported to have different functions for srp and gmp. * but it is supported to have different functions for srp and gmp.
@ -101,17 +99,18 @@ void srp_set_memory_functions(
* The n_hex and g_hex parameters should be 0 unless SRP_NG_CUSTOM is used for ng_type. * The n_hex and g_hex parameters should be 0 unless SRP_NG_CUSTOM is used for ng_type.
* If provided, they must contain ASCII text of the hexidecimal notation. * If provided, they must contain ASCII text of the hexidecimal notation.
* *
* If bytes_s == NULL, it is filled with random data. The caller is responsible for freeing. * If bytes_s == NULL, it is filled with random data.
* The caller is responsible for freeing.
* *
* Returns SRP_OK on success, and SRP_ERR on error. * Returns SRP_OK on success, and SRP_ERR on error.
* bytes_s might be in this case invalid, don't free it. * bytes_s might be in this case invalid, don't free it.
*/ */
SRP_Result srp_create_salted_verification_key( SRP_HashAlgorithm alg, SRP_Result srp_create_salted_verification_key(SRP_HashAlgorithm alg,
SRP_NGType ng_type, const char *username_for_verifier, SRP_NGType ng_type, const char *username_for_verifier,
const unsigned char *password, size_t len_password, const unsigned char *password, size_t len_password,
unsigned char **bytes_s, size_t *len_s, unsigned char **bytes_s, size_t *len_s,
unsigned char **bytes_v, size_t *len_v, unsigned char **bytes_v, size_t *len_v,
const char * n_hex, const char *g_hex ); const char *n_hex, const char *g_hex);
/* Out: bytes_B, len_B. /* Out: bytes_B, len_B.
* *
@ -132,54 +131,54 @@ struct SRPVerifier* srp_verifier_new(SRP_HashAlgorithm alg, SRP_NGType ng_type,
unsigned char** bytes_B, size_t *len_B, unsigned char** bytes_B, size_t *len_B,
const char* n_hex, const char* g_hex); const char* n_hex, const char* g_hex);
// clang-format on
void srp_verifier_delete( struct SRPVerifier* ver ); void srp_verifier_delete(struct SRPVerifier *ver);
// srp_verifier_verify_session must have been called before // srp_verifier_verify_session must have been called before
int srp_verifier_is_authenticated( struct SRPVerifier* ver ); int srp_verifier_is_authenticated(struct SRPVerifier *ver);
const char *srp_verifier_get_username(struct SRPVerifier *ver);
const char * srp_verifier_get_username( struct SRPVerifier* ver );
/* key_length may be null */ /* key_length may be null */
const unsigned char* srp_verifier_get_session_key( struct SRPVerifier* ver, const unsigned char *srp_verifier_get_session_key(
size_t *key_length ); struct SRPVerifier *ver, size_t *key_length);
size_t srp_verifier_get_session_key_length(struct SRPVerifier* ver);
size_t srp_verifier_get_session_key_length(struct SRPVerifier *ver);
/* Verifies session, on success, it writes bytes_HAMK. /* Verifies session, on success, it writes bytes_HAMK.
* user_M must be exactly srp_verifier_get_session_key_length() bytes in size * user_M must be exactly srp_verifier_get_session_key_length() bytes in size
*/ */
void srp_verifier_verify_session( struct SRPVerifier* ver, void srp_verifier_verify_session(
const unsigned char* user_M, unsigned char** bytes_HAMK ); struct SRPVerifier *ver, const unsigned char *user_M, unsigned char **bytes_HAMK);
/*******************************************************************************/ /*******************************************************************************/
/* The n_hex and g_hex parameters should be 0 unless SRP_NG_CUSTOM is used for ng_type */ /* The n_hex and g_hex parameters should be 0 unless SRP_NG_CUSTOM is used for ng_type */
struct SRPUser *srp_user_new(SRP_HashAlgorithm alg, SRP_NGType ng_type, struct SRPUser *srp_user_new(SRP_HashAlgorithm alg, SRP_NGType ng_type,
const char *username, const char *username_for_verifier, const char *username, const char *username_for_verifier,
const unsigned char *bytes_password, size_t len_password, const unsigned char *bytes_password, size_t len_password, const char *n_hex,
const char *n_hex, const char *g_hex); const char *g_hex);
void srp_user_delete(struct SRPUser * usr); void srp_user_delete(struct SRPUser *usr);
int srp_user_is_authenticated(struct SRPUser * usr); int srp_user_is_authenticated(struct SRPUser *usr);
const char *srp_user_get_username(struct SRPUser *usr);
const char* srp_user_get_username(struct SRPUser * usr);
/* key_length may be null */ /* key_length may be null */
const unsigned char* srp_user_get_session_key(struct SRPUser* usr, size_t* key_length); const unsigned char *srp_user_get_session_key(struct SRPUser *usr, size_t *key_length);
size_t srp_user_get_session_key_length(struct SRPUser* usr); size_t srp_user_get_session_key_length(struct SRPUser *usr);
/* Output: username, bytes_A, len_A. If you don't want it get written, set username to NULL. // clang-format off
/* Output: username, bytes_A, len_A.
* If you don't want it get written, set username to NULL.
* If bytes_a == NULL, random data is used for a. */ * If bytes_a == NULL, random data is used for a. */
SRP_Result srp_user_start_authentication(struct SRPUser* usr, char** username, SRP_Result srp_user_start_authentication(struct SRPUser* usr, char **username,
const unsigned char* bytes_a, size_t len_a, const unsigned char *bytes_a, size_t len_a,
unsigned char** bytes_A, size_t* len_A); unsigned char **bytes_A, size_t* len_A);
/* Output: bytes_M, len_M (len_M may be null and will always be /* Output: bytes_M, len_M (len_M may be null and will always be
* srp_user_get_session_key_length() bytes in size) */ * srp_user_get_session_key_length() bytes in size) */
@ -187,8 +186,9 @@ void srp_user_process_challenge(struct SRPUser *usr,
const unsigned char *bytes_s, size_t len_s, const unsigned char *bytes_s, size_t len_s,
const unsigned char *bytes_B, size_t len_B, const unsigned char *bytes_B, size_t len_B,
unsigned char **bytes_M, size_t *len_M); unsigned char **bytes_M, size_t *len_M);
// clang-format on
/* bytes_HAMK must be exactly srp_user_get_session_key_length() bytes in size */ /* bytes_HAMK must be exactly srp_user_get_session_key_length() bytes in size */
void srp_user_verify_session(struct SRPUser* usr, const unsigned char* bytes_HAMK); void srp_user_verify_session(struct SRPUser *usr, const unsigned char *bytes_HAMK);
#endif /* Include Guard */ #endif /* Include Guard */

Binary file not shown.

Before

Width:  |  Height:  |  Size: 6.1 KiB

After

Width:  |  Height:  |  Size: 5.9 KiB