mirror of https://github.com/minetest/minetest.git
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.cpp36e8ba9ce2
~~ modified main.cpp manually; add ALLOW_ZWRITE_ON_TRANSPARENT set3b6480c5b0
~~ modified server.cpp manually; change wrapDegrees -> modulo360f5a5854ea9d
c09d026f05
3c91ad8fc2
This commit is contained in:
parent
32352e90da
commit
8e08e92eb4
|
@ -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
|
# Also remember to set PROTOCOL_VERSION in clientserver.h when releasing
|
||||||
set(VERSION_MAJOR 0)
|
set(VERSION_MAJOR 0)
|
||||||
set(VERSION_MINOR 4)
|
set(VERSION_MINOR 4)
|
||||||
set(VERSION_PATCH 11)
|
set(VERSION_PATCH 12)
|
||||||
set(VERSION_PATCH_ORIG ${VERSION_PATCH})
|
set(VERSION_PATCH_ORIG ${VERSION_PATCH})
|
||||||
|
|
||||||
if(VERSION_EXTRA)
|
if(VERSION_EXTRA)
|
||||||
|
|
31
README.txt
31
README.txt
|
@ -103,18 +103,30 @@ Compiling on GNU/Linux:
|
||||||
-----------------------
|
-----------------------
|
||||||
|
|
||||||
Install dependencies. Here's an example for Debian/Ubuntu:
|
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):
|
You can install git for easily keeping your copy up to date.
|
||||||
$ wget https://github.com/minetest/minetest/tarball/master -O master.tar.gz
|
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
|
$ 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/
|
$ cd games/
|
||||||
$ wget https://github.com/minetest/minetest_game/tarball/master -O minetest_game.tar.gz
|
$ wget https://github.com/minetest/minetest_game/archive/master.tar.gz
|
||||||
$ tar xf minetest_game.tar.gz
|
$ tar xf master.tar.gz
|
||||||
$ mv minetest-minetest_game-* minetest_game
|
$ mv minetest_game-master minetest_game
|
||||||
$ cd ..
|
$ cd ..
|
||||||
|
|
||||||
Build a version that runs directly from the source directory:
|
Build a version that runs directly from the source directory:
|
||||||
|
@ -122,8 +134,7 @@ $ cmake . -DRUN_IN_PLACE=1
|
||||||
$ make -j2
|
$ make -j2
|
||||||
|
|
||||||
Run it:
|
Run it:
|
||||||
$ cd bin
|
$ ./bin/minetest
|
||||||
$ ./minetest
|
|
||||||
|
|
||||||
- Use cmake . -LH to see all CMake options and their current state
|
- 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
|
- If you want to install it system-wide (or are making a distribution package), you will want to use -DRUN_IN_PLACE=0
|
||||||
|
|
|
@ -26,7 +26,7 @@ GAMES_TO_COPY = minetest_game
|
||||||
# Android Version code
|
# Android Version code
|
||||||
# Increase for each build!
|
# Increase for each build!
|
||||||
################################################################################
|
################################################################################
|
||||||
ANDROID_VERSION_CODE = 5
|
ANDROID_VERSION_CODE = 6
|
||||||
|
|
||||||
################################################################################
|
################################################################################
|
||||||
# toolchain config for arm old processors
|
# toolchain config for arm old processors
|
||||||
|
|
|
@ -102,7 +102,6 @@ LOCAL_C_INCLUDES := \
|
||||||
|
|
||||||
LOCAL_SRC_FILES := \
|
LOCAL_SRC_FILES := \
|
||||||
jni/src/ban.cpp \
|
jni/src/ban.cpp \
|
||||||
jni/src/base64.cpp \
|
|
||||||
jni/src/camera.cpp \
|
jni/src/camera.cpp \
|
||||||
jni/src/cavegen.cpp \
|
jni/src/cavegen.cpp \
|
||||||
jni/src/chat.cpp \
|
jni/src/chat.cpp \
|
||||||
|
@ -190,7 +189,6 @@ LOCAL_SRC_FILES := \
|
||||||
jni/src/server.cpp \
|
jni/src/server.cpp \
|
||||||
jni/src/serverlist.cpp \
|
jni/src/serverlist.cpp \
|
||||||
jni/src/serverobject.cpp \
|
jni/src/serverobject.cpp \
|
||||||
jni/src/sha1.cpp \
|
|
||||||
jni/src/shader.cpp \
|
jni/src/shader.cpp \
|
||||||
jni/src/sky.cpp \
|
jni/src/sky.cpp \
|
||||||
jni/src/socket.cpp \
|
jni/src/socket.cpp \
|
||||||
|
@ -205,10 +203,12 @@ LOCAL_SRC_FILES := \
|
||||||
jni/src/version.cpp \
|
jni/src/version.cpp \
|
||||||
jni/src/voxel.cpp \
|
jni/src/voxel.cpp \
|
||||||
jni/src/voxelalgorithms.cpp \
|
jni/src/voxelalgorithms.cpp \
|
||||||
|
jni/src/util/base64.cpp \
|
||||||
jni/src/util/directiontables.cpp \
|
jni/src/util/directiontables.cpp \
|
||||||
jni/src/util/numeric.cpp \
|
jni/src/util/numeric.cpp \
|
||||||
jni/src/util/pointedthing.cpp \
|
jni/src/util/pointedthing.cpp \
|
||||||
jni/src/util/serialize.cpp \
|
jni/src/util/serialize.cpp \
|
||||||
|
jni/src/util/sha1.cpp \
|
||||||
jni/src/util/string.cpp \
|
jni/src/util/string.cpp \
|
||||||
jni/src/util/timetaker.cpp \
|
jni/src/util/timetaker.cpp \
|
||||||
jni/src/touchscreengui.cpp \
|
jni/src/touchscreengui.cpp \
|
||||||
|
|
|
@ -545,12 +545,11 @@ function table.copy(t, seen)
|
||||||
seen = seen or {}
|
seen = seen or {}
|
||||||
seen[t] = n
|
seen[t] = n
|
||||||
for k, v in pairs(t) do
|
for k, v in pairs(t) do
|
||||||
n[type(k) ~= "table" and k or seen[k] or table.copy(k, seen)] =
|
n[(type(k) == "table" and (seen[k] or table.copy(k, seen))) or k] =
|
||||||
type(v) ~= "table" and v or seen[v] or table.copy(v, seen)
|
(type(v) == "table" and (seen[v] or table.copy(v, seen))) or v
|
||||||
end
|
end
|
||||||
return n
|
return n
|
||||||
end
|
end
|
||||||
|
|
||||||
--------------------------------------------------------------------------------
|
--------------------------------------------------------------------------------
|
||||||
-- mainmenu only functions
|
-- mainmenu only functions
|
||||||
--------------------------------------------------------------------------------
|
--------------------------------------------------------------------------------
|
||||||
|
@ -565,7 +564,7 @@ if INIT == "mainmenu" then
|
||||||
return nil
|
return nil
|
||||||
end
|
end
|
||||||
|
|
||||||
function fgettext(text, ...)
|
function fgettext_ne(text, ...)
|
||||||
text = core.gettext(text)
|
text = core.gettext(text)
|
||||||
local arg = {n=select('#', ...), ...}
|
local arg = {n=select('#', ...), ...}
|
||||||
if arg.n >= 1 then
|
if arg.n >= 1 then
|
||||||
|
@ -587,7 +586,11 @@ if INIT == "mainmenu" then
|
||||||
end
|
end
|
||||||
text = result
|
text = result
|
||||||
end
|
end
|
||||||
return core.formspec_escape(text)
|
return text
|
||||||
|
end
|
||||||
|
|
||||||
|
function fgettext(text, ...)
|
||||||
|
return core.formspec_escape(fgettext_ne(text, ...))
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
|
|
@ -115,11 +115,20 @@ function core.serialize(x)
|
||||||
function dump_val(x)
|
function dump_val(x)
|
||||||
local tp = type(x)
|
local tp = type(x)
|
||||||
if x == nil then return "nil"
|
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 == "string" then return string.format("%q", x)
|
||||||
elseif tp == "boolean" then return x and "true" or "false"
|
elseif tp == "boolean" then return x and "true" or "false"
|
||||||
elseif tp == "function" then
|
elseif tp == "function" then
|
||||||
return string.format("loadstring(%q)", string.dump(x))
|
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
|
elseif tp == "table" then
|
||||||
local vals = {}
|
local vals = {}
|
||||||
local idx_dumped = {}
|
local idx_dumped = {}
|
||||||
|
|
|
@ -229,21 +229,28 @@ core.register_chatcommand("setpassword", {
|
||||||
if not toname then
|
if not toname then
|
||||||
return false, "Name field required"
|
return false, "Name field required"
|
||||||
end
|
end
|
||||||
local actstr = "?"
|
local act_str_past = "?"
|
||||||
|
local act_str_pres = "?"
|
||||||
if not raw_password then
|
if not raw_password then
|
||||||
core.set_player_password(toname, "")
|
core.set_player_password(toname, "")
|
||||||
actstr = "cleared"
|
act_str_past = "cleared"
|
||||||
|
act_str_pres = "clears"
|
||||||
else
|
else
|
||||||
core.set_player_password(toname,
|
core.set_player_password(toname,
|
||||||
core.get_password_hash(toname,
|
core.get_password_hash(toname,
|
||||||
raw_password))
|
raw_password))
|
||||||
actstr = "set"
|
act_str_past = "set"
|
||||||
|
act_str_pres = "sets"
|
||||||
end
|
end
|
||||||
if toname ~= name then
|
if toname ~= name then
|
||||||
core.chat_send_player(toname, "Your password was "
|
core.chat_send_player(toname, "Your password was "
|
||||||
.. actstr .. " by " .. name)
|
.. act_str_past .. " by " .. name)
|
||||||
end
|
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,
|
end,
|
||||||
})
|
})
|
||||||
|
|
||||||
|
@ -257,6 +264,9 @@ core.register_chatcommand("clearpassword", {
|
||||||
return false, "Name field required"
|
return false, "Name field required"
|
||||||
end
|
end
|
||||||
core.set_player_password(toname, '')
|
core.set_player_password(toname, '')
|
||||||
|
|
||||||
|
core.log("action", name .. " clears password of " .. toname .. ".")
|
||||||
|
|
||||||
return true, "Password of player \"" .. toname .. "\" cleared"
|
return true, "Password of player \"" .. toname .. "\" cleared"
|
||||||
end,
|
end,
|
||||||
})
|
})
|
||||||
|
@ -404,13 +414,14 @@ core.register_chatcommand("set", {
|
||||||
})
|
})
|
||||||
|
|
||||||
core.register_chatcommand("deleteblocks", {
|
core.register_chatcommand("deleteblocks", {
|
||||||
params = "[here] [<pos1> <pos2>]",
|
params = "(here [radius]) | (<pos1> <pos2>)",
|
||||||
description = "delete map blocks contained in area pos1 to pos2",
|
description = "delete map blocks contained in area pos1 to pos2",
|
||||||
privs = {server=true},
|
privs = {server=true},
|
||||||
func = function(name, param)
|
func = function(name, param)
|
||||||
local p1 = {}
|
local p1 = {}
|
||||||
local p2 = {}
|
local p2 = {}
|
||||||
if param == "here" then
|
local args = param:split(" ")
|
||||||
|
if args[1] == "here" then
|
||||||
local player = core.get_player_by_name(name)
|
local player = core.get_player_by_name(name)
|
||||||
if player == nil then
|
if player == nil then
|
||||||
core.log("error", "player is nil")
|
core.log("error", "player is nil")
|
||||||
|
@ -418,6 +429,12 @@ core.register_chatcommand("deleteblocks", {
|
||||||
end
|
end
|
||||||
p1 = player:getpos()
|
p1 = player:getpos()
|
||||||
p2 = p1
|
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
|
else
|
||||||
local pos1, pos2 = unpack(param:split(") ("))
|
local pos1, pos2 = unpack(param:split(") ("))
|
||||||
if pos1 == nil or pos2 == nil then
|
if pos1 == nil or pos2 == nil then
|
||||||
|
@ -570,6 +587,9 @@ core.register_chatcommand("rollback_check", {
|
||||||
.. " seconds=86400=24h, limit=5)",
|
.. " seconds=86400=24h, limit=5)",
|
||||||
privs = {rollback=true},
|
privs = {rollback=true},
|
||||||
func = function(name, param)
|
func = function(name, param)
|
||||||
|
if not core.setting_getbool("enable_rollback_recording") then
|
||||||
|
return false, "Rollback functions are disabled."
|
||||||
|
end
|
||||||
local range, seconds, limit =
|
local range, seconds, limit =
|
||||||
param:match("(%d+) *(%d*) *(%d*)")
|
param:match("(%d+) *(%d*) *(%d*)")
|
||||||
range = tonumber(range) or 0
|
range = tonumber(range) or 0
|
||||||
|
@ -583,6 +603,10 @@ core.register_chatcommand("rollback_check", {
|
||||||
local name = puncher:get_player_name()
|
local name = puncher:get_player_name()
|
||||||
core.chat_send_player(name, "Checking " .. core.pos_to_string(pos) .. "...")
|
core.chat_send_player(name, "Checking " .. core.pos_to_string(pos) .. "...")
|
||||||
local actions = core.rollback_get_node_actions(pos, range, seconds, limit)
|
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
|
local num_actions = #actions
|
||||||
if num_actions == 0 then
|
if num_actions == 0 then
|
||||||
core.chat_send_player(name, "Nobody has touched"
|
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",
|
description = "revert actions of a player; default for <seconds> is 60",
|
||||||
privs = {rollback=true},
|
privs = {rollback=true},
|
||||||
func = function(name, param)
|
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*)")
|
local target_name, seconds = string.match(param, ":([^ ]+) *(%d*)")
|
||||||
if not target_name then
|
if not target_name then
|
||||||
local player_name = nil
|
local player_name = nil
|
||||||
|
|
|
@ -106,7 +106,7 @@ function core.facedir_to_dir(facedir)
|
||||||
{x=0, y=1, z=0}})
|
{x=0, y=1, z=0}})
|
||||||
|
|
||||||
--indexed into by a table of correlating facedirs
|
--indexed into by a table of correlating facedirs
|
||||||
[({[0]=1, 2, 3, 4,
|
[({[0]=1, 2, 3, 4,
|
||||||
5, 2, 6, 4,
|
5, 2, 6, 4,
|
||||||
6, 2, 5, 4,
|
6, 2, 5, 4,
|
||||||
1, 5, 3, 6,
|
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 "
|
core.log("action", placer:get_player_name() .. " places node "
|
||||||
.. def.name .. " at " .. core.pos_to_string(place_to))
|
.. def.name .. " at " .. core.pos_to_string(place_to))
|
||||||
|
|
||||||
local oldnode = core.get_node(place_to)
|
local oldnode = core.get_node(place_to)
|
||||||
local newnode = {name = def.name, param1 = 0, param2 = param2}
|
local newnode = {name = def.name, param1 = 0, param2 = param2}
|
||||||
|
|
||||||
|
@ -357,19 +357,37 @@ function core.item_drop(itemstack, dropper, pos)
|
||||||
return itemstack
|
return itemstack
|
||||||
end
|
end
|
||||||
|
|
||||||
function core.item_eat(hp_change, replace_with_item)
|
function core.do_item_eat(hp_change, replace_with_item, itemstack, user, pointed_thing)
|
||||||
return function(itemstack, user, pointed_thing) -- closure
|
for _, callback in pairs(core.registered_on_item_eats) do
|
||||||
for _, callback in pairs(core.registered_on_item_eats) do
|
local result = callback(hp_change, replace_with_item, itemstack, user, pointed_thing)
|
||||||
local result = callback(hp_change, replace_with_item, itemstack, user, pointed_thing)
|
if result then
|
||||||
if result then
|
return result
|
||||||
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
|
||||||
end
|
end
|
||||||
if itemstack:take_item() ~= nil then
|
end
|
||||||
user:set_hp(user:get_hp() + hp_change)
|
return itemstack
|
||||||
itemstack:add_item(replace_with_item) -- note: replace_with_item is optional
|
end
|
||||||
end
|
|
||||||
return itemstack
|
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
|
||||||
end
|
end
|
||||||
|
|
||||||
|
@ -425,7 +443,7 @@ function core.node_dig(pos, node, digger)
|
||||||
|
|
||||||
local wielded = digger:get_wielded_item()
|
local wielded = digger:get_wielded_item()
|
||||||
local drops = core.get_node_drops(node.name, wielded:get_name())
|
local drops = core.get_node_drops(node.name, wielded:get_name())
|
||||||
|
|
||||||
local wdef = wielded:get_definition()
|
local wdef = wielded:get_definition()
|
||||||
local tp = wielded:get_tool_capabilities()
|
local tp = wielded:get_tool_capabilities()
|
||||||
local dp = core.get_dig_params(def.groups, tp)
|
local dp = core.get_dig_params(def.groups, tp)
|
||||||
|
@ -438,7 +456,7 @@ function core.node_dig(pos, node, digger)
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
digger:set_wielded_item(wielded)
|
digger:set_wielded_item(wielded)
|
||||||
|
|
||||||
-- Handle drops
|
-- Handle drops
|
||||||
core.handle_node_drops(pos, drops, digger)
|
core.handle_node_drops(pos, drops, digger)
|
||||||
|
|
||||||
|
@ -449,7 +467,7 @@ function core.node_dig(pos, node, digger)
|
||||||
|
|
||||||
-- Remove node and update
|
-- Remove node and update
|
||||||
core.remove_node(pos)
|
core.remove_node(pos)
|
||||||
|
|
||||||
-- Run callback
|
-- Run callback
|
||||||
if def.after_dig_node then
|
if def.after_dig_node then
|
||||||
-- Copy pos and node because callback can modify them
|
-- 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_dig = redef_wrapper(core, 'node_dig'), -- core.node_dig
|
||||||
|
|
||||||
on_receive_fields = nil,
|
on_receive_fields = nil,
|
||||||
|
|
||||||
on_metadata_inventory_move = core.node_metadata_inventory_move_allow_all,
|
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_offer = core.node_metadata_inventory_offer_allow_all,
|
||||||
on_metadata_inventory_take = core.node_metadata_inventory_take_allow_all,
|
on_metadata_inventory_take = core.node_metadata_inventory_take_allow_all,
|
||||||
|
|
|
@ -16,9 +16,15 @@
|
||||||
--51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
|
--51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||||
--------------------------------------------------------------------------------
|
--------------------------------------------------------------------------------
|
||||||
-- Global menu data
|
-- Global menu data
|
||||||
---------------------------------------------------------------------------------
|
--------------------------------------------------------------------------------
|
||||||
menudata = {}
|
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
|
-- Menu helper functions
|
||||||
--------------------------------------------------------------------------------
|
--------------------------------------------------------------------------------
|
||||||
|
@ -42,6 +48,25 @@ function image_column(tooltip, flagname)
|
||||||
"1=" .. core.formspec_escape(defaulttexturedir .. "server_flags_" .. flagname .. ".png")
|
"1=" .. core.formspec_escape(defaulttexturedir .. "server_flags_" .. flagname .. ".png")
|
||||||
end
|
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)
|
function render_favorite(spec,render_details)
|
||||||
local text = ""
|
local text = ""
|
||||||
|
@ -68,6 +93,7 @@ function render_favorite(spec,render_details)
|
||||||
end
|
end
|
||||||
|
|
||||||
local details = ""
|
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
|
if spec.clients ~= nil and spec.clients_max ~= nil then
|
||||||
local clients_color = ''
|
local clients_color = ''
|
||||||
|
@ -87,11 +113,17 @@ function render_favorite(spec,render_details)
|
||||||
clients_color = '#ffba97' -- 90-100%: orange
|
clients_color = '#ffba97' -- 90-100%: orange
|
||||||
end
|
end
|
||||||
|
|
||||||
|
if grey_out then
|
||||||
|
clients_color = '#aaaaaa'
|
||||||
|
end
|
||||||
|
|
||||||
details = details ..
|
details = details ..
|
||||||
clients_color .. ',' ..
|
clients_color .. ',' ..
|
||||||
render_client_count(spec.clients) .. ',' ..
|
render_client_count(spec.clients) .. ',' ..
|
||||||
'/,' ..
|
'/,' ..
|
||||||
render_client_count(spec.clients_max) .. ','
|
render_client_count(spec.clients_max) .. ','
|
||||||
|
elseif grey_out then
|
||||||
|
details = details .. '#aaaaaa,?,/,?,'
|
||||||
else
|
else
|
||||||
details = details .. ',?,/,?,'
|
details = details .. ',?,/,?,'
|
||||||
end
|
end
|
||||||
|
@ -114,7 +146,7 @@ function render_favorite(spec,render_details)
|
||||||
details = details .. "0,"
|
details = details .. "0,"
|
||||||
end
|
end
|
||||||
|
|
||||||
return details .. text
|
return details .. (grey_out and '#aaaaaa,' or ',') .. text
|
||||||
end
|
end
|
||||||
|
|
||||||
--------------------------------------------------------------------------------
|
--------------------------------------------------------------------------------
|
||||||
|
@ -195,7 +227,7 @@ function asyncOnlineFavourites()
|
||||||
nil,
|
nil,
|
||||||
function(result)
|
function(result)
|
||||||
if core.setting_getbool("public_serverlist") then
|
if core.setting_getbool("public_serverlist") then
|
||||||
menudata.favorites = result
|
menudata.favorites = order_favorite_list(result)
|
||||||
core.event_handler("Refresh")
|
core.event_handler("Refresh")
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
@ -225,3 +257,21 @@ function text2textlist(xpos,ypos,width,height,tl_name,textlen,text,transparency)
|
||||||
|
|
||||||
return retval
|
return retval
|
||||||
end
|
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
|
||||||
|
|
|
@ -16,6 +16,9 @@
|
||||||
--51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
|
--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)
|
local function get_formspec(data)
|
||||||
|
|
||||||
|
@ -195,10 +198,12 @@ local function handle_buttons(this, fields)
|
||||||
for i,mod in ipairs(rawlist) do
|
for i,mod in ipairs(rawlist) do
|
||||||
if not mod.is_modpack and
|
if not mod.is_modpack and
|
||||||
mod.typ ~= "game_mod" then
|
mod.typ ~= "game_mod" then
|
||||||
if mod.enabled then
|
if modname_valid(mod.name) then
|
||||||
worldfile:set("load_mod_"..mod.name, "true")
|
worldfile:set("load_mod_"..mod.name, tostring(mod.enabled))
|
||||||
else
|
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
|
end
|
||||||
mods["load_mod_"..mod.name] = nil
|
mods["load_mod_"..mod.name] = nil
|
||||||
end
|
end
|
||||||
|
|
|
@ -90,6 +90,8 @@ local function create_world_buttonhandler(this, fields)
|
||||||
|
|
||||||
local message = nil
|
local message = nil
|
||||||
|
|
||||||
|
core.setting_set("fixed_map_seed", fields["te_seed"])
|
||||||
|
|
||||||
if not menudata.worldlist:uid_exists_raw(worldname) then
|
if not menudata.worldlist:uid_exists_raw(worldname) then
|
||||||
core.setting_set("mg_name",fields["dd_mapgen"])
|
core.setting_set("mg_name",fields["dd_mapgen"])
|
||||||
message = core.create_world(worldname,gameindex)
|
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)
|
message = fgettext("A world named \"$1\" already exists", worldname)
|
||||||
end
|
end
|
||||||
|
|
||||||
core.setting_set("fixed_map_seed", fields["te_seed"])
|
|
||||||
|
|
||||||
if message ~= nil then
|
if message ~= nil then
|
||||||
gamedata.errormessage = message
|
gamedata.errormessage = message
|
||||||
else
|
else
|
||||||
|
|
|
@ -139,7 +139,11 @@ local function init_globals()
|
||||||
tv_main:add(tab_credits)
|
tv_main:add(tab_credits)
|
||||||
|
|
||||||
tv_main:set_global_event_handler(main_event_handler)
|
tv_main:set_global_event_handler(main_event_handler)
|
||||||
tv_main:set_fixed_size(false)
|
if PLATFORM ~= "Android" then
|
||||||
|
tv_main:set_fixed_size(true)
|
||||||
|
else
|
||||||
|
tv_main:set_fixed_size(false)
|
||||||
|
end
|
||||||
|
|
||||||
if not (PLATFORM == "Android") then
|
if not (PLATFORM == "Android") then
|
||||||
tv_main:set_tab(core.setting_get("maintab_LAST"))
|
tv_main:set_tab(core.setting_get("maintab_LAST"))
|
||||||
|
|
|
@ -122,35 +122,36 @@ end
|
||||||
function modstore.showdownloading(title)
|
function modstore.showdownloading(title)
|
||||||
local new_dlg = dialog_create("store_downloading",
|
local new_dlg = dialog_create("store_downloading",
|
||||||
function(data)
|
function(data)
|
||||||
return "size[6,2]label[0.25,0.75;" .. fgettext("Downloading") ..
|
return "size[6,2]label[0.25,0.75;" ..
|
||||||
" " .. data.title .. " " ..
|
fgettext("Downloading $1, please wait...", data.title) .. "]"
|
||||||
fgettext("please wait...") .. "]"
|
|
||||||
end,
|
end,
|
||||||
function(this,fields)
|
function(this,fields)
|
||||||
if fields["btn_hidden_close_download"] ~= nil then
|
if fields["btn_hidden_close_download"] ~= nil then
|
||||||
if fields["btn_hidden_close_download"].successfull then
|
if fields["btn_hidden_close_download"].successfull then
|
||||||
modstore.lastmodentry = fields["btn_hidden_close_download"]
|
modstore.lastmodentry = fields["btn_hidden_close_download"]
|
||||||
modstore.successfulldialog()
|
modstore.successfulldialog(this)
|
||||||
else
|
else
|
||||||
|
this.parent:show()
|
||||||
|
this:delete()
|
||||||
modstore.lastmodtitle = ""
|
modstore.lastmodtitle = ""
|
||||||
end
|
end
|
||||||
|
|
||||||
this:delete()
|
|
||||||
return true
|
return true
|
||||||
end
|
end
|
||||||
|
|
||||||
return false
|
return false
|
||||||
end,
|
end,
|
||||||
nil,
|
nil)
|
||||||
modstore.tv_store)
|
|
||||||
|
|
||||||
|
new_dlg:set_parent(modstore.tv_store)
|
||||||
|
modstore.tv_store:hide()
|
||||||
new_dlg.data.title = title
|
new_dlg.data.title = title
|
||||||
new_dlg:show()
|
new_dlg:show()
|
||||||
end
|
end
|
||||||
|
|
||||||
--------------------------------------------------------------------------------
|
--------------------------------------------------------------------------------
|
||||||
-- @function [parent=#modstore] successfulldialog
|
-- @function [parent=#modstore] successfulldialog
|
||||||
function modstore.successfulldialog()
|
function modstore.successfulldialog(downloading_dlg)
|
||||||
local new_dlg = dialog_create("store_downloading",
|
local new_dlg = dialog_create("store_downloading",
|
||||||
function(data)
|
function(data)
|
||||||
local retval = ""
|
local retval = ""
|
||||||
|
@ -158,18 +159,16 @@ function modstore.successfulldialog()
|
||||||
if modstore.lastmodentry ~= nil then
|
if modstore.lastmodentry ~= nil then
|
||||||
retval = retval .. "label[0,0.25;" .. fgettext("Successfully installed:") .. "]"
|
retval = retval .. "label[0,0.25;" .. fgettext("Successfully installed:") .. "]"
|
||||||
retval = retval .. "label[3,0.25;" .. modstore.lastmodentry.moddetails.title .. "]"
|
retval = retval .. "label[3,0.25;" .. modstore.lastmodentry.moddetails.title .. "]"
|
||||||
|
|
||||||
|
|
||||||
retval = retval .. "label[0,0.75;" .. fgettext("Shortname:") .. "]"
|
retval = retval .. "label[0,0.75;" .. fgettext("Shortname:") .. "]"
|
||||||
retval = retval .. "label[3,0.75;" .. core.formspec_escape(modstore.lastmodentry.moddetails.basename) .. "]"
|
retval = retval .. "label[3,0.75;" .. core.formspec_escape(modstore.lastmodentry.moddetails.basename) .. "]"
|
||||||
|
|
||||||
end
|
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,
|
end,
|
||||||
function(this,fields)
|
function(this,fields)
|
||||||
if fields["btn_confirm_mod_successfull"] ~= nil then
|
if fields["btn_confirm_mod_successfull"] ~= nil then
|
||||||
this.parent:show()
|
this.parent:show()
|
||||||
this:hide()
|
downloading_dlg:delete()
|
||||||
this:delete()
|
this:delete()
|
||||||
|
|
||||||
return true
|
return true
|
||||||
|
@ -177,10 +176,10 @@ function modstore.successfulldialog()
|
||||||
|
|
||||||
return false
|
return false
|
||||||
end,
|
end,
|
||||||
nil,
|
nil)
|
||||||
modstore.tv_store)
|
|
||||||
|
|
||||||
new_dlg.data.title = title
|
new_dlg:set_parent(modstore.tv_store)
|
||||||
|
modstore.tv_store:hide()
|
||||||
new_dlg:show()
|
new_dlg:show()
|
||||||
end
|
end
|
||||||
|
|
||||||
|
@ -217,7 +216,9 @@ function modstore.handle_buttons(parent, fields, name, data)
|
||||||
end
|
end
|
||||||
|
|
||||||
if fields["btn_modstore_close"] then
|
if fields["btn_modstore_close"] then
|
||||||
|
local maintab = ui.find_by_name("maintab")
|
||||||
parent:hide()
|
parent:hide()
|
||||||
|
maintab:show()
|
||||||
return true
|
return true
|
||||||
end
|
end
|
||||||
|
|
||||||
|
@ -228,12 +229,7 @@ function modstore.handle_buttons(parent, fields, name, data)
|
||||||
for i=1,#modstore.modlist_unsorted.data,1 do
|
for i=1,#modstore.modlist_unsorted.data,1 do
|
||||||
if modstore.modlist_unsorted.data[i].id == modid then
|
if modstore.modlist_unsorted.data[i].id == modid then
|
||||||
local moddetails = modstore.modlist_unsorted.data[i].details
|
local moddetails = modstore.modlist_unsorted.data[i].details
|
||||||
|
modstore.lastmodtitle = moddetails.title
|
||||||
if modstore.lastmodtitle ~= "" then
|
|
||||||
modstore.lastmodtitle = modstore.lastmodtitle .. ", "
|
|
||||||
end
|
|
||||||
|
|
||||||
modstore.lastmodtitle = modstore.lastmodtitle .. moddetails.title
|
|
||||||
|
|
||||||
if not core.handle_async(
|
if not core.handle_async(
|
||||||
function(param)
|
function(param)
|
||||||
|
@ -281,7 +277,7 @@ function modstore.handle_buttons(parent, fields, name, data)
|
||||||
texturename = modstore.modlist_unsorted.data[i].texturename
|
texturename = modstore.modlist_unsorted.data[i].texturename
|
||||||
},
|
},
|
||||||
function(result)
|
function(result)
|
||||||
print("Result from async: " .. dump(result.successfull))
|
--print("Result from async: " .. dump(result.successfull))
|
||||||
if result.successfull then
|
if result.successfull then
|
||||||
modmgr.installmod(result.filename,result.moddetails.basename)
|
modmgr.installmod(result.filename,result.moddetails.basename)
|
||||||
os.remove(result.filename)
|
os.remove(result.filename)
|
||||||
|
@ -299,7 +295,7 @@ function modstore.handle_buttons(parent, fields, name, data)
|
||||||
print("ERROR: async event failed")
|
print("ERROR: async event failed")
|
||||||
gamedata.errormessage = "Failed to download " .. modstore.lastmodtitle
|
gamedata.errormessage = "Failed to download " .. modstore.lastmodtitle
|
||||||
end
|
end
|
||||||
parent:hide()
|
|
||||||
modstore.showdownloading(modstore.lastmodtitle)
|
modstore.showdownloading(modstore.lastmodtitle)
|
||||||
return true
|
return true
|
||||||
end
|
end
|
||||||
|
@ -391,7 +387,7 @@ function modstore.getscreenshot(ypos,listentry)
|
||||||
listentry.details.screenshot_url == "") then
|
listentry.details.screenshot_url == "") then
|
||||||
|
|
||||||
if listentry.texturename == nil then
|
if listentry.texturename == nil then
|
||||||
listentry.texturename = modstore.basetexturedir .. "no_screenshot.png"
|
listentry.texturename = defaulttexturedir .. "no_screenshot.png"
|
||||||
end
|
end
|
||||||
|
|
||||||
return "image[0,".. ypos .. ";3,2;" ..
|
return "image[0,".. ypos .. ";3,2;" ..
|
||||||
|
|
|
@ -57,7 +57,7 @@ local function get_formspec(tabview, name, tabdata)
|
||||||
end
|
end
|
||||||
|
|
||||||
if modscreenshot == nil then
|
if modscreenshot == nil then
|
||||||
modscreenshot = modstore.basetexturedir .. "no_screenshot.png"
|
modscreenshot = defaulttexturedir .. "no_screenshot.png"
|
||||||
end
|
end
|
||||||
|
|
||||||
retval = retval
|
retval = retval
|
||||||
|
@ -96,7 +96,7 @@ local function get_formspec(tabview, name, tabdata)
|
||||||
else
|
else
|
||||||
--show dependencies
|
--show dependencies
|
||||||
|
|
||||||
retval = retval .. ",Depends:,"
|
retval = retval .. "," .. fgettext("Depends:") .. ","
|
||||||
|
|
||||||
local toadd = modmgr.get_dependencies(selected_mod.path)
|
local toadd = modmgr.get_dependencies(selected_mod.path)
|
||||||
|
|
||||||
|
|
|
@ -59,9 +59,10 @@ local function get_formspec(tabview, name, tabdata)
|
||||||
"text,align=right;" .. -- clients
|
"text,align=right;" .. -- clients
|
||||||
"text,align=center,padding=0.25;" .. -- "/"
|
"text,align=center,padding=0.25;" .. -- "/"
|
||||||
"text,align=right,padding=0.25;" .. -- clients_max
|
"text,align=right,padding=0.25;" .. -- clients_max
|
||||||
image_column("Creative mode", "creative") .. ",padding=1;" ..
|
image_column(fgettext("Creative mode"), "creative") .. ",padding=1;" ..
|
||||||
image_column("Damage enabled", "damage") .. ",padding=0.25;" ..
|
image_column(fgettext("Damage enabled"), "damage") .. ",padding=0.25;" ..
|
||||||
image_column("PvP enabled", "pvp") .. ",padding=0.25;" ..
|
image_column(fgettext("PvP enabled"), "pvp") .. ",padding=0.25;" ..
|
||||||
|
"color,span=1;" ..
|
||||||
"text,padding=1]" -- name
|
"text,padding=1]" -- name
|
||||||
else
|
else
|
||||||
retval = retval .. "tablecolumns[text]"
|
retval = retval .. "tablecolumns[text]"
|
||||||
|
@ -88,7 +89,6 @@ end
|
||||||
|
|
||||||
--------------------------------------------------------------------------------
|
--------------------------------------------------------------------------------
|
||||||
local function main_button_handler(tabview, fields, name, tabdata)
|
local function main_button_handler(tabview, fields, name, tabdata)
|
||||||
|
|
||||||
if fields["te_name"] ~= nil then
|
if fields["te_name"] ~= nil then
|
||||||
gamedata.playername = fields["te_name"]
|
gamedata.playername = fields["te_name"]
|
||||||
core.setting_set("name", 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"])
|
local event = core.explode_table_event(fields["favourites"])
|
||||||
if event.type == "DCL" then
|
if event.type == "DCL" then
|
||||||
if event.row <= #menudata.favorites 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.address = menudata.favorites[event.row].address
|
||||||
gamedata.port = menudata.favorites[event.row].port
|
gamedata.port = menudata.favorites[event.row].port
|
||||||
gamedata.playername = fields["te_name"]
|
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")
|
local current_favourite = core.get_table_index("favourites")
|
||||||
if current_favourite == nil then return end
|
if current_favourite == nil then return end
|
||||||
core.delete_favorite(current_favourite)
|
core.delete_favorite(current_favourite)
|
||||||
menudata.favorites = core.get_favorites()
|
menudata.favorites = order_favorite_list(core.get_favorites())
|
||||||
tabdata.fav_selected = nil
|
tabdata.fav_selected = nil
|
||||||
|
|
||||||
core.setting_set("address","")
|
core.setting_set("address","")
|
||||||
|
@ -198,8 +202,9 @@ local function main_button_handler(tabview, fields, name, tabdata)
|
||||||
return true
|
return true
|
||||||
end
|
end
|
||||||
|
|
||||||
if fields["btn_mp_connect"] ~= nil or
|
if (fields["btn_mp_connect"] ~= nil or
|
||||||
fields["key_enter"] ~= nil then
|
fields["key_enter"] ~= nil) and fields["te_address"] ~= nil and
|
||||||
|
fields["te_port"] ~= nil then
|
||||||
|
|
||||||
gamedata.playername = fields["te_name"]
|
gamedata.playername = fields["te_name"]
|
||||||
gamedata.password = fields["te_pwd"]
|
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.servername = menudata.favorites[fav_idx].name
|
||||||
gamedata.serverdescription = menudata.favorites[fav_idx].description
|
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
|
else
|
||||||
gamedata.servername = ""
|
gamedata.servername = ""
|
||||||
gamedata.serverdescription = ""
|
gamedata.serverdescription = ""
|
||||||
|
|
|
@ -42,9 +42,10 @@ local function get_formspec(tabview, name, tabdata)
|
||||||
"text,align=right;" .. -- clients
|
"text,align=right;" .. -- clients
|
||||||
"text,align=center,padding=0.25;" .. -- "/"
|
"text,align=center,padding=0.25;" .. -- "/"
|
||||||
"text,align=right,padding=0.25;" .. -- clients_max
|
"text,align=right,padding=0.25;" .. -- clients_max
|
||||||
image_column("Creative mode", "creative") .. ",padding=1;" ..
|
image_column(fgettext("Creative mode"), "creative") .. ",padding=1;" ..
|
||||||
image_column("Damage enabled", "damage") .. ",padding=0.25;" ..
|
image_column(fgettext("Damage enabled"), "damage") .. ",padding=0.25;" ..
|
||||||
image_column("PvP enabled", "pvp") .. ",padding=0.25;" ..
|
image_column(fgettext("PvP enabled"), "pvp") .. ",padding=0.25;" ..
|
||||||
|
"color,span=1;" ..
|
||||||
"text,padding=1]" -- name
|
"text,padding=1]" -- name
|
||||||
else
|
else
|
||||||
retval = retval .. "tablecolumns[text]"
|
retval = retval .. "tablecolumns[text]"
|
||||||
|
@ -87,7 +88,6 @@ local function get_formspec(tabview, name, tabdata)
|
||||||
end
|
end
|
||||||
|
|
||||||
--------------------------------------------------------------------------------
|
--------------------------------------------------------------------------------
|
||||||
|
|
||||||
local function main_button_handler(tabview, fields, name, tabdata)
|
local function main_button_handler(tabview, fields, name, tabdata)
|
||||||
|
|
||||||
if fields["btn_start_singleplayer"] then
|
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.servername = menudata.favorites[fav_idx].name
|
||||||
gamedata.serverdescription = menudata.favorites[fav_idx].description
|
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
|
else
|
||||||
gamedata.servername = ""
|
gamedata.servername = ""
|
||||||
gamedata.serverdescription = ""
|
gamedata.serverdescription = ""
|
||||||
|
|
|
@ -44,7 +44,7 @@ else()
|
||||||
/usr/include/irrlicht
|
/usr/include/irrlicht
|
||||||
)
|
)
|
||||||
|
|
||||||
FIND_LIBRARY(IRRLICHT_LIBRARY NAMES libIrrlicht.a Irrlicht
|
FIND_LIBRARY(IRRLICHT_LIBRARY NAMES libIrrlicht.so libIrrlicht.a Irrlicht
|
||||||
PATHS
|
PATHS
|
||||||
/usr/local/lib
|
/usr/local/lib
|
||||||
/usr/lib
|
/usr/lib
|
||||||
|
|
273
doc/lua_api.txt
273
doc/lua_api.txt
|
@ -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/>
|
* More information at <http://www.minetest.net/>
|
||||||
* Developer Wiki: <http://dev.minetest.net/>
|
* Developer Wiki: <http://dev.minetest.net/>
|
||||||
|
@ -20,7 +20,8 @@ source code patches to <celeron55@gmail.com>.
|
||||||
|
|
||||||
Programming in Lua
|
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
|
Startup
|
||||||
-------
|
-------
|
||||||
|
@ -593,13 +594,14 @@ set to level from `param2`.
|
||||||
Meshes
|
Meshes
|
||||||
------
|
------
|
||||||
If drawtype `mesh` is used, tiles should hold model materials textures.
|
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.
|
For supported model formats see Irrlicht engine documentation.
|
||||||
|
|
||||||
|
|
||||||
Noise Parameters
|
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`
|
||||||
Offset that the noise is translated by (i.e. added) after calculation.
|
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.
|
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
|
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
|
that point is greater than the `noise_threshold`, giving the ability to create
|
||||||
distribution of ore.
|
a non-equal distribution of ore.
|
||||||
|
|
||||||
### `sheet`
|
### `sheet`
|
||||||
Creates a sheet of ore in a blob shape according to the 2D perlin noise described by `noise_params`.
|
Creates a sheet of ore in a blob shape according to the 2D perlin noise
|
||||||
The relative height of the sheet can be controlled by the same perlin noise as well, by specifying
|
described by `noise_params`. The relative height of the sheet can be
|
||||||
a non-zero `scale` parameter in `noise_params`.
|
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
|
**IMPORTANT**: The noise is not transformed by `offset` or `scale` when comparing
|
||||||
threshold, but scale is used to determine relative height.
|
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`.
|
The height of the blob is randomly scattered, with a maximum height of `clust_size`.
|
||||||
|
|
||||||
`clust_scarcity` and `clust_num_ores` are ignored.
|
`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`
|
### `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
|
`noise_params`. The maximum size of the blob is `clust_size`, and
|
||||||
`clust_scarcity` has the same meaning as with the `scatter` type.
|
`clust_scarcity` has the same meaning as with the `scatter` type.
|
||||||
### `vein
|
### `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.
|
The default value is `simple`, and is currently the only type supported.
|
||||||
|
|
||||||
### `simple`
|
### `simple`
|
||||||
Creates a 1 times `H` times 1 column of a specified node (or a random node from a list, if a
|
Creates a 1 times `H` times 1 column of a specified node (or a random node from
|
||||||
decoration list is specified). Can specify a certain node it must spawn next to, such as water or
|
a list, if a decoration list is specified). Can specify a certain node it must
|
||||||
lava, for example. Can also generate a decoration of random height between a specified lower and
|
spawn next to, such as water or lava, for example. Can also generate a
|
||||||
upper bound. This type of decoration is intended for placement of grass, flowers, cacti, papyri,
|
decoration of random height between a specified lower and upper bound.
|
||||||
and so on.
|
This type of decoration is intended for placement of grass, flowers, cacti,
|
||||||
|
papyri, and so on.
|
||||||
|
|
||||||
### `schematic`
|
### `schematic`
|
||||||
Copies a box of `MapNodes` from a specified schematic file (or raw description). Can specify a
|
Copies a box of `MapNodes` from a specified schematic file (or raw description).
|
||||||
probability of a node randomly appearing when placed. This decoration type is intended to be used
|
Can specify a probability of a node randomly appearing when placed.
|
||||||
for multi-node sized discrete structures, such as trees, cave spikes, rocks, and so on.
|
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
|
Schematic specifier
|
||||||
--------------------
|
--------------------
|
||||||
A schematic specifier identifies a schematic by either a filename to a Minetest Schematic file (`.mts`)
|
A schematic specifier identifies a schematic by either a filename to a
|
||||||
or through raw data supplied through Lua, in the form of a table. This table must specify two fields:
|
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 `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
|
In the bulk `MapNode` data, `param1`, instead of the typical light values,
|
||||||
probability of that node appearing in the structure.
|
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 `0` means that node will never appear (0% chance).
|
||||||
* A probability value of `255` means the node will always appear (100% 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
|
* If the probability value `p` is greater than `0`, then there is a
|
||||||
will appear when the schematic is placed on the map.
|
`(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
|
Schematic attributes
|
||||||
--------------------
|
--------------------
|
||||||
See section "Flag Specifier Format".
|
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_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_y`: Placement of this decoration is centered along the Y axis.
|
||||||
* `place_center_z`: Placement of this decoration is centered along the Z 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
|
HUD element types
|
||||||
-----------------
|
-----------------
|
||||||
The position field is used for all 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,
|
To account for differing resolutions, the position coordinates are the percentage
|
||||||
ranging in value from `0` to `1`.
|
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 name field is not yet used, but should contain a description of what the
|
||||||
The direction field is the direction in which something is drawn.
|
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,
|
`0` draws from left to right, `1` draws from right to left, `2` draws from
|
||||||
and `3` draws from bottom to top.
|
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`,
|
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.
|
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.
|
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`
|
### `image`
|
||||||
Displays an image on the HUD.
|
Displays an image on the HUD.
|
||||||
|
@ -876,15 +892,18 @@ For helper functions see "Vector helpers".
|
||||||
|
|
||||||
Flag Specifier Format
|
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.
|
The string format is a comma-delimited set of flag names; whitespace and
|
||||||
Specifying a flag in the string sets the flag, and specifying a flag prefixed by the string `"no"` explicitly
|
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.
|
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
|
In addition to the standard string flag format, the schematic flags field can
|
||||||
to boolean values representing whether or not the flag is set. Additionally, if a field with the flag name
|
also be a table of flag names to boolean values representing whether or not the
|
||||||
prefixed with `"no"` is present, mapped to a boolean of any value, the specified flag is unset.
|
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
|
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
|
dropped as an item. If the node is wallmounted the wallmounted direction is
|
||||||
checked.
|
checked.
|
||||||
* `soil`: saplings will grow on nodes in this group
|
* `soil`: saplings will grow on nodes in this group
|
||||||
* `connect_to_raillike`: makes nodes of raillike drawtype connect to
|
* `connect_to_raillike`: makes nodes of raillike drawtype with same group value
|
||||||
other group members with same drawtype
|
connect to each other
|
||||||
|
|
||||||
### Known damage and digging time defining groups
|
### Known damage and digging time defining groups
|
||||||
* `crumbly`: dirt, sand
|
* `crumbly`: dirt, sand
|
||||||
|
@ -1177,7 +1196,8 @@ Damage calculation:
|
||||||
|
|
||||||
damage = 0
|
damage = 0
|
||||||
foreach group in cap.damage_groups:
|
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)
|
* (object.armor_groups[group] / 100.0)
|
||||||
-- Where object.armor_groups[group] is 0 for inexistent values
|
-- Where object.armor_groups[group] is 0 for inexistent values
|
||||||
return damage
|
return damage
|
||||||
|
@ -1185,7 +1205,7 @@ Damage calculation:
|
||||||
Client predicts damage based on damage groups. Because of this, it is able to
|
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
|
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;
|
pre-defined somehow (e.g. by defining a sprite animation) (not implemented;
|
||||||
TODO).
|
TODO).
|
||||||
Currently a smoke puff will appear when an entity dies.
|
Currently a smoke puff will appear when an entity dies.
|
||||||
|
|
||||||
The group `immortal` completely disables normal damage.
|
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)
|
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
|
This should never be called directly, because damage is usually not handled by
|
||||||
itself.
|
the entity itself.
|
||||||
|
|
||||||
* `puncher` is the object performing the punch. Can be `nil`. Should never be
|
* `puncher` is the object performing the punch. Can be `nil`. Should never be
|
||||||
accessed unless absolutely required, to encourage interoperability.
|
accessed unless absolutely required, to encourage interoperability.
|
||||||
|
@ -1244,12 +1264,14 @@ Example stuff:
|
||||||
print(dump(meta:to_table()))
|
print(dump(meta:to_table()))
|
||||||
meta:from_table({
|
meta:from_table({
|
||||||
inventory = {
|
inventory = {
|
||||||
main = {[1] = "default:dirt", [2] = "", [3] = "", [4] = "", [5] = "", [6] = "",
|
main = {[1] = "default:dirt", [2] = "", [3] = "", [4] = "",
|
||||||
[7] = "", [8] = "", [9] = "", [10] = "", [11] = "", [12] = "", [13] = "",
|
[5] = "", [6] = "", [7] = "", [8] = "", [9] = "",
|
||||||
[14] = "default:cobble", [15] = "", [16] = "", [17] = "", [18] = "",
|
[10] = "", [11] = "", [12] = "", [13] = "",
|
||||||
[19] = "", [20] = "default:cobble", [21] = "", [22] = "", [23] = "",
|
[14] = "default:cobble", [15] = "", [16] = "", [17] = "",
|
||||||
[24] = "", [25] = "", [26] = "", [27] = "", [28] = "", [29] = "", [30] = "",
|
[18] = "", [19] = "", [20] = "default:cobble", [21] = "",
|
||||||
[31] = "", [32] = ""}
|
[22] = "", [23] = "", [24] = "", [25] = "", [26] = "",
|
||||||
|
[27] = "", [28] = "", [29] = "", [30] = "", [31] = "",
|
||||||
|
[32] = ""}
|
||||||
},
|
},
|
||||||
fields = {
|
fields = {
|
||||||
formspec = "size[8,9]list[context;main;0,0;8,4;]list[current_player;main;0,5;8,4;]",
|
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"`
|
* `nodenames`: e.g. `{"ignore", "group:tree"}` or `"default:dirt"`
|
||||||
* `minetest.find_nodes_in_area(minp, maxp, nodenames)`: returns a list of positions
|
* `minetest.find_nodes_in_area(minp, maxp, nodenames)`: returns a list of positions
|
||||||
* `nodenames`: e.g. `{"ignore", "group:tree"}` or `"default:dirt"`
|
* `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(noiseparams)`
|
||||||
* `minetest.get_perlin(seeddiff, octaves, persistence, scale)`
|
* `minetest.get_perlin(seeddiff, octaves, persistence, scale)`
|
||||||
* Return world-specific perlin noise (`int(worldseed)+seeddiff`)
|
* 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`.
|
`mgname`, `seed`, `chunksize`, `water_level`, and `flags`.
|
||||||
* `minetest.set_mapgen_params(MapgenParams)`
|
* `minetest.set_mapgen_params(MapgenParams)`
|
||||||
* Set map generation parameters
|
* Set map generation parameters
|
||||||
* Function cannot be called after the registration period; only initialization and `on_mapgen_init`
|
* Function cannot be called after the registration period; only initialization
|
||||||
* Takes a table as an argument with the fields `mgname`, `seed`, `water_level`, and `flags`.
|
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
|
* Leave field unset to leave that parameter unchanged
|
||||||
* `flags` contains a comma-delimited string of flags to set,
|
* `flags` contains a comma-delimited string of flags to set,
|
||||||
or if the prefix `"no"` is attached, clears instead.
|
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`
|
* `minetest.create_detached_inventory(name, callbacks)`: returns an `InvRef`
|
||||||
* callbacks: See "Detached inventory callbacks"
|
* callbacks: See "Detached inventory callbacks"
|
||||||
* Creates a detached inventory. If it already exists, it is cleared.
|
* 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
|
### Formspec
|
||||||
* `minetest.show_formspec(playername, formname, formspec)`
|
* `minetest.show_formspec(playername, formname, formspec)`
|
||||||
|
@ -2037,7 +2067,11 @@ These functions return the leftover itemstack.
|
||||||
* `minetest.item_drop(itemstack, dropper, pos)`
|
* `minetest.item_drop(itemstack, dropper, pos)`
|
||||||
* Drop the item
|
* Drop the item
|
||||||
* `minetest.item_eat(hp_change, replace_with_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
|
### Defaults for the `on_punch` and `on_dig` node definition callbacks
|
||||||
* `minetest.node_punch(pos, node, puncher, pointed_thing)`
|
* `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.
|
* 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`.
|
* 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`.
|
* `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).
|
* `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 `pos` is not inside the box formed by `p1` and `p2`, it is ignored.
|
||||||
* If `probability_list` equals `nil`, no probabilities are applied.
|
* 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.
|
indicates the y position of the slice with a probability applied.
|
||||||
* If slice probability list equals `nil`, no slice probabilities are applied.
|
* If slice probability list equals `nil`, no slice probabilities are applied.
|
||||||
* Saves schematic in the Minetest Schematic format to filename.
|
* Saves schematic in the Minetest Schematic format to filename.
|
||||||
|
@ -2244,7 +2281,7 @@ Class reference
|
||||||
---------------
|
---------------
|
||||||
|
|
||||||
### `NodeMetaRef`
|
### `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)`.
|
Can be gotten via `minetest.get_meta(pos)`.
|
||||||
|
|
||||||
#### Methods
|
#### Methods
|
||||||
|
@ -2260,7 +2297,7 @@ Can be gotten via `minetest.get_meta(pos)`.
|
||||||
* See "Node Metadata"
|
* See "Node Metadata"
|
||||||
|
|
||||||
### `NoteTimerRef`
|
### `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)`.
|
Can be gotten via `minetest.get_node_timer(pos)`.
|
||||||
|
|
||||||
#### Methods
|
#### Methods
|
||||||
|
@ -2288,6 +2325,7 @@ This is basically a reference to a C++ `ServerActiveObject`
|
||||||
|
|
||||||
#### Methods
|
#### Methods
|
||||||
* `remove()`: remove object (after returning from Lua)
|
* `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}`
|
* `getpos()`: returns `{x=num, y=num, z=num}`
|
||||||
* `setpos(pos)`; `pos`=`{x=num, y=num, z=num}`
|
* `setpos(pos)`; `pos`=`{x=num, y=num, z=num}`
|
||||||
* `moveto(pos, continuous=false)`: interpolated move
|
* `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`)
|
* `gravity`: multiplier to default gravity value (default: `1`)
|
||||||
* `sneak`: whether player can sneak (default: `true`)
|
* `sneak`: whether player can sneak (default: `true`)
|
||||||
* `sneak_glitch`: whether player can use the sneak glitch (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_remove(id)`: remove the HUD element of the specified id
|
||||||
* `hud_change(id, stat, value)`: change a value of a previously added HUD element
|
* `hud_change(id, stat, value)`: change a value of a previously added HUD element
|
||||||
* element `stat` values: `position`, `name`, `scale`, `text`, `number`, `item`, `dir`
|
* 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)`
|
* `override_day_night_ratio(ratio or nil)`
|
||||||
* `0`...`1`: Overrides day-night ratio, controlling sunlight to a specific amount
|
* `0`...`1`: Overrides day-night ratio, controlling sunlight to a specific amount
|
||||||
* `nil`: Disables override, defaulting to sunlight based on day-night cycle
|
* `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_local_animation(walk, dig, walk+dig, frame_speed=frame_speed)`
|
||||||
set animation for player model in third person view
|
|
||||||
* stand/idle animation key frames
|
set animation for player model in third person view
|
||||||
* walk animation key frames
|
|
||||||
* dig animation key frames
|
set_local_animation({x=0, y=79}, -- < stand/idle animation key frames
|
||||||
* walk+dig animation key frames
|
{x=168, y=187}, -- < walk animation key frames
|
||||||
* animation frame speed
|
{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
|
* `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 first person view
|
||||||
* in third person view (max. values `{x=-10/10,y=-10,15,z=-5/5}`)
|
* 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`
|
### `PerlinNoise`
|
||||||
A perlin noise generator.
|
A perlin noise generator.
|
||||||
It can be created via `PerlinNoise(seed, octaves, persistence, scale)`
|
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)`
|
Alternatively with `minetest.get_perlin(seeddiff, octaves, persistence, scale)`
|
||||||
or `minetest.get_perlin(noiseparams)`.
|
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.
|
The map will be pre-loaded if two positions are passed to either.
|
||||||
|
|
||||||
#### Methods
|
#### 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`
|
* returns actual emerged `pmin`, actual emerged `pmax`
|
||||||
* `write_to_map()`: Writes the data loaded from the `VoxelManip` back to the map.
|
* `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
|
* **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
|
* `get_node_at(pos)`: Returns a `MapNode` table of the node currently loaded in
|
||||||
* `set_node_at(pos, node)`: Sets a specific `MapNode` in the `VoxelManip` at that position
|
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
|
* `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
|
* 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
|
* `set_data(data)`: Sets the data contents of the `VoxelManip` object
|
||||||
* `update_map()`: Update map after writing chunk back to map.
|
* `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
|
* To be used only by `VoxelManip` objects created by the mod itself;
|
||||||
retrieved from `minetest.get_mapgen_object`
|
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
|
* `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>}`
|
* `light` is a table, `{day=<0...15>, night=<0...15>}`
|
||||||
* To be used only by a `VoxelManip` object from `minetest.get_mapgen_object`
|
* 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
|
* `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`
|
* 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)
|
* Each value is the bitwise combination of day and night light values (`0` to `15` each)
|
||||||
* `light = day + (night * 16)`
|
* `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
|
* 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
|
* `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`
|
* `set_param2_data(param2_data)`: Sets the `param2` contents of each node in the `VoxelManip`
|
||||||
* `calc_lighting(p1, p2)`: Calculate lighting within the `VoxelManip`
|
* `calc_lighting(p1, p2)`: Calculate lighting within the `VoxelManip`
|
||||||
* To be used only by a `VoxelManip` object from `minetest.get_mapgen_object`
|
* 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
|
* `update_liquids()`: Update liquid flow
|
||||||
* `was_modified()`: Returns `true` or `false` if the data in the voxel manipulator had been modified since
|
* `was_modified()`: Returns `true` or `false` if the data in the voxel manipulator
|
||||||
the last read from map, due to a call to `minetest.set_data()` on the loaded area elsewhere
|
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.
|
* `get_emerged_area()`: Returns actual emerged minimum and maximum positions.
|
||||||
|
|
||||||
### `VoxelArea`
|
### `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.
|
The coordinates are *inclusive*, like most other things in Minetest.
|
||||||
|
|
||||||
#### Methods
|
#### 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`
|
* `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`
|
* `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
|
* `indexp(p)`: same as above, except takes a vector
|
||||||
* `position(i)`: returns the absolute position vector corresponding to index `i`
|
* `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`
|
* `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
|
Mapgen objects
|
||||||
--------------
|
--------------
|
||||||
A mapgen object is a construct used in map generation. Mapgen objects can be used by an `on_generate`
|
A mapgen object is a construct used in map generation. Mapgen objects can be used
|
||||||
callback to speed up operations by avoiding unnecessary recalculations; these can be retrieved using the
|
by an `on_generate` callback to speed up operations by avoiding unnecessary
|
||||||
`minetest.get_mapgen_object()` function. If the requested Mapgen object is unavailable, or
|
recalculations; these can be retrieved using the `minetest.get_mapgen_object()`
|
||||||
`get_mapgen_object()` was called outside of an `on_generate()` callback, `nil` is returned.
|
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:
|
The following Mapgen objects are currently available:
|
||||||
|
|
||||||
### `voxelmanip`
|
### `voxelmanip`
|
||||||
This returns three values; the `VoxelManip` object to be used, minimum and maximum emerged position, in that
|
This returns three values; the `VoxelManip` object to be used, minimum and maximum
|
||||||
order. All mapgens support this object.
|
emerged position, in that order. All mapgens support this object.
|
||||||
|
|
||||||
### `heightmap`
|
### `heightmap`
|
||||||
Returns an array containing the y coordinates of the ground levels of nodes in the most recently
|
Returns an array containing the y coordinates of the ground levels of nodes in
|
||||||
generated chunk by the current mapgen.
|
the most recently generated chunk by the current mapgen.
|
||||||
|
|
||||||
### `biomemap`
|
### `biomemap`
|
||||||
Returns an array containing the biome IDs of nodes in the most recently generated chunk by the
|
Returns an array containing the biome IDs of nodes in the most recently
|
||||||
current mapgen.
|
generated chunk by the current mapgen.
|
||||||
|
|
||||||
### `heatmap`
|
### `heatmap`
|
||||||
Returns an array containing the temperature values of nodes in the most recently generated chunk by
|
Returns an array containing the temperature values of nodes in the most
|
||||||
the current mapgen.
|
recently generated chunk by the current mapgen.
|
||||||
|
|
||||||
### `humiditymap`
|
### `humiditymap`
|
||||||
Returns an array containing the humidity values of nodes in the most recently generated chunk by the
|
Returns an array containing the humidity values of nodes in the most recently
|
||||||
current mapgen.
|
generated chunk by the current mapgen.
|
||||||
|
|
||||||
### `gennotify`
|
### `gennotify`
|
||||||
Returns a table mapping requested generation notification types to arrays of positions at which the
|
Returns a table mapping requested generation notification types to arrays of
|
||||||
corresponding generated structures are located at within the current chunk. To set the capture of positions
|
positions at which the corresponding generated structures are located at within
|
||||||
of interest to be recorded on generate, use `minetest.set_gen_notify()`.
|
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:
|
Possible fields of the table returned are:
|
||||||
|
|
||||||
|
@ -2629,7 +2682,8 @@ Possible fields of the table returned are:
|
||||||
* `large_cave_end`
|
* `large_cave_end`
|
||||||
* `decoration`
|
* `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
|
Registered entities
|
||||||
-------------------
|
-------------------
|
||||||
|
@ -2676,7 +2730,8 @@ L-system trees
|
||||||
angle, --num angle in deg
|
angle, --num angle in deg
|
||||||
iterations, --num max # of iterations, usually 2 -5
|
iterations, --num max # of iterations, usually 2 -5
|
||||||
random_level, --num factor to lower nr of iterations, usually 0 - 3
|
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
|
thin_branches, --boolean true -> use thin (1 node) branches
|
||||||
fruit, --string fruit node name
|
fruit, --string fruit node name
|
||||||
fruit_chance, --num chance (0-100) to replace leaves with fruit node
|
fruit_chance, --num chance (0-100) to replace leaves with fruit node
|
||||||
|
@ -3138,8 +3193,10 @@ Definition tables
|
||||||
schematic = {
|
schematic = {
|
||||||
size = {x=4, y=6, z=4},
|
size = {x=4, y=6, z=4},
|
||||||
data = {
|
data = {
|
||||||
{name="cobble", param1=255, param2=0},
|
{name="default:cobble", param1=255, param2=0},
|
||||||
{name="dirt_with_grass", 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 = {
|
yslice_prob = {
|
||||||
|
@ -3150,7 +3207,7 @@ Definition tables
|
||||||
},
|
},
|
||||||
-- ^ See 'Schematic specifier' for details.
|
-- ^ See 'Schematic specifier' for details.
|
||||||
replacements = {["oldname"] = "convert_to", ...},
|
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'.
|
-- ^ Flags for schematic decorations. See 'Schematic attributes'.
|
||||||
rotation = "90" -- rotate schematic 90 degrees on placement
|
rotation = "90" -- rotate schematic 90 degrees on placement
|
||||||
-- ^ Rotation can be "0", "90", "180", "270", or "random".
|
-- ^ Rotation can be "0", "90", "180", "270", or "random".
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
Minetest Lua Mainmenu API Reference 0.4.11
|
Minetest Lua Mainmenu API Reference 0.4.12
|
||||||
========================================
|
========================================
|
||||||
|
|
||||||
Introduction
|
Introduction
|
||||||
|
@ -197,9 +197,11 @@ core.delete_world(index)
|
||||||
Helpers:
|
Helpers:
|
||||||
core.gettext(string) -> string
|
core.gettext(string) -> string
|
||||||
^ look up the translation of a string in the gettext message catalog
|
^ 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
|
^ 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)
|
core.parse_json(string[, nullvalue]) -> something (possible in async calls)
|
||||||
^ see core.parse_json (lua_api.txt)
|
^ see core.parse_json (lua_api.txt)
|
||||||
dump(obj, dumped={})
|
dump(obj, dumped={})
|
||||||
|
@ -211,6 +213,12 @@ string:trim()
|
||||||
core.is_yes(arg) (possible in async calls)
|
core.is_yes(arg) (possible in async calls)
|
||||||
^ returns whether arg can be interpreted as yes
|
^ 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:
|
Async:
|
||||||
core.handle_async(async_job,parameters,finished)
|
core.handle_async(async_job,parameters,finished)
|
||||||
^ execute a function asynchronously
|
^ execute a function asynchronously
|
||||||
|
|
|
@ -48,6 +48,7 @@
|
||||||
#keymap_rangeselect = KEY_KEY_R
|
#keymap_rangeselect = KEY_KEY_R
|
||||||
#keymap_freemove = KEY_KEY_K
|
#keymap_freemove = KEY_KEY_K
|
||||||
#keymap_fastmove = KEY_KEY_J
|
#keymap_fastmove = KEY_KEY_J
|
||||||
|
#keymap_cinematic = KEY_F8
|
||||||
#keymap_screenshot = KEY_F12
|
#keymap_screenshot = KEY_F12
|
||||||
# If true, keymap_special1 instead of keymap_sneak is used for climbing down and descending
|
# If true, keymap_special1 instead of keymap_sneak is used for climbing down and descending
|
||||||
#aux1_descends = false
|
#aux1_descends = false
|
||||||
|
@ -127,6 +128,13 @@
|
||||||
#free_move = false
|
#free_move = false
|
||||||
# Continuous forward movement (for testing)
|
# Continuous forward movement (for testing)
|
||||||
#continuous_forward = false
|
#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 movement (keymap_special1)
|
||||||
#fast_move = false
|
#fast_move = false
|
||||||
# Invert mouse
|
# Invert mouse
|
||||||
|
@ -252,16 +260,16 @@
|
||||||
#freetype = true
|
#freetype = true
|
||||||
# Path to TrueTypeFont or bitmap
|
# Path to TrueTypeFont or bitmap
|
||||||
#font_path = fonts/liberationsans.ttf
|
#font_path = fonts/liberationsans.ttf
|
||||||
#font_size = 13
|
#font_size = 15
|
||||||
# Font shadow offset, if 0 then shadow will not be drawn
|
# Font shadow offset, if 0 then shadow will not be drawn
|
||||||
#font_shadow = 1
|
#font_shadow = 1
|
||||||
# Font shadow alpha (opaqueness, between 0 and 255)
|
# Font shadow alpha (opaqueness, between 0 and 255)
|
||||||
#font_shadow_alpha = 128
|
#font_shadow_alpha = 128
|
||||||
#mono_font_path = fonts/liberationmono.ttf
|
#mono_font_path = fonts/liberationmono.ttf
|
||||||
#mono_font_size = 13
|
#mono_font_size = 15
|
||||||
# This font will be used for certain languages
|
# This font will be used for certain languages
|
||||||
#fallback_font_path = fonts/DroidSansFallbackFull.ttf
|
#fallback_font_path = fonts/DroidSansFallbackFull.ttf
|
||||||
#fallback_font_size = 13
|
#fallback_font_size = 15
|
||||||
#fallback_font_shadow = 1
|
#fallback_font_shadow = 1
|
||||||
#fallback_font_shadow_alpha = 128
|
#fallback_font_shadow_alpha = 128
|
||||||
# Override language. When no value is provided (default) system language is used.
|
# Override language. When no value is provided (default) system language is used.
|
||||||
|
@ -337,6 +345,7 @@
|
||||||
# If true, disable cheat prevention in multiplayer
|
# If true, disable cheat prevention in multiplayer
|
||||||
#disable_anticheat = false
|
#disable_anticheat = false
|
||||||
# If true, actions are recorded for rollback
|
# If true, actions are recorded for rollback
|
||||||
|
# This option is only read when server starts
|
||||||
#enable_rollback_recording = false
|
#enable_rollback_recording = false
|
||||||
# Handling for deprecated lua api calls:
|
# Handling for deprecated lua api calls:
|
||||||
# "legacy" = (try to) mimic old behaviour (default for release).
|
# "legacy" = (try to) mimic old behaviour (default for release).
|
||||||
|
@ -460,6 +469,8 @@
|
||||||
# Controls size of deserts and beaches in Mapgen V6
|
# Controls size of deserts and beaches in Mapgen V6
|
||||||
#mgv6_freq_desert = 0.45
|
#mgv6_freq_desert = 0.45
|
||||||
#mgv6_freq_beach = 0.15
|
#mgv6_freq_beach = 0.15
|
||||||
|
# Enable/disable floating dungeons and dungeon slices
|
||||||
|
#enable_floating_dungeons = true
|
||||||
|
|
||||||
# Perlin noise attributes for different map generation parameters.
|
# Perlin noise attributes for different map generation parameters.
|
||||||
# Noise parameters can be specified as a set of positional values:
|
# Noise parameters can be specified as a set of positional values:
|
||||||
|
@ -477,33 +488,14 @@
|
||||||
# flags = "defaults"
|
# flags = "defaults"
|
||||||
#}
|
#}
|
||||||
# Only the group format supports noise flags which are needed for eased noise.
|
# 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
|
# Mgv5 uses eased noise for np_ground so this is shown in group format,
|
||||||
# group format, other noise parameters are shown in positional format to save space.
|
# 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_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_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_height = 0, 10, (250, 250, 250), 84174, 4, 0.5, 2.0
|
||||||
#mgv5_np_cave1 = {
|
#mgv5_np_cave1 = 0, 12, (50, 50, 50), 52534, 4, 0.5, 2.0
|
||||||
# offset = 0
|
#mgv5_np_cave2 = 0, 12, (50, 50, 50), 10325, 4, 0.5, 2.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_ground = {
|
#mgv5_np_ground = {
|
||||||
# offset = 0
|
# offset = 0
|
||||||
# scale = 40
|
# scale = 40
|
||||||
|
@ -514,17 +506,6 @@
|
||||||
# lacunarity = 2.0
|
# lacunarity = 2.0
|
||||||
# flags = "eased"
|
# 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_spflags = biomeblend, jungles, mudflow
|
||||||
#mgv6_np_terrain_base = -4, 20, (250, 250, 250), 82341, 5, 0.6, 2.0
|
#mgv6_np_terrain_base = -4, 20, (250, 250, 250), 82341, 5, 0.6, 2.0
|
||||||
|
|
|
@ -2,6 +2,8 @@
|
||||||
Name=Minetest
|
Name=Minetest
|
||||||
GenericName=Minetest
|
GenericName=Minetest
|
||||||
Comment=Multiplayer infinite-world block sandbox
|
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
|
Exec=minetest
|
||||||
Icon=minetest-icon
|
Icon=minetest-icon
|
||||||
Terminal=false
|
Terminal=false
|
||||||
|
|
File diff suppressed because it is too large
Load Diff
|
@ -7,18 +7,18 @@ msgid ""
|
||||||
msgstr ""
|
msgstr ""
|
||||||
"Project-Id-Version: minetest\n"
|
"Project-Id-Version: minetest\n"
|
||||||
"Report-Msgid-Bugs-To: \n"
|
"Report-Msgid-Bugs-To: \n"
|
||||||
"POT-Creation-Date: 2014-12-13 15:24+0100\n"
|
"POT-Creation-Date: 2015-02-14 13:50+0100\n"
|
||||||
"PO-Revision-Date: 2015-01-19 09:56+0100\n"
|
"PO-Revision-Date: 2015-02-14 13:35+0100\n"
|
||||||
"Last-Translator: Diego de las Heras <diegodelasheras@gmail.com>\n"
|
"Last-Translator: Diego de las Heras <diegodelasheras@gmail.com>\n"
|
||||||
"Language-Team: LANGUAGE <LL@li.org>\n"
|
"Language-Team: \n"
|
||||||
"Language: es\n"
|
"Language: es\n"
|
||||||
"MIME-Version: 1.0\n"
|
"MIME-Version: 1.0\n"
|
||||||
"Content-Type: text/plain; charset=UTF-8\n"
|
"Content-Type: text/plain; charset=UTF-8\n"
|
||||||
"Content-Transfer-Encoding: 8bit\n"
|
"Content-Transfer-Encoding: 8bit\n"
|
||||||
"Plural-Forms: nplurals=2; plural=n != 1;\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"
|
msgid "Ok"
|
||||||
msgstr "Aceptar"
|
msgstr "Aceptar"
|
||||||
|
|
||||||
|
@ -40,7 +40,7 @@ msgstr "Ocultar contenido mp"
|
||||||
msgid "Mod:"
|
msgid "Mod:"
|
||||||
msgstr "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:"
|
msgid "Depends:"
|
||||||
msgstr "Dependencias:"
|
msgstr "Dependencias:"
|
||||||
|
|
||||||
|
@ -124,7 +124,7 @@ msgstr "¿Realmente desea borrar \"$1\"?"
|
||||||
|
|
||||||
#: builtin/mainmenu/dlg_delete_mod.lua:27
|
#: builtin/mainmenu/dlg_delete_mod.lua:27
|
||||||
#: builtin/mainmenu/dlg_delete_world.lua:25
|
#: builtin/mainmenu/dlg_delete_world.lua:25
|
||||||
#: builtin/mainmenu/tab_settings.lua:25
|
#: builtin/mainmenu/tab_settings.lua:79
|
||||||
msgid "Yes"
|
msgid "Yes"
|
||||||
msgstr "Sí"
|
msgstr "Sí"
|
||||||
|
|
||||||
|
@ -186,48 +186,40 @@ msgstr "Instalar mod: Imposible encontrar el nombre real del mod para: $1"
|
||||||
msgid "Unsorted"
|
msgid "Unsorted"
|
||||||
msgstr "Sin ordenar"
|
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"
|
msgid "Search"
|
||||||
msgstr "Buscar"
|
msgstr "Buscar"
|
||||||
|
|
||||||
#: builtin/mainmenu/store.lua:125
|
#: builtin/mainmenu/store.lua:126
|
||||||
msgid "Downloading"
|
msgid "Downloading $1, please wait..."
|
||||||
msgstr "Descargando"
|
msgstr "Descargando $1, por favor espere..."
|
||||||
|
|
||||||
#: builtin/mainmenu/store.lua:127
|
#: builtin/mainmenu/store.lua:160
|
||||||
msgid "please wait..."
|
|
||||||
msgstr "por favor espere..."
|
|
||||||
|
|
||||||
#: builtin/mainmenu/store.lua:159
|
|
||||||
msgid "Successfully installed:"
|
msgid "Successfully installed:"
|
||||||
msgstr "Instalado con éxito:"
|
msgstr "Instalado con éxito:"
|
||||||
|
|
||||||
#: builtin/mainmenu/store.lua:163
|
#: builtin/mainmenu/store.lua:162
|
||||||
msgid "Shortname:"
|
msgid "Shortname:"
|
||||||
msgstr "Nombre corto:"
|
msgstr "Nombre corto:"
|
||||||
|
|
||||||
#: builtin/mainmenu/store.lua:167 src/guiFormSpecMenu.cpp:2866
|
#: builtin/mainmenu/store.lua:472
|
||||||
msgid "ok"
|
|
||||||
msgstr "aceptar"
|
|
||||||
|
|
||||||
#: builtin/mainmenu/store.lua:476
|
|
||||||
msgid "Rating"
|
msgid "Rating"
|
||||||
msgstr "Clasificación"
|
msgstr "Clasificación"
|
||||||
|
|
||||||
#: builtin/mainmenu/store.lua:501
|
#: builtin/mainmenu/store.lua:497
|
||||||
msgid "re-Install"
|
msgid "re-Install"
|
||||||
msgstr "Reinstalar"
|
msgstr "Reinstalar"
|
||||||
|
|
||||||
#: builtin/mainmenu/store.lua:503
|
#: builtin/mainmenu/store.lua:499
|
||||||
msgid "Install"
|
msgid "Install"
|
||||||
msgstr "Instalar"
|
msgstr "Instalar"
|
||||||
|
|
||||||
# En el menú principal de mods pone repositorio no tienda.
|
# En el menú principal de mods pone repositorio no tienda.
|
||||||
#: builtin/mainmenu/store.lua:522
|
#: builtin/mainmenu/store.lua:518
|
||||||
msgid "Close store"
|
msgid "Close store"
|
||||||
msgstr "Cerrar repositorio"
|
msgstr "Cerrar repositorio"
|
||||||
|
|
||||||
#: builtin/mainmenu/store.lua:530
|
#: builtin/mainmenu/store.lua:526
|
||||||
msgid "Page $1 of $2"
|
msgid "Page $1 of $2"
|
||||||
msgstr "Página $1 de $2"
|
msgstr "Página $1 de $2"
|
||||||
|
|
||||||
|
@ -288,8 +280,7 @@ msgstr "Mods"
|
||||||
msgid "Address / Port :"
|
msgid "Address / Port :"
|
||||||
msgstr "Dirección / puerto:"
|
msgstr "Dirección / puerto:"
|
||||||
|
|
||||||
#: builtin/mainmenu/tab_multiplayer.lua:24 builtin/mainmenu/tab_server.lua:37
|
#: builtin/mainmenu/tab_multiplayer.lua:24
|
||||||
#: builtin/mainmenu/tab_simple_main.lua:25
|
|
||||||
msgid "Name / Password :"
|
msgid "Name / Password :"
|
||||||
msgstr "Nombre / contraseña:"
|
msgstr "Nombre / contraseña:"
|
||||||
|
|
||||||
|
@ -308,7 +299,22 @@ msgstr "Borrar"
|
||||||
msgid "Connect"
|
msgid "Connect"
|
||||||
msgstr "Conectar"
|
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"
|
msgid "Client"
|
||||||
msgstr "Cliente"
|
msgstr "Cliente"
|
||||||
|
|
||||||
|
@ -328,12 +334,12 @@ msgstr "Iniciar juego"
|
||||||
msgid "Select World:"
|
msgid "Select World:"
|
||||||
msgstr "Selecciona un mundo:"
|
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
|
#: builtin/mainmenu/tab_singleplayer.lua:90
|
||||||
msgid "Creative Mode"
|
msgid "Creative Mode"
|
||||||
msgstr "Modo creativo"
|
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
|
#: builtin/mainmenu/tab_singleplayer.lua:92
|
||||||
msgid "Enable Damage"
|
msgid "Enable Damage"
|
||||||
msgstr "Permitir daños"
|
msgstr "Permitir daños"
|
||||||
|
@ -342,6 +348,11 @@ msgstr "Permitir daños"
|
||||||
msgid "Public"
|
msgid "Public"
|
||||||
msgstr "Público"
|
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
|
#: builtin/mainmenu/tab_server.lua:45
|
||||||
msgid "Bind Address"
|
msgid "Bind Address"
|
||||||
msgstr "Asociar dirección"
|
msgstr "Asociar dirección"
|
||||||
|
@ -358,133 +369,151 @@ msgstr "Puerto del servidor:"
|
||||||
msgid "Server"
|
msgid "Server"
|
||||||
msgstr "Servidor"
|
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
|
#: 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?"
|
msgid "Are you sure to reset your singleplayer world?"
|
||||||
msgstr "¿Estás seguro de querer reiniciar el mundo de un jugador?"
|
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!!!"
|
msgid "No!!!"
|
||||||
msgstr "¡¡¡No!!!"
|
msgstr "¡¡¡No!!!"
|
||||||
|
|
||||||
#: builtin/mainmenu/tab_settings.lua:134
|
#: builtin/mainmenu/tab_settings.lua:181
|
||||||
msgid "Smooth Lighting"
|
msgid "Smooth Lighting"
|
||||||
msgstr "Iluminación suave"
|
msgstr "Iluminación suave"
|
||||||
|
|
||||||
#: builtin/mainmenu/tab_settings.lua:136
|
#: builtin/mainmenu/tab_settings.lua:183
|
||||||
msgid "Enable Particles"
|
msgid "Enable Particles"
|
||||||
msgstr "Habilitar partículas"
|
msgstr "Habilitar partículas"
|
||||||
|
|
||||||
#: builtin/mainmenu/tab_settings.lua:138
|
#: builtin/mainmenu/tab_settings.lua:185
|
||||||
msgid "3D Clouds"
|
msgid "3D Clouds"
|
||||||
msgstr "Nubes 3D"
|
msgstr "Nubes 3D"
|
||||||
|
|
||||||
#: builtin/mainmenu/tab_settings.lua:141
|
#: builtin/mainmenu/tab_settings.lua:187
|
||||||
msgid "Fancy Trees"
|
msgid "Fancy Trees"
|
||||||
msgstr "Árboles detallados"
|
msgstr "Árboles detallados"
|
||||||
|
|
||||||
#: builtin/mainmenu/tab_settings.lua:142
|
#: builtin/mainmenu/tab_settings.lua:189
|
||||||
msgid "Opaque Water"
|
msgid "Opaque Water"
|
||||||
msgstr "Agua opaca"
|
msgstr "Agua opaca"
|
||||||
|
|
||||||
#: builtin/mainmenu/tab_settings.lua:145
|
#: builtin/mainmenu/tab_settings.lua:191
|
||||||
msgid "Connected Glass"
|
msgid "Connected Glass"
|
||||||
msgstr "Vidrios conectados"
|
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"
|
msgid "Restart minetest for driver change to take effect"
|
||||||
msgstr "Reinicia minetest para que los cambios en el controlador tengan efecto"
|
msgstr "Reinicia minetest para que los cambios en el controlador tengan efecto"
|
||||||
|
|
||||||
#: builtin/mainmenu/tab_settings.lua:151
|
#: builtin/mainmenu/tab_settings.lua:207
|
||||||
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
|
|
||||||
msgid "Shaders"
|
msgid "Shaders"
|
||||||
msgstr "Sombreadores"
|
msgstr "Sombreadores"
|
||||||
|
|
||||||
#: builtin/mainmenu/tab_settings.lua:164
|
#: builtin/mainmenu/tab_settings.lua:212
|
||||||
msgid "Change keys"
|
msgid "Change keys"
|
||||||
msgstr "Configurar teclas"
|
msgstr "Configurar teclas"
|
||||||
|
|
||||||
#: builtin/mainmenu/tab_settings.lua:167
|
#: builtin/mainmenu/tab_settings.lua:215
|
||||||
msgid "Reset singleplayer world"
|
msgid "Reset singleplayer world"
|
||||||
msgstr "Reiniciar mundo de un jugador"
|
msgstr "Reiniciar mundo de un jugador"
|
||||||
|
|
||||||
#: builtin/mainmenu/tab_settings.lua:171
|
#: builtin/mainmenu/tab_settings.lua:219
|
||||||
msgid "GUI scale factor"
|
msgid "GUI scale factor"
|
||||||
msgstr "Factor de escala (GUI)"
|
msgstr "Factor de escala (GUI)"
|
||||||
|
|
||||||
#: builtin/mainmenu/tab_settings.lua:175
|
#: builtin/mainmenu/tab_settings.lua:223
|
||||||
msgid "Scaling factor applied to menu elements: "
|
msgid "Scaling factor applied to menu elements: "
|
||||||
msgstr "Factor de escala aplicado a los elementos del menú: "
|
msgstr "Factor de escala aplicado a los elementos del menú: "
|
||||||
|
|
||||||
#: builtin/mainmenu/tab_settings.lua:182
|
#: builtin/mainmenu/tab_settings.lua:229
|
||||||
#, fuzzy
|
|
||||||
msgid "Touch free target"
|
msgid "Touch free target"
|
||||||
msgstr "Tocar para interactuar"
|
msgstr "Tocar para interactuar"
|
||||||
|
|
||||||
#: builtin/mainmenu/tab_settings.lua:187
|
#: builtin/mainmenu/tab_settings.lua:235
|
||||||
msgid "Touchthreshold (px)"
|
msgid "Touchthreshold (px)"
|
||||||
msgstr "Umbral táctil (px)"
|
msgstr "Umbral táctil (px)"
|
||||||
|
|
||||||
#: builtin/mainmenu/tab_settings.lua:194 builtin/mainmenu/tab_settings.lua:208
|
#: builtin/mainmenu/tab_settings.lua:242 builtin/mainmenu/tab_settings.lua:256
|
||||||
#, fuzzy
|
|
||||||
msgid "Bumpmapping"
|
msgid "Bumpmapping"
|
||||||
msgstr "Mapeado de relieve"
|
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"
|
msgid "Generate Normalmaps"
|
||||||
msgstr "Generar mapas normales"
|
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"
|
msgid "Parallax Occlusion"
|
||||||
msgstr "Oclusión de paralaje"
|
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"
|
msgid "Waving Water"
|
||||||
msgstr "Oleaje en el agua"
|
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"
|
msgid "Waving Leaves"
|
||||||
msgstr "Movimiento de hojas"
|
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"
|
msgid "Waving Plants"
|
||||||
msgstr "Movimiento de plantas"
|
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."
|
msgid "To enable shaders the OpenGL driver needs to be used."
|
||||||
msgstr "Para habilitar los sombreadores debe utilizar el controlador OpenGL."
|
msgstr "Para habilitar los sombreadores debe utilizar el controlador OpenGL."
|
||||||
|
|
||||||
#: builtin/mainmenu/tab_settings.lua:330
|
#: builtin/mainmenu/tab_settings.lua:398
|
||||||
msgid "Settings"
|
msgid "Settings"
|
||||||
msgstr "Configuración"
|
msgstr "Configuración"
|
||||||
|
|
||||||
#: builtin/mainmenu/tab_simple_main.lua:67
|
#: builtin/mainmenu/tab_simple_main.lua:79
|
||||||
msgid "Fly mode"
|
msgid "Fly mode"
|
||||||
msgstr "Modo vuelo"
|
msgstr "Modo vuelo"
|
||||||
|
|
||||||
#: builtin/mainmenu/tab_simple_main.lua:71
|
#: builtin/mainmenu/tab_simple_main.lua:83
|
||||||
msgid "Start Singleplayer"
|
msgid "Start Singleplayer"
|
||||||
msgstr "Comenzar un jugador"
|
msgstr "Comenzar un jugador"
|
||||||
|
|
||||||
#: builtin/mainmenu/tab_simple_main.lua:72
|
#: builtin/mainmenu/tab_simple_main.lua:84
|
||||||
msgid "Config mods"
|
msgid "Config mods"
|
||||||
msgstr "Configurar mods"
|
msgstr "Configurar mods"
|
||||||
|
|
||||||
#: builtin/mainmenu/tab_simple_main.lua:191
|
#: builtin/mainmenu/tab_simple_main.lua:203
|
||||||
msgid "Main"
|
msgid "Main"
|
||||||
msgstr "Principal"
|
msgstr "Principal"
|
||||||
|
|
||||||
|
@ -509,39 +538,195 @@ msgstr "Sin información disponible"
|
||||||
msgid "Texturepacks"
|
msgid "Texturepacks"
|
||||||
msgstr "Texturas"
|
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..."
|
msgid "Item textures..."
|
||||||
msgstr "Texturas de objetos..."
|
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
|
#: src/fontengine.cpp:70 src/fontengine.cpp:226
|
||||||
msgid "needs_fallback_font"
|
msgid "needs_fallback_font"
|
||||||
msgstr "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"
|
msgid "Respawn"
|
||||||
msgstr "Revivir"
|
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..."
|
msgid "Item definitions..."
|
||||||
msgstr "Definiciones de objetos..."
|
msgstr "Definiciones de objetos..."
|
||||||
|
|
||||||
#: src/game.cpp:2255
|
#: src/game.cpp:2279
|
||||||
msgid "Node definitions..."
|
msgid "Node definitions..."
|
||||||
msgstr "Definiciones de nodos..."
|
msgstr "Definiciones de nodos..."
|
||||||
|
|
||||||
#: src/game.cpp:2262
|
#: src/game.cpp:2286
|
||||||
msgid "Media..."
|
msgid "Media..."
|
||||||
msgstr "Media..."
|
msgstr "Media..."
|
||||||
|
|
||||||
#: src/game.cpp:2267
|
#: src/game.cpp:2291
|
||||||
msgid " KB/s"
|
msgid " KB/s"
|
||||||
msgstr " KB/s"
|
msgstr " KB/s"
|
||||||
|
|
||||||
#: src/game.cpp:2271
|
#: src/game.cpp:2295
|
||||||
msgid " MB/s"
|
msgid " MB/s"
|
||||||
msgstr " MB/s"
|
msgstr " MB/s"
|
||||||
|
|
||||||
#: src/game.cpp:4220
|
#: src/game.cpp:4210
|
||||||
msgid ""
|
msgid ""
|
||||||
"\n"
|
"\n"
|
||||||
"Check debug.txt for details."
|
"Check debug.txt for details."
|
||||||
|
@ -549,14 +734,14 @@ msgstr ""
|
||||||
"\n"
|
"\n"
|
||||||
"Consulta debug.txt para obtener más detalles."
|
"Consulta debug.txt para obtener más detalles."
|
||||||
|
|
||||||
#: src/guiFormSpecMenu.cpp:2055
|
#: src/guiFormSpecMenu.cpp:2797
|
||||||
msgid "Proceed"
|
|
||||||
msgstr "Continuar"
|
|
||||||
|
|
||||||
#: src/guiFormSpecMenu.cpp:2846
|
|
||||||
msgid "Enter "
|
msgid "Enter "
|
||||||
msgstr "Ingresar "
|
msgstr "Ingresar "
|
||||||
|
|
||||||
|
#: src/guiFormSpecMenu.cpp:2817
|
||||||
|
msgid "ok"
|
||||||
|
msgstr "aceptar"
|
||||||
|
|
||||||
#: src/guiKeyChangeMenu.cpp:125
|
#: src/guiKeyChangeMenu.cpp:125
|
||||||
msgid "Keybindings. (If this menu screws up, remove stuff from minetest.conf)"
|
msgid "Keybindings. (If this menu screws up, remove stuff from minetest.conf)"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
@ -647,23 +832,23 @@ msgstr "Seleccionar distancia"
|
||||||
msgid "Print stacks"
|
msgid "Print stacks"
|
||||||
msgstr "Imprimir pilas"
|
msgstr "Imprimir pilas"
|
||||||
|
|
||||||
#: src/guiPasswordChange.cpp:106
|
#: src/guiPasswordChange.cpp:108
|
||||||
msgid "Old Password"
|
msgid "Old Password"
|
||||||
msgstr "Contraseña anterior"
|
msgstr "Contraseña anterior"
|
||||||
|
|
||||||
#: src/guiPasswordChange.cpp:122
|
#: src/guiPasswordChange.cpp:124
|
||||||
msgid "New Password"
|
msgid "New Password"
|
||||||
msgstr "Contraseña nueva"
|
msgstr "Contraseña nueva"
|
||||||
|
|
||||||
#: src/guiPasswordChange.cpp:137
|
#: src/guiPasswordChange.cpp:139
|
||||||
msgid "Confirm Password"
|
msgid "Confirm Password"
|
||||||
msgstr "Confirmar contraseña"
|
msgstr "Confirmar contraseña"
|
||||||
|
|
||||||
#: src/guiPasswordChange.cpp:153
|
#: src/guiPasswordChange.cpp:155
|
||||||
msgid "Change"
|
msgid "Change"
|
||||||
msgstr "Cambiar"
|
msgstr "Cambiar"
|
||||||
|
|
||||||
#: src/guiPasswordChange.cpp:162
|
#: src/guiPasswordChange.cpp:164
|
||||||
msgid "Passwords do not match!"
|
msgid "Passwords do not match!"
|
||||||
msgstr "¡Las contraseñas no coinciden!"
|
msgstr "¡Las contraseñas no coinciden!"
|
||||||
|
|
||||||
|
@ -963,210 +1148,3 @@ msgstr "PA1"
|
||||||
#: src/keycode.cpp:249
|
#: src/keycode.cpp:249
|
||||||
msgid "Zoom"
|
msgid "Zoom"
|
||||||
msgstr "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!"
|
|
||||||
|
|
|
@ -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 ""
|
msgid ""
|
||||||
msgstr ""
|
msgstr ""
|
||||||
"Project-Id-Version: minetest\n"
|
"Project-Id-Version: minetest\n"
|
||||||
"Report-Msgid-Bugs-To: \n"
|
"Report-Msgid-Bugs-To: \n"
|
||||||
"POT-Creation-Date: 2013-11-23 17:37+0100\n"
|
"POT-Creation-Date: 2015-02-14 23:12+0900\n"
|
||||||
"PO-Revision-Date: 2014-12-28 15:48+0900\n"
|
"PO-Revision-Date: 2015-02-22 10:57+0900\n"
|
||||||
"Last-Translator: Rui Takeda <mrrst0914@gmail.com>\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"
|
"MIME-Version: 1.0\n"
|
||||||
"Content-Type: text/plain; charset=UTF-8\n"
|
"Content-Type: text/plain; charset=UTF-8\n"
|
||||||
"Content-Transfer-Encoding: 8bit\n"
|
"Content-Transfer-Encoding: 8bit\n"
|
||||||
"Plural-Forms: nplurals=1; plural=0;\n"
|
"Plural-Forms: nplurals=1; plural=0;\n"
|
||||||
"X-Generator: Poedit 1.6.5\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"
|
msgid "Ok"
|
||||||
msgstr "決定"
|
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:"
|
msgid "World:"
|
||||||
msgstr "ワールド:"
|
msgstr "ワールド:"
|
||||||
|
|
||||||
msgid "Hide Game"
|
msgid "Hide Game"
|
||||||
msgstr "内部Mod"
|
msgstr "ゲームを隠す"
|
||||||
|
|
||||||
msgid "Hide mp content"
|
msgid "Hide mp content"
|
||||||
msgstr "Modパックの簡略化"
|
msgstr "Modパックの簡略化"
|
||||||
|
@ -247,6 +34,9 @@ msgstr "依存Mod:"
|
||||||
msgid "Save"
|
msgid "Save"
|
||||||
msgstr "保存"
|
msgstr "保存"
|
||||||
|
|
||||||
|
msgid "Cancel"
|
||||||
|
msgstr "キャンセル"
|
||||||
|
|
||||||
msgid "Enable MP"
|
msgid "Enable MP"
|
||||||
msgstr "有効化"
|
msgstr "有効化"
|
||||||
|
|
||||||
|
@ -257,22 +47,103 @@ msgid "enabled"
|
||||||
msgstr "有効化"
|
msgstr "有効化"
|
||||||
|
|
||||||
msgid "Enable all"
|
msgid "Enable all"
|
||||||
msgstr "全て有効化"
|
msgstr "すべて有効化"
|
||||||
|
|
||||||
msgid "Modmgr: failed to delete \"$1\""
|
msgid "World name"
|
||||||
msgstr "Modmgr: \"$1\"の削除に失敗しました"
|
msgstr "ワールド名"
|
||||||
|
|
||||||
msgid "Modmgr: invalid modpath \"$1\""
|
msgid "Seed"
|
||||||
msgstr "Modmgr: \"$1\"は無効なModパスです"
|
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\"?"
|
msgid "Are you sure you want to delete \"$1\"?"
|
||||||
msgstr "\"$1\"を削除してよろしいですか?"
|
msgstr "本当に\"$1\"を削除してよろしいですか?"
|
||||||
|
|
||||||
|
msgid "Yes"
|
||||||
|
msgstr "はい"
|
||||||
|
|
||||||
msgid "No of course not!"
|
msgid "No of course not!"
|
||||||
msgstr "違います!"
|
msgstr "いいえ"
|
||||||
|
|
||||||
msgid "Page $1 of $2"
|
msgid "Modmgr: failed to delete \"$1\""
|
||||||
msgstr "ページ $1/$2"
|
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"
|
msgid "Rating"
|
||||||
msgstr "評価"
|
msgstr "評価"
|
||||||
|
@ -283,63 +154,415 @@ msgstr "再インストール"
|
||||||
msgid "Install"
|
msgid "Install"
|
||||||
msgstr "インストール"
|
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..."
|
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..."
|
msgid "Loading..."
|
||||||
msgstr "ロード中..."
|
msgstr "読み込み中..."
|
||||||
|
|
||||||
msgid "Creating server..."
|
msgid "Creating server..."
|
||||||
msgstr "サーバー構築中..."
|
msgstr "サーバー作成中..."
|
||||||
|
|
||||||
msgid "Creating client..."
|
msgid "Creating client..."
|
||||||
msgstr "クライアント作成中..."
|
msgstr "クライアント作成中..."
|
||||||
|
|
||||||
msgid "Resolving address..."
|
msgid "Resolving address..."
|
||||||
msgstr "アドレス解決中..."
|
msgstr "アドレス解決中..."
|
||||||
|
|
||||||
msgid "Connecting to server..."
|
msgid "Connecting to server..."
|
||||||
msgstr "サーバー接続中..."
|
msgstr "サーバー接続中..."
|
||||||
|
|
||||||
msgid "Item definitions..."
|
msgid "Item definitions..."
|
||||||
msgstr "アイテム定義中..."
|
msgstr "アイテム定義中..."
|
||||||
|
|
||||||
msgid "Node definitions..."
|
msgid "Node definitions..."
|
||||||
msgstr "ノード定義中..."
|
msgstr "ノード定義中..."
|
||||||
|
|
||||||
msgid "Media..."
|
msgid "Media..."
|
||||||
msgstr "..."
|
msgstr "..."
|
||||||
|
|
||||||
msgid "Shutting down..."
|
msgid " KB/s"
|
||||||
msgstr "終了中..."
|
msgstr " KB/秒"
|
||||||
|
|
||||||
|
msgid " MB/s"
|
||||||
|
msgstr " MB/秒"
|
||||||
|
|
||||||
msgid ""
|
msgid ""
|
||||||
"\n"
|
"\n"
|
||||||
"Check debug.txt for details."
|
"Check debug.txt for details."
|
||||||
msgstr ""
|
msgstr ""
|
||||||
"\n"
|
"\n"
|
||||||
"詳細はdebug.txtを御覧ください。"
|
"詳細はdebug.txtをご覧ください。"
|
||||||
|
|
||||||
msgid "You died."
|
msgid "Enter "
|
||||||
msgstr "You died!"
|
msgstr "Enter"
|
||||||
|
|
||||||
msgid "Respawn"
|
msgid "ok"
|
||||||
msgstr "Respawn"
|
|
||||||
|
|
||||||
msgid "Proceed"
|
|
||||||
msgstr "決定"
|
msgstr "決定"
|
||||||
|
|
||||||
msgid "Keybindings. (If this menu screws up, remove stuff from minetest.conf)"
|
msgid "Keybindings. (If this menu screws up, remove stuff from minetest.conf)"
|
||||||
msgstr "キーバインド"
|
msgstr "操作の設定を変更します。"
|
||||||
|
|
||||||
msgid "\"Use\" = climb down"
|
msgid "\"Use\" = climb down"
|
||||||
msgstr "「使う」キーで降りる"
|
msgstr "「使用」で降りる"
|
||||||
|
|
||||||
msgid "Double tap \"jump\" to toggle fly"
|
msgid "Double tap \"jump\" to toggle fly"
|
||||||
msgstr "ジャンプの二回押しで飛行"
|
msgstr "「ジャンプ」二回押しで飛行モード"
|
||||||
|
|
||||||
msgid "Key already in use"
|
msgid "Key already in use"
|
||||||
msgstr "既に使われているキーです"
|
msgstr "すでに使われているキーです。"
|
||||||
|
|
||||||
msgid "press key"
|
msgid "press key"
|
||||||
msgstr "キー入力待ち"
|
msgstr "キー入力待ち"
|
||||||
|
@ -351,19 +574,19 @@ msgid "Backward"
|
||||||
msgstr "後退"
|
msgstr "後退"
|
||||||
|
|
||||||
msgid "Left"
|
msgid "Left"
|
||||||
msgstr "左へ進む"
|
msgstr "左に進む"
|
||||||
|
|
||||||
msgid "Right"
|
msgid "Right"
|
||||||
msgstr "右へ進む"
|
msgstr "右に進む"
|
||||||
|
|
||||||
msgid "Use"
|
msgid "Use"
|
||||||
msgstr "使う"
|
msgstr "使用"
|
||||||
|
|
||||||
msgid "Jump"
|
msgid "Jump"
|
||||||
msgstr "ジャンプ"
|
msgstr "ジャンプ"
|
||||||
|
|
||||||
msgid "Sneak"
|
msgid "Sneak"
|
||||||
msgstr "こっそり進む"
|
msgstr "スニーク"
|
||||||
|
|
||||||
msgid "Drop"
|
msgid "Drop"
|
||||||
msgstr "落とす"
|
msgstr "落とす"
|
||||||
|
@ -381,16 +604,16 @@ msgid "Console"
|
||||||
msgstr "コンソール"
|
msgstr "コンソール"
|
||||||
|
|
||||||
msgid "Toggle fly"
|
msgid "Toggle fly"
|
||||||
msgstr "飛行"
|
msgstr "飛行モード"
|
||||||
|
|
||||||
msgid "Toggle fast"
|
msgid "Toggle fast"
|
||||||
msgstr "高速移動"
|
msgstr "高速移動モード"
|
||||||
|
|
||||||
msgid "Toggle noclip"
|
msgid "Toggle noclip"
|
||||||
msgstr "すり抜け"
|
msgstr "すり抜けモード"
|
||||||
|
|
||||||
msgid "Range select"
|
msgid "Range select"
|
||||||
msgstr "視野切り替え"
|
msgstr "視野範囲変更"
|
||||||
|
|
||||||
msgid "Print stacks"
|
msgid "Print stacks"
|
||||||
msgstr "スタックの表示"
|
msgstr "スタックの表示"
|
||||||
|
@ -408,53 +631,13 @@ msgid "Change"
|
||||||
msgstr "変更"
|
msgstr "変更"
|
||||||
|
|
||||||
msgid "Passwords do not match!"
|
msgid "Passwords do not match!"
|
||||||
msgstr "パスワードが一致しません!"
|
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"
|
|
||||||
|
|
||||||
msgid "Sound Volume: "
|
msgid "Sound Volume: "
|
||||||
msgstr "音量"
|
msgstr "音量:"
|
||||||
|
|
||||||
msgid "Exit"
|
msgid "Exit"
|
||||||
msgstr "戻る"
|
msgstr "閉じる"
|
||||||
|
|
||||||
msgid "Left Button"
|
msgid "Left Button"
|
||||||
msgstr "左ボタン"
|
msgstr "左ボタン"
|
||||||
|
@ -671,56 +854,3 @@ msgstr "PA1"
|
||||||
|
|
||||||
msgid "Zoom"
|
msgid "Zoom"
|
||||||
msgstr "ズーム"
|
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 "操作変更"
|
|
||||||
|
|
File diff suppressed because it is too large
Load Diff
|
@ -355,9 +355,12 @@ add_subdirectory(jthread)
|
||||||
add_subdirectory(script)
|
add_subdirectory(script)
|
||||||
add_subdirectory(util)
|
add_subdirectory(util)
|
||||||
|
|
||||||
|
set (unittests_SRCS
|
||||||
|
test.cpp
|
||||||
|
)
|
||||||
|
|
||||||
set(common_SRCS
|
set(common_SRCS
|
||||||
ban.cpp
|
ban.cpp
|
||||||
base64.cpp
|
|
||||||
cavegen.cpp
|
cavegen.cpp
|
||||||
clientiface.cpp
|
clientiface.cpp
|
||||||
collision.cpp
|
collision.cpp
|
||||||
|
@ -418,12 +421,10 @@ set(common_SRCS
|
||||||
serverlist.cpp
|
serverlist.cpp
|
||||||
serverobject.cpp
|
serverobject.cpp
|
||||||
settings.cpp
|
settings.cpp
|
||||||
sha1.cpp
|
|
||||||
socket.cpp
|
socket.cpp
|
||||||
sound.cpp
|
sound.cpp
|
||||||
staticobject.cpp
|
staticobject.cpp
|
||||||
subgame.cpp
|
subgame.cpp
|
||||||
test.cpp
|
|
||||||
tool.cpp
|
tool.cpp
|
||||||
treegen.cpp
|
treegen.cpp
|
||||||
version.cpp
|
version.cpp
|
||||||
|
@ -432,6 +433,7 @@ set(common_SRCS
|
||||||
${JTHREAD_SRCS}
|
${JTHREAD_SRCS}
|
||||||
${common_SCRIPT_SRCS}
|
${common_SCRIPT_SRCS}
|
||||||
${UTIL_SRCS}
|
${UTIL_SRCS}
|
||||||
|
${unittests_SRCS}
|
||||||
)
|
)
|
||||||
|
|
||||||
# This gives us the icon and file version information
|
# This gives us the icon and file version information
|
||||||
|
|
|
@ -23,7 +23,22 @@ with this program; if not, write to the Free Software Foundation, Inc.,
|
||||||
#include "irr_aabb3d.h"
|
#include "irr_aabb3d.h"
|
||||||
#include <string>
|
#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
|
// Other types are defined in content_object.h
|
||||||
|
|
||||||
struct ActiveObjectMessage
|
struct ActiveObjectMessage
|
||||||
|
@ -60,7 +75,7 @@ public:
|
||||||
m_id = id;
|
m_id = id;
|
||||||
}
|
}
|
||||||
|
|
||||||
virtual u8 getType() const = 0;
|
virtual ActiveObjectType getType() const = 0;
|
||||||
virtual bool getCollisionBox(aabb3f *toset) = 0;
|
virtual bool getCollisionBox(aabb3f *toset) = 0;
|
||||||
virtual bool collideWithObjects() = 0;
|
virtual bool collideWithObjects() = 0;
|
||||||
protected:
|
protected:
|
||||||
|
|
470
src/cavegen.cpp
470
src/cavegen.cpp
|
@ -20,6 +20,7 @@ with this program; if not, write to the Free Software Foundation, Inc.,
|
||||||
#include "util/numeric.h"
|
#include "util/numeric.h"
|
||||||
#include "map.h"
|
#include "map.h"
|
||||||
#include "mapgen.h"
|
#include "mapgen.h"
|
||||||
|
#include "mapgen_v5.h"
|
||||||
#include "mapgen_v6.h"
|
#include "mapgen_v6.h"
|
||||||
#include "mapgen_v7.h"
|
#include "mapgen_v7.h"
|
||||||
#include "cavegen.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);
|
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) {
|
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 min_d = min_tunnel_diameter;
|
||||||
s16 max_d = max_tunnel_diameter;
|
s16 max_d = max_tunnel_diameter;
|
||||||
rs = ps->range(min_d, max_d);
|
rs = ps->range(min_d, max_d);
|
||||||
|
s16 rs_part_max_length_rs = rs * part_max_length_rs;
|
||||||
|
|
||||||
v3s16 maxlen;
|
v3s16 maxlen;
|
||||||
if (large_cave) {
|
if (large_cave) {
|
||||||
maxlen = v3s16(
|
maxlen = v3s16(
|
||||||
rs * part_max_length_rs,
|
rs_part_max_length_rs,
|
||||||
rs * part_max_length_rs / 2,
|
rs_part_max_length_rs / 2,
|
||||||
rs * part_max_length_rs
|
rs_part_max_length_rs
|
||||||
);
|
);
|
||||||
} else {
|
} else {
|
||||||
maxlen = v3s16(
|
maxlen = v3s16(
|
||||||
rs * part_max_length_rs,
|
rs_part_max_length_rs,
|
||||||
ps->range(1, rs * part_max_length_rs),
|
ps->range(1, rs_part_max_length_rs),
|
||||||
rs * part_max_length_rs
|
rs_part_max_length_rs
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
v3f vec(
|
v3f vec(
|
||||||
(float)(ps->next() % (maxlen.X * 1)) - (float)maxlen.X / 2,
|
(float)(ps->next() % maxlen.X) - (float)maxlen.X / 2,
|
||||||
(float)(ps->next() % (maxlen.Y * 1)) - (float)maxlen.Y / 2,
|
(float)(ps->next() % maxlen.Y) - (float)maxlen.Y / 2,
|
||||||
(float)(ps->next() % (maxlen.Z * 1)) - (float)maxlen.Z / 2
|
(float)(ps->next() % maxlen.Z) - (float)maxlen.Z / 2
|
||||||
);
|
);
|
||||||
|
|
||||||
// Jump downward sometimes
|
// Jump downward sometimes
|
||||||
if (!large_cave && ps->range(0, 12) == 0) {
|
if (!large_cave && ps->range(0, 12) == 0) {
|
||||||
vec = v3f(
|
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.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;
|
vec += main_direction;
|
||||||
|
|
||||||
v3f rp = orp + vec;
|
v3f rp = orp + vec;
|
||||||
|
@ -279,12 +567,12 @@ void CaveV6::carveRoute(v3f vec, float f, bool randomize_xz) {
|
||||||
|
|
||||||
///////////////////////////////////////// Caves V7
|
///////////////////////////////////////// Caves V7
|
||||||
|
|
||||||
CaveV7::CaveV7(MapgenV7 *mg, PseudoRandom *ps, bool is_large_cave) {
|
|
||||||
|
CaveV7::CaveV7(MapgenV7 *mg, PseudoRandom *ps) {
|
||||||
this->mg = mg;
|
this->mg = mg;
|
||||||
this->vm = mg->vm;
|
this->vm = mg->vm;
|
||||||
this->ndef = mg->ndef;
|
this->ndef = mg->ndef;
|
||||||
this->water_level = mg->water_level;
|
this->water_level = mg->water_level;
|
||||||
this->large_cave = is_large_cave;
|
|
||||||
this->ps = ps;
|
this->ps = ps;
|
||||||
this->c_water_source = mg->c_water_source;
|
this->c_water_source = mg->c_water_source;
|
||||||
this->c_lava_source = mg->c_lava_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);
|
dswitchint = ps->range(1, 14);
|
||||||
flooded = ps->range(1, 2) == 2;
|
flooded = ps->range(1, 2) == 2;
|
||||||
|
|
||||||
if (large_cave) {
|
part_max_length_rs = ps->range(2, 4);
|
||||||
part_max_length_rs = ps->range(2, 4);
|
tunnel_routepoints = ps->range(5, ps->range(15, 30));
|
||||||
tunnel_routepoints = ps->range(5, ps->range(15, 30));
|
min_tunnel_diameter = 5;
|
||||||
min_tunnel_diameter = 5;
|
max_tunnel_diameter = ps->range(7, ps->range(8, 24));
|
||||||
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);
|
|
||||||
}
|
|
||||||
|
|
||||||
large_cave_is_flat = (ps->range(0, 1) == 0);
|
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
|
// Limit maximum to area
|
||||||
route_y_max = rangelim(route_y_max, 0, ar.Y - 1);
|
route_y_max = rangelim(route_y_max, 0, ar.Y - 1);
|
||||||
|
|
||||||
if (large_cave) {
|
s16 min = 0;
|
||||||
s16 min = 0;
|
if (node_min.Y < water_level && node_max.Y > water_level) {
|
||||||
if (node_min.Y < water_level && node_max.Y > water_level) {
|
min = water_level - max_tunnel_diameter/3 - of.Y;
|
||||||
min = water_level - max_tunnel_diameter/3 - of.Y;
|
route_y_max = 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);
|
|
||||||
}
|
}
|
||||||
|
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_min = route_y_min;
|
||||||
s16 route_start_y_max = route_y_max;
|
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
|
// Add generation notify begin event
|
||||||
v3s16 abs_pos(of.X + orp.X, of.Y + orp.Y, of.Z + orp.Z);
|
v3s16 abs_pos(of.X + orp.X, of.Y + orp.Y, of.Z + orp.Z);
|
||||||
GenNotifyType notifytype = large_cave ?
|
GenNotifyType notifytype = GENNOTIFY_LARGECAVE_BEGIN;
|
||||||
GENNOTIFY_LARGECAVE_BEGIN : GENNOTIFY_CAVE_BEGIN;
|
|
||||||
mg->gennotify.addEvent(notifytype, abs_pos);
|
mg->gennotify.addEvent(notifytype, abs_pos);
|
||||||
|
|
||||||
// Generate some tunnel starting from orp
|
// 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
|
// Add generation notify end event
|
||||||
abs_pos = v3s16(of.X + orp.X, of.Y + orp.Y, of.Z + orp.Z);
|
abs_pos = v3s16(of.X + orp.X, of.Y + orp.Y, of.Z + orp.Z);
|
||||||
notifytype = large_cave ?
|
notifytype = GENNOTIFY_LARGECAVE_END;
|
||||||
GENNOTIFY_LARGECAVE_END : GENNOTIFY_CAVE_END;
|
|
||||||
mg->gennotify.addEvent(notifytype, abs_pos);
|
mg->gennotify.addEvent(notifytype, abs_pos);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
void CaveV7::makeTunnel(bool dirswitch) {
|
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
|
// Randomize size
|
||||||
s16 min_d = min_tunnel_diameter;
|
s16 min_d = min_tunnel_diameter;
|
||||||
s16 max_d = max_tunnel_diameter;
|
s16 max_d = max_tunnel_diameter;
|
||||||
rs = ps->range(min_d, max_d);
|
rs = ps->range(min_d, max_d);
|
||||||
|
s16 rs_part_max_length_rs = rs * part_max_length_rs;
|
||||||
|
|
||||||
v3s16 maxlen;
|
v3s16 maxlen;
|
||||||
if (large_cave) {
|
maxlen = v3s16(
|
||||||
maxlen = v3s16(
|
rs_part_max_length_rs,
|
||||||
rs * part_max_length_rs,
|
rs_part_max_length_rs / 2,
|
||||||
rs * part_max_length_rs / 2,
|
rs_part_max_length_rs
|
||||||
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
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
v3f vec;
|
v3f vec;
|
||||||
// Jump downward sometimes
|
// Jump downward sometimes
|
||||||
if (!large_cave && ps->range(0, 12) == 0) {
|
vec = v3f(
|
||||||
vec = v3f(
|
(float)(ps->next() % maxlen.X) - (float)maxlen.X / 2,
|
||||||
(float)(ps->next() % (maxlen.X * 1)) - (float)maxlen.X / 2,
|
(float)(ps->next() % maxlen.Y) - (float)maxlen.Y / 2,
|
||||||
(float)(ps->next() % (maxlen.Y * 2)) - (float)maxlen.Y,
|
(float)(ps->next() % maxlen.Z) - (float)maxlen.Z / 2
|
||||||
(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
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
// Do not make large caves that are above ground.
|
// Do not make large caves that are above ground.
|
||||||
// It is only necessary to check the startpoint and endpoint.
|
// It is only necessary to check the startpoint and endpoint.
|
||||||
if (large_cave) {
|
v3s16 orpi(orp.X, orp.Y, orp.Z);
|
||||||
v3s16 orpi(orp.X, orp.Y, orp.Z);
|
v3s16 veci(vec.X, vec.Y, vec.Z);
|
||||||
v3s16 veci(vec.X, vec.Y, vec.Z);
|
v3s16 p;
|
||||||
v3s16 p;
|
|
||||||
|
|
||||||
p = orpi + veci + of + rs / 2;
|
p = orpi + veci + of + rs / 2;
|
||||||
if (p.Z >= node_min.Z && p.Z <= node_max.Z &&
|
if (p.Z >= node_min.Z && p.Z <= node_max.Z &&
|
||||||
p.X >= node_min.X && p.X <= node_max.X) {
|
p.X >= node_min.X && p.X <= node_max.X) {
|
||||||
u32 index = (p.Z - node_min.Z) * mg->ystride + (p.X - node_min.X);
|
u32 index = (p.Z - node_min.Z) * mg->ystride + (p.X - node_min.X);
|
||||||
s16 h = mg->ridge_heightmap[index];
|
s16 h = mg->ridge_heightmap[index];
|
||||||
if (h < p.Y)
|
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;
|
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;
|
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,
|
float nval = NoisePerlin3D(np_caveliquids, startp.X,
|
||||||
startp.Y, startp.Z, mg->seed);
|
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;
|
v3f fp = orp + vec * f;
|
||||||
fp.X += 0.1 * ps->range(-10, 10);
|
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);
|
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;
|
bool should_make_cave_hole = ps->range(1, 10) == 1;
|
||||||
|
|
||||||
for (s16 z0 = d0; z0 <= d1; z0++) {
|
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);
|
rs / 2 - MYMAX(0, maxabsxz - rs / 7 - 1);
|
||||||
|
|
||||||
for (s16 y0 = -si2; y0 <= si2; y0++) {
|
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) {
|
if (large_cave_is_flat) {
|
||||||
// Make large caves not so tall
|
// Make large caves not so tall
|
||||||
if (rs > 7 && abs(y0) >= rs / 3)
|
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)
|
c == c_water_source || c == c_lava_source || c == c_ice)
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
if (large_cave) {
|
int full_ymin = node_min.Y - MAP_BLOCKSIZE;
|
||||||
int full_ymin = node_min.Y - MAP_BLOCKSIZE;
|
int full_ymax = node_max.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;
|
|
||||||
|
|
||||||
|
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_data[i] = airnode;
|
||||||
vm->m_flags[i] |= VMANIP_FLAG_CAVE;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -22,9 +22,55 @@ with this program; if not, write to the Free Software Foundation, Inc.,
|
||||||
|
|
||||||
#define VMANIP_FLAG_CAVE VOXELFLAG_CHECKED1
|
#define VMANIP_FLAG_CAVE VOXELFLAG_CHECKED1
|
||||||
|
|
||||||
|
class MapgenV5;
|
||||||
class MapgenV6;
|
class MapgenV6;
|
||||||
class MapgenV7;
|
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 {
|
class CaveV6 {
|
||||||
public:
|
public:
|
||||||
MapgenV6 *mg;
|
MapgenV6 *mg;
|
||||||
|
@ -83,7 +129,6 @@ public:
|
||||||
int dswitchint;
|
int dswitchint;
|
||||||
int part_max_length_rs;
|
int part_max_length_rs;
|
||||||
|
|
||||||
bool large_cave;
|
|
||||||
bool large_cave_is_flat;
|
bool large_cave_is_flat;
|
||||||
bool flooded;
|
bool flooded;
|
||||||
|
|
||||||
|
@ -109,7 +154,7 @@ public:
|
||||||
int water_level;
|
int water_level;
|
||||||
|
|
||||||
CaveV7() {}
|
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 makeCave(v3s16 nmin, v3s16 nmax, int max_stone_height);
|
||||||
void makeTunnel(bool dirswitch);
|
void makeTunnel(bool dirswitch);
|
||||||
void carveRoute(v3f vec, float f, bool randomize_xz, bool is_ravine);
|
void carveRoute(v3f vec, float f, bool randomize_xz, bool is_ravine);
|
||||||
|
|
|
@ -29,6 +29,7 @@
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#include <irrlicht.h>
|
#include <irrlicht.h>
|
||||||
|
#include <iostream>
|
||||||
#include "CGUITTFont.h"
|
#include "CGUITTFont.h"
|
||||||
|
|
||||||
namespace irr
|
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
|
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.
|
// Determine what our texture size should be.
|
||||||
// Add 1 because textures are inclusive-exclusive.
|
// Add 1 because textures are inclusive-exclusive.
|
||||||
core::dimension2du d(bits.width + 1, bits.rows + 1);
|
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);
|
const u32 image_pitch = image->getPitch() / sizeof(u16);
|
||||||
u16* image_data = (u16*)image->lock();
|
u16* image_data = (u16*)image->lock();
|
||||||
u8* glyph_data = bits.buffer;
|
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;
|
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.
|
// 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.
|
// 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);
|
const u32 image_pitch = image->getPitch() / sizeof(u32);
|
||||||
u32* image_data = (u32*)image->lock();
|
u32* image_data = (u32*)image->lock();
|
||||||
u8* glyph_data = bits.buffer;
|
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;
|
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;
|
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);
|
//data[y * image_pitch + x] |= ((u32)(*bitsdata++) << 24);
|
||||||
|
|
|
@ -45,7 +45,7 @@
|
||||||
#define __BYTE_ORDER 0
|
#define __BYTE_ORDER 0
|
||||||
#define __LITTLE_ENDIAN 0
|
#define __LITTLE_ENDIAN 0
|
||||||
#define __BIG_ENDIAN 1
|
#define __BIG_ENDIAN 1
|
||||||
#elif __MACH__
|
#elif defined(__MACH__) && defined(__APPLE__)
|
||||||
#include <machine/endian.h>
|
#include <machine/endian.h>
|
||||||
#elif defined(__FreeBSD__)
|
#elif defined(__FreeBSD__)
|
||||||
#include <sys/endian.h>
|
#include <sys/endian.h>
|
||||||
|
|
|
@ -43,7 +43,7 @@ with this program; if not, write to the Free Software Foundation, Inc.,
|
||||||
#include "nodedef.h"
|
#include "nodedef.h"
|
||||||
#include "itemdef.h"
|
#include "itemdef.h"
|
||||||
#include "shader.h"
|
#include "shader.h"
|
||||||
#include "base64.h"
|
#include "util/base64.h"
|
||||||
#include "clientmap.h"
|
#include "clientmap.h"
|
||||||
#include "clientmedia.h"
|
#include "clientmedia.h"
|
||||||
#include "sound.h"
|
#include "sound.h"
|
||||||
|
@ -52,10 +52,8 @@ with this program; if not, write to the Free Software Foundation, Inc.,
|
||||||
#include "config.h"
|
#include "config.h"
|
||||||
#include "version.h"
|
#include "version.h"
|
||||||
#include "drawscene.h"
|
#include "drawscene.h"
|
||||||
#include "subgame.h"
|
|
||||||
#include "server.h"
|
|
||||||
#include "database.h"
|
|
||||||
#include "database-sqlite3.h"
|
#include "database-sqlite3.h"
|
||||||
|
#include "serialization.h"
|
||||||
|
|
||||||
extern gui::IGUIEnvironment* guienv;
|
extern gui::IGUIEnvironment* guienv;
|
||||||
|
|
||||||
|
@ -271,28 +269,26 @@ Client::Client(
|
||||||
m_time_of_day_update_timer(0),
|
m_time_of_day_update_timer(0),
|
||||||
m_recommended_send_interval(0.1),
|
m_recommended_send_interval(0.1),
|
||||||
m_removed_sounds_check_timer(0),
|
m_removed_sounds_check_timer(0),
|
||||||
m_state(LC_Created)
|
m_state(LC_Created),
|
||||||
|
m_localdb(NULL)
|
||||||
{
|
{
|
||||||
/*
|
// Add local player
|
||||||
Add local player
|
m_env.addPlayer(new LocalPlayer(this, playername));
|
||||||
*/
|
|
||||||
{
|
|
||||||
Player *player = 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_smooth_lighting = g_settings->getBool("smooth_lighting");
|
||||||
|
m_cache_enable_shaders = g_settings->getBool("enable_shaders");
|
||||||
}
|
}
|
||||||
|
|
||||||
void Client::Stop()
|
void Client::Stop()
|
||||||
{
|
{
|
||||||
//request all client managed threads to stop
|
//request all client managed threads to stop
|
||||||
m_mesh_update_thread.Stop();
|
m_mesh_update_thread.Stop();
|
||||||
if (localdb != NULL) {
|
// Save local server map
|
||||||
actionstream << "Local map saving ended" << std::endl;
|
if (m_localdb) {
|
||||||
localdb->endSave();
|
infostream << "Local map saving ended." << std::endl;
|
||||||
delete localserver;
|
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))
|
if(m_map_timer_and_unload_interval.step(dtime, map_timer_and_unload_dtime))
|
||||||
{
|
{
|
||||||
ScopeProfiler sp(g_profiler, "Client: map timer and unload");
|
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,
|
m_env.getMap().timerUpdate(map_timer_and_unload_dtime,
|
||||||
g_settings->getFloat("client_unload_unused_data_timeout"),
|
g_settings->getFloat("client_unload_unused_data_timeout"),
|
||||||
&deleted_blocks);
|
&deleted_blocks);
|
||||||
|
@ -549,8 +545,8 @@ void Client::step(float dtime)
|
||||||
NOTE: This loop is intentionally iterated the way it is.
|
NOTE: This loop is intentionally iterated the way it is.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
std::list<v3s16>::iterator i = deleted_blocks.begin();
|
std::vector<v3s16>::iterator i = deleted_blocks.begin();
|
||||||
std::list<v3s16> sendlist;
|
std::vector<v3s16> sendlist;
|
||||||
for(;;)
|
for(;;)
|
||||||
{
|
{
|
||||||
if(sendlist.size() == 255 || i == deleted_blocks.end())
|
if(sendlist.size() == 255 || i == deleted_blocks.end())
|
||||||
|
@ -569,7 +565,7 @@ void Client::step(float dtime)
|
||||||
writeU16(&reply[0], TOSERVER_DELETEDBLOCKS);
|
writeU16(&reply[0], TOSERVER_DELETEDBLOCKS);
|
||||||
reply[2] = sendlist.size();
|
reply[2] = sendlist.size();
|
||||||
u32 k = 0;
|
u32 k = 0;
|
||||||
for(std::list<v3s16>::iterator
|
for(std::vector<v3s16>::iterator
|
||||||
j = sendlist.begin();
|
j = sendlist.begin();
|
||||||
j != sendlist.end(); ++j)
|
j != sendlist.end(); ++j)
|
||||||
{
|
{
|
||||||
|
@ -807,6 +803,13 @@ void Client::step(float dtime)
|
||||||
Send(1, data, true);
|
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)
|
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
|
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);
|
std::ostringstream os(std::ios_base::binary);
|
||||||
writeU16(os, TOSERVER_REQUEST_MEDIA);
|
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);
|
assert(file_requests_size <= 0xFFFF);
|
||||||
writeU16(os, (u16) (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) {
|
i != file_requests.end(); ++i) {
|
||||||
os<<serializeString(*i);
|
os<<serializeString(*i);
|
||||||
}
|
}
|
||||||
|
@ -945,34 +948,19 @@ void Client::initLocalMapSaving(const Address &address,
|
||||||
const std::string &hostname,
|
const std::string &hostname,
|
||||||
bool is_local_server)
|
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;
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
const std::string world_path = porting::path_user
|
const std::string world_path = porting::path_user
|
||||||
+ DIR_DELIM + "worlds"
|
+ DIR_DELIM + "worlds"
|
||||||
+ DIR_DELIM + "server_"
|
+ DIR_DELIM + "server_"
|
||||||
+ hostname + "_" + to_string(address.getPort());
|
+ hostname + "_" + to_string(address.getPort());
|
||||||
|
|
||||||
SubgameSpec gamespec;
|
fs::CreateAllDirs(world_path);
|
||||||
|
|
||||||
if (!getWorldExists(world_path)) {
|
m_localdb = new Database_SQLite3(world_path);
|
||||||
gamespec = findSubgame(g_settings->get("default_game"));
|
m_localdb->beginSave();
|
||||||
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();
|
|
||||||
actionstream << "Local map saving started, map will be saved at '" << world_path << "'" << std::endl;
|
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);
|
sector->insertBlock(block);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (localdb != NULL) {
|
if (m_localdb) {
|
||||||
((ServerMap&) localserver->getMap()).saveBlock(block, 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
|
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");
|
//TimeTaker timer("data fill");
|
||||||
|
@ -2807,7 +2795,8 @@ void Client::makeScreenshot(IrrlichtDevice *device)
|
||||||
if (image) {
|
if (image) {
|
||||||
raw_image->copyTo(image);
|
raw_image->copyTo(image);
|
||||||
irr::c8 filename[256];
|
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(),
|
g_settings->get("screenshot_path").c_str(),
|
||||||
device->getTimer()->getRealTime());
|
device->getTimer()->getRealTime());
|
||||||
std::ostringstream sstr;
|
std::ostringstream sstr;
|
||||||
|
|
11
src/client.h
11
src/client.h
|
@ -47,7 +47,6 @@ struct MapDrawControl;
|
||||||
class MtEventManager;
|
class MtEventManager;
|
||||||
struct PointedThing;
|
struct PointedThing;
|
||||||
class Database;
|
class Database;
|
||||||
class Server;
|
|
||||||
|
|
||||||
struct QueuedMeshUpdate
|
struct QueuedMeshUpdate
|
||||||
{
|
{
|
||||||
|
@ -465,7 +464,7 @@ public:
|
||||||
// Insert a media file appropriately into the appropriate manager
|
// Insert a media file appropriately into the appropriate manager
|
||||||
bool loadMedia(const std::string &data, const std::string &filename);
|
bool loadMedia(const std::string &data, const std::string &filename);
|
||||||
// Send a request for conventional media transfer
|
// 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
|
// Send a notification that no conventional media transfer is needed
|
||||||
void received_media();
|
void received_media();
|
||||||
|
|
||||||
|
@ -569,11 +568,13 @@ private:
|
||||||
LocalClientState m_state;
|
LocalClientState m_state;
|
||||||
|
|
||||||
// Used for saving server map to disk client-side
|
// Used for saving server map to disk client-side
|
||||||
Database *localdb;
|
Database *m_localdb;
|
||||||
Server *localserver;
|
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_smooth_lighting;
|
||||||
|
bool m_cache_enable_shaders;
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif // !CLIENT_HEADER
|
#endif // !CLIENT_HEADER
|
||||||
|
|
|
@ -59,7 +59,7 @@ void RemoteClient::ResendBlockIfOnWire(v3s16 p)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void RemoteClient::GetNextBlocks(
|
void RemoteClient::GetNextBlocks (
|
||||||
ServerEnvironment *env,
|
ServerEnvironment *env,
|
||||||
EmergeManager * emerge,
|
EmergeManager * emerge,
|
||||||
float dtime,
|
float dtime,
|
||||||
|
@ -182,18 +182,15 @@ void RemoteClient::GetNextBlocks(
|
||||||
//bool queue_is_full = false;
|
//bool queue_is_full = false;
|
||||||
|
|
||||||
s16 d;
|
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"
|
Get the border/face dot coordinates of a "d-radiused"
|
||||||
box
|
box
|
||||||
*/
|
*/
|
||||||
std::list<v3s16> list;
|
std::vector<v3s16> list = FacePositionCache::getFacePositions(d);
|
||||||
getFacePositions(list, d);
|
|
||||||
|
|
||||||
std::list<v3s16>::iterator li;
|
std::vector<v3s16>::iterator li;
|
||||||
for(li=list.begin(); li!=list.end(); ++li)
|
for(li = list.begin(); li != list.end(); ++li) {
|
||||||
{
|
|
||||||
v3s16 p = *li + center;
|
v3s16 p = *li + center;
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
|
|
@ -161,9 +161,9 @@ static bool isOccluded(Map *map, v3s16 p0, v3s16 p1, float step, float stepfac,
|
||||||
else
|
else
|
||||||
is_transparent = (f.solidness != 2);
|
is_transparent = (f.solidness != 2);
|
||||||
if(!is_transparent){
|
if(!is_transparent){
|
||||||
count++;
|
if(count == needed_count)
|
||||||
if(count >= needed_count)
|
|
||||||
return true;
|
return true;
|
||||||
|
count++;
|
||||||
}
|
}
|
||||||
step *= stepfac;
|
step *= stepfac;
|
||||||
}
|
}
|
||||||
|
@ -247,7 +247,7 @@ void ClientMap::updateDrawList(video::IVideoDriver* driver)
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
std::list< MapBlock * > sectorblocks;
|
MapBlockVect sectorblocks;
|
||||||
sector->getBlocks(sectorblocks);
|
sector->getBlocks(sectorblocks);
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
@ -256,8 +256,8 @@ void ClientMap::updateDrawList(video::IVideoDriver* driver)
|
||||||
|
|
||||||
u32 sector_blocks_drawn = 0;
|
u32 sector_blocks_drawn = 0;
|
||||||
|
|
||||||
std::list< MapBlock * >::iterator i;
|
for(MapBlockVect::iterator i = sectorblocks.begin();
|
||||||
for(i=sectorblocks.begin(); i!=sectorblocks.end(); i++)
|
i != sectorblocks.end(); i++)
|
||||||
{
|
{
|
||||||
MapBlock *block = *i;
|
MapBlock *block = *i;
|
||||||
|
|
||||||
|
@ -391,12 +391,12 @@ void ClientMap::updateDrawList(video::IVideoDriver* driver)
|
||||||
struct MeshBufList
|
struct MeshBufList
|
||||||
{
|
{
|
||||||
video::SMaterial m;
|
video::SMaterial m;
|
||||||
std::list<scene::IMeshBuffer*> bufs;
|
std::vector<scene::IMeshBuffer*> bufs;
|
||||||
};
|
};
|
||||||
|
|
||||||
struct MeshBufListList
|
struct MeshBufListList
|
||||||
{
|
{
|
||||||
std::list<MeshBufList> lists;
|
std::vector<MeshBufList> lists;
|
||||||
|
|
||||||
void clear()
|
void clear()
|
||||||
{
|
{
|
||||||
|
@ -405,7 +405,7 @@ struct MeshBufListList
|
||||||
|
|
||||||
void add(scene::IMeshBuffer *buf)
|
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){
|
i != lists.end(); ++i){
|
||||||
MeshBufList &l = *i;
|
MeshBufList &l = *i;
|
||||||
video::SMaterial &m = buf->getMaterial();
|
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;
|
int timecheck_counter = 0;
|
||||||
for(std::list<MeshBufList>::iterator i = lists.begin();
|
for(std::vector<MeshBufList>::iterator i = lists.begin();
|
||||||
i != lists.end(); ++i)
|
i != lists.end(); ++i) {
|
||||||
{
|
timecheck_counter++;
|
||||||
{
|
if(timecheck_counter > 50) {
|
||||||
timecheck_counter++;
|
timecheck_counter = 0;
|
||||||
if(timecheck_counter > 50)
|
int time2 = time(0);
|
||||||
{
|
if(time2 > time1 + 4) {
|
||||||
timecheck_counter = 0;
|
infostream << "ClientMap::renderMap(): "
|
||||||
int time2 = time(0);
|
"Rendering takes ages, returning."
|
||||||
if(time2 > time1 + 4)
|
<< std::endl;
|
||||||
{
|
return;
|
||||||
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);
|
driver->setMaterial(list.m);
|
||||||
|
|
||||||
for(std::list<scene::IMeshBuffer*>::iterator j = list.bufs.begin();
|
for(std::vector<scene::IMeshBuffer*>::iterator j = list.bufs.begin();
|
||||||
j != list.bufs.end(); ++j)
|
j != list.bufs.end(); ++j) {
|
||||||
{
|
|
||||||
scene::IMeshBuffer *buf = *j;
|
scene::IMeshBuffer *buf = *j;
|
||||||
driver->drawMeshBuffer(buf);
|
driver->drawMeshBuffer(buf);
|
||||||
vertex_count += buf->getVertexCount();
|
vertex_count += buf->getVertexCount();
|
||||||
meshbuffer_count++;
|
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
|
} // ScopeProfiler
|
||||||
|
|
||||||
|
|
|
@ -18,20 +18,20 @@ with this program; if not, write to the Free Software Foundation, Inc.,
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#include "clientmedia.h"
|
#include "clientmedia.h"
|
||||||
#include "util/serialize.h"
|
|
||||||
#include "util/string.h"
|
|
||||||
#include "httpfetch.h"
|
#include "httpfetch.h"
|
||||||
#include "client.h"
|
#include "client.h"
|
||||||
#include "clientserver.h"
|
#include "clientserver.h"
|
||||||
#include "filecache.h"
|
#include "filecache.h"
|
||||||
#include "filesys.h"
|
#include "filesys.h"
|
||||||
#include "hex.h"
|
|
||||||
#include "sha1.h"
|
|
||||||
#include "debug.h"
|
#include "debug.h"
|
||||||
#include "log.h"
|
#include "log.h"
|
||||||
#include "porting.h"
|
#include "porting.h"
|
||||||
#include "settings.h"
|
#include "settings.h"
|
||||||
#include "main.h"
|
#include "main.h"
|
||||||
|
#include "util/hex.h"
|
||||||
|
#include "util/serialize.h"
|
||||||
|
#include "util/sha1.h"
|
||||||
|
#include "util/string.h"
|
||||||
|
|
||||||
static std::string getMediaCacheDir()
|
static std::string getMediaCacheDir()
|
||||||
{
|
{
|
||||||
|
@ -488,7 +488,7 @@ void ClientMediaDownloader::startConventionalTransfers(Client *client)
|
||||||
if (m_uncached_received_count != m_uncached_count) {
|
if (m_uncached_received_count != m_uncached_count) {
|
||||||
// Some media files have not been received yet, use the
|
// Some media files have not been received yet, use the
|
||||||
// conventional slow method (minetest protocol) to get them
|
// 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
|
for (std::map<std::string, FileStatus*>::iterator
|
||||||
it = m_files.begin();
|
it = m_files.begin();
|
||||||
it != m_files.end(); ++it) {
|
it != m_files.end(); ++it) {
|
||||||
|
|
|
@ -39,14 +39,13 @@ ClientActiveObject::~ClientActiveObject()
|
||||||
removeFromScene(true);
|
removeFromScene(true);
|
||||||
}
|
}
|
||||||
|
|
||||||
ClientActiveObject* ClientActiveObject::create(u8 type, IGameDef *gamedef,
|
ClientActiveObject* ClientActiveObject::create(ActiveObjectType type,
|
||||||
ClientEnvironment *env)
|
IGameDef *gamedef, ClientEnvironment *env)
|
||||||
{
|
{
|
||||||
// Find factory function
|
// Find factory function
|
||||||
std::map<u16, Factory>::iterator n;
|
std::map<u16, Factory>::iterator n;
|
||||||
n = m_types.find(type);
|
n = m_types.find(type);
|
||||||
if(n == m_types.end())
|
if(n == m_types.end()) {
|
||||||
{
|
|
||||||
// If factory is not found, just return.
|
// If factory is not found, just return.
|
||||||
dstream<<"WARNING: ClientActiveObject: No factory for type="
|
dstream<<"WARNING: ClientActiveObject: No factory for type="
|
||||||
<<(int)type<<std::endl;
|
<<(int)type<<std::endl;
|
||||||
|
|
|
@ -86,7 +86,7 @@ public:
|
||||||
virtual void initialize(const std::string &data){}
|
virtual void initialize(const std::string &data){}
|
||||||
|
|
||||||
// Create a certain type of ClientActiveObject
|
// Create a certain type of ClientActiveObject
|
||||||
static ClientActiveObject* create(u8 type, IGameDef *gamedef,
|
static ClientActiveObject* create(ActiveObjectType type, IGameDef *gamedef,
|
||||||
ClientEnvironment *env);
|
ClientEnvironment *env);
|
||||||
|
|
||||||
// If returns true, punch will not be sent to the server
|
// If returns true, punch will not be sent to the server
|
||||||
|
|
|
@ -300,16 +300,14 @@ collisionMoveResult collisionMoveSimple(Environment *env, IGameDef *gamedef,
|
||||||
/* add object boxes to cboxes */
|
/* add object boxes to cboxes */
|
||||||
|
|
||||||
|
|
||||||
std::list<ActiveObject*> objects;
|
std::vector<ActiveObject*> objects;
|
||||||
#ifndef SERVER
|
#ifndef SERVER
|
||||||
ClientEnvironment *c_env = dynamic_cast<ClientEnvironment*>(env);
|
ClientEnvironment *c_env = dynamic_cast<ClientEnvironment*>(env);
|
||||||
if (c_env != 0)
|
if (c_env != 0) {
|
||||||
{
|
|
||||||
f32 distance = speed_f.getLength();
|
f32 distance = speed_f.getLength();
|
||||||
std::vector<DistanceSortedActiveObject> clientobjects;
|
std::vector<DistanceSortedActiveObject> clientobjects;
|
||||||
c_env->getActiveObjects(pos_f,distance * 1.5,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)) {
|
if ((self == 0) || (self != clientobjects[i].obj)) {
|
||||||
objects.push_back((ActiveObject*)clientobjects[i].obj);
|
objects.push_back((ActiveObject*)clientobjects[i].obj);
|
||||||
}
|
}
|
||||||
|
@ -319,12 +317,10 @@ collisionMoveResult collisionMoveSimple(Environment *env, IGameDef *gamedef,
|
||||||
#endif
|
#endif
|
||||||
{
|
{
|
||||||
ServerEnvironment *s_env = dynamic_cast<ServerEnvironment*>(env);
|
ServerEnvironment *s_env = dynamic_cast<ServerEnvironment*>(env);
|
||||||
if (s_env != 0)
|
if (s_env != 0) {
|
||||||
{
|
|
||||||
f32 distance = speed_f.getLength();
|
f32 distance = speed_f.getLength();
|
||||||
std::set<u16> s_objects = s_env->getObjectsInsideRadius(pos_f,distance * 1.5);
|
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);
|
ServerActiveObject *current = s_env->getActiveObject(*iter);
|
||||||
if ((self == 0) || (self != current)) {
|
if ((self == 0) || (self != current)) {
|
||||||
objects.push_back((ActiveObject*)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;
|
ActiveObject *object = *iter;
|
||||||
|
|
||||||
if (object != NULL)
|
if (object != NULL) {
|
||||||
{
|
|
||||||
aabb3f object_collisionbox;
|
aabb3f object_collisionbox;
|
||||||
if (object->getCollisionBox(&object_collisionbox) &&
|
if (object->getCollisionBox(&object_collisionbox) &&
|
||||||
object->collideWithObjects())
|
object->collideWithObjects()) {
|
||||||
{
|
|
||||||
cboxes.push_back(object_collisionbox);
|
cboxes.push_back(object_collisionbox);
|
||||||
is_unloaded.push_back(false);
|
is_unloaded.push_back(false);
|
||||||
is_step_up.push_back(false);
|
is_step_up.push_back(false);
|
||||||
|
|
|
@ -100,7 +100,13 @@ with this program; if not, write to the Free Software Foundation, Inc.,
|
||||||
/*
|
/*
|
||||||
GUI related things
|
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)
|
#define DEFAULT_FONT_SIZE (10)
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
|
@ -34,7 +34,6 @@ with this program; if not, write to the Free Software Foundation, Inc.,
|
||||||
#include "serialization.h" // For decompressZlib
|
#include "serialization.h" // For decompressZlib
|
||||||
#include "gamedef.h"
|
#include "gamedef.h"
|
||||||
#include "clientobject.h"
|
#include "clientobject.h"
|
||||||
#include "content_object.h"
|
|
||||||
#include "mesh.h"
|
#include "mesh.h"
|
||||||
#include "itemdef.h"
|
#include "itemdef.h"
|
||||||
#include "tool.h"
|
#include "tool.h"
|
||||||
|
@ -145,7 +144,7 @@ public:
|
||||||
TestCAO(IGameDef *gamedef, ClientEnvironment *env);
|
TestCAO(IGameDef *gamedef, ClientEnvironment *env);
|
||||||
virtual ~TestCAO();
|
virtual ~TestCAO();
|
||||||
|
|
||||||
u8 getType() const
|
ActiveObjectType getType() const
|
||||||
{
|
{
|
||||||
return ACTIVEOBJECT_TYPE_TEST;
|
return ACTIVEOBJECT_TYPE_TEST;
|
||||||
}
|
}
|
||||||
|
@ -289,7 +288,7 @@ public:
|
||||||
ItemCAO(IGameDef *gamedef, ClientEnvironment *env);
|
ItemCAO(IGameDef *gamedef, ClientEnvironment *env);
|
||||||
virtual ~ItemCAO();
|
virtual ~ItemCAO();
|
||||||
|
|
||||||
u8 getType() const
|
ActiveObjectType getType() const
|
||||||
{
|
{
|
||||||
return ACTIVEOBJECT_TYPE_ITEM;
|
return ACTIVEOBJECT_TYPE_ITEM;
|
||||||
}
|
}
|
||||||
|
@ -963,7 +962,7 @@ void GenericCAO::addToScene(scene::ISceneManager *smgr, ITextureSource *tsrc,
|
||||||
// Add a text node for showing the name
|
// Add a text node for showing the name
|
||||||
gui::IGUIEnvironment* gui = irr->getGUIEnvironment();
|
gui::IGUIEnvironment* gui = irr->getGUIEnvironment();
|
||||||
std::wstring wname = narrow_to_wide(m_name);
|
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);
|
wname.c_str(), video::SColor(255,255,255,255), node);
|
||||||
m_textnode->grab();
|
m_textnode->grab();
|
||||||
m_textnode->setPosition(v3f(0, BS*1.1, 0));
|
m_textnode->setPosition(v3f(0, BS*1.1, 0));
|
||||||
|
|
|
@ -22,7 +22,6 @@ with this program; if not, write to the Free Software Foundation, Inc.,
|
||||||
|
|
||||||
#include <map>
|
#include <map>
|
||||||
#include "irrlichttypes_extrabloated.h"
|
#include "irrlichttypes_extrabloated.h"
|
||||||
#include "content_object.h"
|
|
||||||
#include "clientobject.h"
|
#include "clientobject.h"
|
||||||
#include "object_properties.h"
|
#include "object_properties.h"
|
||||||
#include "itemgroup.h"
|
#include "itemgroup.h"
|
||||||
|
@ -115,7 +114,7 @@ public:
|
||||||
return new GenericCAO(gamedef, env);
|
return new GenericCAO(gamedef, env);
|
||||||
}
|
}
|
||||||
|
|
||||||
inline u8 getType() const
|
inline ActiveObjectType getType() const
|
||||||
{
|
{
|
||||||
return ACTIVEOBJECT_TYPE_GENERIC;
|
return ACTIVEOBJECT_TYPE_GENERIC;
|
||||||
}
|
}
|
||||||
|
|
|
@ -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
|
// (compatible with ContentFeatures). If you specified 0,0,1,1
|
||||||
// for each face, that would be the same as passing NULL.
|
// for each face, that would be the same as passing NULL.
|
||||||
void makeCuboid(MeshCollector *collector, const aabb3f &box,
|
void makeCuboid(MeshCollector *collector, const aabb3f &box,
|
||||||
TileSpec *tiles, int tilecount,
|
TileSpec *tiles, int tilecount, video::SColor &c, const f32* txc)
|
||||||
video::SColor &c, const f32* txc)
|
|
||||||
{
|
{
|
||||||
assert(tilecount >= 1 && tilecount <= 6);
|
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] = {
|
static const f32 txc_default[24] = {
|
||||||
0,0,1,1,
|
0,0,1,1,
|
||||||
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};
|
u16 indices[] = {0,1,2,2,3,0};
|
||||||
// Add to mesh collector
|
// Add to mesh collector
|
||||||
for(s32 j=0; j<24; j+=4)
|
for (s32 j = 0; j < 24; j += 4) {
|
||||||
{
|
int tileindex = MYMIN(j / 4, tilecount - 1);
|
||||||
int tileindex = MYMIN(j/4, tilecount-1);
|
collector->append(tiles[tileindex], vertices + j, 4, indices, 6);
|
||||||
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,
|
void mapblock_mesh_generate_special(MeshMakeData *data,
|
||||||
MeshCollector &collector)
|
MeshCollector &collector)
|
||||||
{
|
{
|
||||||
|
@ -191,54 +191,6 @@ void mapblock_mesh_generate_special(MeshMakeData *data,
|
||||||
|
|
||||||
v3s16 blockpos_nodes = data->m_blockpos*MAP_BLOCKSIZE;
|
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 z = 0; z < MAP_BLOCKSIZE; z++)
|
||||||
for(s16 y = 0; y < MAP_BLOCKSIZE; y++)
|
for(s16 y = 0; y < MAP_BLOCKSIZE; y++)
|
||||||
for(s16 x = 0; x < MAP_BLOCKSIZE; x++)
|
for(s16 x = 0; x < MAP_BLOCKSIZE; x++)
|
||||||
|
@ -1469,77 +1421,65 @@ void mapblock_mesh_generate_special(MeshMakeData *data,
|
||||||
|
|
||||||
content_t thiscontent = n.getContent();
|
content_t thiscontent = n.getContent();
|
||||||
std::string groupname = "connect_to_raillike"; // name of the group that enables connecting to raillike nodes of different kind
|
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
|
if ((nodedef->get(n_minus_x).drawtype == NDT_RAILLIKE
|
||||||
&& ((ItemGroupList) nodedef->get(n_minus_x).groups)[groupname] != 0
|
&& ((ItemGroupList) nodedef->get(n_minus_x).groups)[groupname] != self_group)
|
||||||
&& self_connect_to_raillike)
|
|
||||||
|| n_minus_x.getContent() == thiscontent)
|
|| n_minus_x.getContent() == thiscontent)
|
||||||
is_rail_x[0] = true;
|
is_rail_x[0] = true;
|
||||||
|
|
||||||
if ((nodedef->get(n_minus_x_minus_y).drawtype == NDT_RAILLIKE
|
if ((nodedef->get(n_minus_x_minus_y).drawtype == NDT_RAILLIKE
|
||||||
&& ((ItemGroupList) nodedef->get(n_minus_x_minus_y).groups)[groupname] != 0
|
&& ((ItemGroupList) nodedef->get(n_minus_x_minus_y).groups)[groupname] != self_group)
|
||||||
&& self_connect_to_raillike)
|
|
||||||
|| n_minus_x_minus_y.getContent() == thiscontent)
|
|| n_minus_x_minus_y.getContent() == thiscontent)
|
||||||
is_rail_x_minus_y[0] = true;
|
is_rail_x_minus_y[0] = true;
|
||||||
|
|
||||||
if ((nodedef->get(n_minus_x_plus_y).drawtype == NDT_RAILLIKE
|
if ((nodedef->get(n_minus_x_plus_y).drawtype == NDT_RAILLIKE
|
||||||
&& ((ItemGroupList) nodedef->get(n_minus_x_plus_y).groups)[groupname] != 0
|
&& ((ItemGroupList) nodedef->get(n_minus_x_plus_y).groups)[groupname] != self_group)
|
||||||
&& self_connect_to_raillike)
|
|
||||||
|| n_minus_x_plus_y.getContent() == thiscontent)
|
|| n_minus_x_plus_y.getContent() == thiscontent)
|
||||||
is_rail_x_plus_y[0] = true;
|
is_rail_x_plus_y[0] = true;
|
||||||
|
|
||||||
if ((nodedef->get(n_plus_x).drawtype == NDT_RAILLIKE
|
if ((nodedef->get(n_plus_x).drawtype == NDT_RAILLIKE
|
||||||
&& ((ItemGroupList) nodedef->get(n_plus_x).groups)[groupname] != 0
|
&& ((ItemGroupList) nodedef->get(n_plus_x).groups)[groupname] != self_group)
|
||||||
&& self_connect_to_raillike)
|
|
||||||
|| n_plus_x.getContent() == thiscontent)
|
|| n_plus_x.getContent() == thiscontent)
|
||||||
is_rail_x[1] = true;
|
is_rail_x[1] = true;
|
||||||
|
|
||||||
if ((nodedef->get(n_plus_x_minus_y).drawtype == NDT_RAILLIKE
|
if ((nodedef->get(n_plus_x_minus_y).drawtype == NDT_RAILLIKE
|
||||||
&& ((ItemGroupList) nodedef->get(n_plus_x_minus_y).groups)[groupname] != 0
|
&& ((ItemGroupList) nodedef->get(n_plus_x_minus_y).groups)[groupname] != self_group)
|
||||||
&& self_connect_to_raillike)
|
|
||||||
|| n_plus_x_minus_y.getContent() == thiscontent)
|
|| n_plus_x_minus_y.getContent() == thiscontent)
|
||||||
is_rail_x_minus_y[1] = true;
|
is_rail_x_minus_y[1] = true;
|
||||||
|
|
||||||
if ((nodedef->get(n_plus_x_plus_y).drawtype == NDT_RAILLIKE
|
if ((nodedef->get(n_plus_x_plus_y).drawtype == NDT_RAILLIKE
|
||||||
&& ((ItemGroupList) nodedef->get(n_plus_x_plus_y).groups)[groupname] != 0
|
&& ((ItemGroupList) nodedef->get(n_plus_x_plus_y).groups)[groupname] != self_group)
|
||||||
&& self_connect_to_raillike)
|
|
||||||
|| n_plus_x_plus_y.getContent() == thiscontent)
|
|| n_plus_x_plus_y.getContent() == thiscontent)
|
||||||
is_rail_x_plus_y[1] = true;
|
is_rail_x_plus_y[1] = true;
|
||||||
|
|
||||||
if ((nodedef->get(n_minus_z).drawtype == NDT_RAILLIKE
|
if ((nodedef->get(n_minus_z).drawtype == NDT_RAILLIKE
|
||||||
&& ((ItemGroupList) nodedef->get(n_minus_z).groups)[groupname] != 0
|
&& ((ItemGroupList) nodedef->get(n_minus_z).groups)[groupname] != self_group)
|
||||||
&& self_connect_to_raillike)
|
|
||||||
|| n_minus_z.getContent() == thiscontent)
|
|| n_minus_z.getContent() == thiscontent)
|
||||||
is_rail_z[0] = true;
|
is_rail_z[0] = true;
|
||||||
|
|
||||||
if ((nodedef->get(n_minus_z_minus_y).drawtype == NDT_RAILLIKE
|
if ((nodedef->get(n_minus_z_minus_y).drawtype == NDT_RAILLIKE
|
||||||
&& ((ItemGroupList) nodedef->get(n_minus_z_minus_y).groups)[groupname] != 0
|
&& ((ItemGroupList) nodedef->get(n_minus_z_minus_y).groups)[groupname] != self_group)
|
||||||
&& self_connect_to_raillike)
|
|
||||||
|| n_minus_z_minus_y.getContent() == thiscontent)
|
|| n_minus_z_minus_y.getContent() == thiscontent)
|
||||||
is_rail_z_minus_y[0] = true;
|
is_rail_z_minus_y[0] = true;
|
||||||
|
|
||||||
if ((nodedef->get(n_minus_z_plus_y).drawtype == NDT_RAILLIKE
|
if ((nodedef->get(n_minus_z_plus_y).drawtype == NDT_RAILLIKE
|
||||||
&& ((ItemGroupList) nodedef->get(n_minus_z_plus_y).groups)[groupname] != 0
|
&& ((ItemGroupList) nodedef->get(n_minus_z_plus_y).groups)[groupname] != self_group)
|
||||||
&& self_connect_to_raillike)
|
|
||||||
|| n_minus_z_plus_y.getContent() == thiscontent)
|
|| n_minus_z_plus_y.getContent() == thiscontent)
|
||||||
is_rail_z_plus_y[0] = true;
|
is_rail_z_plus_y[0] = true;
|
||||||
|
|
||||||
if ((nodedef->get(n_plus_z).drawtype == NDT_RAILLIKE
|
if ((nodedef->get(n_plus_z).drawtype == NDT_RAILLIKE
|
||||||
&& ((ItemGroupList) nodedef->get(n_plus_z).groups)[groupname] != 0
|
&& ((ItemGroupList) nodedef->get(n_plus_z).groups)[groupname] != self_group)
|
||||||
&& self_connect_to_raillike)
|
|
||||||
|| n_plus_z.getContent() == thiscontent)
|
|| n_plus_z.getContent() == thiscontent)
|
||||||
is_rail_z[1] = true;
|
is_rail_z[1] = true;
|
||||||
|
|
||||||
if ((nodedef->get(n_plus_z_minus_y).drawtype == NDT_RAILLIKE
|
if ((nodedef->get(n_plus_z_minus_y).drawtype == NDT_RAILLIKE
|
||||||
&& ((ItemGroupList) nodedef->get(n_plus_z_minus_y).groups)[groupname] != 0
|
&& ((ItemGroupList) nodedef->get(n_plus_z_minus_y).groups)[groupname] != self_group)
|
||||||
&& self_connect_to_raillike)
|
|
||||||
|| n_plus_z_minus_y.getContent() == thiscontent)
|
|| n_plus_z_minus_y.getContent() == thiscontent)
|
||||||
is_rail_z_minus_y[1] = true;
|
is_rail_z_minus_y[1] = true;
|
||||||
|
|
||||||
if ((nodedef->get(n_plus_z_plus_y).drawtype == NDT_RAILLIKE
|
if ((nodedef->get(n_plus_z_plus_y).drawtype == NDT_RAILLIKE
|
||||||
&& ((ItemGroupList) nodedef->get(n_plus_z_plus_y).groups)[groupname] != 0
|
&& ((ItemGroupList) nodedef->get(n_plus_z_plus_y).groups)[groupname] != self_group)
|
||||||
&& self_connect_to_raillike)
|
|
||||||
|| n_plus_z_plus_y.getContent() == thiscontent)
|
|| n_plus_z_plus_y.getContent() == thiscontent)
|
||||||
is_rail_z_plus_y[1] = true;
|
is_rail_z_plus_y[1] = true;
|
||||||
|
|
||||||
|
@ -1766,5 +1706,55 @@ void mapblock_mesh_generate_special(MeshMakeData *data,
|
||||||
break;}
|
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);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -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
|
|
||||||
|
|
|
@ -35,54 +35,6 @@ with this program; if not, write to the Free Software Foundation, Inc.,
|
||||||
|
|
||||||
std::map<u16, ServerActiveObject::Factory> ServerActiveObject::m_types;
|
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
|
TestSAO
|
||||||
*/
|
*/
|
||||||
|
@ -97,7 +49,7 @@ public:
|
||||||
{
|
{
|
||||||
ServerActiveObject::registerType(getType(), create);
|
ServerActiveObject::registerType(getType(), create);
|
||||||
}
|
}
|
||||||
u8 getType() const
|
ActiveObjectType getType() const
|
||||||
{ return ACTIVEOBJECT_TYPE_TEST; }
|
{ return ACTIVEOBJECT_TYPE_TEST; }
|
||||||
|
|
||||||
static ServerActiveObject* create(ServerEnvironment *env, v3f pos,
|
static ServerActiveObject* create(ServerEnvironment *env, v3f pos,
|
||||||
|
@ -158,203 +110,6 @@ private:
|
||||||
// Prototype (registers item for deserialization)
|
// Prototype (registers item for deserialization)
|
||||||
TestSAO proto_TestSAO(NULL, v3f(0,0,0));
|
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
|
LuaEntitySAO
|
||||||
*/
|
*/
|
||||||
|
@ -965,7 +720,6 @@ PlayerSAO::PlayerSAO(ServerEnvironment *env_, Player *player_, u16 peer_id_,
|
||||||
m_inventory_not_sent(false),
|
m_inventory_not_sent(false),
|
||||||
m_hp_not_sent(false),
|
m_hp_not_sent(false),
|
||||||
m_breath_not_sent(false),
|
m_breath_not_sent(false),
|
||||||
m_wielded_item_not_sent(false),
|
|
||||||
m_physics_override_speed(1),
|
m_physics_override_speed(1),
|
||||||
m_physics_override_jump(1),
|
m_physics_override_jump(1),
|
||||||
m_physics_override_gravity(1),
|
m_physics_override_gravity(1),
|
||||||
|
@ -1171,13 +925,7 @@ void PlayerSAO::step(float dtime, bool send_recommended)
|
||||||
m_messages_out.push_back(aom);
|
m_messages_out.push_back(aom);
|
||||||
}
|
}
|
||||||
|
|
||||||
if(m_wielded_item_not_sent)
|
if(m_armor_groups_sent == false) {
|
||||||
{
|
|
||||||
m_wielded_item_not_sent = false;
|
|
||||||
// GenericCAO has no special way to show this
|
|
||||||
}
|
|
||||||
|
|
||||||
if(m_armor_groups_sent == false){
|
|
||||||
m_armor_groups_sent = true;
|
m_armor_groups_sent = true;
|
||||||
std::string str = gob_cmd_update_armor_groups(
|
std::string str = gob_cmd_update_armor_groups(
|
||||||
m_armor_groups);
|
m_armor_groups);
|
||||||
|
@ -1442,10 +1190,8 @@ int PlayerSAO::getWieldIndex() const
|
||||||
|
|
||||||
void PlayerSAO::setWieldIndex(int i)
|
void PlayerSAO::setWieldIndex(int i)
|
||||||
{
|
{
|
||||||
if(i != m_wield_index)
|
if(i != m_wield_index) {
|
||||||
{
|
|
||||||
m_wield_index = i;
|
m_wield_index = i;
|
||||||
m_wielded_item_not_sent = true;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -21,14 +21,10 @@ with this program; if not, write to the Free Software Foundation, Inc.,
|
||||||
#define CONTENT_SAO_HEADER
|
#define CONTENT_SAO_HEADER
|
||||||
|
|
||||||
#include "serverobject.h"
|
#include "serverobject.h"
|
||||||
#include "content_object.h"
|
|
||||||
#include "itemgroup.h"
|
#include "itemgroup.h"
|
||||||
#include "player.h"
|
#include "player.h"
|
||||||
#include "object_properties.h"
|
#include "object_properties.h"
|
||||||
|
|
||||||
ServerActiveObject* createItemSAO(ServerEnvironment *env, v3f pos,
|
|
||||||
const std::string &itemstring);
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
LuaEntitySAO needs some internals exposed.
|
LuaEntitySAO needs some internals exposed.
|
||||||
*/
|
*/
|
||||||
|
@ -39,9 +35,9 @@ public:
|
||||||
LuaEntitySAO(ServerEnvironment *env, v3f pos,
|
LuaEntitySAO(ServerEnvironment *env, v3f pos,
|
||||||
const std::string &name, const std::string &state);
|
const std::string &name, const std::string &state);
|
||||||
~LuaEntitySAO();
|
~LuaEntitySAO();
|
||||||
u8 getType() const
|
ActiveObjectType getType() const
|
||||||
{ return ACTIVEOBJECT_TYPE_LUAENTITY; }
|
{ return ACTIVEOBJECT_TYPE_LUAENTITY; }
|
||||||
u8 getSendType() const
|
ActiveObjectType getSendType() const
|
||||||
{ return ACTIVEOBJECT_TYPE_GENERIC; }
|
{ return ACTIVEOBJECT_TYPE_GENERIC; }
|
||||||
virtual void addedToEnvironment(u32 dtime_s);
|
virtual void addedToEnvironment(u32 dtime_s);
|
||||||
static ServerActiveObject* create(ServerEnvironment *env, v3f pos,
|
static ServerActiveObject* create(ServerEnvironment *env, v3f pos,
|
||||||
|
@ -158,9 +154,9 @@ public:
|
||||||
PlayerSAO(ServerEnvironment *env_, Player *player_, u16 peer_id_,
|
PlayerSAO(ServerEnvironment *env_, Player *player_, u16 peer_id_,
|
||||||
const std::set<std::string> &privs, bool is_singleplayer);
|
const std::set<std::string> &privs, bool is_singleplayer);
|
||||||
~PlayerSAO();
|
~PlayerSAO();
|
||||||
u8 getType() const
|
ActiveObjectType getType() const
|
||||||
{ return ACTIVEOBJECT_TYPE_PLAYER; }
|
{ return ACTIVEOBJECT_TYPE_PLAYER; }
|
||||||
u8 getSendType() const
|
ActiveObjectType getSendType() const
|
||||||
{ return ACTIVEOBJECT_TYPE_GENERIC; }
|
{ return ACTIVEOBJECT_TYPE_GENERIC; }
|
||||||
std::string getDescription();
|
std::string getDescription();
|
||||||
|
|
||||||
|
@ -324,7 +320,6 @@ public:
|
||||||
bool m_inventory_not_sent;
|
bool m_inventory_not_sent;
|
||||||
bool m_hp_not_sent;
|
bool m_hp_not_sent;
|
||||||
bool m_breath_not_sent;
|
bool m_breath_not_sent;
|
||||||
bool m_wielded_item_not_sent;
|
|
||||||
|
|
||||||
float m_physics_override_speed;
|
float m_physics_override_speed;
|
||||||
float m_physics_override_jump;
|
float m_physics_override_jump;
|
||||||
|
|
|
@ -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 "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;
|
m_database[getBlockAsInteger(pos)] = data;
|
||||||
}
|
|
||||||
|
|
||||||
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;
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
std::string Database_Dummy::loadBlock(v3s16 blockpos)
|
std::string Database_Dummy::loadBlock(const v3s16 &pos)
|
||||||
{
|
{
|
||||||
if (m_database.count(getBlockAsInteger(blockpos)))
|
s64 i = getBlockAsInteger(pos);
|
||||||
return m_database[getBlockAsInteger(blockpos)];
|
if (m_database.count(i))
|
||||||
|
return m_database[i];
|
||||||
else
|
else
|
||||||
return "";
|
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;
|
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)
|
for (std::map<s64, std::string>::const_iterator x = m_database.begin();
|
||||||
{
|
x != m_database.end(); ++x) {
|
||||||
v3s16 p = getIntegerAsBlock(x->first);
|
dst.push_back(getIntegerAsBlock(x->first));
|
||||||
//dstream<<"block_i="<<block_i<<" p="<<PP(p)<<std::endl;
|
|
||||||
dst.push_back(p);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
Database_Dummy::~Database_Dummy()
|
|
||||||
{
|
|
||||||
m_database.clear();
|
|
||||||
}
|
|
||||||
|
|
|
@ -25,22 +25,17 @@ with this program; if not, write to the Free Software Foundation, Inc.,
|
||||||
#include "database.h"
|
#include "database.h"
|
||||||
#include "irrlichttypes.h"
|
#include "irrlichttypes.h"
|
||||||
|
|
||||||
class ServerMap;
|
|
||||||
|
|
||||||
class Database_Dummy : public Database
|
class Database_Dummy : public Database
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
Database_Dummy(ServerMap *map);
|
virtual bool saveBlock(const v3s16 &pos, const std::string &data);
|
||||||
virtual void beginSave();
|
virtual std::string loadBlock(const v3s16 &pos);
|
||||||
virtual void endSave();
|
virtual bool deleteBlock(const v3s16 &pos);
|
||||||
virtual bool saveBlock(v3s16 blockpos, std::string &data);
|
virtual void listAllLoadableBlocks(std::vector<v3s16> &dst);
|
||||||
virtual std::string loadBlock(v3s16 blockpos);
|
|
||||||
virtual bool deleteBlock(v3s16 blockpos);
|
|
||||||
virtual void listAllLoadableBlocks(std::list<v3s16> &dst);
|
|
||||||
virtual int Initialized(void);
|
|
||||||
~Database_Dummy();
|
|
||||||
private:
|
private:
|
||||||
ServerMap *srvmap;
|
std::map<s64, std::string> m_database;
|
||||||
std::map<u64, std::string> m_database;
|
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
|
|
@ -22,57 +22,54 @@ with this program; if not, write to the Free Software Foundation, Inc.,
|
||||||
#if USE_LEVELDB
|
#if USE_LEVELDB
|
||||||
|
|
||||||
#include "database-leveldb.h"
|
#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 "log.h"
|
||||||
#include "filesys.h"
|
#include "filesys.h"
|
||||||
|
#include "exceptions.h"
|
||||||
|
#include "util/string.h"
|
||||||
|
|
||||||
|
#include "leveldb/db.h"
|
||||||
|
|
||||||
|
|
||||||
#define ENSURE_STATUS_OK(s) \
|
#define ENSURE_STATUS_OK(s) \
|
||||||
if (!(s).ok()) { \
|
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;
|
leveldb::Options options;
|
||||||
options.create_if_missing = true;
|
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);
|
ENSURE_STATUS_OK(status);
|
||||||
srvmap = map;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
int Database_LevelDB::Initialized(void)
|
Database_LevelDB::~Database_LevelDB()
|
||||||
{
|
{
|
||||||
return 1;
|
delete m_database;
|
||||||
}
|
}
|
||||||
|
|
||||||
void Database_LevelDB::beginSave() {}
|
bool Database_LevelDB::saveBlock(const v3s16 &pos, const std::string &data)
|
||||||
void Database_LevelDB::endSave() {}
|
|
||||||
|
|
||||||
bool Database_LevelDB::saveBlock(v3s16 blockpos, std::string &data)
|
|
||||||
{
|
{
|
||||||
leveldb::Status status = m_database->Put(leveldb::WriteOptions(),
|
leveldb::Status status = m_database->Put(leveldb::WriteOptions(),
|
||||||
i64tos(getBlockAsInteger(blockpos)), data);
|
i64tos(getBlockAsInteger(pos)), data);
|
||||||
if (!status.ok()) {
|
if (!status.ok()) {
|
||||||
errorstream << "WARNING: saveBlock: LevelDB error saving block "
|
errorstream << "WARNING: saveBlock: LevelDB error saving block "
|
||||||
<< PP(blockpos) << ": " << status.ToString() << std::endl;
|
<< PP(pos) << ": " << status.ToString() << std::endl;
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
std::string Database_LevelDB::loadBlock(v3s16 blockpos)
|
std::string Database_LevelDB::loadBlock(const v3s16 &pos)
|
||||||
{
|
{
|
||||||
std::string datastr;
|
std::string datastr;
|
||||||
leveldb::Status status = m_database->Get(leveldb::ReadOptions(),
|
leveldb::Status status = m_database->Get(leveldb::ReadOptions(),
|
||||||
i64tos(getBlockAsInteger(blockpos)), &datastr);
|
i64tos(getBlockAsInteger(pos)), &datastr);
|
||||||
|
|
||||||
if(status.ok())
|
if(status.ok())
|
||||||
return datastr;
|
return datastr;
|
||||||
|
@ -80,20 +77,20 @@ std::string Database_LevelDB::loadBlock(v3s16 blockpos)
|
||||||
return "";
|
return "";
|
||||||
}
|
}
|
||||||
|
|
||||||
bool Database_LevelDB::deleteBlock(v3s16 blockpos)
|
bool Database_LevelDB::deleteBlock(const v3s16 &pos)
|
||||||
{
|
{
|
||||||
leveldb::Status status = m_database->Delete(leveldb::WriteOptions(),
|
leveldb::Status status = m_database->Delete(leveldb::WriteOptions(),
|
||||||
i64tos(getBlockAsInteger(blockpos)));
|
i64tos(getBlockAsInteger(pos)));
|
||||||
if (!status.ok()) {
|
if (!status.ok()) {
|
||||||
errorstream << "WARNING: deleteBlock: LevelDB error deleting block "
|
errorstream << "WARNING: deleteBlock: LevelDB error deleting block "
|
||||||
<< PP(blockpos) << ": " << status.ToString() << std::endl;
|
<< PP(pos) << ": " << status.ToString() << std::endl;
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
return true;
|
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());
|
leveldb::Iterator* it = m_database->NewIterator(leveldb::ReadOptions());
|
||||||
for (it->SeekToFirst(); it->Valid(); it->Next()) {
|
for (it->SeekToFirst(); it->Valid(); it->Next()) {
|
||||||
|
@ -103,8 +100,5 @@ void Database_LevelDB::listAllLoadableBlocks(std::list<v3s16> &dst)
|
||||||
delete it;
|
delete it;
|
||||||
}
|
}
|
||||||
|
|
||||||
Database_LevelDB::~Database_LevelDB()
|
#endif // USE_LEVELDB
|
||||||
{
|
|
||||||
delete m_database;
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
|
|
|
@ -28,23 +28,22 @@ with this program; if not, write to the Free Software Foundation, Inc.,
|
||||||
#include "leveldb/db.h"
|
#include "leveldb/db.h"
|
||||||
#include <string>
|
#include <string>
|
||||||
|
|
||||||
class ServerMap;
|
|
||||||
|
|
||||||
class Database_LevelDB : public Database
|
class Database_LevelDB : public Database
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
Database_LevelDB(ServerMap *map, std::string savedir);
|
Database_LevelDB(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);
|
|
||||||
~Database_LevelDB();
|
~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:
|
private:
|
||||||
ServerMap *srvmap;
|
leveldb::DB *m_database;
|
||||||
leveldb::DB* m_database;
|
|
||||||
};
|
};
|
||||||
|
|
||||||
|
#endif // USE_LEVELDB
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
#endif
|
|
||||||
|
|
|
@ -20,151 +20,140 @@ with this program; if not, write to the Free Software Foundation, Inc.,
|
||||||
#include "config.h"
|
#include "config.h"
|
||||||
|
|
||||||
#if USE_REDIS
|
#if USE_REDIS
|
||||||
/*
|
|
||||||
Redis databases
|
|
||||||
*/
|
|
||||||
|
|
||||||
|
|
||||||
#include "database-redis.h"
|
#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 "settings.h"
|
||||||
#include "log.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;
|
std::string tmp;
|
||||||
try {
|
try {
|
||||||
tmp = conf.get("redis_address");
|
tmp = conf.get("redis_address");
|
||||||
hash = conf.get("redis_hash");
|
hash = conf.get("redis_hash");
|
||||||
} catch(SettingNotFoundException e) {
|
} catch (SettingNotFoundException) {
|
||||||
throw SettingNotFoundException("Set redis_address and redis_hash in world.mt to use the redis backend");
|
throw SettingNotFoundException("Set redis_address and "
|
||||||
|
"redis_hash in world.mt to use the redis backend");
|
||||||
}
|
}
|
||||||
const char *addr = tmp.c_str();
|
const char *addr = tmp.c_str();
|
||||||
int port = conf.exists("redis_port") ? conf.getU16("redis_port") : 6379;
|
int port = conf.exists("redis_port") ? conf.getU16("redis_port") : 6379;
|
||||||
ctx = redisConnect(addr, port);
|
ctx = redisConnect(addr, port);
|
||||||
if(!ctx)
|
if (!ctx) {
|
||||||
throw FileNotGoodException("Cannot allocate redis context");
|
throw FileNotGoodException("Cannot allocate redis context");
|
||||||
else if(ctx->err) {
|
} else if(ctx->err) {
|
||||||
std::string err = std::string("Connection error: ") + ctx->errstr;
|
std::string err = std::string("Connection error: ") + ctx->errstr;
|
||||||
redisFree(ctx);
|
redisFree(ctx);
|
||||||
throw FileNotGoodException(err);
|
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()
|
Database_Redis::~Database_Redis()
|
||||||
{
|
{
|
||||||
redisFree(ctx);
|
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
|
||||||
|
|
||||||
|
|
|
@ -28,24 +28,28 @@ with this program; if not, write to the Free Software Foundation, Inc.,
|
||||||
#include <hiredis.h>
|
#include <hiredis.h>
|
||||||
#include <string>
|
#include <string>
|
||||||
|
|
||||||
class ServerMap;
|
class Settings;
|
||||||
|
|
||||||
class Database_Redis : public Database
|
class Database_Redis : public Database
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
Database_Redis(ServerMap *map, std::string savedir);
|
Database_Redis(Settings &conf);
|
||||||
|
~Database_Redis();
|
||||||
|
|
||||||
virtual void beginSave();
|
virtual void beginSave();
|
||||||
virtual void endSave();
|
virtual void endSave();
|
||||||
virtual bool saveBlock(v3s16 blockpos, std::string &data);
|
|
||||||
virtual std::string loadBlock(v3s16 blockpos);
|
virtual bool saveBlock(const v3s16 &pos, const std::string &data);
|
||||||
virtual bool deleteBlock(v3s16 blockpos);
|
virtual std::string loadBlock(const v3s16 &pos);
|
||||||
virtual void listAllLoadableBlocks(std::list<v3s16> &dst);
|
virtual bool deleteBlock(const v3s16 &pos);
|
||||||
virtual int Initialized(void);
|
virtual void listAllLoadableBlocks(std::vector<v3s16> &dst);
|
||||||
~Database_Redis();
|
|
||||||
private:
|
private:
|
||||||
ServerMap *srvmap;
|
|
||||||
redisContext *ctx;
|
redisContext *ctx;
|
||||||
std::string hash;
|
std::string hash;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
#endif // USE_REDIS
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
#endif
|
|
||||||
|
|
|
@ -18,297 +18,231 @@ with this program; if not, write to the Free Software Foundation, Inc.,
|
||||||
*/
|
*/
|
||||||
|
|
||||||
/*
|
/*
|
||||||
SQLite format specification:
|
SQLite format specification:
|
||||||
- Initially only replaces sectors/ and sectors2/
|
blocks:
|
||||||
|
(PK) INT id
|
||||||
If map.sqlite does not exist in the save dir
|
BLOB data
|
||||||
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
|
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
|
||||||
#include "database-sqlite3.h"
|
#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 "log.h"
|
||||||
#include "filesys.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)
|
#include <cassert>
|
||||||
{
|
|
||||||
m_database = NULL;
|
|
||||||
m_database_read = NULL;
|
|
||||||
m_database_write = NULL;
|
|
||||||
m_database_list = NULL;
|
|
||||||
m_database_delete = NULL;
|
|
||||||
m_savedir = savedir;
|
|
||||||
srvmap = map;
|
|
||||||
}
|
|
||||||
|
|
||||||
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() {
|
void Database_SQLite3::beginSave() {
|
||||||
verifyDatabase();
|
verifyDatabase();
|
||||||
if(sqlite3_exec(m_database, "BEGIN;", NULL, NULL, NULL) != SQLITE_OK)
|
SQLRES(sqlite3_step(m_stmt_begin), SQLITE_DONE);
|
||||||
errorstream<<"WARNING: beginSave() failed, saving might be slow.";
|
sqlite3_reset(m_stmt_begin);
|
||||||
}
|
}
|
||||||
|
|
||||||
void Database_SQLite3::endSave() {
|
void Database_SQLite3::endSave() {
|
||||||
verifyDatabase();
|
verifyDatabase();
|
||||||
if(sqlite3_exec(m_database, "COMMIT;", NULL, NULL, NULL) != SQLITE_OK)
|
SQLRES(sqlite3_step(m_stmt_end), SQLITE_DONE);
|
||||||
errorstream<<"WARNING: endSave() failed, map might not have saved.";
|
sqlite3_reset(m_stmt_end);
|
||||||
}
|
}
|
||||||
|
|
||||||
void Database_SQLite3::createDirs(std::string path)
|
void Database_SQLite3::openDatabase()
|
||||||
{
|
{
|
||||||
if(fs::CreateAllDirs(path) == false)
|
if (m_database) return;
|
||||||
{
|
|
||||||
infostream<<DTIME<<"Database_SQLite3: Failed to create directory "
|
|
||||||
<<"\""<<path<<"\""<<std::endl;
|
|
||||||
throw BaseException("Database_SQLite3 failed to create directory");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void Database_SQLite3::verifyDatabase() {
|
std::string dbp = m_savedir + DIR_DELIM + "map.sqlite";
|
||||||
if(m_database)
|
|
||||||
return;
|
|
||||||
|
|
||||||
std::string dbp = m_savedir + DIR_DELIM "map.sqlite";
|
|
||||||
bool needs_create = false;
|
|
||||||
int d;
|
|
||||||
|
|
||||||
// Open the database connection
|
// 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))
|
bool needs_create = !fs::PathExists(dbp);
|
||||||
needs_create = true;
|
|
||||||
|
|
||||||
d = sqlite3_open_v2(dbp.c_str(), &m_database, SQLITE_OPEN_READWRITE | SQLITE_OPEN_CREATE, NULL);
|
if (sqlite3_open_v2(dbp.c_str(), &m_database,
|
||||||
if(d != SQLITE_OK) {
|
SQLITE_OPEN_READWRITE | SQLITE_OPEN_CREATE,
|
||||||
errorstream<<"SQLite3 database failed to open: "<<sqlite3_errmsg(m_database)<<std::endl;
|
NULL) != SQLITE_OK) {
|
||||||
|
errorstream << "SQLite3 database failed to open: "
|
||||||
|
<< sqlite3_errmsg(m_database) << std::endl;
|
||||||
throw FileNotGoodException("Cannot open database file");
|
throw FileNotGoodException("Cannot open database file");
|
||||||
}
|
}
|
||||||
|
|
||||||
if(needs_create)
|
if (needs_create) {
|
||||||
createDatabase();
|
createDatabase();
|
||||||
|
}
|
||||||
|
|
||||||
std::string querystr = std::string("PRAGMA synchronous = ")
|
std::string query_str = std::string("PRAGMA synchronous = ")
|
||||||
+ itos(g_settings->getU16("sqlite_synchronous"));
|
+ itos(g_settings->getU16("sqlite_synchronous"));
|
||||||
d = sqlite3_exec(m_database, querystr.c_str(), NULL, NULL, NULL);
|
SQLOK(sqlite3_exec(m_database, query_str.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");
|
|
||||||
}
|
|
||||||
|
|
||||||
d = sqlite3_prepare(m_database, "SELECT `data` FROM `blocks` WHERE `pos`=? LIMIT 1", -1, &m_database_read, NULL);
|
void Database_SQLite3::verifyDatabase()
|
||||||
if(d != SQLITE_OK) {
|
{
|
||||||
errorstream<<"SQLite3 read statment failed to prepare: "<<sqlite3_errmsg(m_database)<<std::endl;
|
if (m_initialized) return;
|
||||||
throw FileNotGoodException("Cannot prepare read statement");
|
|
||||||
}
|
openDatabase();
|
||||||
|
|
||||||
|
PREPARE_STATEMENT(begin, "BEGIN");
|
||||||
|
PREPARE_STATEMENT(end, "COMMIT");
|
||||||
|
PREPARE_STATEMENT(read, "SELECT `data` FROM `blocks` WHERE `pos` = ? LIMIT 1");
|
||||||
#ifdef __ANDROID__
|
#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
|
#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
|
#endif
|
||||||
if(d != SQLITE_OK) {
|
PREPARE_STATEMENT(delete, "DELETE FROM `blocks` WHERE `pos` = ?");
|
||||||
errorstream<<"SQLite3 write statment failed to prepare: "<<sqlite3_errmsg(m_database)<<std::endl;
|
PREPARE_STATEMENT(list, "SELECT `pos` FROM `blocks`");
|
||||||
throw FileNotGoodException("Cannot prepare write statement");
|
|
||||||
}
|
|
||||||
|
|
||||||
d = sqlite3_prepare(m_database, "DELETE FROM `blocks` WHERE `pos`=?;", -1, &m_database_delete, NULL);
|
m_initialized = true;
|
||||||
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");
|
|
||||||
}
|
|
||||||
|
|
||||||
d = sqlite3_prepare(m_database, "SELECT `pos` FROM `blocks`", -1, &m_database_list, NULL);
|
verbosestream << "ServerMap: SQLite3 database opened." << std::endl;
|
||||||
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;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
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();
|
verifyDatabase();
|
||||||
|
|
||||||
if (sqlite3_bind_int64(m_database_delete, 1,
|
bindPos(m_stmt_delete, pos);
|
||||||
getBlockAsInteger(blockpos)) != SQLITE_OK) {
|
|
||||||
errorstream << "WARNING: Could not bind block position for delete: "
|
|
||||||
<< sqlite3_errmsg(m_database) << std::endl;
|
|
||||||
}
|
|
||||||
|
|
||||||
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 "
|
errorstream << "WARNING: deleteBlock: Block failed to delete "
|
||||||
<< PP(blockpos) << ": " << sqlite3_errmsg(m_database) << std::endl;
|
<< PP(pos) << ": " << sqlite3_errmsg(m_database) << std::endl;
|
||||||
sqlite3_reset(m_database_delete);
|
|
||||||
return false;
|
|
||||||
}
|
}
|
||||||
|
return good;
|
||||||
sqlite3_reset(m_database_delete);
|
|
||||||
return true;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
bool Database_SQLite3::saveBlock(v3s16 blockpos, std::string &data)
|
bool Database_SQLite3::saveBlock(const v3s16 &pos, const std::string &data)
|
||||||
{
|
{
|
||||||
verifyDatabase();
|
verifyDatabase();
|
||||||
|
|
||||||
s64 bkey = getBlockAsInteger(blockpos);
|
|
||||||
|
|
||||||
#ifdef __ANDROID__
|
#ifdef __ANDROID__
|
||||||
/**
|
/**
|
||||||
* Note: For some unknown reason sqlite3 fails to REPLACE blocks on android,
|
* Note: For some unknown reason SQLite3 fails to REPLACE blocks on Android,
|
||||||
* deleting them and inserting first works.
|
* deleting them and then inserting works.
|
||||||
*/
|
*/
|
||||||
if (sqlite3_bind_int64(m_database_read, 1, bkey) != SQLITE_OK) {
|
bindPos(m_stmt_read, pos);
|
||||||
infostream << "WARNING: Could not bind block position for load: "
|
|
||||||
<< sqlite3_errmsg(m_database)<<std::endl;
|
if (sqlite3_step(m_stmt_read) == SQLITE_ROW) {
|
||||||
}
|
deleteBlock(pos);
|
||||||
|
|
||||||
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);
|
|
||||||
}
|
}
|
||||||
|
sqlite3_reset(m_stmt_read);
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
if (sqlite3_bind_int64(m_database_write, 1, bkey) != SQLITE_OK) {
|
bindPos(m_stmt_write, pos);
|
||||||
errorstream << "WARNING: saveBlock: Block position failed to bind: "
|
SQLOK(sqlite3_bind_blob(m_stmt_write, 2, data.data(), data.size(), NULL));
|
||||||
<< PP(blockpos) << ": " << sqlite3_errmsg(m_database) << std::endl;
|
|
||||||
sqlite3_reset(m_database_write);
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (sqlite3_bind_blob(m_database_write, 2, (void *)data.c_str(),
|
SQLRES(sqlite3_step(m_stmt_write), SQLITE_DONE)
|
||||||
data.size(), NULL) != SQLITE_OK) {
|
sqlite3_reset(m_stmt_write);
|
||||||
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);
|
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
std::string Database_SQLite3::loadBlock(v3s16 blockpos)
|
std::string Database_SQLite3::loadBlock(const v3s16 &pos)
|
||||||
{
|
{
|
||||||
verifyDatabase();
|
verifyDatabase();
|
||||||
|
|
||||||
if (sqlite3_bind_int64(m_database_read, 1, getBlockAsInteger(blockpos)) != SQLITE_OK) {
|
bindPos(m_stmt_read, pos);
|
||||||
errorstream << "Could not bind block position for load: "
|
|
||||||
<< sqlite3_errmsg(m_database)<<std::endl;
|
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) {
|
std::string s;
|
||||||
const char *data = (const char *) sqlite3_column_blob(m_database_read, 0);
|
if (data)
|
||||||
size_t len = sqlite3_column_bytes(m_database_read, 0);
|
s = std::string(data, len);
|
||||||
|
|
||||||
std::string s = "";
|
sqlite3_step(m_stmt_read);
|
||||||
if(data)
|
// We should never get more than 1 row, so ok to reset
|
||||||
s = std::string(data, len);
|
sqlite3_reset(m_stmt_read);
|
||||||
|
|
||||||
sqlite3_step(m_database_read);
|
return s;
|
||||||
// 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 "";
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void Database_SQLite3::createDatabase()
|
void Database_SQLite3::createDatabase()
|
||||||
{
|
{
|
||||||
int e;
|
|
||||||
assert(m_database);
|
assert(m_database);
|
||||||
e = sqlite3_exec(m_database,
|
SQLOK(sqlite3_exec(m_database,
|
||||||
"CREATE TABLE IF NOT EXISTS `blocks` ("
|
"CREATE TABLE IF NOT EXISTS `blocks` (\n"
|
||||||
"`pos` INT NOT NULL PRIMARY KEY,"
|
" `pos` INT PRIMARY KEY,\n"
|
||||||
"`data` BLOB"
|
" `data` BLOB\n"
|
||||||
");"
|
");\n",
|
||||||
, NULL, NULL, NULL);
|
NULL, NULL, NULL));
|
||||||
if(e != SQLITE_OK)
|
|
||||||
throw FileNotGoodException("Could not create sqlite3 database structure");
|
|
||||||
else
|
|
||||||
infostream<<"ServerMap: SQLite3 database structure was created";
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void Database_SQLite3::listAllLoadableBlocks(std::list<v3s16> &dst)
|
void Database_SQLite3::listAllLoadableBlocks(std::vector<v3s16> &dst)
|
||||||
{
|
{
|
||||||
verifyDatabase();
|
verifyDatabase();
|
||||||
|
|
||||||
while(sqlite3_step(m_database_list) == SQLITE_ROW)
|
while (sqlite3_step(m_stmt_list) == SQLITE_ROW) {
|
||||||
{
|
dst.push_back(getIntegerAsBlock(sqlite3_column_int64(m_stmt_list, 0)));
|
||||||
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);
|
|
||||||
}
|
}
|
||||||
|
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()
|
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)
|
if (sqlite3_close(m_database) != SQLITE_OK) {
|
||||||
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) {
|
|
||||||
errorstream << "Database_SQLite3::~Database_SQLite3(): "
|
errorstream << "Database_SQLite3::~Database_SQLite3(): "
|
||||||
<< "Failed to close database: rc=" << rc << std::endl;
|
<< "Failed to close database: "
|
||||||
|
<< sqlite3_errmsg(m_database) << std::endl;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -27,35 +27,43 @@ extern "C" {
|
||||||
#include "sqlite3.h"
|
#include "sqlite3.h"
|
||||||
}
|
}
|
||||||
|
|
||||||
class ServerMap;
|
|
||||||
|
|
||||||
class Database_SQLite3 : public Database
|
class Database_SQLite3 : public Database
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
Database_SQLite3(ServerMap *map, std::string savedir);
|
Database_SQLite3(const std::string &savedir);
|
||||||
|
|
||||||
virtual void beginSave();
|
virtual void beginSave();
|
||||||
virtual void endSave();
|
virtual void endSave();
|
||||||
|
|
||||||
virtual bool saveBlock(v3s16 blockpos, std::string &data);
|
virtual bool saveBlock(const v3s16 &pos, const std::string &data);
|
||||||
virtual std::string loadBlock(v3s16 blockpos);
|
virtual std::string loadBlock(const v3s16 &pos);
|
||||||
virtual bool deleteBlock(v3s16 blockpos);
|
virtual bool deleteBlock(const v3s16 &pos);
|
||||||
virtual void listAllLoadableBlocks(std::list<v3s16> &dst);
|
virtual void listAllLoadableBlocks(std::vector<v3s16> &dst);
|
||||||
virtual int Initialized(void);
|
virtual bool initialized() const { return m_initialized; }
|
||||||
~Database_SQLite3();
|
~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
|
// Create the database structure
|
||||||
void createDatabase();
|
void createDatabase();
|
||||||
// Verify we can read/write to the database
|
// Open and initialize the database if needed
|
||||||
void verifyDatabase();
|
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
|
#endif
|
||||||
|
|
||||||
|
|
|
@ -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 +
|
return (u64) pos.Z * 0x1000000 +
|
||||||
(u64) pos.Y * 0x1000 +
|
(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;
|
v3s16 pos;
|
||||||
pos.X = unsigned_to_signed(pythonmodulo(i, 4096), 2048);
|
pos.X = unsigned_to_signed(pythonmodulo(i, 4096), 2048);
|
||||||
|
|
|
@ -20,7 +20,7 @@ with this program; if not, write to the Free Software Foundation, Inc.,
|
||||||
#ifndef DATABASE_HEADER
|
#ifndef DATABASE_HEADER
|
||||||
#define DATABASE_HEADER
|
#define DATABASE_HEADER
|
||||||
|
|
||||||
#include <list>
|
#include <vector>
|
||||||
#include <string>
|
#include <string>
|
||||||
#include "irr_v3d.h"
|
#include "irr_v3d.h"
|
||||||
#include "irrlichttypes.h"
|
#include "irrlichttypes.h"
|
||||||
|
@ -32,16 +32,22 @@ with this program; if not, write to the Free Software Foundation, Inc.,
|
||||||
class Database
|
class Database
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
virtual void beginSave() = 0;
|
virtual ~Database() {}
|
||||||
virtual void endSave() = 0;
|
|
||||||
|
|
||||||
virtual bool saveBlock(v3s16 blockpos, std::string &data) = 0;
|
virtual void beginSave() {}
|
||||||
virtual std::string loadBlock(v3s16 blockpos) = 0;
|
virtual void endSave() {}
|
||||||
virtual bool deleteBlock(v3s16 blockpos) = 0;
|
|
||||||
s64 getBlockAsInteger(const v3s16 pos) const;
|
virtual bool saveBlock(const v3s16 &pos, const std::string &data) = 0;
|
||||||
v3s16 getIntegerAsBlock(s64 i) const;
|
virtual std::string loadBlock(const v3s16 &pos) = 0;
|
||||||
virtual void listAllLoadableBlocks(std::list<v3s16> &dst) = 0;
|
virtual bool deleteBlock(const v3s16 &pos) = 0;
|
||||||
virtual int Initialized(void)=0;
|
|
||||||
virtual ~Database() {};
|
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
|
#endif
|
||||||
|
|
||||||
|
|
|
@ -48,6 +48,7 @@ void set_default_settings(Settings *settings)
|
||||||
settings->setDefault("keymap_freemove", "KEY_KEY_K");
|
settings->setDefault("keymap_freemove", "KEY_KEY_K");
|
||||||
settings->setDefault("keymap_fastmove", "KEY_KEY_J");
|
settings->setDefault("keymap_fastmove", "KEY_KEY_J");
|
||||||
settings->setDefault("keymap_noclip", "KEY_KEY_H");
|
settings->setDefault("keymap_noclip", "KEY_KEY_H");
|
||||||
|
settings->setDefault("keymap_cinematic", "KEY_F8");
|
||||||
settings->setDefault("keymap_screenshot", "KEY_F12");
|
settings->setDefault("keymap_screenshot", "KEY_F12");
|
||||||
settings->setDefault("keymap_toggle_hud", "KEY_F1");
|
settings->setDefault("keymap_toggle_hud", "KEY_F1");
|
||||||
settings->setDefault("keymap_toggle_chat", "KEY_F2");
|
settings->setDefault("keymap_toggle_chat", "KEY_F2");
|
||||||
|
@ -115,6 +116,9 @@ void set_default_settings(Settings *settings)
|
||||||
settings->setDefault("free_move", "false");
|
settings->setDefault("free_move", "false");
|
||||||
settings->setDefault("noclip", "false");
|
settings->setDefault("noclip", "false");
|
||||||
settings->setDefault("continuous_forward", "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("fast_move", "false");
|
||||||
settings->setDefault("invert_mouse", "false");
|
settings->setDefault("invert_mouse", "false");
|
||||||
settings->setDefault("enable_clouds", "true");
|
settings->setDefault("enable_clouds", "true");
|
||||||
|
@ -288,6 +292,7 @@ void set_default_settings(Settings *settings)
|
||||||
settings->setDefault("water_level", "1");
|
settings->setDefault("water_level", "1");
|
||||||
settings->setDefault("chunksize", "5");
|
settings->setDefault("chunksize", "5");
|
||||||
settings->setDefault("mg_flags", "");
|
settings->setDefault("mg_flags", "");
|
||||||
|
settings->setDefault("enable_floating_dungeons", "true");
|
||||||
|
|
||||||
// IPv6
|
// IPv6
|
||||||
settings->setDefault("enable_ipv6", "true");
|
settings->setDefault("enable_ipv6", "true");
|
||||||
|
|
|
@ -79,14 +79,17 @@ void DungeonGen::generate(u32 bseed, v3s16 nmin, v3s16 nmax) {
|
||||||
// Dungeon generator doesn't modify places which have this set
|
// Dungeon generator doesn't modify places which have this set
|
||||||
vm->clearFlag(VMANIP_FLAG_DUNGEON_INSIDE | VMANIP_FLAG_DUNGEON_PRESERVE);
|
vm->clearFlag(VMANIP_FLAG_DUNGEON_INSIDE | VMANIP_FLAG_DUNGEON_PRESERVE);
|
||||||
|
|
||||||
// Set all air and water to be untouchable to make dungeons open
|
bool no_float = !g_settings->getBool("enable_floating_dungeons");
|
||||||
// to caves and open air
|
|
||||||
|
// 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 z = nmin.Z; z <= nmax.Z; z++) {
|
||||||
for (s16 y = nmin.Y; y <= nmax.Y; y++) {
|
for (s16 y = nmin.Y; y <= nmax.Y; y++) {
|
||||||
u32 i = vm->m_area.index(nmin.X, y, z);
|
u32 i = vm->m_area.index(nmin.X, y, z);
|
||||||
for (s16 x = nmin.X; x <= nmax.X; x++) {
|
for (s16 x = nmin.X; x <= nmax.X; x++) {
|
||||||
content_t c = vm->m_data[i].getContent();
|
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;
|
vm->m_flags[i] |= VMANIP_FLAG_DUNGEON_PRESERVE;
|
||||||
i++;
|
i++;
|
||||||
}
|
}
|
||||||
|
|
|
@ -361,7 +361,10 @@ void EmergeManager::loadParamsFromSettings(Settings *settings)
|
||||||
std::string seed_str;
|
std::string seed_str;
|
||||||
const char *setname = (settings == g_settings) ? "fixed_map_seed" : "seed";
|
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());
|
params.seed = read_seed(seed_str.c_str());
|
||||||
} else {
|
} else {
|
||||||
params.seed =
|
params.seed =
|
||||||
|
|
|
@ -61,9 +61,8 @@ Environment::Environment():
|
||||||
Environment::~Environment()
|
Environment::~Environment()
|
||||||
{
|
{
|
||||||
// Deallocate players
|
// Deallocate players
|
||||||
for(std::list<Player*>::iterator i = m_players.begin();
|
for(std::vector<Player*>::iterator i = m_players.begin();
|
||||||
i != m_players.end(); ++i)
|
i != m_players.end(); ++i) {
|
||||||
{
|
|
||||||
delete (*i);
|
delete (*i);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -89,7 +88,7 @@ void Environment::removePlayer(u16 peer_id)
|
||||||
{
|
{
|
||||||
DSTACK(__FUNCTION_NAME);
|
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();)
|
i != m_players.end();)
|
||||||
{
|
{
|
||||||
Player *player = *i;
|
Player *player = *i;
|
||||||
|
@ -104,7 +103,7 @@ void Environment::removePlayer(u16 peer_id)
|
||||||
|
|
||||||
void Environment::removePlayer(const char *name)
|
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) {
|
it != m_players.end(); ++it) {
|
||||||
if (strcmp((*it)->getName(), name) == 0) {
|
if (strcmp((*it)->getName(), name) == 0) {
|
||||||
delete *it;
|
delete *it;
|
||||||
|
@ -116,9 +115,8 @@ void Environment::removePlayer(const char *name)
|
||||||
|
|
||||||
Player * Environment::getPlayer(u16 peer_id)
|
Player * Environment::getPlayer(u16 peer_id)
|
||||||
{
|
{
|
||||||
for(std::list<Player*>::iterator i = m_players.begin();
|
for(std::vector<Player*>::iterator i = m_players.begin();
|
||||||
i != m_players.end(); ++i)
|
i != m_players.end(); ++i) {
|
||||||
{
|
|
||||||
Player *player = *i;
|
Player *player = *i;
|
||||||
if(player->peer_id == peer_id)
|
if(player->peer_id == peer_id)
|
||||||
return player;
|
return player;
|
||||||
|
@ -128,9 +126,8 @@ Player * Environment::getPlayer(u16 peer_id)
|
||||||
|
|
||||||
Player * Environment::getPlayer(const char *name)
|
Player * Environment::getPlayer(const char *name)
|
||||||
{
|
{
|
||||||
for(std::list<Player*>::iterator i = m_players.begin();
|
for(std::vector<Player*>::iterator i = m_players.begin();
|
||||||
i != m_players.end(); ++i)
|
i != m_players.end(); ++i) {
|
||||||
{
|
|
||||||
Player *player = *i;
|
Player *player = *i;
|
||||||
if(strcmp(player->getName(), name) == 0)
|
if(strcmp(player->getName(), name) == 0)
|
||||||
return player;
|
return player;
|
||||||
|
@ -140,15 +137,13 @@ Player * Environment::getPlayer(const char *name)
|
||||||
|
|
||||||
Player * Environment::getRandomConnectedPlayer()
|
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 chosen_one = myrand() % connected_players.size();
|
||||||
u32 j = 0;
|
u32 j = 0;
|
||||||
for(std::list<Player*>::iterator
|
for(std::vector<Player*>::iterator
|
||||||
i = connected_players.begin();
|
i = connected_players.begin();
|
||||||
i != connected_players.end(); ++i)
|
i != connected_players.end(); ++i) {
|
||||||
{
|
if(j == chosen_one) {
|
||||||
if(j == chosen_one)
|
|
||||||
{
|
|
||||||
Player *player = *i;
|
Player *player = *i;
|
||||||
return player;
|
return player;
|
||||||
}
|
}
|
||||||
|
@ -159,17 +154,15 @@ Player * Environment::getRandomConnectedPlayer()
|
||||||
|
|
||||||
Player * Environment::getNearestConnectedPlayer(v3f pos)
|
Player * Environment::getNearestConnectedPlayer(v3f pos)
|
||||||
{
|
{
|
||||||
std::list<Player*> connected_players = getPlayers(true);
|
std::vector<Player*> connected_players = getPlayers(true);
|
||||||
f32 nearest_d = 0;
|
f32 nearest_d = 0;
|
||||||
Player *nearest_player = NULL;
|
Player *nearest_player = NULL;
|
||||||
for(std::list<Player*>::iterator
|
for(std::vector<Player*>::iterator
|
||||||
i = connected_players.begin();
|
i = connected_players.begin();
|
||||||
i != connected_players.end(); ++i)
|
i != connected_players.end(); ++i) {
|
||||||
{
|
|
||||||
Player *player = *i;
|
Player *player = *i;
|
||||||
f32 d = player->getPosition().getDistanceFrom(pos);
|
f32 d = player->getPosition().getDistanceFrom(pos);
|
||||||
if(d < nearest_d || nearest_player == NULL)
|
if(d < nearest_d || nearest_player == NULL) {
|
||||||
{
|
|
||||||
nearest_d = d;
|
nearest_d = d;
|
||||||
nearest_player = player;
|
nearest_player = player;
|
||||||
}
|
}
|
||||||
|
@ -177,22 +170,20 @@ Player * Environment::getNearestConnectedPlayer(v3f pos)
|
||||||
return nearest_player;
|
return nearest_player;
|
||||||
}
|
}
|
||||||
|
|
||||||
std::list<Player*> Environment::getPlayers()
|
std::vector<Player*> Environment::getPlayers()
|
||||||
{
|
{
|
||||||
return m_players;
|
return m_players;
|
||||||
}
|
}
|
||||||
|
|
||||||
std::list<Player*> Environment::getPlayers(bool ignore_disconnected)
|
std::vector<Player*> Environment::getPlayers(bool ignore_disconnected)
|
||||||
{
|
{
|
||||||
std::list<Player*> newlist;
|
std::vector<Player*> newlist;
|
||||||
for(std::list<Player*>::iterator
|
for(std::vector<Player*>::iterator
|
||||||
i = m_players.begin();
|
i = m_players.begin();
|
||||||
i != m_players.end(); ++i)
|
i != m_players.end(); ++i) {
|
||||||
{
|
|
||||||
Player *player = *i;
|
Player *player = *i;
|
||||||
|
|
||||||
if(ignore_disconnected)
|
if(ignore_disconnected) {
|
||||||
{
|
|
||||||
// Ignore disconnected players
|
// Ignore disconnected players
|
||||||
if(player->peer_id == 0)
|
if(player->peer_id == 0)
|
||||||
continue;
|
continue;
|
||||||
|
@ -212,24 +203,42 @@ u32 Environment::getDayNightRatio()
|
||||||
|
|
||||||
void Environment::setTimeOfDaySpeed(float speed)
|
void Environment::setTimeOfDaySpeed(float speed)
|
||||||
{
|
{
|
||||||
JMutexAutoLock(this->m_lock);
|
JMutexAutoLock(this->m_timeofday_lock);
|
||||||
m_time_of_day_speed = speed;
|
m_time_of_day_speed = speed;
|
||||||
}
|
}
|
||||||
|
|
||||||
float Environment::getTimeOfDaySpeed()
|
float Environment::getTimeOfDaySpeed()
|
||||||
{
|
{
|
||||||
JMutexAutoLock(this->m_lock);
|
JMutexAutoLock(this->m_timeofday_lock);
|
||||||
float retval = m_time_of_day_speed;
|
float retval = m_time_of_day_speed;
|
||||||
return retval;
|
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)
|
void Environment::stepTimeOfDay(float dtime)
|
||||||
{
|
{
|
||||||
float day_speed = 0;
|
// getTimeOfDaySpeed lock the value we need to prevent MT problems
|
||||||
{
|
float day_speed = getTimeOfDaySpeed();
|
||||||
JMutexAutoLock(this->m_lock);
|
|
||||||
day_speed = m_time_of_day_speed;
|
|
||||||
}
|
|
||||||
|
|
||||||
m_time_counter += dtime;
|
m_time_counter += dtime;
|
||||||
f32 speed = day_speed * 24000./(24.*3600);
|
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,
|
s16 radius,
|
||||||
std::set<v3s16> &blocks_removed,
|
std::set<v3s16> &blocks_removed,
|
||||||
std::set<v3s16> &blocks_added)
|
std::set<v3s16> &blocks_added)
|
||||||
|
@ -296,7 +305,7 @@ void ActiveBlockList::update(std::list<v3s16> &active_positions,
|
||||||
Create the new list
|
Create the new list
|
||||||
*/
|
*/
|
||||||
std::set<v3s16> newlist = m_forceloaded_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)
|
i != active_positions.end(); ++i)
|
||||||
{
|
{
|
||||||
fillRadiusBlock(*i, radius, newlist);
|
fillRadiusBlock(*i, radius, newlist);
|
||||||
|
@ -373,7 +382,7 @@ ServerEnvironment::~ServerEnvironment()
|
||||||
m_map->drop();
|
m_map->drop();
|
||||||
|
|
||||||
// Delete ActiveBlockModifiers
|
// Delete ActiveBlockModifiers
|
||||||
for(std::list<ABMWithState>::iterator
|
for(std::vector<ABMWithState>::iterator
|
||||||
i = m_abms.begin(); i != m_abms.end(); ++i){
|
i = m_abms.begin(); i != m_abms.end(); ++i){
|
||||||
delete i->abm;
|
delete i->abm;
|
||||||
}
|
}
|
||||||
|
@ -395,8 +404,8 @@ bool ServerEnvironment::line_of_sight(v3f pos1, v3f pos2, float stepsize, v3s16
|
||||||
|
|
||||||
//calculate normalized direction vector
|
//calculate normalized direction vector
|
||||||
v3f normalized_vector = v3f((pos2.X - pos1.X)/distance,
|
v3f normalized_vector = v3f((pos2.X - pos1.X)/distance,
|
||||||
(pos2.Y - pos1.Y)/distance,
|
(pos2.Y - pos1.Y)/distance,
|
||||||
(pos2.Z - pos1.Z)/distance);
|
(pos2.Z - pos1.Z)/distance);
|
||||||
|
|
||||||
//find out if there's a node on path between pos1 and pos2
|
//find out if there's a node on path between pos1 and pos2
|
||||||
for (float i = 1; i < distance; i += stepsize) {
|
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";
|
std::string players_path = m_path_world + DIR_DELIM "players";
|
||||||
fs::CreateDir(players_path);
|
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 != m_players.end();
|
||||||
++it) {
|
++it) {
|
||||||
RemotePlayer *player = static_cast<RemotePlayer*>(*it);
|
RemotePlayer *player = static_cast<RemotePlayer*>(*it);
|
||||||
|
@ -549,9 +558,9 @@ class ABMHandler
|
||||||
{
|
{
|
||||||
private:
|
private:
|
||||||
ServerEnvironment *m_env;
|
ServerEnvironment *m_env;
|
||||||
std::map<content_t, std::list<ActiveABM> > m_aabms;
|
std::map<content_t, std::vector<ActiveABM> > m_aabms;
|
||||||
public:
|
public:
|
||||||
ABMHandler(std::list<ABMWithState> &abms,
|
ABMHandler(std::vector<ABMWithState> &abms,
|
||||||
float dtime_s, ServerEnvironment *env,
|
float dtime_s, ServerEnvironment *env,
|
||||||
bool use_timers):
|
bool use_timers):
|
||||||
m_env(env)
|
m_env(env)
|
||||||
|
@ -559,8 +568,8 @@ public:
|
||||||
if(dtime_s < 0.001)
|
if(dtime_s < 0.001)
|
||||||
return;
|
return;
|
||||||
INodeDefManager *ndef = env->getGameDef()->ndef();
|
INodeDefManager *ndef = env->getGameDef()->ndef();
|
||||||
for(std::list<ABMWithState>::iterator
|
for(std::vector<ABMWithState>::iterator
|
||||||
i = abms.begin(); i != abms.end(); ++i){
|
i = abms.begin(); i != abms.end(); ++i) {
|
||||||
ActiveBlockModifier *abm = i->abm;
|
ActiveBlockModifier *abm = i->abm;
|
||||||
float trigger_interval = abm->getTriggerInterval();
|
float trigger_interval = abm->getTriggerInterval();
|
||||||
if(trigger_interval < 0.001)
|
if(trigger_interval < 0.001)
|
||||||
|
@ -604,10 +613,10 @@ public:
|
||||||
k != ids.end(); k++)
|
k != ids.end(); k++)
|
||||||
{
|
{
|
||||||
content_t c = *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);
|
j = m_aabms.find(c);
|
||||||
if(j == m_aabms.end()){
|
if(j == m_aabms.end()){
|
||||||
std::list<ActiveABM> aabmlist;
|
std::vector<ActiveABM> aabmlist;
|
||||||
m_aabms[c] = aabmlist;
|
m_aabms[c] = aabmlist;
|
||||||
j = m_aabms.find(c);
|
j = m_aabms.find(c);
|
||||||
}
|
}
|
||||||
|
@ -664,14 +673,13 @@ public:
|
||||||
content_t c = n.getContent();
|
content_t c = n.getContent();
|
||||||
v3s16 p = p0 + block->getPosRelative();
|
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);
|
j = m_aabms.find(c);
|
||||||
if(j == m_aabms.end())
|
if(j == m_aabms.end())
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
for(std::list<ActiveABM>::iterator
|
for(std::vector<ActiveABM>::iterator
|
||||||
i = j->second.begin(); i != j->second.end(); i++)
|
i = j->second.begin(); i != j->second.end(); i++) {
|
||||||
{
|
|
||||||
if(myrand() % i->chance != 0)
|
if(myrand() % i->chance != 0)
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
|
@ -851,11 +859,10 @@ void ServerEnvironment::clearAllObjects()
|
||||||
{
|
{
|
||||||
infostream<<"ServerEnvironment::clearAllObjects(): "
|
infostream<<"ServerEnvironment::clearAllObjects(): "
|
||||||
<<"Removing all active objects"<<std::endl;
|
<<"Removing all active objects"<<std::endl;
|
||||||
std::list<u16> objects_to_remove;
|
std::vector<u16> objects_to_remove;
|
||||||
for(std::map<u16, ServerActiveObject*>::iterator
|
for(std::map<u16, ServerActiveObject*>::iterator
|
||||||
i = m_active_objects.begin();
|
i = m_active_objects.begin();
|
||||||
i != m_active_objects.end(); ++i)
|
i != m_active_objects.end(); ++i) {
|
||||||
{
|
|
||||||
ServerActiveObject* obj = i->second;
|
ServerActiveObject* obj = i->second;
|
||||||
if(obj->getType() == ACTIVEOBJECT_TYPE_PLAYER)
|
if(obj->getType() == ACTIVEOBJECT_TYPE_PLAYER)
|
||||||
continue;
|
continue;
|
||||||
|
@ -888,15 +895,15 @@ void ServerEnvironment::clearAllObjects()
|
||||||
// Id to be removed from m_active_objects
|
// Id to be removed from m_active_objects
|
||||||
objects_to_remove.push_back(id);
|
objects_to_remove.push_back(id);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Remove references from m_active_objects
|
// Remove references from m_active_objects
|
||||||
for(std::list<u16>::iterator i = objects_to_remove.begin();
|
for(std::vector<u16>::iterator i = objects_to_remove.begin();
|
||||||
i != objects_to_remove.end(); ++i)
|
i != objects_to_remove.end(); ++i) {
|
||||||
{
|
|
||||||
m_active_objects.erase(*i);
|
m_active_objects.erase(*i);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Get list of loaded blocks
|
// Get list of loaded blocks
|
||||||
std::list<v3s16> loaded_blocks;
|
std::vector<v3s16> loaded_blocks;
|
||||||
infostream<<"ServerEnvironment::clearAllObjects(): "
|
infostream<<"ServerEnvironment::clearAllObjects(): "
|
||||||
<<"Listing all loaded blocks"<<std::endl;
|
<<"Listing all loaded blocks"<<std::endl;
|
||||||
m_map->listAllLoadedBlocks(loaded_blocks);
|
m_map->listAllLoadedBlocks(loaded_blocks);
|
||||||
|
@ -905,7 +912,7 @@ void ServerEnvironment::clearAllObjects()
|
||||||
<<loaded_blocks.size()<<std::endl;
|
<<loaded_blocks.size()<<std::endl;
|
||||||
|
|
||||||
// Get list of loadable blocks
|
// Get list of loadable blocks
|
||||||
std::list<v3s16> loadable_blocks;
|
std::vector<v3s16> loadable_blocks;
|
||||||
infostream<<"ServerEnvironment::clearAllObjects(): "
|
infostream<<"ServerEnvironment::clearAllObjects(): "
|
||||||
<<"Listing all loadable blocks"<<std::endl;
|
<<"Listing all loadable blocks"<<std::endl;
|
||||||
m_map->listAllLoadableBlocks(loadable_blocks);
|
m_map->listAllLoadableBlocks(loadable_blocks);
|
||||||
|
@ -915,9 +922,8 @@ void ServerEnvironment::clearAllObjects()
|
||||||
<<", now clearing"<<std::endl;
|
<<", now clearing"<<std::endl;
|
||||||
|
|
||||||
// Grab a reference on each loaded block to avoid unloading it
|
// Grab a reference on each loaded block to avoid unloading it
|
||||||
for(std::list<v3s16>::iterator i = loaded_blocks.begin();
|
for(std::vector<v3s16>::iterator i = loaded_blocks.begin();
|
||||||
i != loaded_blocks.end(); ++i)
|
i != loaded_blocks.end(); ++i) {
|
||||||
{
|
|
||||||
v3s16 p = *i;
|
v3s16 p = *i;
|
||||||
MapBlock *block = m_map->getBlockNoCreateNoEx(p);
|
MapBlock *block = m_map->getBlockNoCreateNoEx(p);
|
||||||
assert(block);
|
assert(block);
|
||||||
|
@ -931,9 +937,8 @@ void ServerEnvironment::clearAllObjects()
|
||||||
u32 num_blocks_checked = 0;
|
u32 num_blocks_checked = 0;
|
||||||
u32 num_blocks_cleared = 0;
|
u32 num_blocks_cleared = 0;
|
||||||
u32 num_objs_cleared = 0;
|
u32 num_objs_cleared = 0;
|
||||||
for(std::list<v3s16>::iterator i = loadable_blocks.begin();
|
for(std::vector<v3s16>::iterator i = loadable_blocks.begin();
|
||||||
i != loadable_blocks.end(); ++i)
|
i != loadable_blocks.end(); ++i) {
|
||||||
{
|
|
||||||
v3s16 p = *i;
|
v3s16 p = *i;
|
||||||
MapBlock *block = m_map->emergeBlock(p, false);
|
MapBlock *block = m_map->emergeBlock(p, false);
|
||||||
if(!block){
|
if(!block){
|
||||||
|
@ -969,9 +974,8 @@ void ServerEnvironment::clearAllObjects()
|
||||||
m_map->unloadUnreferencedBlocks();
|
m_map->unloadUnreferencedBlocks();
|
||||||
|
|
||||||
// Drop references that were added above
|
// Drop references that were added above
|
||||||
for(std::list<v3s16>::iterator i = loaded_blocks.begin();
|
for(std::vector<v3s16>::iterator i = loaded_blocks.begin();
|
||||||
i != loaded_blocks.end(); ++i)
|
i != loaded_blocks.end(); ++i) {
|
||||||
{
|
|
||||||
v3s16 p = *i;
|
v3s16 p = *i;
|
||||||
MapBlock *block = m_map->getBlockNoCreateNoEx(p);
|
MapBlock *block = m_map->getBlockNoCreateNoEx(p);
|
||||||
assert(block);
|
assert(block);
|
||||||
|
@ -1012,7 +1016,7 @@ void ServerEnvironment::step(float dtime)
|
||||||
*/
|
*/
|
||||||
{
|
{
|
||||||
ScopeProfiler sp(g_profiler, "SEnv: handle players avg", SPT_AVG);
|
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)
|
i != m_players.end(); ++i)
|
||||||
{
|
{
|
||||||
Player *player = *i;
|
Player *player = *i;
|
||||||
|
@ -1035,15 +1039,15 @@ void ServerEnvironment::step(float dtime)
|
||||||
/*
|
/*
|
||||||
Get player block positions
|
Get player block positions
|
||||||
*/
|
*/
|
||||||
std::list<v3s16> players_blockpos;
|
std::vector<v3s16> players_blockpos;
|
||||||
for(std::list<Player*>::iterator
|
for(std::vector<Player*>::iterator
|
||||||
i = m_players.begin();
|
i = m_players.begin();
|
||||||
i != m_players.end(); ++i)
|
i != m_players.end(); ++i) {
|
||||||
{
|
|
||||||
Player *player = *i;
|
Player *player = *i;
|
||||||
// Ignore disconnected players
|
// Ignore disconnected players
|
||||||
if(player->peer_id == 0)
|
if(player->peer_id == 0)
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
v3s16 blockpos = getNodeBlockPos(
|
v3s16 blockpos = getNodeBlockPos(
|
||||||
floatToInt(player->getPosition(), BS));
|
floatToInt(player->getPosition(), BS));
|
||||||
players_blockpos.push_back(blockpos);
|
players_blockpos.push_back(blockpos);
|
||||||
|
@ -1178,7 +1182,7 @@ void ServerEnvironment::step(float dtime)
|
||||||
<<") being handled"<<std::endl;*/
|
<<") being handled"<<std::endl;*/
|
||||||
|
|
||||||
MapBlock *block = m_map->getBlockNoCreateNoEx(p);
|
MapBlock *block = m_map->getBlockNoCreateNoEx(p);
|
||||||
if(block==NULL)
|
if(block == NULL)
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
// Set current time as timestamp
|
// Set current time as timestamp
|
||||||
|
@ -1542,11 +1546,10 @@ u16 ServerEnvironment::addActiveObjectRaw(ServerActiveObject *object,
|
||||||
*/
|
*/
|
||||||
void ServerEnvironment::removeRemovedObjects()
|
void ServerEnvironment::removeRemovedObjects()
|
||||||
{
|
{
|
||||||
std::list<u16> objects_to_remove;
|
std::vector<u16> objects_to_remove;
|
||||||
for(std::map<u16, ServerActiveObject*>::iterator
|
for(std::map<u16, ServerActiveObject*>::iterator
|
||||||
i = m_active_objects.begin();
|
i = m_active_objects.begin();
|
||||||
i != m_active_objects.end(); ++i)
|
i != m_active_objects.end(); ++i) {
|
||||||
{
|
|
||||||
u16 id = i->first;
|
u16 id = i->first;
|
||||||
ServerActiveObject* obj = i->second;
|
ServerActiveObject* obj = i->second;
|
||||||
// This shouldn't happen but check it
|
// This shouldn't happen but check it
|
||||||
|
@ -1616,13 +1619,13 @@ void ServerEnvironment::removeRemovedObjects()
|
||||||
// Delete
|
// Delete
|
||||||
if(obj->environmentDeletes())
|
if(obj->environmentDeletes())
|
||||||
delete obj;
|
delete obj;
|
||||||
|
|
||||||
// Id to be removed from m_active_objects
|
// Id to be removed from m_active_objects
|
||||||
objects_to_remove.push_back(id);
|
objects_to_remove.push_back(id);
|
||||||
}
|
}
|
||||||
// Remove references from m_active_objects
|
// Remove references from m_active_objects
|
||||||
for(std::list<u16>::iterator i = objects_to_remove.begin();
|
for(std::vector<u16>::iterator i = objects_to_remove.begin();
|
||||||
i != objects_to_remove.end(); ++i)
|
i != objects_to_remove.end(); ++i) {
|
||||||
{
|
|
||||||
m_active_objects.erase(*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)
|
void ServerEnvironment::activateObjects(MapBlock *block, u32 dtime_s)
|
||||||
{
|
{
|
||||||
if(block==NULL)
|
if(block == NULL)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
// Ignore if no stored objects (to not set changed flag)
|
// Ignore if no stored objects (to not set changed flag)
|
||||||
if(block->m_static_objects.m_stored.empty())
|
if(block->m_static_objects.m_stored.empty())
|
||||||
return;
|
return;
|
||||||
|
|
||||||
verbosestream<<"ServerEnvironment::activateObjects(): "
|
verbosestream<<"ServerEnvironment::activateObjects(): "
|
||||||
<<"activating objects of block "<<PP(block->getPos())
|
<<"activating objects of block "<<PP(block->getPos())
|
||||||
<<" ("<<block->m_static_objects.m_stored.size()
|
<<" ("<<block->m_static_objects.m_stored.size()
|
||||||
<<" objects)"<<std::endl;
|
<<" objects)"<<std::endl;
|
||||||
bool large_amount = (block->m_static_objects.m_stored.size() > g_settings->getU16("max_objects_per_block"));
|
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: "
|
errorstream<<"suspiciously large amount of objects detected: "
|
||||||
<<block->m_static_objects.m_stored.size()<<" in "
|
<<block->m_static_objects.m_stored.size()<<" in "
|
||||||
<<PP(block->getPos())
|
<<PP(block->getPos())
|
||||||
|
@ -1690,20 +1695,17 @@ void ServerEnvironment::activateObjects(MapBlock *block, u32 dtime_s)
|
||||||
}
|
}
|
||||||
|
|
||||||
// Activate stored objects
|
// Activate stored objects
|
||||||
std::list<StaticObject> new_stored;
|
std::vector<StaticObject> new_stored;
|
||||||
for(std::list<StaticObject>::iterator
|
for (std::vector<StaticObject>::iterator
|
||||||
i = block->m_static_objects.m_stored.begin();
|
i = block->m_static_objects.m_stored.begin();
|
||||||
i != block->m_static_objects.m_stored.end(); ++i)
|
i != block->m_static_objects.m_stored.end(); ++i) {
|
||||||
{
|
|
||||||
/*infostream<<"Server: Creating an active object from "
|
|
||||||
<<"static data"<<std::endl;*/
|
|
||||||
StaticObject &s_obj = *i;
|
StaticObject &s_obj = *i;
|
||||||
|
|
||||||
// Create an active object from the data
|
// Create an active object from the data
|
||||||
ServerActiveObject *obj = ServerActiveObject::create
|
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 couldn't create object, store static data back.
|
||||||
if(obj==NULL)
|
if(obj == NULL) {
|
||||||
{
|
|
||||||
errorstream<<"ServerEnvironment::activateObjects(): "
|
errorstream<<"ServerEnvironment::activateObjects(): "
|
||||||
<<"failed to create active object from static object "
|
<<"failed to create active object from static object "
|
||||||
<<"in block "<<PP(s_obj.pos/BS)
|
<<"in block "<<PP(s_obj.pos/BS)
|
||||||
|
@ -1722,10 +1724,9 @@ void ServerEnvironment::activateObjects(MapBlock *block, u32 dtime_s)
|
||||||
// Clear stored list
|
// Clear stored list
|
||||||
block->m_static_objects.m_stored.clear();
|
block->m_static_objects.m_stored.clear();
|
||||||
// Add leftover failed stuff to stored list
|
// Add leftover failed stuff to stored list
|
||||||
for(std::list<StaticObject>::iterator
|
for(std::vector<StaticObject>::iterator
|
||||||
i = new_stored.begin();
|
i = new_stored.begin();
|
||||||
i != new_stored.end(); ++i)
|
i != new_stored.end(); ++i) {
|
||||||
{
|
|
||||||
StaticObject &s_obj = *i;
|
StaticObject &s_obj = *i;
|
||||||
block->m_static_objects.m_stored.push_back(s_obj);
|
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)
|
void ServerEnvironment::deactivateFarObjects(bool force_delete)
|
||||||
{
|
{
|
||||||
std::list<u16> objects_to_remove;
|
std::vector<u16> objects_to_remove;
|
||||||
for(std::map<u16, ServerActiveObject*>::iterator
|
for(std::map<u16, ServerActiveObject*>::iterator
|
||||||
i = m_active_objects.begin();
|
i = m_active_objects.begin();
|
||||||
i != m_active_objects.end(); ++i)
|
i != m_active_objects.end(); ++i) {
|
||||||
{
|
|
||||||
ServerActiveObject* obj = i->second;
|
ServerActiveObject* obj = i->second;
|
||||||
assert(obj);
|
assert(obj);
|
||||||
|
|
||||||
|
@ -1986,9 +1986,8 @@ void ServerEnvironment::deactivateFarObjects(bool force_delete)
|
||||||
}
|
}
|
||||||
|
|
||||||
// Remove references from m_active_objects
|
// Remove references from m_active_objects
|
||||||
for(std::list<u16>::iterator i = objects_to_remove.begin();
|
for(std::vector<u16>::iterator i = objects_to_remove.begin();
|
||||||
i != objects_to_remove.end(); ++i)
|
i != objects_to_remove.end(); ++i) {
|
||||||
{
|
|
||||||
m_active_objects.erase(*i);
|
m_active_objects.erase(*i);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -2025,9 +2024,8 @@ ClientEnvironment::~ClientEnvironment()
|
||||||
delete i->second;
|
delete i->second;
|
||||||
}
|
}
|
||||||
|
|
||||||
for(std::list<ClientSimpleObject*>::iterator
|
for(std::vector<ClientSimpleObject*>::iterator
|
||||||
i = m_simple_objects.begin(); i != m_simple_objects.end(); ++i)
|
i = m_simple_objects.begin(); i != m_simple_objects.end(); ++i) {
|
||||||
{
|
|
||||||
delete *i;
|
delete *i;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -2059,9 +2057,8 @@ void ClientEnvironment::addPlayer(Player *player)
|
||||||
|
|
||||||
LocalPlayer * ClientEnvironment::getLocalPlayer()
|
LocalPlayer * ClientEnvironment::getLocalPlayer()
|
||||||
{
|
{
|
||||||
for(std::list<Player*>::iterator i = m_players.begin();
|
for(std::vector<Player*>::iterator i = m_players.begin();
|
||||||
i != m_players.end(); ++i)
|
i != m_players.end(); ++i) {
|
||||||
{
|
|
||||||
Player *player = *i;
|
Player *player = *i;
|
||||||
if(player->isLocal())
|
if(player->isLocal())
|
||||||
return (LocalPlayer*)player;
|
return (LocalPlayer*)player;
|
||||||
|
@ -2084,7 +2081,7 @@ void ClientEnvironment::step(float dtime)
|
||||||
LocalPlayer *lplayer = getLocalPlayer();
|
LocalPlayer *lplayer = getLocalPlayer();
|
||||||
assert(lplayer);
|
assert(lplayer);
|
||||||
// collision info queue
|
// collision info queue
|
||||||
std::list<CollisionInfo> player_collisions;
|
std::vector<CollisionInfo> player_collisions;
|
||||||
|
|
||||||
/*
|
/*
|
||||||
Get the speed the player is going
|
Get the speed the player is going
|
||||||
|
@ -2199,10 +2196,8 @@ void ClientEnvironment::step(float dtime)
|
||||||
|
|
||||||
//std::cout<<"Looped "<<loopcount<<" times."<<std::endl;
|
//std::cout<<"Looped "<<loopcount<<" times."<<std::endl;
|
||||||
|
|
||||||
for(std::list<CollisionInfo>::iterator
|
for(std::vector<CollisionInfo>::iterator i = player_collisions.begin();
|
||||||
i = player_collisions.begin();
|
i != player_collisions.end(); ++i) {
|
||||||
i != player_collisions.end(); ++i)
|
|
||||||
{
|
|
||||||
CollisionInfo &info = *i;
|
CollisionInfo &info = *i;
|
||||||
v3f speed_diff = info.new_speed - info.old_speed;;
|
v3f speed_diff = info.new_speed - info.old_speed;;
|
||||||
// Handle only fall damage
|
// Handle only fall damage
|
||||||
|
@ -2317,16 +2312,14 @@ void ClientEnvironment::step(float dtime)
|
||||||
/*
|
/*
|
||||||
Stuff that can be done in an arbitarily large dtime
|
Stuff that can be done in an arbitarily large dtime
|
||||||
*/
|
*/
|
||||||
for(std::list<Player*>::iterator i = m_players.begin();
|
for(std::vector<Player*>::iterator i = m_players.begin();
|
||||||
i != m_players.end(); ++i)
|
i != m_players.end(); ++i) {
|
||||||
{
|
|
||||||
Player *player = *i;
|
Player *player = *i;
|
||||||
|
|
||||||
/*
|
/*
|
||||||
Handle non-local players
|
Handle non-local players
|
||||||
*/
|
*/
|
||||||
if(player->isLocal() == false)
|
if(player->isLocal() == false) {
|
||||||
{
|
|
||||||
// Move
|
// Move
|
||||||
player->move(dtime, this, 100*BS);
|
player->move(dtime, this, 100*BS);
|
||||||
|
|
||||||
|
@ -2387,16 +2380,18 @@ void ClientEnvironment::step(float dtime)
|
||||||
Step and handle simple objects
|
Step and handle simple objects
|
||||||
*/
|
*/
|
||||||
g_profiler->avg("CEnv: num of simple objects", m_simple_objects.size());
|
g_profiler->avg("CEnv: num of simple objects", m_simple_objects.size());
|
||||||
for(std::list<ClientSimpleObject*>::iterator
|
for(std::vector<ClientSimpleObject*>::iterator
|
||||||
i = m_simple_objects.begin(); i != m_simple_objects.end();)
|
i = m_simple_objects.begin(); i != m_simple_objects.end();) {
|
||||||
{
|
std::vector<ClientSimpleObject*>::iterator cur = i;
|
||||||
ClientSimpleObject *simple = *i;
|
ClientSimpleObject *simple = *cur;
|
||||||
std::list<ClientSimpleObject*>::iterator cur = i;
|
|
||||||
++i;
|
|
||||||
simple->step(dtime);
|
simple->step(dtime);
|
||||||
if(simple->m_to_be_removed){
|
if(simple->m_to_be_removed) {
|
||||||
delete simple;
|
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)
|
const std::string &init_data)
|
||||||
{
|
{
|
||||||
ClientActiveObject* obj =
|
ClientActiveObject* obj =
|
||||||
ClientActiveObject::create(type, m_gamedef, this);
|
ClientActiveObject::create((ActiveObjectType) type, m_gamedef, this);
|
||||||
if(obj == NULL)
|
if(obj == NULL)
|
||||||
{
|
{
|
||||||
infostream<<"ClientEnvironment::addActiveObject(): "
|
infostream<<"ClientEnvironment::addActiveObject(): "
|
||||||
|
|
|
@ -75,28 +75,19 @@ public:
|
||||||
Player * getPlayer(const char *name);
|
Player * getPlayer(const char *name);
|
||||||
Player * getRandomConnectedPlayer();
|
Player * getRandomConnectedPlayer();
|
||||||
Player * getNearestConnectedPlayer(v3f pos);
|
Player * getNearestConnectedPlayer(v3f pos);
|
||||||
std::list<Player*> getPlayers();
|
std::vector<Player*> getPlayers();
|
||||||
std::list<Player*> getPlayers(bool ignore_disconnected);
|
std::vector<Player*> getPlayers(bool ignore_disconnected);
|
||||||
|
|
||||||
u32 getDayNightRatio();
|
u32 getDayNightRatio();
|
||||||
|
|
||||||
// 0-23999
|
// 0-23999
|
||||||
virtual void setTimeOfDay(u32 time)
|
virtual void setTimeOfDay(u32 time);
|
||||||
{
|
u32 getTimeOfDay();
|
||||||
m_time_of_day = time;
|
float getTimeOfDayF();
|
||||||
m_time_of_day_f = (float)time / 24000.0;
|
|
||||||
}
|
|
||||||
|
|
||||||
u32 getTimeOfDay()
|
|
||||||
{ return m_time_of_day; }
|
|
||||||
|
|
||||||
float getTimeOfDayF()
|
|
||||||
{ return m_time_of_day_f; }
|
|
||||||
|
|
||||||
void stepTimeOfDay(float dtime);
|
void stepTimeOfDay(float dtime);
|
||||||
|
|
||||||
void setTimeOfDaySpeed(float speed);
|
void setTimeOfDaySpeed(float speed);
|
||||||
|
|
||||||
float getTimeOfDaySpeed();
|
float getTimeOfDaySpeed();
|
||||||
|
|
||||||
void setDayNightRatioOverride(bool enable, u32 value)
|
void setDayNightRatioOverride(bool enable, u32 value)
|
||||||
|
@ -110,7 +101,7 @@ public:
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
// peer_ids in here should be unique, except that there may be many 0s
|
// 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
|
// Time of day in milli-hours (0-23999); determines day and night
|
||||||
u32 m_time_of_day;
|
u32 m_time_of_day;
|
||||||
// Time of day in 0...1
|
// Time of day in 0...1
|
||||||
|
@ -134,7 +125,8 @@ protected:
|
||||||
bool m_cache_enable_shaders;
|
bool m_cache_enable_shaders;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
JMutex m_lock;
|
JMutex m_timeofday_lock;
|
||||||
|
JMutex m_time_lock;
|
||||||
|
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -182,7 +174,7 @@ struct ABMWithState
|
||||||
class ActiveBlockList
|
class ActiveBlockList
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
void update(std::list<v3s16> &active_positions,
|
void update(std::vector<v3s16> &active_positions,
|
||||||
s16 radius,
|
s16 radius,
|
||||||
std::set<v3s16> &blocks_removed,
|
std::set<v3s16> &blocks_removed,
|
||||||
std::set<v3s16> &blocks_added);
|
std::set<v3s16> &blocks_added);
|
||||||
|
@ -401,7 +393,7 @@ private:
|
||||||
u32 m_game_time;
|
u32 m_game_time;
|
||||||
// A helper variable for incrementing the latter
|
// A helper variable for incrementing the latter
|
||||||
float m_game_time_fraction_counter;
|
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
|
// An interval for generally sending object positions and stuff
|
||||||
float m_recommended_send_interval;
|
float m_recommended_send_interval;
|
||||||
// Estimate for general maximum lag as determined by server.
|
// Estimate for general maximum lag as determined by server.
|
||||||
|
@ -529,7 +521,7 @@ private:
|
||||||
IGameDef *m_gamedef;
|
IGameDef *m_gamedef;
|
||||||
IrrlichtDevice *m_irr;
|
IrrlichtDevice *m_irr;
|
||||||
std::map<u16, ClientActiveObject*> m_active_objects;
|
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;
|
std::list<ClientEnvEvent> m_client_event_queue;
|
||||||
IntervalLimiter m_active_object_light_update_interval;
|
IntervalLimiter m_active_object_light_update_interval;
|
||||||
IntervalLimiter m_lava_hurt_interval;
|
IntervalLimiter m_lava_hurt_interval;
|
||||||
|
|
84
src/game.cpp
84
src/game.cpp
|
@ -492,7 +492,7 @@ private:
|
||||||
color(color)
|
color(color)
|
||||||
{}
|
{}
|
||||||
};
|
};
|
||||||
std::list<Piece> m_log;
|
std::vector<Piece> m_log;
|
||||||
public:
|
public:
|
||||||
u32 m_log_max_size;
|
u32 m_log_max_size;
|
||||||
|
|
||||||
|
@ -515,7 +515,7 @@ public:
|
||||||
{
|
{
|
||||||
std::map<std::string, Meta> m_meta;
|
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++) {
|
k != m_log.end(); k++) {
|
||||||
const Piece &piece = *k;
|
const Piece &piece = *k;
|
||||||
|
|
||||||
|
@ -613,7 +613,7 @@ public:
|
||||||
float lastscaledvalue = 0.0;
|
float lastscaledvalue = 0.0;
|
||||||
bool lastscaledvalue_exists = false;
|
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++) {
|
j != m_log.end(); j++) {
|
||||||
const Piece &piece = *j;
|
const Piece &piece = *j;
|
||||||
float value = 0;
|
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]"
|
#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,
|
static void show_chat_menu(GUIFormSpecMenu **cur_formspec,
|
||||||
InventoryManager *invmgr, IGameDef *gamedef,
|
InventoryManager *invmgr, IGameDef *gamedef,
|
||||||
|
@ -1074,7 +1078,7 @@ static void show_deathscreen(GUIFormSpecMenu **cur_formspec,
|
||||||
std::string(FORMSPEC_VERSION_STRING) +
|
std::string(FORMSPEC_VERSION_STRING) +
|
||||||
SIZE_TAG
|
SIZE_TAG
|
||||||
"bgcolor[#320000b4;true]"
|
"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") + "]"
|
"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;"
|
os << "button_exit[4," << (ypos++) << ";3,0.5;btn_change_password;"
|
||||||
<< wide_to_narrow(wstrgettext("Change Password")) << "]";
|
<< wide_to_narrow(wstrgettext("Change Password")) << "]";
|
||||||
}
|
}
|
||||||
|
|
||||||
#ifndef __ANDROID__
|
#ifndef __ANDROID__
|
||||||
os << "button_exit[4," << (ypos++) << ";3,0.5;btn_sound;"
|
os << "button_exit[4," << (ypos++) << ";3,0.5;btn_sound;"
|
||||||
<< wide_to_narrow(wstrgettext("Sound Volume")) << "]";
|
<< 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");
|
LocalFormspecHandler *txt_dst = new LocalFormspecHandler("MT_PAUSE_MENU");
|
||||||
|
|
||||||
create_formspec_menu(cur_formspec, invmgr, gamedef, tsrc, device, fs_src, txt_dst, NULL);
|
create_formspec_menu(cur_formspec, invmgr, gamedef, tsrc, device, fs_src, txt_dst, NULL);
|
||||||
|
(*cur_formspec)->setFocus(L"btn_continue");
|
||||||
(*cur_formspec)->doPause = true;
|
(*cur_formspec)->doPause = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1249,6 +1253,7 @@ struct KeyCache {
|
||||||
KEYMAP_ID_FREEMOVE,
|
KEYMAP_ID_FREEMOVE,
|
||||||
KEYMAP_ID_FASTMOVE,
|
KEYMAP_ID_FASTMOVE,
|
||||||
KEYMAP_ID_NOCLIP,
|
KEYMAP_ID_NOCLIP,
|
||||||
|
KEYMAP_ID_CINEMATIC,
|
||||||
KEYMAP_ID_SCREENSHOT,
|
KEYMAP_ID_SCREENSHOT,
|
||||||
KEYMAP_ID_TOGGLE_HUD,
|
KEYMAP_ID_TOGGLE_HUD,
|
||||||
KEYMAP_ID_TOGGLE_CHAT,
|
KEYMAP_ID_TOGGLE_CHAT,
|
||||||
|
@ -1297,6 +1302,7 @@ void KeyCache::populate()
|
||||||
key[KEYMAP_ID_FREEMOVE] = getKeySetting("keymap_freemove");
|
key[KEYMAP_ID_FREEMOVE] = getKeySetting("keymap_freemove");
|
||||||
key[KEYMAP_ID_FASTMOVE] = getKeySetting("keymap_fastmove");
|
key[KEYMAP_ID_FASTMOVE] = getKeySetting("keymap_fastmove");
|
||||||
key[KEYMAP_ID_NOCLIP] = getKeySetting("keymap_noclip");
|
key[KEYMAP_ID_NOCLIP] = getKeySetting("keymap_noclip");
|
||||||
|
key[KEYMAP_ID_CINEMATIC] = getKeySetting("keymap_cinematic");
|
||||||
key[KEYMAP_ID_SCREENSHOT] = getKeySetting("keymap_screenshot");
|
key[KEYMAP_ID_SCREENSHOT] = getKeySetting("keymap_screenshot");
|
||||||
key[KEYMAP_ID_TOGGLE_HUD] = getKeySetting("keymap_toggle_hud");
|
key[KEYMAP_ID_TOGGLE_HUD] = getKeySetting("keymap_toggle_hud");
|
||||||
key[KEYMAP_ID_TOGGLE_CHAT] = getKeySetting("keymap_toggle_chat");
|
key[KEYMAP_ID_TOGGLE_CHAT] = getKeySetting("keymap_toggle_chat");
|
||||||
|
@ -1493,6 +1499,7 @@ protected:
|
||||||
void toggleFreeMoveAlt(float *statustext_time, float *jump_timer);
|
void toggleFreeMoveAlt(float *statustext_time, float *jump_timer);
|
||||||
void toggleFast(float *statustext_time);
|
void toggleFast(float *statustext_time);
|
||||||
void toggleNoClip(float *statustext_time);
|
void toggleNoClip(float *statustext_time);
|
||||||
|
void toggleCinematic(float *statustext_time);
|
||||||
|
|
||||||
void toggleChat(float *statustext_time, bool *flag);
|
void toggleChat(float *statustext_time, bool *flag);
|
||||||
void toggleHud(float *statustext_time, bool *flag);
|
void toggleHud(float *statustext_time, bool *flag);
|
||||||
|
@ -1733,6 +1740,7 @@ void Game::run()
|
||||||
{
|
{
|
||||||
ProfilerGraph graph;
|
ProfilerGraph graph;
|
||||||
RunStats stats = { 0 };
|
RunStats stats = { 0 };
|
||||||
|
CameraOrientation cam_view_target = { 0 };
|
||||||
CameraOrientation cam_view = { 0 };
|
CameraOrientation cam_view = { 0 };
|
||||||
GameRunData runData = { 0 };
|
GameRunData runData = { 0 };
|
||||||
FpsControl draw_times = { 0 };
|
FpsControl draw_times = { 0 };
|
||||||
|
@ -1788,7 +1796,17 @@ void Game::run()
|
||||||
updateProfilers(runData, stats, draw_times, dtime);
|
updateProfilers(runData, stats, draw_times, dtime);
|
||||||
processUserInput(&flags, &runData, dtime);
|
processUserInput(&flags, &runData, dtime);
|
||||||
// Update camera before player movement to avoid camera lag of one frame
|
// 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);
|
updatePlayerControl(cam_view);
|
||||||
step(&dtime);
|
step(&dtime);
|
||||||
processClientEvents(&cam_view, &runData.damage_flash);
|
processClientEvents(&cam_view, &runData.damage_flash);
|
||||||
|
@ -2564,6 +2582,8 @@ void Game::processKeyboardInput(VolatileRunFlags *flags,
|
||||||
toggleFast(statustext_time);
|
toggleFast(statustext_time);
|
||||||
} else if (input->wasKeyDown(keycache.key[KeyCache::KEYMAP_ID_NOCLIP])) {
|
} else if (input->wasKeyDown(keycache.key[KeyCache::KEYMAP_ID_NOCLIP])) {
|
||||||
toggleNoClip(statustext_time);
|
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])) {
|
} else if (input->wasKeyDown(keycache.key[KeyCache::KEYMAP_ID_SCREENSHOT])) {
|
||||||
client->makeScreenshot(device);
|
client->makeScreenshot(device);
|
||||||
} else if (input->wasKeyDown(keycache.key[KeyCache::KEYMAP_ID_TOGGLE_HUD])) {
|
} else if (input->wasKeyDown(keycache.key[KeyCache::KEYMAP_ID_TOGGLE_HUD])) {
|
||||||
|
@ -2669,6 +2689,15 @@ void Game::dropSelectedItem()
|
||||||
|
|
||||||
void Game::openInventory()
|
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;
|
infostream << "the_game: " << "Launching inventory" << std::endl;
|
||||||
|
|
||||||
PlayerInventoryFormSource *fs_src = new PlayerInventoryFormSource(client);
|
PlayerInventoryFormSource *fs_src = new PlayerInventoryFormSource(client);
|
||||||
|
@ -2741,6 +2770,16 @@ void Game::toggleNoClip(float *statustext_time)
|
||||||
statustext += L" (note: no 'noclip' privilege)";
|
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)
|
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();
|
v3s16 old_camera_offset = camera->getOffset();
|
||||||
|
|
||||||
if (input->wasKeyDown(keycache.key[KeyCache::KEYMAP_ID_CAMERA_MODE])) {
|
if (input->wasKeyDown(keycache.key[KeyCache::KEYMAP_ID_CAMERA_MODE])) {
|
||||||
camera->toggleCameraMode();
|
|
||||||
GenericCAO *playercao = player->getCAO();
|
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);
|
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,
|
void Game::updateGui(float *statustext_time, const RunStats &stats,
|
||||||
const GameRunData& runData, f32 dtime, const VolatileRunFlags &flags,
|
const GameRunData& runData, f32 dtime, const VolatileRunFlags &flags,
|
||||||
const CameraOrientation &cam)
|
const CameraOrientation &cam)
|
||||||
|
@ -3981,6 +4045,7 @@ void Game::updateGui(float *statustext_time, const RunStats &stats,
|
||||||
<< ", " << (player_position.Y / BS)
|
<< ", " << (player_position.Y / BS)
|
||||||
<< ", " << (player_position.Z / BS)
|
<< ", " << (player_position.Z / BS)
|
||||||
<< ") (yaw=" << (wrapDegrees_0_360(cam.camera_yaw))
|
<< ") (yaw=" << (wrapDegrees_0_360(cam.camera_yaw))
|
||||||
|
<< " " << yawToDirectionString(cam.camera_yaw)
|
||||||
<< ") (seed = " << ((u64)client->getMapSeed())
|
<< ") (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.");
|
error_message = narrow_to_wide(e.what()) + wstrgettext("\nCheck debug.txt for details.");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -26,24 +26,24 @@ with this program; if not, write to the Free Software Foundation, Inc.,
|
||||||
#include "log.h"
|
#include "log.h"
|
||||||
|
|
||||||
#if USE_GETTEXT && defined(_MSC_VER)
|
#if USE_GETTEXT && defined(_MSC_VER)
|
||||||
#include <WinNls.h>
|
#include <windows.h>
|
||||||
#include <map>
|
#include <map>
|
||||||
#include <direct.h>
|
#include <direct.h>
|
||||||
#include "filesys.h"
|
#include "filesys.h"
|
||||||
|
|
||||||
#define setlocale(category,localename) \
|
#define setlocale(category, localename) \
|
||||||
setlocale(category,MSVC_LocaleLookup(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)
|
BOOL CALLBACK UpdateLocaleCallback(LPTSTR pStr)
|
||||||
{
|
{
|
||||||
char* endptr = 0;
|
char* endptr = 0;
|
||||||
int LOCALEID = strtol(pStr,&endptr,16);
|
int LOCALEID = strtol(pStr, &endptr,16);
|
||||||
|
|
||||||
wchar_t buffer[LOCALE_NAME_MAX_LENGTH];
|
wchar_t buffer[LOCALE_NAME_MAX_LENGTH];
|
||||||
memset(buffer,0,sizeof(buffer));
|
memset(buffer, 0, sizeof(buffer));
|
||||||
if (GetLocaleInfoW(
|
if (GetLocaleInfoW(
|
||||||
LOCALEID,
|
LOCALEID,
|
||||||
LOCALE_SISO639LANGNAME,
|
LOCALE_SISO639LANGNAME,
|
||||||
|
@ -52,7 +52,7 @@ BOOL CALLBACK UpdateLocaleCallback(LPTSTR pStr)
|
||||||
|
|
||||||
std::wstring name = buffer;
|
std::wstring name = buffer;
|
||||||
|
|
||||||
memset(buffer,0,sizeof(buffer));
|
memset(buffer, 0, sizeof(buffer));
|
||||||
GetLocaleInfoW(
|
GetLocaleInfoW(
|
||||||
LOCALEID,
|
LOCALEID,
|
||||||
LOCALE_SISO3166CTRYNAME,
|
LOCALE_SISO3166CTRYNAME,
|
||||||
|
@ -61,7 +61,7 @@ BOOL CALLBACK UpdateLocaleCallback(LPTSTR pStr)
|
||||||
|
|
||||||
std::wstring country = buffer;
|
std::wstring country = buffer;
|
||||||
|
|
||||||
memset(buffer,0,sizeof(buffer));
|
memset(buffer, 0, sizeof(buffer));
|
||||||
GetLocaleInfoW(
|
GetLocaleInfoW(
|
||||||
LOCALEID,
|
LOCALEID,
|
||||||
LOCALE_SENGLISHLANGUAGENAME,
|
LOCALE_SENGLISHLANGUAGENAME,
|
||||||
|
@ -96,7 +96,7 @@ const char* MSVC_LocaleLookup(const char* raw_shortname) {
|
||||||
}
|
}
|
||||||
|
|
||||||
if (first_use) {
|
if (first_use) {
|
||||||
EnumSystemLocalesA(UpdateLocaleCallback,LCID_SUPPORTED | LCID_ALTERNATE_SORTS);
|
EnumSystemLocalesA(UpdateLocaleCallback, LCID_SUPPORTED | LCID_ALTERNATE_SORTS);
|
||||||
first_use = false;
|
first_use = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -148,8 +148,8 @@ void init_gettext(const char *path, const std::string &configured_language) {
|
||||||
if (current_language_var != configured_language) {
|
if (current_language_var != configured_language) {
|
||||||
STARTUPINFO startupinfo;
|
STARTUPINFO startupinfo;
|
||||||
PROCESS_INFORMATION processinfo;
|
PROCESS_INFORMATION processinfo;
|
||||||
memset(&startupinfo,0,sizeof(startupinfo));
|
memset(&startupinfo, 0, sizeof(startupinfo));
|
||||||
memset(&processinfo,0,sizeof(processinfo));
|
memset(&processinfo, 0, sizeof(processinfo));
|
||||||
errorstream << "MSVC localization workaround active restating minetest in new environment!" << std::endl;
|
errorstream << "MSVC localization workaround active restating minetest in new environment!" << std::endl;
|
||||||
|
|
||||||
std::string parameters = "";
|
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 **/
|
/** users may start by short name in commandline without extention **/
|
||||||
std::string appname = argv[0];
|
std::string appname = argv[0];
|
||||||
if (appname.substr(appname.length() -4) != ".exe") {
|
if (appname.substr(appname.length() - 4) != ".exe") {
|
||||||
appname += ".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" */
|
/* no matter what locale is used we need number format to be "C" */
|
||||||
/* to ensure formspec parameters are evaluated correct! */
|
/* to ensure formspec parameters are evaluated correct! */
|
||||||
|
|
||||||
setlocale(LC_NUMERIC,"C");
|
setlocale(LC_NUMERIC, "C");
|
||||||
infostream << "Message locale is now set to: "
|
infostream << "Message locale is now set to: "
|
||||||
<< setlocale(LC_ALL, 0) << std::endl;
|
<< setlocale(LC_ALL, 0) << std::endl;
|
||||||
}
|
}
|
||||||
|
|
|
@ -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 const wchar_t *narrow_to_wide_c(const char *mbs);
|
||||||
extern std::wstring narrow_to_wide(const std::string &mbs);
|
extern std::wstring narrow_to_wide(const std::string &mbs);
|
||||||
|
|
||||||
|
|
||||||
// You must free the returned string!
|
// You must free the returned string!
|
||||||
inline const wchar_t *wgettext(const char *str)
|
inline const wchar_t *wgettext(const char *str)
|
||||||
{
|
{
|
||||||
return narrow_to_wide_c(gettext(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)
|
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)
|
inline std::string strgettext(const std::string &text)
|
||||||
|
|
|
@ -99,7 +99,7 @@ GUIChatConsole::GUIChatConsole(
|
||||||
{
|
{
|
||||||
core::dimension2d<u32> dim = m_font->getDimension(L"M");
|
core::dimension2d<u32> dim = m_font->getDimension(L"M");
|
||||||
m_fontsize = v2u32(dim.Width, dim.Height);
|
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.X = MYMAX(m_fontsize.X, 1);
|
||||||
m_fontsize.Y = MYMAX(m_fontsize.Y, 1);
|
m_fontsize.Y = MYMAX(m_fontsize.Y, 1);
|
||||||
|
@ -109,7 +109,10 @@ GUIChatConsole::GUIChatConsole(
|
||||||
}
|
}
|
||||||
|
|
||||||
GUIChatConsole::~GUIChatConsole()
|
GUIChatConsole::~GUIChatConsole()
|
||||||
{}
|
{
|
||||||
|
if (m_font)
|
||||||
|
m_font->drop();
|
||||||
|
}
|
||||||
|
|
||||||
void GUIChatConsole::openConsole(f32 height)
|
void GUIChatConsole::openConsole(f32 height)
|
||||||
{
|
{
|
||||||
|
|
|
@ -122,9 +122,6 @@ private:
|
||||||
// font
|
// font
|
||||||
gui::IGUIFont* m_font;
|
gui::IGUIFont* m_font;
|
||||||
v2u32 m_fontsize;
|
v2u32 m_fontsize;
|
||||||
#if USE_FREETYPE
|
|
||||||
bool m_use_freetype;
|
|
||||||
#endif
|
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -39,9 +39,6 @@ with this program; if not, write to the Free Software Foundation, Inc.,
|
||||||
#include "log.h"
|
#include "log.h"
|
||||||
#include "tile.h" // ITextureSource
|
#include "tile.h" // ITextureSource
|
||||||
#include "hud.h" // drawItemStack
|
#include "hud.h" // drawItemStack
|
||||||
#include "hex.h"
|
|
||||||
#include "util/string.h"
|
|
||||||
#include "util/numeric.h"
|
|
||||||
#include "filesys.h"
|
#include "filesys.h"
|
||||||
#include "gettime.h"
|
#include "gettime.h"
|
||||||
#include "gettext.h"
|
#include "gettext.h"
|
||||||
|
@ -50,8 +47,10 @@ with this program; if not, write to the Free Software Foundation, Inc.,
|
||||||
#include "main.h"
|
#include "main.h"
|
||||||
#include "settings.h"
|
#include "settings.h"
|
||||||
#include "client.h"
|
#include "client.h"
|
||||||
#include "util/string.h" // for parseColorString()
|
|
||||||
#include "fontengine.h"
|
#include "fontengine.h"
|
||||||
|
#include "util/hex.h"
|
||||||
|
#include "util/numeric.h"
|
||||||
|
#include "util/string.h" // for parseColorString()
|
||||||
|
|
||||||
#define MY_CHECKPOS(a,b) \
|
#define MY_CHECKPOS(a,b) \
|
||||||
if (v_pos.size() != 2) { \
|
if (v_pos.size() != 2) { \
|
||||||
|
@ -97,6 +96,7 @@ GUIFormSpecMenu::GUIFormSpecMenu(irr::IrrlichtDevice* dev,
|
||||||
m_form_src(fsrc),
|
m_form_src(fsrc),
|
||||||
m_text_dst(tdst),
|
m_text_dst(tdst),
|
||||||
m_formspec_version(0),
|
m_formspec_version(0),
|
||||||
|
m_focused_element(L""),
|
||||||
m_font(NULL)
|
m_font(NULL)
|
||||||
#ifdef __ANDROID__
|
#ifdef __ANDROID__
|
||||||
,m_JavaDialogFieldName(L"")
|
,m_JavaDialogFieldName(L"")
|
||||||
|
@ -1757,8 +1757,6 @@ void GUIFormSpecMenu::parseElement(parserData* data, std::string element)
|
||||||
<<std::endl;
|
<<std::endl;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
void GUIFormSpecMenu::regenerateGui(v2u32 screensize)
|
void GUIFormSpecMenu::regenerateGui(v2u32 screensize)
|
||||||
{
|
{
|
||||||
/* useless to regenerate without a screensize */
|
/* useless to regenerate without a screensize */
|
||||||
|
@ -1775,6 +1773,10 @@ void GUIFormSpecMenu::regenerateGui(v2u32 screensize)
|
||||||
mydata.table_dyndata[tablename] = table->getDynamicData();
|
mydata.table_dyndata[tablename] = table->getDynamicData();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
//set focus
|
||||||
|
if (!m_focused_element.empty())
|
||||||
|
mydata.focused_fieldname = m_focused_element;
|
||||||
|
|
||||||
//preserve focus
|
//preserve focus
|
||||||
gui::IGUIElement *focused_element = Environment->getFocus();
|
gui::IGUIElement *focused_element = Environment->getFocus();
|
||||||
if (focused_element && focused_element->getParent() == this) {
|
if (focused_element && focused_element->getParent() == this) {
|
||||||
|
|
|
@ -246,13 +246,20 @@ public:
|
||||||
m_allowclose = value;
|
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_lock = lock;
|
||||||
m_lockscreensize = basescreensize;
|
m_lockscreensize = basescreensize;
|
||||||
}
|
}
|
||||||
|
|
||||||
void removeChildren();
|
void removeChildren();
|
||||||
void setInitialFocus();
|
void setInitialFocus();
|
||||||
|
|
||||||
|
void setFocus(std::wstring elementname)
|
||||||
|
{
|
||||||
|
m_focused_element = elementname;
|
||||||
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
Remove and re-add (or reposition) stuff
|
Remove and re-add (or reposition) stuff
|
||||||
*/
|
*/
|
||||||
|
@ -348,6 +355,7 @@ private:
|
||||||
IFormSource *m_form_src;
|
IFormSource *m_form_src;
|
||||||
TextDest *m_text_dst;
|
TextDest *m_text_dst;
|
||||||
unsigned int m_formspec_version;
|
unsigned int m_formspec_version;
|
||||||
|
std::wstring m_focused_element;
|
||||||
|
|
||||||
typedef struct {
|
typedef struct {
|
||||||
bool explicit_size;
|
bool explicit_size;
|
||||||
|
|
|
@ -51,6 +51,7 @@ enum
|
||||||
GUI_ID_KEY_FAST_BUTTON,
|
GUI_ID_KEY_FAST_BUTTON,
|
||||||
GUI_ID_KEY_JUMP_BUTTON,
|
GUI_ID_KEY_JUMP_BUTTON,
|
||||||
GUI_ID_KEY_NOCLIP_BUTTON,
|
GUI_ID_KEY_NOCLIP_BUTTON,
|
||||||
|
GUI_ID_KEY_CINEMATIC_BUTTON,
|
||||||
GUI_ID_KEY_CHAT_BUTTON,
|
GUI_ID_KEY_CHAT_BUTTON,
|
||||||
GUI_ID_KEY_CMD_BUTTON,
|
GUI_ID_KEY_CMD_BUTTON,
|
||||||
GUI_ID_KEY_CONSOLE_BUTTON,
|
GUI_ID_KEY_CONSOLE_BUTTON,
|
||||||
|
@ -137,27 +138,27 @@ void GUIKeyChangeMenu::regenerateGui(v2u32 screensize)
|
||||||
{
|
{
|
||||||
key_setting *k = key_settings.at(i);
|
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);
|
rect += topleft + v2s32(offset.X, offset.Y);
|
||||||
Environment->addStaticText(k->button_name, rect, false, true, this, -1);
|
Environment->addStaticText(k->button_name, rect, false, true, this, -1);
|
||||||
}
|
}
|
||||||
|
|
||||||
{
|
{
|
||||||
core::rect < s32 > rect(0, 0, 100, 30);
|
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());
|
const wchar_t *text = wgettext(k->key.name());
|
||||||
k->button = Environment->addButton(rect, this, k->id, text);
|
k->button = Environment->addButton(rect, this, k->id, text);
|
||||||
delete[] text;
|
delete[] text;
|
||||||
}
|
}
|
||||||
if(i + 1 == KMaxButtonPerColumns)
|
if(i + 1 == KMaxButtonPerColumns)
|
||||||
offset = v2s32(250, 60);
|
offset = v2s32(260, 60);
|
||||||
else
|
else
|
||||||
offset += v2s32(0, 25);
|
offset += v2s32(0, 25);
|
||||||
}
|
}
|
||||||
|
|
||||||
{
|
{
|
||||||
s32 option_x = offset.X + 10;
|
s32 option_x = offset.X;
|
||||||
s32 option_y = offset.Y;
|
s32 option_y = offset.Y + 5;
|
||||||
u32 option_w = 180;
|
u32 option_w = 180;
|
||||||
{
|
{
|
||||||
core::rect<s32> rect(0, 0, option_w, 30);
|
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_x = offset.X;
|
||||||
s32 option_y = offset.Y;
|
s32 option_y = offset.Y + 5;
|
||||||
u32 option_w = 220;
|
u32 option_w = 280;
|
||||||
{
|
{
|
||||||
core::rect<s32> rect(0, 0, option_w, 30);
|
core::rect<s32> rect(0, 0, option_w, 30);
|
||||||
rect += topleft + v2s32(option_x, option_y);
|
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()
|
void GUIKeyChangeMenu::init_keys()
|
||||||
{
|
{
|
||||||
this->add_key(GUI_ID_KEY_FORWARD_BUTTON, wgettext("Forward"), "keymap_forward");
|
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_BACKWARD_BUTTON, wgettext("Backward"), "keymap_backward");
|
||||||
this->add_key(GUI_ID_KEY_LEFT_BUTTON, wgettext("Left"), "keymap_left");
|
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_RIGHT_BUTTON, wgettext("Right"), "keymap_right");
|
||||||
this->add_key(GUI_ID_KEY_USE_BUTTON, wgettext("Use"), "keymap_special1");
|
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_JUMP_BUTTON, wgettext("Jump"), "keymap_jump");
|
||||||
this->add_key(GUI_ID_KEY_SNEAK_BUTTON, wgettext("Sneak"), "keymap_sneak");
|
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_DROP_BUTTON, wgettext("Drop"), "keymap_drop");
|
||||||
this->add_key(GUI_ID_KEY_INVENTORY_BUTTON, wgettext("Inventory"), "keymap_inventory");
|
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_CHAT_BUTTON, wgettext("Chat"), "keymap_chat");
|
||||||
this->add_key(GUI_ID_KEY_CMD_BUTTON, wgettext("Command"), "keymap_cmd");
|
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_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_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_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_CINEMATIC_BUTTON, wgettext("Toggle Cinematic"), "keymap_cinematic");
|
||||||
this->add_key(GUI_ID_KEY_RANGE_BUTTON, wgettext("Range select"), "keymap_rangeselect");
|
this->add_key(GUI_ID_KEY_NOCLIP_BUTTON, wgettext("Toggle noclip"), "keymap_noclip");
|
||||||
this->add_key(GUI_ID_KEY_DUMP_BUTTON, wgettext("Print stacks"), "keymap_print_debug_stacks");
|
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");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -103,8 +103,8 @@ void GUIPasswordChange::regenerateGui(v2u32 screensize)
|
||||||
*/
|
*/
|
||||||
s32 ypos = 50;
|
s32 ypos = 50;
|
||||||
{
|
{
|
||||||
core::rect<s32> rect(0, 0, 110, 20);
|
core::rect<s32> rect(0, 0, 150, 20);
|
||||||
rect += topleft_client + v2s32(35, ypos+6);
|
rect += topleft_client + v2s32(25, ypos+6);
|
||||||
text = wgettext("Old Password");
|
text = wgettext("Old Password");
|
||||||
Environment->addStaticText(text, rect, false, true, this, -1);
|
Environment->addStaticText(text, rect, false, true, this, -1);
|
||||||
delete[] text;
|
delete[] text;
|
||||||
|
@ -119,8 +119,8 @@ void GUIPasswordChange::regenerateGui(v2u32 screensize)
|
||||||
}
|
}
|
||||||
ypos += 50;
|
ypos += 50;
|
||||||
{
|
{
|
||||||
core::rect<s32> rect(0, 0, 110, 20);
|
core::rect<s32> rect(0, 0, 150, 20);
|
||||||
rect += topleft_client + v2s32(35, ypos+6);
|
rect += topleft_client + v2s32(25, ypos+6);
|
||||||
text = wgettext("New Password");
|
text = wgettext("New Password");
|
||||||
Environment->addStaticText(text, rect, false, true, this, -1);
|
Environment->addStaticText(text, rect, false, true, this, -1);
|
||||||
delete[] text;
|
delete[] text;
|
||||||
|
@ -134,8 +134,8 @@ void GUIPasswordChange::regenerateGui(v2u32 screensize)
|
||||||
}
|
}
|
||||||
ypos += 50;
|
ypos += 50;
|
||||||
{
|
{
|
||||||
core::rect<s32> rect(0, 0, 110, 20);
|
core::rect<s32> rect(0, 0, 150, 20);
|
||||||
rect += topleft_client + v2s32(35, ypos+6);
|
rect += topleft_client + v2s32(25, ypos+6);
|
||||||
text = wgettext("Confirm Password");
|
text = wgettext("Confirm Password");
|
||||||
Environment->addStaticText(text, rect, false, true, this, -1);
|
Environment->addStaticText(text, rect, false, true, this, -1);
|
||||||
delete[] text;
|
delete[] text;
|
||||||
|
|
|
@ -37,7 +37,7 @@ with this program; if not, write to the Free Software Foundation, Inc.,
|
||||||
#include "settings.h"
|
#include "settings.h"
|
||||||
|
|
||||||
JMutex g_httpfetch_mutex;
|
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()
|
HTTPFetchRequest::HTTPFetchRequest()
|
||||||
{
|
{
|
||||||
|
@ -57,7 +57,7 @@ static void httpfetch_deliver_result(const HTTPFetchResult &fetch_result)
|
||||||
unsigned long caller = fetch_result.caller;
|
unsigned long caller = fetch_result.caller;
|
||||||
if (caller != HTTPFETCH_DISCARD) {
|
if (caller != HTTPFETCH_DISCARD) {
|
||||||
JMutexAutoLock lock(g_httpfetch_mutex);
|
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
|
// Check each caller ID except HTTPFETCH_DISCARD
|
||||||
const unsigned long discard = HTTPFETCH_DISCARD;
|
const unsigned long discard = HTTPFETCH_DISCARD;
|
||||||
for (unsigned long caller = discard + 1; caller != discard; ++caller) {
|
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);
|
it = g_httpfetch_results.find(caller);
|
||||||
if (it == g_httpfetch_results.end()) {
|
if (it == g_httpfetch_results.end()) {
|
||||||
verbosestream<<"httpfetch_caller_alloc: allocating "
|
verbosestream << "httpfetch_caller_alloc: allocating "
|
||||||
<<caller<<std::endl;
|
<< caller << std::endl;
|
||||||
// Access element to create it
|
// Access element to create it
|
||||||
g_httpfetch_results[caller];
|
g_httpfetch_results[caller];
|
||||||
return caller;
|
return caller;
|
||||||
|
@ -102,19 +102,19 @@ bool httpfetch_async_get(unsigned long caller, HTTPFetchResult &fetch_result)
|
||||||
JMutexAutoLock lock(g_httpfetch_mutex);
|
JMutexAutoLock lock(g_httpfetch_mutex);
|
||||||
|
|
||||||
// Check that caller exists
|
// 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);
|
it = g_httpfetch_results.find(caller);
|
||||||
if (it == g_httpfetch_results.end())
|
if (it == g_httpfetch_results.end())
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
// Check that result queue is nonempty
|
// Check that result queue is nonempty
|
||||||
std::list<HTTPFetchResult> &caller_results = it->second;
|
std::queue<HTTPFetchResult> &caller_results = it->second;
|
||||||
if (caller_results.empty())
|
if (caller_results.empty())
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
// Pop first result
|
// Pop first result
|
||||||
fetch_result = caller_results.front();
|
fetch_result = caller_results.front();
|
||||||
caller_results.pop_front();
|
caller_results.pop();
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -194,7 +194,6 @@ private:
|
||||||
HTTPFetchRequest request;
|
HTTPFetchRequest request;
|
||||||
HTTPFetchResult result;
|
HTTPFetchResult result;
|
||||||
std::ostringstream oss;
|
std::ostringstream oss;
|
||||||
char *post_fields;
|
|
||||||
struct curl_slist *http_header;
|
struct curl_slist *http_header;
|
||||||
curl_httppost *post;
|
curl_httppost *post;
|
||||||
};
|
};
|
||||||
|
|
|
@ -249,8 +249,8 @@ public:
|
||||||
virtual ~CItemDefManager()
|
virtual ~CItemDefManager()
|
||||||
{
|
{
|
||||||
#ifndef SERVER
|
#ifndef SERVER
|
||||||
const std::list<ClientCached*> &values = m_clientcached.getValues();
|
const std::vector<ClientCached*> &values = m_clientcached.getValues();
|
||||||
for(std::list<ClientCached*>::const_iterator
|
for(std::vector<ClientCached*>::const_iterator
|
||||||
i = values.begin(); i != values.end(); ++i)
|
i = values.begin(); i != values.end(); ++i)
|
||||||
{
|
{
|
||||||
ClientCached *cc = *i;
|
ClientCached *cc = *i;
|
||||||
|
@ -362,8 +362,6 @@ public:
|
||||||
|
|
||||||
scene::IMesh *node_mesh = NULL;
|
scene::IMesh *node_mesh = NULL;
|
||||||
|
|
||||||
bool reenable_shaders = false;
|
|
||||||
|
|
||||||
if (need_rtt_mesh || need_wield_mesh) {
|
if (need_rtt_mesh || need_wield_mesh) {
|
||||||
u8 param1 = 0;
|
u8 param1 = 0;
|
||||||
if (f.param_type == CPT_LIGHT)
|
if (f.param_type == CPT_LIGHT)
|
||||||
|
@ -372,11 +370,7 @@ public:
|
||||||
/*
|
/*
|
||||||
Make a mesh from the node
|
Make a mesh from the node
|
||||||
*/
|
*/
|
||||||
if (g_settings->getBool("enable_shaders")) {
|
MeshMakeData mesh_make_data(gamedef, false);
|
||||||
reenable_shaders = true;
|
|
||||||
g_settings->setBool("enable_shaders", false);
|
|
||||||
}
|
|
||||||
MeshMakeData mesh_make_data(gamedef);
|
|
||||||
u8 param2 = 0;
|
u8 param2 = 0;
|
||||||
if (f.param_type_2 == CPT2_WALLMOUNTED)
|
if (f.param_type_2 == CPT2_WALLMOUNTED)
|
||||||
param2 = 1;
|
param2 = 1;
|
||||||
|
@ -443,9 +437,6 @@ public:
|
||||||
|
|
||||||
if (node_mesh)
|
if (node_mesh)
|
||||||
node_mesh->drop();
|
node_mesh->drop();
|
||||||
|
|
||||||
if (reenable_shaders)
|
|
||||||
g_settings->setBool("enable_shaders",true);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Put in cache
|
// Put in cache
|
||||||
|
|
|
@ -30,7 +30,7 @@
|
||||||
|
|
||||||
#ifdef _WIN32
|
#ifdef _WIN32
|
||||||
#include <windows.h>
|
#include <windows.h>
|
||||||
#elif __MACH__
|
#elif defined(__MACH__) && defined(__APPLE__)
|
||||||
#include <mach/mach.h>
|
#include <mach/mach.h>
|
||||||
#include <mach/task.h>
|
#include <mach/task.h>
|
||||||
#include <mach/semaphore.h>
|
#include <mach/semaphore.h>
|
||||||
|
@ -43,7 +43,7 @@
|
||||||
class Event {
|
class Event {
|
||||||
#ifdef _WIN32
|
#ifdef _WIN32
|
||||||
HANDLE hEvent;
|
HANDLE hEvent;
|
||||||
#elif __MACH__
|
#elif defined(__MACH__) && defined(__APPLE__)
|
||||||
semaphore_t sem;
|
semaphore_t sem;
|
||||||
#else
|
#else
|
||||||
sem_t sem;
|
sem_t sem;
|
||||||
|
|
|
@ -24,7 +24,7 @@ with this program; if not, write to the Free Software Foundation, Inc.,
|
||||||
#include <windows.h>
|
#include <windows.h>
|
||||||
#include <assert.h>
|
#include <assert.h>
|
||||||
#define MAX_SEMAPHORE_COUNT 1024
|
#define MAX_SEMAPHORE_COUNT 1024
|
||||||
#elif __MACH__
|
#elif defined(__MACH__) && defined(__APPLE__)
|
||||||
#include <pthread.h>
|
#include <pthread.h>
|
||||||
#include <mach/mach.h>
|
#include <mach/mach.h>
|
||||||
#include <mach/task.h>
|
#include <mach/task.h>
|
||||||
|
@ -52,7 +52,7 @@ public:
|
||||||
private:
|
private:
|
||||||
#if defined(WIN32)
|
#if defined(WIN32)
|
||||||
HANDLE m_hSemaphore;
|
HANDLE m_hSemaphore;
|
||||||
#elif __MACH__
|
#elif defined(__MACH__) && defined(__APPLE__)
|
||||||
semaphore_t m_semaphore;
|
semaphore_t m_semaphore;
|
||||||
int semcount;
|
int semcount;
|
||||||
#else
|
#else
|
||||||
|
|
|
@ -29,7 +29,7 @@
|
||||||
|
|
||||||
#define UNUSED(expr) do { (void)(expr); } while (0)
|
#define UNUSED(expr) do { (void)(expr); } while (0)
|
||||||
|
|
||||||
#ifdef __MACH__
|
#if defined(__MACH__) && defined(__APPLE__)
|
||||||
#undef sem_t
|
#undef sem_t
|
||||||
#define sem_t semaphore_t
|
#define sem_t semaphore_t
|
||||||
#undef sem_init
|
#undef sem_init
|
||||||
|
|
|
@ -20,13 +20,13 @@ with this program; if not, write to the Free Software Foundation, Inc.,
|
||||||
#include <errno.h>
|
#include <errno.h>
|
||||||
#include <sys/time.h>
|
#include <sys/time.h>
|
||||||
#include "jthread/jsemaphore.h"
|
#include "jthread/jsemaphore.h"
|
||||||
#ifdef __MACH__
|
#if defined(__MACH__) && defined(__APPLE__)
|
||||||
#include <unistd.h>
|
#include <unistd.h>
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#define UNUSED(expr) do { (void)(expr); } while (0)
|
#define UNUSED(expr) do { (void)(expr); } while (0)
|
||||||
|
|
||||||
#ifdef __MACH__
|
#if defined(__MACH__) && defined(__APPLE__)
|
||||||
#undef sem_t
|
#undef sem_t
|
||||||
#undef sem_init
|
#undef sem_init
|
||||||
#undef sem_wait
|
#undef sem_wait
|
||||||
|
@ -44,7 +44,7 @@ JSemaphore::JSemaphore() {
|
||||||
int sem_init_retval = sem_init(&m_semaphore,0,0);
|
int sem_init_retval = sem_init(&m_semaphore,0,0);
|
||||||
assert(sem_init_retval == 0);
|
assert(sem_init_retval == 0);
|
||||||
UNUSED(sem_init_retval);
|
UNUSED(sem_init_retval);
|
||||||
#ifdef __MACH__
|
#if defined(__MACH__) && defined(__APPLE__)
|
||||||
semcount = 0;
|
semcount = 0;
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
@ -73,7 +73,7 @@ void JSemaphore::Post() {
|
||||||
int sem_post_retval = sem_post(&m_semaphore);
|
int sem_post_retval = sem_post(&m_semaphore);
|
||||||
assert(sem_post_retval == 0);
|
assert(sem_post_retval == 0);
|
||||||
UNUSED(sem_post_retval);
|
UNUSED(sem_post_retval);
|
||||||
#ifdef __MACH__
|
#if defined(__MACH__) && defined(__APPLE__)
|
||||||
pthread_mutex_lock(&semcount_mutex);
|
pthread_mutex_lock(&semcount_mutex);
|
||||||
semcount++;
|
semcount++;
|
||||||
pthread_mutex_unlock(&semcount_mutex);
|
pthread_mutex_unlock(&semcount_mutex);
|
||||||
|
@ -84,7 +84,7 @@ void JSemaphore::Wait() {
|
||||||
int sem_wait_retval = sem_wait(&m_semaphore);
|
int sem_wait_retval = sem_wait(&m_semaphore);
|
||||||
assert(sem_wait_retval == 0);
|
assert(sem_wait_retval == 0);
|
||||||
UNUSED(sem_wait_retval);
|
UNUSED(sem_wait_retval);
|
||||||
#ifdef __MACH__
|
#if defined(__MACH__) && defined(__APPLE__)
|
||||||
pthread_mutex_lock(&semcount_mutex);
|
pthread_mutex_lock(&semcount_mutex);
|
||||||
semcount--;
|
semcount--;
|
||||||
pthread_mutex_unlock(&semcount_mutex);
|
pthread_mutex_unlock(&semcount_mutex);
|
||||||
|
@ -92,7 +92,7 @@ void JSemaphore::Wait() {
|
||||||
}
|
}
|
||||||
|
|
||||||
bool JSemaphore::Wait(unsigned int time_ms) {
|
bool JSemaphore::Wait(unsigned int time_ms) {
|
||||||
#ifdef __MACH__
|
#if defined(__MACH__) && defined(__APPLE__)
|
||||||
mach_timespec_t waittime;
|
mach_timespec_t waittime;
|
||||||
waittime.tv_sec = time_ms / 1000;
|
waittime.tv_sec = time_ms / 1000;
|
||||||
waittime.tv_nsec = 1000000 * (time_ms % 1000);
|
waittime.tv_nsec = 1000000 * (time_ms % 1000);
|
||||||
|
@ -106,14 +106,14 @@ bool JSemaphore::Wait(unsigned int time_ms) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
#ifndef __MACH__
|
#if !(defined(__MACH__) && defined(__APPLE__))
|
||||||
waittime.tv_nsec = ((time_ms % 1000) * 1000 * 1000) + (now.tv_usec * 1000);
|
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_sec = (time_ms / 1000) + (waittime.tv_nsec / (1000*1000*1000)) + now.tv_sec;
|
||||||
waittime.tv_nsec %= 1000*1000*1000;
|
waittime.tv_nsec %= 1000*1000*1000;
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
errno = 0;
|
errno = 0;
|
||||||
#ifdef __MACH__
|
#if defined(__MACH__) && defined(__APPLE__)
|
||||||
int sem_wait_retval = semaphore_timedwait(m_semaphore, waittime);
|
int sem_wait_retval = semaphore_timedwait(m_semaphore, waittime);
|
||||||
if (sem_wait_retval == KERN_OPERATION_TIMED_OUT) {
|
if (sem_wait_retval == KERN_OPERATION_TIMED_OUT) {
|
||||||
errno = ETIMEDOUT;
|
errno = ETIMEDOUT;
|
||||||
|
@ -128,7 +128,7 @@ bool JSemaphore::Wait(unsigned int time_ms) {
|
||||||
|
|
||||||
if (sem_wait_retval == 0)
|
if (sem_wait_retval == 0)
|
||||||
{
|
{
|
||||||
#ifdef __MACH__
|
#if defined(__MACH__) && defined(__APPLE__)
|
||||||
pthread_mutex_lock(&semcount_mutex);
|
pthread_mutex_lock(&semcount_mutex);
|
||||||
semcount--;
|
semcount--;
|
||||||
pthread_mutex_unlock(&semcount_mutex);
|
pthread_mutex_unlock(&semcount_mutex);
|
||||||
|
@ -144,7 +144,7 @@ bool JSemaphore::Wait(unsigned int time_ms) {
|
||||||
|
|
||||||
int JSemaphore::GetValue() {
|
int JSemaphore::GetValue() {
|
||||||
int retval = 0;
|
int retval = 0;
|
||||||
#ifdef __MACH__
|
#if defined(__MACH__) && defined(__APPLE__)
|
||||||
pthread_mutex_lock(&semcount_mutex);
|
pthread_mutex_lock(&semcount_mutex);
|
||||||
retval = semcount;
|
retval = semcount;
|
||||||
pthread_mutex_unlock(&semcount_mutex);
|
pthread_mutex_unlock(&semcount_mutex);
|
||||||
|
|
|
@ -22,8 +22,8 @@ with this program; if not, write to the Free Software Foundation, Inc.,
|
||||||
#include "exceptions.h"
|
#include "exceptions.h"
|
||||||
#include "settings.h"
|
#include "settings.h"
|
||||||
#include "log.h"
|
#include "log.h"
|
||||||
#include "hex.h"
|
|
||||||
#include "debug.h"
|
#include "debug.h"
|
||||||
|
#include "util/hex.h"
|
||||||
|
|
||||||
class UnknownKeycode : public BaseException
|
class UnknownKeycode : public BaseException
|
||||||
{
|
{
|
||||||
|
|
|
@ -67,7 +67,7 @@ LocalPlayer::~LocalPlayer()
|
||||||
}
|
}
|
||||||
|
|
||||||
void LocalPlayer::move(f32 dtime, Environment *env, f32 pos_max_d,
|
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();
|
Map *map = &env->getMap();
|
||||||
INodeDefManager *nodemgr = m_gamedef->ndef();
|
INodeDefManager *nodemgr = m_gamedef->ndef();
|
||||||
|
@ -323,9 +323,8 @@ void LocalPlayer::move(f32 dtime, Environment *env, f32 pos_max_d,
|
||||||
*/
|
*/
|
||||||
bool bouncy_jump = false;
|
bool bouncy_jump = false;
|
||||||
// Dont report if flying
|
// Dont report if flying
|
||||||
if(collision_info && !(g_settings->getBool("free_move") && fly_allowed))
|
if(collision_info && !(g_settings->getBool("free_move") && fly_allowed)) {
|
||||||
{
|
for(size_t i=0; i<result.collisions.size(); i++) {
|
||||||
for(size_t i=0; i<result.collisions.size(); i++){
|
|
||||||
const CollisionInfo &info = result.collisions[i];
|
const CollisionInfo &info = result.collisions[i];
|
||||||
collision_info->push_back(info);
|
collision_info->push_back(info);
|
||||||
if(info.new_speed.Y - info.old_speed.Y > 0.1*BS &&
|
if(info.new_speed.Y - info.old_speed.Y > 0.1*BS &&
|
||||||
|
|
|
@ -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);
|
||||||
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);
|
void applyControl(float dtime);
|
||||||
|
|
||||||
|
|
35
src/log.cpp
35
src/log.cpp
|
@ -24,13 +24,14 @@ with this program; if not, write to the Free Software Foundation, Inc.,
|
||||||
#include <sstream>
|
#include <sstream>
|
||||||
#include <algorithm>
|
#include <algorithm>
|
||||||
#include "threads.h"
|
#include "threads.h"
|
||||||
|
#include "jthread/jmutexautolock.h"
|
||||||
#include "debug.h"
|
#include "debug.h"
|
||||||
#include "gettime.h"
|
#include "gettime.h"
|
||||||
#include "porting.h"
|
#include "porting.h"
|
||||||
#include "config.h"
|
#include "config.h"
|
||||||
|
|
||||||
#ifdef __ANDROID__
|
#ifdef __ANDROID__
|
||||||
unsigned int android_log_level_mapping[] {
|
unsigned int android_log_level_mapping[] = {
|
||||||
/* LMT_ERROR */ ANDROID_LOG_ERROR,
|
/* LMT_ERROR */ ANDROID_LOG_ERROR,
|
||||||
/* LMT_ACTION */ ANDROID_LOG_WARN,
|
/* LMT_ACTION */ ANDROID_LOG_WARN,
|
||||||
/* LMT_INFO */ ANDROID_LOG_INFO,
|
/* LMT_INFO */ ANDROID_LOG_INFO,
|
||||||
|
@ -38,7 +39,7 @@ unsigned int android_log_level_mapping[] {
|
||||||
};
|
};
|
||||||
#endif
|
#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;
|
std::map<threadid_t, std::string> log_threadnames;
|
||||||
JMutex log_threadnamemutex;
|
JMutex log_threadnamemutex;
|
||||||
|
|
||||||
|
@ -62,7 +63,7 @@ void log_add_output_all_levs(ILogOutput *out)
|
||||||
void log_remove_output(ILogOutput *out)
|
void log_remove_output(ILogOutput *out)
|
||||||
{
|
{
|
||||||
for(int i=0; i<LMT_NUM_VALUES; i++){
|
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);
|
std::find(log_outputs[i].begin(), log_outputs[i].end(), out);
|
||||||
if(it != log_outputs[i].end())
|
if(it != log_outputs[i].end())
|
||||||
log_outputs[i].erase(it);
|
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)
|
void log_set_lev_silence(enum LogMessageLevel lev, bool silence)
|
||||||
{
|
{
|
||||||
log_threadnamemutex.Lock();
|
JMutexAutoLock lock(log_threadnamemutex);
|
||||||
|
|
||||||
for (std::list<ILogOutput *>::iterator
|
for (std::vector<ILogOutput *>::iterator it = log_outputs[lev].begin();
|
||||||
it = log_outputs[lev].begin();
|
it != log_outputs[lev].end(); ++it) {
|
||||||
it != log_outputs[lev].end();
|
|
||||||
++it) {
|
|
||||||
ILogOutput *out = *it;
|
ILogOutput *out = *it;
|
||||||
out->silence = silence;
|
out->silence = silence;
|
||||||
}
|
}
|
||||||
|
|
||||||
log_threadnamemutex.Unlock();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void log_register_thread(const std::string &name)
|
void log_register_thread(const std::string &name)
|
||||||
{
|
{
|
||||||
threadid_t id = get_current_thread_id();
|
threadid_t id = get_current_thread_id();
|
||||||
log_threadnamemutex.Lock();
|
JMutexAutoLock lock(log_threadnamemutex);
|
||||||
|
|
||||||
log_threadnames[id] = name;
|
log_threadnames[id] = name;
|
||||||
log_threadnamemutex.Unlock();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void log_deregister_thread()
|
void log_deregister_thread()
|
||||||
{
|
{
|
||||||
threadid_t id = get_current_thread_id();
|
threadid_t id = get_current_thread_id();
|
||||||
log_threadnamemutex.Lock();
|
JMutexAutoLock lock(log_threadnamemutex);
|
||||||
|
|
||||||
log_threadnames.erase(id);
|
log_threadnames.erase(id);
|
||||||
log_threadnamemutex.Unlock();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static std::string get_lev_string(enum LogMessageLevel lev)
|
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)
|
void log_printline(enum LogMessageLevel lev, const std::string &text)
|
||||||
{
|
{
|
||||||
log_threadnamemutex.Lock();
|
JMutexAutoLock lock(log_threadnamemutex);
|
||||||
std::string threadname = "(unknown thread)";
|
std::string threadname = "(unknown thread)";
|
||||||
std::map<threadid_t, std::string>::const_iterator i;
|
std::map<threadid_t, std::string>::const_iterator i;
|
||||||
i = log_threadnames.find(get_current_thread_id());
|
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;
|
threadname = i->second;
|
||||||
std::string levelname = get_lev_string(lev);
|
std::string levelname = get_lev_string(lev);
|
||||||
std::ostringstream os(std::ios_base::binary);
|
std::ostringstream os(std::ios_base::binary);
|
||||||
os<<getTimestamp()<<": "<<levelname<<"["<<threadname<<"]: "<<text;
|
os << getTimestamp() << ": " << levelname << "["<<threadname<<"]: " << text;
|
||||||
for(std::list<ILogOutput*>::iterator i = log_outputs[lev].begin();
|
|
||||||
i != log_outputs[lev].end(); i++){
|
for(std::vector<ILogOutput*>::iterator i = log_outputs[lev].begin();
|
||||||
|
i != log_outputs[lev].end(); i++) {
|
||||||
ILogOutput *out = *i;
|
ILogOutput *out = *i;
|
||||||
if (out->silence)
|
if (out->silence)
|
||||||
continue;
|
continue;
|
||||||
|
@ -138,7 +136,6 @@ void log_printline(enum LogMessageLevel lev, const std::string &text)
|
||||||
out->printLog(os.str(), lev);
|
out->printLog(os.str(), lev);
|
||||||
out->printLog(lev, text);
|
out->printLog(lev, text);
|
||||||
}
|
}
|
||||||
log_threadnamemutex.Unlock();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
class Logbuf : public std::streambuf
|
class Logbuf : public std::streambuf
|
||||||
|
|
|
@ -47,10 +47,6 @@ else()
|
||||||
endif()
|
endif()
|
||||||
mark_as_advanced(LUA_USE_DLOPEN)
|
mark_as_advanced(LUA_USE_DLOPEN)
|
||||||
|
|
||||||
if(DEFAULT_POSIX)
|
|
||||||
else()
|
|
||||||
endif()
|
|
||||||
|
|
||||||
if(DEFAULT_ANSI)
|
if(DEFAULT_ANSI)
|
||||||
option(LUA_ANSI "Disable non-ansi features." ON)
|
option(LUA_ANSI "Disable non-ansi features." ON)
|
||||||
else()
|
else()
|
||||||
|
@ -87,6 +83,10 @@ if(LUA_USE_DLOPEN)
|
||||||
endif(NOT APPLE)
|
endif(NOT APPLE)
|
||||||
endif(LUA_USE_DLOPEN)
|
endif(LUA_USE_DLOPEN)
|
||||||
|
|
||||||
|
if(DEFAULT_POSIX)
|
||||||
|
set(COMMON_CFLAGS "${COMMON_CFLAGS} -DLUA_USE_POSIX")
|
||||||
|
endif(DEFAULT_POSIX)
|
||||||
|
|
||||||
if(LUA_ANSI)
|
if(LUA_ANSI)
|
||||||
set(COMMON_CFLAGS "${COMMON_CFLAGS} -DLUA_ANSI")
|
set(COMMON_CFLAGS "${COMMON_CFLAGS} -DLUA_ANSI")
|
||||||
endif(LUA_ANSI)
|
endif(LUA_ANSI)
|
||||||
|
|
149
src/main.cpp
149
src/main.cpp
|
@ -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.
|
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
|
#ifdef _MSC_VER
|
||||||
#ifndef SERVER // Dedicated server isn't linked with Irrlicht
|
#ifndef SERVER // Dedicated server isn't linked with Irrlicht
|
||||||
#pragma comment(lib, "Irrlicht.lib")
|
#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 "serverlist.h"
|
||||||
#include "httpfetch.h"
|
#include "httpfetch.h"
|
||||||
#include "guiEngine.h"
|
#include "guiEngine.h"
|
||||||
|
#include "map.h"
|
||||||
#include "mapsector.h"
|
#include "mapsector.h"
|
||||||
#include "player.h"
|
#include "player.h"
|
||||||
#include "fontengine.h"
|
#include "fontengine.h"
|
||||||
|
#include "database.h"
|
||||||
#include "database-sqlite3.h"
|
|
||||||
#ifdef USE_LEVELDB
|
|
||||||
#include "database-leveldb.h"
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#if USE_REDIS
|
|
||||||
#include "database-redis.h"
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#ifdef HAVE_TOUCHSCREENGUI
|
#ifdef HAVE_TOUCHSCREENGUI
|
||||||
#include "touchscreengui.h"
|
#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 determine_subgame(GameParams *game_params);
|
||||||
|
|
||||||
static bool run_dedicated_server(const GameParams &game_params, const Settings &cmd_args);
|
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,
|
static bool migrate_database(const GameParams &game_params, const Settings &cmd_args);
|
||||||
Server *server);
|
|
||||||
|
|
||||||
#ifndef SERVER
|
#ifndef SERVER
|
||||||
static bool print_video_modes();
|
static bool print_video_modes();
|
||||||
|
@ -836,9 +815,9 @@ int main(int argc, char *argv[])
|
||||||
|
|
||||||
#ifndef __ANDROID__
|
#ifndef __ANDROID__
|
||||||
// Run unit tests
|
// Run unit tests
|
||||||
if ((ENABLE_TESTS && cmd_args.getFlag("disable-unittests") == false)
|
if (cmd_args.getFlag("run-unittests")) {
|
||||||
|| cmd_args.getFlag("enable-unittests") == true) {
|
|
||||||
run_tests();
|
run_tests();
|
||||||
|
return 0;
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
@ -909,10 +888,8 @@ static void set_allowed_options(OptionList *allowed_options)
|
||||||
_("Load configuration from specified file"))));
|
_("Load configuration from specified file"))));
|
||||||
allowed_options->insert(std::make_pair("port", ValueSpec(VALUETYPE_STRING,
|
allowed_options->insert(std::make_pair("port", ValueSpec(VALUETYPE_STRING,
|
||||||
_("Set network port (UDP)"))));
|
_("Set network port (UDP)"))));
|
||||||
allowed_options->insert(std::make_pair("disable-unittests", ValueSpec(VALUETYPE_FLAG,
|
allowed_options->insert(std::make_pair("run-unittests", ValueSpec(VALUETYPE_FLAG,
|
||||||
_("Disable unit tests"))));
|
_("Run the unit tests and exit"))));
|
||||||
allowed_options->insert(std::make_pair("enable-unittests", ValueSpec(VALUETYPE_FLAG,
|
|
||||||
_("Enable unit tests"))));
|
|
||||||
allowed_options->insert(std::make_pair("map-dir", ValueSpec(VALUETYPE_STRING,
|
allowed_options->insert(std::make_pair("map-dir", ValueSpec(VALUETYPE_STRING,
|
||||||
_("Same as --world (deprecated)"))));
|
_("Same as --world (deprecated)"))));
|
||||||
allowed_options->insert(std::make_pair("world", ValueSpec(VALUETYPE_STRING,
|
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;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Database migration
|
||||||
|
if (cmd_args.exists("migrate"))
|
||||||
|
return migrate_database(game_params, cmd_args);
|
||||||
|
|
||||||
// Create server
|
// Create server
|
||||||
Server server(game_params.world_path,
|
Server server(game_params.world_path,
|
||||||
game_params.game_spec, false, bind_addr.isIPv6());
|
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);
|
server.start(bind_addr);
|
||||||
|
|
||||||
// Run server
|
// Run server
|
||||||
|
@ -1483,79 +1460,63 @@ static bool run_dedicated_server(const GameParams &game_params, const Settings &
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
static bool migrate_database(const GameParams &game_params, const Settings &cmd_args,
|
static bool migrate_database(const GameParams &game_params, const Settings &cmd_args)
|
||||||
Server *server)
|
|
||||||
{
|
{
|
||||||
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");
|
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) {
|
if (backend == migrate_to) {
|
||||||
errorstream << "Cannot migrate: new backend is same as the old one"
|
errorstream << "Cannot migrate: new backend is same"
|
||||||
<< std::endl;
|
<< " as the old one" << std::endl;
|
||||||
return false;
|
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")
|
u32 count = 0;
|
||||||
new_db = new Database_SQLite3(&(ServerMap&)server->getMap(),
|
time_t last_update_time = 0;
|
||||||
game_params.world_path);
|
bool &kill = *porting::signal_handler_killstatus();
|
||||||
#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;
|
|
||||||
}
|
|
||||||
|
|
||||||
std::list<v3s16> blocks;
|
std::vector<v3s16> blocks;
|
||||||
ServerMap &old_map = ((ServerMap&)server->getMap());
|
old_db->listAllLoadableBlocks(blocks);
|
||||||
old_map.listAllLoadableBlocks(blocks);
|
|
||||||
int count = 0;
|
|
||||||
new_db->beginSave();
|
new_db->beginSave();
|
||||||
for (std::list<v3s16>::iterator i = blocks.begin(); i != blocks.end(); i++) {
|
for (std::vector<v3s16>::const_iterator it = blocks.begin(); it != blocks.end(); ++it) {
|
||||||
MapBlock *block = old_map.loadBlock(*i);
|
if (kill) return false;
|
||||||
if (!block) {
|
|
||||||
errorstream << "Failed to load block " << PP(*i) << ", skipping it.";
|
const std::string &data = old_db->loadBlock(*it);
|
||||||
|
if (!data.empty()) {
|
||||||
|
new_db->saveBlock(*it, data);
|
||||||
} else {
|
} else {
|
||||||
old_map.saveBlock(block, new_db);
|
errorstream << "Failed to load block " << PP(*it) << ", skipping it." << std::endl;
|
||||||
MapSector *sector = old_map.getSectorNoGenerate(v2s16(i->X, i->Z));
|
}
|
||||||
sector->deleteBlock(block);
|
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();
|
new_db->endSave();
|
||||||
|
delete old_db;
|
||||||
delete new_db;
|
delete new_db;
|
||||||
|
|
||||||
actionstream << "Successfully migrated " << count << " blocks" << std::endl;
|
actionstream << "Successfully migrated " << count << " blocks" << std::endl;
|
||||||
world_mt.set("backend", migrate_to);
|
world_mt.set("backend", migrate_to);
|
||||||
if (!world_mt.updateConfigFile(
|
if (!world_mt.updateConfigFile(world_mt_path.c_str()))
|
||||||
(game_params.world_path+ DIR_DELIM + "world.mt").c_str()))
|
|
||||||
errorstream << "Failed to update world.mt!" << std::endl;
|
errorstream << "Failed to update world.mt!" << std::endl;
|
||||||
else
|
else
|
||||||
actionstream << "world.mt updated" << std::endl;
|
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);
|
input = new RealInputHandler(device, receiver);
|
||||||
|
|
||||||
smgr = device->getSceneManager();
|
smgr = device->getSceneManager();
|
||||||
|
smgr->getParameters()->setAttribute(scene::ALLOW_ZWRITE_ON_TRANSPARENT, true);
|
||||||
|
|
||||||
guienv = device->getGUIEnvironment();
|
guienv = device->getGUIEnvironment();
|
||||||
skin = guienv->getSkin();
|
skin = guienv->getSkin();
|
||||||
skin->setColor(gui::EGDC_BUTTON_TEXT, video::SColor(255, 255, 255, 255));
|
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_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));
|
skin->setColor(gui::EGDC_HIGH_LIGHT_TEXT, video::SColor(255, 255, 255, 255));
|
||||||
|
|
||||||
g_fontengine = new FontEngine(g_settings, guienv);
|
g_fontengine = new FontEngine(g_settings, guienv);
|
||||||
|
|
226
src/map.cpp
226
src/map.cpp
|
@ -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<<")"
|
#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
|
Map
|
||||||
|
@ -1421,43 +1405,39 @@ bool Map::getDayNightDiff(v3s16 blockpos)
|
||||||
Updates usage timers
|
Updates usage timers
|
||||||
*/
|
*/
|
||||||
void Map::timerUpdate(float dtime, float unload_timeout,
|
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);
|
bool save_before_unloading = (mapType() == MAPTYPE_SERVER);
|
||||||
|
|
||||||
// Profile modified reasons
|
// Profile modified reasons
|
||||||
Profiler modprofiler;
|
Profiler modprofiler;
|
||||||
|
|
||||||
std::list<v2s16> sector_deletion_queue;
|
std::vector<v2s16> sector_deletion_queue;
|
||||||
u32 deleted_blocks_count = 0;
|
u32 deleted_blocks_count = 0;
|
||||||
u32 saved_blocks_count = 0;
|
u32 saved_blocks_count = 0;
|
||||||
u32 block_count_all = 0;
|
u32 block_count_all = 0;
|
||||||
|
|
||||||
beginSave();
|
beginSave();
|
||||||
for(std::map<v2s16, MapSector*>::iterator si = m_sectors.begin();
|
for(std::map<v2s16, MapSector*>::iterator si = m_sectors.begin();
|
||||||
si != m_sectors.end(); ++si)
|
si != m_sectors.end(); ++si) {
|
||||||
{
|
|
||||||
MapSector *sector = si->second;
|
MapSector *sector = si->second;
|
||||||
|
|
||||||
bool all_blocks_deleted = true;
|
bool all_blocks_deleted = true;
|
||||||
|
|
||||||
std::list<MapBlock*> blocks;
|
MapBlockVect blocks;
|
||||||
sector->getBlocks(blocks);
|
sector->getBlocks(blocks);
|
||||||
|
|
||||||
for(std::list<MapBlock*>::iterator i = blocks.begin();
|
for(MapBlockVect::iterator i = blocks.begin();
|
||||||
i != blocks.end(); ++i)
|
i != blocks.end(); ++i) {
|
||||||
{
|
|
||||||
MapBlock *block = (*i);
|
MapBlock *block = (*i);
|
||||||
|
|
||||||
block->incrementUsageTimer(dtime);
|
block->incrementUsageTimer(dtime);
|
||||||
|
|
||||||
if(block->refGet() == 0 && block->getUsageTimer() > unload_timeout)
|
if(block->refGet() == 0 && block->getUsageTimer() > unload_timeout) {
|
||||||
{
|
|
||||||
v3s16 p = block->getPos();
|
v3s16 p = block->getPos();
|
||||||
|
|
||||||
// Save if modified
|
// 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);
|
modprofiler.add(block->getModifiedReason(), 1);
|
||||||
if (!saveBlock(block))
|
if (!saveBlock(block))
|
||||||
continue;
|
continue;
|
||||||
|
@ -1472,15 +1452,13 @@ void Map::timerUpdate(float dtime, float unload_timeout,
|
||||||
|
|
||||||
deleted_blocks_count++;
|
deleted_blocks_count++;
|
||||||
}
|
}
|
||||||
else
|
else {
|
||||||
{
|
|
||||||
all_blocks_deleted = false;
|
all_blocks_deleted = false;
|
||||||
block_count_all++;
|
block_count_all++;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if(all_blocks_deleted)
|
if(all_blocks_deleted) {
|
||||||
{
|
|
||||||
sector_deletion_queue.push_back(si->first);
|
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);
|
timerUpdate(0.0, -1.0, unloaded_blocks);
|
||||||
}
|
}
|
||||||
|
|
||||||
void Map::deleteSectors(std::list<v2s16> &list)
|
void Map::deleteSectors(std::vector<v2s16> §orList)
|
||||||
{
|
{
|
||||||
for(std::list<v2s16>::iterator j = list.begin();
|
for(std::vector<v2s16>::iterator j = sectorList.begin();
|
||||||
j != list.end(); ++j)
|
j != sectorList.end(); ++j) {
|
||||||
{
|
|
||||||
MapSector *sector = m_sectors[*j];
|
MapSector *sector = m_sectors[*j];
|
||||||
// If sector is in sector cache, remove it from there
|
// If sector is in sector cache, remove it from there
|
||||||
if(m_sector_cache == sector)
|
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)
|
void Map::PrintInfo(std::ostream &out)
|
||||||
{
|
{
|
||||||
out<<"Map: ";
|
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
|
// Find out whether there is a suspect for this action
|
||||||
std::string suspect;
|
std::string suspect;
|
||||||
if(m_gamedef->rollback()){
|
if(m_gamedef->rollback()) {
|
||||||
suspect = m_gamedef->rollback()->getSuspect(p0, 83, 1);
|
suspect = m_gamedef->rollback()->getSuspect(p0, 83, 1);
|
||||||
}
|
}
|
||||||
|
|
||||||
if(!suspect.empty()){
|
if(m_gamedef->rollback() && !suspect.empty()){
|
||||||
// Blame suspect
|
// Blame suspect
|
||||||
RollbackScopeActor rollback_scope(m_gamedef->rollback(), suspect, true);
|
RollbackScopeActor rollback_scope(m_gamedef->rollback(), suspect, true);
|
||||||
// Get old node for rollback
|
// 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());
|
bool succeeded = conf.readConfigFile(conf_path.c_str());
|
||||||
if (!succeeded || !conf.exists("backend")) {
|
if (!succeeded || !conf.exists("backend")) {
|
||||||
// fall back to sqlite3
|
// fall back to sqlite3
|
||||||
dbase = new Database_SQLite3(this, savedir);
|
|
||||||
conf.set("backend", "sqlite3");
|
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_savedir = savedir;
|
||||||
m_map_saving_enabled = false;
|
m_map_saving_enabled = false;
|
||||||
|
@ -2892,7 +2800,8 @@ plan_b:
|
||||||
}
|
}
|
||||||
|
|
||||||
bool ServerMap::loadFromFolders() {
|
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 true;
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
@ -2914,14 +2823,14 @@ std::string ServerMap::getSectorDir(v2s16 pos, int layout)
|
||||||
{
|
{
|
||||||
case 1:
|
case 1:
|
||||||
snprintf(cc, 9, "%.4x%.4x",
|
snprintf(cc, 9, "%.4x%.4x",
|
||||||
(unsigned int)pos.X&0xffff,
|
(unsigned int) pos.X & 0xffff,
|
||||||
(unsigned int)pos.Y&0xffff);
|
(unsigned int) pos.Y & 0xffff);
|
||||||
|
|
||||||
return m_savedir + DIR_DELIM + "sectors" + DIR_DELIM + cc;
|
return m_savedir + DIR_DELIM + "sectors" + DIR_DELIM + cc;
|
||||||
case 2:
|
case 2:
|
||||||
snprintf(cc, 9, "%.3x" DIR_DELIM "%.3x",
|
snprintf(cc, 9, (std::string("%.3x") + DIR_DELIM + "%.3x").c_str(),
|
||||||
(unsigned int)pos.X&0xfff,
|
(unsigned int) pos.X & 0xfff,
|
||||||
(unsigned int)pos.Y&0xfff);
|
(unsigned int) pos.Y & 0xfff);
|
||||||
|
|
||||||
return m_savedir + DIR_DELIM + "sectors2" + DIR_DELIM + cc;
|
return m_savedir + DIR_DELIM + "sectors2" + DIR_DELIM + cc;
|
||||||
default:
|
default:
|
||||||
|
@ -2945,10 +2854,10 @@ v2s16 ServerMap::getSectorPos(std::string dirname)
|
||||||
{
|
{
|
||||||
// New layout
|
// New layout
|
||||||
fs::RemoveLastPathComponent(dirname, &component, 2);
|
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...
|
// Sign-extend the 12 bit values up to 16 bits...
|
||||||
if(x&0x800) x|=0xF000;
|
if(x & 0x800) x |= 0xF000;
|
||||||
if(y&0x800) y|=0xF000;
|
if(y & 0x800) y |= 0xF000;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
|
@ -2983,8 +2892,7 @@ std::string ServerMap::getBlockFilename(v3s16 p)
|
||||||
void ServerMap::save(ModifiedState save_level)
|
void ServerMap::save(ModifiedState save_level)
|
||||||
{
|
{
|
||||||
DSTACK(__FUNCTION_NAME);
|
DSTACK(__FUNCTION_NAME);
|
||||||
if(m_map_saving_enabled == false)
|
if(m_map_saving_enabled == false) {
|
||||||
{
|
|
||||||
infostream<<"WARNING: Not saving map, saving disabled."<<std::endl;
|
infostream<<"WARNING: Not saving map, saving disabled."<<std::endl;
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
@ -2993,8 +2901,7 @@ void ServerMap::save(ModifiedState save_level)
|
||||||
infostream<<"ServerMap: Saving whole map, this can take time."
|
infostream<<"ServerMap: Saving whole map, this can take time."
|
||||||
<<std::endl;
|
<<std::endl;
|
||||||
|
|
||||||
if(m_map_metadata_changed || save_level == MOD_STATE_CLEAN)
|
if(m_map_metadata_changed || save_level == MOD_STATE_CLEAN) {
|
||||||
{
|
|
||||||
saveMapMeta();
|
saveMapMeta();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -3009,30 +2916,27 @@ void ServerMap::save(ModifiedState save_level)
|
||||||
bool save_started = false;
|
bool save_started = false;
|
||||||
|
|
||||||
for(std::map<v2s16, MapSector*>::iterator i = m_sectors.begin();
|
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;
|
ServerMapSector *sector = (ServerMapSector*)i->second;
|
||||||
assert(sector->getId() == MAPSECTOR_SERVER);
|
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);
|
saveSectorMeta(sector);
|
||||||
sector_meta_count++;
|
sector_meta_count++;
|
||||||
}
|
}
|
||||||
std::list<MapBlock*> blocks;
|
|
||||||
|
MapBlockVect blocks;
|
||||||
sector->getBlocks(blocks);
|
sector->getBlocks(blocks);
|
||||||
|
|
||||||
for(std::list<MapBlock*>::iterator j = blocks.begin();
|
for(MapBlockVect::iterator j = blocks.begin();
|
||||||
j != blocks.end(); ++j)
|
j != blocks.end(); ++j) {
|
||||||
{
|
|
||||||
MapBlock *block = *j;
|
MapBlock *block = *j;
|
||||||
|
|
||||||
block_count_all++;
|
block_count_all++;
|
||||||
|
|
||||||
if(block->getModified() >= (u32)save_level)
|
if(block->getModified() >= (u32)save_level) {
|
||||||
{
|
|
||||||
// Lazy beginSave()
|
// Lazy beginSave()
|
||||||
if(!save_started){
|
if(!save_started) {
|
||||||
beginSave();
|
beginSave();
|
||||||
save_started = true;
|
save_started = true;
|
||||||
}
|
}
|
||||||
|
@ -3050,6 +2954,7 @@ void ServerMap::save(ModifiedState save_level)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if(save_started)
|
if(save_started)
|
||||||
endSave();
|
endSave();
|
||||||
|
|
||||||
|
@ -3057,8 +2962,7 @@ void ServerMap::save(ModifiedState save_level)
|
||||||
Only print if something happened or saved whole map
|
Only print if something happened or saved whole map
|
||||||
*/
|
*/
|
||||||
if(save_level == MOD_STATE_CLEAN || sector_meta_count != 0
|
if(save_level == MOD_STATE_CLEAN || sector_meta_count != 0
|
||||||
|| block_count != 0)
|
|| block_count != 0) {
|
||||||
{
|
|
||||||
infostream<<"ServerMap: Written: "
|
infostream<<"ServerMap: Written: "
|
||||||
<<sector_meta_count<<" sector metadata files, "
|
<<sector_meta_count<<" sector metadata files, "
|
||||||
<<block_count<<" block 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()){
|
if (loadFromFolders()) {
|
||||||
errorstream<<"Map::listAllLoadableBlocks(): Result will be missing "
|
errorstream << "Map::listAllLoadableBlocks(): Result will be missing "
|
||||||
<<"all blocks that are stored in flat files"<<std::endl;
|
<< "all blocks that are stored in flat files." << std::endl;
|
||||||
}
|
}
|
||||||
dbase->listAllLoadableBlocks(dst);
|
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();
|
for(std::map<v2s16, MapSector*>::iterator si = m_sectors.begin();
|
||||||
si != m_sectors.end(); ++si)
|
si != m_sectors.end(); ++si)
|
||||||
{
|
{
|
||||||
MapSector *sector = si->second;
|
MapSector *sector = si->second;
|
||||||
|
|
||||||
std::list<MapBlock*> blocks;
|
MapBlockVect blocks;
|
||||||
sector->getBlocks(blocks);
|
sector->getBlocks(blocks);
|
||||||
|
|
||||||
for(std::list<MapBlock*>::iterator i = blocks.begin();
|
for(MapBlockVect::iterator i = blocks.begin();
|
||||||
i != blocks.end(); ++i)
|
i != blocks.end(); ++i) {
|
||||||
{
|
v3s16 p = (*i)->getPos();
|
||||||
MapBlock *block = (*i);
|
|
||||||
v3s16 p = block->getPos();
|
|
||||||
dst.push_back(p);
|
dst.push_back(p);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -3331,6 +3233,24 @@ bool ServerMap::loadSectorFull(v2s16 p2d)
|
||||||
}
|
}
|
||||||
#endif
|
#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()
|
void ServerMap::beginSave()
|
||||||
{
|
{
|
||||||
dbase->beginSave();
|
dbase->beginSave();
|
||||||
|
@ -3370,7 +3290,7 @@ bool ServerMap::saveBlock(MapBlock *block, Database *db)
|
||||||
|
|
||||||
std::string data = o.str();
|
std::string data = o.str();
|
||||||
bool ret = db->saveBlock(p3d, data);
|
bool ret = db->saveBlock(p3d, data);
|
||||||
if(ret) {
|
if (ret) {
|
||||||
// We just wrote it to the disk so clear modified flag
|
// We just wrote it to the disk so clear modified flag
|
||||||
block->resetModified();
|
block->resetModified();
|
||||||
}
|
}
|
||||||
|
@ -3382,7 +3302,7 @@ void ServerMap::loadBlock(std::string sectordir, std::string blockfile,
|
||||||
{
|
{
|
||||||
DSTACK(__FUNCTION_NAME);
|
DSTACK(__FUNCTION_NAME);
|
||||||
|
|
||||||
std::string fullpath = sectordir+DIR_DELIM+blockfile;
|
std::string fullpath = sectordir + DIR_DELIM + blockfile;
|
||||||
try {
|
try {
|
||||||
|
|
||||||
std::ifstream is(fullpath.c_str(), std::ios_base::binary);
|
std::ifstream is(fullpath.c_str(), std::ios_base::binary);
|
||||||
|
@ -3584,7 +3504,7 @@ MapBlock* ServerMap::loadBlock(v3s16 blockpos)
|
||||||
*/
|
*/
|
||||||
|
|
||||||
std::string blockfilename = getBlockFilename(blockpos);
|
std::string blockfilename = getBlockFilename(blockpos);
|
||||||
if(fs::PathExists(sectordir+DIR_DELIM+blockfilename) == false)
|
if(fs::PathExists(sectordir + DIR_DELIM + blockfilename) == false)
|
||||||
return NULL;
|
return NULL;
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
|
24
src/map.h
24
src/map.h
|
@ -34,6 +34,7 @@ with this program; if not, write to the Free Software Foundation, Inc.,
|
||||||
#include "util/container.h"
|
#include "util/container.h"
|
||||||
#include "nodetimer.h"
|
#include "nodetimer.h"
|
||||||
|
|
||||||
|
class Settings;
|
||||||
class Database;
|
class Database;
|
||||||
class ClientMap;
|
class ClientMap;
|
||||||
class MapSector;
|
class MapSector;
|
||||||
|
@ -277,28 +278,18 @@ public:
|
||||||
Saves modified blocks before unloading on MAPTYPE_SERVER.
|
Saves modified blocks before unloading on MAPTYPE_SERVER.
|
||||||
*/
|
*/
|
||||||
void timerUpdate(float dtime, float unload_timeout,
|
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().
|
Unloads all blocks with a zero refCount().
|
||||||
Saves modified blocks before unloading on MAPTYPE_SERVER.
|
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
|
// Deletes sectors and their blocks from memory
|
||||||
// Takes cache into account
|
// Takes cache into account
|
||||||
// If deleted sector is in sector cache, clears cache
|
// If deleted sector is in sector cache, clears cache
|
||||||
void deleteSectors(std::list<v2s16> &list);
|
void deleteSectors(std::vector<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
|
|
||||||
|
|
||||||
// For debug printing. Prints "Map: ", "ServerMap: " or "ClientMap: "
|
// For debug printing. Prints "Map: ", "ServerMap: " or "ClientMap: "
|
||||||
virtual void PrintInfo(std::ostream &out);
|
virtual void PrintInfo(std::ostream &out);
|
||||||
|
@ -455,6 +446,7 @@ public:
|
||||||
/*
|
/*
|
||||||
Database functions
|
Database functions
|
||||||
*/
|
*/
|
||||||
|
static Database *createDatabase(const std::string &name, const std::string &savedir, Settings &conf);
|
||||||
// Verify we can read/write to the database
|
// Verify we can read/write to the database
|
||||||
void verifyDatabase();
|
void verifyDatabase();
|
||||||
|
|
||||||
|
@ -466,8 +458,8 @@ public:
|
||||||
void endSave();
|
void endSave();
|
||||||
|
|
||||||
void save(ModifiedState save_level);
|
void save(ModifiedState save_level);
|
||||||
void listAllLoadableBlocks(std::list<v3s16> &dst);
|
void listAllLoadableBlocks(std::vector<v3s16> &dst);
|
||||||
void listAllLoadedBlocks(std::list<v3s16> &dst);
|
void listAllLoadedBlocks(std::vector<v3s16> &dst);
|
||||||
// Saves map seed and possibly other stuff
|
// Saves map seed and possibly other stuff
|
||||||
void saveMapMeta();
|
void saveMapMeta();
|
||||||
void loadMapMeta();
|
void loadMapMeta();
|
||||||
|
@ -491,8 +483,8 @@ public:
|
||||||
// Returns true if sector now resides in memory
|
// Returns true if sector now resides in memory
|
||||||
//bool deFlushSector(v2s16 p2d);
|
//bool deFlushSector(v2s16 p2d);
|
||||||
|
|
||||||
bool saveBlock(MapBlock *block, Database *db);
|
|
||||||
bool saveBlock(MapBlock *block);
|
bool saveBlock(MapBlock *block);
|
||||||
|
static bool saveBlock(MapBlock *block, Database *db);
|
||||||
// This will generate a sector with getSector if not found.
|
// 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);
|
void loadBlock(std::string sectordir, std::string blockfile, MapSector *sector, bool save_after_load=false);
|
||||||
MapBlock* loadBlock(v3s16 p);
|
MapBlock* loadBlock(v3s16 p);
|
||||||
|
|
|
@ -330,47 +330,42 @@ void MapBlock::copyFrom(VoxelManipulator &dst)
|
||||||
void MapBlock::actuallyUpdateDayNightDiff()
|
void MapBlock::actuallyUpdateDayNightDiff()
|
||||||
{
|
{
|
||||||
INodeDefManager *nodemgr = m_gamedef->ndef();
|
INodeDefManager *nodemgr = m_gamedef->ndef();
|
||||||
|
|
||||||
// Running this function un-expires m_day_night_differs
|
// Running this function un-expires m_day_night_differs
|
||||||
m_day_night_differs_expired = false;
|
m_day_night_differs_expired = false;
|
||||||
|
|
||||||
if(data == NULL)
|
if (data == NULL) {
|
||||||
{
|
|
||||||
m_day_night_differs = false;
|
m_day_night_differs = false;
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool differs = false;
|
bool differs;
|
||||||
|
|
||||||
/*
|
/*
|
||||||
Check if any lighting value 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];
|
MapNode &n = data[i];
|
||||||
if(n.getLight(LIGHTBANK_DAY, nodemgr) != n.getLight(LIGHTBANK_NIGHT, nodemgr))
|
|
||||||
{
|
differs = !n.isLightDayNightEq(nodemgr);
|
||||||
differs = true;
|
if (differs)
|
||||||
break;
|
break;
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
If some lighting values differ, check if the whole thing is
|
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;
|
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];
|
MapNode &n = data[i];
|
||||||
if(n.getContent() != CONTENT_AIR)
|
if (n.getContent() != CONTENT_AIR) {
|
||||||
{
|
|
||||||
only_air = false;
|
only_air = false;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if(only_air)
|
if (only_air)
|
||||||
differs = false;
|
differs = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -614,6 +614,8 @@ private:
|
||||||
int m_refcount;
|
int m_refcount;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
typedef std::vector<MapBlock*> MapBlockVect;
|
||||||
|
|
||||||
inline bool blockpos_over_limit(v3s16 p)
|
inline bool blockpos_over_limit(v3s16 p)
|
||||||
{
|
{
|
||||||
return
|
return
|
||||||
|
|
|
@ -42,7 +42,7 @@ static void applyFacesShading(video::SColor& color, float factor)
|
||||||
MeshMakeData
|
MeshMakeData
|
||||||
*/
|
*/
|
||||||
|
|
||||||
MeshMakeData::MeshMakeData(IGameDef *gamedef):
|
MeshMakeData::MeshMakeData(IGameDef *gamedef, bool use_shaders):
|
||||||
m_vmanip(),
|
m_vmanip(),
|
||||||
m_blockpos(-1337,-1337,-1337),
|
m_blockpos(-1337,-1337,-1337),
|
||||||
m_crack_pos_relative(-1337, -1337, -1337),
|
m_crack_pos_relative(-1337, -1337, -1337),
|
||||||
|
@ -50,7 +50,8 @@ MeshMakeData::MeshMakeData(IGameDef *gamedef):
|
||||||
m_smooth_lighting(false),
|
m_smooth_lighting(false),
|
||||||
m_show_hud(false),
|
m_show_hud(false),
|
||||||
m_highlight_mesh_color(255, 255, 255, 255),
|
m_highlight_mesh_color(255, 255, 255, 255),
|
||||||
m_gamedef(gamedef)
|
m_gamedef(gamedef),
|
||||||
|
m_use_shaders(use_shaders)
|
||||||
{}
|
{}
|
||||||
|
|
||||||
void MeshMakeData::fill(MapBlock *block)
|
void MeshMakeData::fill(MapBlock *block)
|
||||||
|
@ -247,7 +248,7 @@ static u16 getSmoothLightCombined(v3s16 p, MeshMakeData *data)
|
||||||
|
|
||||||
for (u32 i = 0; i < 8; i++)
|
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 it's CONTENT_IGNORE we can't do any light calculations
|
||||||
if (n.getContent() == CONTENT_IGNORE) {
|
if (n.getContent() == CONTENT_IGNORE) {
|
||||||
|
@ -437,8 +438,6 @@ struct FastFace
|
||||||
static void makeFastFace(TileSpec tile, u16 li0, u16 li1, u16 li2, u16 li3,
|
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)
|
v3f p, v3s16 dir, v3f scale, u8 light_source, std::vector<FastFace> &dest)
|
||||||
{
|
{
|
||||||
FastFace face;
|
|
||||||
|
|
||||||
// Position is at the center of the cube.
|
// Position is at the center of the cube.
|
||||||
v3f pos = p * BS;
|
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;
|
u8 alpha = tile.alpha;
|
||||||
|
|
||||||
|
dest.push_back(FastFace());
|
||||||
|
|
||||||
|
FastFace& face = *dest.rbegin();
|
||||||
|
|
||||||
face.vertices[0] = video::S3DVertex(vertex_pos[0], normal,
|
face.vertices[0] = video::S3DVertex(vertex_pos[0], normal,
|
||||||
MapBlock_LightColor(alpha, li0, light_source),
|
MapBlock_LightColor(alpha, li0, light_source),
|
||||||
core::vector2d<f32>(x0+w*abs_scale, y0+h));
|
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));
|
core::vector2d<f32>(x0+w*abs_scale, y0));
|
||||||
|
|
||||||
face.tile = tile;
|
face.tile = tile;
|
||||||
dest.push_back(face);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
@ -744,8 +746,8 @@ TileSpec getNodeTile(MapNode mn, v3s16 p, v3s16 dir, MeshMakeData *data)
|
||||||
static void getTileInfo(
|
static void getTileInfo(
|
||||||
// Input:
|
// Input:
|
||||||
MeshMakeData *data,
|
MeshMakeData *data,
|
||||||
v3s16 p,
|
const v3s16 &p,
|
||||||
v3s16 face_dir,
|
const v3s16 &face_dir,
|
||||||
// Output:
|
// Output:
|
||||||
bool &makes_face,
|
bool &makes_face,
|
||||||
v3s16 &p_corrected,
|
v3s16 &p_corrected,
|
||||||
|
@ -759,14 +761,20 @@ static void getTileInfo(
|
||||||
INodeDefManager *ndef = data->m_gamedef->ndef();
|
INodeDefManager *ndef = data->m_gamedef->ndef();
|
||||||
v3s16 blockpos_nodes = data->m_blockpos * MAP_BLOCKSIZE;
|
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
|
// 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;
|
makes_face = false;
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
MapNode n1 = vmanip.getNodeNoEx(blockpos_nodes + p + face_dir);
|
|
||||||
|
|
||||||
// This is hackish
|
// This is hackish
|
||||||
bool equivalent = false;
|
bool equivalent = false;
|
||||||
|
@ -1028,7 +1036,7 @@ MapBlockMesh::MapBlockMesh(MeshMakeData *data, v3s16 camera_offset):
|
||||||
m_last_daynight_ratio((u32) -1),
|
m_last_daynight_ratio((u32) -1),
|
||||||
m_daynight_diffs()
|
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");
|
m_enable_highlighting = g_settings->getBool("enable_node_highlighting");
|
||||||
|
|
||||||
// 4-21ms for MAP_BLOCKSIZE=16 (NOTE: probably outdated)
|
// 4-21ms for MAP_BLOCKSIZE=16 (NOTE: probably outdated)
|
||||||
|
@ -1036,6 +1044,7 @@ MapBlockMesh::MapBlockMesh(MeshMakeData *data, v3s16 camera_offset):
|
||||||
//TimeTaker timer1("MapBlockMesh()");
|
//TimeTaker timer1("MapBlockMesh()");
|
||||||
|
|
||||||
std::vector<FastFace> fastfaces_new;
|
std::vector<FastFace> fastfaces_new;
|
||||||
|
fastfaces_new.reserve(512);
|
||||||
|
|
||||||
/*
|
/*
|
||||||
We are including the faces of the trailing edges of the block.
|
We are including the faces of the trailing edges of the block.
|
||||||
|
|
|
@ -45,8 +45,9 @@ struct MeshMakeData
|
||||||
video::SColor m_highlight_mesh_color;
|
video::SColor m_highlight_mesh_color;
|
||||||
|
|
||||||
IGameDef *m_gamedef;
|
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
|
Copy central data directly from block, and other data from
|
||||||
|
|
|
@ -41,6 +41,8 @@ with this program; if not, write to the Free Software Foundation, Inc.,
|
||||||
|
|
||||||
const char *GenElementManager::ELEMENT_TITLE = "element";
|
const char *GenElementManager::ELEMENT_TITLE = "element";
|
||||||
|
|
||||||
|
static const s16 INVALID_HEIGHT = MAP_GENERATION_LIMIT + 1;
|
||||||
|
|
||||||
FlagDesc flagdesc_mapgen[] = {
|
FlagDesc flagdesc_mapgen[] = {
|
||||||
{"trees", MG_TREES},
|
{"trees", MG_TREES},
|
||||||
{"caves", MG_CAVES},
|
{"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)
|
void Mapgen::updateHeightmap(v3s16 nmin, v3s16 nmax)
|
||||||
{
|
{
|
||||||
if (!heightmap)
|
if (!heightmap)
|
||||||
|
@ -166,11 +174,13 @@ void Mapgen::updateHeightmap(v3s16 nmin, v3s16 nmax)
|
||||||
for (s16 x = nmin.X; x <= nmax.X; x++, index++) {
|
for (s16 x = nmin.X; x <= nmax.X; x++, index++) {
|
||||||
s16 y = findGroundLevel(v2s16(x, z), nmin.Y, nmax.Y);
|
s16 y = findGroundLevel(v2s16(x, z), nmin.Y, nmax.Y);
|
||||||
|
|
||||||
// if the values found are out of range, trust the old heightmap
|
if (heightmap[index] != INVALID_HEIGHT) {
|
||||||
if (y == nmax.Y && heightmap[index] > nmax.Y)
|
// if the values found are out of range, trust the old heightmap
|
||||||
continue;
|
if (y == nmax.Y && heightmap[index] > nmax.Y)
|
||||||
if (y == nmin.Y - 1 && heightmap[index] < nmin.Y)
|
continue;
|
||||||
continue;
|
if (y == nmin.Y - 1 && heightmap[index] < nmin.Y)
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
heightmap[index] = y;
|
heightmap[index] = y;
|
||||||
}
|
}
|
||||||
|
@ -417,9 +427,8 @@ void GenerateNotifier::getEvents(
|
||||||
std::map<std::string, std::vector<v3s16> > &event_map,
|
std::map<std::string, std::vector<v3s16> > &event_map,
|
||||||
bool peek_events)
|
bool peek_events)
|
||||||
{
|
{
|
||||||
std::list<GenNotifyEvent>::iterator it;
|
for (std::vector<GenNotifyEvent>::iterator it = m_notify_events.begin();
|
||||||
|
it != m_notify_events.end(); ++it) {
|
||||||
for (it = m_notify_events.begin(); it != m_notify_events.end(); ++it) {
|
|
||||||
GenNotifyEvent &gn = *it;
|
GenNotifyEvent &gn = *it;
|
||||||
std::string name = (gn.type == GENNOTIFY_DECORATION) ?
|
std::string name = (gn.type == GENNOTIFY_DECORATION) ?
|
||||||
"decoration#"+ itos(gn.id) :
|
"decoration#"+ itos(gn.id) :
|
||||||
|
|
|
@ -91,7 +91,7 @@ public:
|
||||||
private:
|
private:
|
||||||
u32 m_notify_on;
|
u32 m_notify_on;
|
||||||
std::set<u32> *m_notify_on_deco_ids;
|
std::set<u32> *m_notify_on_deco_ids;
|
||||||
std::list<GenNotifyEvent> m_notify_events;
|
std::vector<GenNotifyEvent> m_notify_events;
|
||||||
};
|
};
|
||||||
|
|
||||||
struct MapgenSpecificParams {
|
struct MapgenSpecificParams {
|
||||||
|
@ -151,6 +151,7 @@ public:
|
||||||
static u32 getBlockSeed2(v3s16 p, int seed);
|
static u32 getBlockSeed2(v3s16 p, int seed);
|
||||||
s16 findGroundLevelFull(v2s16 p2d);
|
s16 findGroundLevelFull(v2s16 p2d);
|
||||||
s16 findGroundLevel(v2s16 p2d, s16 ymin, s16 ymax);
|
s16 findGroundLevel(v2s16 p2d, s16 ymin, s16 ymax);
|
||||||
|
void initHeightMap(s16 *dest, size_t len);
|
||||||
void updateHeightmap(v3s16 nmin, v3s16 nmax);
|
void updateHeightmap(v3s16 nmin, v3s16 nmax);
|
||||||
void updateLiquid(UniqueQueue<v3s16> *trans_liquid, v3s16 nmin, v3s16 nmax);
|
void updateLiquid(UniqueQueue<v3s16> *trans_liquid, v3s16 nmin, v3s16 nmax);
|
||||||
|
|
||||||
|
|
|
@ -42,7 +42,6 @@ with this program; if not, write to the Free Software Foundation, Inc.,
|
||||||
|
|
||||||
|
|
||||||
FlagDesc flagdesc_mapgen_v5[] = {
|
FlagDesc flagdesc_mapgen_v5[] = {
|
||||||
{"blobs", MGV5_BLOBS},
|
|
||||||
{NULL, 0}
|
{NULL, 0}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -61,6 +60,8 @@ MapgenV5::MapgenV5(int mapgenid, MapgenParams *params, EmergeManager *emerge)
|
||||||
this->biomemap = new u8[csize.X * csize.Z];
|
this->biomemap = new u8[csize.X * csize.Z];
|
||||||
this->heightmap = new s16[csize.X * csize.Z];
|
this->heightmap = new s16[csize.X * csize.Z];
|
||||||
|
|
||||||
|
initHeightMap(this->heightmap, csize.X * csize.Z);
|
||||||
|
|
||||||
MapgenV5Params *sp = (MapgenV5Params *)params->sparams;
|
MapgenV5Params *sp = (MapgenV5Params *)params->sparams;
|
||||||
this->spflags = sp->spflags;
|
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_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_cave2 = new Noise(&sp->np_cave2, seed, csize.X, csize.Y + 2, csize.Z);
|
||||||
noise_ground = new Noise(&sp->np_ground, seed, csize.X, csize.Y + 2, csize.Z);
|
noise_ground = new Noise(&sp->np_ground, seed, csize.X, csize.Y + 2, csize.Z);
|
||||||
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
|
// Biome noise
|
||||||
noise_heat = new Noise(¶ms->np_biome_heat, seed, csize.X, csize.Z);
|
noise_heat = new Noise(¶ms->np_biome_heat, seed, csize.X, csize.Z);
|
||||||
|
@ -117,8 +116,6 @@ MapgenV5::~MapgenV5()
|
||||||
delete noise_cave1;
|
delete noise_cave1;
|
||||||
delete noise_cave2;
|
delete noise_cave2;
|
||||||
delete noise_ground;
|
delete noise_ground;
|
||||||
delete noise_crumble;
|
|
||||||
delete noise_wetness;
|
|
||||||
|
|
||||||
delete noise_heat;
|
delete noise_heat;
|
||||||
delete noise_humidity;
|
delete noise_humidity;
|
||||||
|
@ -130,7 +127,7 @@ MapgenV5::~MapgenV5()
|
||||||
|
|
||||||
MapgenV5Params::MapgenV5Params()
|
MapgenV5Params::MapgenV5Params()
|
||||||
{
|
{
|
||||||
spflags = MGV5_BLOBS;
|
spflags = 0;
|
||||||
|
|
||||||
np_filler_depth = NoiseParams(0, 1, v3f(150, 150, 150), 261, 4, 0.7, 2.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);
|
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_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_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_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_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)
|
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_cave1", np_cave1);
|
||||||
settings->getNoiseParams("mgv5_np_cave2", np_cave2);
|
settings->getNoiseParams("mgv5_np_cave2", np_cave2);
|
||||||
settings->getNoiseParams("mgv5_np_ground", np_ground);
|
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_cave1", np_cave1);
|
||||||
settings->setNoiseParams("mgv5_np_cave2", np_cave2);
|
settings->setNoiseParams("mgv5_np_cave2", np_cave2);
|
||||||
settings->setNoiseParams("mgv5_np_ground", np_ground);
|
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);
|
//TimeTaker t("getGroundLevelAtPoint", NULL, PRECISION_MICRO);
|
||||||
|
|
||||||
float f = 0.55 + NoisePerlin2D(&noise_factor->np, p.X, p.Y, seed);
|
float f = 0.55 + NoisePerlin2D(&noise_factor->np, p.X, p.Y, seed);
|
||||||
if(f < 0.01)
|
if (f < 0.01)
|
||||||
f = 0.01;
|
f = 0.01;
|
||||||
else if(f >= 1.0)
|
else if (f >= 1.0)
|
||||||
f *= 1.6;
|
f *= 1.6;
|
||||||
float h = water_level + NoisePerlin2D(&noise_height->np, p.X, p.Y, seed);
|
float h = water_level + NoisePerlin2D(&noise_height->np, p.X, p.Y, seed);
|
||||||
|
|
||||||
s16 search_top = water_level + 15;
|
s16 search_top = water_level + 15;
|
||||||
s16 search_base = water_level;
|
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;
|
s16 level = -31000;
|
||||||
for (s16 y = search_top; y >= search_base; y--) {
|
for (s16 y = search_top; y >= search_base; y--) {
|
||||||
float n_ground = NoisePerlin3D(&noise_ground->np, p.X, y, p.Y, seed);
|
float n_ground = NoisePerlin3D(&noise_ground->np, p.X, y, p.Y, seed);
|
||||||
if(n_ground * f > y - h) {
|
if (n_ground * f > y - h) {
|
||||||
if(y >= search_top - 7)
|
if (y >= search_top - 7)
|
||||||
break;
|
break;
|
||||||
else
|
else
|
||||||
level = y;
|
level = y;
|
||||||
|
@ -247,18 +230,20 @@ void MapgenV5::makeChunk(BlockMakeData *data)
|
||||||
|
|
||||||
// Generate base terrain
|
// Generate base terrain
|
||||||
s16 stone_surface_max_y = generateBaseTerrain();
|
s16 stone_surface_max_y = generateBaseTerrain();
|
||||||
|
|
||||||
|
// Create heightmap
|
||||||
updateHeightmap(node_min, node_max);
|
updateHeightmap(node_min, node_max);
|
||||||
|
|
||||||
// Calculate biomes
|
// Create biomemap at heightmap surface
|
||||||
bmgr->calcBiomes(csize.X, csize.Z, noise_heat->result,
|
bmgr->calcBiomes(csize.X, csize.Z, noise_heat->result,
|
||||||
noise_humidity->result, heightmap, biomemap);
|
noise_humidity->result, heightmap, biomemap);
|
||||||
|
|
||||||
// Actually place the biome-specific nodes
|
// Actually place the biome-specific nodes
|
||||||
generateBiomes();
|
generateBiomes(noise_heat->result, noise_humidity->result);
|
||||||
|
|
||||||
// Generate caves
|
// Generate caves
|
||||||
if ((flags & MG_CAVES) && (stone_surface_max_y >= node_min.Y))
|
if ((flags & MG_CAVES) && (stone_surface_max_y >= node_min.Y))
|
||||||
generateCaves();
|
generateCaves(stone_surface_max_y);
|
||||||
|
|
||||||
// Generate dungeons and desert temples
|
// Generate dungeons and desert temples
|
||||||
if ((flags & MG_DUNGEONS) && (stone_surface_max_y >= node_min.Y)) {
|
if ((flags & MG_DUNGEONS) && (stone_surface_max_y >= node_min.Y)) {
|
||||||
|
@ -269,11 +254,6 @@ void MapgenV5::makeChunk(BlockMakeData *data)
|
||||||
// Generate the registered decorations
|
// Generate the registered decorations
|
||||||
m_emerge->decomgr->placeAllDecos(this, blockseed, node_min, node_max);
|
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
|
// Generate the registered ores
|
||||||
m_emerge->oremgr->placeAllOres(this, blockseed, node_min, node_max);
|
m_emerge->oremgr->placeAllOres(this, blockseed, node_min, node_max);
|
||||||
|
|
||||||
|
@ -311,11 +291,6 @@ void MapgenV5::calculateNoise()
|
||||||
noise_cave2->perlinMap3D(x, y, z);
|
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) {
|
if (node_max.Y >= water_level) {
|
||||||
noise_filler_depth->perlinMap2D(x, z);
|
noise_filler_depth->perlinMap2D(x, z);
|
||||||
noise_heat->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) {
|
//bool is_cave(u32 index) {
|
||||||
// double d1 = contour(noise_cave1->result[index]);
|
// double d1 = contour(noise_cave1->result[index]);
|
||||||
// double d2 = contour(noise_cave2->result[index]);
|
// double d2 = contour(noise_cave2->result[index]);
|
||||||
|
@ -351,22 +324,22 @@ int MapgenV5::generateBaseTerrain()
|
||||||
u32 index2d = 0;
|
u32 index2d = 0;
|
||||||
int stone_surface_max_y = -MAP_GENERATION_LIMIT;
|
int stone_surface_max_y = -MAP_GENERATION_LIMIT;
|
||||||
|
|
||||||
for(s16 z=node_min.Z; z<=node_max.Z; z++) {
|
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 y=node_min.Y - 1; y<=node_max.Y + 1; y++) {
|
||||||
u32 i = vm->m_area.index(node_min.X, y, z);
|
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++) {
|
||||||
if(vm->m_data[i].getContent() != CONTENT_IGNORE)
|
if (vm->m_data[i].getContent() != CONTENT_IGNORE)
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
float f = 0.55 + noise_factor->result[index2d];
|
float f = 0.55 + noise_factor->result[index2d];
|
||||||
if(f < 0.01)
|
if (f < 0.01)
|
||||||
f = 0.01;
|
f = 0.01;
|
||||||
else if(f >= 1.0)
|
else if (f >= 1.0)
|
||||||
f *= 1.6;
|
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 (noise_ground->result[index] * f < y - h) {
|
||||||
if(y <= water_level)
|
if (y <= water_level)
|
||||||
vm->m_data[i] = MapNode(c_water_source);
|
vm->m_data[i] = MapNode(c_water_source);
|
||||||
else
|
else
|
||||||
vm->m_data[i] = MapNode(CONTENT_AIR);
|
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)
|
if (node_max.Y < water_level)
|
||||||
return;
|
return;
|
||||||
|
@ -399,12 +372,11 @@ void MapgenV5::generateBiomes()
|
||||||
|
|
||||||
for (s16 z = node_min.Z; z <= node_max.Z; z++)
|
for (s16 z = node_min.Z; z <= node_max.Z; z++)
|
||||||
for (s16 x = node_min.X; x <= node_max.X; x++, index++) {
|
for (s16 x = node_min.X; x <= node_max.X; x++, index++) {
|
||||||
Biome *biome = (Biome *)bmgr->get(biomemap[index]);
|
Biome *biome = NULL;
|
||||||
s16 dfiller = biome->depth_filler + noise_filler_depth->result[index];
|
s16 dfiller = 0;
|
||||||
s16 y0_top = biome->depth_top;
|
s16 y0_top = 0;
|
||||||
s16 y0_filler = biome->depth_top + dfiller;
|
s16 y0_filler = 0;
|
||||||
s16 shore_max = water_level + biome->height_shore;
|
s16 depth_water_top = 0;
|
||||||
s16 depth_water_top = biome->depth_water_top;
|
|
||||||
|
|
||||||
s16 nplaced = 0;
|
s16 nplaced = 0;
|
||||||
u32 i = vm->m_area.index(x, node_max.Y, z);
|
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--) {
|
for (s16 y = node_max.Y; y >= node_min.Y; y--) {
|
||||||
content_t c = vm->m_data[i].getContent();
|
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) {
|
if (c == c_stone && have_air) {
|
||||||
content_t c_below = vm->m_data[i - em.X].getContent();
|
content_t c_below = vm->m_data[i - em.X].getContent();
|
||||||
|
|
||||||
if (c_below != CONTENT_AIR) {
|
if (c_below != CONTENT_AIR) {
|
||||||
if (nplaced < y0_top) {
|
if (nplaced < y0_top) {
|
||||||
if(y < water_level)
|
vm->m_data[i] = MapNode(biome->c_top);
|
||||||
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);
|
|
||||||
nplaced++;
|
nplaced++;
|
||||||
} else if (nplaced < y0_filler && nplaced >= y0_top) {
|
} else if (nplaced < y0_filler && nplaced >= y0_top) {
|
||||||
if(y < water_level)
|
vm->m_data[i] = MapNode(biome->c_filler);
|
||||||
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);
|
|
||||||
nplaced++;
|
nplaced++;
|
||||||
} else if (c == c_stone) {
|
} else if (c == c_stone) {
|
||||||
have_air = false;
|
have_air = false;
|
||||||
|
@ -470,18 +440,18 @@ void MapgenV5::generateBiomes()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
void MapgenV5::generateCaves()
|
void MapgenV5::generateCaves(int max_stone_y)
|
||||||
{
|
{
|
||||||
u32 index = 0;
|
u32 index = 0;
|
||||||
u32 index2d = 0;
|
u32 index2d = 0;
|
||||||
|
|
||||||
for(s16 z=node_min.Z; z<=node_max.Z; z++) {
|
for (s16 z=node_min.Z; z<=node_max.Z; z++) {
|
||||||
for(s16 y=node_min.Y - 1; y<=node_max.Y + 1; y++) {
|
for (s16 y=node_min.Y - 1; y<=node_max.Y + 1; y++) {
|
||||||
u32 i = vm->m_area.index(node_min.X, y, z);
|
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]);
|
Biome *biome = (Biome *)bmgr->get(biomemap[index2d]);
|
||||||
content_t c = vm->m_data[i].getContent();
|
content_t c = vm->m_data[i].getContent();
|
||||||
if(c == CONTENT_AIR
|
if (c == CONTENT_AIR
|
||||||
|| (y <= water_level
|
|| (y <= water_level
|
||||||
&& c != biome->c_stone
|
&& c != biome->c_stone
|
||||||
&& c != c_stone))
|
&& c != c_stone))
|
||||||
|
@ -489,43 +459,22 @@ void MapgenV5::generateCaves()
|
||||||
|
|
||||||
float d1 = contour(noise_cave1->result[index]);
|
float d1 = contour(noise_cave1->result[index]);
|
||||||
float d2 = contour(noise_cave2->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);
|
vm->m_data[i] = MapNode(CONTENT_AIR);
|
||||||
}
|
}
|
||||||
index2d = index2d - ystride;
|
index2d = index2d - ystride;
|
||||||
}
|
}
|
||||||
index2d = index2d + ystride;
|
index2d = index2d + ystride;
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
|
if (node_max.Y > -256)
|
||||||
|
return;
|
||||||
|
|
||||||
void MapgenV5::generateBlobs()
|
PseudoRandom ps(blockseed + 21343);
|
||||||
{
|
u32 bruises_count = (ps.range(1, 5) == 1) ? ps.range(1, 2) : 0;
|
||||||
u32 index = 0;
|
for (u32 i = 0; i < bruises_count; i++) {
|
||||||
|
CaveV5 cave(this, &ps);
|
||||||
for(s16 z=node_min.Z; z<=node_max.Z; z++) {
|
cave.makeCave(node_min, node_max, max_stone_y);
|
||||||
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);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -23,7 +23,9 @@ with this program; if not, write to the Free Software Foundation, Inc.,
|
||||||
#include "mapgen.h"
|
#include "mapgen.h"
|
||||||
|
|
||||||
/////////////////// Mapgen V5 flags
|
/////////////////// Mapgen V5 flags
|
||||||
#define MGV5_BLOBS 0x01
|
//#define MGV5_ 0x01
|
||||||
|
|
||||||
|
class BiomeManager;
|
||||||
|
|
||||||
extern FlagDesc flagdesc_mapgen_v5[];
|
extern FlagDesc flagdesc_mapgen_v5[];
|
||||||
|
|
||||||
|
@ -36,8 +38,6 @@ struct MapgenV5Params : public MapgenSpecificParams {
|
||||||
NoiseParams np_cave1;
|
NoiseParams np_cave1;
|
||||||
NoiseParams np_cave2;
|
NoiseParams np_cave2;
|
||||||
NoiseParams np_ground;
|
NoiseParams np_ground;
|
||||||
NoiseParams np_crumble;
|
|
||||||
NoiseParams np_wetness;
|
|
||||||
|
|
||||||
MapgenV5Params();
|
MapgenV5Params();
|
||||||
~MapgenV5Params() {}
|
~MapgenV5Params() {}
|
||||||
|
@ -67,8 +67,6 @@ public:
|
||||||
Noise *noise_cave1;
|
Noise *noise_cave1;
|
||||||
Noise *noise_cave2;
|
Noise *noise_cave2;
|
||||||
Noise *noise_ground;
|
Noise *noise_ground;
|
||||||
Noise *noise_crumble;
|
|
||||||
Noise *noise_wetness;
|
|
||||||
Noise *noise_heat;
|
Noise *noise_heat;
|
||||||
Noise *noise_humidity;
|
Noise *noise_humidity;
|
||||||
|
|
||||||
|
@ -95,9 +93,8 @@ public:
|
||||||
int getGroundLevelAtPoint(v2s16 p);
|
int getGroundLevelAtPoint(v2s16 p);
|
||||||
void calculateNoise();
|
void calculateNoise();
|
||||||
int generateBaseTerrain();
|
int generateBaseTerrain();
|
||||||
void generateBiomes();
|
void generateBiomes(float *heat_map, float *humidity_map);
|
||||||
void generateCaves();
|
void generateCaves(int max_stone_y);
|
||||||
void generateBlobs();
|
|
||||||
void dustTopNodes();
|
void dustTopNodes();
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
@ -55,6 +55,10 @@ MapgenV6::MapgenV6(int mapgenid, MapgenParams *params, EmergeManager *emerge)
|
||||||
this->m_emerge = emerge;
|
this->m_emerge = emerge;
|
||||||
this->ystride = csize.X; //////fix this
|
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;
|
MapgenV6Params *sp = (MapgenV6Params *)params->sparams;
|
||||||
this->spflags = sp->spflags;
|
this->spflags = sp->spflags;
|
||||||
this->freq_desert = sp->freq_desert;
|
this->freq_desert = sp->freq_desert;
|
||||||
|
@ -115,6 +119,8 @@ MapgenV6::~MapgenV6()
|
||||||
delete noise_mud;
|
delete noise_mud;
|
||||||
delete noise_beach;
|
delete noise_beach;
|
||||||
delete noise_biome;
|
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
|
// Add dungeons
|
||||||
if ((flags & MG_DUNGEONS) && (stone_surface_max_y >= node_min.Y)) {
|
if ((flags & MG_DUNGEONS) && (stone_surface_max_y >= node_min.Y)) {
|
||||||
DungeonParams dp;
|
DungeonParams dp;
|
||||||
|
|
|
@ -64,6 +64,8 @@ MapgenV7::MapgenV7(int mapgenid, MapgenParams *params, EmergeManager *emerge)
|
||||||
this->heightmap = new s16[csize.X * csize.Z];
|
this->heightmap = new s16[csize.X * csize.Z];
|
||||||
this->ridge_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;
|
MapgenV7Params *sp = (MapgenV7Params *)params->sparams;
|
||||||
this->spflags = sp->spflags;
|
this->spflags = sp->spflags;
|
||||||
|
|
||||||
|
@ -239,14 +241,15 @@ void MapgenV7::makeChunk(BlockMakeData *data)
|
||||||
// Generate base terrain, mountains, and ridges with initial heightmaps
|
// Generate base terrain, mountains, and ridges with initial heightmaps
|
||||||
s16 stone_surface_max_y = generateTerrain();
|
s16 stone_surface_max_y = generateTerrain();
|
||||||
|
|
||||||
|
// Create heightmap
|
||||||
updateHeightmap(node_min, node_max);
|
updateHeightmap(node_min, node_max);
|
||||||
|
|
||||||
// Calculate biomes
|
// Create biomemap at heightmap surface
|
||||||
bmgr->calcBiomes(csize.X, csize.Z, noise_heat->result,
|
bmgr->calcBiomes(csize.X, csize.Z, noise_heat->result,
|
||||||
noise_humidity->result, heightmap, biomemap);
|
noise_humidity->result, heightmap, biomemap);
|
||||||
|
|
||||||
// Actually place the biome-specific nodes and what not
|
// Actually place the biome-specific nodes
|
||||||
generateBiomes();
|
generateBiomes(noise_heat->result, noise_humidity->result);
|
||||||
|
|
||||||
if (flags & MG_CAVES)
|
if (flags & MG_CAVES)
|
||||||
generateCaves(stone_surface_max_y);
|
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)
|
if (node_max.Y < water_level)
|
||||||
return;
|
return;
|
||||||
|
@ -548,12 +551,11 @@ void MapgenV7::generateBiomes()
|
||||||
|
|
||||||
for (s16 z = node_min.Z; z <= node_max.Z; z++)
|
for (s16 z = node_min.Z; z <= node_max.Z; z++)
|
||||||
for (s16 x = node_min.X; x <= node_max.X; x++, index++) {
|
for (s16 x = node_min.X; x <= node_max.X; x++, index++) {
|
||||||
Biome *biome = (Biome *)bmgr->get(biomemap[index]);
|
Biome *biome = NULL;
|
||||||
s16 dfiller = biome->depth_filler + noise_filler_depth->result[index];
|
s16 dfiller = 0;
|
||||||
s16 y0_top = biome->depth_top;
|
s16 y0_top = 0;
|
||||||
s16 y0_filler = biome->depth_top + dfiller;
|
s16 y0_filler = 0;
|
||||||
s16 shore_max = water_level + biome->height_shore;
|
s16 depth_water_top = 0;
|
||||||
s16 depth_water_top = biome->depth_water_top;
|
|
||||||
|
|
||||||
s16 nplaced = 0;
|
s16 nplaced = 0;
|
||||||
u32 i = vm->m_area.index(x, node_max.Y, z);
|
u32 i = vm->m_area.index(x, node_max.Y, z);
|
||||||
|
@ -574,25 +576,23 @@ void MapgenV7::generateBiomes()
|
||||||
have_air = !getMountainTerrainFromMap(j, index, y);
|
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) {
|
if (c == c_stone && have_air) {
|
||||||
content_t c_below = vm->m_data[i - em.X].getContent();
|
content_t c_below = vm->m_data[i - em.X].getContent();
|
||||||
|
|
||||||
if (c_below != CONTENT_AIR) {
|
if (c_below != CONTENT_AIR) {
|
||||||
if (nplaced < y0_top) {
|
if (nplaced < y0_top) {
|
||||||
if(y < water_level)
|
vm->m_data[i] = MapNode(biome->c_top);
|
||||||
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);
|
|
||||||
nplaced++;
|
nplaced++;
|
||||||
} else if (nplaced < y0_filler && nplaced >= y0_top) {
|
} else if (nplaced < y0_filler && nplaced >= y0_top) {
|
||||||
if(y < water_level)
|
vm->m_data[i] = MapNode(biome->c_filler);
|
||||||
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);
|
|
||||||
nplaced++;
|
nplaced++;
|
||||||
} else if (c == c_stone) {
|
} else if (c == c_stone) {
|
||||||
have_air = false;
|
have_air = false;
|
||||||
|
@ -792,7 +792,7 @@ void MapgenV7::generateCaves(int max_stone_y)
|
||||||
PseudoRandom ps(blockseed + 21343);
|
PseudoRandom ps(blockseed + 21343);
|
||||||
u32 bruises_count = (ps.range(1, 5) == 1) ? ps.range(1, 2) : 0;
|
u32 bruises_count = (ps.range(1, 5) == 1) ? ps.range(1, 2) : 0;
|
||||||
for (u32 i = 0; i < bruises_count; i++) {
|
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);
|
cave.makeCave(node_min, node_max, max_stone_y);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -114,7 +114,7 @@ public:
|
||||||
int generateMountainTerrain(int ymax);
|
int generateMountainTerrain(int ymax);
|
||||||
void generateRidgeTerrain();
|
void generateRidgeTerrain();
|
||||||
|
|
||||||
void generateBiomes();
|
void generateBiomes(float *heat_map, float *humidity_map);
|
||||||
void dustTopNodes();
|
void dustTopNodes();
|
||||||
|
|
||||||
//void addTopNodes();
|
//void addTopNodes();
|
||||||
|
|
|
@ -74,6 +74,22 @@ void MapNode::setLight(enum LightBank bank, u8 a_light, INodeDefManager *nodemgr
|
||||||
assert(0);
|
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
|
u8 MapNode::getLight(enum LightBank bank, INodeDefManager *nodemgr) const
|
||||||
{
|
{
|
||||||
// Select the brightest of [light source, propagated light]
|
// 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);
|
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,
|
return MYMAX(f->light_source,
|
||||||
bank == LIGHTBANK_DAY ? param1 & 0x0f : (param1 >> 4) & 0x0f);
|
bank == LIGHTBANK_DAY ? param1 & 0x0f : (param1 >> 4) & 0x0f);
|
||||||
|
|
|
@ -192,6 +192,14 @@ struct MapNode
|
||||||
}
|
}
|
||||||
|
|
||||||
void setLight(enum LightBank bank, u8 a_light, INodeDefManager *nodemgr);
|
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;
|
u8 getLight(enum LightBank bank, INodeDefManager *nodemgr) const;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -209,7 +217,7 @@ struct MapNode
|
||||||
* @pre f != NULL
|
* @pre f != NULL
|
||||||
* @pre f->param_type == CPT_LIGHT
|
* @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;
|
bool getLightBanks(u8 &lightday, u8 &lightnight, INodeDefManager *nodemgr) const;
|
||||||
|
|
||||||
|
|
|
@ -133,7 +133,7 @@ void MapSector::deleteBlock(MapBlock *block)
|
||||||
delete 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();
|
for(std::map<s16, MapBlock*>::iterator bi = m_blocks.begin();
|
||||||
bi != m_blocks.end(); ++bi)
|
bi != m_blocks.end(); ++bi)
|
||||||
|
|
|
@ -22,11 +22,11 @@ with this program; if not, write to the Free Software Foundation, Inc.,
|
||||||
|
|
||||||
#include "irrlichttypes.h"
|
#include "irrlichttypes.h"
|
||||||
#include "irr_v2d.h"
|
#include "irr_v2d.h"
|
||||||
|
#include "mapblock.h"
|
||||||
#include <ostream>
|
#include <ostream>
|
||||||
#include <map>
|
#include <map>
|
||||||
#include <list>
|
#include <vector>
|
||||||
|
|
||||||
class MapBlock;
|
|
||||||
class Map;
|
class Map;
|
||||||
class IGameDef;
|
class IGameDef;
|
||||||
|
|
||||||
|
@ -61,7 +61,7 @@ public:
|
||||||
|
|
||||||
void deleteBlock(MapBlock *block);
|
void deleteBlock(MapBlock *block);
|
||||||
|
|
||||||
void getBlocks(std::list<MapBlock*> &dest);
|
void getBlocks(MapBlockVect &dest);
|
||||||
|
|
||||||
// Always false at the moment, because sector contains no metadata.
|
// Always false at the moment, because sector contains no metadata.
|
||||||
bool differs_from_disk;
|
bool differs_from_disk;
|
||||||
|
|
|
@ -43,7 +43,6 @@ BiomeManager::BiomeManager(IGameDef *gamedef) :
|
||||||
b->flags = 0;
|
b->flags = 0;
|
||||||
b->depth_top = 0;
|
b->depth_top = 0;
|
||||||
b->depth_filler = 0;
|
b->depth_filler = 0;
|
||||||
b->height_shore = 0;
|
|
||||||
b->depth_water_top = 0;
|
b->depth_water_top = 0;
|
||||||
b->y_min = -MAP_GENERATION_LIMIT;
|
b->y_min = -MAP_GENERATION_LIMIT;
|
||||||
b->y_max = MAP_GENERATION_LIMIT;
|
b->y_max = MAP_GENERATION_LIMIT;
|
||||||
|
@ -53,9 +52,6 @@ BiomeManager::BiomeManager(IGameDef *gamedef) :
|
||||||
NodeResolveInfo *nri = new NodeResolveInfo(b);
|
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("air");
|
|
||||||
nri->nodenames.push_back("air");
|
|
||||||
nri->nodenames.push_back("mapgen_stone");
|
nri->nodenames.push_back("mapgen_stone");
|
||||||
nri->nodenames.push_back("mapgen_water_source");
|
nri->nodenames.push_back("mapgen_water_source");
|
||||||
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_with_grass", CONTENT_AIR, c_top);
|
||||||
m_ndef->getIdFromResolveInfo(nri, "mapgen_dirt", CONTENT_AIR, c_filler);
|
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_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_top);
|
||||||
m_ndef->getIdFromResolveInfo(nri, "mapgen_water_source", CONTENT_AIR, c_water);
|
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
Loading…
Reference in New Issue