Cherry-pick most commits since 15c0376

Commits not directly related to network changes were cherry-picked
on a best-effort basis, as some cause difficult merge conflicts.

Commits skipped over:
0d1eedcccc
aa474e4501
82482ecd9d
b214cde5b4
2066655aae
7e088fdfe3
40bf1d7b5f
1b2f64473e
7e56637ed0
64ff966bae
51057a56f5
009149a073
cf4045ff0f
e357577cb2
49f84b76bc
b019221c30
7880ff74b6
146f77fdb7
a704c04f00

Commits with conflicts:
038d3a31df
e9eda2b0d0
708337dfc2 ~~ modified client.cpp manually; shadow changes to packethandlers/client.cpp
36e8ba9ce2 ~~ modified main.cpp manually; add ALLOW_ZWRITE_ON_TRANSPARENT set
3b6480c5b0 ~~ modified server.cpp manually; change wrapDegrees -> modulo360f
5a5854ea9d
c09d026f05
3c91ad8fc2
This commit is contained in:
kwolekr 2015-03-07 16:25:15 -05:00
parent 32352e90da
commit 8e08e92eb4
139 changed files with 4975 additions and 3374 deletions

View File

@ -12,7 +12,7 @@ set(VERSION_EXTRA "" CACHE STRING "Stuff to append to version string")
# Also remember to set PROTOCOL_VERSION in clientserver.h when releasing
set(VERSION_MAJOR 0)
set(VERSION_MINOR 4)
set(VERSION_PATCH 11)
set(VERSION_PATCH 12)
set(VERSION_PATCH_ORIG ${VERSION_PATCH})
if(VERSION_EXTRA)

View File

@ -103,18 +103,30 @@ Compiling on GNU/Linux:
-----------------------
Install dependencies. Here's an example for Debian/Ubuntu:
$ apt-get install build-essential libirrlicht-dev cmake libbz2-dev libpng12-dev libjpeg8-dev libxxf86vm-dev libgl1-mesa-dev libsqlite3-dev libogg-dev libvorbis-dev libopenal-dev libcurl4-gnutls-dev libfreetype6-dev
$ sudo apt-get install build-essential libirrlicht-dev cmake libbz2-dev libpng12-dev libjpeg8-dev libxxf86vm-dev libgl1-mesa-dev libsqlite3-dev libogg-dev libvorbis-dev libopenal-dev libcurl4-gnutls-dev libfreetype6-dev zlib1g-dev libjsoncpp-dev
Download source, extract (this is the URL to the latest of source repository, which might not work at all times):
$ wget https://github.com/minetest/minetest/tarball/master -O master.tar.gz
You can install git for easily keeping your copy up to date.
If you dont want git, read below on how to get the source without git.
This is an example for installing git on Debian/Ubuntu:
$ sudo apt-get install git-core
Download source (this is the URL to the latest of source repository, which might not work at all times) using git:
$ git clone --depth 1 https://github.com/minetest/minetest.git
$ cd minetest
Download minetest_game (otherwise only the "Minimal development test" game is available) using git:
$ git clone --depth 1 https://github.com/minetest/minetest_game.git games/minetest_game
Download source, without using git:
$ wget https://github.com/minetest/minetest/archive/master.tar.gz
$ tar xf master.tar.gz
$ cd minetest-minetest-286edd4 (or similar)
$ cd minetest-master
Download minetest_game (otherwise only the "Minimal development test" game is available)
Download minetest_game, without using git:
$ cd games/
$ wget https://github.com/minetest/minetest_game/tarball/master -O minetest_game.tar.gz
$ tar xf minetest_game.tar.gz
$ mv minetest-minetest_game-* minetest_game
$ wget https://github.com/minetest/minetest_game/archive/master.tar.gz
$ tar xf master.tar.gz
$ mv minetest_game-master minetest_game
$ cd ..
Build a version that runs directly from the source directory:
@ -122,8 +134,7 @@ $ cmake . -DRUN_IN_PLACE=1
$ make -j2
Run it:
$ cd bin
$ ./minetest
$ ./bin/minetest
- Use cmake . -LH to see all CMake options and their current state
- If you want to install it system-wide (or are making a distribution package), you will want to use -DRUN_IN_PLACE=0

View File

@ -26,7 +26,7 @@ GAMES_TO_COPY = minetest_game
# Android Version code
# Increase for each build!
################################################################################
ANDROID_VERSION_CODE = 5
ANDROID_VERSION_CODE = 6
################################################################################
# toolchain config for arm old processors

View File

@ -102,7 +102,6 @@ LOCAL_C_INCLUDES := \
LOCAL_SRC_FILES := \
jni/src/ban.cpp \
jni/src/base64.cpp \
jni/src/camera.cpp \
jni/src/cavegen.cpp \
jni/src/chat.cpp \
@ -190,7 +189,6 @@ LOCAL_SRC_FILES := \
jni/src/server.cpp \
jni/src/serverlist.cpp \
jni/src/serverobject.cpp \
jni/src/sha1.cpp \
jni/src/shader.cpp \
jni/src/sky.cpp \
jni/src/socket.cpp \
@ -205,10 +203,12 @@ LOCAL_SRC_FILES := \
jni/src/version.cpp \
jni/src/voxel.cpp \
jni/src/voxelalgorithms.cpp \
jni/src/util/base64.cpp \
jni/src/util/directiontables.cpp \
jni/src/util/numeric.cpp \
jni/src/util/pointedthing.cpp \
jni/src/util/serialize.cpp \
jni/src/util/sha1.cpp \
jni/src/util/string.cpp \
jni/src/util/timetaker.cpp \
jni/src/touchscreengui.cpp \

View File

@ -545,12 +545,11 @@ function table.copy(t, seen)
seen = seen or {}
seen[t] = n
for k, v in pairs(t) do
n[type(k) ~= "table" and k or seen[k] or table.copy(k, seen)] =
type(v) ~= "table" and v or seen[v] or table.copy(v, seen)
n[(type(k) == "table" and (seen[k] or table.copy(k, seen))) or k] =
(type(v) == "table" and (seen[v] or table.copy(v, seen))) or v
end
return n
end
--------------------------------------------------------------------------------
-- mainmenu only functions
--------------------------------------------------------------------------------
@ -565,7 +564,7 @@ if INIT == "mainmenu" then
return nil
end
function fgettext(text, ...)
function fgettext_ne(text, ...)
text = core.gettext(text)
local arg = {n=select('#', ...), ...}
if arg.n >= 1 then
@ -587,7 +586,11 @@ if INIT == "mainmenu" then
end
text = result
end
return core.formspec_escape(text)
return text
end
function fgettext(text, ...)
return core.formspec_escape(fgettext_ne(text, ...))
end
end

View File

@ -115,11 +115,20 @@ function core.serialize(x)
function dump_val(x)
local tp = type(x)
if x == nil then return "nil"
elseif tp == "number" then return string.format("%d", x)
elseif tp == "string" then return string.format("%q", x)
elseif tp == "boolean" then return x and "true" or "false"
elseif tp == "function" then
return string.format("loadstring(%q)", string.dump(x))
elseif tp == "number" then
-- Serialize integers with string.format to prevent
-- scientific notation, which doesn't preserve
-- precision and breaks things like node position
-- hashes. Serialize floats normally.
if math.floor(x) == x then
return string.format("%d", x)
else
return tostring(x)
end
elseif tp == "table" then
local vals = {}
local idx_dumped = {}

View File

@ -229,21 +229,28 @@ core.register_chatcommand("setpassword", {
if not toname then
return false, "Name field required"
end
local actstr = "?"
local act_str_past = "?"
local act_str_pres = "?"
if not raw_password then
core.set_player_password(toname, "")
actstr = "cleared"
act_str_past = "cleared"
act_str_pres = "clears"
else
core.set_player_password(toname,
core.get_password_hash(toname,
raw_password))
actstr = "set"
act_str_past = "set"
act_str_pres = "sets"
end
if toname ~= name then
core.chat_send_player(toname, "Your password was "
.. actstr .. " by " .. name)
.. act_str_past .. " by " .. name)
end
return true, "Password of player \"" .. toname .. "\" " .. actstr
core.log("action", name .. " " .. act_str_pres
.. " password of " .. toname .. ".")
return true, "Password of player \"" .. toname .. "\" " .. act_str_past
end,
})
@ -257,6 +264,9 @@ core.register_chatcommand("clearpassword", {
return false, "Name field required"
end
core.set_player_password(toname, '')
core.log("action", name .. " clears password of " .. toname .. ".")
return true, "Password of player \"" .. toname .. "\" cleared"
end,
})
@ -404,13 +414,14 @@ core.register_chatcommand("set", {
})
core.register_chatcommand("deleteblocks", {
params = "[here] [<pos1> <pos2>]",
params = "(here [radius]) | (<pos1> <pos2>)",
description = "delete map blocks contained in area pos1 to pos2",
privs = {server=true},
func = function(name, param)
local p1 = {}
local p2 = {}
if param == "here" then
local args = param:split(" ")
if args[1] == "here" then
local player = core.get_player_by_name(name)
if player == nil then
core.log("error", "player is nil")
@ -418,6 +429,12 @@ core.register_chatcommand("deleteblocks", {
end
p1 = player:getpos()
p2 = p1
if #args >= 2 then
local radius = tonumber(args[2]) or 0
p1 = vector.add(p1, radius)
p2 = vector.subtract(p2, radius)
end
else
local pos1, pos2 = unpack(param:split(") ("))
if pos1 == nil or pos2 == nil then
@ -570,6 +587,9 @@ core.register_chatcommand("rollback_check", {
.. " seconds=86400=24h, limit=5)",
privs = {rollback=true},
func = function(name, param)
if not core.setting_getbool("enable_rollback_recording") then
return false, "Rollback functions are disabled."
end
local range, seconds, limit =
param:match("(%d+) *(%d*) *(%d*)")
range = tonumber(range) or 0
@ -583,6 +603,10 @@ core.register_chatcommand("rollback_check", {
local name = puncher:get_player_name()
core.chat_send_player(name, "Checking " .. core.pos_to_string(pos) .. "...")
local actions = core.rollback_get_node_actions(pos, range, seconds, limit)
if not actions then
core.chat_send_player(name, "Rollback functions are disabled")
return
end
local num_actions = #actions
if num_actions == 0 then
core.chat_send_player(name, "Nobody has touched"
@ -614,6 +638,9 @@ core.register_chatcommand("rollback", {
description = "revert actions of a player; default for <seconds> is 60",
privs = {rollback=true},
func = function(name, param)
if not core.setting_getbool("enable_rollback_recording") then
return false, "Rollback functions are disabled."
end
local target_name, seconds = string.match(param, ":([^ ]+) *(%d*)")
if not target_name then
local player_name = nil

View File

@ -106,7 +106,7 @@ function core.facedir_to_dir(facedir)
{x=0, y=1, z=0}})
--indexed into by a table of correlating facedirs
[({[0]=1, 2, 3, 4,
[({[0]=1, 2, 3, 4,
5, 2, 6, 4,
6, 2, 5, 4,
1, 5, 3, 6,
@ -238,7 +238,7 @@ function core.item_place_node(itemstack, placer, pointed_thing, param2)
core.log("action", placer:get_player_name() .. " places node "
.. def.name .. " at " .. core.pos_to_string(place_to))
local oldnode = core.get_node(place_to)
local newnode = {name = def.name, param1 = 0, param2 = param2}
@ -357,19 +357,37 @@ function core.item_drop(itemstack, dropper, pos)
return itemstack
end
function core.item_eat(hp_change, replace_with_item)
return function(itemstack, user, pointed_thing) -- closure
for _, callback in pairs(core.registered_on_item_eats) do
local result = callback(hp_change, replace_with_item, itemstack, user, pointed_thing)
if result then
return result
function core.do_item_eat(hp_change, replace_with_item, itemstack, user, pointed_thing)
for _, callback in pairs(core.registered_on_item_eats) do
local result = callback(hp_change, replace_with_item, itemstack, user, pointed_thing)
if result then
return result
end
end
if itemstack:take_item() ~= nil then
user:set_hp(user:get_hp() + hp_change)
if replace_with_item then
if itemstack:is_empty() then
itemstack:add_item(replace_with_item)
else
local inv = user:get_inventory()
if inv:room_for_item("main", {name=replace_with_item}) then
inv:add_item("main", replace_with_item)
else
local pos = user:getpos()
pos.y = math.floor(pos.y + 0.5)
core.add_item(pos, replace_with_item)
end
end
end
if itemstack:take_item() ~= nil then
user:set_hp(user:get_hp() + hp_change)
itemstack:add_item(replace_with_item) -- note: replace_with_item is optional
end
return itemstack
end
return itemstack
end
function core.item_eat(hp_change, replace_with_item)
return function(itemstack, user, pointed_thing) -- closure
return core.do_item_eat(hp_change, replace_with_item, itemstack, user, pointed_thing)
end
end
@ -425,7 +443,7 @@ function core.node_dig(pos, node, digger)
local wielded = digger:get_wielded_item()
local drops = core.get_node_drops(node.name, wielded:get_name())
local wdef = wielded:get_definition()
local tp = wielded:get_tool_capabilities()
local dp = core.get_dig_params(def.groups, tp)
@ -438,7 +456,7 @@ function core.node_dig(pos, node, digger)
end
end
digger:set_wielded_item(wielded)
-- Handle drops
core.handle_node_drops(pos, drops, digger)
@ -449,7 +467,7 @@ function core.node_dig(pos, node, digger)
-- Remove node and update
core.remove_node(pos)
-- Run callback
if def.after_dig_node then
-- Copy pos and node because callback can modify them
@ -507,7 +525,7 @@ core.nodedef_default = {
on_dig = redef_wrapper(core, 'node_dig'), -- core.node_dig
on_receive_fields = nil,
on_metadata_inventory_move = core.node_metadata_inventory_move_allow_all,
on_metadata_inventory_offer = core.node_metadata_inventory_offer_allow_all,
on_metadata_inventory_take = core.node_metadata_inventory_take_allow_all,

View File

@ -16,9 +16,15 @@
--51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
--------------------------------------------------------------------------------
-- Global menu data
---------------------------------------------------------------------------------
--------------------------------------------------------------------------------
menudata = {}
--------------------------------------------------------------------------------
-- Local cached values
--------------------------------------------------------------------------------
local min_supp_proto = core.get_min_supp_proto()
local max_supp_proto = core.get_max_supp_proto()
--------------------------------------------------------------------------------
-- Menu helper functions
--------------------------------------------------------------------------------
@ -42,6 +48,25 @@ function image_column(tooltip, flagname)
"1=" .. core.formspec_escape(defaulttexturedir .. "server_flags_" .. flagname .. ".png")
end
--------------------------------------------------------------------------------
function order_favorite_list(list)
local res = {}
--orders the favorite list after support
for i=1,#list,1 do
local fav = list[i]
if is_server_protocol_compat(fav.proto_min, fav.proto_max) then
table.insert(res, fav)
end
end
for i=1,#list,1 do
local fav = list[i]
if not is_server_protocol_compat(fav.proto_min, fav.proto_max) then
table.insert(res, fav)
end
end
return res
end
--------------------------------------------------------------------------------
function render_favorite(spec,render_details)
local text = ""
@ -68,6 +93,7 @@ function render_favorite(spec,render_details)
end
local details = ""
local grey_out = not is_server_protocol_compat(spec.proto_max, spec.proto_min)
if spec.clients ~= nil and spec.clients_max ~= nil then
local clients_color = ''
@ -87,11 +113,17 @@ function render_favorite(spec,render_details)
clients_color = '#ffba97' -- 90-100%: orange
end
if grey_out then
clients_color = '#aaaaaa'
end
details = details ..
clients_color .. ',' ..
render_client_count(spec.clients) .. ',' ..
'/,' ..
render_client_count(spec.clients_max) .. ','
elseif grey_out then
details = details .. '#aaaaaa,?,/,?,'
else
details = details .. ',?,/,?,'
end
@ -114,7 +146,7 @@ function render_favorite(spec,render_details)
details = details .. "0,"
end
return details .. text
return details .. (grey_out and '#aaaaaa,' or ',') .. text
end
--------------------------------------------------------------------------------
@ -195,7 +227,7 @@ function asyncOnlineFavourites()
nil,
function(result)
if core.setting_getbool("public_serverlist") then
menudata.favorites = result
menudata.favorites = order_favorite_list(result)
core.event_handler("Refresh")
end
end
@ -225,3 +257,21 @@ function text2textlist(xpos,ypos,width,height,tl_name,textlen,text,transparency)
return retval
end
--------------------------------------------------------------------------------
function is_server_protocol_compat(proto_min, proto_max)
return not ((min_supp_proto > (proto_max or 24)) or (max_supp_proto < (proto_min or 13)))
end
--------------------------------------------------------------------------------
function is_server_protocol_compat_or_error(proto_min, proto_max)
if not is_server_protocol_compat(proto_min, proto_max) then
gamedata.errormessage = fgettext_ne("Protocol version mismatch, server " ..
((proto_min ~= proto_max) and "supports protocols between $1 and $2" or "enforces protocol version $1") ..
", we " ..
((min_supp_proto ~= max_supp_proto) and "support protocols between version $3 and $4." or "only support protocol version $3"),
proto_min or 13, proto_max or 24, min_supp_proto, max_supp_proto)
return false
end
return true
end

View File

@ -16,6 +16,9 @@
--51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
--------------------------------------------------------------------------------
local function modname_valid(name)
return not name:find("[^a-z0-9_]")
end
local function get_formspec(data)
@ -195,10 +198,12 @@ local function handle_buttons(this, fields)
for i,mod in ipairs(rawlist) do
if not mod.is_modpack and
mod.typ ~= "game_mod" then
if mod.enabled then
worldfile:set("load_mod_"..mod.name, "true")
if modname_valid(mod.name) then
worldfile:set("load_mod_"..mod.name, tostring(mod.enabled))
else
worldfile:set("load_mod_"..mod.name, "false")
if mod.enabled then
gamedata.errormessage = fgettext_ne("Failed to enable mod \"$1\" as it contains disallowed characters. Only chararacters [a-z0-9_] are allowed.", mod.name)
end
end
mods["load_mod_"..mod.name] = nil
end

View File

@ -90,6 +90,8 @@ local function create_world_buttonhandler(this, fields)
local message = nil
core.setting_set("fixed_map_seed", fields["te_seed"])
if not menudata.worldlist:uid_exists_raw(worldname) then
core.setting_set("mg_name",fields["dd_mapgen"])
message = core.create_world(worldname,gameindex)
@ -97,8 +99,6 @@ local function create_world_buttonhandler(this, fields)
message = fgettext("A world named \"$1\" already exists", worldname)
end
core.setting_set("fixed_map_seed", fields["te_seed"])
if message ~= nil then
gamedata.errormessage = message
else

View File

@ -139,7 +139,11 @@ local function init_globals()
tv_main:add(tab_credits)
tv_main:set_global_event_handler(main_event_handler)
tv_main:set_fixed_size(false)
if PLATFORM ~= "Android" then
tv_main:set_fixed_size(true)
else
tv_main:set_fixed_size(false)
end
if not (PLATFORM == "Android") then
tv_main:set_tab(core.setting_get("maintab_LAST"))

View File

@ -122,35 +122,36 @@ end
function modstore.showdownloading(title)
local new_dlg = dialog_create("store_downloading",
function(data)
return "size[6,2]label[0.25,0.75;" .. fgettext("Downloading") ..
" " .. data.title .. " " ..
fgettext("please wait...") .. "]"
return "size[6,2]label[0.25,0.75;" ..
fgettext("Downloading $1, please wait...", data.title) .. "]"
end,
function(this,fields)
if fields["btn_hidden_close_download"] ~= nil then
if fields["btn_hidden_close_download"].successfull then
modstore.lastmodentry = fields["btn_hidden_close_download"]
modstore.successfulldialog()
modstore.successfulldialog(this)
else
this.parent:show()
this:delete()
modstore.lastmodtitle = ""
end
this:delete()
return true
end
return false
end,
nil,
modstore.tv_store)
nil)
new_dlg:set_parent(modstore.tv_store)
modstore.tv_store:hide()
new_dlg.data.title = title
new_dlg:show()
end
--------------------------------------------------------------------------------
-- @function [parent=#modstore] successfulldialog
function modstore.successfulldialog()
function modstore.successfulldialog(downloading_dlg)
local new_dlg = dialog_create("store_downloading",
function(data)
local retval = ""
@ -158,18 +159,16 @@ function modstore.successfulldialog()
if modstore.lastmodentry ~= nil then
retval = retval .. "label[0,0.25;" .. fgettext("Successfully installed:") .. "]"
retval = retval .. "label[3,0.25;" .. modstore.lastmodentry.moddetails.title .. "]"
retval = retval .. "label[0,0.75;" .. fgettext("Shortname:") .. "]"
retval = retval .. "label[3,0.75;" .. core.formspec_escape(modstore.lastmodentry.moddetails.basename) .. "]"
end
retval = retval .. "button[2.5,1.5;1,0.5;btn_confirm_mod_successfull;" .. fgettext("ok") .. "]"
retval = retval .. "button[2.2,1.5;1.5,0.5;btn_confirm_mod_successfull;" .. fgettext("Ok") .. "]"
return retval
end,
function(this,fields)
if fields["btn_confirm_mod_successfull"] ~= nil then
this.parent:show()
this:hide()
downloading_dlg:delete()
this:delete()
return true
@ -177,10 +176,10 @@ function modstore.successfulldialog()
return false
end,
nil,
modstore.tv_store)
nil)
new_dlg.data.title = title
new_dlg:set_parent(modstore.tv_store)
modstore.tv_store:hide()
new_dlg:show()
end
@ -217,7 +216,9 @@ function modstore.handle_buttons(parent, fields, name, data)
end
if fields["btn_modstore_close"] then
local maintab = ui.find_by_name("maintab")
parent:hide()
maintab:show()
return true
end
@ -228,12 +229,7 @@ function modstore.handle_buttons(parent, fields, name, data)
for i=1,#modstore.modlist_unsorted.data,1 do
if modstore.modlist_unsorted.data[i].id == modid then
local moddetails = modstore.modlist_unsorted.data[i].details
if modstore.lastmodtitle ~= "" then
modstore.lastmodtitle = modstore.lastmodtitle .. ", "
end
modstore.lastmodtitle = modstore.lastmodtitle .. moddetails.title
modstore.lastmodtitle = moddetails.title
if not core.handle_async(
function(param)
@ -281,7 +277,7 @@ function modstore.handle_buttons(parent, fields, name, data)
texturename = modstore.modlist_unsorted.data[i].texturename
},
function(result)
print("Result from async: " .. dump(result.successfull))
--print("Result from async: " .. dump(result.successfull))
if result.successfull then
modmgr.installmod(result.filename,result.moddetails.basename)
os.remove(result.filename)
@ -299,7 +295,7 @@ function modstore.handle_buttons(parent, fields, name, data)
print("ERROR: async event failed")
gamedata.errormessage = "Failed to download " .. modstore.lastmodtitle
end
parent:hide()
modstore.showdownloading(modstore.lastmodtitle)
return true
end
@ -391,7 +387,7 @@ function modstore.getscreenshot(ypos,listentry)
listentry.details.screenshot_url == "") then
if listentry.texturename == nil then
listentry.texturename = modstore.basetexturedir .. "no_screenshot.png"
listentry.texturename = defaulttexturedir .. "no_screenshot.png"
end
return "image[0,".. ypos .. ";3,2;" ..

View File

@ -57,7 +57,7 @@ local function get_formspec(tabview, name, tabdata)
end
if modscreenshot == nil then
modscreenshot = modstore.basetexturedir .. "no_screenshot.png"
modscreenshot = defaulttexturedir .. "no_screenshot.png"
end
retval = retval
@ -96,7 +96,7 @@ local function get_formspec(tabview, name, tabdata)
else
--show dependencies
retval = retval .. ",Depends:,"
retval = retval .. "," .. fgettext("Depends:") .. ","
local toadd = modmgr.get_dependencies(selected_mod.path)

View File

@ -59,9 +59,10 @@ local function get_formspec(tabview, name, tabdata)
"text,align=right;" .. -- clients
"text,align=center,padding=0.25;" .. -- "/"
"text,align=right,padding=0.25;" .. -- clients_max
image_column("Creative mode", "creative") .. ",padding=1;" ..
image_column("Damage enabled", "damage") .. ",padding=0.25;" ..
image_column("PvP enabled", "pvp") .. ",padding=0.25;" ..
image_column(fgettext("Creative mode"), "creative") .. ",padding=1;" ..
image_column(fgettext("Damage enabled"), "damage") .. ",padding=0.25;" ..
image_column(fgettext("PvP enabled"), "pvp") .. ",padding=0.25;" ..
"color,span=1;" ..
"text,padding=1]" -- name
else
retval = retval .. "tablecolumns[text]"
@ -88,7 +89,6 @@ end
--------------------------------------------------------------------------------
local function main_button_handler(tabview, fields, name, tabdata)
if fields["te_name"] ~= nil then
gamedata.playername = fields["te_name"]
core.setting_set("name", fields["te_name"])
@ -98,6 +98,10 @@ local function main_button_handler(tabview, fields, name, tabdata)
local event = core.explode_table_event(fields["favourites"])
if event.type == "DCL" then
if event.row <= #menudata.favorites then
if not is_server_protocol_compat_or_error(menudata.favorites[event.row].proto_min,
menudata.favorites[event.row].proto_max) then
return true
end
gamedata.address = menudata.favorites[event.row].address
gamedata.port = menudata.favorites[event.row].port
gamedata.playername = fields["te_name"]
@ -189,7 +193,7 @@ local function main_button_handler(tabview, fields, name, tabdata)
local current_favourite = core.get_table_index("favourites")
if current_favourite == nil then return end
core.delete_favorite(current_favourite)
menudata.favorites = core.get_favorites()
menudata.favorites = order_favorite_list(core.get_favorites())
tabdata.fav_selected = nil
core.setting_set("address","")
@ -198,8 +202,9 @@ local function main_button_handler(tabview, fields, name, tabdata)
return true
end
if fields["btn_mp_connect"] ~= nil or
fields["key_enter"] ~= nil then
if (fields["btn_mp_connect"] ~= nil or
fields["key_enter"] ~= nil) and fields["te_address"] ~= nil and
fields["te_port"] ~= nil then
gamedata.playername = fields["te_name"]
gamedata.password = fields["te_pwd"]
@ -214,6 +219,11 @@ local function main_button_handler(tabview, fields, name, tabdata)
gamedata.servername = menudata.favorites[fav_idx].name
gamedata.serverdescription = menudata.favorites[fav_idx].description
if not is_server_protocol_compat_or_error(menudata.favorites[fav_idx].proto_min,
menudata.favorites[fav_idx].proto_max)then
return true
end
else
gamedata.servername = ""
gamedata.serverdescription = ""

View File

@ -42,9 +42,10 @@ local function get_formspec(tabview, name, tabdata)
"text,align=right;" .. -- clients
"text,align=center,padding=0.25;" .. -- "/"
"text,align=right,padding=0.25;" .. -- clients_max
image_column("Creative mode", "creative") .. ",padding=1;" ..
image_column("Damage enabled", "damage") .. ",padding=0.25;" ..
image_column("PvP enabled", "pvp") .. ",padding=0.25;" ..
image_column(fgettext("Creative mode"), "creative") .. ",padding=1;" ..
image_column(fgettext("Damage enabled"), "damage") .. ",padding=0.25;" ..
image_column(fgettext("PvP enabled"), "pvp") .. ",padding=0.25;" ..
"color,span=1;" ..
"text,padding=1]" -- name
else
retval = retval .. "tablecolumns[text]"
@ -87,7 +88,6 @@ local function get_formspec(tabview, name, tabdata)
end
--------------------------------------------------------------------------------
local function main_button_handler(tabview, fields, name, tabdata)
if fields["btn_start_singleplayer"] then
@ -159,6 +159,11 @@ local function main_button_handler(tabview, fields, name, tabdata)
gamedata.servername = menudata.favorites[fav_idx].name
gamedata.serverdescription = menudata.favorites[fav_idx].description
if not is_server_protocol_compat_or_error(menudata.favorites[fav_idx].proto_min,
menudata.favorites[fav_idx].proto_max) then
return true
end
else
gamedata.servername = ""
gamedata.serverdescription = ""

View File

@ -44,7 +44,7 @@ else()
/usr/include/irrlicht
)
FIND_LIBRARY(IRRLICHT_LIBRARY NAMES libIrrlicht.a Irrlicht
FIND_LIBRARY(IRRLICHT_LIBRARY NAMES libIrrlicht.so libIrrlicht.a Irrlicht
PATHS
/usr/local/lib
/usr/lib

View File

@ -1,4 +1,4 @@
Minetest Lua Modding API Reference 0.4.11
Minetest Lua Modding API Reference 0.4.12
=========================================
* More information at <http://www.minetest.net/>
* Developer Wiki: <http://dev.minetest.net/>
@ -20,7 +20,8 @@ source code patches to <celeron55@gmail.com>.
Programming in Lua
------------------
If you have any difficulty in understanding this, please read [Programming in Lua](http://www.lua.org/pil/).
If you have any difficulty in understanding this, please read
[Programming in Lua](http://www.lua.org/pil/).
Startup
-------
@ -593,13 +594,14 @@ set to level from `param2`.
Meshes
------
If drawtype `mesh` is used, tiles should hold model materials textures.
Only static meshes are implemented.
Only static meshes are implemented.
For supported model formats see Irrlicht engine documentation.
Noise Parameters
----------------
Noise Parameters, or commonly called "`NoiseParams`", define the properties of perlin noise.
Noise Parameters, or commonly called "`NoiseParams`", define the properties of
perlin noise.
### `offset`
Offset that the noise is translated by (i.e. added) after calculation.
@ -679,24 +681,26 @@ All default ores are of the uniformly-distributed scatter type.
Randomly chooses a location and generates a cluster of ore.
If `noise_params` is specified, the ore will be placed if the 3D perlin noise at
that point is greater than the `noise_threshold`, giving the ability to create a non-equal
distribution of ore.
that point is greater than the `noise_threshold`, giving the ability to create
a non-equal distribution of ore.
### `sheet`
Creates a sheet of ore in a blob shape according to the 2D perlin noise described by `noise_params`.
The relative height of the sheet can be controlled by the same perlin noise as well, by specifying
a non-zero `scale` parameter in `noise_params`.
Creates a sheet of ore in a blob shape according to the 2D perlin noise
described by `noise_params`. The relative height of the sheet can be
controlled by the same perlin noise as well, by specifying a non-zero
`scale` parameter in `noise_params`.
**IMPORTANT**: The noise is not transformed by `offset` or `scale` when comparing against the noise
threshold, but scale is used to determine relative height.
**IMPORTANT**: The noise is not transformed by `offset` or `scale` when comparing
against the noise threshold, but scale is used to determine relative height.
The height of the blob is randomly scattered, with a maximum height of `clust_size`.
`clust_scarcity` and `clust_num_ores` are ignored.
This is essentially an improved version of the so-called "stratus" ore seen in some unofficial mods.
This is essentially an improved version of the so-called "stratus" ore seen in
some unofficial mods.
### `blob`
Creates a deformed sphere of ore according to 3d perlin noise described by
Creates a deformed sphere of ore according to 3d perlin noise described by
`noise_params`. The maximum size of the blob is `clust_size`, and
`clust_scarcity` has the same meaning as with the `scatter` type.
### `vein
@ -741,64 +745,75 @@ The varying types of decorations that can be placed.
The default value is `simple`, and is currently the only type supported.
### `simple`
Creates a 1 times `H` times 1 column of a specified node (or a random node from a list, if a
decoration list is specified). Can specify a certain node it must spawn next to, such as water or
lava, for example. Can also generate a decoration of random height between a specified lower and
upper bound. This type of decoration is intended for placement of grass, flowers, cacti, papyri,
and so on.
Creates a 1 times `H` times 1 column of a specified node (or a random node from
a list, if a decoration list is specified). Can specify a certain node it must
spawn next to, such as water or lava, for example. Can also generate a
decoration of random height between a specified lower and upper bound.
This type of decoration is intended for placement of grass, flowers, cacti,
papyri, and so on.
### `schematic`
Copies a box of `MapNodes` from a specified schematic file (or raw description). Can specify a
probability of a node randomly appearing when placed. This decoration type is intended to be used
for multi-node sized discrete structures, such as trees, cave spikes, rocks, and so on.
Copies a box of `MapNodes` from a specified schematic file (or raw description).
Can specify a probability of a node randomly appearing when placed.
This decoration type is intended to be used for multi-node sized discrete
structures, such as trees, cave spikes, rocks, and so on.
Schematic specifier
--------------------
A schematic specifier identifies a schematic by either a filename to a Minetest Schematic file (`.mts`)
or through raw data supplied through Lua, in the form of a table. This table must specify two fields:
A schematic specifier identifies a schematic by either a filename to a
Minetest Schematic file (`.mts`) or through raw data supplied through Lua,
in the form of a table. This table must specify two fields:
* The `size` field is a 3D vector containing the dimensions of the provided schematic.
* The `data` field is a flat table of MapNodes making up the schematic, in the order of `[z [y [x]]]`.
* The `data` field is a flat table of MapNodes making up the schematic,
in the order of `[z [y [x]]]`.
**Important**: The default value for `param1` in MapNodes here is `255`, which represents "always place".
**Important**: The default value for `param1` in MapNodes here is `255`,
which represents "always place".
In the bulk `MapNode` data, `param1`, instead of the typical light values, instead represents the
probability of that node appearing in the structure.
In the bulk `MapNode` data, `param1`, instead of the typical light values,
instead represents the probability of that node appearing in the structure.
When passed to `minetest.create_schematic`, probability is an integer value ranging from `0` to `255`:
When passed to `minetest.create_schematic`, probability is an integer value
ranging from `0` to `255`:
* A probability value of `0` means that node will never appear (0% chance).
* A probability value of `255` means the node will always appear (100% chance).
* If the probability value `p` is greater than `0`, then there is a `(p / 256 * 100)`% chance that node
will appear when the schematic is placed on the map.
* If the probability value `p` is greater than `0`, then there is a
`(p / 256 * 100)`% chance that node will appear when the schematic is
placed on the map.
**Important note**: Node aliases cannot be used for a raw schematic provided when registering as a decoration.
**Important note**: Node aliases cannot be used for a raw schematic provided
when registering as a decoration.
Schematic attributes
--------------------
See section "Flag Specifier Format".
Currently supported flags: `place_center_x`, `place_center_y`, `place_center_z`.
Currently supported flags: `place_center_x`, `place_center_y`,
`place_center_z`, `force_placement`.
* `place_center_x`: Placement of this decoration is centered along the X axis.
* `place_center_y`: Placement of this decoration is centered along the Y axis.
* `place_center_z`: Placement of this decoration is centered along the Z axis.
* `force_placement`: Schematic nodes other than "ignore" will replace existing nodes.
HUD element types
-----------------
The position field is used for all element types.
To account for differing resolutions, the position coordinates are the percentage of the screen,
ranging in value from `0` to `1`.
To account for differing resolutions, the position coordinates are the percentage
of the screen, ranging in value from `0` to `1`.
The name field is not yet used, but should contain a description of what the HUD element represents.
The direction field is the direction in which something is drawn.
The name field is not yet used, but should contain a description of what the
HUD element represents. The direction field is the direction in which something
is drawn.
`0` draws from left to right, `1` draws from right to left, `2` draws from top to bottom,
and `3` draws from bottom to top.
`0` draws from left to right, `1` draws from right to left, `2` draws from
top to bottom, and `3` draws from bottom to top.
The `alignment` field specifies how the item will be aligned. It ranges from `-1` to `1`,
with `0` being the center, `-1` is moved to the left/up, and `1` is to the right/down.
@ -812,7 +827,8 @@ items in the HUD.
Below are the specific uses for fields in each type; fields not listed for that type are ignored.
**Note**: Future revisions to the HUD API may be incompatible; the HUD API is still in the experimental stages.
**Note**: Future revisions to the HUD API may be incompatible; the HUD API is still
in the experimental stages.
### `image`
Displays an image on the HUD.
@ -876,15 +892,18 @@ For helper functions see "Vector helpers".
Flag Specifier Format
---------------------
Flags using the standardized flag specifier format can be specified in either of two ways, by string or table.
Flags using the standardized flag specifier format can be specified in either of
two ways, by string or table.
The string format is a comma-delimited set of flag names; whitespace and unrecognized flag fields are ignored.
Specifying a flag in the string sets the flag, and specifying a flag prefixed by the string `"no"` explicitly
The string format is a comma-delimited set of flag names; whitespace and
unrecognized flag fields are ignored. Specifying a flag in the string sets the
flag, and specifying a flag prefixed by the string `"no"` explicitly
clears the flag from whatever the default may be.
In addition to the standard string flag format, the schematic flags field can also be a table of flag names
to boolean values representing whether or not the flag is set. Additionally, if a field with the flag name
prefixed with `"no"` is present, mapped to a boolean of any value, the specified flag is unset.
In addition to the standard string flag format, the schematic flags field can
also be a table of flag names to boolean values representing whether or not the
flag is set. Additionally, if a field with the flag name prefixed with `"no"`
is present, mapped to a boolean of any value, the specified flag is unset.
E.g. A flag field of value
@ -1036,8 +1055,8 @@ Another example: Make red wool from white wool and red dye:
dropped as an item. If the node is wallmounted the wallmounted direction is
checked.
* `soil`: saplings will grow on nodes in this group
* `connect_to_raillike`: makes nodes of raillike drawtype connect to
other group members with same drawtype
* `connect_to_raillike`: makes nodes of raillike drawtype with same group value
connect to each other
### Known damage and digging time defining groups
* `crumbly`: dirt, sand
@ -1177,7 +1196,8 @@ Damage calculation:
damage = 0
foreach group in cap.damage_groups:
damage += cap.damage_groups[group] * limit(actual_interval / cap.full_punch_interval, 0.0, 1.0)
damage += cap.damage_groups[group] * limit(actual_interval /
cap.full_punch_interval, 0.0, 1.0)
* (object.armor_groups[group] / 100.0)
-- Where object.armor_groups[group] is 0 for inexistent values
return damage
@ -1185,7 +1205,7 @@ Damage calculation:
Client predicts damage based on damage groups. Because of this, it is able to
give an immediate response when an entity is damaged or dies; the response is
pre-defined somehow (e.g. by defining a sprite animation) (not implemented;
TODO).
TODO).
Currently a smoke puff will appear when an entity dies.
The group `immortal` completely disables normal damage.
@ -1198,8 +1218,8 @@ On the Lua side, every punch calls:
entity:on_punch(puncher, time_from_last_punch, tool_capabilities, direction)
This should never be called directly, because damage is usually not handled by the entity
itself.
This should never be called directly, because damage is usually not handled by
the entity itself.
* `puncher` is the object performing the punch. Can be `nil`. Should never be
accessed unless absolutely required, to encourage interoperability.
@ -1244,12 +1264,14 @@ Example stuff:
print(dump(meta:to_table()))
meta:from_table({
inventory = {
main = {[1] = "default:dirt", [2] = "", [3] = "", [4] = "", [5] = "", [6] = "",
[7] = "", [8] = "", [9] = "", [10] = "", [11] = "", [12] = "", [13] = "",
[14] = "default:cobble", [15] = "", [16] = "", [17] = "", [18] = "",
[19] = "", [20] = "default:cobble", [21] = "", [22] = "", [23] = "",
[24] = "", [25] = "", [26] = "", [27] = "", [28] = "", [29] = "", [30] = "",
[31] = "", [32] = ""}
main = {[1] = "default:dirt", [2] = "", [3] = "", [4] = "",
[5] = "", [6] = "", [7] = "", [8] = "", [9] = "",
[10] = "", [11] = "", [12] = "", [13] = "",
[14] = "default:cobble", [15] = "", [16] = "", [17] = "",
[18] = "", [19] = "", [20] = "default:cobble", [21] = "",
[22] = "", [23] = "", [24] = "", [25] = "", [26] = "",
[27] = "", [28] = "", [29] = "", [30] = "", [31] = "",
[32] = ""}
},
fields = {
formspec = "size[8,9]list[context;main;0,0;8,4;]list[current_player;main;0,5;8,4;]",
@ -1849,6 +1871,9 @@ and `minetest.auth_reload` call the authetification handler.
* `nodenames`: e.g. `{"ignore", "group:tree"}` or `"default:dirt"`
* `minetest.find_nodes_in_area(minp, maxp, nodenames)`: returns a list of positions
* `nodenames`: e.g. `{"ignore", "group:tree"}` or `"default:dirt"`
* `minetest.find_nodes_in_area_under_air(minp, maxp, nodenames)`: returns a list of positions
* returned positions are nodes with a node air above
* `nodenames`: e.g. `{"ignore", "group:tree"}` or `"default:dirt"`
* `minetest.get_perlin(noiseparams)`
* `minetest.get_perlin(seeddiff, octaves, persistence, scale)`
* Return world-specific perlin noise (`int(worldseed)+seeddiff`)
@ -1866,8 +1891,10 @@ and `minetest.auth_reload` call the authetification handler.
`mgname`, `seed`, `chunksize`, `water_level`, and `flags`.
* `minetest.set_mapgen_params(MapgenParams)`
* Set map generation parameters
* Function cannot be called after the registration period; only initialization and `on_mapgen_init`
* Takes a table as an argument with the fields `mgname`, `seed`, `water_level`, and `flags`.
* Function cannot be called after the registration period; only initialization
and `on_mapgen_init`
* Takes a table as an argument with the fields `mgname`, `seed`, `water_level`,
and `flags`.
* Leave field unset to leave that parameter unchanged
* `flags` contains a comma-delimited string of flags to set,
or if the prefix `"no"` is attached, clears instead.
@ -1926,6 +1953,9 @@ and `minetest.auth_reload` call the authetification handler.
* `minetest.create_detached_inventory(name, callbacks)`: returns an `InvRef`
* callbacks: See "Detached inventory callbacks"
* Creates a detached inventory. If it already exists, it is cleared.
* `minetest.do_item_eat(hp_change, replace_with_item, itemstack, user, pointed_thing)`:
returns left over ItemStack
* See `minetest.item_eat` and `minetest.register_on_item_eat`
### Formspec
* `minetest.show_formspec(playername, formname, formspec)`
@ -2037,7 +2067,11 @@ These functions return the leftover itemstack.
* `minetest.item_drop(itemstack, dropper, pos)`
* Drop the item
* `minetest.item_eat(hp_change, replace_with_item)`
* Eat the item. `replace_with_item` can be `nil`.
* Eat the item.
* `replace_with_item` is the itemstring which is added to the inventory.
If the player is eating a stack, then replace_with_item goes to a
different spot. Can be `nil`
* See `minetest.do_item_eat`
### Defaults for the `on_punch` and `on_dig` node definition callbacks
* `minetest.node_punch(pos, node, puncher, pointed_thing)`
@ -2094,12 +2128,15 @@ These functions return the leftover itemstack.
* Create a schematic from the volume of map specified by the box formed by p1 and p2.
* Apply the specified probability values to the specified nodes in `probability_list`.
* `probability_list` is an array of tables containing two fields, `pos` and `prob`.
* `pos` is the 3D vector specifying the absolute coordinates of the node being modified,
* `pos` is the 3D vector specifying the absolute coordinates of the
node being modified,
* `prob` is the integer value from `0` to `255` of the probability (see: Schematic specifier).
* If there are two or more entries with the same pos value, the last entry is used.
* If there are two or more entries with the same pos value, the
last entry is used.
* If `pos` is not inside the box formed by `p1` and `p2`, it is ignored.
* If `probability_list` equals `nil`, no probabilities are applied.
* Slice probability works in the same manner, except takes a field called `ypos` instead which
* Slice probability works in the same manner, except takes a field
called `ypos` instead which
indicates the y position of the slice with a probability applied.
* If slice probability list equals `nil`, no slice probabilities are applied.
* Saves schematic in the Minetest Schematic format to filename.
@ -2244,7 +2281,7 @@ Class reference
---------------
### `NodeMetaRef`
Node metadata: reference extra data and functionality stored in a node.
Node metadata: reference extra data and functionality stored in a node.
Can be gotten via `minetest.get_meta(pos)`.
#### Methods
@ -2260,7 +2297,7 @@ Can be gotten via `minetest.get_meta(pos)`.
* See "Node Metadata"
### `NoteTimerRef`
Node Timers: a high resolution persistent per-node timer.
Node Timers: a high resolution persistent per-node timer.
Can be gotten via `minetest.get_node_timer(pos)`.
#### Methods
@ -2288,6 +2325,7 @@ This is basically a reference to a C++ `ServerActiveObject`
#### Methods
* `remove()`: remove object (after returning from Lua)
* Note: Doesn't work on players, use minetest.kick_player instead
* `getpos()`: returns `{x=num, y=num, z=num}`
* `setpos(pos)`; `pos`=`{x=num, y=num, z=num}`
* `moveto(pos, continuous=false)`: interpolated move
@ -2360,7 +2398,8 @@ This is basically a reference to a C++ `ServerActiveObject`
* `gravity`: multiplier to default gravity value (default: `1`)
* `sneak`: whether player can sneak (default: `true`)
* `sneak_glitch`: whether player can use the sneak glitch (default: `true`)
* `hud_add(hud definition)`: add a HUD element described by HUD def, returns ID number on success
* `hud_add(hud definition)`: add a HUD element described by HUD def, returns ID
number on success
* `hud_remove(id)`: remove the HUD element of the specified id
* `hud_change(id, stat, value)`: change a value of a previously added HUD element
* element `stat` values: `position`, `name`, `scale`, `text`, `number`, `item`, `dir`
@ -2392,13 +2431,16 @@ This is basically a reference to a C++ `ServerActiveObject`
* `override_day_night_ratio(ratio or nil)`
* `0`...`1`: Overrides day-night ratio, controlling sunlight to a specific amount
* `nil`: Disables override, defaulting to sunlight based on day-night cycle
* `set_local_animation({x=0, y=79}, {x=168, y=187}, {x=189, y=198}, {x=200, y=219}, frame_speed=30)`:
set animation for player model in third person view
* stand/idle animation key frames
* walk animation key frames
* dig animation key frames
* walk+dig animation key frames
* animation frame speed
* `set_local_animation(walk, dig, walk+dig, frame_speed=frame_speed)`
set animation for player model in third person view
set_local_animation({x=0, y=79}, -- < stand/idle animation key frames
{x=168, y=187}, -- < walk animation key frames
{x=189, y=198}, -- < dig animation key frames
{x=200, y=219}, -- < walk+dig animation key frames
frame_speed=30): -- < animation frame speed
* `set_eye_offset({x=0,y=0,z=0},{x=0,y=0,z=0})`: defines offset value for camera per player
* in first person view
* in third person view (max. values `{x=-10/10,y=-10,15,z=-5/5}`)
@ -2485,7 +2527,7 @@ It can be created via `PseudoRandom(seed)`.
### `PerlinNoise`
A perlin noise generator.
It can be created via `PerlinNoise(seed, octaves, persistence, scale)`
or `PerlinNoise(noiseparams)`.
or `PerlinNoise(noiseparams)`.
Alternatively with `minetest.get_perlin(seeddiff, octaves, persistence, scale)`
or `minetest.get_perlin(noiseparams)`.
@ -2519,36 +2561,43 @@ It can be created via `VoxelManip()` or `minetest.get_voxel_manip()`.
The map will be pre-loaded if two positions are passed to either.
#### Methods
* `read_from_map(p1, p2)`: Reads a chunk of map from the map containing the region formed by `p1` and `p2`.
* `read_from_map(p1, p2)`: Reads a chunk of map from the map containing the
region formed by `p1` and `p2`.
* returns actual emerged `pmin`, actual emerged `pmax`
* `write_to_map()`: Writes the data loaded from the `VoxelManip` back to the map.
* **important**: data must be set using `VoxelManip:set_data` before calling this
* `get_node_at(pos)`: Returns a `MapNode` table of the node currently loaded in the `VoxelManip` at that position
* `set_node_at(pos, node)`: Sets a specific `MapNode` in the `VoxelManip` at that position
* `get_node_at(pos)`: Returns a `MapNode` table of the node currently loaded in
the `VoxelManip` at that position
* `set_node_at(pos, node)`: Sets a specific `MapNode` in the `VoxelManip` at
that position
* `get_data()`: Gets the data read into the `VoxelManip` object
* returns raw node data is in the form of an array of node content IDs
* `set_data(data)`: Sets the data contents of the `VoxelManip` object
* `update_map()`: Update map after writing chunk back to map.
* To be used only by `VoxelManip` objects created by the mod itself; not a `VoxelManip` that was
retrieved from `minetest.get_mapgen_object`
* To be used only by `VoxelManip` objects created by the mod itself;
not a `VoxelManip` that was retrieved from `minetest.get_mapgen_object`
* `set_lighting(light, p1, p2)`: Set the lighting within the `VoxelManip` to a uniform value
* `light` is a table, `{day=<0...15>, night=<0...15>}`
* To be used only by a `VoxelManip` object from `minetest.get_mapgen_object`
* (`p1`, `p2`) is the area in which lighting is set; defaults to the whole area if left out
* (`p1`, `p2`) is the area in which lighting is set;
defaults to the whole area if left out
* `get_light_data()`: Gets the light data read into the `VoxelManip` object
* Returns an array (indices 1 to volume) of integers ranging from `0` to `255`
* Each value is the bitwise combination of day and night light values (`0` to `15` each)
* `light = day + (night * 16)`
* `set_light_data(light_data)`: Sets the `param1` (light) contents of each node in the `VoxelManip`
* `set_light_data(light_data)`: Sets the `param1` (light) contents of each node
in the `VoxelManip`
* expects lighting data in the same format that `get_light_data()` returns
* `get_param2_data()`: Gets the raw `param2` data read into the `VoxelManip` object
* `set_param2_data(param2_data)`: Sets the `param2` contents of each node in the `VoxelManip`
* `calc_lighting(p1, p2)`: Calculate lighting within the `VoxelManip`
* To be used only by a `VoxelManip` object from `minetest.get_mapgen_object`
* (`p1`, `p2`) is the area in which lighting is set; defaults to the whole area if left out
* (`p1`, `p2`) is the area in which lighting is set; defaults to the whole area
if left out
* `update_liquids()`: Update liquid flow
* `was_modified()`: Returns `true` or `false` if the data in the voxel manipulator had been modified since
the last read from map, due to a call to `minetest.set_data()` on the loaded area elsewhere
* `was_modified()`: Returns `true` or `false` if the data in the voxel manipulator
had been modified since the last read from map, due to a call to
`minetest.set_data()` on the loaded area elsewhere
* `get_emerged_area()`: Returns actual emerged minimum and maximum positions.
### `VoxelArea`
@ -2557,10 +2606,12 @@ It can be created via `VoxelArea:new{MinEdge=pmin, MaxEdge=pmax}`.
The coordinates are *inclusive*, like most other things in Minetest.
#### Methods
* `getExtent()`: returns a 3D vector containing the size of the area formed by `MinEdge` and `MaxEdge`
* `getExtent()`: returns a 3D vector containing the size of the area formed by
`MinEdge` and `MaxEdge`
* `getVolume()`: returns the volume of the area formed by `MinEdge` and `MaxEdge`
* `index(x, y, z)`: returns the index of an absolute position in a flat array starting at `1`
* useful for things like `VoxelManip`, raw Schematic specifiers, `PerlinNoiseMap:get2d`/`3dMap`, and so on
* useful for things like `VoxelManip`, raw Schematic specifiers,
`PerlinNoiseMap:get2d`/`3dMap`, and so on
* `indexp(p)`: same as above, except takes a vector
* `position(i)`: returns the absolute position vector corresponding to index `i`
* `contains(x, y, z)`: check if (`x`,`y`,`z`) is inside area formed by `MinEdge` and `MaxEdge`
@ -2587,37 +2638,39 @@ It can be created via `Settings(filename)`.
Mapgen objects
--------------
A mapgen object is a construct used in map generation. Mapgen objects can be used by an `on_generate`
callback to speed up operations by avoiding unnecessary recalculations; these can be retrieved using the
`minetest.get_mapgen_object()` function. If the requested Mapgen object is unavailable, or
`get_mapgen_object()` was called outside of an `on_generate()` callback, `nil` is returned.
A mapgen object is a construct used in map generation. Mapgen objects can be used
by an `on_generate` callback to speed up operations by avoiding unnecessary
recalculations; these can be retrieved using the `minetest.get_mapgen_object()`
function. If the requested Mapgen object is unavailable, or `get_mapgen_object()`
was called outside of an `on_generate()` callback, `nil` is returned.
The following Mapgen objects are currently available:
### `voxelmanip`
This returns three values; the `VoxelManip` object to be used, minimum and maximum emerged position, in that
order. All mapgens support this object.
This returns three values; the `VoxelManip` object to be used, minimum and maximum
emerged position, in that order. All mapgens support this object.
### `heightmap`
Returns an array containing the y coordinates of the ground levels of nodes in the most recently
generated chunk by the current mapgen.
Returns an array containing the y coordinates of the ground levels of nodes in
the most recently generated chunk by the current mapgen.
### `biomemap`
Returns an array containing the biome IDs of nodes in the most recently generated chunk by the
current mapgen.
Returns an array containing the biome IDs of nodes in the most recently
generated chunk by the current mapgen.
### `heatmap`
Returns an array containing the temperature values of nodes in the most recently generated chunk by
the current mapgen.
Returns an array containing the temperature values of nodes in the most
recently generated chunk by the current mapgen.
### `humiditymap`
Returns an array containing the humidity values of nodes in the most recently generated chunk by the
current mapgen.
Returns an array containing the humidity values of nodes in the most recently
generated chunk by the current mapgen.
### `gennotify`
Returns a table mapping requested generation notification types to arrays of positions at which the
corresponding generated structures are located at within the current chunk. To set the capture of positions
of interest to be recorded on generate, use `minetest.set_gen_notify()`.
Returns a table mapping requested generation notification types to arrays of
positions at which the corresponding generated structures are located at within
the current chunk. To set the capture of positions of interest to be recorded
on generate, use `minetest.set_gen_notify()`.
Possible fields of the table returned are:
@ -2629,7 +2682,8 @@ Possible fields of the table returned are:
* `large_cave_end`
* `decoration`
Decorations have a key in the format of `"decoration#id"`, where `id` is the numeric unique decoration ID.
Decorations have a key in the format of `"decoration#id"`, where `id` is the
numeric unique decoration ID.
Registered entities
-------------------
@ -2676,7 +2730,8 @@ L-system trees
angle, --num angle in deg
iterations, --num max # of iterations, usually 2 -5
random_level, --num factor to lower nr of iterations, usually 0 - 3
trunk_type, --string single/double/crossed) type of trunk: 1 node, 2x2 nodes or 3x3 in cross shape
trunk_type, --string single/double/crossed) type of trunk: 1 node,
-- 2x2 nodes or 3x3 in cross shape
thin_branches, --boolean true -> use thin (1 node) branches
fruit, --string fruit node name
fruit_chance, --num chance (0-100) to replace leaves with fruit node
@ -3138,8 +3193,10 @@ Definition tables
schematic = {
size = {x=4, y=6, z=4},
data = {
{name="cobble", param1=255, param2=0},
{name="dirt_with_grass", param1=255, param2=0},
{name="default:cobble", param1=255, param2=0},
{name="default:dirt_with_grass", param1=255, param2=0},
{name="ignore", param1=255, param2=0},
{name="air", param1=255, param2=0},
...
},
yslice_prob = {
@ -3150,7 +3207,7 @@ Definition tables
},
-- ^ See 'Schematic specifier' for details.
replacements = {["oldname"] = "convert_to", ...},
flags = "place_center_x, place_center_z",
flags = "place_center_x, place_center_y, place_center_z, force_placement",
-- ^ Flags for schematic decorations. See 'Schematic attributes'.
rotation = "90" -- rotate schematic 90 degrees on placement
-- ^ Rotation can be "0", "90", "180", "270", or "random".

View File

@ -1,4 +1,4 @@
Minetest Lua Mainmenu API Reference 0.4.11
Minetest Lua Mainmenu API Reference 0.4.12
========================================
Introduction
@ -197,9 +197,11 @@ core.delete_world(index)
Helpers:
core.gettext(string) -> string
^ look up the translation of a string in the gettext message catalog
fgettext(string, ...) -> string
fgettext_ne(string, ...)
^ call core.gettext(string), replace "$1"..."$9" with the given
^ extra arguments, call core.formspec_escape and return the result
^ extra arguments and return the result
fgettext(string, ...) -> string
^ same as fgettext_ne(), but calls core.formspec_escape before returning result
core.parse_json(string[, nullvalue]) -> something (possible in async calls)
^ see core.parse_json (lua_api.txt)
dump(obj, dumped={})
@ -211,6 +213,12 @@ string:trim()
core.is_yes(arg) (possible in async calls)
^ returns whether arg can be interpreted as yes
Version compat:
core.get_min_supp_proto()
^ returns the minimum supported network protocol version
core.get_max_supp_proto()
^ returns the maximum supported network protocol version
Async:
core.handle_async(async_job,parameters,finished)
^ execute a function asynchronously

View File

@ -48,6 +48,7 @@
#keymap_rangeselect = KEY_KEY_R
#keymap_freemove = KEY_KEY_K
#keymap_fastmove = KEY_KEY_J
#keymap_cinematic = KEY_F8
#keymap_screenshot = KEY_F12
# If true, keymap_special1 instead of keymap_sneak is used for climbing down and descending
#aux1_descends = false
@ -127,6 +128,13 @@
#free_move = false
# Continuous forward movement (for testing)
#continuous_forward = false
# Enable cinematic mode
#cinematic = false
# Camera smoothing - smooths rotation of camera. 0 is no smoothing.
# Must be equal to or greater than 0, and less than 1.
#camera_smoothing = 0.0
# Camera smoothing when in cinematic mode
#cinematic_camera_smoothing = 0.7
# Fast movement (keymap_special1)
#fast_move = false
# Invert mouse
@ -252,16 +260,16 @@
#freetype = true
# Path to TrueTypeFont or bitmap
#font_path = fonts/liberationsans.ttf
#font_size = 13
#font_size = 15
# Font shadow offset, if 0 then shadow will not be drawn
#font_shadow = 1
# Font shadow alpha (opaqueness, between 0 and 255)
#font_shadow_alpha = 128
#mono_font_path = fonts/liberationmono.ttf
#mono_font_size = 13
#mono_font_size = 15
# This font will be used for certain languages
#fallback_font_path = fonts/DroidSansFallbackFull.ttf
#fallback_font_size = 13
#fallback_font_size = 15
#fallback_font_shadow = 1
#fallback_font_shadow_alpha = 128
# Override language. When no value is provided (default) system language is used.
@ -337,6 +345,7 @@
# If true, disable cheat prevention in multiplayer
#disable_anticheat = false
# If true, actions are recorded for rollback
# This option is only read when server starts
#enable_rollback_recording = false
# Handling for deprecated lua api calls:
# "legacy" = (try to) mimic old behaviour (default for release).
@ -460,6 +469,8 @@
# Controls size of deserts and beaches in Mapgen V6
#mgv6_freq_desert = 0.45
#mgv6_freq_beach = 0.15
# Enable/disable floating dungeons and dungeon slices
#enable_floating_dungeons = true
# Perlin noise attributes for different map generation parameters.
# Noise parameters can be specified as a set of positional values:
@ -477,33 +488,14 @@
# flags = "defaults"
#}
# Only the group format supports noise flags which are needed for eased noise.
# Mgv5 uses eased noise for np_cave1, np_cave2, np_ground and np_crumble, so these are shown in
# group format, other noise parameters are shown in positional format to save space.
# Mgv5 uses eased noise for np_ground so this is shown in group format,
# other noise parameters are shown in positional format to save space.
#mgv5_spflags = blobs
#mgv5_np_filler_depth = 0, 1, (150, 150, 150), 261, 4, 0.7, 2.0
#mgv5_np_factor = 0, 1, (250, 250, 250), 920381, 3, 0.45, 2.0
#mgv5_np_height = 0, 10, (250, 250, 250), 84174, 4, 0.5, 2.0
#mgv5_np_cave1 = {
# offset = 0
# scale = 6
# spread = (50, 50, 50)
# seed = 52534
# octaves = 4
# persistence = 0.5
# lacunarity = 2.0
# flags = "eased"
#}
#mgv5_np_cave2 = {
# offset = 0
# scale = 6
# spread = (50, 50, 50)
# seed = 10325
# octaves = 4
# persistence = 0.5
# lacunarity = 2.0
# flags = "eased"
#}
#mgv5_np_cave1 = 0, 12, (50, 50, 50), 52534, 4, 0.5, 2.0
#mgv5_np_cave2 = 0, 12, (50, 50, 50), 10325, 4, 0.5, 2.0
#mgv5_np_ground = {
# offset = 0
# scale = 40
@ -514,17 +506,6 @@
# lacunarity = 2.0
# flags = "eased"
#}
#mgv5_np_crumble = {
# offset = 0
# scale = 1
# spread = (20, 20, 20)
# seed = 34413
# octaves = 3
# persistence = 1.3
# lacunarity = 2.0
# flags = "eased"
#}
#mgv5_np_wetness = 0, 1, (40, 40, 40), 32474, 4, 1.1, 2.0
#mgv6_spflags = biomeblend, jungles, mudflow
#mgv6_np_terrain_base = -4, 20, (250, 250, 250), 82341, 5, 0.6, 2.0

View File

@ -2,6 +2,8 @@
Name=Minetest
GenericName=Minetest
Comment=Multiplayer infinite-world block sandbox
Comment[fr]=Jeu multijoueurs de type bac à sable avec des mondes infinis
Comment[de]=Mehrspieler-Sandkastenspiel mit unendlichen Blockwelten
Exec=minetest
Icon=minetest-icon
Terminal=false

File diff suppressed because it is too large Load Diff

View File

@ -7,18 +7,18 @@ msgid ""
msgstr ""
"Project-Id-Version: minetest\n"
"Report-Msgid-Bugs-To: \n"
"POT-Creation-Date: 2014-12-13 15:24+0100\n"
"PO-Revision-Date: 2015-01-19 09:56+0100\n"
"POT-Creation-Date: 2015-02-14 13:50+0100\n"
"PO-Revision-Date: 2015-02-14 13:35+0100\n"
"Last-Translator: Diego de las Heras <diegodelasheras@gmail.com>\n"
"Language-Team: LANGUAGE <LL@li.org>\n"
"Language-Team: \n"
"Language: es\n"
"MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=UTF-8\n"
"Content-Transfer-Encoding: 8bit\n"
"Plural-Forms: nplurals=2; plural=n != 1;\n"
"X-Generator: Poedit 1.7.3\n"
"X-Generator: Poedit 1.7.4\n"
#: builtin/fstk/ui.lua:67
#: builtin/fstk/ui.lua:67 builtin/mainmenu/store.lua:165
msgid "Ok"
msgstr "Aceptar"
@ -40,7 +40,7 @@ msgstr "Ocultar contenido mp"
msgid "Mod:"
msgstr "Mod:"
#: builtin/mainmenu/dlg_config_world.lua:48
#: builtin/mainmenu/dlg_config_world.lua:48 builtin/mainmenu/tab_mods.lua:99
msgid "Depends:"
msgstr "Dependencias:"
@ -124,7 +124,7 @@ msgstr "¿Realmente desea borrar \"$1\"?"
#: builtin/mainmenu/dlg_delete_mod.lua:27
#: builtin/mainmenu/dlg_delete_world.lua:25
#: builtin/mainmenu/tab_settings.lua:25
#: builtin/mainmenu/tab_settings.lua:79
msgid "Yes"
msgstr "Sí"
@ -186,48 +186,40 @@ msgstr "Instalar mod: Imposible encontrar el nombre real del mod para: $1"
msgid "Unsorted"
msgstr "Sin ordenar"
#: builtin/mainmenu/store.lua:99 builtin/mainmenu/store.lua:584
#: builtin/mainmenu/store.lua:99 builtin/mainmenu/store.lua:580
msgid "Search"
msgstr "Buscar"
#: builtin/mainmenu/store.lua:125
msgid "Downloading"
msgstr "Descargando"
#: builtin/mainmenu/store.lua:126
msgid "Downloading $1, please wait..."
msgstr "Descargando $1, por favor espere..."
#: builtin/mainmenu/store.lua:127
msgid "please wait..."
msgstr "por favor espere..."
#: builtin/mainmenu/store.lua:159
#: builtin/mainmenu/store.lua:160
msgid "Successfully installed:"
msgstr "Instalado con éxito:"
#: builtin/mainmenu/store.lua:163
#: builtin/mainmenu/store.lua:162
msgid "Shortname:"
msgstr "Nombre corto:"
#: builtin/mainmenu/store.lua:167 src/guiFormSpecMenu.cpp:2866
msgid "ok"
msgstr "aceptar"
#: builtin/mainmenu/store.lua:476
#: builtin/mainmenu/store.lua:472
msgid "Rating"
msgstr "Clasificación"
#: builtin/mainmenu/store.lua:501
#: builtin/mainmenu/store.lua:497
msgid "re-Install"
msgstr "Reinstalar"
#: builtin/mainmenu/store.lua:503
#: builtin/mainmenu/store.lua:499
msgid "Install"
msgstr "Instalar"
# En el menú principal de mods pone repositorio no tienda.
#: builtin/mainmenu/store.lua:522
#: builtin/mainmenu/store.lua:518
msgid "Close store"
msgstr "Cerrar repositorio"
#: builtin/mainmenu/store.lua:530
#: builtin/mainmenu/store.lua:526
msgid "Page $1 of $2"
msgstr "Página $1 de $2"
@ -288,8 +280,7 @@ msgstr "Mods"
msgid "Address / Port :"
msgstr "Dirección / puerto:"
#: builtin/mainmenu/tab_multiplayer.lua:24 builtin/mainmenu/tab_server.lua:37
#: builtin/mainmenu/tab_simple_main.lua:25
#: builtin/mainmenu/tab_multiplayer.lua:24
msgid "Name / Password :"
msgstr "Nombre / contraseña:"
@ -308,7 +299,22 @@ msgstr "Borrar"
msgid "Connect"
msgstr "Conectar"
#: builtin/mainmenu/tab_multiplayer.lua:252
#: builtin/mainmenu/tab_multiplayer.lua:62
#: builtin/mainmenu/tab_simple_main.lua:45
msgid "Creative mode"
msgstr "Modo creativo"
#: builtin/mainmenu/tab_multiplayer.lua:63
#: builtin/mainmenu/tab_simple_main.lua:46
msgid "Damage enabled"
msgstr "Daño activado"
#: builtin/mainmenu/tab_multiplayer.lua:64
#: builtin/mainmenu/tab_simple_main.lua:47
msgid "PvP enabled"
msgstr "PvP activado"
#: builtin/mainmenu/tab_multiplayer.lua:247
msgid "Client"
msgstr "Cliente"
@ -328,12 +334,12 @@ msgstr "Iniciar juego"
msgid "Select World:"
msgstr "Selecciona un mundo:"
#: builtin/mainmenu/tab_server.lua:31 builtin/mainmenu/tab_simple_main.lua:63
#: builtin/mainmenu/tab_server.lua:31 builtin/mainmenu/tab_simple_main.lua:75
#: builtin/mainmenu/tab_singleplayer.lua:90
msgid "Creative Mode"
msgstr "Modo creativo"
#: builtin/mainmenu/tab_server.lua:33 builtin/mainmenu/tab_simple_main.lua:65
#: builtin/mainmenu/tab_server.lua:33 builtin/mainmenu/tab_simple_main.lua:77
#: builtin/mainmenu/tab_singleplayer.lua:92
msgid "Enable Damage"
msgstr "Permitir daños"
@ -342,6 +348,11 @@ msgstr "Permitir daños"
msgid "Public"
msgstr "Público"
# Los dos puntos son intencionados.
#: builtin/mainmenu/tab_server.lua:37 builtin/mainmenu/tab_simple_main.lua:25
msgid "Name/Password"
msgstr "Nombre / contraseña:"
#: builtin/mainmenu/tab_server.lua:45
msgid "Bind Address"
msgstr "Asociar dirección"
@ -358,133 +369,151 @@ msgstr "Puerto del servidor:"
msgid "Server"
msgstr "Servidor"
#: builtin/mainmenu/tab_settings.lua:21
msgid "No Filter"
msgstr "Sin filtro"
#: builtin/mainmenu/tab_settings.lua:22
msgid "Bilinear Filter"
msgstr "Filtro bi-lineal"
#: builtin/mainmenu/tab_settings.lua:23
msgid "Trilinear Filter"
msgstr "Filtro tri-lineal"
#: builtin/mainmenu/tab_settings.lua:32
msgid "No Mipmap"
msgstr "Sin Mipmap"
#: builtin/mainmenu/tab_settings.lua:33
msgid "Mipmap"
msgstr "Mipmap"
#: builtin/mainmenu/tab_settings.lua:34
msgid "Mipmap + Aniso. Filter"
msgstr "Mipmap + Filtro aniso."
#: builtin/mainmenu/tab_settings.lua:77
msgid "Are you sure to reset your singleplayer world?"
msgstr "¿Estás seguro de querer reiniciar el mundo de un jugador?"
#: builtin/mainmenu/tab_settings.lua:27
#: builtin/mainmenu/tab_settings.lua:81
msgid "No!!!"
msgstr "¡¡¡No!!!"
#: builtin/mainmenu/tab_settings.lua:134
#: builtin/mainmenu/tab_settings.lua:181
msgid "Smooth Lighting"
msgstr "Iluminación suave"
#: builtin/mainmenu/tab_settings.lua:136
#: builtin/mainmenu/tab_settings.lua:183
msgid "Enable Particles"
msgstr "Habilitar partículas"
#: builtin/mainmenu/tab_settings.lua:138
#: builtin/mainmenu/tab_settings.lua:185
msgid "3D Clouds"
msgstr "Nubes 3D"
#: builtin/mainmenu/tab_settings.lua:141
#: builtin/mainmenu/tab_settings.lua:187
msgid "Fancy Trees"
msgstr "Árboles detallados"
#: builtin/mainmenu/tab_settings.lua:142
#: builtin/mainmenu/tab_settings.lua:189
msgid "Opaque Water"
msgstr "Agua opaca"
#: builtin/mainmenu/tab_settings.lua:145
#: builtin/mainmenu/tab_settings.lua:191
msgid "Connected Glass"
msgstr "Vidrios conectados"
#: builtin/mainmenu/tab_settings.lua:149
#: builtin/mainmenu/tab_settings.lua:193
msgid "Node Highlighting"
msgstr "Resaltar nodos"
#: builtin/mainmenu/tab_settings.lua:196
msgid "Texturing:"
msgstr "Texturizado:"
#: builtin/mainmenu/tab_settings.lua:201
msgid "Rendering:"
msgstr "Renderizado:"
#: builtin/mainmenu/tab_settings.lua:205
msgid "Restart minetest for driver change to take effect"
msgstr "Reinicia minetest para que los cambios en el controlador tengan efecto"
#: builtin/mainmenu/tab_settings.lua:151
msgid "Mip-Mapping"
msgstr "Mip-Mapping"
#: builtin/mainmenu/tab_settings.lua:153
msgid "Anisotropic Filtering"
msgstr "Filtrado Anisotrópico"
#: builtin/mainmenu/tab_settings.lua:155
msgid "Bi-Linear Filtering"
msgstr "Filtrado Bi-Lineal"
#: builtin/mainmenu/tab_settings.lua:157
msgid "Tri-Linear Filtering"
msgstr "Filtrado Tri-Lineal"
#: builtin/mainmenu/tab_settings.lua:160
#: builtin/mainmenu/tab_settings.lua:207
msgid "Shaders"
msgstr "Sombreadores"
#: builtin/mainmenu/tab_settings.lua:164
#: builtin/mainmenu/tab_settings.lua:212
msgid "Change keys"
msgstr "Configurar teclas"
#: builtin/mainmenu/tab_settings.lua:167
#: builtin/mainmenu/tab_settings.lua:215
msgid "Reset singleplayer world"
msgstr "Reiniciar mundo de un jugador"
#: builtin/mainmenu/tab_settings.lua:171
#: builtin/mainmenu/tab_settings.lua:219
msgid "GUI scale factor"
msgstr "Factor de escala (GUI)"
#: builtin/mainmenu/tab_settings.lua:175
#: builtin/mainmenu/tab_settings.lua:223
msgid "Scaling factor applied to menu elements: "
msgstr "Factor de escala aplicado a los elementos del menú: "
#: builtin/mainmenu/tab_settings.lua:182
#, fuzzy
#: builtin/mainmenu/tab_settings.lua:229
msgid "Touch free target"
msgstr "Tocar para interactuar"
#: builtin/mainmenu/tab_settings.lua:187
#: builtin/mainmenu/tab_settings.lua:235
msgid "Touchthreshold (px)"
msgstr "Umbral táctil (px)"
#: builtin/mainmenu/tab_settings.lua:194 builtin/mainmenu/tab_settings.lua:208
#, fuzzy
#: builtin/mainmenu/tab_settings.lua:242 builtin/mainmenu/tab_settings.lua:256
msgid "Bumpmapping"
msgstr "Mapeado de relieve"
#: builtin/mainmenu/tab_settings.lua:196 builtin/mainmenu/tab_settings.lua:209
#: builtin/mainmenu/tab_settings.lua:244 builtin/mainmenu/tab_settings.lua:257
msgid "Generate Normalmaps"
msgstr "Generar mapas normales"
#: builtin/mainmenu/tab_settings.lua:198 builtin/mainmenu/tab_settings.lua:210
#: builtin/mainmenu/tab_settings.lua:246 builtin/mainmenu/tab_settings.lua:258
msgid "Parallax Occlusion"
msgstr "Oclusión de paralaje"
#: builtin/mainmenu/tab_settings.lua:200 builtin/mainmenu/tab_settings.lua:211
#: builtin/mainmenu/tab_settings.lua:248 builtin/mainmenu/tab_settings.lua:259
msgid "Waving Water"
msgstr "Oleaje en el agua"
#: builtin/mainmenu/tab_settings.lua:202 builtin/mainmenu/tab_settings.lua:212
#: builtin/mainmenu/tab_settings.lua:250 builtin/mainmenu/tab_settings.lua:260
msgid "Waving Leaves"
msgstr "Movimiento de hojas"
#: builtin/mainmenu/tab_settings.lua:204 builtin/mainmenu/tab_settings.lua:213
#: builtin/mainmenu/tab_settings.lua:252 builtin/mainmenu/tab_settings.lua:261
msgid "Waving Plants"
msgstr "Movimiento de plantas"
#: builtin/mainmenu/tab_settings.lua:255
#: builtin/mainmenu/tab_settings.lua:287
msgid "To enable shaders the OpenGL driver needs to be used."
msgstr "Para habilitar los sombreadores debe utilizar el controlador OpenGL."
#: builtin/mainmenu/tab_settings.lua:330
#: builtin/mainmenu/tab_settings.lua:398
msgid "Settings"
msgstr "Configuración"
#: builtin/mainmenu/tab_simple_main.lua:67
#: builtin/mainmenu/tab_simple_main.lua:79
msgid "Fly mode"
msgstr "Modo vuelo"
#: builtin/mainmenu/tab_simple_main.lua:71
#: builtin/mainmenu/tab_simple_main.lua:83
msgid "Start Singleplayer"
msgstr "Comenzar un jugador"
#: builtin/mainmenu/tab_simple_main.lua:72
#: builtin/mainmenu/tab_simple_main.lua:84
msgid "Config mods"
msgstr "Configurar mods"
#: builtin/mainmenu/tab_simple_main.lua:191
#: builtin/mainmenu/tab_simple_main.lua:203
msgid "Main"
msgstr "Principal"
@ -509,39 +538,195 @@ msgstr "Sin información disponible"
msgid "Texturepacks"
msgstr "Texturas"
#: src/client.cpp:2726
#: src/client.cpp:2788
msgid "Loading textures..."
msgstr "Cargando texturas..."
#: src/client.cpp:2798
msgid "Rebuilding shaders..."
msgstr "Reconstruyendo sombreadores..."
#: src/client.cpp:2805
msgid "Initializing nodes..."
msgstr "Inicializando nodos..."
#: src/client.cpp:2820
msgid "Item textures..."
msgstr "Texturas de objetos..."
#: src/client.cpp:2845
msgid "Done!"
msgstr "¡Completado!"
#: src/client/clientlauncher.cpp:171
msgid "Main Menu"
msgstr "Menú principal"
#: src/client/clientlauncher.cpp:209
msgid "Player name too long."
msgstr "Nombre de jugador demasiado largo."
#: src/client/clientlauncher.cpp:247
msgid "Connection error (timed out?)"
msgstr "Error de conexión (¿tiempo agotado?)"
#: src/client/clientlauncher.cpp:412
msgid "No world selected and no address provided. Nothing to do."
msgstr ""
"No se seleccionó el mundo y no se ha especificado una dirección. Nada que "
"hacer."
#: src/client/clientlauncher.cpp:419
msgid "Provided world path doesn't exist: "
msgstr "La ruta del mundo especificada no existe: "
#: src/client/clientlauncher.cpp:428
msgid "Could not find or load game \""
msgstr "No se puede encontrar o cargar el juego \""
#: src/client/clientlauncher.cpp:446
msgid "Invalid gamespec."
msgstr "Juego especificado no válido."
#: src/fontengine.cpp:70 src/fontengine.cpp:226
msgid "needs_fallback_font"
msgstr "needs_fallback_font"
#: src/game.cpp:1063
#: src/game.cpp:1057 src/guiFormSpecMenu.cpp:2006
msgid "Proceed"
msgstr "Continuar"
#: src/game.cpp:1077
msgid "You died."
msgstr "Has muerto."
#: src/game.cpp:1078
msgid "Respawn"
msgstr "Revivir"
#: src/game.cpp:2250
#: src/game.cpp:1097
msgid ""
"Default Controls:\n"
"No menu visible:\n"
"- single tap: button activate\n"
"- double tap: place/use\n"
"- slide finger: look around\n"
"Menu/Inventory visible:\n"
"- double tap (outside):\n"
" -->close\n"
"- touch stack, touch slot:\n"
" --> move stack\n"
"- touch&drag, tap 2nd finger\n"
" --> place single item to slot\n"
msgstr ""
"Controles predeterminados:\n"
"Con el menú oculto:\n"
"- toque simple: botón activar\n"
"- toque doble: colocar/usar\n"
"- deslizar dedo: mirar alrededor\n"
"Con el menú/inventario visible:\n"
"- toque doble (fuera):\n"
" -->cerrar\n"
"- toque en la pila de objetos:\n"
" -->mover la pila\n"
"- toque y arrastrar, toque con 2 dedos:\n"
" -->colocar solamente un objeto\n"
#: src/game.cpp:1111
msgid ""
"Default Controls:\n"
"- WASD: move\n"
"- Space: jump/climb\n"
"- Shift: sneak/go down\n"
"- Q: drop item\n"
"- I: inventory\n"
"- Mouse: turn/look\n"
"- Mouse left: dig/punch\n"
"- Mouse right: place/use\n"
"- Mouse wheel: select item\n"
"- T: chat\n"
msgstr ""
"Controles predeterminados:\n"
"- WASD: moverse\n"
"- Espacio: saltar/subir\n"
"- Mayús.: puntillas/bajar\n"
"- Q: soltar objeto\n"
"- I: inventario\n"
"- Ratón: girar/mirar\n"
"- Ratón izq.: cavar/golpear\n"
"- Ratón der.: colocar/usar\n"
"- Ratón rueda: elegir objeto\n"
"- T: chat\n"
#: src/game.cpp:1130
msgid "Continue"
msgstr "Continuar"
#: src/game.cpp:1134
msgid "Change Password"
msgstr "Cambiar contraseña"
#: src/game.cpp:1139
msgid "Sound Volume"
msgstr "Volumen del sonido"
#: src/game.cpp:1141
msgid "Change Keys"
msgstr "Configurar teclas"
#: src/game.cpp:1144
msgid "Exit to Menu"
msgstr "Salir al menú"
#: src/game.cpp:1146
msgid "Exit to OS"
msgstr "Salir al S.O."
#: src/game.cpp:1809
msgid "Shutting down..."
msgstr "Cerrando..."
#: src/game.cpp:1858
msgid "Loading..."
msgstr "Cargando..."
#: src/game.cpp:1915
msgid "Creating server..."
msgstr "Creando servidor..."
#: src/game.cpp:1952
msgid "Creating client..."
msgstr "Creando cliente..."
#: src/game.cpp:2125
msgid "Resolving address..."
msgstr "Resolviendo dirección..."
#: src/game.cpp:2216
msgid "Connecting to server..."
msgstr "Conectando al servidor..."
#: src/game.cpp:2274
msgid "Item definitions..."
msgstr "Definiciones de objetos..."
#: src/game.cpp:2255
#: src/game.cpp:2279
msgid "Node definitions..."
msgstr "Definiciones de nodos..."
#: src/game.cpp:2262
#: src/game.cpp:2286
msgid "Media..."
msgstr "Media..."
#: src/game.cpp:2267
#: src/game.cpp:2291
msgid " KB/s"
msgstr " KB/s"
#: src/game.cpp:2271
#: src/game.cpp:2295
msgid " MB/s"
msgstr " MB/s"
#: src/game.cpp:4220
#: src/game.cpp:4210
msgid ""
"\n"
"Check debug.txt for details."
@ -549,14 +734,14 @@ msgstr ""
"\n"
"Consulta debug.txt para obtener más detalles."
#: src/guiFormSpecMenu.cpp:2055
msgid "Proceed"
msgstr "Continuar"
#: src/guiFormSpecMenu.cpp:2846
#: src/guiFormSpecMenu.cpp:2797
msgid "Enter "
msgstr "Ingresar "
#: src/guiFormSpecMenu.cpp:2817
msgid "ok"
msgstr "aceptar"
#: src/guiKeyChangeMenu.cpp:125
msgid "Keybindings. (If this menu screws up, remove stuff from minetest.conf)"
msgstr ""
@ -647,23 +832,23 @@ msgstr "Seleccionar distancia"
msgid "Print stacks"
msgstr "Imprimir pilas"
#: src/guiPasswordChange.cpp:106
#: src/guiPasswordChange.cpp:108
msgid "Old Password"
msgstr "Contraseña anterior"
#: src/guiPasswordChange.cpp:122
#: src/guiPasswordChange.cpp:124
msgid "New Password"
msgstr "Contraseña nueva"
#: src/guiPasswordChange.cpp:137
#: src/guiPasswordChange.cpp:139
msgid "Confirm Password"
msgstr "Confirmar contraseña"
#: src/guiPasswordChange.cpp:153
#: src/guiPasswordChange.cpp:155
msgid "Change"
msgstr "Cambiar"
#: src/guiPasswordChange.cpp:162
#: src/guiPasswordChange.cpp:164
msgid "Passwords do not match!"
msgstr "¡Las contraseñas no coinciden!"
@ -963,210 +1148,3 @@ msgstr "PA1"
#: src/keycode.cpp:249
msgid "Zoom"
msgstr "Zoom"
#: src/main.cpp:1681
msgid "Main Menu"
msgstr "Menú principal"
#: src/main.cpp:1719
msgid "Player name too long."
msgstr "Nombre de jugador demasiado largo."
#: src/main.cpp:1757
msgid "Connection error (timed out?)"
msgstr "Error de conexión (¿tiempo agotado?)"
#: src/main.cpp:1919
msgid "No world selected and no address provided. Nothing to do."
msgstr ""
"No se seleccionó el mundo y no se ha especificado una dirección. Nada que "
"hacer."
#: src/main.cpp:1926
msgid "Provided world path doesn't exist: "
msgstr "La ruta del mundo especificada no existe: "
#: src/main.cpp:1935
msgid "Could not find or load game \""
msgstr "No se puede encontrar o cargar el juego \""
#: src/main.cpp:1953
msgid "Invalid gamespec."
msgstr "Juego especificado no válido."
msgid ""
"Default Controls:\n"
"- WASD: move\n"
"- Space: jump/climb\n"
"- Shift: sneak/go down\n"
"- Q: drop item\n"
"- I: inventory\n"
"- Mouse: turn/look\n"
"- Mouse left: dig/punch\n"
"- Mouse right: place/use\n"
"- Mouse wheel: select item\n"
"- T: chat\n"
msgstr ""
"Controles predeterminados:\n"
"- WASD: moverse\n"
"- Espacio: saltar/subir\n"
"- Mayús.: puntillas/bajar\n"
"- Q: soltar objeto\n"
"- I: inventario\n"
"- Ratón: girar/mirar\n"
"- Ratón izq.: cavar/golpear\n"
"- Ratón der.: colocar/usar\n"
"- Ratón rueda: elegir objeto\n"
"- T: chat\n"
msgid "is required by:"
msgstr "es requerido por:"
msgid "Configuration saved. "
msgstr "Configuración guardada. "
msgid "Warning: Configuration not consistent. "
msgstr "Advertencia: La configuración no es coherente."
msgid "Cannot create world: Name contains invalid characters"
msgstr "No se puede crear el mundo: El nombre contiene caracteres no válidos"
msgid "Multiplayer"
msgstr "Multijugador"
msgid "Advanced"
msgstr "Avanzado"
msgid "Show Public"
msgstr "Mostrar público"
msgid "Show Favorites"
msgstr "Mostrar favoritos"
msgid "Leave address blank to start a local server."
msgstr "Dejar la dirección en blanco para iniciar un servidor local."
msgid "Address required."
msgstr "Requiere una dirección."
msgid "Cannot delete world: Nothing selected"
msgstr "No se puede eliminar el mundo: Ninguno seleccionado"
msgid "Files to be deleted"
msgstr "Archivos que se eliminarán"
msgid "Cannot create world: No games found"
msgstr "No se puede crear el mundo: No se encontraron juegos"
msgid "Cannot configure world: Nothing selected"
msgstr "No se puede configurar el mundo: Ninguno seleccionado"
msgid "Failed to delete all world files"
msgstr "No se pudo eliminar todos los archivos del mundo"
msgid ""
"Warning: Some configured mods are missing.\n"
"Their setting will be removed when you save the configuration. "
msgstr ""
"Advertencia: Algunos mods configurados faltan.\n"
"Sus ajustes se eliminarán al guardar la configuración. "
msgid ""
"Warning: Some mods are not configured yet.\n"
"They will be enabled by default when you save the configuration. "
msgstr ""
"Advertencia: Algunos mods todavía no están configurados.\n"
"Se habilitarán de forma predeterminada al guardar la configuración. "
msgid "Exit to OS"
msgstr "Salir al S.O."
msgid "Exit to Menu"
msgstr "Salir al menú"
msgid "Sound Volume"
msgstr "Volumen del sonido"
msgid "Change Password"
msgstr "Cambiar contraseña"
msgid "Continue"
msgstr "Continuar"
msgid "You died."
msgstr "Has muerto."
msgid "Shutting down..."
msgstr "Cerrando..."
msgid "Connecting to server..."
msgstr "Conectando al servidor..."
msgid "Resolving address..."
msgstr "Resolviendo dirección..."
msgid "Creating client..."
msgstr "Creando cliente..."
msgid "Creating server...."
msgstr "Creando servidor..."
msgid "Loading..."
msgstr "Cargando..."
msgid "Local install"
msgstr "Instalación local"
msgid "Preload item visuals"
msgstr "Precarga elementos visuales"
msgid "Password"
msgstr "Contraseña"
msgid "Name"
msgstr "Nombre"
msgid "Favorites:"
msgstr "Favoritos:"
msgid "<<-- Add mod"
msgstr "<<-- Añadir mod"
msgid "Remove selected mod"
msgstr "Eliminar el mod seleccionado"
msgid "Mods:"
msgstr "Mods:"
msgid "Games"
msgstr "Juegos"
msgid "Gamemgr: Unable to copy mod \"$1\" to game \"$2\""
msgstr "Gamemgr: Imposible copiar el mod \"$1\" al juego \"$2\""
msgid "Game Name"
msgstr "Nombre del juego"
msgid "Change Keys"
msgstr "Configurar teclas"
msgid "Name/Password"
msgstr "Nombre / contraseña:"
msgid "Node Highlighting"
msgstr "Resaltar nodos"
msgid "Texturing:"
msgstr "Texturizado:"
msgid "Rendering:"
msgstr "Renderizado:"
msgid "Rebuilding shaders..."
msgstr "Reconstruyendo sombreadores..."
msgid "Initializing nodes..."
msgstr "Inicializando nodos..."
msgid "Done!"
msgstr "¡Completado!"

View File

@ -1,239 +1,26 @@
# SOME DESCRIPTIVE TITLE.
# Copyright (C) YEAR THE PACKAGE'S COPYRIGHT HOLDER
# This file is distributed under the same license as the PACKAGE package.
# FIRST AUTHOR <EMAIL@ADDRESS>, YEAR.
#
msgid ""
msgstr ""
"Project-Id-Version: minetest\n"
"Report-Msgid-Bugs-To: \n"
"POT-Creation-Date: 2013-11-23 17:37+0100\n"
"PO-Revision-Date: 2014-12-28 15:48+0900\n"
"POT-Creation-Date: 2015-02-14 23:12+0900\n"
"PO-Revision-Date: 2015-02-22 10:57+0900\n"
"Last-Translator: Rui Takeda <mrrst0914@gmail.com>\n"
"Language-Team: Japanese\n"
"Language-Team: Japanese <minetest_jp@m.add.ac>\n"
"Language: ja\n"
"MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=UTF-8\n"
"Content-Transfer-Encoding: 8bit\n"
"Plural-Forms: nplurals=1; plural=0;\n"
"X-Generator: Poedit 1.6.5\n"
"Language: ja_JP\n"
"X-Poedit-SourceCharset: UTF-8\n"
msgid "Game Name"
msgstr "ゲーム名"
msgid "Create"
msgstr "作成"
msgid "Cancel"
msgstr "キャンセル"
msgid "Gamemgr: Unable to copy mod \"$1\" to game \"$2\""
msgstr "Gamemgr: \"$1\"のModを \"$2\" にコピーできません"
msgid "Games"
msgstr "ゲーム"
msgid "Mods:"
msgstr "Mod:"
msgid "edit game"
msgstr "ゲーム編集"
msgid "new game"
msgstr "新規ゲーム"
msgid "Remove selected mod"
msgstr "選択したModを削除"
msgid "Ok"
msgstr "決定"
msgid "World name"
msgstr "ワールド名"
msgid "Seed"
msgstr "シード値"
msgid "Mapgen"
msgstr "マップ生成"
msgid "Game"
msgstr "ゲーム"
msgid "Delete World \"$1\"?"
msgstr "\"$1\"のワールドを削除しますか?"
msgid "Yes"
msgstr "はい"
msgid "No"
msgstr "いいえ"
msgid "A world named \"$1\" already exists"
msgstr "\"$1\"という名前のワールドを作成できません。同名のワールドが存在しています"
msgid "No worldname given or no game selected"
msgstr "ワールド名が入力されていないか、ゲームが選択されていません"
msgid "To enable shaders the OpenGL driver needs to be used."
msgstr "シェーダーを有効にするには、OpenGLのドライバが必要です"
msgid "Address/Port"
msgstr "アドレス/ポート"
msgid "Name/Password"
msgstr "名前/パスワード"
msgid "Public Serverlist"
msgstr "公開されているサーバーリスト"
msgid "Delete"
msgstr "削除"
msgid "Connect"
msgstr "接続"
msgid "New"
msgstr "作成"
msgid "Configure"
msgstr "設定"
msgid "Start Game"
msgstr "ゲームスタート"
msgid "Select World:"
msgstr "ワールド選択:"
msgid "Creative Mode"
msgstr "クリエイティブモード"
msgid "Enable Damage"
msgstr "ダメージ有効"
msgid "Public"
msgstr "公開する"
msgid "Name"
msgstr "名前"
msgid "Password"
msgstr "パスワード"
msgid "Server Port"
msgstr "ポート"
msgid "Fancy Trees"
msgstr "きれいな木"
msgid "Smooth Lighting"
msgstr "自然な光"
msgid "3D Clouds"
msgstr "立体な雲"
msgid "Opaque Water"
msgstr "不透明な水面"
msgid "Mip-Mapping"
msgstr "ミップマップ"
msgid "Anisotropic Filtering"
msgstr "異方性フィルタリング"
msgid "Bi-Linear Filtering"
msgstr "バイリニアフィルタリング"
msgid "Tri-Linear Filtering"
msgstr "トリリニアフィルタリング"
msgid "Shaders"
msgstr "シェーダー"
msgid "Connected Glass"
msgstr "ガラスを繋げる"
msgid "Enable Particles"
msgstr "破片の有効化"
msgid "Finite Liquid"
msgstr "液体の制限"
msgid "Change keys"
msgstr "キー割当て変更"
msgid "Play"
msgstr "ゲームスタート"
msgid "Select texture pack:"
msgstr "テクスチャパックを選択:"
msgid "No information available"
msgstr "情報がありません"
msgid "Core Developers"
msgstr "開発者"
msgid "Active Contributors"
msgstr "貢献者"
msgid "Previous Contributors"
msgstr "以前の貢献者"
msgid "Singleplayer"
msgstr "シングルプレイ"
msgid "Client"
msgstr "クライアント"
msgid "Server"
msgstr "マルチプレイ"
msgid "Settings"
msgstr "設定"
msgid "Texturepacks"
msgstr "テクスチャパック"
msgid "Mods"
msgstr "Mod"
msgid "Credits"
msgstr "クレジット"
msgid "Installed Mods:"
msgstr "インストール済みのMod:"
msgid "Online mod repository"
msgstr "オンラインで検索"
msgid "No mod description available"
msgstr "Modの説明がありません"
msgid "Mod information:"
msgstr "Modの情報:"
msgid "Rename"
msgstr "名前を変更"
msgid "Uninstall selected modpack"
msgstr "選択したModパックを削除"
msgid "Uninstall selected mod"
msgstr "選択したModを削除"
msgid "Rename Modpack:"
msgstr "Modパックの名前を変更"
msgid "Accept"
msgstr "了承"
msgid "World:"
msgstr "ワールド:"
msgid "Hide Game"
msgstr "内部Mod"
msgstr "ゲームを隠す"
msgid "Hide mp content"
msgstr "Modパックの簡略化"
@ -247,6 +34,9 @@ msgstr "依存Mod:"
msgid "Save"
msgstr "保存"
msgid "Cancel"
msgstr "キャンセル"
msgid "Enable MP"
msgstr "有効化"
@ -257,22 +47,103 @@ msgid "enabled"
msgstr "有効化"
msgid "Enable all"
msgstr "て有効化"
msgstr "すべて有効化"
msgid "Modmgr: failed to delete \"$1\""
msgstr "Modmgr: \"$1\"の削除に失敗しました"
msgid "World name"
msgstr "ワールド名"
msgid "Modmgr: invalid modpath \"$1\""
msgstr "Modmgr: \"$1\"は無効なModパスです"
msgid "Seed"
msgstr "Seed値"
msgid "Mapgen"
msgstr "ワールドタイプ"
msgid "Game"
msgstr "ゲーム"
msgid "Create"
msgstr "作成"
msgid "You have no subgames installed."
msgstr "ゲームがインストールされていません。"
msgid "Download one from minetest.net"
msgstr "minetest.netから再ダウンロードしてください。"
msgid "Warning: The minimal development test is meant for developers."
msgstr "警告:Minimal development testは開発者のためのゲームです。"
msgid "Download a subgame, such as minetest_game, from minetest.net"
msgstr "minetest.netからminetest_gameのゲームをダウンロードしてください。"
msgid "A world named \"$1\" already exists"
msgstr "ワールド名\"$1\"はすでに使用されています。"
msgid "No worldname given or no game selected"
msgstr "ワールド名が入力されていないか、ゲームが選択されていません。"
msgid "Are you sure you want to delete \"$1\"?"
msgstr "\"$1\"を削除してよろしいですか?"
msgstr "本当に\"$1\"を削除してよろしいですか?"
msgid "Yes"
msgstr "はい"
msgid "No of course not!"
msgstr "違います!"
msgstr "いいえ"
msgid "Page $1 of $2"
msgstr "ページ $1/$2"
msgid "Modmgr: failed to delete \"$1\""
msgstr "Modマネージャー:\"$1\"の削除に失敗しました。"
msgid "Modmgr: invalid modpath \"$1\""
msgstr "Modマネージャー:Mod\"$1\"の場所が不明です。"
msgid "Delete World \"$1\"?"
msgstr "ワールド\"$1\"を削除してよろしいですか?"
msgid "No"
msgstr "いいえ"
msgid "Rename Modpack:"
msgstr "名前を変更"
msgid "Accept"
msgstr "決定"
msgid "Install Mod: file: \"$1\""
msgstr "Modインストール:ファイル\"$1\"からModをインストールします。"
msgid ""
"\n"
"Install Mod: unsupported filetype \"$1\" or broken archive"
msgstr ""
"\n"
"Modインストール:ファイル\"$1\"は非対応の形式か、壊れています。"
msgid "Failed to install $1 to $2"
msgstr "$2へ$1をインストールできませんでした。"
msgid "Install Mod: unable to find suitable foldername for modpack $1"
msgstr ""
"Modインストール:Modパック$1に適したフォルダ名を見つけることができませんでし"
"た。"
msgid "Install Mod: unable to find real modname for: $1"
msgstr "Modインストール:$1の本来のMod名が不明です。"
msgid "Unsorted"
msgstr "未分類"
msgid "Search"
msgstr "検索"
msgid "Downloading $1, please wait..."
msgstr "$1をダウンロードしています。しばらくお待ちください..."
msgid "Successfully installed:"
msgstr "インストールが完了しました。:"
msgid "Shortname:"
msgstr "省略名"
msgid "Rating"
msgstr "評価"
@ -283,63 +154,415 @@ msgstr "再インストール"
msgid "Install"
msgstr "インストール"
msgid "Close store"
msgstr "閉じる"
msgid "Page $1 of $2"
msgstr "ページ $1/$2"
msgid "Credits"
msgstr "クレジット"
msgid "Core Developers"
msgstr "開発者"
msgid "Active Contributors"
msgstr "開発協力者"
msgid "Previous Contributors"
msgstr "以前の開発協力者"
msgid "Installed Mods:"
msgstr "インストール済みのMod:"
msgid "Online mod repository"
msgstr "オンラインでModを検索"
msgid "No mod description available"
msgstr "Modの説明がありません。"
msgid "Mod information:"
msgstr "Modの情報:"
msgid "Rename"
msgstr "名前を変更"
msgid "Uninstall selected modpack"
msgstr "選択したModパックを削除"
msgid "Uninstall selected mod"
msgstr "選択したModを削除"
msgid "Select Mod File:"
msgstr "Modファイルを選択"
msgid "Mods"
msgstr "Mod"
msgid "Address / Port :"
msgstr "アドレスとポート:"
msgid "Name / Password :"
msgstr "名前とパスワード:"
msgid "Public Serverlist"
msgstr "公開済みのサーバーの一覧"
msgid "Delete"
msgstr "削除"
msgid "Connect"
msgstr "接続"
msgid "Creative mode"
msgstr "クリエイティブモード"
msgid "Damage enabled"
msgstr "HPあり"
msgid "PvP enabled"
msgstr "PvPあり"
msgid "Client"
msgstr "クライアント"
msgid "New"
msgstr "作成"
msgid "Configure"
msgstr "設定"
msgid "Start Game"
msgstr "ゲームスタート"
msgid "Select World:"
msgstr "ワールドを選択:"
msgid "Creative Mode"
msgstr "クリエイティブモード"
msgid "Enable Damage"
msgstr "ダメージあり"
msgid "Public"
msgstr "サーバーを公開する"
msgid "Name/Password"
msgstr "名前とパスワード"
msgid "Bind Address"
msgstr "バインドアドレス"
msgid "Port"
msgstr "ポート"
msgid "Server Port"
msgstr "サーバーのポート"
msgid "Server"
msgstr "サーバー"
msgid "No Filter"
msgstr "フィルタ無し"
msgid "Bilinear Filter"
msgstr "バイリニアフィルタ"
msgid "Trilinear Filter"
msgstr "トリリニアフィルタ"
msgid "No Mipmap"
msgstr "ミップマップ無し"
msgid "Mipmap"
msgstr "ミップマップ"
msgid "Mipmap + Aniso. Filter"
msgstr "異方性フィルタ"
msgid "Are you sure to reset your singleplayer world?"
msgstr "シングルプレイヤーのワールドをリセットしてよろしいですか?"
msgid "No!!!"
msgstr "いいえ"
msgid "Smooth Lighting"
msgstr "滑らかな光"
msgid "Enable Particles"
msgstr "パーティクル有効化"
msgid "3D Clouds"
msgstr "立体の雲"
msgid "Fancy Trees"
msgstr "綺麗な木"
msgid "Opaque Water"
msgstr "不透明な水"
msgid "Connected Glass"
msgstr "ガラスをつなげる"
msgid "Node Highlighting"
msgstr "ノードの強調"
msgid "Texturing:"
msgstr "テクスチャリング:"
msgid "Rendering:"
msgstr "レンダリング:"
msgid "Restart minetest for driver change to take effect"
msgstr "ドライバーを変更するためMinetesを再起動します"
msgid "Shaders"
msgstr "シェーダー"
msgid "Change keys"
msgstr "操作変更"
msgid "Reset singleplayer world"
msgstr "シングルプレイヤーのワールドをリセット"
msgid "GUI scale factor"
msgstr "メニューの大きさ"
msgid "Scaling factor applied to menu elements: "
msgstr "メニューの大きさとして設定する数値:"
msgid "Touch free target"
msgstr "タッチ位置を自由にする"
msgid "Touchthreshold (px)"
msgstr "タッチのしきい値(ピクセル単位)"
msgid "Bumpmapping"
msgstr "バンプマッピング"
msgid "Generate Normalmaps"
msgstr "ノーマルマップの生成"
msgid "Parallax Occlusion"
msgstr "視差遮蔽マッピング"
msgid "Waving Water"
msgstr "揺れる水"
msgid "Waving Leaves"
msgstr "揺れる葉"
msgid "Waving Plants"
msgstr "揺れる草花"
msgid "To enable shaders the OpenGL driver needs to be used."
msgstr "シェーダーを有効にするにはOpenGLを使用する必要があります。"
msgid "Settings"
msgstr "設定"
msgid "Fly mode"
msgstr "飛行モード"
msgid "Start Singleplayer"
msgstr "ゲームスタート"
msgid "Config mods"
msgstr "Mod設定"
msgid "Main"
msgstr "メイン"
msgid "Play"
msgstr "ゲームスタート"
msgid "Singleplayer"
msgstr "シングルプレイヤー"
msgid "Select texture pack:"
msgstr "テクスチャパックを選択:"
msgid "No information available"
msgstr "情報がありません。"
msgid "Texturepacks"
msgstr "テクスチャパック"
msgid "Loading textures..."
msgstr "テクスチャ読み込み中..."
msgid "Rebuilding shaders..."
msgstr "シェーダー構築中..."
msgid "Initializing nodes..."
msgstr "ノードの設定中..."
msgid "Item textures..."
msgstr "アイテムのテクスチャ設定中..."
msgstr "アイテムのテクスチャを設定中..."
msgid "Done!"
msgstr "完了!"
msgid "Main Menu"
msgstr "メインメニュー"
msgid "Player name too long."
msgstr "名前が長過ぎます。"
msgid "Connection error (timed out?)"
msgstr "接続失敗(またはタイムアウト)"
msgid "No world selected and no address provided. Nothing to do."
msgstr "ワールドが選択されていないアドレスです。続行できません。"
msgid "Provided world path doesn't exist: "
msgstr "ワールドが存在しません:"
msgid "Could not find or load game \""
msgstr "ゲーム\"の読み込みができません。"
msgid "Invalid gamespec."
msgstr "無効なgamespecです。"
msgid "needs_fallback_font"
msgstr "yes"
msgid "Proceed"
msgstr "決定"
msgid "You died."
msgstr "You died."
msgid "Respawn"
msgstr "Respawn"
msgid ""
"Default Controls:\n"
"No menu visible:\n"
"- single tap: button activate\n"
"- double tap: place/use\n"
"- slide finger: look around\n"
"Menu/Inventory visible:\n"
"- double tap (outside):\n"
" -->close\n"
"- touch stack, touch slot:\n"
" --> move stack\n"
"- touch&drag, tap 2nd finger\n"
" --> place single item to slot\n"
msgstr ""
"基本操作:\n"
"タッチによる操作\n"
"- シングルタップ:ブロックの破壊\n"
"- ダブルタップ:設置やアイテムの使用\n"
"- 指でスライド:見回す\n"
"メニュー(インベントリ)の操作\n"
"- ダブルタップ:\n"
"-- 閉じる\n"
"- アイテムスロットをタッチ:\n"
"-- アイテムの移動\n"
"- タッチしてドラッグ:\n"
"-- アイテムを置く\n"
msgid ""
"Default Controls:\n"
"- WASD: move\n"
"- Space: jump/climb\n"
"- Shift: sneak/go down\n"
"- Q: drop item\n"
"- I: inventory\n"
"- Mouse: turn/look\n"
"- Mouse left: dig/punch\n"
"- Mouse right: place/use\n"
"- Mouse wheel: select item\n"
"- T: chat\n"
msgstr ""
"基本操作:\n"
"- WASD:移動\n"
"- スペース:ジャンプ、登る\n"
"- Shift:スニーク、降りる\n"
"- Q:アイテムを落とす\n"
"- I:インベントリ\n"
"- マウス移動:見回す\n"
"- 左クリック:ブロック破壊\n"
"- 右クリック:設置や使用\n"
"- ホイール:アイテム選択\n"
"- T:チャット画面\n"
msgid "Continue"
msgstr "再開"
msgid "Change Password"
msgstr "パスワード変更"
msgid "Sound Volume"
msgstr "音量"
msgid "Change Keys"
msgstr "操作変更"
msgid "Exit to Menu"
msgstr "タイトル"
msgid "Exit to OS"
msgstr "終了"
msgid "Shutting down..."
msgstr "終了中..."
msgid "Loading..."
msgstr "ロード中..."
msgstr "読み込み中..."
msgid "Creating server..."
msgstr "サーバー構築中..."
msgstr "サーバー作成中..."
msgid "Creating client..."
msgstr "クライアント作成中..."
msgstr "クライアント作成中..."
msgid "Resolving address..."
msgstr "アドレス解決中..."
msgstr "アドレス解決中..."
msgid "Connecting to server..."
msgstr "サーバー接続中..."
msgstr "サーバー接続中..."
msgid "Item definitions..."
msgstr "アイテム定義中..."
msgstr "アイテム定義中..."
msgid "Node definitions..."
msgstr "ノード定義中..."
msgstr "ノード定義中..."
msgid "Media..."
msgstr "..."
msgid "Shutting down..."
msgstr "終了中..."
msgid " KB/s"
msgstr " KB/秒"
msgid " MB/s"
msgstr " MB/秒"
msgid ""
"\n"
"Check debug.txt for details."
msgstr ""
"\n"
"詳細はdebug.txtを御覧ください。"
"詳細はdebug.txtを覧ください。"
msgid "You died."
msgstr "You died!"
msgid "Enter "
msgstr "Enter"
msgid "Respawn"
msgstr "Respawn"
msgid "Proceed"
msgid "ok"
msgstr "決定"
msgid "Keybindings. (If this menu screws up, remove stuff from minetest.conf)"
msgstr "キーバインド"
msgstr "操作の設定を変更します。"
msgid "\"Use\" = climb down"
msgstr "「使う」キーで降りる"
msgstr "「使用」で降りる"
msgid "Double tap \"jump\" to toggle fly"
msgstr "ジャンプの二回押しで飛行"
msgstr "「ジャンプ」二回押しで飛行モード"
msgid "Key already in use"
msgstr "既に使われているキーです"
msgstr "すでに使われているキーです。"
msgid "press key"
msgstr "キー入力待ち"
@ -351,19 +574,19 @@ msgid "Backward"
msgstr "後退"
msgid "Left"
msgstr "左進む"
msgstr "左進む"
msgid "Right"
msgstr "右進む"
msgstr "右進む"
msgid "Use"
msgstr "使"
msgstr "使"
msgid "Jump"
msgstr "ジャンプ"
msgid "Sneak"
msgstr "こっそり進む"
msgstr "スニーク"
msgid "Drop"
msgstr "落とす"
@ -381,16 +604,16 @@ msgid "Console"
msgstr "コンソール"
msgid "Toggle fly"
msgstr "飛行"
msgstr "飛行モード"
msgid "Toggle fast"
msgstr "高速移動"
msgstr "高速移動モード"
msgid "Toggle noclip"
msgstr "すり抜け"
msgstr "すり抜けモード"
msgid "Range select"
msgstr "視野切り替え"
msgstr "視野範囲変更"
msgid "Print stacks"
msgstr "スタックの表示"
@ -408,53 +631,13 @@ msgid "Change"
msgstr "変更"
msgid "Passwords do not match!"
msgstr "パスワードが一致しません!"
msgid "Continue"
msgstr "続ける"
msgid "Change Password"
msgstr "パスワード変更"
msgid "Sound Volume"
msgstr "音量"
msgid "Exit to Menu"
msgstr "タイトル"
msgid "Exit to OS"
msgstr "終了"
msgid ""
"Default Controls:\n"
"- WASD: move\n"
"- Space: jump/climb\n"
"- Shift: sneak/go down\n"
"- Q: drop item\n"
"- I: inventory\n"
"- Mouse: turn/look\n"
"- Mouse left: dig/punch\n"
"- Mouse right: place/use\n"
"- Mouse wheel: select item\n"
"- T: chat\n"
msgstr ""
"基本操作:\n"
"WASD:移動\n"
"スペース:ジャンプ/登る\n"
"シフト:忍び歩き/降りる\n"
"Q:アイテムを落とす\n"
"I:インベントリ\n"
"マウス:見回す\n"
"左クリック:掘る/パンチ\n"
"右クリック:使う\n"
"マウスホイール:アイテム選択\n"
"T:チャット\n"
msgstr "パスワードが一致しません!"
msgid "Sound Volume: "
msgstr "音量"
msgstr "音量:"
msgid "Exit"
msgstr "る"
msgstr "閉じる"
msgid "Left Button"
msgstr "左ボタン"
@ -671,56 +854,3 @@ msgstr "PA1"
msgid "Zoom"
msgstr "ズーム"
msgid "needs_fallback_font"
msgstr "yes"
msgid "Main Menu"
msgstr "メインメニュー"
msgid "No world selected and no address provided. Nothing to do."
msgstr ""
"ワールドが選択できていないか、アドレスが入力されていません。そのため実行されませ"
"ん。"
msgid "Could not find or load game \""
msgstr "読み込みか検索に失敗: \""
msgid "Invalid gamespec."
msgstr "無効なgamespecです"
msgid "Connection error (timed out?)"
msgstr "接続エラー(タイムアウト)"
msgid "Bumpmapping"
msgstr "バンプマッピング"
msgid "Generate Normalmaps"
msgstr "法線マッピング"
msgid "Parallax Occlusion"
msgstr "視差オクルージョンマッピング"
msgid "Waving Water"
msgstr "揺れる水"
msgid "Waving Leaves"
msgstr "揺れる葉"
msgid "Waving Plants"
msgstr "揺れる草花"
msgid "GUI scale factor"
msgstr "メニューの大きさ"
msgid "Unsorted"
msgstr "未分類"
msgid "Search"
msgstr "検索"
msgid "Close store"
msgstr "閉じる"
msgid "Change Keys"
msgstr "操作変更"

1248
po/tr/minetest.po Normal file

File diff suppressed because it is too large Load Diff

View File

@ -355,9 +355,12 @@ add_subdirectory(jthread)
add_subdirectory(script)
add_subdirectory(util)
set (unittests_SRCS
test.cpp
)
set(common_SRCS
ban.cpp
base64.cpp
cavegen.cpp
clientiface.cpp
collision.cpp
@ -418,12 +421,10 @@ set(common_SRCS
serverlist.cpp
serverobject.cpp
settings.cpp
sha1.cpp
socket.cpp
sound.cpp
staticobject.cpp
subgame.cpp
test.cpp
tool.cpp
treegen.cpp
version.cpp
@ -432,6 +433,7 @@ set(common_SRCS
${JTHREAD_SRCS}
${common_SCRIPT_SRCS}
${UTIL_SRCS}
${unittests_SRCS}
)
# This gives us the icon and file version information

View File

@ -23,7 +23,22 @@ with this program; if not, write to the Free Software Foundation, Inc.,
#include "irr_aabb3d.h"
#include <string>
#define ACTIVEOBJECT_TYPE_INVALID 0
enum ActiveObjectType {
ACTIVEOBJECT_TYPE_INVALID = 0,
ACTIVEOBJECT_TYPE_TEST = 1,
// Deprecated stuff
ACTIVEOBJECT_TYPE_ITEM = 2,
ACTIVEOBJECT_TYPE_RAT = 3,
ACTIVEOBJECT_TYPE_OERKKI1 = 4,
ACTIVEOBJECT_TYPE_FIREFLY = 5,
ACTIVEOBJECT_TYPE_MOBV2 = 6,
// End deprecated stuff
ACTIVEOBJECT_TYPE_LUAENTITY = 7,
// Special type, not stored as a static object
ACTIVEOBJECT_TYPE_PLAYER = 100,
// Special type, only exists as CAO
ACTIVEOBJECT_TYPE_GENERIC = 101,
};
// Other types are defined in content_object.h
struct ActiveObjectMessage
@ -60,7 +75,7 @@ public:
m_id = id;
}
virtual u8 getType() const = 0;
virtual ActiveObjectType getType() const = 0;
virtual bool getCollisionBox(aabb3f *toset) = 0;
virtual bool collideWithObjects() = 0;
protected:

View File

@ -20,6 +20,7 @@ with this program; if not, write to the Free Software Foundation, Inc.,
#include "util/numeric.h"
#include "map.h"
#include "mapgen.h"
#include "mapgen_v5.h"
#include "mapgen_v6.h"
#include "mapgen_v7.h"
#include "cavegen.h"
@ -27,7 +28,263 @@ with this program; if not, write to the Free Software Foundation, Inc.,
NoiseParams nparams_caveliquids(0, 1, v3f(150.0, 150.0, 150.0), 776, 3, 0.6, 2.0);
///////////////////////////////////////////////////////////////////////////////
///////////////////////////////////////// Caves V5
CaveV5::CaveV5(MapgenV5 *mg, PseudoRandom *ps) {
this->mg = mg;
this->vm = mg->vm;
this->ndef = mg->ndef;
this->water_level = mg->water_level;
this->ps = ps;
this->c_water_source = mg->c_water_source;
this->c_lava_source = mg->c_lava_source;
this->c_ice = mg->c_ice;
this->np_caveliquids = &nparams_caveliquids;
dswitchint = ps->range(1, 14);
flooded = ps->range(1, 2) == 2;
part_max_length_rs = ps->range(2, 4);
tunnel_routepoints = ps->range(5, ps->range(15, 30));
min_tunnel_diameter = 5;
max_tunnel_diameter = ps->range(7, ps->range(8, 24));
large_cave_is_flat = (ps->range(0, 1) == 0);
}
void CaveV5::makeCave(v3s16 nmin, v3s16 nmax, int max_stone_height) {
node_min = nmin;
node_max = nmax;
main_direction = v3f(0, 0, 0);
// Allowed route area size in nodes
ar = node_max - node_min + v3s16(1, 1, 1);
// Area starting point in nodes
of = node_min;
// Allow a bit more
//(this should be more than the maximum radius of the tunnel)
s16 insure = 10;
s16 more = MYMAX(MAP_BLOCKSIZE - max_tunnel_diameter / 2 - insure, 1);
ar += v3s16(1,0,1) * more * 2;
of -= v3s16(1,0,1) * more;
route_y_min = 0;
// Allow half a diameter + 7 over stone surface
route_y_max = -of.Y + max_stone_y + max_tunnel_diameter / 2 + 7;
// Limit maximum to area
route_y_max = rangelim(route_y_max, 0, ar.Y - 1);
s16 min = 0;
if (node_min.Y < water_level && node_max.Y > water_level) {
min = water_level - max_tunnel_diameter/3 - of.Y;
route_y_max = water_level + max_tunnel_diameter/3 - of.Y;
}
route_y_min = ps->range(min, min + max_tunnel_diameter);
route_y_min = rangelim(route_y_min, 0, route_y_max);
s16 route_start_y_min = route_y_min;
s16 route_start_y_max = route_y_max;
route_start_y_min = rangelim(route_start_y_min, 0, ar.Y - 1);
route_start_y_max = rangelim(route_start_y_max, route_start_y_min, ar.Y - 1);
// Randomize starting position
orp = v3f(
(float)(ps->next() % ar.X) + 0.5,
(float)(ps->range(route_start_y_min, route_start_y_max)) + 0.5,
(float)(ps->next() % ar.Z) + 0.5
);
// Add generation notify begin event
v3s16 abs_pos(of.X + orp.X, of.Y + orp.Y, of.Z + orp.Z);
GenNotifyType notifytype = GENNOTIFY_LARGECAVE_BEGIN;
mg->gennotify.addEvent(notifytype, abs_pos);
// Generate some tunnel starting from orp
for (u16 j = 0; j < tunnel_routepoints; j++)
makeTunnel(j % dswitchint == 0);
// Add generation notify end event
abs_pos = v3s16(of.X + orp.X, of.Y + orp.Y, of.Z + orp.Z);
notifytype = GENNOTIFY_LARGECAVE_END;
mg->gennotify.addEvent(notifytype, abs_pos);
}
void CaveV5::makeTunnel(bool dirswitch) {
// Randomize size
s16 min_d = min_tunnel_diameter;
s16 max_d = max_tunnel_diameter;
rs = ps->range(min_d, max_d);
s16 rs_part_max_length_rs = rs * part_max_length_rs;
v3s16 maxlen;
maxlen = v3s16(
rs_part_max_length_rs,
rs_part_max_length_rs / 2,
rs_part_max_length_rs
);
v3f vec;
// Jump downward sometimes
vec = v3f(
(float)(ps->next() % maxlen.X) - (float)maxlen.X / 2,
(float)(ps->next() % maxlen.Y) - (float)maxlen.Y / 2,
(float)(ps->next() % maxlen.Z) - (float)maxlen.Z / 2
);
// Do not make large caves that are above ground.
// It is only necessary to check the startpoint and endpoint.
v3s16 orpi(orp.X, orp.Y, orp.Z);
v3s16 veci(vec.X, vec.Y, vec.Z);
v3s16 p;
p = orpi + veci + of + rs / 2;
if (p.Z >= node_min.Z && p.Z <= node_max.Z &&
p.X >= node_min.X && p.X <= node_max.X) {
u32 index = (p.Z - node_min.Z) * mg->ystride + (p.X - node_min.X);
s16 h = mg->heightmap[index];
if (h < p.Y)
return;
} else if (p.Y > water_level) {
return; // If it's not in our heightmap, use a simple heuristic
}
p = orpi + of + rs / 2;
if (p.Z >= node_min.Z && p.Z <= node_max.Z &&
p.X >= node_min.X && p.X <= node_max.X) {
u32 index = (p.Z - node_min.Z) * mg->ystride + (p.X - node_min.X);
s16 h = mg->heightmap[index];
if (h < p.Y)
return;
} else if (p.Y > water_level) {
return;
}
vec += main_direction;
v3f rp = orp + vec;
if (rp.X < 0)
rp.X = 0;
else if (rp.X >= ar.X)
rp.X = ar.X - 1;
if (rp.Y < route_y_min)
rp.Y = route_y_min;
else if (rp.Y >= route_y_max)
rp.Y = route_y_max - 1;
if (rp.Z < 0)
rp.Z = 0;
else if (rp.Z >= ar.Z)
rp.Z = ar.Z - 1;
vec = rp - orp;
float veclen = vec.getLength();
if (veclen < 0.05)
veclen = 1.0;
// Every second section is rough
bool randomize_xz = (ps->range(1, 2) == 1);
// Make a ravine every once in a while if it's long enough
//float xylen = vec.X * vec.X + vec.Z * vec.Z;
//disable ravines for now
bool is_ravine = false; //(xylen > 500.0) && !large_cave && (ps->range(1, 8) == 1);
// Carve routes
for (float f = 0; f < 1.0; f += 1.0 / veclen)
carveRoute(vec, f, randomize_xz, is_ravine);
orp = rp;
}
void CaveV5::carveRoute(v3f vec, float f, bool randomize_xz, bool is_ravine) {
MapNode airnode(CONTENT_AIR);
MapNode waternode(c_water_source);
MapNode lavanode(c_lava_source);
v3s16 startp(orp.X, orp.Y, orp.Z);
startp += of;
float nval = NoisePerlin3D(np_caveliquids, startp.X,
startp.Y, startp.Z, mg->seed);
MapNode liquidnode = nval < 0.40 ? lavanode : waternode;
v3f fp = orp + vec * f;
fp.X += 0.1 * ps->range(-10, 10);
fp.Z += 0.1 * ps->range(-10, 10);
v3s16 cp(fp.X, fp.Y, fp.Z);
s16 d0 = -rs/2;
s16 d1 = d0 + rs;
if (randomize_xz) {
d0 += ps->range(-1, 1);
d1 += ps->range(-1, 1);
}
bool should_make_cave_hole = ps->range(1, 10) == 1;
for (s16 z0 = d0; z0 <= d1; z0++) {
s16 si = rs / 2 - MYMAX(0, abs(z0) - rs / 7 - 1);
for (s16 x0 = -si - ps->range(0,1); x0 <= si - 1 + ps->range(0,1); x0++) {
s16 maxabsxz = MYMAX(abs(x0), abs(z0));
s16 si2 = is_ravine ? MYMIN(ps->range(25, 26), ar.Y) :
rs / 2 - MYMAX(0, maxabsxz - rs / 7 - 1);
for (s16 y0 = -si2; y0 <= si2; y0++) {
if (large_cave_is_flat) {
// Make large caves not so tall
if (rs > 7 && abs(y0) >= rs / 3)
continue;
}
v3s16 p(cp.X + x0, cp.Y + y0, cp.Z + z0);
p += of;
if (!is_ravine && mg->heightmap && should_make_cave_hole &&
p.X <= node_max.X && p.Z <= node_max.Z) {
int maplen = node_max.X - node_min.X + 1;
int idx = (p.Z - node_min.Z) * maplen + (p.X - node_min.X);
if (p.Y >= mg->heightmap[idx] - 2)
continue;
}
if (vm->m_area.contains(p) == false)
continue;
u32 i = vm->m_area.index(p);
// Don't replace air, water, lava, or ice
content_t c = vm->m_data[i].getContent();
if (!ndef->get(c).is_ground_content || c == CONTENT_AIR ||
c == c_water_source || c == c_lava_source || c == c_ice)
continue;
int full_ymin = node_min.Y - MAP_BLOCKSIZE;
int full_ymax = node_max.Y + MAP_BLOCKSIZE;
if (flooded && full_ymin < water_level && full_ymax > water_level)
vm->m_data[i] = (p.Y <= water_level) ? waternode : airnode;
else if (flooded && full_ymax < water_level)
vm->m_data[i] = (p.Y < startp.Y - 4) ? liquidnode : airnode;
else
vm->m_data[i] = airnode;
}
}
}
}
///////////////////////////////////////// Caves V6
CaveV6::CaveV6(MapgenV6 *mg, PseudoRandom *ps, PseudoRandom *ps2, bool is_large_cave) {
@ -141,37 +398,68 @@ void CaveV6::makeTunnel(bool dirswitch) {
s16 min_d = min_tunnel_diameter;
s16 max_d = max_tunnel_diameter;
rs = ps->range(min_d, max_d);
s16 rs_part_max_length_rs = rs * part_max_length_rs;
v3s16 maxlen;
if (large_cave) {
maxlen = v3s16(
rs * part_max_length_rs,
rs * part_max_length_rs / 2,
rs * part_max_length_rs
rs_part_max_length_rs,
rs_part_max_length_rs / 2,
rs_part_max_length_rs
);
} else {
maxlen = v3s16(
rs * part_max_length_rs,
ps->range(1, rs * part_max_length_rs),
rs * part_max_length_rs
rs_part_max_length_rs,
ps->range(1, rs_part_max_length_rs),
rs_part_max_length_rs
);
}
v3f vec(
(float)(ps->next() % (maxlen.X * 1)) - (float)maxlen.X / 2,
(float)(ps->next() % (maxlen.Y * 1)) - (float)maxlen.Y / 2,
(float)(ps->next() % (maxlen.Z * 1)) - (float)maxlen.Z / 2
(float)(ps->next() % maxlen.X) - (float)maxlen.X / 2,
(float)(ps->next() % maxlen.Y) - (float)maxlen.Y / 2,
(float)(ps->next() % maxlen.Z) - (float)maxlen.Z / 2
);
// Jump downward sometimes
if (!large_cave && ps->range(0, 12) == 0) {
vec = v3f(
(float)(ps->next() % (maxlen.X * 1)) - (float)maxlen.X / 2,
(float)(ps->next() % maxlen.X) - (float)maxlen.X / 2,
(float)(ps->next() % (maxlen.Y * 2)) - (float)maxlen.Y,
(float)(ps->next() % (maxlen.Z * 1)) - (float)maxlen.Z / 2
(float)(ps->next() % maxlen.Z) - (float)maxlen.Z / 2
);
}
// Do not make large caves that are entirely above ground.
// It is only necessary to check the startpoint and endpoint.
if (large_cave) {
v3s16 orpi(orp.X, orp.Y, orp.Z);
v3s16 veci(vec.X, vec.Y, vec.Z);
s16 h1;
s16 h2;
v3s16 p1 = orpi + veci + of + rs / 2;
if (p1.Z >= node_min.Z && p1.Z <= node_max.Z &&
p1.X >= node_min.X && p1.X <= node_max.X) {
u32 index1 = (p1.Z - node_min.Z) * mg->ystride + (p1.X - node_min.X);
h1 = mg->heightmap[index1];
} else {
h1 = water_level; // If not in heightmap
}
v3s16 p2 = orpi + of + rs / 2;
if (p2.Z >= node_min.Z && p2.Z <= node_max.Z &&
p2.X >= node_min.X && p2.X <= node_max.X) {
u32 index2 = (p2.Z - node_min.Z) * mg->ystride + (p2.X - node_min.X);
h2 = mg->heightmap[index2];
} else {
h2 = water_level;
}
if (p1.Y > h1 && p2.Y > h2) // If startpoint and endpoint are above ground
return;
}
vec += main_direction;
v3f rp = orp + vec;
@ -279,12 +567,12 @@ void CaveV6::carveRoute(v3f vec, float f, bool randomize_xz) {
///////////////////////////////////////// Caves V7
CaveV7::CaveV7(MapgenV7 *mg, PseudoRandom *ps, bool is_large_cave) {
CaveV7::CaveV7(MapgenV7 *mg, PseudoRandom *ps) {
this->mg = mg;
this->vm = mg->vm;
this->ndef = mg->ndef;
this->water_level = mg->water_level;
this->large_cave = is_large_cave;
this->ps = ps;
this->c_water_source = mg->c_water_source;
this->c_lava_source = mg->c_lava_source;
@ -294,17 +582,10 @@ CaveV7::CaveV7(MapgenV7 *mg, PseudoRandom *ps, bool is_large_cave) {
dswitchint = ps->range(1, 14);
flooded = ps->range(1, 2) == 2;
if (large_cave) {
part_max_length_rs = ps->range(2, 4);
tunnel_routepoints = ps->range(5, ps->range(15, 30));
min_tunnel_diameter = 5;
max_tunnel_diameter = ps->range(7, ps->range(8, 24));
} else {
part_max_length_rs = ps->range(2, 9);
tunnel_routepoints = ps->range(10, ps->range(15, 30));
min_tunnel_diameter = 2;
max_tunnel_diameter = ps->range(2, 6);
}
part_max_length_rs = ps->range(2, 4);
tunnel_routepoints = ps->range(5, ps->range(15, 30));
min_tunnel_diameter = 5;
max_tunnel_diameter = ps->range(7, ps->range(8, 24));
large_cave_is_flat = (ps->range(0, 1) == 0);
}
@ -335,15 +616,13 @@ void CaveV7::makeCave(v3s16 nmin, v3s16 nmax, int max_stone_height) {
// Limit maximum to area
route_y_max = rangelim(route_y_max, 0, ar.Y - 1);
if (large_cave) {
s16 min = 0;
if (node_min.Y < water_level && node_max.Y > water_level) {
min = water_level - max_tunnel_diameter/3 - of.Y;
route_y_max = water_level + max_tunnel_diameter/3 - of.Y;
}
route_y_min = ps->range(min, min + max_tunnel_diameter);
route_y_min = rangelim(route_y_min, 0, route_y_max);
s16 min = 0;
if (node_min.Y < water_level && node_max.Y > water_level) {
min = water_level - max_tunnel_diameter/3 - of.Y;
route_y_max = water_level + max_tunnel_diameter/3 - of.Y;
}
route_y_min = ps->range(min, min + max_tunnel_diameter);
route_y_min = rangelim(route_y_min, 0, route_y_max);
s16 route_start_y_min = route_y_min;
s16 route_start_y_max = route_y_max;
@ -360,8 +639,7 @@ void CaveV7::makeCave(v3s16 nmin, v3s16 nmax, int max_stone_height) {
// Add generation notify begin event
v3s16 abs_pos(of.X + orp.X, of.Y + orp.Y, of.Z + orp.Z);
GenNotifyType notifytype = large_cave ?
GENNOTIFY_LARGECAVE_BEGIN : GENNOTIFY_CAVE_BEGIN;
GenNotifyType notifytype = GENNOTIFY_LARGECAVE_BEGIN;
mg->gennotify.addEvent(notifytype, abs_pos);
// Generate some tunnel starting from orp
@ -370,86 +648,60 @@ void CaveV7::makeCave(v3s16 nmin, v3s16 nmax, int max_stone_height) {
// Add generation notify end event
abs_pos = v3s16(of.X + orp.X, of.Y + orp.Y, of.Z + orp.Z);
notifytype = large_cave ?
GENNOTIFY_LARGECAVE_END : GENNOTIFY_CAVE_END;
notifytype = GENNOTIFY_LARGECAVE_END;
mg->gennotify.addEvent(notifytype, abs_pos);
}
void CaveV7::makeTunnel(bool dirswitch) {
if (dirswitch && !large_cave) {
main_direction = v3f(
((float)(ps->next() % 20) - (float)10) / 10,
((float)(ps->next() % 20) - (float)10) / 30,
((float)(ps->next() % 20) - (float)10) / 10
);
main_direction *= (float)ps->range(0, 10) / 10;
}
// Randomize size
s16 min_d = min_tunnel_diameter;
s16 max_d = max_tunnel_diameter;
rs = ps->range(min_d, max_d);
s16 rs_part_max_length_rs = rs * part_max_length_rs;
v3s16 maxlen;
if (large_cave) {
maxlen = v3s16(
rs * part_max_length_rs,
rs * part_max_length_rs / 2,
rs * part_max_length_rs
);
} else {
maxlen = v3s16(
rs * part_max_length_rs,
ps->range(1, rs * part_max_length_rs),
rs * part_max_length_rs
);
}
maxlen = v3s16(
rs_part_max_length_rs,
rs_part_max_length_rs / 2,
rs_part_max_length_rs
);
v3f vec;
// Jump downward sometimes
if (!large_cave && ps->range(0, 12) == 0) {
vec = v3f(
(float)(ps->next() % (maxlen.X * 1)) - (float)maxlen.X / 2,
(float)(ps->next() % (maxlen.Y * 2)) - (float)maxlen.Y,
(float)(ps->next() % (maxlen.Z * 1)) - (float)maxlen.Z / 2
);
} else {
vec = v3f(
(float)(ps->next() % (maxlen.X * 1)) - (float)maxlen.X / 2,
(float)(ps->next() % (maxlen.Y * 1)) - (float)maxlen.Y / 2,
(float)(ps->next() % (maxlen.Z * 1)) - (float)maxlen.Z / 2
);
}
vec = v3f(
(float)(ps->next() % maxlen.X) - (float)maxlen.X / 2,
(float)(ps->next() % maxlen.Y) - (float)maxlen.Y / 2,
(float)(ps->next() % maxlen.Z) - (float)maxlen.Z / 2
);
// Do not make large caves that are above ground.
// It is only necessary to check the startpoint and endpoint.
if (large_cave) {
v3s16 orpi(orp.X, orp.Y, orp.Z);
v3s16 veci(vec.X, vec.Y, vec.Z);
v3s16 p;
v3s16 orpi(orp.X, orp.Y, orp.Z);
v3s16 veci(vec.X, vec.Y, vec.Z);
v3s16 p;
p = orpi + veci + of + rs / 2;
if (p.Z >= node_min.Z && p.Z <= node_max.Z &&
p = orpi + veci + of + rs / 2;
if (p.Z >= node_min.Z && p.Z <= node_max.Z &&
p.X >= node_min.X && p.X <= node_max.X) {
u32 index = (p.Z - node_min.Z) * mg->ystride + (p.X - node_min.X);
s16 h = mg->ridge_heightmap[index];
if (h < p.Y)
return;
} else if (p.Y > water_level) {
return; // If it's not in our heightmap, use a simple heuristic
}
p = orpi + of + rs / 2;
if (p.Z >= node_min.Z && p.Z <= node_max.Z &&
p.X >= node_min.X && p.X <= node_max.X) {
u32 index = (p.Z - node_min.Z) * mg->ystride + (p.X - node_min.X);
s16 h = mg->ridge_heightmap[index];
if (h < p.Y)
return;
} else if (p.Y > water_level) {
u32 index = (p.Z - node_min.Z) * mg->ystride + (p.X - node_min.X);
s16 h = mg->ridge_heightmap[index];
if (h < p.Y)
return;
}
} else if (p.Y > water_level) {
return; // If it's not in our heightmap, use a simple heuristic
}
p = orpi + of + rs / 2;
if (p.Z >= node_min.Z && p.Z <= node_max.Z &&
p.X >= node_min.X && p.X <= node_max.X) {
u32 index = (p.Z - node_min.Z) * mg->ystride + (p.X - node_min.X);
s16 h = mg->ridge_heightmap[index];
if (h < p.Y)
return;
} else if (p.Y > water_level) {
return;
}
vec += main_direction;
@ -502,7 +754,7 @@ void CaveV7::carveRoute(v3f vec, float f, bool randomize_xz, bool is_ravine) {
float nval = NoisePerlin3D(np_caveliquids, startp.X,
startp.Y, startp.Z, mg->seed);
MapNode liquidnode = nval < 0.40 ? lavanode : waternode;
MapNode liquidnode = (nval < 0.40 && node_max.Y < -256) ? lavanode : waternode;
v3f fp = orp + vec * f;
fp.X += 0.1 * ps->range(-10, 10);
@ -516,7 +768,6 @@ void CaveV7::carveRoute(v3f vec, float f, bool randomize_xz, bool is_ravine) {
d1 += ps->range(-1, 1);
}
bool flat_cave_floor = !large_cave && ps->range(0, 2) == 2;
bool should_make_cave_hole = ps->range(1, 10) == 1;
for (s16 z0 = d0; z0 <= d1; z0++) {
@ -528,10 +779,6 @@ void CaveV7::carveRoute(v3f vec, float f, bool randomize_xz, bool is_ravine) {
rs / 2 - MYMAX(0, maxabsxz - rs / 7 - 1);
for (s16 y0 = -si2; y0 <= si2; y0++) {
// Make better floors in small caves
if(flat_cave_floor && y0 <= -rs/2 && rs<=7)
continue;
if (large_cave_is_flat) {
// Make large caves not so tall
if (rs > 7 && abs(y0) >= rs / 3)
@ -560,24 +807,17 @@ void CaveV7::carveRoute(v3f vec, float f, bool randomize_xz, bool is_ravine) {
c == c_water_source || c == c_lava_source || c == c_ice)
continue;
if (large_cave) {
int full_ymin = node_min.Y - MAP_BLOCKSIZE;
int full_ymax = node_max.Y + MAP_BLOCKSIZE;
if (flooded && full_ymin < water_level && full_ymax > water_level)
vm->m_data[i] = (p.Y <= water_level) ? waternode : airnode;
else if (flooded && full_ymax < water_level)
vm->m_data[i] = (p.Y < startp.Y - 4) ? liquidnode : airnode;
else
vm->m_data[i] = airnode;
} else {
if (c == CONTENT_IGNORE)
continue;
int full_ymin = node_min.Y - MAP_BLOCKSIZE;
int full_ymax = node_max.Y + MAP_BLOCKSIZE;
if (flooded && full_ymin < water_level && full_ymax > water_level)
vm->m_data[i] = (p.Y <= water_level) ? waternode : airnode;
else if (flooded && full_ymax < water_level)
vm->m_data[i] = (p.Y < startp.Y - 4) ? liquidnode : airnode;
else
vm->m_data[i] = airnode;
vm->m_flags[i] |= VMANIP_FLAG_CAVE;
}
}
}
}
}

View File

@ -22,9 +22,55 @@ with this program; if not, write to the Free Software Foundation, Inc.,
#define VMANIP_FLAG_CAVE VOXELFLAG_CHECKED1
class MapgenV5;
class MapgenV6;
class MapgenV7;
class CaveV5 {
public:
MapgenV5 *mg;
MMVManip *vm;
INodeDefManager *ndef;
NoiseParams *np_caveliquids;
s16 min_tunnel_diameter;
s16 max_tunnel_diameter;
u16 tunnel_routepoints;
int dswitchint;
int part_max_length_rs;
bool large_cave_is_flat;
bool flooded;
s16 max_stone_y;
v3s16 node_min;
v3s16 node_max;
v3f orp; // starting point, relative to caved space
v3s16 of; // absolute coordinates of caved space
v3s16 ar; // allowed route area
s16 rs; // tunnel radius size
v3f main_direction;
s16 route_y_min;
s16 route_y_max;
PseudoRandom *ps;
content_t c_water_source;
content_t c_lava_source;
content_t c_ice;
int water_level;
CaveV5() {}
CaveV5(MapgenV5 *mg, PseudoRandom *ps);
void makeCave(v3s16 nmin, v3s16 nmax, int max_stone_height);
void makeTunnel(bool dirswitch);
void carveRoute(v3f vec, float f, bool randomize_xz, bool is_ravine);
};
class CaveV6 {
public:
MapgenV6 *mg;
@ -83,7 +129,6 @@ public:
int dswitchint;
int part_max_length_rs;
bool large_cave;
bool large_cave_is_flat;
bool flooded;
@ -109,7 +154,7 @@ public:
int water_level;
CaveV7() {}
CaveV7(MapgenV7 *mg, PseudoRandom *ps, bool large_cave);
CaveV7(MapgenV7 *mg, PseudoRandom *ps);
void makeCave(v3s16 nmin, v3s16 nmax, int max_stone_height);
void makeTunnel(bool dirswitch);
void carveRoute(v3f vec, float f, bool randomize_xz, bool is_ravine);

View File

@ -29,6 +29,7 @@
*/
#include <irrlicht.h>
#include <iostream>
#include "CGUITTFont.h"
namespace irr
@ -64,8 +65,24 @@ scene::SMesh CGUITTFont::shared_plane_;
//
/** Checks that no dimension of the FT_BitMap object is negative. If either is
* negative, abort execution.
*/
inline void checkFontBitmapSize(const FT_Bitmap &bits)
{
if ((s32)bits.rows < 0 || (s32)bits.width < 0) {
std::cout << "Insane font glyph size. File: "
<< __FILE__ << " Line " << __LINE__
<< std::endl;
abort();
}
}
video::IImage* SGUITTGlyph::createGlyphImage(const FT_Bitmap& bits, video::IVideoDriver* driver) const
{
// Make sure our casts to s32 in the loops below will not cause problems
checkFontBitmapSize(bits);
// Determine what our texture size should be.
// Add 1 because textures are inclusive-exclusive.
core::dimension2du d(bits.width + 1, bits.rows + 1);
@ -87,10 +104,11 @@ video::IImage* SGUITTGlyph::createGlyphImage(const FT_Bitmap& bits, video::IVide
const u32 image_pitch = image->getPitch() / sizeof(u16);
u16* image_data = (u16*)image->lock();
u8* glyph_data = bits.buffer;
for (int y = 0; y < bits.rows; ++y)
for (s32 y = 0; y < (s32)bits.rows; ++y)
{
u16* row = image_data;
for (int x = 0; x < bits.width; ++x)
for (s32 x = 0; x < (s32)bits.width; ++x)
{
// Monochrome bitmaps store 8 pixels per byte. The left-most pixel is the bit 0x80.
// So, we go through the data each bit at a time.
@ -116,10 +134,10 @@ video::IImage* SGUITTGlyph::createGlyphImage(const FT_Bitmap& bits, video::IVide
const u32 image_pitch = image->getPitch() / sizeof(u32);
u32* image_data = (u32*)image->lock();
u8* glyph_data = bits.buffer;
for (int y = 0; y < bits.rows; ++y)
for (s32 y = 0; y < (s32)bits.rows; ++y)
{
u8* row = glyph_data;
for (int x = 0; x < bits.width; ++x)
for (s32 x = 0; x < (s32)bits.width; ++x)
{
image_data[y * image_pitch + x] |= static_cast<u32>(255.0f * (static_cast<float>(*row++) / gray_count)) << 24;
//data[y * image_pitch + x] |= ((u32)(*bitsdata++) << 24);

View File

@ -45,7 +45,7 @@
#define __BYTE_ORDER 0
#define __LITTLE_ENDIAN 0
#define __BIG_ENDIAN 1
#elif __MACH__
#elif defined(__MACH__) && defined(__APPLE__)
#include <machine/endian.h>
#elif defined(__FreeBSD__)
#include <sys/endian.h>

View File

@ -43,7 +43,7 @@ with this program; if not, write to the Free Software Foundation, Inc.,
#include "nodedef.h"
#include "itemdef.h"
#include "shader.h"
#include "base64.h"
#include "util/base64.h"
#include "clientmap.h"
#include "clientmedia.h"
#include "sound.h"
@ -52,10 +52,8 @@ with this program; if not, write to the Free Software Foundation, Inc.,
#include "config.h"
#include "version.h"
#include "drawscene.h"
#include "subgame.h"
#include "server.h"
#include "database.h"
#include "database-sqlite3.h"
#include "serialization.h"
extern gui::IGUIEnvironment* guienv;
@ -271,28 +269,26 @@ Client::Client(
m_time_of_day_update_timer(0),
m_recommended_send_interval(0.1),
m_removed_sounds_check_timer(0),
m_state(LC_Created)
m_state(LC_Created),
m_localdb(NULL)
{
/*
Add local player
*/
{
Player *player = new LocalPlayer(this, playername);
// Add local player
m_env.addPlayer(new LocalPlayer(this, playername));
m_env.addPlayer(player);
}
m_cache_save_interval = g_settings->getU16("server_map_save_interval");
m_cache_smooth_lighting = g_settings->getBool("smooth_lighting");
m_cache_enable_shaders = g_settings->getBool("enable_shaders");
}
void Client::Stop()
{
//request all client managed threads to stop
m_mesh_update_thread.Stop();
if (localdb != NULL) {
actionstream << "Local map saving ended" << std::endl;
localdb->endSave();
delete localserver;
// Save local server map
if (m_localdb) {
infostream << "Local map saving ended." << std::endl;
m_localdb->endSave();
}
}
@ -535,7 +531,7 @@ void Client::step(float dtime)
if(m_map_timer_and_unload_interval.step(dtime, map_timer_and_unload_dtime))
{
ScopeProfiler sp(g_profiler, "Client: map timer and unload");
std::list<v3s16> deleted_blocks;
std::vector<v3s16> deleted_blocks;
m_env.getMap().timerUpdate(map_timer_and_unload_dtime,
g_settings->getFloat("client_unload_unused_data_timeout"),
&deleted_blocks);
@ -549,8 +545,8 @@ void Client::step(float dtime)
NOTE: This loop is intentionally iterated the way it is.
*/
std::list<v3s16>::iterator i = deleted_blocks.begin();
std::list<v3s16> sendlist;
std::vector<v3s16>::iterator i = deleted_blocks.begin();
std::vector<v3s16> sendlist;
for(;;)
{
if(sendlist.size() == 255 || i == deleted_blocks.end())
@ -569,7 +565,7 @@ void Client::step(float dtime)
writeU16(&reply[0], TOSERVER_DELETEDBLOCKS);
reply[2] = sendlist.size();
u32 k = 0;
for(std::list<v3s16>::iterator
for(std::vector<v3s16>::iterator
j = sendlist.begin();
j != sendlist.end(); ++j)
{
@ -807,6 +803,13 @@ void Client::step(float dtime)
Send(1, data, true);
}
}
// Write server map
if (m_localdb && m_localdb_save_interval.step(dtime,
m_cache_save_interval)) {
m_localdb->endSave();
m_localdb->beginSave();
}
}
bool Client::loadMedia(const std::string &data, const std::string &filename)
@ -906,7 +909,7 @@ void Client::deletingPeer(con::Peer *peer, bool timeout)
string name
}
*/
void Client::request_media(const std::list<std::string> &file_requests)
void Client::request_media(const std::vector<std::string> &file_requests)
{
std::ostringstream os(std::ios_base::binary);
writeU16(os, TOSERVER_REQUEST_MEDIA);
@ -914,7 +917,7 @@ void Client::request_media(const std::list<std::string> &file_requests)
assert(file_requests_size <= 0xFFFF);
writeU16(os, (u16) (file_requests_size & 0xFFFF));
for(std::list<std::string>::const_iterator i = file_requests.begin();
for(std::vector<std::string>::const_iterator i = file_requests.begin();
i != file_requests.end(); ++i) {
os<<serializeString(*i);
}
@ -945,34 +948,19 @@ void Client::initLocalMapSaving(const Address &address,
const std::string &hostname,
bool is_local_server)
{
localdb = NULL;
if (!g_settings->getBool("enable_local_map_saving") || is_local_server)
if (!g_settings->getBool("enable_local_map_saving") || is_local_server) {
return;
}
const std::string world_path = porting::path_user
+ DIR_DELIM + "worlds"
+ DIR_DELIM + "server_"
+ hostname + "_" + to_string(address.getPort());
SubgameSpec gamespec;
fs::CreateAllDirs(world_path);
if (!getWorldExists(world_path)) {
gamespec = findSubgame(g_settings->get("default_game"));
if (!gamespec.isValid())
gamespec = findSubgame("minimal");
} else {
gamespec = findWorldSubgame(world_path);
}
if (!gamespec.isValid()) {
errorstream << "Couldn't find subgame for local map saving." << std::endl;
return;
}
localserver = new Server(world_path, gamespec, false, false);
localdb = new Database_SQLite3(&(ServerMap&)localserver->getMap(), world_path);
localdb->beginSave();
m_localdb = new Database_SQLite3(world_path);
m_localdb->beginSave();
actionstream << "Local map saving started, map will be saved at '" << world_path << "'" << std::endl;
}
@ -1209,8 +1197,8 @@ void Client::ProcessData(u8 *data, u32 datasize, u16 sender_peer_id)
sector->insertBlock(block);
}
if (localdb != NULL) {
((ServerMap&) localserver->getMap()).saveBlock(block, localdb);
if (m_localdb) {
ServerMap::saveBlock(block, m_localdb);
}
/*
@ -2613,7 +2601,7 @@ void Client::addUpdateMeshTask(v3s16 p, bool ack_to_server, bool urgent)
Create a task to update the mesh of the block
*/
MeshMakeData *data = new MeshMakeData(this);
MeshMakeData *data = new MeshMakeData(this, m_cache_enable_shaders);
{
//TimeTaker timer("data fill");
@ -2807,7 +2795,8 @@ void Client::makeScreenshot(IrrlichtDevice *device)
if (image) {
raw_image->copyTo(image);
irr::c8 filename[256];
snprintf(filename, sizeof(filename), "%s" DIR_DELIM "screenshot_%u.png",
snprintf(filename, sizeof(filename),
(std::string("%s") + DIR_DELIM + "screenshot_%u.png").c_str(),
g_settings->get("screenshot_path").c_str(),
device->getTimer()->getRealTime());
std::ostringstream sstr;

View File

@ -47,7 +47,6 @@ struct MapDrawControl;
class MtEventManager;
struct PointedThing;
class Database;
class Server;
struct QueuedMeshUpdate
{
@ -465,7 +464,7 @@ public:
// Insert a media file appropriately into the appropriate manager
bool loadMedia(const std::string &data, const std::string &filename);
// Send a request for conventional media transfer
void request_media(const std::list<std::string> &file_requests);
void request_media(const std::vector<std::string> &file_requests);
// Send a notification that no conventional media transfer is needed
void received_media();
@ -569,11 +568,13 @@ private:
LocalClientState m_state;
// Used for saving server map to disk client-side
Database *localdb;
Server *localserver;
Database *m_localdb;
IntervalLimiter m_localdb_save_interval;
u16 m_cache_save_interval;
// TODO: Add callback to update this when g_settings changes
// TODO: Add callback to update these when g_settings changes
bool m_cache_smooth_lighting;
bool m_cache_enable_shaders;
};
#endif // !CLIENT_HEADER

View File

@ -59,7 +59,7 @@ void RemoteClient::ResendBlockIfOnWire(v3s16 p)
}
}
void RemoteClient::GetNextBlocks(
void RemoteClient::GetNextBlocks (
ServerEnvironment *env,
EmergeManager * emerge,
float dtime,
@ -182,18 +182,15 @@ void RemoteClient::GetNextBlocks(
//bool queue_is_full = false;
s16 d;
for(d = d_start; d <= d_max; d++)
{
for(d = d_start; d <= d_max; d++) {
/*
Get the border/face dot coordinates of a "d-radiused"
box
*/
std::list<v3s16> list;
getFacePositions(list, d);
std::vector<v3s16> list = FacePositionCache::getFacePositions(d);
std::list<v3s16>::iterator li;
for(li=list.begin(); li!=list.end(); ++li)
{
std::vector<v3s16>::iterator li;
for(li = list.begin(); li != list.end(); ++li) {
v3s16 p = *li + center;
/*

View File

@ -161,9 +161,9 @@ static bool isOccluded(Map *map, v3s16 p0, v3s16 p1, float step, float stepfac,
else
is_transparent = (f.solidness != 2);
if(!is_transparent){
count++;
if(count >= needed_count)
if(count == needed_count)
return true;
count++;
}
step *= stepfac;
}
@ -247,7 +247,7 @@ void ClientMap::updateDrawList(video::IVideoDriver* driver)
continue;
}
std::list< MapBlock * > sectorblocks;
MapBlockVect sectorblocks;
sector->getBlocks(sectorblocks);
/*
@ -256,8 +256,8 @@ void ClientMap::updateDrawList(video::IVideoDriver* driver)
u32 sector_blocks_drawn = 0;
std::list< MapBlock * >::iterator i;
for(i=sectorblocks.begin(); i!=sectorblocks.end(); i++)
for(MapBlockVect::iterator i = sectorblocks.begin();
i != sectorblocks.end(); i++)
{
MapBlock *block = *i;
@ -391,12 +391,12 @@ void ClientMap::updateDrawList(video::IVideoDriver* driver)
struct MeshBufList
{
video::SMaterial m;
std::list<scene::IMeshBuffer*> bufs;
std::vector<scene::IMeshBuffer*> bufs;
};
struct MeshBufListList
{
std::list<MeshBufList> lists;
std::vector<MeshBufList> lists;
void clear()
{
@ -405,7 +405,7 @@ struct MeshBufListList
void add(scene::IMeshBuffer *buf)
{
for(std::list<MeshBufList>::iterator i = lists.begin();
for(std::vector<MeshBufList>::iterator i = lists.begin();
i != lists.end(); ++i){
MeshBufList &l = *i;
video::SMaterial &m = buf->getMaterial();
@ -595,25 +595,20 @@ void ClientMap::renderMap(video::IVideoDriver* driver, s32 pass)
}
}
std::list<MeshBufList> &lists = drawbufs.lists;
std::vector<MeshBufList> &lists = drawbufs.lists;
int timecheck_counter = 0;
for(std::list<MeshBufList>::iterator i = lists.begin();
i != lists.end(); ++i)
{
{
timecheck_counter++;
if(timecheck_counter > 50)
{
timecheck_counter = 0;
int time2 = time(0);
if(time2 > time1 + 4)
{
infostream<<"ClientMap::renderMap(): "
"Rendering takes ages, returning."
<<std::endl;
return;
}
for(std::vector<MeshBufList>::iterator i = lists.begin();
i != lists.end(); ++i) {
timecheck_counter++;
if(timecheck_counter > 50) {
timecheck_counter = 0;
int time2 = time(0);
if(time2 > time1 + 4) {
infostream << "ClientMap::renderMap(): "
"Rendering takes ages, returning."
<< std::endl;
return;
}
}
@ -621,60 +616,14 @@ void ClientMap::renderMap(video::IVideoDriver* driver, s32 pass)
driver->setMaterial(list.m);
for(std::list<scene::IMeshBuffer*>::iterator j = list.bufs.begin();
j != list.bufs.end(); ++j)
{
for(std::vector<scene::IMeshBuffer*>::iterator j = list.bufs.begin();
j != list.bufs.end(); ++j) {
scene::IMeshBuffer *buf = *j;
driver->drawMeshBuffer(buf);
vertex_count += buf->getVertexCount();
meshbuffer_count++;
}
#if 0
/*
Draw the faces of the block
*/
{
//JMutexAutoLock lock(block->mesh_mutex);
MapBlockMesh *mapBlockMesh = block->mesh;
assert(mapBlockMesh);
scene::SMesh *mesh = mapBlockMesh->getMesh();
assert(mesh);
u32 c = mesh->getMeshBufferCount();
bool stuff_actually_drawn = false;
for(u32 i=0; i<c; i++)
{
scene::IMeshBuffer *buf = mesh->getMeshBuffer(i);
const video::SMaterial& material = buf->getMaterial();
video::IMaterialRenderer* rnd =
driver->getMaterialRenderer(material.MaterialType);
bool transparent = (rnd && rnd->isTransparent());
// Render transparent on transparent pass and likewise.
if(transparent == is_transparent_pass)
{
if(buf->getVertexCount() == 0)
errorstream<<"Block ["<<analyze_block(block)
<<"] contains an empty meshbuf"<<std::endl;
/*
This *shouldn't* hurt too much because Irrlicht
doesn't change opengl textures if the old
material has the same texture.
*/
driver->setMaterial(buf->getMaterial());
driver->drawMeshBuffer(buf);
vertex_count += buf->getVertexCount();
meshbuffer_count++;
stuff_actually_drawn = true;
}
}
if(stuff_actually_drawn)
blocks_had_pass_meshbuf++;
else
blocks_without_stuff++;
}
#endif
}
} // ScopeProfiler

View File

@ -18,20 +18,20 @@ with this program; if not, write to the Free Software Foundation, Inc.,
*/
#include "clientmedia.h"
#include "util/serialize.h"
#include "util/string.h"
#include "httpfetch.h"
#include "client.h"
#include "clientserver.h"
#include "filecache.h"
#include "filesys.h"
#include "hex.h"
#include "sha1.h"
#include "debug.h"
#include "log.h"
#include "porting.h"
#include "settings.h"
#include "main.h"
#include "util/hex.h"
#include "util/serialize.h"
#include "util/sha1.h"
#include "util/string.h"
static std::string getMediaCacheDir()
{
@ -488,7 +488,7 @@ void ClientMediaDownloader::startConventionalTransfers(Client *client)
if (m_uncached_received_count != m_uncached_count) {
// Some media files have not been received yet, use the
// conventional slow method (minetest protocol) to get them
std::list<std::string> file_requests;
std::vector<std::string> file_requests;
for (std::map<std::string, FileStatus*>::iterator
it = m_files.begin();
it != m_files.end(); ++it) {

View File

@ -39,14 +39,13 @@ ClientActiveObject::~ClientActiveObject()
removeFromScene(true);
}
ClientActiveObject* ClientActiveObject::create(u8 type, IGameDef *gamedef,
ClientEnvironment *env)
ClientActiveObject* ClientActiveObject::create(ActiveObjectType type,
IGameDef *gamedef, ClientEnvironment *env)
{
// Find factory function
std::map<u16, Factory>::iterator n;
n = m_types.find(type);
if(n == m_types.end())
{
if(n == m_types.end()) {
// If factory is not found, just return.
dstream<<"WARNING: ClientActiveObject: No factory for type="
<<(int)type<<std::endl;

View File

@ -86,7 +86,7 @@ public:
virtual void initialize(const std::string &data){}
// Create a certain type of ClientActiveObject
static ClientActiveObject* create(u8 type, IGameDef *gamedef,
static ClientActiveObject* create(ActiveObjectType type, IGameDef *gamedef,
ClientEnvironment *env);
// If returns true, punch will not be sent to the server

View File

@ -300,16 +300,14 @@ collisionMoveResult collisionMoveSimple(Environment *env, IGameDef *gamedef,
/* add object boxes to cboxes */
std::list<ActiveObject*> objects;
std::vector<ActiveObject*> objects;
#ifndef SERVER
ClientEnvironment *c_env = dynamic_cast<ClientEnvironment*>(env);
if (c_env != 0)
{
if (c_env != 0) {
f32 distance = speed_f.getLength();
std::vector<DistanceSortedActiveObject> clientobjects;
c_env->getActiveObjects(pos_f,distance * 1.5,clientobjects);
for (size_t i=0; i < clientobjects.size(); i++)
{
for (size_t i=0; i < clientobjects.size(); i++) {
if ((self == 0) || (self != clientobjects[i].obj)) {
objects.push_back((ActiveObject*)clientobjects[i].obj);
}
@ -319,12 +317,10 @@ collisionMoveResult collisionMoveSimple(Environment *env, IGameDef *gamedef,
#endif
{
ServerEnvironment *s_env = dynamic_cast<ServerEnvironment*>(env);
if (s_env != 0)
{
if (s_env != 0) {
f32 distance = speed_f.getLength();
std::set<u16> s_objects = s_env->getObjectsInsideRadius(pos_f,distance * 1.5);
for (std::set<u16>::iterator iter = s_objects.begin(); iter != s_objects.end(); iter++)
{
for (std::set<u16>::iterator iter = s_objects.begin(); iter != s_objects.end(); iter++) {
ServerActiveObject *current = s_env->getActiveObject(*iter);
if ((self == 0) || (self != current)) {
objects.push_back((ActiveObject*)current);
@ -333,16 +329,14 @@ collisionMoveResult collisionMoveSimple(Environment *env, IGameDef *gamedef,
}
}
for (std::list<ActiveObject*>::const_iterator iter = objects.begin();iter != objects.end(); ++iter)
{
for (std::vector<ActiveObject*>::const_iterator iter = objects.begin();
iter != objects.end(); ++iter) {
ActiveObject *object = *iter;
if (object != NULL)
{
if (object != NULL) {
aabb3f object_collisionbox;
if (object->getCollisionBox(&object_collisionbox) &&
object->collideWithObjects())
{
object->collideWithObjects()) {
cboxes.push_back(object_collisionbox);
is_unloaded.push_back(false);
is_step_up.push_back(false);

View File

@ -100,7 +100,13 @@ with this program; if not, write to the Free Software Foundation, Inc.,
/*
GUI related things
*/
#define TTF_DEFAULT_FONT_SIZE (14)
// TODO: implement dpi-based scaling for windows and remove this hack
#if defined(_WIN32)
#define TTF_DEFAULT_FONT_SIZE (18)
#else
#define TTF_DEFAULT_FONT_SIZE (15)
#endif
#define DEFAULT_FONT_SIZE (10)
#endif

View File

@ -34,7 +34,6 @@ with this program; if not, write to the Free Software Foundation, Inc.,
#include "serialization.h" // For decompressZlib
#include "gamedef.h"
#include "clientobject.h"
#include "content_object.h"
#include "mesh.h"
#include "itemdef.h"
#include "tool.h"
@ -145,7 +144,7 @@ public:
TestCAO(IGameDef *gamedef, ClientEnvironment *env);
virtual ~TestCAO();
u8 getType() const
ActiveObjectType getType() const
{
return ACTIVEOBJECT_TYPE_TEST;
}
@ -289,7 +288,7 @@ public:
ItemCAO(IGameDef *gamedef, ClientEnvironment *env);
virtual ~ItemCAO();
u8 getType() const
ActiveObjectType getType() const
{
return ACTIVEOBJECT_TYPE_ITEM;
}
@ -963,7 +962,7 @@ void GenericCAO::addToScene(scene::ISceneManager *smgr, ITextureSource *tsrc,
// Add a text node for showing the name
gui::IGUIEnvironment* gui = irr->getGUIEnvironment();
std::wstring wname = narrow_to_wide(m_name);
m_textnode = smgr->addTextSceneNode(gui->getBuiltInFont(),
m_textnode = smgr->addTextSceneNode(gui->getSkin()->getFont(),
wname.c_str(), video::SColor(255,255,255,255), node);
m_textnode->grab();
m_textnode->setPosition(v3f(0, BS*1.1, 0));

View File

@ -22,7 +22,6 @@ with this program; if not, write to the Free Software Foundation, Inc.,
#include <map>
#include "irrlichttypes_extrabloated.h"
#include "content_object.h"
#include "clientobject.h"
#include "object_properties.h"
#include "itemgroup.h"
@ -115,7 +114,7 @@ public:
return new GenericCAO(gamedef, env);
}
inline u8 getType() const
inline ActiveObjectType getType() const
{
return ACTIVEOBJECT_TYPE_GENERIC;
}

View File

@ -45,8 +45,7 @@ with this program; if not, write to the Free Software Foundation, Inc.,
// (compatible with ContentFeatures). If you specified 0,0,1,1
// for each face, that would be the same as passing NULL.
void makeCuboid(MeshCollector *collector, const aabb3f &box,
TileSpec *tiles, int tilecount,
video::SColor &c, const f32* txc)
TileSpec *tiles, int tilecount, video::SColor &c, const f32* txc)
{
assert(tilecount >= 1 && tilecount <= 6);
@ -55,8 +54,7 @@ void makeCuboid(MeshCollector *collector, const aabb3f &box,
if(txc == NULL)
{
if(txc == NULL) {
static const f32 txc_default[24] = {
0,0,1,1,
0,0,1,1,
@ -160,14 +158,16 @@ void makeCuboid(MeshCollector *collector, const aabb3f &box,
}
u16 indices[] = {0,1,2,2,3,0};
// Add to mesh collector
for(s32 j=0; j<24; j+=4)
{
int tileindex = MYMIN(j/4, tilecount-1);
collector->append(tiles[tileindex],
vertices+j, 4, indices, 6);
for (s32 j = 0; j < 24; j += 4) {
int tileindex = MYMIN(j / 4, tilecount - 1);
collector->append(tiles[tileindex], vertices + j, 4, indices, 6);
}
}
/*
TODO: Fix alpha blending for special nodes
Currently only the last element rendered is blended correct
*/
void mapblock_mesh_generate_special(MeshMakeData *data,
MeshCollector &collector)
{
@ -191,54 +191,6 @@ void mapblock_mesh_generate_special(MeshMakeData *data,
v3s16 blockpos_nodes = data->m_blockpos*MAP_BLOCKSIZE;
// Create selection mesh
v3s16 p = data->m_highlighted_pos_relative;
if (data->m_show_hud &&
(p.X >= 0) && (p.X < MAP_BLOCKSIZE) &&
(p.Y >= 0) && (p.Y < MAP_BLOCKSIZE) &&
(p.Z >= 0) && (p.Z < MAP_BLOCKSIZE)) {
MapNode n = data->m_vmanip.getNodeNoEx(blockpos_nodes + p);
if(n.getContent() != CONTENT_AIR) {
// Get selection mesh light level
static const v3s16 dirs[7] = {
v3s16( 0, 0, 0),
v3s16( 0, 1, 0),
v3s16( 0,-1, 0),
v3s16( 1, 0, 0),
v3s16(-1, 0, 0),
v3s16( 0, 0, 1),
v3s16( 0, 0,-1)
};
u16 l = 0;
u16 l1 = 0;
for (u8 i = 0; i < 7; i++) {
MapNode n1 = data->m_vmanip.getNodeNoEx(blockpos_nodes + p + dirs[i]);
l1 = getInteriorLight(n1, -4, nodedef);
if (l1 > l)
l = l1;
}
video::SColor c = MapBlock_LightColor(255, l, 0);
data->m_highlight_mesh_color = c;
std::vector<aabb3f> boxes = n.getSelectionBoxes(nodedef);
TileSpec h_tile;
h_tile.material_flags |= MATERIAL_FLAG_HIGHLIGHTED;
h_tile.texture = tsrc->getTexture("halo.png",&h_tile.texture_id);
v3f pos = intToFloat(p, BS);
f32 d = 0.05 * BS;
for(std::vector<aabb3f>::iterator
i = boxes.begin();
i != boxes.end(); i++)
{
aabb3f box = *i;
box.MinEdge += v3f(-d, -d, -d) + pos;
box.MaxEdge += v3f(d, d, d) + pos;
makeCuboid(&collector, box, &h_tile, 1, c, NULL);
}
}
}
for(s16 z = 0; z < MAP_BLOCKSIZE; z++)
for(s16 y = 0; y < MAP_BLOCKSIZE; y++)
for(s16 x = 0; x < MAP_BLOCKSIZE; x++)
@ -1469,77 +1421,65 @@ void mapblock_mesh_generate_special(MeshMakeData *data,
content_t thiscontent = n.getContent();
std::string groupname = "connect_to_raillike"; // name of the group that enables connecting to raillike nodes of different kind
bool self_connect_to_raillike = ((ItemGroupList) nodedef->get(n).groups)[groupname] != 0;
int self_group = ((ItemGroupList) nodedef->get(n).groups)[groupname];
if ((nodedef->get(n_minus_x).drawtype == NDT_RAILLIKE
&& ((ItemGroupList) nodedef->get(n_minus_x).groups)[groupname] != 0
&& self_connect_to_raillike)
&& ((ItemGroupList) nodedef->get(n_minus_x).groups)[groupname] != self_group)
|| n_minus_x.getContent() == thiscontent)
is_rail_x[0] = true;
if ((nodedef->get(n_minus_x_minus_y).drawtype == NDT_RAILLIKE
&& ((ItemGroupList) nodedef->get(n_minus_x_minus_y).groups)[groupname] != 0
&& self_connect_to_raillike)
&& ((ItemGroupList) nodedef->get(n_minus_x_minus_y).groups)[groupname] != self_group)
|| n_minus_x_minus_y.getContent() == thiscontent)
is_rail_x_minus_y[0] = true;
if ((nodedef->get(n_minus_x_plus_y).drawtype == NDT_RAILLIKE
&& ((ItemGroupList) nodedef->get(n_minus_x_plus_y).groups)[groupname] != 0
&& self_connect_to_raillike)
&& ((ItemGroupList) nodedef->get(n_minus_x_plus_y).groups)[groupname] != self_group)
|| n_minus_x_plus_y.getContent() == thiscontent)
is_rail_x_plus_y[0] = true;
if ((nodedef->get(n_plus_x).drawtype == NDT_RAILLIKE
&& ((ItemGroupList) nodedef->get(n_plus_x).groups)[groupname] != 0
&& self_connect_to_raillike)
&& ((ItemGroupList) nodedef->get(n_plus_x).groups)[groupname] != self_group)
|| n_plus_x.getContent() == thiscontent)
is_rail_x[1] = true;
if ((nodedef->get(n_plus_x_minus_y).drawtype == NDT_RAILLIKE
&& ((ItemGroupList) nodedef->get(n_plus_x_minus_y).groups)[groupname] != 0
&& self_connect_to_raillike)
&& ((ItemGroupList) nodedef->get(n_plus_x_minus_y).groups)[groupname] != self_group)
|| n_plus_x_minus_y.getContent() == thiscontent)
is_rail_x_minus_y[1] = true;
if ((nodedef->get(n_plus_x_plus_y).drawtype == NDT_RAILLIKE
&& ((ItemGroupList) nodedef->get(n_plus_x_plus_y).groups)[groupname] != 0
&& self_connect_to_raillike)
&& ((ItemGroupList) nodedef->get(n_plus_x_plus_y).groups)[groupname] != self_group)
|| n_plus_x_plus_y.getContent() == thiscontent)
is_rail_x_plus_y[1] = true;
if ((nodedef->get(n_minus_z).drawtype == NDT_RAILLIKE
&& ((ItemGroupList) nodedef->get(n_minus_z).groups)[groupname] != 0
&& self_connect_to_raillike)
&& ((ItemGroupList) nodedef->get(n_minus_z).groups)[groupname] != self_group)
|| n_minus_z.getContent() == thiscontent)
is_rail_z[0] = true;
if ((nodedef->get(n_minus_z_minus_y).drawtype == NDT_RAILLIKE
&& ((ItemGroupList) nodedef->get(n_minus_z_minus_y).groups)[groupname] != 0
&& self_connect_to_raillike)
&& ((ItemGroupList) nodedef->get(n_minus_z_minus_y).groups)[groupname] != self_group)
|| n_minus_z_minus_y.getContent() == thiscontent)
is_rail_z_minus_y[0] = true;
if ((nodedef->get(n_minus_z_plus_y).drawtype == NDT_RAILLIKE
&& ((ItemGroupList) nodedef->get(n_minus_z_plus_y).groups)[groupname] != 0
&& self_connect_to_raillike)
&& ((ItemGroupList) nodedef->get(n_minus_z_plus_y).groups)[groupname] != self_group)
|| n_minus_z_plus_y.getContent() == thiscontent)
is_rail_z_plus_y[0] = true;
if ((nodedef->get(n_plus_z).drawtype == NDT_RAILLIKE
&& ((ItemGroupList) nodedef->get(n_plus_z).groups)[groupname] != 0
&& self_connect_to_raillike)
&& ((ItemGroupList) nodedef->get(n_plus_z).groups)[groupname] != self_group)
|| n_plus_z.getContent() == thiscontent)
is_rail_z[1] = true;
if ((nodedef->get(n_plus_z_minus_y).drawtype == NDT_RAILLIKE
&& ((ItemGroupList) nodedef->get(n_plus_z_minus_y).groups)[groupname] != 0
&& self_connect_to_raillike)
&& ((ItemGroupList) nodedef->get(n_plus_z_minus_y).groups)[groupname] != self_group)
|| n_plus_z_minus_y.getContent() == thiscontent)
is_rail_z_minus_y[1] = true;
if ((nodedef->get(n_plus_z_plus_y).drawtype == NDT_RAILLIKE
&& ((ItemGroupList) nodedef->get(n_plus_z_plus_y).groups)[groupname] != 0
&& self_connect_to_raillike)
&& ((ItemGroupList) nodedef->get(n_plus_z_plus_y).groups)[groupname] != self_group)
|| n_plus_z_plus_y.getContent() == thiscontent)
is_rail_z_plus_y[1] = true;
@ -1766,5 +1706,55 @@ void mapblock_mesh_generate_special(MeshMakeData *data,
break;}
}
}
/*
Caused by incorrect alpha blending, selection mesh needs to be created as
last element to ensure it gets blended correct over nodes with alpha channel
*/
// Create selection mesh
v3s16 p = data->m_highlighted_pos_relative;
if (data->m_show_hud &&
(p.X >= 0) && (p.X < MAP_BLOCKSIZE) &&
(p.Y >= 0) && (p.Y < MAP_BLOCKSIZE) &&
(p.Z >= 0) && (p.Z < MAP_BLOCKSIZE)) {
MapNode n = data->m_vmanip.getNodeNoEx(blockpos_nodes + p);
if(n.getContent() != CONTENT_AIR) {
// Get selection mesh light level
static const v3s16 dirs[7] = {
v3s16( 0, 0, 0),
v3s16( 0, 1, 0),
v3s16( 0,-1, 0),
v3s16( 1, 0, 0),
v3s16(-1, 0, 0),
v3s16( 0, 0, 1),
v3s16( 0, 0,-1)
};
u16 l = 0;
u16 l1 = 0;
for (u8 i = 0; i < 7; i++) {
MapNode n1 = data->m_vmanip.getNodeNoEx(blockpos_nodes + p + dirs[i]);
l1 = getInteriorLight(n1, -4, nodedef);
if (l1 > l)
l = l1;
}
video::SColor c = MapBlock_LightColor(255, l, 0);
data->m_highlight_mesh_color = c;
std::vector<aabb3f> boxes = n.getSelectionBoxes(nodedef);
TileSpec h_tile;
h_tile.material_flags |= MATERIAL_FLAG_HIGHLIGHTED;
h_tile.texture = tsrc->getTexture("halo.png",&h_tile.texture_id);
v3f pos = intToFloat(p, BS);
f32 d = 0.05 * BS;
for (std::vector<aabb3f>::iterator i = boxes.begin();
i != boxes.end(); i++) {
aabb3f box = *i;
box.MinEdge += v3f(-d, -d, -d) + pos;
box.MaxEdge += v3f(d, d, d) + pos;
makeCuboid(&collector, box, &h_tile, 1, c, NULL);
}
}
}
}

View File

@ -1,39 +0,0 @@
/*
Minetest
Copyright (C) 2010-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 2.1 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU Lesser General Public License for more details.
You should have received a copy of the GNU Lesser General Public License along
with this program; if not, write to the Free Software Foundation, Inc.,
51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
*/
#ifndef CONTENT_OBJECT_HEADER
#define CONTENT_OBJECT_HEADER
#define ACTIVEOBJECT_TYPE_TEST 1
#define ACTIVEOBJECT_TYPE_ITEM 2
#define ACTIVEOBJECT_TYPE_RAT 3
#define ACTIVEOBJECT_TYPE_OERKKI1 4
#define ACTIVEOBJECT_TYPE_FIREFLY 5
#define ACTIVEOBJECT_TYPE_MOBV2 6
#define ACTIVEOBJECT_TYPE_LUAENTITY 7
// Special type, not stored as a static object
#define ACTIVEOBJECT_TYPE_PLAYER 100
// Special type, only exists as CAO
#define ACTIVEOBJECT_TYPE_GENERIC 101
#endif

View File

@ -35,54 +35,6 @@ with this program; if not, write to the Free Software Foundation, Inc.,
std::map<u16, ServerActiveObject::Factory> ServerActiveObject::m_types;
/*
DummyLoadSAO
*/
class DummyLoadSAO : public ServerActiveObject
{
public:
DummyLoadSAO(ServerEnvironment *env, v3f pos, u8 type):
ServerActiveObject(env, pos)
{
ServerActiveObject::registerType(type, create);
}
// Pretend to be the test object (to fool the client)
u8 getType() const
{ return ACTIVEOBJECT_TYPE_TEST; }
// And never save to disk
bool isStaticAllowed() const
{ return false; }
static ServerActiveObject* create(ServerEnvironment *env, v3f pos,
const std::string &data)
{
return new DummyLoadSAO(env, pos, 0);
}
void step(float dtime, bool send_recommended)
{
m_removed = true;
infostream<<"DummyLoadSAO step"<<std::endl;
}
bool getCollisionBox(aabb3f *toset) {
return false;
}
bool collideWithObjects() {
return false;
}
private:
};
// Prototype (registers item for deserialization)
DummyLoadSAO proto1_DummyLoadSAO(NULL, v3f(0,0,0), ACTIVEOBJECT_TYPE_RAT);
DummyLoadSAO proto2_DummyLoadSAO(NULL, v3f(0,0,0), ACTIVEOBJECT_TYPE_OERKKI1);
DummyLoadSAO proto3_DummyLoadSAO(NULL, v3f(0,0,0), ACTIVEOBJECT_TYPE_FIREFLY);
DummyLoadSAO proto4_DummyLoadSAO(NULL, v3f(0,0,0), ACTIVEOBJECT_TYPE_MOBV2);
/*
TestSAO
*/
@ -97,7 +49,7 @@ public:
{
ServerActiveObject::registerType(getType(), create);
}
u8 getType() const
ActiveObjectType getType() const
{ return ACTIVEOBJECT_TYPE_TEST; }
static ServerActiveObject* create(ServerEnvironment *env, v3f pos,
@ -158,203 +110,6 @@ private:
// Prototype (registers item for deserialization)
TestSAO proto_TestSAO(NULL, v3f(0,0,0));
/*
ItemSAO
DEPRECATED: New dropped items are implemented in Lua; see
builtin/item_entity.lua.
*/
class ItemSAO : public ServerActiveObject
{
public:
u8 getType() const
{ return ACTIVEOBJECT_TYPE_ITEM; }
float getMinimumSavedMovement()
{ return 0.1*BS; }
static ServerActiveObject* create(ServerEnvironment *env, v3f pos,
const std::string &data)
{
std::istringstream is(data, std::ios::binary);
char buf[1];
// read version
is.read(buf, 1);
u8 version = buf[0];
// check if version is supported
if(version != 0)
return NULL;
std::string itemstring = deSerializeString(is);
infostream<<"create(): Creating item \""
<<itemstring<<"\""<<std::endl;
return new ItemSAO(env, pos, itemstring);
}
ItemSAO(ServerEnvironment *env, v3f pos,
const std::string &itemstring):
ServerActiveObject(env, pos),
m_itemstring(itemstring),
m_itemstring_changed(false),
m_speed_f(0,0,0),
m_last_sent_position(0,0,0)
{
ServerActiveObject::registerType(getType(), create);
}
void step(float dtime, bool send_recommended)
{
ScopeProfiler sp2(g_profiler, "step avg", SPT_AVG);
assert(m_env);
const float interval = 0.2;
if(m_move_interval.step(dtime, interval)==false)
return;
dtime = interval;
core::aabbox3d<f32> box(-BS/3.,0.0,-BS/3., BS/3.,BS*2./3.,BS/3.);
collisionMoveResult moveresult;
// Apply gravity
m_speed_f += v3f(0, -dtime*9.81*BS, 0);
// Maximum movement without glitches
f32 pos_max_d = BS*0.25;
// Limit speed
if(m_speed_f.getLength()*dtime > pos_max_d)
m_speed_f *= pos_max_d / (m_speed_f.getLength()*dtime);
v3f pos_f = getBasePosition();
v3f accel_f = v3f(0,0,0);
f32 stepheight = 0;
moveresult = collisionMoveSimple(m_env,m_env->getGameDef(),
pos_max_d, box, stepheight, dtime,
pos_f, m_speed_f, accel_f);
if(send_recommended == false)
return;
if(pos_f.getDistanceFrom(m_last_sent_position) > 0.05*BS)
{
setBasePosition(pos_f);
m_last_sent_position = pos_f;
std::ostringstream os(std::ios::binary);
// command (0 = update position)
writeU8(os, 0);
// pos
writeV3F1000(os, m_base_position);
// create message and add to list
ActiveObjectMessage aom(getId(), false, os.str());
m_messages_out.push_back(aom);
}
if(m_itemstring_changed)
{
m_itemstring_changed = false;
std::ostringstream os(std::ios::binary);
// command (1 = update itemstring)
writeU8(os, 1);
// itemstring
os<<serializeString(m_itemstring);
// create message and add to list
ActiveObjectMessage aom(getId(), false, os.str());
m_messages_out.push_back(aom);
}
}
std::string getClientInitializationData(u16 protocol_version)
{
std::ostringstream os(std::ios::binary);
// version
writeU8(os, 0);
// pos
writeV3F1000(os, m_base_position);
// itemstring
os<<serializeString(m_itemstring);
return os.str();
}
std::string getStaticData()
{
infostream<<__FUNCTION_NAME<<std::endl;
std::ostringstream os(std::ios::binary);
// version
writeU8(os, 0);
// itemstring
os<<serializeString(m_itemstring);
return os.str();
}
ItemStack createItemStack()
{
try{
IItemDefManager *idef = m_env->getGameDef()->idef();
ItemStack item;
item.deSerialize(m_itemstring, idef);
infostream<<__FUNCTION_NAME<<": m_itemstring=\""<<m_itemstring
<<"\" -> item=\""<<item.getItemString()<<"\""
<<std::endl;
return item;
}
catch(SerializationError &e)
{
infostream<<__FUNCTION_NAME<<": serialization error: "
<<"m_itemstring=\""<<m_itemstring<<"\""<<std::endl;
return ItemStack();
}
}
int punch(v3f dir,
const ToolCapabilities *toolcap,
ServerActiveObject *puncher,
float time_from_last_punch)
{
// Take item into inventory
ItemStack item = createItemStack();
Inventory *inv = puncher->getInventory();
if(inv != NULL)
{
std::string wieldlist = puncher->getWieldList();
ItemStack leftover = inv->addItem(wieldlist, item);
puncher->setInventoryModified();
if(leftover.empty())
{
m_removed = true;
}
else
{
m_itemstring = leftover.getItemString();
m_itemstring_changed = true;
}
}
return 0;
}
bool getCollisionBox(aabb3f *toset) {
return false;
}
bool collideWithObjects() {
return false;
}
private:
std::string m_itemstring;
bool m_itemstring_changed;
v3f m_speed_f;
v3f m_last_sent_position;
IntervalLimiter m_move_interval;
};
// Prototype (registers item for deserialization)
ItemSAO proto_ItemSAO(NULL, v3f(0,0,0), "");
ServerActiveObject* createItemSAO(ServerEnvironment *env, v3f pos,
const std::string &itemstring)
{
return new ItemSAO(env, pos, itemstring);
}
/*
LuaEntitySAO
*/
@ -965,7 +720,6 @@ PlayerSAO::PlayerSAO(ServerEnvironment *env_, Player *player_, u16 peer_id_,
m_inventory_not_sent(false),
m_hp_not_sent(false),
m_breath_not_sent(false),
m_wielded_item_not_sent(false),
m_physics_override_speed(1),
m_physics_override_jump(1),
m_physics_override_gravity(1),
@ -1171,13 +925,7 @@ void PlayerSAO::step(float dtime, bool send_recommended)
m_messages_out.push_back(aom);
}
if(m_wielded_item_not_sent)
{
m_wielded_item_not_sent = false;
// GenericCAO has no special way to show this
}
if(m_armor_groups_sent == false){
if(m_armor_groups_sent == false) {
m_armor_groups_sent = true;
std::string str = gob_cmd_update_armor_groups(
m_armor_groups);
@ -1442,10 +1190,8 @@ int PlayerSAO::getWieldIndex() const
void PlayerSAO::setWieldIndex(int i)
{
if(i != m_wield_index)
{
if(i != m_wield_index) {
m_wield_index = i;
m_wielded_item_not_sent = true;
}
}

View File

@ -21,14 +21,10 @@ with this program; if not, write to the Free Software Foundation, Inc.,
#define CONTENT_SAO_HEADER
#include "serverobject.h"
#include "content_object.h"
#include "itemgroup.h"
#include "player.h"
#include "object_properties.h"
ServerActiveObject* createItemSAO(ServerEnvironment *env, v3f pos,
const std::string &itemstring);
/*
LuaEntitySAO needs some internals exposed.
*/
@ -39,9 +35,9 @@ public:
LuaEntitySAO(ServerEnvironment *env, v3f pos,
const std::string &name, const std::string &state);
~LuaEntitySAO();
u8 getType() const
ActiveObjectType getType() const
{ return ACTIVEOBJECT_TYPE_LUAENTITY; }
u8 getSendType() const
ActiveObjectType getSendType() const
{ return ACTIVEOBJECT_TYPE_GENERIC; }
virtual void addedToEnvironment(u32 dtime_s);
static ServerActiveObject* create(ServerEnvironment *env, v3f pos,
@ -158,9 +154,9 @@ public:
PlayerSAO(ServerEnvironment *env_, Player *player_, u16 peer_id_,
const std::set<std::string> &privs, bool is_singleplayer);
~PlayerSAO();
u8 getType() const
ActiveObjectType getType() const
{ return ACTIVEOBJECT_TYPE_PLAYER; }
u8 getSendType() const
ActiveObjectType getSendType() const
{ return ACTIVEOBJECT_TYPE_GENERIC; }
std::string getDescription();
@ -324,7 +320,6 @@ public:
bool m_inventory_not_sent;
bool m_hp_not_sent;
bool m_breath_not_sent;
bool m_wielded_item_not_sent;
float m_physics_override_speed;
float m_physics_override_jump;

View File

@ -18,64 +18,38 @@ with this program; if not, write to the Free Software Foundation, Inc.,
*/
/*
Dummy "database" class
Dummy database class
*/
#include "database-dummy.h"
#include "map.h"
#include "mapsector.h"
#include "mapblock.h"
#include "serialization.h"
#include "main.h"
#include "settings.h"
#include "log.h"
Database_Dummy::Database_Dummy(ServerMap *map)
bool Database_Dummy::saveBlock(const v3s16 &pos, const std::string &data)
{
srvmap = map;
}
int Database_Dummy::Initialized(void)
{
return 1;
}
void Database_Dummy::beginSave() {}
void Database_Dummy::endSave() {}
bool Database_Dummy::saveBlock(v3s16 blockpos, std::string &data)
{
m_database[getBlockAsInteger(blockpos)] = data;
m_database[getBlockAsInteger(pos)] = data;
return true;
}
std::string Database_Dummy::loadBlock(v3s16 blockpos)
std::string Database_Dummy::loadBlock(const v3s16 &pos)
{
if (m_database.count(getBlockAsInteger(blockpos)))
return m_database[getBlockAsInteger(blockpos)];
s64 i = getBlockAsInteger(pos);
if (m_database.count(i))
return m_database[i];
else
return "";
}
bool Database_Dummy::deleteBlock(v3s16 blockpos)
bool Database_Dummy::deleteBlock(const v3s16 &pos)
{
m_database.erase(getBlockAsInteger(blockpos));
m_database.erase(getBlockAsInteger(pos));
return true;
}
void Database_Dummy::listAllLoadableBlocks(std::list<v3s16> &dst)
void Database_Dummy::listAllLoadableBlocks(std::vector<v3s16> &dst)
{
for(std::map<u64, std::string>::iterator x = m_database.begin(); x != m_database.end(); ++x)
{
v3s16 p = getIntegerAsBlock(x->first);
//dstream<<"block_i="<<block_i<<" p="<<PP(p)<<std::endl;
dst.push_back(p);
for (std::map<s64, std::string>::const_iterator x = m_database.begin();
x != m_database.end(); ++x) {
dst.push_back(getIntegerAsBlock(x->first));
}
}
Database_Dummy::~Database_Dummy()
{
m_database.clear();
}

View File

@ -25,22 +25,17 @@ with this program; if not, write to the Free Software Foundation, Inc.,
#include "database.h"
#include "irrlichttypes.h"
class ServerMap;
class Database_Dummy : public Database
{
public:
Database_Dummy(ServerMap *map);
virtual void beginSave();
virtual void endSave();
virtual bool saveBlock(v3s16 blockpos, std::string &data);
virtual std::string loadBlock(v3s16 blockpos);
virtual bool deleteBlock(v3s16 blockpos);
virtual void listAllLoadableBlocks(std::list<v3s16> &dst);
virtual int Initialized(void);
~Database_Dummy();
virtual bool saveBlock(const v3s16 &pos, const std::string &data);
virtual std::string loadBlock(const v3s16 &pos);
virtual bool deleteBlock(const v3s16 &pos);
virtual void listAllLoadableBlocks(std::vector<v3s16> &dst);
private:
ServerMap *srvmap;
std::map<u64, std::string> m_database;
std::map<s64, std::string> m_database;
};
#endif

View File

@ -22,57 +22,54 @@ with this program; if not, write to the Free Software Foundation, Inc.,
#if USE_LEVELDB
#include "database-leveldb.h"
#include "leveldb/db.h"
#include "map.h"
#include "mapsector.h"
#include "mapblock.h"
#include "serialization.h"
#include "main.h"
#include "settings.h"
#include "log.h"
#include "filesys.h"
#include "exceptions.h"
#include "util/string.h"
#include "leveldb/db.h"
#define ENSURE_STATUS_OK(s) \
if (!(s).ok()) { \
throw FileNotGoodException(std::string("LevelDB error: ") + (s).ToString()); \
throw FileNotGoodException(std::string("LevelDB error: ") + \
(s).ToString()); \
}
Database_LevelDB::Database_LevelDB(ServerMap *map, std::string savedir)
Database_LevelDB::Database_LevelDB(const std::string &savedir)
{
leveldb::Options options;
options.create_if_missing = true;
leveldb::Status status = leveldb::DB::Open(options, savedir + DIR_DELIM + "map.db", &m_database);
leveldb::Status status = leveldb::DB::Open(options,
savedir + DIR_DELIM + "map.db", &m_database);
ENSURE_STATUS_OK(status);
srvmap = map;
}
int Database_LevelDB::Initialized(void)
Database_LevelDB::~Database_LevelDB()
{
return 1;
delete m_database;
}
void Database_LevelDB::beginSave() {}
void Database_LevelDB::endSave() {}
bool Database_LevelDB::saveBlock(v3s16 blockpos, std::string &data)
bool Database_LevelDB::saveBlock(const v3s16 &pos, const std::string &data)
{
leveldb::Status status = m_database->Put(leveldb::WriteOptions(),
i64tos(getBlockAsInteger(blockpos)), data);
i64tos(getBlockAsInteger(pos)), data);
if (!status.ok()) {
errorstream << "WARNING: saveBlock: LevelDB error saving block "
<< PP(blockpos) << ": " << status.ToString() << std::endl;
<< PP(pos) << ": " << status.ToString() << std::endl;
return false;
}
return true;
}
std::string Database_LevelDB::loadBlock(v3s16 blockpos)
std::string Database_LevelDB::loadBlock(const v3s16 &pos)
{
std::string datastr;
leveldb::Status status = m_database->Get(leveldb::ReadOptions(),
i64tos(getBlockAsInteger(blockpos)), &datastr);
i64tos(getBlockAsInteger(pos)), &datastr);
if(status.ok())
return datastr;
@ -80,20 +77,20 @@ std::string Database_LevelDB::loadBlock(v3s16 blockpos)
return "";
}
bool Database_LevelDB::deleteBlock(v3s16 blockpos)
bool Database_LevelDB::deleteBlock(const v3s16 &pos)
{
leveldb::Status status = m_database->Delete(leveldb::WriteOptions(),
i64tos(getBlockAsInteger(blockpos)));
i64tos(getBlockAsInteger(pos)));
if (!status.ok()) {
errorstream << "WARNING: deleteBlock: LevelDB error deleting block "
<< PP(blockpos) << ": " << status.ToString() << std::endl;
<< PP(pos) << ": " << status.ToString() << std::endl;
return false;
}
return true;
}
void Database_LevelDB::listAllLoadableBlocks(std::list<v3s16> &dst)
void Database_LevelDB::listAllLoadableBlocks(std::vector<v3s16> &dst)
{
leveldb::Iterator* it = m_database->NewIterator(leveldb::ReadOptions());
for (it->SeekToFirst(); it->Valid(); it->Next()) {
@ -103,8 +100,5 @@ void Database_LevelDB::listAllLoadableBlocks(std::list<v3s16> &dst)
delete it;
}
Database_LevelDB::~Database_LevelDB()
{
delete m_database;
}
#endif
#endif // USE_LEVELDB

View File

@ -28,23 +28,22 @@ with this program; if not, write to the Free Software Foundation, Inc.,
#include "leveldb/db.h"
#include <string>
class ServerMap;
class Database_LevelDB : public Database
{
public:
Database_LevelDB(ServerMap *map, std::string savedir);
virtual void beginSave();
virtual void endSave();
virtual bool saveBlock(v3s16 blockpos, std::string &data);
virtual std::string loadBlock(v3s16 blockpos);
virtual bool deleteBlock(v3s16 blockpos);
virtual void listAllLoadableBlocks(std::list<v3s16> &dst);
virtual int Initialized(void);
Database_LevelDB(const std::string &savedir);
~Database_LevelDB();
virtual bool saveBlock(const v3s16 &pos, const std::string &data);
virtual std::string loadBlock(const v3s16 &pos);
virtual bool deleteBlock(const v3s16 &pos);
virtual void listAllLoadableBlocks(std::vector<v3s16> &dst);
private:
ServerMap *srvmap;
leveldb::DB* m_database;
leveldb::DB *m_database;
};
#endif // USE_LEVELDB
#endif
#endif

View File

@ -20,151 +20,140 @@ with this program; if not, write to the Free Software Foundation, Inc.,
#include "config.h"
#if USE_REDIS
/*
Redis databases
*/
#include "database-redis.h"
#include <hiredis.h>
#include "map.h"
#include "mapsector.h"
#include "mapblock.h"
#include "serialization.h"
#include "main.h"
#include "settings.h"
#include "log.h"
#include "filesys.h"
#include "exceptions.h"
#include "util/string.h"
#include <hiredis.h>
#include <cassert>
Database_Redis::Database_Redis(ServerMap *map, std::string savedir)
Database_Redis::Database_Redis(Settings &conf)
{
Settings conf;
conf.readConfigFile((std::string(savedir) + DIR_DELIM + "world.mt").c_str());
std::string tmp;
try {
tmp = conf.get("redis_address");
hash = conf.get("redis_hash");
} catch(SettingNotFoundException e) {
throw SettingNotFoundException("Set redis_address and redis_hash in world.mt to use the redis backend");
tmp = conf.get("redis_address");
hash = conf.get("redis_hash");
} catch (SettingNotFoundException) {
throw SettingNotFoundException("Set redis_address and "
"redis_hash in world.mt to use the redis backend");
}
const char *addr = tmp.c_str();
int port = conf.exists("redis_port") ? conf.getU16("redis_port") : 6379;
ctx = redisConnect(addr, port);
if(!ctx)
if (!ctx) {
throw FileNotGoodException("Cannot allocate redis context");
else if(ctx->err) {
} else if(ctx->err) {
std::string err = std::string("Connection error: ") + ctx->errstr;
redisFree(ctx);
throw FileNotGoodException(err);
}
srvmap = map;
}
int Database_Redis::Initialized(void)
{
return 1;
}
void Database_Redis::beginSave() {
redisReply *reply;
reply = (redisReply*) redisCommand(ctx, "MULTI");
if(!reply)
throw FileNotGoodException(std::string("redis command 'MULTI' failed: ") + ctx->errstr);
freeReplyObject(reply);
}
void Database_Redis::endSave() {
redisReply *reply;
reply = (redisReply*) redisCommand(ctx, "EXEC");
if(!reply)
throw FileNotGoodException(std::string("redis command 'EXEC' failed: ") + ctx->errstr);
freeReplyObject(reply);
}
bool Database_Redis::saveBlock(v3s16 blockpos, std::string &data)
{
std::string tmp = i64tos(getBlockAsInteger(blockpos));
redisReply *reply = (redisReply *)redisCommand(ctx, "HSET %s %s %b",
hash.c_str(), tmp.c_str(), data.c_str(), data.size());
if (!reply) {
errorstream << "WARNING: saveBlock: redis command 'HSET' failed on "
"block " << PP(blockpos) << ": " << ctx->errstr << std::endl;
freeReplyObject(reply);
return false;
}
if (reply->type == REDIS_REPLY_ERROR) {
errorstream << "WARNING: saveBlock: saving block " << PP(blockpos)
<< "failed" << std::endl;
freeReplyObject(reply);
return false;
}
freeReplyObject(reply);
return true;
}
std::string Database_Redis::loadBlock(v3s16 blockpos)
{
std::string tmp = i64tos(getBlockAsInteger(blockpos));
redisReply *reply;
reply = (redisReply*) redisCommand(ctx, "HGET %s %s", hash.c_str(), tmp.c_str());
if(!reply)
throw FileNotGoodException(std::string("redis command 'HGET %s %s' failed: ") + ctx->errstr);
if(reply->type != REDIS_REPLY_STRING)
return "";
std::string str(reply->str, reply->len);
freeReplyObject(reply); // std::string copies the memory so this won't cause any problems
return str;
}
bool Database_Redis::deleteBlock(v3s16 blockpos)
{
std::string tmp = i64tos(getBlockAsInteger(blockpos));
redisReply *reply = (redisReply *)redisCommand(ctx, "HDEL %s %s",
hash.c_str(), tmp.c_str());
if (!reply) {
errorstream << "WARNING: deleteBlock: redis command 'HDEL' failed on "
"block " << PP(blockpos) << ": " << ctx->errstr << std::endl;
freeReplyObject(reply);
return false;
}
if (reply->type == REDIS_REPLY_ERROR) {
errorstream << "WARNING: deleteBlock: deleting block " << PP(blockpos)
<< "failed" << std::endl;
freeReplyObject(reply);
return false;
}
freeReplyObject(reply);
return true;
}
void Database_Redis::listAllLoadableBlocks(std::list<v3s16> &dst)
{
redisReply *reply;
reply = (redisReply*) redisCommand(ctx, "HKEYS %s", hash.c_str());
if(!reply)
throw FileNotGoodException(std::string("redis command 'HKEYS %s' failed: ") + ctx->errstr);
if(reply->type != REDIS_REPLY_ARRAY)
throw FileNotGoodException("Failed to get keys from database");
for(size_t i = 0; i < reply->elements; i++)
{
assert(reply->element[i]->type == REDIS_REPLY_STRING);
dst.push_back(getIntegerAsBlock(stoi64(reply->element[i]->str)));
}
freeReplyObject(reply);
}
Database_Redis::~Database_Redis()
{
redisFree(ctx);
}
#endif
void Database_Redis::beginSave() {
redisReply *reply = static_cast<redisReply *>(redisCommand(ctx, "MULTI"));
if (!reply) {
throw FileNotGoodException(std::string(
"Redis command 'MULTI' failed: ") + ctx->errstr);
}
freeReplyObject(reply);
}
void Database_Redis::endSave() {
redisReply *reply = static_cast<redisReply *>(redisCommand(ctx, "EXEC"));
if (!reply) {
throw FileNotGoodException(std::string(
"Redis command 'EXEC' failed: ") + ctx->errstr);
}
freeReplyObject(reply);
}
bool Database_Redis::saveBlock(const v3s16 &pos, const std::string &data)
{
std::string tmp = i64tos(getBlockAsInteger(pos));
redisReply *reply = static_cast<redisReply *>(redisCommand(ctx, "HSET %s %s %b",
hash.c_str(), tmp.c_str(), data.c_str(), data.size()));
if (!reply) {
errorstream << "WARNING: saveBlock: redis command 'HSET' failed on "
"block " << PP(pos) << ": " << ctx->errstr << std::endl;
freeReplyObject(reply);
return false;
}
if (reply->type == REDIS_REPLY_ERROR) {
errorstream << "WARNING: saveBlock: saving block " << PP(pos)
<< "failed" << std::endl;
freeReplyObject(reply);
return false;
}
freeReplyObject(reply);
return true;
}
std::string Database_Redis::loadBlock(const v3s16 &pos)
{
std::string tmp = i64tos(getBlockAsInteger(pos));
redisReply *reply = static_cast<redisReply *>(redisCommand(ctx,
"HGET %s %s", hash.c_str(), tmp.c_str()));
if (!reply) {
throw FileNotGoodException(std::string(
"Redis command 'HGET %s %s' failed: ") + ctx->errstr);
} else if (reply->type != REDIS_REPLY_STRING) {
return "";
}
std::string str(reply->str, reply->len);
freeReplyObject(reply); // std::string copies the memory so this won't cause any problems
return str;
}
bool Database_Redis::deleteBlock(const v3s16 &pos)
{
std::string tmp = i64tos(getBlockAsInteger(pos));
redisReply *reply = static_cast<redisReply *>(redisCommand(ctx,
"HDEL %s %s", hash.c_str(), tmp.c_str()));
if (!reply) {
throw FileNotGoodException(std::string(
"Redis command 'HDEL %s %s' failed: ") + ctx->errstr);
} else if (reply->type == REDIS_REPLY_ERROR) {
errorstream << "WARNING: deleteBlock: deleting block " << PP(pos)
<< " failed" << std::endl;
freeReplyObject(reply);
return false;
}
freeReplyObject(reply);
return true;
}
void Database_Redis::listAllLoadableBlocks(std::vector<v3s16> &dst)
{
redisReply *reply = static_cast<redisReply *>(redisCommand(ctx, "HKEYS %s", hash.c_str()));
if (!reply) {
throw FileNotGoodException(std::string(
"Redis command 'HKEYS %s' failed: ") + ctx->errstr);
} else if (reply->type != REDIS_REPLY_ARRAY) {
throw FileNotGoodException("Failed to get keys from database");
}
for (size_t i = 0; i < reply->elements; i++) {
assert(reply->element[i]->type == REDIS_REPLY_STRING);
dst.push_back(getIntegerAsBlock(stoi64(reply->element[i]->str)));
}
freeReplyObject(reply);
}
#endif // USE_REDIS

View File

@ -28,24 +28,28 @@ with this program; if not, write to the Free Software Foundation, Inc.,
#include <hiredis.h>
#include <string>
class ServerMap;
class Settings;
class Database_Redis : public Database
{
public:
Database_Redis(ServerMap *map, std::string savedir);
Database_Redis(Settings &conf);
~Database_Redis();
virtual void beginSave();
virtual void endSave();
virtual bool saveBlock(v3s16 blockpos, std::string &data);
virtual std::string loadBlock(v3s16 blockpos);
virtual bool deleteBlock(v3s16 blockpos);
virtual void listAllLoadableBlocks(std::list<v3s16> &dst);
virtual int Initialized(void);
~Database_Redis();
virtual bool saveBlock(const v3s16 &pos, const std::string &data);
virtual std::string loadBlock(const v3s16 &pos);
virtual bool deleteBlock(const v3s16 &pos);
virtual void listAllLoadableBlocks(std::vector<v3s16> &dst);
private:
ServerMap *srvmap;
redisContext *ctx;
std::string hash;
};
#endif // USE_REDIS
#endif
#endif

View File

@ -18,297 +18,231 @@ with this program; if not, write to the Free Software Foundation, Inc.,
*/
/*
SQLite format specification:
- Initially only replaces sectors/ and sectors2/
If map.sqlite does not exist in the save dir
or the block was not found in the database
the map will try to load from sectors folder.
In either case, map.sqlite will be created
and all future saves will save there.
Structure of map.sqlite:
Tables:
blocks
(PK) INT pos
BLOB data
SQLite format specification:
blocks:
(PK) INT id
BLOB data
*/
#include "database-sqlite3.h"
#include "map.h"
#include "mapsector.h"
#include "mapblock.h"
#include "serialization.h"
#include "main.h"
#include "settings.h"
#include "log.h"
#include "filesys.h"
#include "exceptions.h"
#include "main.h"
#include "settings.h"
#include "util/string.h"
Database_SQLite3::Database_SQLite3(ServerMap *map, std::string savedir)
{
m_database = NULL;
m_database_read = NULL;
m_database_write = NULL;
m_database_list = NULL;
m_database_delete = NULL;
m_savedir = savedir;
srvmap = map;
}
#include <cassert>
int Database_SQLite3::Initialized(void)
#define SQLRES(s, r) \
if ((s) != (r)) { \
throw FileNotGoodException(std::string(\
"SQLite3 database error (" \
__FILE__ ":" TOSTRING(__LINE__) \
"): ") +\
sqlite3_errmsg(m_database)); \
}
#define SQLOK(s) SQLRES(s, SQLITE_OK)
#define PREPARE_STATEMENT(name, query) \
SQLOK(sqlite3_prepare_v2(m_database, query, -1, &m_stmt_##name, NULL))
#define FINALIZE_STATEMENT(statement) \
if (sqlite3_finalize(statement) != SQLITE_OK) { \
throw FileNotGoodException(std::string( \
"SQLite3: Failed to finalize " #statement ": ") + \
sqlite3_errmsg(m_database)); \
}
Database_SQLite3::Database_SQLite3(const std::string &savedir) :
m_initialized(false),
m_savedir(savedir),
m_database(NULL),
m_stmt_read(NULL),
m_stmt_write(NULL),
m_stmt_list(NULL),
m_stmt_delete(NULL)
{
return m_database ? 1 : 0;
}
void Database_SQLite3::beginSave() {
verifyDatabase();
if(sqlite3_exec(m_database, "BEGIN;", NULL, NULL, NULL) != SQLITE_OK)
errorstream<<"WARNING: beginSave() failed, saving might be slow.";
SQLRES(sqlite3_step(m_stmt_begin), SQLITE_DONE);
sqlite3_reset(m_stmt_begin);
}
void Database_SQLite3::endSave() {
verifyDatabase();
if(sqlite3_exec(m_database, "COMMIT;", NULL, NULL, NULL) != SQLITE_OK)
errorstream<<"WARNING: endSave() failed, map might not have saved.";
SQLRES(sqlite3_step(m_stmt_end), SQLITE_DONE);
sqlite3_reset(m_stmt_end);
}
void Database_SQLite3::createDirs(std::string path)
void Database_SQLite3::openDatabase()
{
if(fs::CreateAllDirs(path) == false)
{
infostream<<DTIME<<"Database_SQLite3: Failed to create directory "
<<"\""<<path<<"\""<<std::endl;
throw BaseException("Database_SQLite3 failed to create directory");
}
}
if (m_database) return;
void Database_SQLite3::verifyDatabase() {
if(m_database)
return;
std::string dbp = m_savedir + DIR_DELIM "map.sqlite";
bool needs_create = false;
int d;
std::string dbp = m_savedir + DIR_DELIM + "map.sqlite";
// Open the database connection
createDirs(m_savedir); // ?
if (!fs::CreateAllDirs(m_savedir)) {
infostream << "Database_SQLite3: Failed to create directory \""
<< m_savedir << "\"" << std::endl;
throw FileNotGoodException("Failed to create database "
"save directory");
}
if(!fs::PathExists(dbp))
needs_create = true;
bool needs_create = !fs::PathExists(dbp);
d = sqlite3_open_v2(dbp.c_str(), &m_database, SQLITE_OPEN_READWRITE | SQLITE_OPEN_CREATE, NULL);
if(d != SQLITE_OK) {
errorstream<<"SQLite3 database failed to open: "<<sqlite3_errmsg(m_database)<<std::endl;
if (sqlite3_open_v2(dbp.c_str(), &m_database,
SQLITE_OPEN_READWRITE | SQLITE_OPEN_CREATE,
NULL) != SQLITE_OK) {
errorstream << "SQLite3 database failed to open: "
<< sqlite3_errmsg(m_database) << std::endl;
throw FileNotGoodException("Cannot open database file");
}
if(needs_create)
if (needs_create) {
createDatabase();
}
std::string querystr = std::string("PRAGMA synchronous = ")
std::string query_str = std::string("PRAGMA synchronous = ")
+ itos(g_settings->getU16("sqlite_synchronous"));
d = sqlite3_exec(m_database, querystr.c_str(), NULL, NULL, NULL);
if(d != SQLITE_OK) {
errorstream<<"Database pragma set failed: "
<<sqlite3_errmsg(m_database)<<std::endl;
throw FileNotGoodException("Cannot set pragma");
}
SQLOK(sqlite3_exec(m_database, query_str.c_str(), NULL, NULL, NULL));
}
d = sqlite3_prepare(m_database, "SELECT `data` FROM `blocks` WHERE `pos`=? LIMIT 1", -1, &m_database_read, NULL);
if(d != SQLITE_OK) {
errorstream<<"SQLite3 read statment failed to prepare: "<<sqlite3_errmsg(m_database)<<std::endl;
throw FileNotGoodException("Cannot prepare read statement");
}
void Database_SQLite3::verifyDatabase()
{
if (m_initialized) return;
openDatabase();
PREPARE_STATEMENT(begin, "BEGIN");
PREPARE_STATEMENT(end, "COMMIT");
PREPARE_STATEMENT(read, "SELECT `data` FROM `blocks` WHERE `pos` = ? LIMIT 1");
#ifdef __ANDROID__
d = sqlite3_prepare(m_database, "INSERT INTO `blocks` VALUES(?, ?);", -1, &m_database_write, NULL);
PREPARE_STATEMENT(write, "INSERT INTO `blocks` (`pos`, `data`) VALUES (?, ?)");
#else
d = sqlite3_prepare(m_database, "REPLACE INTO `blocks` VALUES(?, ?);", -1, &m_database_write, NULL);
PREPARE_STATEMENT(write, "REPLACE INTO `blocks` (`pos`, `data`) VALUES (?, ?)");
#endif
if(d != SQLITE_OK) {
errorstream<<"SQLite3 write statment failed to prepare: "<<sqlite3_errmsg(m_database)<<std::endl;
throw FileNotGoodException("Cannot prepare write statement");
}
PREPARE_STATEMENT(delete, "DELETE FROM `blocks` WHERE `pos` = ?");
PREPARE_STATEMENT(list, "SELECT `pos` FROM `blocks`");
d = sqlite3_prepare(m_database, "DELETE FROM `blocks` WHERE `pos`=?;", -1, &m_database_delete, NULL);
if(d != SQLITE_OK) {
infostream<<"WARNING: SQLite3 database delete statment failed to prepare: "<<sqlite3_errmsg(m_database)<<std::endl;
throw FileNotGoodException("Cannot prepare delete statement");
}
m_initialized = true;
d = sqlite3_prepare(m_database, "SELECT `pos` FROM `blocks`", -1, &m_database_list, NULL);
if(d != SQLITE_OK) {
infostream<<"SQLite3 list statment failed to prepare: "<<sqlite3_errmsg(m_database)<<std::endl;
throw FileNotGoodException("Cannot prepare read statement");
}
infostream<<"ServerMap: SQLite3 database opened"<<std::endl;
verbosestream << "ServerMap: SQLite3 database opened." << std::endl;
}
bool Database_SQLite3::deleteBlock(v3s16 blockpos)
inline void Database_SQLite3::bindPos(sqlite3_stmt *stmt, const v3s16 &pos, int index)
{
SQLOK(sqlite3_bind_int64(stmt, index, getBlockAsInteger(pos)));
}
bool Database_SQLite3::deleteBlock(const v3s16 &pos)
{
verifyDatabase();
if (sqlite3_bind_int64(m_database_delete, 1,
getBlockAsInteger(blockpos)) != SQLITE_OK) {
errorstream << "WARNING: Could not bind block position for delete: "
<< sqlite3_errmsg(m_database) << std::endl;
}
bindPos(m_stmt_delete, pos);
if (sqlite3_step(m_database_delete) != SQLITE_DONE) {
bool good = sqlite3_step(m_stmt_delete) == SQLITE_DONE;
sqlite3_reset(m_stmt_delete);
if (!good) {
errorstream << "WARNING: deleteBlock: Block failed to delete "
<< PP(blockpos) << ": " << sqlite3_errmsg(m_database) << std::endl;
sqlite3_reset(m_database_delete);
return false;
<< PP(pos) << ": " << sqlite3_errmsg(m_database) << std::endl;
}
sqlite3_reset(m_database_delete);
return true;
return good;
}
bool Database_SQLite3::saveBlock(v3s16 blockpos, std::string &data)
bool Database_SQLite3::saveBlock(const v3s16 &pos, const std::string &data)
{
verifyDatabase();
s64 bkey = getBlockAsInteger(blockpos);
#ifdef __ANDROID__
/**
* Note: For some unknown reason sqlite3 fails to REPLACE blocks on android,
* deleting them and inserting first works.
* Note: For some unknown reason SQLite3 fails to REPLACE blocks on Android,
* deleting them and then inserting works.
*/
if (sqlite3_bind_int64(m_database_read, 1, bkey) != SQLITE_OK) {
infostream << "WARNING: Could not bind block position for load: "
<< sqlite3_errmsg(m_database)<<std::endl;
}
int step_result = sqlite3_step(m_database_read);
sqlite3_reset(m_database_read);
if (step_result == SQLITE_ROW) {
if (sqlite3_bind_int64(m_database_delete, 1, bkey) != SQLITE_OK) {
infostream << "WARNING: Could not bind block position for delete: "
<< sqlite3_errmsg(m_database)<<std::endl;
}
if (sqlite3_step(m_database_delete) != SQLITE_DONE) {
errorstream << "WARNING: saveBlock: Block failed to delete "
<< PP(blockpos) << ": " << sqlite3_errmsg(m_database) << std::endl;
return false;
}
sqlite3_reset(m_database_delete);
bindPos(m_stmt_read, pos);
if (sqlite3_step(m_stmt_read) == SQLITE_ROW) {
deleteBlock(pos);
}
sqlite3_reset(m_stmt_read);
#endif
if (sqlite3_bind_int64(m_database_write, 1, bkey) != SQLITE_OK) {
errorstream << "WARNING: saveBlock: Block position failed to bind: "
<< PP(blockpos) << ": " << sqlite3_errmsg(m_database) << std::endl;
sqlite3_reset(m_database_write);
return false;
}
bindPos(m_stmt_write, pos);
SQLOK(sqlite3_bind_blob(m_stmt_write, 2, data.data(), data.size(), NULL));
if (sqlite3_bind_blob(m_database_write, 2, (void *)data.c_str(),
data.size(), NULL) != SQLITE_OK) {
errorstream << "WARNING: saveBlock: Block data failed to bind: "
<< PP(blockpos) << ": " << sqlite3_errmsg(m_database) << std::endl;
sqlite3_reset(m_database_write);
return false;
}
if (sqlite3_step(m_database_write) != SQLITE_DONE) {
errorstream << "WARNING: saveBlock: Block failed to save "
<< PP(blockpos) << ": " << sqlite3_errmsg(m_database) << std::endl;
sqlite3_reset(m_database_write);
return false;
}
sqlite3_reset(m_database_write);
SQLRES(sqlite3_step(m_stmt_write), SQLITE_DONE)
sqlite3_reset(m_stmt_write);
return true;
}
std::string Database_SQLite3::loadBlock(v3s16 blockpos)
std::string Database_SQLite3::loadBlock(const v3s16 &pos)
{
verifyDatabase();
if (sqlite3_bind_int64(m_database_read, 1, getBlockAsInteger(blockpos)) != SQLITE_OK) {
errorstream << "Could not bind block position for load: "
<< sqlite3_errmsg(m_database)<<std::endl;
bindPos(m_stmt_read, pos);
if (sqlite3_step(m_stmt_read) != SQLITE_ROW) {
sqlite3_reset(m_stmt_read);
return "";
}
const char *data = (const char *) sqlite3_column_blob(m_stmt_read, 0);
size_t len = sqlite3_column_bytes(m_stmt_read, 0);
if (sqlite3_step(m_database_read) == SQLITE_ROW) {
const char *data = (const char *) sqlite3_column_blob(m_database_read, 0);
size_t len = sqlite3_column_bytes(m_database_read, 0);
std::string s;
if (data)
s = std::string(data, len);
std::string s = "";
if(data)
s = std::string(data, len);
sqlite3_step(m_stmt_read);
// We should never get more than 1 row, so ok to reset
sqlite3_reset(m_stmt_read);
sqlite3_step(m_database_read);
// We should never get more than 1 row, so ok to reset
sqlite3_reset(m_database_read);
return s;
}
sqlite3_reset(m_database_read);
return "";
return s;
}
void Database_SQLite3::createDatabase()
{
int e;
assert(m_database);
e = sqlite3_exec(m_database,
"CREATE TABLE IF NOT EXISTS `blocks` ("
"`pos` INT NOT NULL PRIMARY KEY,"
"`data` BLOB"
");"
, NULL, NULL, NULL);
if(e != SQLITE_OK)
throw FileNotGoodException("Could not create sqlite3 database structure");
else
infostream<<"ServerMap: SQLite3 database structure was created";
SQLOK(sqlite3_exec(m_database,
"CREATE TABLE IF NOT EXISTS `blocks` (\n"
" `pos` INT PRIMARY KEY,\n"
" `data` BLOB\n"
");\n",
NULL, NULL, NULL));
}
void Database_SQLite3::listAllLoadableBlocks(std::list<v3s16> &dst)
void Database_SQLite3::listAllLoadableBlocks(std::vector<v3s16> &dst)
{
verifyDatabase();
while(sqlite3_step(m_database_list) == SQLITE_ROW)
{
sqlite3_int64 block_i = sqlite3_column_int64(m_database_list, 0);
v3s16 p = getIntegerAsBlock(block_i);
//dstream<<"block_i="<<block_i<<" p="<<PP(p)<<std::endl;
dst.push_back(p);
while (sqlite3_step(m_stmt_list) == SQLITE_ROW) {
dst.push_back(getIntegerAsBlock(sqlite3_column_int64(m_stmt_list, 0)));
}
sqlite3_reset(m_stmt_list);
}
#define FINALIZE_STATEMENT(statement) \
if ( statement ) \
rc = sqlite3_finalize(statement); \
if ( rc != SQLITE_OK ) \
errorstream << "Database_SQLite3::~Database_SQLite3():" \
<< "Failed to finalize: " << #statement << ": rc=" << rc << std::endl;
Database_SQLite3::~Database_SQLite3()
{
int rc = SQLITE_OK;
FINALIZE_STATEMENT(m_stmt_read)
FINALIZE_STATEMENT(m_stmt_write)
FINALIZE_STATEMENT(m_stmt_list)
FINALIZE_STATEMENT(m_stmt_begin)
FINALIZE_STATEMENT(m_stmt_end)
FINALIZE_STATEMENT(m_stmt_delete)
FINALIZE_STATEMENT(m_database_read)
FINALIZE_STATEMENT(m_database_write)
FINALIZE_STATEMENT(m_database_list)
FINALIZE_STATEMENT(m_database_delete)
if(m_database)
rc = sqlite3_close(m_database);
if (rc != SQLITE_OK) {
if (sqlite3_close(m_database) != SQLITE_OK) {
errorstream << "Database_SQLite3::~Database_SQLite3(): "
<< "Failed to close database: rc=" << rc << std::endl;
<< "Failed to close database: "
<< sqlite3_errmsg(m_database) << std::endl;
}
}

View File

@ -27,35 +27,43 @@ extern "C" {
#include "sqlite3.h"
}
class ServerMap;
class Database_SQLite3 : public Database
{
public:
Database_SQLite3(ServerMap *map, std::string savedir);
Database_SQLite3(const std::string &savedir);
virtual void beginSave();
virtual void endSave();
virtual bool saveBlock(v3s16 blockpos, std::string &data);
virtual std::string loadBlock(v3s16 blockpos);
virtual bool deleteBlock(v3s16 blockpos);
virtual void listAllLoadableBlocks(std::list<v3s16> &dst);
virtual int Initialized(void);
virtual bool saveBlock(const v3s16 &pos, const std::string &data);
virtual std::string loadBlock(const v3s16 &pos);
virtual bool deleteBlock(const v3s16 &pos);
virtual void listAllLoadableBlocks(std::vector<v3s16> &dst);
virtual bool initialized() const { return m_initialized; }
~Database_SQLite3();
private:
ServerMap *srvmap;
std::string m_savedir;
sqlite3 *m_database;
sqlite3_stmt *m_database_read;
sqlite3_stmt *m_database_write;
sqlite3_stmt *m_database_delete;
sqlite3_stmt *m_database_list;
private:
// Open the database
void openDatabase();
// Create the database structure
void createDatabase();
// Verify we can read/write to the database
// Open and initialize the database if needed
void verifyDatabase();
void createDirs(std::string path);
void bindPos(sqlite3_stmt *stmt, const v3s16 &pos, int index=1);
bool m_initialized;
std::string m_savedir;
sqlite3 *m_database;
sqlite3_stmt *m_stmt_read;
sqlite3_stmt *m_stmt_write;
sqlite3_stmt *m_stmt_list;
sqlite3_stmt *m_stmt_delete;
sqlite3_stmt *m_stmt_begin;
sqlite3_stmt *m_stmt_end;
};
#endif

View File

@ -48,7 +48,7 @@ static inline s64 pythonmodulo(s64 i, s16 mod)
}
s64 Database::getBlockAsInteger(const v3s16 pos) const
s64 Database::getBlockAsInteger(const v3s16 &pos)
{
return (u64) pos.Z * 0x1000000 +
(u64) pos.Y * 0x1000 +
@ -56,7 +56,7 @@ s64 Database::getBlockAsInteger(const v3s16 pos) const
}
v3s16 Database::getIntegerAsBlock(s64 i) const
v3s16 Database::getIntegerAsBlock(s64 i)
{
v3s16 pos;
pos.X = unsigned_to_signed(pythonmodulo(i, 4096), 2048);

View File

@ -20,7 +20,7 @@ with this program; if not, write to the Free Software Foundation, Inc.,
#ifndef DATABASE_HEADER
#define DATABASE_HEADER
#include <list>
#include <vector>
#include <string>
#include "irr_v3d.h"
#include "irrlichttypes.h"
@ -32,16 +32,22 @@ with this program; if not, write to the Free Software Foundation, Inc.,
class Database
{
public:
virtual void beginSave() = 0;
virtual void endSave() = 0;
virtual ~Database() {}
virtual bool saveBlock(v3s16 blockpos, std::string &data) = 0;
virtual std::string loadBlock(v3s16 blockpos) = 0;
virtual bool deleteBlock(v3s16 blockpos) = 0;
s64 getBlockAsInteger(const v3s16 pos) const;
v3s16 getIntegerAsBlock(s64 i) const;
virtual void listAllLoadableBlocks(std::list<v3s16> &dst) = 0;
virtual int Initialized(void)=0;
virtual ~Database() {};
virtual void beginSave() {}
virtual void endSave() {}
virtual bool saveBlock(const v3s16 &pos, const std::string &data) = 0;
virtual std::string loadBlock(const v3s16 &pos) = 0;
virtual bool deleteBlock(const v3s16 &pos) = 0;
static s64 getBlockAsInteger(const v3s16 &pos);
static v3s16 getIntegerAsBlock(s64 i);
virtual void listAllLoadableBlocks(std::vector<v3s16> &dst) = 0;
virtual bool initialized() const { return true; }
};
#endif

View File

@ -48,6 +48,7 @@ void set_default_settings(Settings *settings)
settings->setDefault("keymap_freemove", "KEY_KEY_K");
settings->setDefault("keymap_fastmove", "KEY_KEY_J");
settings->setDefault("keymap_noclip", "KEY_KEY_H");
settings->setDefault("keymap_cinematic", "KEY_F8");
settings->setDefault("keymap_screenshot", "KEY_F12");
settings->setDefault("keymap_toggle_hud", "KEY_F1");
settings->setDefault("keymap_toggle_chat", "KEY_F2");
@ -115,6 +116,9 @@ void set_default_settings(Settings *settings)
settings->setDefault("free_move", "false");
settings->setDefault("noclip", "false");
settings->setDefault("continuous_forward", "false");
settings->setDefault("cinematic", "false");
settings->setDefault("camera_smoothing", "0");
settings->setDefault("cinematic_camera_smoothing", "0.7");
settings->setDefault("fast_move", "false");
settings->setDefault("invert_mouse", "false");
settings->setDefault("enable_clouds", "true");
@ -288,6 +292,7 @@ void set_default_settings(Settings *settings)
settings->setDefault("water_level", "1");
settings->setDefault("chunksize", "5");
settings->setDefault("mg_flags", "");
settings->setDefault("enable_floating_dungeons", "true");
// IPv6
settings->setDefault("enable_ipv6", "true");

View File

@ -79,14 +79,17 @@ void DungeonGen::generate(u32 bseed, v3s16 nmin, v3s16 nmax) {
// Dungeon generator doesn't modify places which have this set
vm->clearFlag(VMANIP_FLAG_DUNGEON_INSIDE | VMANIP_FLAG_DUNGEON_PRESERVE);
// Set all air and water to be untouchable to make dungeons open
// to caves and open air
bool no_float = !g_settings->getBool("enable_floating_dungeons");
// Set all air and water (and optionally ignore) to be untouchable
// to make dungeons open to caves and open air
for (s16 z = nmin.Z; z <= nmax.Z; z++) {
for (s16 y = nmin.Y; y <= nmax.Y; y++) {
u32 i = vm->m_area.index(nmin.X, y, z);
for (s16 x = nmin.X; x <= nmax.X; x++) {
content_t c = vm->m_data[i].getContent();
if (c == CONTENT_AIR || c == dp.c_water)
if (c == CONTENT_AIR || c == dp.c_water
|| (no_float && c == CONTENT_IGNORE))
vm->m_flags[i] |= VMANIP_FLAG_DUNGEON_PRESERVE;
i++;
}

View File

@ -361,7 +361,10 @@ void EmergeManager::loadParamsFromSettings(Settings *settings)
std::string seed_str;
const char *setname = (settings == g_settings) ? "fixed_map_seed" : "seed";
if (settings->getNoEx(setname, seed_str) && !seed_str.empty()) {
if (!settings->getNoEx("seed", seed_str)) {
g_settings->getNoEx(setname, seed_str);
}
if (!seed_str.empty()) {
params.seed = read_seed(seed_str.c_str());
} else {
params.seed =

View File

@ -61,9 +61,8 @@ Environment::Environment():
Environment::~Environment()
{
// Deallocate players
for(std::list<Player*>::iterator i = m_players.begin();
i != m_players.end(); ++i)
{
for(std::vector<Player*>::iterator i = m_players.begin();
i != m_players.end(); ++i) {
delete (*i);
}
}
@ -89,7 +88,7 @@ void Environment::removePlayer(u16 peer_id)
{
DSTACK(__FUNCTION_NAME);
for(std::list<Player*>::iterator i = m_players.begin();
for(std::vector<Player*>::iterator i = m_players.begin();
i != m_players.end();)
{
Player *player = *i;
@ -104,7 +103,7 @@ void Environment::removePlayer(u16 peer_id)
void Environment::removePlayer(const char *name)
{
for (std::list<Player*>::iterator it = m_players.begin();
for (std::vector<Player*>::iterator it = m_players.begin();
it != m_players.end(); ++it) {
if (strcmp((*it)->getName(), name) == 0) {
delete *it;
@ -116,9 +115,8 @@ void Environment::removePlayer(const char *name)
Player * Environment::getPlayer(u16 peer_id)
{
for(std::list<Player*>::iterator i = m_players.begin();
i != m_players.end(); ++i)
{
for(std::vector<Player*>::iterator i = m_players.begin();
i != m_players.end(); ++i) {
Player *player = *i;
if(player->peer_id == peer_id)
return player;
@ -128,9 +126,8 @@ Player * Environment::getPlayer(u16 peer_id)
Player * Environment::getPlayer(const char *name)
{
for(std::list<Player*>::iterator i = m_players.begin();
i != m_players.end(); ++i)
{
for(std::vector<Player*>::iterator i = m_players.begin();
i != m_players.end(); ++i) {
Player *player = *i;
if(strcmp(player->getName(), name) == 0)
return player;
@ -140,15 +137,13 @@ Player * Environment::getPlayer(const char *name)
Player * Environment::getRandomConnectedPlayer()
{
std::list<Player*> connected_players = getPlayers(true);
std::vector<Player*> connected_players = getPlayers(true);
u32 chosen_one = myrand() % connected_players.size();
u32 j = 0;
for(std::list<Player*>::iterator
for(std::vector<Player*>::iterator
i = connected_players.begin();
i != connected_players.end(); ++i)
{
if(j == chosen_one)
{
i != connected_players.end(); ++i) {
if(j == chosen_one) {
Player *player = *i;
return player;
}
@ -159,17 +154,15 @@ Player * Environment::getRandomConnectedPlayer()
Player * Environment::getNearestConnectedPlayer(v3f pos)
{
std::list<Player*> connected_players = getPlayers(true);
std::vector<Player*> connected_players = getPlayers(true);
f32 nearest_d = 0;
Player *nearest_player = NULL;
for(std::list<Player*>::iterator
for(std::vector<Player*>::iterator
i = connected_players.begin();
i != connected_players.end(); ++i)
{
i != connected_players.end(); ++i) {
Player *player = *i;
f32 d = player->getPosition().getDistanceFrom(pos);
if(d < nearest_d || nearest_player == NULL)
{
if(d < nearest_d || nearest_player == NULL) {
nearest_d = d;
nearest_player = player;
}
@ -177,22 +170,20 @@ Player * Environment::getNearestConnectedPlayer(v3f pos)
return nearest_player;
}
std::list<Player*> Environment::getPlayers()
std::vector<Player*> Environment::getPlayers()
{
return m_players;
}
std::list<Player*> Environment::getPlayers(bool ignore_disconnected)
std::vector<Player*> Environment::getPlayers(bool ignore_disconnected)
{
std::list<Player*> newlist;
for(std::list<Player*>::iterator
std::vector<Player*> newlist;
for(std::vector<Player*>::iterator
i = m_players.begin();
i != m_players.end(); ++i)
{
i != m_players.end(); ++i) {
Player *player = *i;
if(ignore_disconnected)
{
if(ignore_disconnected) {
// Ignore disconnected players
if(player->peer_id == 0)
continue;
@ -212,24 +203,42 @@ u32 Environment::getDayNightRatio()
void Environment::setTimeOfDaySpeed(float speed)
{
JMutexAutoLock(this->m_lock);
JMutexAutoLock(this->m_timeofday_lock);
m_time_of_day_speed = speed;
}
float Environment::getTimeOfDaySpeed()
{
JMutexAutoLock(this->m_lock);
JMutexAutoLock(this->m_timeofday_lock);
float retval = m_time_of_day_speed;
return retval;
}
void Environment::setTimeOfDay(u32 time)
{
JMutexAutoLock(this->m_time_lock);
m_time_of_day = time;
m_time_of_day_f = (float)time / 24000.0;
}
u32 Environment::getTimeOfDay()
{
JMutexAutoLock(this->m_time_lock);
u32 retval = m_time_of_day;
return retval;
}
float Environment::getTimeOfDayF()
{
JMutexAutoLock(this->m_time_lock);
float retval = m_time_of_day_f;
return retval;
}
void Environment::stepTimeOfDay(float dtime)
{
float day_speed = 0;
{
JMutexAutoLock(this->m_lock);
day_speed = m_time_of_day_speed;
}
// getTimeOfDaySpeed lock the value we need to prevent MT problems
float day_speed = getTimeOfDaySpeed();
m_time_counter += dtime;
f32 speed = day_speed * 24000./(24.*3600);
@ -287,7 +296,7 @@ void fillRadiusBlock(v3s16 p0, s16 r, std::set<v3s16> &list)
}
}
void ActiveBlockList::update(std::list<v3s16> &active_positions,
void ActiveBlockList::update(std::vector<v3s16> &active_positions,
s16 radius,
std::set<v3s16> &blocks_removed,
std::set<v3s16> &blocks_added)
@ -296,7 +305,7 @@ void ActiveBlockList::update(std::list<v3s16> &active_positions,
Create the new list
*/
std::set<v3s16> newlist = m_forceloaded_list;
for(std::list<v3s16>::iterator i = active_positions.begin();
for(std::vector<v3s16>::iterator i = active_positions.begin();
i != active_positions.end(); ++i)
{
fillRadiusBlock(*i, radius, newlist);
@ -373,7 +382,7 @@ ServerEnvironment::~ServerEnvironment()
m_map->drop();
// Delete ActiveBlockModifiers
for(std::list<ABMWithState>::iterator
for(std::vector<ABMWithState>::iterator
i = m_abms.begin(); i != m_abms.end(); ++i){
delete i->abm;
}
@ -395,8 +404,8 @@ bool ServerEnvironment::line_of_sight(v3f pos1, v3f pos2, float stepsize, v3s16
//calculate normalized direction vector
v3f normalized_vector = v3f((pos2.X - pos1.X)/distance,
(pos2.Y - pos1.Y)/distance,
(pos2.Z - pos1.Z)/distance);
(pos2.Y - pos1.Y)/distance,
(pos2.Z - pos1.Z)/distance);
//find out if there's a node on path between pos1 and pos2
for (float i = 1; i < distance; i += stepsize) {
@ -421,7 +430,7 @@ void ServerEnvironment::saveLoadedPlayers()
std::string players_path = m_path_world + DIR_DELIM "players";
fs::CreateDir(players_path);
for (std::list<Player*>::iterator it = m_players.begin();
for (std::vector<Player*>::iterator it = m_players.begin();
it != m_players.end();
++it) {
RemotePlayer *player = static_cast<RemotePlayer*>(*it);
@ -549,9 +558,9 @@ class ABMHandler
{
private:
ServerEnvironment *m_env;
std::map<content_t, std::list<ActiveABM> > m_aabms;
std::map<content_t, std::vector<ActiveABM> > m_aabms;
public:
ABMHandler(std::list<ABMWithState> &abms,
ABMHandler(std::vector<ABMWithState> &abms,
float dtime_s, ServerEnvironment *env,
bool use_timers):
m_env(env)
@ -559,8 +568,8 @@ public:
if(dtime_s < 0.001)
return;
INodeDefManager *ndef = env->getGameDef()->ndef();
for(std::list<ABMWithState>::iterator
i = abms.begin(); i != abms.end(); ++i){
for(std::vector<ABMWithState>::iterator
i = abms.begin(); i != abms.end(); ++i) {
ActiveBlockModifier *abm = i->abm;
float trigger_interval = abm->getTriggerInterval();
if(trigger_interval < 0.001)
@ -604,10 +613,10 @@ public:
k != ids.end(); k++)
{
content_t c = *k;
std::map<content_t, std::list<ActiveABM> >::iterator j;
std::map<content_t, std::vector<ActiveABM> >::iterator j;
j = m_aabms.find(c);
if(j == m_aabms.end()){
std::list<ActiveABM> aabmlist;
std::vector<ActiveABM> aabmlist;
m_aabms[c] = aabmlist;
j = m_aabms.find(c);
}
@ -664,14 +673,13 @@ public:
content_t c = n.getContent();
v3s16 p = p0 + block->getPosRelative();
std::map<content_t, std::list<ActiveABM> >::iterator j;
std::map<content_t, std::vector<ActiveABM> >::iterator j;
j = m_aabms.find(c);
if(j == m_aabms.end())
continue;
for(std::list<ActiveABM>::iterator
i = j->second.begin(); i != j->second.end(); i++)
{
for(std::vector<ActiveABM>::iterator
i = j->second.begin(); i != j->second.end(); i++) {
if(myrand() % i->chance != 0)
continue;
@ -851,11 +859,10 @@ void ServerEnvironment::clearAllObjects()
{
infostream<<"ServerEnvironment::clearAllObjects(): "
<<"Removing all active objects"<<std::endl;
std::list<u16> objects_to_remove;
std::vector<u16> objects_to_remove;
for(std::map<u16, ServerActiveObject*>::iterator
i = m_active_objects.begin();
i != m_active_objects.end(); ++i)
{
i != m_active_objects.end(); ++i) {
ServerActiveObject* obj = i->second;
if(obj->getType() == ACTIVEOBJECT_TYPE_PLAYER)
continue;
@ -888,15 +895,15 @@ void ServerEnvironment::clearAllObjects()
// Id to be removed from m_active_objects
objects_to_remove.push_back(id);
}
// Remove references from m_active_objects
for(std::list<u16>::iterator i = objects_to_remove.begin();
i != objects_to_remove.end(); ++i)
{
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::list<v3s16> loaded_blocks;
std::vector<v3s16> loaded_blocks;
infostream<<"ServerEnvironment::clearAllObjects(): "
<<"Listing all loaded blocks"<<std::endl;
m_map->listAllLoadedBlocks(loaded_blocks);
@ -905,7 +912,7 @@ void ServerEnvironment::clearAllObjects()
<<loaded_blocks.size()<<std::endl;
// Get list of loadable blocks
std::list<v3s16> loadable_blocks;
std::vector<v3s16> loadable_blocks;
infostream<<"ServerEnvironment::clearAllObjects(): "
<<"Listing all loadable blocks"<<std::endl;
m_map->listAllLoadableBlocks(loadable_blocks);
@ -915,9 +922,8 @@ void ServerEnvironment::clearAllObjects()
<<", now clearing"<<std::endl;
// Grab a reference on each loaded block to avoid unloading it
for(std::list<v3s16>::iterator i = loaded_blocks.begin();
i != loaded_blocks.end(); ++i)
{
for(std::vector<v3s16>::iterator i = loaded_blocks.begin();
i != loaded_blocks.end(); ++i) {
v3s16 p = *i;
MapBlock *block = m_map->getBlockNoCreateNoEx(p);
assert(block);
@ -931,9 +937,8 @@ void ServerEnvironment::clearAllObjects()
u32 num_blocks_checked = 0;
u32 num_blocks_cleared = 0;
u32 num_objs_cleared = 0;
for(std::list<v3s16>::iterator i = loadable_blocks.begin();
i != loadable_blocks.end(); ++i)
{
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){
@ -969,9 +974,8 @@ void ServerEnvironment::clearAllObjects()
m_map->unloadUnreferencedBlocks();
// Drop references that were added above
for(std::list<v3s16>::iterator i = loaded_blocks.begin();
i != loaded_blocks.end(); ++i)
{
for(std::vector<v3s16>::iterator i = loaded_blocks.begin();
i != loaded_blocks.end(); ++i) {
v3s16 p = *i;
MapBlock *block = m_map->getBlockNoCreateNoEx(p);
assert(block);
@ -1012,7 +1016,7 @@ void ServerEnvironment::step(float dtime)
*/
{
ScopeProfiler sp(g_profiler, "SEnv: handle players avg", SPT_AVG);
for(std::list<Player*>::iterator i = m_players.begin();
for(std::vector<Player*>::iterator i = m_players.begin();
i != m_players.end(); ++i)
{
Player *player = *i;
@ -1035,15 +1039,15 @@ void ServerEnvironment::step(float dtime)
/*
Get player block positions
*/
std::list<v3s16> players_blockpos;
for(std::list<Player*>::iterator
std::vector<v3s16> players_blockpos;
for(std::vector<Player*>::iterator
i = m_players.begin();
i != m_players.end(); ++i)
{
i != m_players.end(); ++i) {
Player *player = *i;
// Ignore disconnected players
if(player->peer_id == 0)
continue;
v3s16 blockpos = getNodeBlockPos(
floatToInt(player->getPosition(), BS));
players_blockpos.push_back(blockpos);
@ -1178,7 +1182,7 @@ void ServerEnvironment::step(float dtime)
<<") being handled"<<std::endl;*/
MapBlock *block = m_map->getBlockNoCreateNoEx(p);
if(block==NULL)
if(block == NULL)
continue;
// Set current time as timestamp
@ -1542,11 +1546,10 @@ u16 ServerEnvironment::addActiveObjectRaw(ServerActiveObject *object,
*/
void ServerEnvironment::removeRemovedObjects()
{
std::list<u16> objects_to_remove;
std::vector<u16> objects_to_remove;
for(std::map<u16, ServerActiveObject*>::iterator
i = m_active_objects.begin();
i != m_active_objects.end(); ++i)
{
i != m_active_objects.end(); ++i) {
u16 id = i->first;
ServerActiveObject* obj = i->second;
// This shouldn't happen but check it
@ -1616,13 +1619,13 @@ void ServerEnvironment::removeRemovedObjects()
// Delete
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::list<u16>::iterator i = objects_to_remove.begin();
i != objects_to_remove.end(); ++i)
{
for(std::vector<u16>::iterator i = objects_to_remove.begin();
i != objects_to_remove.end(); ++i) {
m_active_objects.erase(*i);
}
}
@ -1666,17 +1669,19 @@ static void print_hexdump(std::ostream &o, const std::string &data)
*/
void ServerEnvironment::activateObjects(MapBlock *block, u32 dtime_s)
{
if(block==NULL)
if(block == NULL)
return;
// Ignore if no stored objects (to not set changed flag)
if(block->m_static_objects.m_stored.empty())
return;
verbosestream<<"ServerEnvironment::activateObjects(): "
<<"activating objects of block "<<PP(block->getPos())
<<" ("<<block->m_static_objects.m_stored.size()
<<" objects)"<<std::endl;
bool large_amount = (block->m_static_objects.m_stored.size() > g_settings->getU16("max_objects_per_block"));
if(large_amount){
if (large_amount) {
errorstream<<"suspiciously large amount of objects detected: "
<<block->m_static_objects.m_stored.size()<<" in "
<<PP(block->getPos())
@ -1690,20 +1695,17 @@ void ServerEnvironment::activateObjects(MapBlock *block, u32 dtime_s)
}
// Activate stored objects
std::list<StaticObject> new_stored;
for(std::list<StaticObject>::iterator
std::vector<StaticObject> new_stored;
for (std::vector<StaticObject>::iterator
i = block->m_static_objects.m_stored.begin();
i != block->m_static_objects.m_stored.end(); ++i)
{
/*infostream<<"Server: Creating an active object from "
<<"static data"<<std::endl;*/
i != block->m_static_objects.m_stored.end(); ++i) {
StaticObject &s_obj = *i;
// Create an active object from the data
ServerActiveObject *obj = ServerActiveObject::create
(s_obj.type, this, 0, s_obj.pos, s_obj.data);
((ActiveObjectType) s_obj.type, this, 0, s_obj.pos, s_obj.data);
// If couldn't create object, store static data back.
if(obj==NULL)
{
if(obj == NULL) {
errorstream<<"ServerEnvironment::activateObjects(): "
<<"failed to create active object from static object "
<<"in block "<<PP(s_obj.pos/BS)
@ -1722,10 +1724,9 @@ void ServerEnvironment::activateObjects(MapBlock *block, u32 dtime_s)
// Clear stored list
block->m_static_objects.m_stored.clear();
// Add leftover failed stuff to stored list
for(std::list<StaticObject>::iterator
for(std::vector<StaticObject>::iterator
i = new_stored.begin();
i != new_stored.end(); ++i)
{
i != new_stored.end(); ++i) {
StaticObject &s_obj = *i;
block->m_static_objects.m_stored.push_back(s_obj);
}
@ -1765,11 +1766,10 @@ void ServerEnvironment::activateObjects(MapBlock *block, u32 dtime_s)
*/
void ServerEnvironment::deactivateFarObjects(bool force_delete)
{
std::list<u16> objects_to_remove;
std::vector<u16> objects_to_remove;
for(std::map<u16, ServerActiveObject*>::iterator
i = m_active_objects.begin();
i != m_active_objects.end(); ++i)
{
i != m_active_objects.end(); ++i) {
ServerActiveObject* obj = i->second;
assert(obj);
@ -1986,9 +1986,8 @@ void ServerEnvironment::deactivateFarObjects(bool force_delete)
}
// Remove references from m_active_objects
for(std::list<u16>::iterator i = objects_to_remove.begin();
i != objects_to_remove.end(); ++i)
{
for(std::vector<u16>::iterator i = objects_to_remove.begin();
i != objects_to_remove.end(); ++i) {
m_active_objects.erase(*i);
}
}
@ -2025,9 +2024,8 @@ ClientEnvironment::~ClientEnvironment()
delete i->second;
}
for(std::list<ClientSimpleObject*>::iterator
i = m_simple_objects.begin(); i != m_simple_objects.end(); ++i)
{
for(std::vector<ClientSimpleObject*>::iterator
i = m_simple_objects.begin(); i != m_simple_objects.end(); ++i) {
delete *i;
}
@ -2059,9 +2057,8 @@ void ClientEnvironment::addPlayer(Player *player)
LocalPlayer * ClientEnvironment::getLocalPlayer()
{
for(std::list<Player*>::iterator i = m_players.begin();
i != m_players.end(); ++i)
{
for(std::vector<Player*>::iterator i = m_players.begin();
i != m_players.end(); ++i) {
Player *player = *i;
if(player->isLocal())
return (LocalPlayer*)player;
@ -2084,7 +2081,7 @@ void ClientEnvironment::step(float dtime)
LocalPlayer *lplayer = getLocalPlayer();
assert(lplayer);
// collision info queue
std::list<CollisionInfo> player_collisions;
std::vector<CollisionInfo> player_collisions;
/*
Get the speed the player is going
@ -2199,10 +2196,8 @@ void ClientEnvironment::step(float dtime)
//std::cout<<"Looped "<<loopcount<<" times."<<std::endl;
for(std::list<CollisionInfo>::iterator
i = player_collisions.begin();
i != player_collisions.end(); ++i)
{
for(std::vector<CollisionInfo>::iterator i = player_collisions.begin();
i != player_collisions.end(); ++i) {
CollisionInfo &info = *i;
v3f speed_diff = info.new_speed - info.old_speed;;
// Handle only fall damage
@ -2317,16 +2312,14 @@ void ClientEnvironment::step(float dtime)
/*
Stuff that can be done in an arbitarily large dtime
*/
for(std::list<Player*>::iterator i = m_players.begin();
i != m_players.end(); ++i)
{
for(std::vector<Player*>::iterator i = m_players.begin();
i != m_players.end(); ++i) {
Player *player = *i;
/*
Handle non-local players
*/
if(player->isLocal() == false)
{
if(player->isLocal() == false) {
// Move
player->move(dtime, this, 100*BS);
@ -2387,16 +2380,18 @@ void ClientEnvironment::step(float dtime)
Step and handle simple objects
*/
g_profiler->avg("CEnv: num of simple objects", m_simple_objects.size());
for(std::list<ClientSimpleObject*>::iterator
i = m_simple_objects.begin(); i != m_simple_objects.end();)
{
ClientSimpleObject *simple = *i;
std::list<ClientSimpleObject*>::iterator cur = i;
++i;
for(std::vector<ClientSimpleObject*>::iterator
i = m_simple_objects.begin(); i != m_simple_objects.end();) {
std::vector<ClientSimpleObject*>::iterator cur = i;
ClientSimpleObject *simple = *cur;
simple->step(dtime);
if(simple->m_to_be_removed){
if(simple->m_to_be_removed) {
delete simple;
m_simple_objects.erase(cur);
i = m_simple_objects.erase(cur);
}
else {
++i;
}
}
}
@ -2488,7 +2483,7 @@ void ClientEnvironment::addActiveObject(u16 id, u8 type,
const std::string &init_data)
{
ClientActiveObject* obj =
ClientActiveObject::create(type, m_gamedef, this);
ClientActiveObject::create((ActiveObjectType) type, m_gamedef, this);
if(obj == NULL)
{
infostream<<"ClientEnvironment::addActiveObject(): "

View File

@ -75,28 +75,19 @@ public:
Player * getPlayer(const char *name);
Player * getRandomConnectedPlayer();
Player * getNearestConnectedPlayer(v3f pos);
std::list<Player*> getPlayers();
std::list<Player*> getPlayers(bool ignore_disconnected);
std::vector<Player*> getPlayers();
std::vector<Player*> getPlayers(bool ignore_disconnected);
u32 getDayNightRatio();
// 0-23999
virtual void setTimeOfDay(u32 time)
{
m_time_of_day = time;
m_time_of_day_f = (float)time / 24000.0;
}
u32 getTimeOfDay()
{ return m_time_of_day; }
float getTimeOfDayF()
{ return m_time_of_day_f; }
virtual void setTimeOfDay(u32 time);
u32 getTimeOfDay();
float getTimeOfDayF();
void stepTimeOfDay(float dtime);
void setTimeOfDaySpeed(float speed);
float getTimeOfDaySpeed();
void setDayNightRatioOverride(bool enable, u32 value)
@ -110,7 +101,7 @@ public:
protected:
// peer_ids in here should be unique, except that there may be many 0s
std::list<Player*> m_players;
std::vector<Player*> m_players;
// Time of day in milli-hours (0-23999); determines day and night
u32 m_time_of_day;
// Time of day in 0...1
@ -134,7 +125,8 @@ protected:
bool m_cache_enable_shaders;
private:
JMutex m_lock;
JMutex m_timeofday_lock;
JMutex m_time_lock;
};
@ -182,7 +174,7 @@ struct ABMWithState
class ActiveBlockList
{
public:
void update(std::list<v3s16> &active_positions,
void update(std::vector<v3s16> &active_positions,
s16 radius,
std::set<v3s16> &blocks_removed,
std::set<v3s16> &blocks_added);
@ -401,7 +393,7 @@ private:
u32 m_game_time;
// A helper variable for incrementing the latter
float m_game_time_fraction_counter;
std::list<ABMWithState> m_abms;
std::vector<ABMWithState> m_abms;
// An interval for generally sending object positions and stuff
float m_recommended_send_interval;
// Estimate for general maximum lag as determined by server.
@ -529,7 +521,7 @@ private:
IGameDef *m_gamedef;
IrrlichtDevice *m_irr;
std::map<u16, ClientActiveObject*> m_active_objects;
std::list<ClientSimpleObject*> m_simple_objects;
std::vector<ClientSimpleObject*> m_simple_objects;
std::list<ClientEnvEvent> m_client_event_queue;
IntervalLimiter m_active_object_light_update_interval;
IntervalLimiter m_lava_hurt_interval;

View File

@ -492,7 +492,7 @@ private:
color(color)
{}
};
std::list<Piece> m_log;
std::vector<Piece> m_log;
public:
u32 m_log_max_size;
@ -515,7 +515,7 @@ public:
{
std::map<std::string, Meta> m_meta;
for (std::list<Piece>::const_iterator k = m_log.begin();
for (std::vector<Piece>::const_iterator k = m_log.begin();
k != m_log.end(); k++) {
const Piece &piece = *k;
@ -613,7 +613,7 @@ public:
float lastscaledvalue = 0.0;
bool lastscaledvalue_exists = false;
for (std::list<Piece>::const_iterator j = m_log.begin();
for (std::vector<Piece>::const_iterator j = m_log.begin();
j != m_log.end(); j++) {
const Piece &piece = *j;
float value = 0;
@ -1043,7 +1043,11 @@ static inline void create_formspec_menu(GUIFormSpecMenu **cur_formspec,
}
}
#ifdef __ANDROID__
#define SIZE_TAG "size[11,5.5]"
#else
#define SIZE_TAG "size[11,5.5,true]" // Fixed size on desktop
#endif
static void show_chat_menu(GUIFormSpecMenu **cur_formspec,
InventoryManager *invmgr, IGameDef *gamedef,
@ -1074,7 +1078,7 @@ static void show_deathscreen(GUIFormSpecMenu **cur_formspec,
std::string(FORMSPEC_VERSION_STRING) +
SIZE_TAG
"bgcolor[#320000b4;true]"
"label[4.85,1.35;You died.]"
"label[4.85,1.35;" + gettext("You died.") + "]"
"button_exit[4,3;3,0.5;btn_respawn;" + gettext("Respawn") + "]"
;
@ -1133,7 +1137,7 @@ static void show_pause_menu(GUIFormSpecMenu **cur_formspec,
os << "button_exit[4," << (ypos++) << ";3,0.5;btn_change_password;"
<< wide_to_narrow(wstrgettext("Change Password")) << "]";
}
#ifndef __ANDROID__
os << "button_exit[4," << (ypos++) << ";3,0.5;btn_sound;"
<< wide_to_narrow(wstrgettext("Sound Volume")) << "]";
@ -1157,7 +1161,7 @@ static void show_pause_menu(GUIFormSpecMenu **cur_formspec,
LocalFormspecHandler *txt_dst = new LocalFormspecHandler("MT_PAUSE_MENU");
create_formspec_menu(cur_formspec, invmgr, gamedef, tsrc, device, fs_src, txt_dst, NULL);
(*cur_formspec)->setFocus(L"btn_continue");
(*cur_formspec)->doPause = true;
}
@ -1249,6 +1253,7 @@ struct KeyCache {
KEYMAP_ID_FREEMOVE,
KEYMAP_ID_FASTMOVE,
KEYMAP_ID_NOCLIP,
KEYMAP_ID_CINEMATIC,
KEYMAP_ID_SCREENSHOT,
KEYMAP_ID_TOGGLE_HUD,
KEYMAP_ID_TOGGLE_CHAT,
@ -1297,6 +1302,7 @@ void KeyCache::populate()
key[KEYMAP_ID_FREEMOVE] = getKeySetting("keymap_freemove");
key[KEYMAP_ID_FASTMOVE] = getKeySetting("keymap_fastmove");
key[KEYMAP_ID_NOCLIP] = getKeySetting("keymap_noclip");
key[KEYMAP_ID_CINEMATIC] = getKeySetting("keymap_cinematic");
key[KEYMAP_ID_SCREENSHOT] = getKeySetting("keymap_screenshot");
key[KEYMAP_ID_TOGGLE_HUD] = getKeySetting("keymap_toggle_hud");
key[KEYMAP_ID_TOGGLE_CHAT] = getKeySetting("keymap_toggle_chat");
@ -1493,6 +1499,7 @@ protected:
void toggleFreeMoveAlt(float *statustext_time, float *jump_timer);
void toggleFast(float *statustext_time);
void toggleNoClip(float *statustext_time);
void toggleCinematic(float *statustext_time);
void toggleChat(float *statustext_time, bool *flag);
void toggleHud(float *statustext_time, bool *flag);
@ -1733,6 +1740,7 @@ void Game::run()
{
ProfilerGraph graph;
RunStats stats = { 0 };
CameraOrientation cam_view_target = { 0 };
CameraOrientation cam_view = { 0 };
GameRunData runData = { 0 };
FpsControl draw_times = { 0 };
@ -1788,7 +1796,17 @@ void Game::run()
updateProfilers(runData, stats, draw_times, dtime);
processUserInput(&flags, &runData, dtime);
// Update camera before player movement to avoid camera lag of one frame
updateCameraDirection(&cam_view, &flags);
updateCameraDirection(&cam_view_target, &flags);
float cam_smoothing = 0;
if (g_settings->getBool("cinematic"))
cam_smoothing = 1 - g_settings->getFloat("cinematic_camera_smoothing");
else
cam_smoothing = 1 - g_settings->getFloat("camera_smoothing");
cam_smoothing = rangelim(cam_smoothing, 0.01f, 1.0f);
cam_view.camera_yaw += (cam_view_target.camera_yaw -
cam_view.camera_yaw) * cam_smoothing;
cam_view.camera_pitch += (cam_view_target.camera_pitch -
cam_view.camera_pitch) * cam_smoothing;
updatePlayerControl(cam_view);
step(&dtime);
processClientEvents(&cam_view, &runData.damage_flash);
@ -2564,6 +2582,8 @@ void Game::processKeyboardInput(VolatileRunFlags *flags,
toggleFast(statustext_time);
} else if (input->wasKeyDown(keycache.key[KeyCache::KEYMAP_ID_NOCLIP])) {
toggleNoClip(statustext_time);
} else if (input->wasKeyDown(keycache.key[KeyCache::KEYMAP_ID_CINEMATIC])) {
toggleCinematic(statustext_time);
} else if (input->wasKeyDown(keycache.key[KeyCache::KEYMAP_ID_SCREENSHOT])) {
client->makeScreenshot(device);
} else if (input->wasKeyDown(keycache.key[KeyCache::KEYMAP_ID_TOGGLE_HUD])) {
@ -2669,6 +2689,15 @@ void Game::dropSelectedItem()
void Game::openInventory()
{
/*
* Don't permit to open inventory is CAO or player doesn't exists.
* This prevent showing an empty inventory at player load
*/
LocalPlayer *player = client->getEnv().getLocalPlayer();
if (player == NULL || player->getCAO() == NULL)
return;
infostream << "the_game: " << "Launching inventory" << std::endl;
PlayerInventoryFormSource *fs_src = new PlayerInventoryFormSource(client);
@ -2741,6 +2770,16 @@ void Game::toggleNoClip(float *statustext_time)
statustext += L" (note: no 'noclip' privilege)";
}
void Game::toggleCinematic(float *statustext_time)
{
static const wchar_t *msg[] = { L"cinematic disabled", L"cinematic enabled" };
bool cinematic = !g_settings->getBool("cinematic");
g_settings->set("cinematic", bool_to_cstr(cinematic));
*statustext_time = 0;
statustext = msg[cinematic];
}
void Game::toggleChat(float *statustext_time, bool *flag)
{
@ -3218,10 +3257,13 @@ void Game::updateCamera(VolatileRunFlags *flags, u32 busy_time,
v3s16 old_camera_offset = camera->getOffset();
if (input->wasKeyDown(keycache.key[KeyCache::KEYMAP_ID_CAMERA_MODE])) {
camera->toggleCameraMode();
GenericCAO *playercao = player->getCAO();
assert(playercao != NULL);
// If playercao not loaded, don't change camera
if (playercao == NULL)
return;
camera->toggleCameraMode();
playercao->setVisible(camera->getCameraMode() > CAMERA_MODE_FIRST);
}
@ -3926,6 +3968,28 @@ void Game::updateFrame(std::vector<aabb3f> &highlight_boxes,
}
inline static const char *yawToDirectionString(int yaw)
{
// NOTE: TODO: This can be done mathematically without the else/else-if
// cascade.
const char *player_direction;
yaw = wrapDegrees_0_360(yaw);
if (yaw >= 45 && yaw < 135)
player_direction = "West [-X]";
else if (yaw >= 135 && yaw < 225)
player_direction = "South [-Z]";
else if (yaw >= 225 && yaw < 315)
player_direction = "East [+X]";
else
player_direction = "North [+Z]";
return player_direction;
}
void Game::updateGui(float *statustext_time, const RunStats &stats,
const GameRunData& runData, f32 dtime, const VolatileRunFlags &flags,
const CameraOrientation &cam)
@ -3981,6 +4045,7 @@ void Game::updateGui(float *statustext_time, const RunStats &stats,
<< ", " << (player_position.Y / BS)
<< ", " << (player_position.Z / BS)
<< ") (yaw=" << (wrapDegrees_0_360(cam.camera_yaw))
<< " " << yawToDirectionString(cam.camera_yaw)
<< ") (seed = " << ((u64)client->getMapSeed())
<< ")";
@ -4198,4 +4263,3 @@ void the_game(bool *kill,
error_message = narrow_to_wide(e.what()) + wstrgettext("\nCheck debug.txt for details.");
}
}

View File

@ -26,24 +26,24 @@ with this program; if not, write to the Free Software Foundation, Inc.,
#include "log.h"
#if USE_GETTEXT && defined(_MSC_VER)
#include <WinNls.h>
#include <windows.h>
#include <map>
#include <direct.h>
#include "filesys.h"
#define setlocale(category,localename) \
setlocale(category,MSVC_LocaleLookup(localename))
#define setlocale(category, localename) \
setlocale(category, MSVC_LocaleLookup(localename))
static std::map<std::wstring,std::wstring> glb_supported_locales;
static std::map<std::wstring, std::wstring> glb_supported_locales;
/******************************************************************************/
BOOL CALLBACK UpdateLocaleCallback(LPTSTR pStr)
{
char* endptr = 0;
int LOCALEID = strtol(pStr,&endptr,16);
int LOCALEID = strtol(pStr, &endptr,16);
wchar_t buffer[LOCALE_NAME_MAX_LENGTH];
memset(buffer,0,sizeof(buffer));
memset(buffer, 0, sizeof(buffer));
if (GetLocaleInfoW(
LOCALEID,
LOCALE_SISO639LANGNAME,
@ -52,7 +52,7 @@ BOOL CALLBACK UpdateLocaleCallback(LPTSTR pStr)
std::wstring name = buffer;
memset(buffer,0,sizeof(buffer));
memset(buffer, 0, sizeof(buffer));
GetLocaleInfoW(
LOCALEID,
LOCALE_SISO3166CTRYNAME,
@ -61,7 +61,7 @@ BOOL CALLBACK UpdateLocaleCallback(LPTSTR pStr)
std::wstring country = buffer;
memset(buffer,0,sizeof(buffer));
memset(buffer, 0, sizeof(buffer));
GetLocaleInfoW(
LOCALEID,
LOCALE_SENGLISHLANGUAGENAME,
@ -96,7 +96,7 @@ const char* MSVC_LocaleLookup(const char* raw_shortname) {
}
if (first_use) {
EnumSystemLocalesA(UpdateLocaleCallback,LCID_SUPPORTED | LCID_ALTERNATE_SORTS);
EnumSystemLocalesA(UpdateLocaleCallback, LCID_SUPPORTED | LCID_ALTERNATE_SORTS);
first_use = false;
}
@ -148,8 +148,8 @@ void init_gettext(const char *path, const std::string &configured_language) {
if (current_language_var != configured_language) {
STARTUPINFO startupinfo;
PROCESS_INFORMATION processinfo;
memset(&startupinfo,0,sizeof(startupinfo));
memset(&processinfo,0,sizeof(processinfo));
memset(&startupinfo, 0, sizeof(startupinfo));
memset(&processinfo, 0, sizeof(processinfo));
errorstream << "MSVC localization workaround active restating minetest in new environment!" << std::endl;
std::string parameters = "";
@ -169,7 +169,7 @@ void init_gettext(const char *path, const std::string &configured_language) {
/** users may start by short name in commandline without extention **/
std::string appname = argv[0];
if (appname.substr(appname.length() -4) != ".exe") {
if (appname.substr(appname.length() - 4) != ".exe") {
appname += ".exe";
}
@ -260,7 +260,7 @@ void init_gettext(const char *path, const std::string &configured_language) {
/* no matter what locale is used we need number format to be "C" */
/* to ensure formspec parameters are evaluated correct! */
setlocale(LC_NUMERIC,"C");
setlocale(LC_NUMERIC, "C");
infostream << "Message locale is now set to: "
<< setlocale(LC_ALL, 0) << std::endl;
}

View File

@ -41,16 +41,19 @@ void init_gettext(const char *path, const std::string &configured_language);
extern const wchar_t *narrow_to_wide_c(const char *mbs);
extern std::wstring narrow_to_wide(const std::string &mbs);
// You must free the returned string!
inline const wchar_t *wgettext(const char *str)
{
return narrow_to_wide_c(gettext(str));
}
// Gettext under MSVC needs this strange way. Just don't ask...
inline std::wstring wstrgettext(const std::string &text)
{
return narrow_to_wide(gettext(text.c_str()));
const wchar_t *tmp = wgettext(text.c_str());
std::wstring retval = (std::wstring)tmp;
delete[] tmp;
return retval;
}
inline std::string strgettext(const std::string &text)

View File

@ -99,7 +99,7 @@ GUIChatConsole::GUIChatConsole(
{
core::dimension2d<u32> dim = m_font->getDimension(L"M");
m_fontsize = v2u32(dim.Width, dim.Height);
dstream << "Font size: " << m_fontsize.X << " " << m_fontsize.Y << std::endl;
m_font->grab();
}
m_fontsize.X = MYMAX(m_fontsize.X, 1);
m_fontsize.Y = MYMAX(m_fontsize.Y, 1);
@ -109,7 +109,10 @@ GUIChatConsole::GUIChatConsole(
}
GUIChatConsole::~GUIChatConsole()
{}
{
if (m_font)
m_font->drop();
}
void GUIChatConsole::openConsole(f32 height)
{

View File

@ -122,9 +122,6 @@ private:
// font
gui::IGUIFont* m_font;
v2u32 m_fontsize;
#if USE_FREETYPE
bool m_use_freetype;
#endif
};

View File

@ -39,9 +39,6 @@ with this program; if not, write to the Free Software Foundation, Inc.,
#include "log.h"
#include "tile.h" // ITextureSource
#include "hud.h" // drawItemStack
#include "hex.h"
#include "util/string.h"
#include "util/numeric.h"
#include "filesys.h"
#include "gettime.h"
#include "gettext.h"
@ -50,8 +47,10 @@ with this program; if not, write to the Free Software Foundation, Inc.,
#include "main.h"
#include "settings.h"
#include "client.h"
#include "util/string.h" // for parseColorString()
#include "fontengine.h"
#include "util/hex.h"
#include "util/numeric.h"
#include "util/string.h" // for parseColorString()
#define MY_CHECKPOS(a,b) \
if (v_pos.size() != 2) { \
@ -97,6 +96,7 @@ GUIFormSpecMenu::GUIFormSpecMenu(irr::IrrlichtDevice* dev,
m_form_src(fsrc),
m_text_dst(tdst),
m_formspec_version(0),
m_focused_element(L""),
m_font(NULL)
#ifdef __ANDROID__
,m_JavaDialogFieldName(L"")
@ -1757,8 +1757,6 @@ void GUIFormSpecMenu::parseElement(parserData* data, std::string element)
<<std::endl;
}
void GUIFormSpecMenu::regenerateGui(v2u32 screensize)
{
/* useless to regenerate without a screensize */
@ -1775,6 +1773,10 @@ void GUIFormSpecMenu::regenerateGui(v2u32 screensize)
mydata.table_dyndata[tablename] = table->getDynamicData();
}
//set focus
if (!m_focused_element.empty())
mydata.focused_fieldname = m_focused_element;
//preserve focus
gui::IGUIElement *focused_element = Environment->getFocus();
if (focused_element && focused_element->getParent() == this) {

View File

@ -246,13 +246,20 @@ public:
m_allowclose = value;
}
void lockSize(bool lock,v2u32 basescreensize=v2u32(0,0)) {
void lockSize(bool lock,v2u32 basescreensize=v2u32(0,0))
{
m_lock = lock;
m_lockscreensize = basescreensize;
}
void removeChildren();
void setInitialFocus();
void setFocus(std::wstring elementname)
{
m_focused_element = elementname;
}
/*
Remove and re-add (or reposition) stuff
*/
@ -348,6 +355,7 @@ private:
IFormSource *m_form_src;
TextDest *m_text_dst;
unsigned int m_formspec_version;
std::wstring m_focused_element;
typedef struct {
bool explicit_size;

View File

@ -51,6 +51,7 @@ enum
GUI_ID_KEY_FAST_BUTTON,
GUI_ID_KEY_JUMP_BUTTON,
GUI_ID_KEY_NOCLIP_BUTTON,
GUI_ID_KEY_CINEMATIC_BUTTON,
GUI_ID_KEY_CHAT_BUTTON,
GUI_ID_KEY_CMD_BUTTON,
GUI_ID_KEY_CONSOLE_BUTTON,
@ -137,27 +138,27 @@ void GUIKeyChangeMenu::regenerateGui(v2u32 screensize)
{
key_setting *k = key_settings.at(i);
{
core::rect < s32 > rect(0, 0, 100, 20);
core::rect < s32 > rect(0, 0, 110, 20);
rect += topleft + v2s32(offset.X, offset.Y);
Environment->addStaticText(k->button_name, rect, false, true, this, -1);
}
{
core::rect < s32 > rect(0, 0, 100, 30);
rect += topleft + v2s32(offset.X + 105, offset.Y - 5);
rect += topleft + v2s32(offset.X + 115, offset.Y - 5);
const wchar_t *text = wgettext(k->key.name());
k->button = Environment->addButton(rect, this, k->id, text);
delete[] text;
}
if(i + 1 == KMaxButtonPerColumns)
offset = v2s32(250, 60);
offset = v2s32(260, 60);
else
offset += v2s32(0, 25);
}
{
s32 option_x = offset.X + 10;
s32 option_y = offset.Y;
s32 option_x = offset.X;
s32 option_y = offset.Y + 5;
u32 option_w = 180;
{
core::rect<s32> rect(0, 0, option_w, 30);
@ -171,9 +172,9 @@ void GUIKeyChangeMenu::regenerateGui(v2u32 screensize)
}
{
s32 option_x = offset.X + 10;
s32 option_y = offset.Y;
u32 option_w = 220;
s32 option_x = offset.X;
s32 option_y = offset.Y + 5;
u32 option_w = 280;
{
core::rect<s32> rect(0, 0, option_w, 30);
rect += topleft + v2s32(option_x, option_y);
@ -394,22 +395,23 @@ void GUIKeyChangeMenu::add_key(int id, const wchar_t *button_name, const std::st
void GUIKeyChangeMenu::init_keys()
{
this->add_key(GUI_ID_KEY_FORWARD_BUTTON, wgettext("Forward"), "keymap_forward");
this->add_key(GUI_ID_KEY_BACKWARD_BUTTON, wgettext("Backward"), "keymap_backward");
this->add_key(GUI_ID_KEY_LEFT_BUTTON, wgettext("Left"), "keymap_left");
this->add_key(GUI_ID_KEY_RIGHT_BUTTON, wgettext("Right"), "keymap_right");
this->add_key(GUI_ID_KEY_USE_BUTTON, wgettext("Use"), "keymap_special1");
this->add_key(GUI_ID_KEY_JUMP_BUTTON, wgettext("Jump"), "keymap_jump");
this->add_key(GUI_ID_KEY_SNEAK_BUTTON, wgettext("Sneak"), "keymap_sneak");
this->add_key(GUI_ID_KEY_DROP_BUTTON, wgettext("Drop"), "keymap_drop");
this->add_key(GUI_ID_KEY_INVENTORY_BUTTON, wgettext("Inventory"), "keymap_inventory");
this->add_key(GUI_ID_KEY_CHAT_BUTTON, wgettext("Chat"), "keymap_chat");
this->add_key(GUI_ID_KEY_CMD_BUTTON, wgettext("Command"), "keymap_cmd");
this->add_key(GUI_ID_KEY_CONSOLE_BUTTON, wgettext("Console"), "keymap_console");
this->add_key(GUI_ID_KEY_FLY_BUTTON, wgettext("Toggle fly"), "keymap_freemove");
this->add_key(GUI_ID_KEY_FAST_BUTTON, wgettext("Toggle fast"), "keymap_fastmove");
this->add_key(GUI_ID_KEY_NOCLIP_BUTTON, wgettext("Toggle noclip"), "keymap_noclip");
this->add_key(GUI_ID_KEY_RANGE_BUTTON, wgettext("Range select"), "keymap_rangeselect");
this->add_key(GUI_ID_KEY_DUMP_BUTTON, wgettext("Print stacks"), "keymap_print_debug_stacks");
this->add_key(GUI_ID_KEY_FORWARD_BUTTON, wgettext("Forward"), "keymap_forward");
this->add_key(GUI_ID_KEY_BACKWARD_BUTTON, wgettext("Backward"), "keymap_backward");
this->add_key(GUI_ID_KEY_LEFT_BUTTON, wgettext("Left"), "keymap_left");
this->add_key(GUI_ID_KEY_RIGHT_BUTTON, wgettext("Right"), "keymap_right");
this->add_key(GUI_ID_KEY_USE_BUTTON, wgettext("Use"), "keymap_special1");
this->add_key(GUI_ID_KEY_JUMP_BUTTON, wgettext("Jump"), "keymap_jump");
this->add_key(GUI_ID_KEY_SNEAK_BUTTON, wgettext("Sneak"), "keymap_sneak");
this->add_key(GUI_ID_KEY_DROP_BUTTON, wgettext("Drop"), "keymap_drop");
this->add_key(GUI_ID_KEY_INVENTORY_BUTTON, wgettext("Inventory"), "keymap_inventory");
this->add_key(GUI_ID_KEY_CHAT_BUTTON, wgettext("Chat"), "keymap_chat");
this->add_key(GUI_ID_KEY_CMD_BUTTON, wgettext("Command"), "keymap_cmd");
this->add_key(GUI_ID_KEY_CONSOLE_BUTTON, wgettext("Console"), "keymap_console");
this->add_key(GUI_ID_KEY_FLY_BUTTON, wgettext("Toggle fly"), "keymap_freemove");
this->add_key(GUI_ID_KEY_FAST_BUTTON, wgettext("Toggle fast"), "keymap_fastmove");
this->add_key(GUI_ID_KEY_CINEMATIC_BUTTON, wgettext("Toggle Cinematic"), "keymap_cinematic");
this->add_key(GUI_ID_KEY_NOCLIP_BUTTON, wgettext("Toggle noclip"), "keymap_noclip");
this->add_key(GUI_ID_KEY_RANGE_BUTTON, wgettext("Range select"), "keymap_rangeselect");
this->add_key(GUI_ID_KEY_DUMP_BUTTON, wgettext("Print stacks"), "keymap_print_debug_stacks");
}

View File

@ -103,8 +103,8 @@ void GUIPasswordChange::regenerateGui(v2u32 screensize)
*/
s32 ypos = 50;
{
core::rect<s32> rect(0, 0, 110, 20);
rect += topleft_client + v2s32(35, ypos+6);
core::rect<s32> rect(0, 0, 150, 20);
rect += topleft_client + v2s32(25, ypos+6);
text = wgettext("Old Password");
Environment->addStaticText(text, rect, false, true, this, -1);
delete[] text;
@ -119,8 +119,8 @@ void GUIPasswordChange::regenerateGui(v2u32 screensize)
}
ypos += 50;
{
core::rect<s32> rect(0, 0, 110, 20);
rect += topleft_client + v2s32(35, ypos+6);
core::rect<s32> rect(0, 0, 150, 20);
rect += topleft_client + v2s32(25, ypos+6);
text = wgettext("New Password");
Environment->addStaticText(text, rect, false, true, this, -1);
delete[] text;
@ -134,8 +134,8 @@ void GUIPasswordChange::regenerateGui(v2u32 screensize)
}
ypos += 50;
{
core::rect<s32> rect(0, 0, 110, 20);
rect += topleft_client + v2s32(35, ypos+6);
core::rect<s32> rect(0, 0, 150, 20);
rect += topleft_client + v2s32(25, ypos+6);
text = wgettext("Confirm Password");
Environment->addStaticText(text, rect, false, true, this, -1);
delete[] text;

View File

@ -37,7 +37,7 @@ with this program; if not, write to the Free Software Foundation, Inc.,
#include "settings.h"
JMutex g_httpfetch_mutex;
std::map<unsigned long, std::list<HTTPFetchResult> > g_httpfetch_results;
std::map<unsigned long, std::queue<HTTPFetchResult> > g_httpfetch_results;
HTTPFetchRequest::HTTPFetchRequest()
{
@ -57,7 +57,7 @@ static void httpfetch_deliver_result(const HTTPFetchResult &fetch_result)
unsigned long caller = fetch_result.caller;
if (caller != HTTPFETCH_DISCARD) {
JMutexAutoLock lock(g_httpfetch_mutex);
g_httpfetch_results[caller].push_back(fetch_result);
g_httpfetch_results[caller].push(fetch_result);
}
}
@ -70,11 +70,11 @@ unsigned long httpfetch_caller_alloc()
// Check each caller ID except HTTPFETCH_DISCARD
const unsigned long discard = HTTPFETCH_DISCARD;
for (unsigned long caller = discard + 1; caller != discard; ++caller) {
std::map<unsigned long, std::list<HTTPFetchResult> >::iterator
std::map<unsigned long, std::queue<HTTPFetchResult> >::iterator
it = g_httpfetch_results.find(caller);
if (it == g_httpfetch_results.end()) {
verbosestream<<"httpfetch_caller_alloc: allocating "
<<caller<<std::endl;
verbosestream << "httpfetch_caller_alloc: allocating "
<< caller << std::endl;
// Access element to create it
g_httpfetch_results[caller];
return caller;
@ -102,19 +102,19 @@ bool httpfetch_async_get(unsigned long caller, HTTPFetchResult &fetch_result)
JMutexAutoLock lock(g_httpfetch_mutex);
// Check that caller exists
std::map<unsigned long, std::list<HTTPFetchResult> >::iterator
std::map<unsigned long, std::queue<HTTPFetchResult> >::iterator
it = g_httpfetch_results.find(caller);
if (it == g_httpfetch_results.end())
return false;
// Check that result queue is nonempty
std::list<HTTPFetchResult> &caller_results = it->second;
std::queue<HTTPFetchResult> &caller_results = it->second;
if (caller_results.empty())
return false;
// Pop first result
fetch_result = caller_results.front();
caller_results.pop_front();
caller_results.pop();
return true;
}
@ -194,7 +194,6 @@ private:
HTTPFetchRequest request;
HTTPFetchResult result;
std::ostringstream oss;
char *post_fields;
struct curl_slist *http_header;
curl_httppost *post;
};

View File

@ -249,8 +249,8 @@ public:
virtual ~CItemDefManager()
{
#ifndef SERVER
const std::list<ClientCached*> &values = m_clientcached.getValues();
for(std::list<ClientCached*>::const_iterator
const std::vector<ClientCached*> &values = m_clientcached.getValues();
for(std::vector<ClientCached*>::const_iterator
i = values.begin(); i != values.end(); ++i)
{
ClientCached *cc = *i;
@ -362,8 +362,6 @@ public:
scene::IMesh *node_mesh = NULL;
bool reenable_shaders = false;
if (need_rtt_mesh || need_wield_mesh) {
u8 param1 = 0;
if (f.param_type == CPT_LIGHT)
@ -372,11 +370,7 @@ public:
/*
Make a mesh from the node
*/
if (g_settings->getBool("enable_shaders")) {
reenable_shaders = true;
g_settings->setBool("enable_shaders", false);
}
MeshMakeData mesh_make_data(gamedef);
MeshMakeData mesh_make_data(gamedef, false);
u8 param2 = 0;
if (f.param_type_2 == CPT2_WALLMOUNTED)
param2 = 1;
@ -443,9 +437,6 @@ public:
if (node_mesh)
node_mesh->drop();
if (reenable_shaders)
g_settings->setBool("enable_shaders",true);
}
// Put in cache

View File

@ -30,7 +30,7 @@
#ifdef _WIN32
#include <windows.h>
#elif __MACH__
#elif defined(__MACH__) && defined(__APPLE__)
#include <mach/mach.h>
#include <mach/task.h>
#include <mach/semaphore.h>
@ -43,7 +43,7 @@
class Event {
#ifdef _WIN32
HANDLE hEvent;
#elif __MACH__
#elif defined(__MACH__) && defined(__APPLE__)
semaphore_t sem;
#else
sem_t sem;

View File

@ -24,7 +24,7 @@ with this program; if not, write to the Free Software Foundation, Inc.,
#include <windows.h>
#include <assert.h>
#define MAX_SEMAPHORE_COUNT 1024
#elif __MACH__
#elif defined(__MACH__) && defined(__APPLE__)
#include <pthread.h>
#include <mach/mach.h>
#include <mach/task.h>
@ -52,7 +52,7 @@ public:
private:
#if defined(WIN32)
HANDLE m_hSemaphore;
#elif __MACH__
#elif defined(__MACH__) && defined(__APPLE__)
semaphore_t m_semaphore;
int semcount;
#else

View File

@ -29,7 +29,7 @@
#define UNUSED(expr) do { (void)(expr); } while (0)
#ifdef __MACH__
#if defined(__MACH__) && defined(__APPLE__)
#undef sem_t
#define sem_t semaphore_t
#undef sem_init

View File

@ -20,13 +20,13 @@ with this program; if not, write to the Free Software Foundation, Inc.,
#include <errno.h>
#include <sys/time.h>
#include "jthread/jsemaphore.h"
#ifdef __MACH__
#if defined(__MACH__) && defined(__APPLE__)
#include <unistd.h>
#endif
#define UNUSED(expr) do { (void)(expr); } while (0)
#ifdef __MACH__
#if defined(__MACH__) && defined(__APPLE__)
#undef sem_t
#undef sem_init
#undef sem_wait
@ -44,7 +44,7 @@ JSemaphore::JSemaphore() {
int sem_init_retval = sem_init(&m_semaphore,0,0);
assert(sem_init_retval == 0);
UNUSED(sem_init_retval);
#ifdef __MACH__
#if defined(__MACH__) && defined(__APPLE__)
semcount = 0;
#endif
}
@ -73,7 +73,7 @@ void JSemaphore::Post() {
int sem_post_retval = sem_post(&m_semaphore);
assert(sem_post_retval == 0);
UNUSED(sem_post_retval);
#ifdef __MACH__
#if defined(__MACH__) && defined(__APPLE__)
pthread_mutex_lock(&semcount_mutex);
semcount++;
pthread_mutex_unlock(&semcount_mutex);
@ -84,7 +84,7 @@ void JSemaphore::Wait() {
int sem_wait_retval = sem_wait(&m_semaphore);
assert(sem_wait_retval == 0);
UNUSED(sem_wait_retval);
#ifdef __MACH__
#if defined(__MACH__) && defined(__APPLE__)
pthread_mutex_lock(&semcount_mutex);
semcount--;
pthread_mutex_unlock(&semcount_mutex);
@ -92,7 +92,7 @@ void JSemaphore::Wait() {
}
bool JSemaphore::Wait(unsigned int time_ms) {
#ifdef __MACH__
#if defined(__MACH__) && defined(__APPLE__)
mach_timespec_t waittime;
waittime.tv_sec = time_ms / 1000;
waittime.tv_nsec = 1000000 * (time_ms % 1000);
@ -106,14 +106,14 @@ bool JSemaphore::Wait(unsigned int time_ms) {
return false;
}
#ifndef __MACH__
#if !(defined(__MACH__) && defined(__APPLE__))
waittime.tv_nsec = ((time_ms % 1000) * 1000 * 1000) + (now.tv_usec * 1000);
waittime.tv_sec = (time_ms / 1000) + (waittime.tv_nsec / (1000*1000*1000)) + now.tv_sec;
waittime.tv_nsec %= 1000*1000*1000;
#endif
errno = 0;
#ifdef __MACH__
#if defined(__MACH__) && defined(__APPLE__)
int sem_wait_retval = semaphore_timedwait(m_semaphore, waittime);
if (sem_wait_retval == KERN_OPERATION_TIMED_OUT) {
errno = ETIMEDOUT;
@ -128,7 +128,7 @@ bool JSemaphore::Wait(unsigned int time_ms) {
if (sem_wait_retval == 0)
{
#ifdef __MACH__
#if defined(__MACH__) && defined(__APPLE__)
pthread_mutex_lock(&semcount_mutex);
semcount--;
pthread_mutex_unlock(&semcount_mutex);
@ -144,7 +144,7 @@ bool JSemaphore::Wait(unsigned int time_ms) {
int JSemaphore::GetValue() {
int retval = 0;
#ifdef __MACH__
#if defined(__MACH__) && defined(__APPLE__)
pthread_mutex_lock(&semcount_mutex);
retval = semcount;
pthread_mutex_unlock(&semcount_mutex);

View File

@ -22,8 +22,8 @@ with this program; if not, write to the Free Software Foundation, Inc.,
#include "exceptions.h"
#include "settings.h"
#include "log.h"
#include "hex.h"
#include "debug.h"
#include "util/hex.h"
class UnknownKeycode : public BaseException
{

View File

@ -67,7 +67,7 @@ LocalPlayer::~LocalPlayer()
}
void LocalPlayer::move(f32 dtime, Environment *env, f32 pos_max_d,
std::list<CollisionInfo> *collision_info)
std::vector<CollisionInfo> *collision_info)
{
Map *map = &env->getMap();
INodeDefManager *nodemgr = m_gamedef->ndef();
@ -323,9 +323,8 @@ void LocalPlayer::move(f32 dtime, Environment *env, f32 pos_max_d,
*/
bool bouncy_jump = false;
// Dont report if flying
if(collision_info && !(g_settings->getBool("free_move") && fly_allowed))
{
for(size_t i=0; i<result.collisions.size(); i++){
if(collision_info && !(g_settings->getBool("free_move") && fly_allowed)) {
for(size_t i=0; i<result.collisions.size(); i++) {
const CollisionInfo &info = result.collisions[i];
collision_info->push_back(info);
if(info.new_speed.Y - info.old_speed.Y > 0.1*BS &&

View File

@ -48,7 +48,7 @@ public:
void move(f32 dtime, Environment *env, f32 pos_max_d);
void move(f32 dtime, Environment *env, f32 pos_max_d,
std::list<CollisionInfo> *collision_info);
std::vector<CollisionInfo> *collision_info);
void applyControl(float dtime);

View File

@ -24,13 +24,14 @@ with this program; if not, write to the Free Software Foundation, Inc.,
#include <sstream>
#include <algorithm>
#include "threads.h"
#include "jthread/jmutexautolock.h"
#include "debug.h"
#include "gettime.h"
#include "porting.h"
#include "config.h"
#ifdef __ANDROID__
unsigned int android_log_level_mapping[] {
unsigned int android_log_level_mapping[] = {
/* LMT_ERROR */ ANDROID_LOG_ERROR,
/* LMT_ACTION */ ANDROID_LOG_WARN,
/* LMT_INFO */ ANDROID_LOG_INFO,
@ -38,7 +39,7 @@ unsigned int android_log_level_mapping[] {
};
#endif
std::list<ILogOutput*> log_outputs[LMT_NUM_VALUES];
std::vector<ILogOutput*> log_outputs[LMT_NUM_VALUES];
std::map<threadid_t, std::string> log_threadnames;
JMutex log_threadnamemutex;
@ -62,7 +63,7 @@ void log_add_output_all_levs(ILogOutput *out)
void log_remove_output(ILogOutput *out)
{
for(int i=0; i<LMT_NUM_VALUES; i++){
std::list<ILogOutput*>::iterator it =
std::vector<ILogOutput*>::iterator it =
std::find(log_outputs[i].begin(), log_outputs[i].end(), out);
if(it != log_outputs[i].end())
log_outputs[i].erase(it);
@ -71,33 +72,29 @@ void log_remove_output(ILogOutput *out)
void log_set_lev_silence(enum LogMessageLevel lev, bool silence)
{
log_threadnamemutex.Lock();
JMutexAutoLock lock(log_threadnamemutex);
for (std::list<ILogOutput *>::iterator
it = log_outputs[lev].begin();
it != log_outputs[lev].end();
++it) {
for (std::vector<ILogOutput *>::iterator it = log_outputs[lev].begin();
it != log_outputs[lev].end(); ++it) {
ILogOutput *out = *it;
out->silence = silence;
}
log_threadnamemutex.Unlock();
}
void log_register_thread(const std::string &name)
{
threadid_t id = get_current_thread_id();
log_threadnamemutex.Lock();
JMutexAutoLock lock(log_threadnamemutex);
log_threadnames[id] = name;
log_threadnamemutex.Unlock();
}
void log_deregister_thread()
{
threadid_t id = get_current_thread_id();
log_threadnamemutex.Lock();
JMutexAutoLock lock(log_threadnamemutex);
log_threadnames.erase(id);
log_threadnamemutex.Unlock();
}
static std::string get_lev_string(enum LogMessageLevel lev)
@ -119,7 +116,7 @@ static std::string get_lev_string(enum LogMessageLevel lev)
void log_printline(enum LogMessageLevel lev, const std::string &text)
{
log_threadnamemutex.Lock();
JMutexAutoLock lock(log_threadnamemutex);
std::string threadname = "(unknown thread)";
std::map<threadid_t, std::string>::const_iterator i;
i = log_threadnames.find(get_current_thread_id());
@ -127,9 +124,10 @@ void log_printline(enum LogMessageLevel lev, const std::string &text)
threadname = i->second;
std::string levelname = get_lev_string(lev);
std::ostringstream os(std::ios_base::binary);
os<<getTimestamp()<<": "<<levelname<<"["<<threadname<<"]: "<<text;
for(std::list<ILogOutput*>::iterator i = log_outputs[lev].begin();
i != log_outputs[lev].end(); i++){
os << getTimestamp() << ": " << levelname << "["<<threadname<<"]: " << text;
for(std::vector<ILogOutput*>::iterator i = log_outputs[lev].begin();
i != log_outputs[lev].end(); i++) {
ILogOutput *out = *i;
if (out->silence)
continue;
@ -138,7 +136,6 @@ void log_printline(enum LogMessageLevel lev, const std::string &text)
out->printLog(os.str(), lev);
out->printLog(lev, text);
}
log_threadnamemutex.Unlock();
}
class Logbuf : public std::streambuf

View File

@ -47,10 +47,6 @@ else()
endif()
mark_as_advanced(LUA_USE_DLOPEN)
if(DEFAULT_POSIX)
else()
endif()
if(DEFAULT_ANSI)
option(LUA_ANSI "Disable non-ansi features." ON)
else()
@ -87,6 +83,10 @@ if(LUA_USE_DLOPEN)
endif(NOT APPLE)
endif(LUA_USE_DLOPEN)
if(DEFAULT_POSIX)
set(COMMON_CFLAGS "${COMMON_CFLAGS} -DLUA_USE_POSIX")
endif(DEFAULT_POSIX)
if(LUA_ANSI)
set(COMMON_CFLAGS "${COMMON_CFLAGS} -DLUA_ANSI")
endif(LUA_ANSI)

View File

@ -17,19 +17,6 @@ with this program; if not, write to the Free Software Foundation, Inc.,
51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
*/
#ifdef NDEBUG
/*#ifdef _WIN32
#pragma message ("Disabling unit tests")
#else
#warning "Disabling unit tests"
#endif*/
// Disable unit tests
#define ENABLE_TESTS 0
#else
// Enable unit tests
#define ENABLE_TESTS 1
#endif
#ifdef _MSC_VER
#ifndef SERVER // Dedicated server isn't linked with Irrlicht
#pragma comment(lib, "Irrlicht.lib")
@ -75,18 +62,11 @@ with this program; if not, write to the Free Software Foundation, Inc.,
#include "serverlist.h"
#include "httpfetch.h"
#include "guiEngine.h"
#include "map.h"
#include "mapsector.h"
#include "player.h"
#include "fontengine.h"
#include "database-sqlite3.h"
#ifdef USE_LEVELDB
#include "database-leveldb.h"
#endif
#if USE_REDIS
#include "database-redis.h"
#endif
#include "database.h"
#ifdef HAVE_TOUCHSCREENGUI
#include "touchscreengui.h"
@ -174,8 +154,7 @@ static bool get_game_from_cmdline(GameParams *game_params, const Settings &cmd_a
static bool determine_subgame(GameParams *game_params);
static bool run_dedicated_server(const GameParams &game_params, const Settings &cmd_args);
static bool migrate_database(const GameParams &game_params, const Settings &cmd_args,
Server *server);
static bool migrate_database(const GameParams &game_params, const Settings &cmd_args);
#ifndef SERVER
static bool print_video_modes();
@ -836,9 +815,9 @@ int main(int argc, char *argv[])
#ifndef __ANDROID__
// Run unit tests
if ((ENABLE_TESTS && cmd_args.getFlag("disable-unittests") == false)
|| cmd_args.getFlag("enable-unittests") == true) {
if (cmd_args.getFlag("run-unittests")) {
run_tests();
return 0;
}
#endif
@ -909,10 +888,8 @@ static void set_allowed_options(OptionList *allowed_options)
_("Load configuration from specified file"))));
allowed_options->insert(std::make_pair("port", ValueSpec(VALUETYPE_STRING,
_("Set network port (UDP)"))));
allowed_options->insert(std::make_pair("disable-unittests", ValueSpec(VALUETYPE_FLAG,
_("Disable unit tests"))));
allowed_options->insert(std::make_pair("enable-unittests", ValueSpec(VALUETYPE_FLAG,
_("Enable unit tests"))));
allowed_options->insert(std::make_pair("run-unittests", ValueSpec(VALUETYPE_FLAG,
_("Run the unit tests and exit"))));
allowed_options->insert(std::make_pair("map-dir", ValueSpec(VALUETYPE_STRING,
_("Same as --world (deprecated)"))));
allowed_options->insert(std::make_pair("world", ValueSpec(VALUETYPE_STRING,
@ -1466,14 +1443,14 @@ static bool run_dedicated_server(const GameParams &game_params, const Settings &
return false;
}
// Database migration
if (cmd_args.exists("migrate"))
return migrate_database(game_params, cmd_args);
// Create server
Server server(game_params.world_path,
game_params.game_spec, false, bind_addr.isIPv6());
// Database migration
if (cmd_args.exists("migrate"))
return migrate_database(game_params, cmd_args, &server);
server.start(bind_addr);
// Run server
@ -1483,79 +1460,63 @@ static bool run_dedicated_server(const GameParams &game_params, const Settings &
return true;
}
static bool migrate_database(const GameParams &game_params, const Settings &cmd_args,
Server *server)
static bool migrate_database(const GameParams &game_params, const Settings &cmd_args)
{
Settings world_mt;
bool success = world_mt.readConfigFile((game_params.world_path
+ DIR_DELIM + "world.mt").c_str());
if (!success) {
errorstream << "Cannot read world.mt" << std::endl;
return false;
}
if (!world_mt.exists("backend")) {
errorstream << "Please specify your current backend in world.mt file:"
<< std::endl << " backend = {sqlite3|leveldb|redis|dummy}"
<< std::endl;
return false;
}
std::string backend = world_mt.get("backend");
Database *new_db;
std::string migrate_to = cmd_args.get("migrate");
Settings world_mt;
std::string world_mt_path = game_params.world_path + DIR_DELIM + "world.mt";
if (!world_mt.readConfigFile(world_mt_path.c_str())) {
errorstream << "Cannot read world.mt!" << std::endl;
return false;
}
if (!world_mt.exists("backend")) {
errorstream << "Please specify your current backend in world.mt:"
<< std::endl
<< " backend = {sqlite3|leveldb|redis|dummy}"
<< std::endl;
return false;
}
std::string backend = world_mt.get("backend");
if (backend == migrate_to) {
errorstream << "Cannot migrate: new backend is same as the old one"
<< std::endl;
errorstream << "Cannot migrate: new backend is same"
<< " as the old one" << std::endl;
return false;
}
Database *old_db = ServerMap::createDatabase(backend, game_params.world_path, world_mt),
*new_db = ServerMap::createDatabase(migrate_to, game_params.world_path, world_mt);
if (migrate_to == "sqlite3")
new_db = new Database_SQLite3(&(ServerMap&)server->getMap(),
game_params.world_path);
#if USE_LEVELDB
else if (migrate_to == "leveldb")
new_db = new Database_LevelDB(&(ServerMap&)server->getMap(),
game_params.world_path);
#endif
#if USE_REDIS
else if (migrate_to == "redis")
new_db = new Database_Redis(&(ServerMap&)server->getMap(),
game_params.world_path);
#endif
else {
errorstream << "Migration to " << migrate_to << " is not supported"
<< std::endl;
return false;
}
u32 count = 0;
time_t last_update_time = 0;
bool &kill = *porting::signal_handler_killstatus();
std::list<v3s16> blocks;
ServerMap &old_map = ((ServerMap&)server->getMap());
old_map.listAllLoadableBlocks(blocks);
int count = 0;
std::vector<v3s16> blocks;
old_db->listAllLoadableBlocks(blocks);
new_db->beginSave();
for (std::list<v3s16>::iterator i = blocks.begin(); i != blocks.end(); i++) {
MapBlock *block = old_map.loadBlock(*i);
if (!block) {
errorstream << "Failed to load block " << PP(*i) << ", skipping it.";
for (std::vector<v3s16>::const_iterator it = blocks.begin(); it != blocks.end(); ++it) {
if (kill) return false;
const std::string &data = old_db->loadBlock(*it);
if (!data.empty()) {
new_db->saveBlock(*it, data);
} else {
old_map.saveBlock(block, new_db);
MapSector *sector = old_map.getSectorNoGenerate(v2s16(i->X, i->Z));
sector->deleteBlock(block);
errorstream << "Failed to load block " << PP(*it) << ", skipping it." << std::endl;
}
if (++count % 0xFF == 0 && time(NULL) - last_update_time >= 1) {
std::cerr << " Migrated " << count << " blocks, "
<< (100.0 * count / blocks.size()) << "% completed.\r";
new_db->endSave();
new_db->beginSave();
last_update_time = time(NULL);
}
++count;
if (count % 500 == 0)
actionstream << "Migrated " << count << " blocks "
<< (100.0 * count / blocks.size()) << "% completed" << std::endl;
}
std::cerr << std::endl;
new_db->endSave();
delete old_db;
delete new_db;
actionstream << "Successfully migrated " << count << " blocks" << std::endl;
world_mt.set("backend", migrate_to);
if (!world_mt.updateConfigFile(
(game_params.world_path+ DIR_DELIM + "world.mt").c_str()))
if (!world_mt.updateConfigFile(world_mt_path.c_str()))
errorstream << "Failed to update world.mt!" << std::endl;
else
actionstream << "world.mt updated" << std::endl;
@ -1633,13 +1594,15 @@ bool ClientLauncher::run(GameParams &game_params, const Settings &cmd_args)
input = new RealInputHandler(device, receiver);
smgr = device->getSceneManager();
smgr->getParameters()->setAttribute(scene::ALLOW_ZWRITE_ON_TRANSPARENT, true);
guienv = device->getGUIEnvironment();
skin = guienv->getSkin();
skin->setColor(gui::EGDC_BUTTON_TEXT, video::SColor(255, 255, 255, 255));
skin->setColor(gui::EGDC_3D_HIGH_LIGHT, video::SColor(255, 0, 0, 0));
skin->setColor(gui::EGDC_3D_LIGHT, video::SColor(0, 0, 0, 0));
skin->setColor(gui::EGDC_3D_HIGH_LIGHT, video::SColor(255, 30, 30, 30));
skin->setColor(gui::EGDC_3D_SHADOW, video::SColor(255, 0, 0, 0));
skin->setColor(gui::EGDC_HIGH_LIGHT, video::SColor(255, 70, 100, 50));
skin->setColor(gui::EGDC_HIGH_LIGHT, video::SColor(255, 70, 120, 50));
skin->setColor(gui::EGDC_HIGH_LIGHT_TEXT, video::SColor(255, 255, 255, 255));
g_fontengine = new FontEngine(g_settings, guienv);

View File

@ -53,22 +53,6 @@ with this program; if not, write to the Free Software Foundation, Inc.,
#define PP(x) "("<<(x).X<<","<<(x).Y<<","<<(x).Z<<")"
/*
SQLite format specification:
- Initially only replaces sectors/ and sectors2/
If map.sqlite does not exist in the save dir
or the block was not found in the database
the map will try to load from sectors folder.
In either case, map.sqlite will be created
and all future saves will save there.
Structure of map.sqlite:
Tables:
blocks
(PK) INT pos
BLOB data
*/
/*
Map
@ -1421,43 +1405,39 @@ bool Map::getDayNightDiff(v3s16 blockpos)
Updates usage timers
*/
void Map::timerUpdate(float dtime, float unload_timeout,
std::list<v3s16> *unloaded_blocks)
std::vector<v3s16> *unloaded_blocks)
{
bool save_before_unloading = (mapType() == MAPTYPE_SERVER);
// Profile modified reasons
Profiler modprofiler;
std::list<v2s16> sector_deletion_queue;
std::vector<v2s16> sector_deletion_queue;
u32 deleted_blocks_count = 0;
u32 saved_blocks_count = 0;
u32 block_count_all = 0;
beginSave();
for(std::map<v2s16, MapSector*>::iterator si = m_sectors.begin();
si != m_sectors.end(); ++si)
{
si != m_sectors.end(); ++si) {
MapSector *sector = si->second;
bool all_blocks_deleted = true;
std::list<MapBlock*> blocks;
MapBlockVect blocks;
sector->getBlocks(blocks);
for(std::list<MapBlock*>::iterator i = blocks.begin();
i != blocks.end(); ++i)
{
for(MapBlockVect::iterator i = blocks.begin();
i != blocks.end(); ++i) {
MapBlock *block = (*i);
block->incrementUsageTimer(dtime);
if(block->refGet() == 0 && block->getUsageTimer() > unload_timeout)
{
if(block->refGet() == 0 && block->getUsageTimer() > unload_timeout) {
v3s16 p = block->getPos();
// Save if modified
if (block->getModified() != MOD_STATE_CLEAN && save_before_unloading)
{
if (block->getModified() != MOD_STATE_CLEAN && save_before_unloading) {
modprofiler.add(block->getModifiedReason(), 1);
if (!saveBlock(block))
continue;
@ -1472,15 +1452,13 @@ void Map::timerUpdate(float dtime, float unload_timeout,
deleted_blocks_count++;
}
else
{
else {
all_blocks_deleted = false;
block_count_all++;
}
}
if(all_blocks_deleted)
{
if(all_blocks_deleted) {
sector_deletion_queue.push_back(si->first);
}
}
@ -1506,16 +1484,15 @@ void Map::timerUpdate(float dtime, float unload_timeout,
}
}
void Map::unloadUnreferencedBlocks(std::list<v3s16> *unloaded_blocks)
void Map::unloadUnreferencedBlocks(std::vector<v3s16> *unloaded_blocks)
{
timerUpdate(0.0, -1.0, unloaded_blocks);
}
void Map::deleteSectors(std::list<v2s16> &list)
void Map::deleteSectors(std::vector<v2s16> &sectorList)
{
for(std::list<v2s16>::iterator j = list.begin();
j != list.end(); ++j)
{
for(std::vector<v2s16>::iterator j = sectorList.begin();
j != sectorList.end(); ++j) {
MapSector *sector = m_sectors[*j];
// If sector is in sector cache, remove it from there
if(m_sector_cache == sector)
@ -1526,63 +1503,6 @@ void Map::deleteSectors(std::list<v2s16> &list)
}
}
#if 0
void Map::unloadUnusedData(float timeout,
core::list<v3s16> *deleted_blocks)
{
core::list<v2s16> sector_deletion_queue;
u32 deleted_blocks_count = 0;
u32 saved_blocks_count = 0;
core::map<v2s16, MapSector*>::Iterator si = m_sectors.getIterator();
for(; si.atEnd() == false; si++)
{
MapSector *sector = si.getNode()->getValue();
bool all_blocks_deleted = true;
core::list<MapBlock*> blocks;
sector->getBlocks(blocks);
for(core::list<MapBlock*>::Iterator i = blocks.begin();
i != blocks.end(); i++)
{
MapBlock *block = (*i);
if(block->getUsageTimer() > timeout)
{
// Save if modified
if(block->getModified() != MOD_STATE_CLEAN)
{
saveBlock(block);
saved_blocks_count++;
}
// Delete from memory
sector->deleteBlock(block);
deleted_blocks_count++;
}
else
{
all_blocks_deleted = false;
}
}
if(all_blocks_deleted)
{
sector_deletion_queue.push_back(si.getNode()->getKey());
}
}
deleteSectors(sector_deletion_queue);
infostream<<"Map: Unloaded "<<deleted_blocks_count<<" blocks from memory"
<<", of which "<<saved_blocks_count<<" were wr."
<<std::endl;
//return sector_deletion_queue.getSize();
//return deleted_blocks_count;
}
#endif
void Map::PrintInfo(std::ostream &out)
{
out<<"Map: ";
@ -1863,11 +1783,11 @@ void Map::transformLiquids(std::map<v3s16, MapBlock*> & modified_blocks)
// Find out whether there is a suspect for this action
std::string suspect;
if(m_gamedef->rollback()){
if(m_gamedef->rollback()) {
suspect = m_gamedef->rollback()->getSuspect(p0, 83, 1);
}
if(!suspect.empty()){
if(m_gamedef->rollback() && !suspect.empty()){
// Blame suspect
RollbackScopeActor rollback_scope(m_gamedef->rollback(), suspect, true);
// Get old node for rollback
@ -2095,25 +2015,13 @@ ServerMap::ServerMap(std::string savedir, IGameDef *gamedef, EmergeManager *emer
bool succeeded = conf.readConfigFile(conf_path.c_str());
if (!succeeded || !conf.exists("backend")) {
// fall back to sqlite3
dbase = new Database_SQLite3(this, savedir);
conf.set("backend", "sqlite3");
} else {
std::string backend = conf.get("backend");
if (backend == "dummy")
dbase = new Database_Dummy(this);
else if (backend == "sqlite3")
dbase = new Database_SQLite3(this, savedir);
#if USE_LEVELDB
else if (backend == "leveldb")
dbase = new Database_LevelDB(this, savedir);
#endif
#if USE_REDIS
else if (backend == "redis")
dbase = new Database_Redis(this, savedir);
#endif
else
throw BaseException("Unknown map backend");
}
std::string backend = conf.get("backend");
dbase = createDatabase(backend, savedir, conf);
if (!conf.updateConfigFile(conf_path.c_str()))
errorstream << "ServerMap::ServerMap(): Failed to update world.mt!" << std::endl;
m_savedir = savedir;
m_map_saving_enabled = false;
@ -2892,7 +2800,8 @@ plan_b:
}
bool ServerMap::loadFromFolders() {
if(!dbase->Initialized() && !fs::PathExists(m_savedir + DIR_DELIM + "map.sqlite")) // ?
if (!dbase->initialized() &&
!fs::PathExists(m_savedir + DIR_DELIM + "map.sqlite"))
return true;
return false;
}
@ -2914,14 +2823,14 @@ std::string ServerMap::getSectorDir(v2s16 pos, int layout)
{
case 1:
snprintf(cc, 9, "%.4x%.4x",
(unsigned int)pos.X&0xffff,
(unsigned int)pos.Y&0xffff);
(unsigned int) pos.X & 0xffff,
(unsigned int) pos.Y & 0xffff);
return m_savedir + DIR_DELIM + "sectors" + DIR_DELIM + cc;
case 2:
snprintf(cc, 9, "%.3x" DIR_DELIM "%.3x",
(unsigned int)pos.X&0xfff,
(unsigned int)pos.Y&0xfff);
snprintf(cc, 9, (std::string("%.3x") + DIR_DELIM + "%.3x").c_str(),
(unsigned int) pos.X & 0xfff,
(unsigned int) pos.Y & 0xfff);
return m_savedir + DIR_DELIM + "sectors2" + DIR_DELIM + cc;
default:
@ -2945,10 +2854,10 @@ v2s16 ServerMap::getSectorPos(std::string dirname)
{
// New layout
fs::RemoveLastPathComponent(dirname, &component, 2);
r = sscanf(component.c_str(), "%3x" DIR_DELIM "%3x", &x, &y);
r = sscanf(component.c_str(), (std::string("%3x") + DIR_DELIM + "%3x").c_str(), &x, &y);
// Sign-extend the 12 bit values up to 16 bits...
if(x&0x800) x|=0xF000;
if(y&0x800) y|=0xF000;
if(x & 0x800) x |= 0xF000;
if(y & 0x800) y |= 0xF000;
}
else
{
@ -2983,8 +2892,7 @@ std::string ServerMap::getBlockFilename(v3s16 p)
void ServerMap::save(ModifiedState save_level)
{
DSTACK(__FUNCTION_NAME);
if(m_map_saving_enabled == false)
{
if(m_map_saving_enabled == false) {
infostream<<"WARNING: Not saving map, saving disabled."<<std::endl;
return;
}
@ -2993,8 +2901,7 @@ void ServerMap::save(ModifiedState save_level)
infostream<<"ServerMap: Saving whole map, this can take time."
<<std::endl;
if(m_map_metadata_changed || save_level == MOD_STATE_CLEAN)
{
if(m_map_metadata_changed || save_level == MOD_STATE_CLEAN) {
saveMapMeta();
}
@ -3009,30 +2916,27 @@ void ServerMap::save(ModifiedState save_level)
bool save_started = false;
for(std::map<v2s16, MapSector*>::iterator i = m_sectors.begin();
i != m_sectors.end(); ++i)
{
i != m_sectors.end(); ++i) {
ServerMapSector *sector = (ServerMapSector*)i->second;
assert(sector->getId() == MAPSECTOR_SERVER);
if(sector->differs_from_disk || save_level == MOD_STATE_CLEAN)
{
if(sector->differs_from_disk || save_level == MOD_STATE_CLEAN) {
saveSectorMeta(sector);
sector_meta_count++;
}
std::list<MapBlock*> blocks;
MapBlockVect blocks;
sector->getBlocks(blocks);
for(std::list<MapBlock*>::iterator j = blocks.begin();
j != blocks.end(); ++j)
{
for(MapBlockVect::iterator j = blocks.begin();
j != blocks.end(); ++j) {
MapBlock *block = *j;
block_count_all++;
if(block->getModified() >= (u32)save_level)
{
if(block->getModified() >= (u32)save_level) {
// Lazy beginSave()
if(!save_started){
if(!save_started) {
beginSave();
save_started = true;
}
@ -3050,6 +2954,7 @@ void ServerMap::save(ModifiedState save_level)
}
}
}
if(save_started)
endSave();
@ -3057,8 +2962,7 @@ void ServerMap::save(ModifiedState save_level)
Only print if something happened or saved whole map
*/
if(save_level == MOD_STATE_CLEAN || sector_meta_count != 0
|| block_count != 0)
{
|| block_count != 0) {
infostream<<"ServerMap: Written: "
<<sector_meta_count<<" sector metadata files, "
<<block_count<<" block files"
@ -3070,30 +2974,28 @@ void ServerMap::save(ModifiedState save_level)
}
}
void ServerMap::listAllLoadableBlocks(std::list<v3s16> &dst)
void ServerMap::listAllLoadableBlocks(std::vector<v3s16> &dst)
{
if(loadFromFolders()){
errorstream<<"Map::listAllLoadableBlocks(): Result will be missing "
<<"all blocks that are stored in flat files"<<std::endl;
if (loadFromFolders()) {
errorstream << "Map::listAllLoadableBlocks(): Result will be missing "
<< "all blocks that are stored in flat files." << std::endl;
}
dbase->listAllLoadableBlocks(dst);
}
void ServerMap::listAllLoadedBlocks(std::list<v3s16> &dst)
void ServerMap::listAllLoadedBlocks(std::vector<v3s16> &dst)
{
for(std::map<v2s16, MapSector*>::iterator si = m_sectors.begin();
si != m_sectors.end(); ++si)
{
MapSector *sector = si->second;
std::list<MapBlock*> blocks;
MapBlockVect blocks;
sector->getBlocks(blocks);
for(std::list<MapBlock*>::iterator i = blocks.begin();
i != blocks.end(); ++i)
{
MapBlock *block = (*i);
v3s16 p = block->getPos();
for(MapBlockVect::iterator i = blocks.begin();
i != blocks.end(); ++i) {
v3s16 p = (*i)->getPos();
dst.push_back(p);
}
}
@ -3331,6 +3233,24 @@ bool ServerMap::loadSectorFull(v2s16 p2d)
}
#endif
Database *ServerMap::createDatabase(const std::string &name, const std::string &savedir, Settings &conf)
{
if (name == "sqlite3")
return new Database_SQLite3(savedir);
if (name == "dummy")
return new Database_Dummy();
#if USE_LEVELDB
else if (name == "leveldb")
return new Database_LevelDB(savedir);
#endif
#if USE_REDIS
else if (name == "redis")
return new Database_Redis(conf);
#endif
else
throw BaseException(std::string("Database backend ") + name + " not supported.");
}
void ServerMap::beginSave()
{
dbase->beginSave();
@ -3370,7 +3290,7 @@ bool ServerMap::saveBlock(MapBlock *block, Database *db)
std::string data = o.str();
bool ret = db->saveBlock(p3d, data);
if(ret) {
if (ret) {
// We just wrote it to the disk so clear modified flag
block->resetModified();
}
@ -3382,7 +3302,7 @@ void ServerMap::loadBlock(std::string sectordir, std::string blockfile,
{
DSTACK(__FUNCTION_NAME);
std::string fullpath = sectordir+DIR_DELIM+blockfile;
std::string fullpath = sectordir + DIR_DELIM + blockfile;
try {
std::ifstream is(fullpath.c_str(), std::ios_base::binary);
@ -3584,7 +3504,7 @@ MapBlock* ServerMap::loadBlock(v3s16 blockpos)
*/
std::string blockfilename = getBlockFilename(blockpos);
if(fs::PathExists(sectordir+DIR_DELIM+blockfilename) == false)
if(fs::PathExists(sectordir + DIR_DELIM + blockfilename) == false)
return NULL;
/*

View File

@ -34,6 +34,7 @@ with this program; if not, write to the Free Software Foundation, Inc.,
#include "util/container.h"
#include "nodetimer.h"
class Settings;
class Database;
class ClientMap;
class MapSector;
@ -277,28 +278,18 @@ public:
Saves modified blocks before unloading on MAPTYPE_SERVER.
*/
void timerUpdate(float dtime, float unload_timeout,
std::list<v3s16> *unloaded_blocks=NULL);
std::vector<v3s16> *unloaded_blocks=NULL);
/*
Unloads all blocks with a zero refCount().
Saves modified blocks before unloading on MAPTYPE_SERVER.
*/
void unloadUnreferencedBlocks(std::list<v3s16> *unloaded_blocks=NULL);
void unloadUnreferencedBlocks(std::vector<v3s16> *unloaded_blocks=NULL);
// Deletes sectors and their blocks from memory
// Takes cache into account
// If deleted sector is in sector cache, clears cache
void deleteSectors(std::list<v2s16> &list);
#if 0
/*
Unload unused data
= flush changed to disk and delete from memory, if usage timer of
block is more than timeout
*/
void unloadUnusedData(float timeout,
core::list<v3s16> *deleted_blocks=NULL);
#endif
void deleteSectors(std::vector<v2s16> &list);
// For debug printing. Prints "Map: ", "ServerMap: " or "ClientMap: "
virtual void PrintInfo(std::ostream &out);
@ -455,6 +446,7 @@ public:
/*
Database functions
*/
static Database *createDatabase(const std::string &name, const std::string &savedir, Settings &conf);
// Verify we can read/write to the database
void verifyDatabase();
@ -466,8 +458,8 @@ public:
void endSave();
void save(ModifiedState save_level);
void listAllLoadableBlocks(std::list<v3s16> &dst);
void listAllLoadedBlocks(std::list<v3s16> &dst);
void listAllLoadableBlocks(std::vector<v3s16> &dst);
void listAllLoadedBlocks(std::vector<v3s16> &dst);
// Saves map seed and possibly other stuff
void saveMapMeta();
void loadMapMeta();
@ -491,8 +483,8 @@ public:
// Returns true if sector now resides in memory
//bool deFlushSector(v2s16 p2d);
bool saveBlock(MapBlock *block, Database *db);
bool saveBlock(MapBlock *block);
static bool saveBlock(MapBlock *block, Database *db);
// This will generate a sector with getSector if not found.
void loadBlock(std::string sectordir, std::string blockfile, MapSector *sector, bool save_after_load=false);
MapBlock* loadBlock(v3s16 p);

View File

@ -330,47 +330,42 @@ void MapBlock::copyFrom(VoxelManipulator &dst)
void MapBlock::actuallyUpdateDayNightDiff()
{
INodeDefManager *nodemgr = m_gamedef->ndef();
// Running this function un-expires m_day_night_differs
m_day_night_differs_expired = false;
if(data == NULL)
{
if (data == NULL) {
m_day_night_differs = false;
return;
}
bool differs = false;
bool differs;
/*
Check if any lighting value differs
*/
for(u32 i=0; i<MAP_BLOCKSIZE*MAP_BLOCKSIZE*MAP_BLOCKSIZE; i++)
{
for (u32 i = 0; i < MAP_BLOCKSIZE*MAP_BLOCKSIZE*MAP_BLOCKSIZE; i++) {
MapNode &n = data[i];
if(n.getLight(LIGHTBANK_DAY, nodemgr) != n.getLight(LIGHTBANK_NIGHT, nodemgr))
{
differs = true;
differs = !n.isLightDayNightEq(nodemgr);
if (differs)
break;
}
}
/*
If some lighting values differ, check if the whole thing is
just air. If it is, differ = false
just air. If it is just air, differs = false
*/
if(differs)
{
if (differs) {
bool only_air = true;
for(u32 i=0; i<MAP_BLOCKSIZE*MAP_BLOCKSIZE*MAP_BLOCKSIZE; i++)
{
for (u32 i = 0; i < MAP_BLOCKSIZE*MAP_BLOCKSIZE*MAP_BLOCKSIZE; i++) {
MapNode &n = data[i];
if(n.getContent() != CONTENT_AIR)
{
if (n.getContent() != CONTENT_AIR) {
only_air = false;
break;
}
}
if(only_air)
if (only_air)
differs = false;
}

View File

@ -614,6 +614,8 @@ private:
int m_refcount;
};
typedef std::vector<MapBlock*> MapBlockVect;
inline bool blockpos_over_limit(v3s16 p)
{
return

View File

@ -42,7 +42,7 @@ static void applyFacesShading(video::SColor& color, float factor)
MeshMakeData
*/
MeshMakeData::MeshMakeData(IGameDef *gamedef):
MeshMakeData::MeshMakeData(IGameDef *gamedef, bool use_shaders):
m_vmanip(),
m_blockpos(-1337,-1337,-1337),
m_crack_pos_relative(-1337, -1337, -1337),
@ -50,7 +50,8 @@ MeshMakeData::MeshMakeData(IGameDef *gamedef):
m_smooth_lighting(false),
m_show_hud(false),
m_highlight_mesh_color(255, 255, 255, 255),
m_gamedef(gamedef)
m_gamedef(gamedef),
m_use_shaders(use_shaders)
{}
void MeshMakeData::fill(MapBlock *block)
@ -247,7 +248,7 @@ static u16 getSmoothLightCombined(v3s16 p, MeshMakeData *data)
for (u32 i = 0; i < 8; i++)
{
MapNode n = data->m_vmanip.getNodeNoEx(p - dirs8[i]);
const MapNode &n = data->m_vmanip.getNodeRefUnsafeCheckFlags(p - dirs8[i]);
// if it's CONTENT_IGNORE we can't do any light calculations
if (n.getContent() == CONTENT_IGNORE) {
@ -437,8 +438,6 @@ struct FastFace
static void makeFastFace(TileSpec tile, u16 li0, u16 li1, u16 li2, u16 li3,
v3f p, v3s16 dir, v3f scale, u8 light_source, std::vector<FastFace> &dest)
{
FastFace face;
// Position is at the center of the cube.
v3f pos = p * BS;
@ -589,6 +588,10 @@ static void makeFastFace(TileSpec tile, u16 li0, u16 li1, u16 li2, u16 li3,
u8 alpha = tile.alpha;
dest.push_back(FastFace());
FastFace& face = *dest.rbegin();
face.vertices[0] = video::S3DVertex(vertex_pos[0], normal,
MapBlock_LightColor(alpha, li0, light_source),
core::vector2d<f32>(x0+w*abs_scale, y0+h));
@ -603,7 +606,6 @@ static void makeFastFace(TileSpec tile, u16 li0, u16 li1, u16 li2, u16 li3,
core::vector2d<f32>(x0+w*abs_scale, y0));
face.tile = tile;
dest.push_back(face);
}
/*
@ -744,8 +746,8 @@ TileSpec getNodeTile(MapNode mn, v3s16 p, v3s16 dir, MeshMakeData *data)
static void getTileInfo(
// Input:
MeshMakeData *data,
v3s16 p,
v3s16 face_dir,
const v3s16 &p,
const v3s16 &face_dir,
// Output:
bool &makes_face,
v3s16 &p_corrected,
@ -759,14 +761,20 @@ static void getTileInfo(
INodeDefManager *ndef = data->m_gamedef->ndef();
v3s16 blockpos_nodes = data->m_blockpos * MAP_BLOCKSIZE;
MapNode n0 = vmanip.getNodeNoEx(blockpos_nodes + p);
MapNode &n0 = vmanip.getNodeRefUnsafe(blockpos_nodes + p);
// Don't even try to get n1 if n0 is already CONTENT_IGNORE
if (n0.getContent() == CONTENT_IGNORE ) {
if (n0.getContent() == CONTENT_IGNORE) {
makes_face = false;
return;
}
const MapNode &n1 = vmanip.getNodeRefUnsafeCheckFlags(blockpos_nodes + p + face_dir);
if (n1.getContent() == CONTENT_IGNORE) {
makes_face = false;
return;
}
MapNode n1 = vmanip.getNodeNoEx(blockpos_nodes + p + face_dir);
// This is hackish
bool equivalent = false;
@ -1028,7 +1036,7 @@ MapBlockMesh::MapBlockMesh(MeshMakeData *data, v3s16 camera_offset):
m_last_daynight_ratio((u32) -1),
m_daynight_diffs()
{
m_enable_shaders = g_settings->getBool("enable_shaders");
m_enable_shaders = data->m_use_shaders;
m_enable_highlighting = g_settings->getBool("enable_node_highlighting");
// 4-21ms for MAP_BLOCKSIZE=16 (NOTE: probably outdated)
@ -1036,6 +1044,7 @@ MapBlockMesh::MapBlockMesh(MeshMakeData *data, v3s16 camera_offset):
//TimeTaker timer1("MapBlockMesh()");
std::vector<FastFace> fastfaces_new;
fastfaces_new.reserve(512);
/*
We are including the faces of the trailing edges of the block.

View File

@ -45,8 +45,9 @@ struct MeshMakeData
video::SColor m_highlight_mesh_color;
IGameDef *m_gamedef;
bool m_use_shaders;
MeshMakeData(IGameDef *gamedef);
MeshMakeData(IGameDef *gamedef, bool use_shaders);
/*
Copy central data directly from block, and other data from

View File

@ -41,6 +41,8 @@ with this program; if not, write to the Free Software Foundation, Inc.,
const char *GenElementManager::ELEMENT_TITLE = "element";
static const s16 INVALID_HEIGHT = MAP_GENERATION_LIMIT + 1;
FlagDesc flagdesc_mapgen[] = {
{"trees", MG_TREES},
{"caves", MG_CAVES},
@ -155,6 +157,12 @@ s16 Mapgen::findGroundLevel(v2s16 p2d, s16 ymin, s16 ymax)
}
void Mapgen::initHeightMap(s16 *dest, size_t len)
{
for (size_t i = 0; i < len; i++)
dest[i] = INVALID_HEIGHT;
}
void Mapgen::updateHeightmap(v3s16 nmin, v3s16 nmax)
{
if (!heightmap)
@ -166,11 +174,13 @@ void Mapgen::updateHeightmap(v3s16 nmin, v3s16 nmax)
for (s16 x = nmin.X; x <= nmax.X; x++, index++) {
s16 y = findGroundLevel(v2s16(x, z), nmin.Y, nmax.Y);
// if the values found are out of range, trust the old heightmap
if (y == nmax.Y && heightmap[index] > nmax.Y)
continue;
if (y == nmin.Y - 1 && heightmap[index] < nmin.Y)
continue;
if (heightmap[index] != INVALID_HEIGHT) {
// if the values found are out of range, trust the old heightmap
if (y == nmax.Y && heightmap[index] > nmax.Y)
continue;
if (y == nmin.Y - 1 && heightmap[index] < nmin.Y)
continue;
}
heightmap[index] = y;
}
@ -417,9 +427,8 @@ void GenerateNotifier::getEvents(
std::map<std::string, std::vector<v3s16> > &event_map,
bool peek_events)
{
std::list<GenNotifyEvent>::iterator it;
for (it = m_notify_events.begin(); it != m_notify_events.end(); ++it) {
for (std::vector<GenNotifyEvent>::iterator it = m_notify_events.begin();
it != m_notify_events.end(); ++it) {
GenNotifyEvent &gn = *it;
std::string name = (gn.type == GENNOTIFY_DECORATION) ?
"decoration#"+ itos(gn.id) :

View File

@ -91,7 +91,7 @@ public:
private:
u32 m_notify_on;
std::set<u32> *m_notify_on_deco_ids;
std::list<GenNotifyEvent> m_notify_events;
std::vector<GenNotifyEvent> m_notify_events;
};
struct MapgenSpecificParams {
@ -151,6 +151,7 @@ public:
static u32 getBlockSeed2(v3s16 p, int seed);
s16 findGroundLevelFull(v2s16 p2d);
s16 findGroundLevel(v2s16 p2d, s16 ymin, s16 ymax);
void initHeightMap(s16 *dest, size_t len);
void updateHeightmap(v3s16 nmin, v3s16 nmax);
void updateLiquid(UniqueQueue<v3s16> *trans_liquid, v3s16 nmin, v3s16 nmax);

View File

@ -42,7 +42,6 @@ with this program; if not, write to the Free Software Foundation, Inc.,
FlagDesc flagdesc_mapgen_v5[] = {
{"blobs", MGV5_BLOBS},
{NULL, 0}
};
@ -61,6 +60,8 @@ MapgenV5::MapgenV5(int mapgenid, MapgenParams *params, EmergeManager *emerge)
this->biomemap = new u8[csize.X * csize.Z];
this->heightmap = new s16[csize.X * csize.Z];
initHeightMap(this->heightmap, csize.X * csize.Z);
MapgenV5Params *sp = (MapgenV5Params *)params->sparams;
this->spflags = sp->spflags;
@ -73,8 +74,6 @@ MapgenV5::MapgenV5(int mapgenid, MapgenParams *params, EmergeManager *emerge)
noise_cave1 = new Noise(&sp->np_cave1, seed, csize.X, csize.Y + 2, csize.Z);
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_crumble = new Noise(&sp->np_crumble, seed, csize.X, csize.Y + 2, csize.Z);
noise_wetness = new Noise(&sp->np_wetness, seed, csize.X, csize.Y + 2, csize.Z);
// Biome noise
noise_heat = new Noise(&params->np_biome_heat, seed, csize.X, csize.Z);
@ -117,8 +116,6 @@ MapgenV5::~MapgenV5()
delete noise_cave1;
delete noise_cave2;
delete noise_ground;
delete noise_crumble;
delete noise_wetness;
delete noise_heat;
delete noise_humidity;
@ -130,7 +127,7 @@ MapgenV5::~MapgenV5()
MapgenV5Params::MapgenV5Params()
{
spflags = MGV5_BLOBS;
spflags = 0;
np_filler_depth = NoiseParams(0, 1, v3f(150, 150, 150), 261, 4, 0.7, 2.0);
np_factor = NoiseParams(0, 1, v3f(250, 250, 250), 920381, 3, 0.45, 2.0);
@ -138,18 +135,11 @@ MapgenV5Params::MapgenV5Params()
np_cave1 = NoiseParams(0, 12, v3f(50, 50, 50), 52534, 4, 0.5, 2.0);
np_cave2 = NoiseParams(0, 12, v3f(50, 50, 50), 10325, 4, 0.5, 2.0);
np_ground = NoiseParams(0, 40, v3f(80, 80, 80), 983240, 4, 0.55, 2.0, NOISE_FLAG_EASED);
np_crumble = NoiseParams(0, 1, v3f(20, 20, 20), 34413, 3, 1.3, 2.0, NOISE_FLAG_EASED);
np_wetness = NoiseParams(0, 1, v3f(40, 40, 40), 32474, 4, 1.1, 2.0);
}
// Scaling the output of the noise function affects the overdrive of the
// contour function, which affects the shape of the output considerably.
// Two original MT 0.3 parameters for non-eased noise:
//#define CAVE_NOISE_SCALE 12.0
//#define CAVE_NOISE_THRESHOLD (1.5/CAVE_NOISE_SCALE)
//#define CAVE_NOISE_THRESHOLD (1.5/CAVE_NOISE_SCALE) = 0.125
void MapgenV5Params::readParams(Settings *settings)
@ -162,8 +152,6 @@ void MapgenV5Params::readParams(Settings *settings)
settings->getNoiseParams("mgv5_np_cave1", np_cave1);
settings->getNoiseParams("mgv5_np_cave2", np_cave2);
settings->getNoiseParams("mgv5_np_ground", np_ground);
settings->getNoiseParams("mgv5_np_crumble", np_crumble);
settings->getNoiseParams("mgv5_np_wetness", np_wetness);
}
@ -177,8 +165,6 @@ void MapgenV5Params::writeParams(Settings *settings)
settings->setNoiseParams("mgv5_np_cave1", np_cave1);
settings->setNoiseParams("mgv5_np_cave2", np_cave2);
settings->setNoiseParams("mgv5_np_ground", np_ground);
settings->setNoiseParams("mgv5_np_crumble", np_crumble);
settings->setNoiseParams("mgv5_np_wetness", np_wetness);
}
@ -187,23 +173,20 @@ int MapgenV5::getGroundLevelAtPoint(v2s16 p)
//TimeTaker t("getGroundLevelAtPoint", NULL, PRECISION_MICRO);
float f = 0.55 + NoisePerlin2D(&noise_factor->np, p.X, p.Y, seed);
if(f < 0.01)
if (f < 0.01)
f = 0.01;
else if(f >= 1.0)
else if (f >= 1.0)
f *= 1.6;
float h = water_level + NoisePerlin2D(&noise_height->np, p.X, p.Y, seed);
s16 search_top = water_level + 15;
s16 search_base = water_level;
// Use these 2 lines instead for a slower search returning highest ground level:
//s16 search_top = h + f * noise_ground->np->octaves * noise_ground->np->scale;
//s16 search_base = h - f * noise_ground->np->octaves * noise_ground->np->scale;
s16 level = -31000;
for (s16 y = search_top; y >= search_base; y--) {
float n_ground = NoisePerlin3D(&noise_ground->np, p.X, y, p.Y, seed);
if(n_ground * f > y - h) {
if(y >= search_top - 7)
if (n_ground * f > y - h) {
if (y >= search_top - 7)
break;
else
level = y;
@ -247,18 +230,20 @@ void MapgenV5::makeChunk(BlockMakeData *data)
// Generate base terrain
s16 stone_surface_max_y = generateBaseTerrain();
// Create heightmap
updateHeightmap(node_min, node_max);
// Calculate biomes
// Create biomemap at heightmap surface
bmgr->calcBiomes(csize.X, csize.Z, noise_heat->result,
noise_humidity->result, heightmap, biomemap);
// Actually place the biome-specific nodes
generateBiomes();
generateBiomes(noise_heat->result, noise_humidity->result);
// Generate caves
if ((flags & MG_CAVES) && (stone_surface_max_y >= node_min.Y))
generateCaves();
generateCaves(stone_surface_max_y);
// Generate dungeons and desert temples
if ((flags & MG_DUNGEONS) && (stone_surface_max_y >= node_min.Y)) {
@ -269,11 +254,6 @@ void MapgenV5::makeChunk(BlockMakeData *data)
// Generate the registered decorations
m_emerge->decomgr->placeAllDecos(this, blockseed, node_min, node_max);
// Generate underground dirt, sand, gravel and lava blobs
if (spflags & MGV5_BLOBS) {
generateBlobs();
}
// Generate the registered ores
m_emerge->oremgr->placeAllOres(this, blockseed, node_min, node_max);
@ -311,11 +291,6 @@ void MapgenV5::calculateNoise()
noise_cave2->perlinMap3D(x, y, z);
}
if (spflags & MGV5_BLOBS) {
noise_crumble->perlinMap3D(x, y, z);
noise_wetness->perlinMap3D(x, y, z);
}
if (node_max.Y >= water_level) {
noise_filler_depth->perlinMap2D(x, z);
noise_heat->perlinMap2D(x, z);
@ -326,8 +301,6 @@ void MapgenV5::calculateNoise()
}
// Two original MT 0.3 functions:
//bool is_cave(u32 index) {
// double d1 = contour(noise_cave1->result[index]);
// double d2 = contour(noise_cave2->result[index]);
@ -351,22 +324,22 @@ int MapgenV5::generateBaseTerrain()
u32 index2d = 0;
int stone_surface_max_y = -MAP_GENERATION_LIMIT;
for(s16 z=node_min.Z; z<=node_max.Z; z++) {
for(s16 y=node_min.Y - 1; y<=node_max.Y + 1; y++) {
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 i = vm->m_area.index(node_min.X, y, z);
for(s16 x=node_min.X; x<=node_max.X; x++, i++, index++, index2d++) {
if(vm->m_data[i].getContent() != CONTENT_IGNORE)
for (s16 x=node_min.X; x<=node_max.X; x++, i++, index++, index2d++) {
if (vm->m_data[i].getContent() != CONTENT_IGNORE)
continue;
float f = 0.55 + noise_factor->result[index2d];
if(f < 0.01)
if (f < 0.01)
f = 0.01;
else if(f >= 1.0)
else if (f >= 1.0)
f *= 1.6;
float h = water_level + noise_height->result[index2d];
float h = noise_height->result[index2d];
if(noise_ground->result[index] * f < y - h) {
if(y <= water_level)
if (noise_ground->result[index] * f < y - h) {
if (y <= water_level)
vm->m_data[i] = MapNode(c_water_source);
else
vm->m_data[i] = MapNode(CONTENT_AIR);
@ -385,7 +358,7 @@ int MapgenV5::generateBaseTerrain()
}
void MapgenV5::generateBiomes()
void MapgenV5::generateBiomes(float *heat_map, float *humidity_map)
{
if (node_max.Y < water_level)
return;
@ -399,12 +372,11 @@ void MapgenV5::generateBiomes()
for (s16 z = node_min.Z; z <= node_max.Z; z++)
for (s16 x = node_min.X; x <= node_max.X; x++, index++) {
Biome *biome = (Biome *)bmgr->get(biomemap[index]);
s16 dfiller = biome->depth_filler + noise_filler_depth->result[index];
s16 y0_top = biome->depth_top;
s16 y0_filler = biome->depth_top + dfiller;
s16 shore_max = water_level + biome->height_shore;
s16 depth_water_top = biome->depth_water_top;
Biome *biome = NULL;
s16 dfiller = 0;
s16 y0_top = 0;
s16 y0_filler = 0;
s16 depth_water_top = 0;
s16 nplaced = 0;
u32 i = vm->m_area.index(x, node_max.Y, z);
@ -415,25 +387,23 @@ void MapgenV5::generateBiomes()
for (s16 y = node_max.Y; y >= node_min.Y; y--) {
content_t c = vm->m_data[i].getContent();
if (c != CONTENT_IGNORE && c != CONTENT_AIR && (y == node_max.Y || have_air)) {
biome = bmgr->getBiome(heat_map[index], humidity_map[index], y);
dfiller = biome->depth_filler + noise_filler_depth->result[index];
y0_top = biome->depth_top;
y0_filler = biome->depth_top + dfiller;
depth_water_top = biome->depth_water_top;
}
if (c == c_stone && have_air) {
content_t c_below = vm->m_data[i - em.X].getContent();
if (c_below != CONTENT_AIR) {
if (nplaced < y0_top) {
if(y < water_level)
vm->m_data[i] = MapNode(biome->c_underwater);
else if(y <= shore_max)
vm->m_data[i] = MapNode(biome->c_shore_top);
else
vm->m_data[i] = MapNode(biome->c_top);
vm->m_data[i] = MapNode(biome->c_top);
nplaced++;
} else if (nplaced < y0_filler && nplaced >= y0_top) {
if(y < water_level)
vm->m_data[i] = MapNode(biome->c_underwater);
else if(y <= shore_max)
vm->m_data[i] = MapNode(biome->c_shore_filler);
else
vm->m_data[i] = MapNode(biome->c_filler);
vm->m_data[i] = MapNode(biome->c_filler);
nplaced++;
} else if (c == c_stone) {
have_air = false;
@ -470,18 +440,18 @@ void MapgenV5::generateBiomes()
}
void MapgenV5::generateCaves()
void MapgenV5::generateCaves(int max_stone_y)
{
u32 index = 0;
u32 index2d = 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++) {
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 i = vm->m_area.index(node_min.X, y, z);
for(s16 x=node_min.X; x<=node_max.X; x++, i++, index++, index2d++) {
for (s16 x=node_min.X; x<=node_max.X; x++, i++, index++, index2d++) {
Biome *biome = (Biome *)bmgr->get(biomemap[index2d]);
content_t c = vm->m_data[i].getContent();
if(c == CONTENT_AIR
if (c == CONTENT_AIR
|| (y <= water_level
&& c != biome->c_stone
&& c != c_stone))
@ -489,43 +459,22 @@ void MapgenV5::generateCaves()
float d1 = contour(noise_cave1->result[index]);
float d2 = contour(noise_cave2->result[index]);
if(d1*d2 > 0.125)
if (d1*d2 > 0.125)
vm->m_data[i] = MapNode(CONTENT_AIR);
}
index2d = index2d - ystride;
}
index2d = index2d + ystride;
}
}
if (node_max.Y > -256)
return;
void MapgenV5::generateBlobs()
{
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 i = vm->m_area.index(node_min.X, y, z);
for(s16 x=node_min.X; x<=node_max.X; x++, i++, index++) {
content_t c = vm->m_data[i].getContent();
if(c != c_stone)
continue;
if(noise_crumble->result[index] > 1.3) {
if(noise_wetness->result[index] > 0.0)
vm->m_data[i] = MapNode(c_dirt);
else
vm->m_data[i] = MapNode(c_sand);
} else if(noise_crumble->result[index] > 0.7) {
if(noise_wetness->result[index] < -0.6)
vm->m_data[i] = MapNode(c_gravel);
} else if(noise_crumble->result[index] < -3.5 +
MYMIN(0.1 *
sqrt((float)MYMAX(0, -y)), 1.5)) {
vm->m_data[i] = MapNode(c_lava_source);
}
}
}
PseudoRandom ps(blockseed + 21343);
u32 bruises_count = (ps.range(1, 5) == 1) ? ps.range(1, 2) : 0;
for (u32 i = 0; i < bruises_count; i++) {
CaveV5 cave(this, &ps);
cave.makeCave(node_min, node_max, max_stone_y);
}
}

View File

@ -23,7 +23,9 @@ with this program; if not, write to the Free Software Foundation, Inc.,
#include "mapgen.h"
/////////////////// Mapgen V5 flags
#define MGV5_BLOBS 0x01
//#define MGV5_ 0x01
class BiomeManager;
extern FlagDesc flagdesc_mapgen_v5[];
@ -36,8 +38,6 @@ struct MapgenV5Params : public MapgenSpecificParams {
NoiseParams np_cave1;
NoiseParams np_cave2;
NoiseParams np_ground;
NoiseParams np_crumble;
NoiseParams np_wetness;
MapgenV5Params();
~MapgenV5Params() {}
@ -67,8 +67,6 @@ public:
Noise *noise_cave1;
Noise *noise_cave2;
Noise *noise_ground;
Noise *noise_crumble;
Noise *noise_wetness;
Noise *noise_heat;
Noise *noise_humidity;
@ -95,9 +93,8 @@ public:
int getGroundLevelAtPoint(v2s16 p);
void calculateNoise();
int generateBaseTerrain();
void generateBiomes();
void generateCaves();
void generateBlobs();
void generateBiomes(float *heat_map, float *humidity_map);
void generateCaves(int max_stone_y);
void dustTopNodes();
};

View File

@ -55,6 +55,10 @@ MapgenV6::MapgenV6(int mapgenid, MapgenParams *params, EmergeManager *emerge)
this->m_emerge = emerge;
this->ystride = csize.X; //////fix this
this->heightmap = new s16[csize.X * csize.Z];
initHeightMap(this->heightmap, csize.X * csize.Z);
MapgenV6Params *sp = (MapgenV6Params *)params->sparams;
this->spflags = sp->spflags;
this->freq_desert = sp->freq_desert;
@ -115,6 +119,8 @@ MapgenV6::~MapgenV6()
delete noise_mud;
delete noise_beach;
delete noise_biome;
delete[] heightmap;
}
@ -498,6 +504,9 @@ void MapgenV6::makeChunk(BlockMakeData *data)
}
// Create heightmap after mudflow
updateHeightmap(node_min, node_max);
// Add dungeons
if ((flags & MG_DUNGEONS) && (stone_surface_max_y >= node_min.Y)) {
DungeonParams dp;

View File

@ -64,6 +64,8 @@ MapgenV7::MapgenV7(int mapgenid, MapgenParams *params, EmergeManager *emerge)
this->heightmap = new s16[csize.X * csize.Z];
this->ridge_heightmap = new s16[csize.X * csize.Z];
initHeightMap(this->heightmap, csize.X * csize.Z);
MapgenV7Params *sp = (MapgenV7Params *)params->sparams;
this->spflags = sp->spflags;
@ -239,14 +241,15 @@ void MapgenV7::makeChunk(BlockMakeData *data)
// Generate base terrain, mountains, and ridges with initial heightmaps
s16 stone_surface_max_y = generateTerrain();
// Create heightmap
updateHeightmap(node_min, node_max);
// Calculate biomes
// Create biomemap at heightmap surface
bmgr->calcBiomes(csize.X, csize.Z, noise_heat->result,
noise_humidity->result, heightmap, biomemap);
// Actually place the biome-specific nodes and what not
generateBiomes();
// Actually place the biome-specific nodes
generateBiomes(noise_heat->result, noise_humidity->result);
if (flags & MG_CAVES)
generateCaves(stone_surface_max_y);
@ -534,7 +537,7 @@ void MapgenV7::generateRidgeTerrain()
}
void MapgenV7::generateBiomes()
void MapgenV7::generateBiomes(float *heat_map, float *humidity_map)
{
if (node_max.Y < water_level)
return;
@ -548,12 +551,11 @@ void MapgenV7::generateBiomes()
for (s16 z = node_min.Z; z <= node_max.Z; z++)
for (s16 x = node_min.X; x <= node_max.X; x++, index++) {
Biome *biome = (Biome *)bmgr->get(biomemap[index]);
s16 dfiller = biome->depth_filler + noise_filler_depth->result[index];
s16 y0_top = biome->depth_top;
s16 y0_filler = biome->depth_top + dfiller;
s16 shore_max = water_level + biome->height_shore;
s16 depth_water_top = biome->depth_water_top;
Biome *biome = NULL;
s16 dfiller = 0;
s16 y0_top = 0;
s16 y0_filler = 0;
s16 depth_water_top = 0;
s16 nplaced = 0;
u32 i = vm->m_area.index(x, node_max.Y, z);
@ -574,25 +576,23 @@ void MapgenV7::generateBiomes()
have_air = !getMountainTerrainFromMap(j, index, y);
}
if (c != CONTENT_IGNORE && c != CONTENT_AIR && (y == node_max.Y || have_air)) {
biome = bmgr->getBiome(heat_map[index], humidity_map[index], y);
dfiller = biome->depth_filler + noise_filler_depth->result[index];
y0_top = biome->depth_top;
y0_filler = biome->depth_top + dfiller;
depth_water_top = biome->depth_water_top;
}
if (c == c_stone && have_air) {
content_t c_below = vm->m_data[i - em.X].getContent();
if (c_below != CONTENT_AIR) {
if (nplaced < y0_top) {
if(y < water_level)
vm->m_data[i] = MapNode(biome->c_underwater);
else if(y <= shore_max)
vm->m_data[i] = MapNode(biome->c_shore_top);
else
vm->m_data[i] = MapNode(biome->c_top);
vm->m_data[i] = MapNode(biome->c_top);
nplaced++;
} else if (nplaced < y0_filler && nplaced >= y0_top) {
if(y < water_level)
vm->m_data[i] = MapNode(biome->c_underwater);
else if(y <= shore_max)
vm->m_data[i] = MapNode(biome->c_shore_filler);
else
vm->m_data[i] = MapNode(biome->c_filler);
vm->m_data[i] = MapNode(biome->c_filler);
nplaced++;
} else if (c == c_stone) {
have_air = false;
@ -792,7 +792,7 @@ void MapgenV7::generateCaves(int max_stone_y)
PseudoRandom ps(blockseed + 21343);
u32 bruises_count = (ps.range(1, 5) == 1) ? ps.range(1, 2) : 0;
for (u32 i = 0; i < bruises_count; i++) {
CaveV7 cave(this, &ps, true);
CaveV7 cave(this, &ps);
cave.makeCave(node_min, node_max, max_stone_y);
}
}

View File

@ -114,7 +114,7 @@ public:
int generateMountainTerrain(int ymax);
void generateRidgeTerrain();
void generateBiomes();
void generateBiomes(float *heat_map, float *humidity_map);
void dustTopNodes();
//void addTopNodes();

View File

@ -74,6 +74,22 @@ void MapNode::setLight(enum LightBank bank, u8 a_light, INodeDefManager *nodemgr
assert(0);
}
bool MapNode::isLightDayNightEq(INodeDefManager *nodemgr) const
{
const ContentFeatures &f = nodemgr->get(*this);
bool isEqual;
if (f.param_type == CPT_LIGHT) {
u8 day = MYMAX(f.light_source, param1 & 0x0f);
u8 night = MYMAX(f.light_source, (param1 >> 4) & 0x0f);
isEqual = day == night;
} else {
isEqual = true;
}
return isEqual;
}
u8 MapNode::getLight(enum LightBank bank, INodeDefManager *nodemgr) const
{
// Select the brightest of [light source, propagated light]
@ -88,7 +104,7 @@ u8 MapNode::getLight(enum LightBank bank, INodeDefManager *nodemgr) const
return MYMAX(f.light_source, light);
}
u8 MapNode::getLightNoChecks(enum LightBank bank, const ContentFeatures *f)
u8 MapNode::getLightNoChecks(enum LightBank bank, const ContentFeatures *f) const
{
return MYMAX(f->light_source,
bank == LIGHTBANK_DAY ? param1 & 0x0f : (param1 >> 4) & 0x0f);

View File

@ -192,6 +192,14 @@ struct MapNode
}
void setLight(enum LightBank bank, u8 a_light, INodeDefManager *nodemgr);
/**
* Check if the light value for night differs from the light value for day.
*
* @return If the light values are equal, returns true; otherwise false
*/
bool isLightDayNightEq(INodeDefManager *nodemgr) const;
u8 getLight(enum LightBank bank, INodeDefManager *nodemgr) const;
/**
@ -209,7 +217,7 @@ struct MapNode
* @pre f != NULL
* @pre f->param_type == CPT_LIGHT
*/
u8 getLightNoChecks(LightBank bank, const ContentFeatures *f);
u8 getLightNoChecks(LightBank bank, const ContentFeatures *f) const;
bool getLightBanks(u8 &lightday, u8 &lightnight, INodeDefManager *nodemgr) const;

View File

@ -133,7 +133,7 @@ void MapSector::deleteBlock(MapBlock *block)
delete block;
}
void MapSector::getBlocks(std::list<MapBlock*> &dest)
void MapSector::getBlocks(MapBlockVect &dest)
{
for(std::map<s16, MapBlock*>::iterator bi = m_blocks.begin();
bi != m_blocks.end(); ++bi)

View File

@ -22,11 +22,11 @@ with this program; if not, write to the Free Software Foundation, Inc.,
#include "irrlichttypes.h"
#include "irr_v2d.h"
#include "mapblock.h"
#include <ostream>
#include <map>
#include <list>
#include <vector>
class MapBlock;
class Map;
class IGameDef;
@ -61,7 +61,7 @@ public:
void deleteBlock(MapBlock *block);
void getBlocks(std::list<MapBlock*> &dest);
void getBlocks(MapBlockVect &dest);
// Always false at the moment, because sector contains no metadata.
bool differs_from_disk;

View File

@ -43,7 +43,6 @@ BiomeManager::BiomeManager(IGameDef *gamedef) :
b->flags = 0;
b->depth_top = 0;
b->depth_filler = 0;
b->height_shore = 0;
b->depth_water_top = 0;
b->y_min = -MAP_GENERATION_LIMIT;
b->y_max = MAP_GENERATION_LIMIT;
@ -53,9 +52,6 @@ BiomeManager::BiomeManager(IGameDef *gamedef) :
NodeResolveInfo *nri = new NodeResolveInfo(b);
nri->nodenames.push_back("air");
nri->nodenames.push_back("air");
nri->nodenames.push_back("air");
nri->nodenames.push_back("air");
nri->nodenames.push_back("air");
nri->nodenames.push_back("mapgen_stone");
nri->nodenames.push_back("mapgen_water_source");
nri->nodenames.push_back("mapgen_water_source");
@ -126,9 +122,6 @@ void Biome::resolveNodeNames(NodeResolveInfo *nri)
{
m_ndef->getIdFromResolveInfo(nri, "mapgen_dirt_with_grass", CONTENT_AIR, c_top);
m_ndef->getIdFromResolveInfo(nri, "mapgen_dirt", CONTENT_AIR, c_filler);
m_ndef->getIdFromResolveInfo(nri, "mapgen_sand", CONTENT_AIR, c_shore_top);
m_ndef->getIdFromResolveInfo(nri, "mapgen_sand", CONTENT_AIR, c_shore_filler);
m_ndef->getIdFromResolveInfo(nri, "mapgen_sand", CONTENT_AIR, c_underwater);
m_ndef->getIdFromResolveInfo(nri, "mapgen_stone", CONTENT_AIR, c_stone);
m_ndef->getIdFromResolveInfo(nri, "mapgen_water_source", CONTENT_AIR, c_water_top);
m_ndef->getIdFromResolveInfo(nri, "mapgen_water_source", CONTENT_AIR, c_water);

Some files were not shown because too many files have changed in this diff Show More