Revert all commits up to (including) a704c04f

This commit is contained in:
kwolekr 2015-03-07 16:16:25 -05:00
parent ffdf8dedb7
commit 32352e90da
173 changed files with 8751 additions and 11138 deletions

2
.gitignore vendored
View File

@ -59,8 +59,6 @@ src/json/CMakeFiles/
src/json/libjsoncpp.a
src/sqlite/CMakeFiles/*
src/sqlite/libsqlite3.a
src/client/CMakeFiles/
src/network/CMakeFiles/
CMakeCache.txt
CPackConfig.cmake
CPackSourceConfig.cmake

View File

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

View File

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

View File

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

View File

@ -102,6 +102,7 @@ LOCAL_C_INCLUDES := \
LOCAL_SRC_FILES := \
jni/src/ban.cpp \
jni/src/base64.cpp \
jni/src/camera.cpp \
jni/src/cavegen.cpp \
jni/src/chat.cpp \
@ -112,6 +113,7 @@ LOCAL_SRC_FILES := \
jni/src/clientobject.cpp \
jni/src/clouds.cpp \
jni/src/collision.cpp \
jni/src/connection.cpp \
jni/src/content_abm.cpp \
jni/src/content_cao.cpp \
jni/src/content_cso.cpp \
@ -188,6 +190,7 @@ LOCAL_SRC_FILES := \
jni/src/server.cpp \
jni/src/serverlist.cpp \
jni/src/serverobject.cpp \
jni/src/sha1.cpp \
jni/src/shader.cpp \
jni/src/sky.cpp \
jni/src/socket.cpp \
@ -196,34 +199,22 @@ LOCAL_SRC_FILES := \
jni/src/staticobject.cpp \
jni/src/subgame.cpp \
jni/src/test.cpp \
jni/src/tile.cpp \
jni/src/tool.cpp \
jni/src/treegen.cpp \
jni/src/version.cpp \
jni/src/voxel.cpp \
jni/src/voxelalgorithms.cpp \
jni/src/util/base64.cpp \
jni/src/util/directiontables.cpp \
jni/src/util/numeric.cpp \
jni/src/util/pointedthing.cpp \
jni/src/util/serialize.cpp \
jni/src/util/sha1.cpp \
jni/src/util/string.cpp \
jni/src/util/timetaker.cpp \
jni/src/touchscreengui.cpp \
jni/src/database-leveldb.cpp \
jni/src/settings.cpp \
jni/src/wieldmesh.cpp \
jni/src/client/clientlauncher.cpp \
jni/src/client/tile.cpp
# Network
LOCAL_SRC_FILES += \
jni/src/network/connection.cpp \
jni/src/network/networkpacket.cpp \
jni/src/network/clientopcodes.cpp \
jni/src/network/serveropcodes.cpp \
jni/src/network/packethandlers/server.cpp \
jni/src/network/packethandlers/client.cpp
jni/src/wieldmesh.cpp
# lua api
LOCAL_SRC_FILES += \

View File

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

View File

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

View File

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

View File

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

View File

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

View File

@ -16,9 +16,6 @@
--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)
@ -198,12 +195,10 @@ local function handle_buttons(this, fields)
for i,mod in ipairs(rawlist) do
if not mod.is_modpack and
mod.typ ~= "game_mod" then
if modname_valid(mod.name) then
worldfile:set("load_mod_"..mod.name, tostring(mod.enabled))
if mod.enabled then
worldfile:set("load_mod_"..mod.name, "true")
else
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
worldfile:set("load_mod_"..mod.name, "false")
end
mods["load_mod_"..mod.name] = nil
end

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

File diff suppressed because it is too large Load Diff

View File

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

View File

@ -1,185 +1,215 @@
# SOME DESCRIPTIVE TITLE.
# Copyright (C) YEAR THE PACKAGE'S COPYRIGHT HOLDER
# This file is distributed under the same license as the PACKAGE package.
# FIRST AUTHOR <EMAIL@ADDRESS>, YEAR.
#
msgid ""
msgstr ""
"Project-Id-Version: minetest\n"
"Report-Msgid-Bugs-To: \n"
"POT-Creation-Date: 2015-02-14 23:12+0900\n"
"PO-Revision-Date: 2015-02-22 10:57+0900\n"
"POT-Creation-Date: 2013-11-23 17:37+0100\n"
"PO-Revision-Date: 2014-12-28 15:48+0900\n"
"Last-Translator: Rui Takeda <mrrst0914@gmail.com>\n"
"Language-Team: Japanese <minetest_jp@m.add.ac>\n"
"Language: ja\n"
"Language-Team: Japanese\n"
"MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=UTF-8\n"
"Content-Transfer-Encoding: 8bit\n"
"Plural-Forms: nplurals=1; plural=0;\n"
"X-Generator: Poedit 1.6.5\n"
"Language: ja_JP\n"
"X-Poedit-SourceCharset: UTF-8\n"
msgid "Ok"
msgstr "決定"
msgid "Game Name"
msgstr "ゲーム名"
msgid "World:"
msgstr "ワールド:"
msgid "Hide Game"
msgstr "ゲームを隠す"
msgid "Hide mp content"
msgstr "Modパックの簡略化"
msgid "Mod:"
msgstr "Mod名:"
msgid "Depends:"
msgstr "依存Mod:"
msgid "Save"
msgstr "保存"
msgid "Create"
msgstr "作成"
msgid "Cancel"
msgstr "キャンセル"
msgid "Enable MP"
msgstr "有効化"
msgid "Gamemgr: Unable to copy mod \"$1\" to game \"$2\""
msgstr "Gamemgr: \"$1\"のModを \"$2\" にコピーできません"
msgid "Disable MP"
msgstr "無効化"
msgid "Games"
msgstr "ゲーム"
msgid "enabled"
msgstr "有効化"
msgid "Mods:"
msgstr "Mod:"
msgid "Enable all"
msgstr "すべて有効化"
msgid "edit game"
msgstr "ゲーム編集"
msgid "new game"
msgstr "新規ゲーム"
msgid "Remove selected mod"
msgstr "選択したModを削除"
msgid "Ok"
msgstr "決定"
msgid "World name"
msgstr "ワールド名"
msgid "Seed"
msgstr "Seed値"
msgstr "シード値"
msgid "Mapgen"
msgstr "ワールドタイプ"
msgstr "マップ生成"
msgid "Game"
msgstr "ゲーム"
msgid "Create"
msgstr "作成"
msgid "You have no subgames installed."
msgstr "ゲームがインストールされていません。"
msgid "Download one from minetest.net"
msgstr "minetest.netから再ダウンロードしてください。"
msgid "Warning: The minimal development test is meant for developers."
msgstr "警告:Minimal development testは開発者のためのゲームです。"
msgid "Download a subgame, such as minetest_game, from minetest.net"
msgstr "minetest.netからminetest_gameのゲームをダウンロードしてください。"
msgid "A world named \"$1\" already exists"
msgstr "ワールド名\"$1\"はすでに使用されています。"
msgid "No worldname given or no game selected"
msgstr "ワールド名が入力されていないか、ゲームが選択されていません。"
msgid "Are you sure you want to delete \"$1\"?"
msgstr "本当に\"$1\"を削除してよろしいですか?"
msgid "Delete World \"$1\"?"
msgstr "\"$1\"のワールドを削除しますか?"
msgid "Yes"
msgstr "はい"
msgid "No of course not!"
msgstr "いいえ"
msgid "Modmgr: failed to delete \"$1\""
msgstr "Modマネージャー:\"$1\"の削除に失敗しました。"
msgid "Modmgr: invalid modpath \"$1\""
msgstr "Modマネージャー:Mod\"$1\"の場所が不明です。"
msgid "Delete World \"$1\"?"
msgstr "ワールド\"$1\"を削除してよろしいですか?"
msgid "No"
msgstr "いいえ"
msgid "Rename Modpack:"
msgstr "名前を変更"
msgid "A world named \"$1\" already exists"
msgstr "\"$1\"という名前のワールドを作成できません。同名のワールドが存在しています"
msgid "Accept"
msgstr "決定"
msgid "No worldname given or no game selected"
msgstr "ワールド名が入力されていないか、ゲームが選択されていません"
msgid "Install Mod: file: \"$1\""
msgstr "Modインストール:ファイル\"$1\"からModをインストールします。"
msgid "To enable shaders the OpenGL driver needs to be used."
msgstr "シェーダーを有効にするには、OpenGLのドライバが必要です"
msgid ""
"\n"
"Install Mod: unsupported filetype \"$1\" or broken archive"
msgstr ""
"\n"
"Modインストール:ファイル\"$1\"は非対応の形式か、壊れています。"
msgid "Address/Port"
msgstr "アドレス/ポート"
msgid "Failed to install $1 to $2"
msgstr "$2へ$1をインストールできませんでした。"
msgid "Name/Password"
msgstr "名前/パスワード"
msgid "Install Mod: unable to find suitable foldername for modpack $1"
msgstr ""
"Modインストール:Modパック$1に適したフォルダ名を見つけることができませんでし"
"た。"
msgid "Public Serverlist"
msgstr "公開されているサーバーリスト"
msgid "Install Mod: unable to find real modname for: $1"
msgstr "Modインストール:$1の本来のMod名が不明です。"
msgid "Delete"
msgstr "削除"
msgid "Unsorted"
msgstr "未分類"
msgid "Connect"
msgstr "接続"
msgid "Search"
msgstr "検索"
msgid "New"
msgstr "作成"
msgid "Downloading $1, please wait..."
msgstr "$1をダウンロードしています。しばらくお待ちください..."
msgid "Configure"
msgstr "設定"
msgid "Successfully installed:"
msgstr "インストールが完了しました。:"
msgid "Start Game"
msgstr "ゲームスタート"
msgid "Shortname:"
msgstr "省略名"
msgid "Select World:"
msgstr "ワールド選択:"
msgid "Rating"
msgstr "評価"
msgid "Creative Mode"
msgstr "クリエイティブモード"
msgid "re-Install"
msgstr "再インストール"
msgid "Enable Damage"
msgstr "ダメージ有効"
msgid "Install"
msgstr "インストール"
msgid "Public"
msgstr "公開する"
msgid "Close store"
msgstr "閉じる"
msgid "Name"
msgstr "名前"
msgid "Page $1 of $2"
msgstr "ページ $1/$2"
msgid "Password"
msgstr "パスワード"
msgid "Credits"
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 "開発協力者"
msgstr "貢献者"
msgid "Previous Contributors"
msgstr "以前の開発協力者"
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 "オンラインでModを検索"
msgstr "オンラインで検索"
msgid "No mod description available"
msgstr "Modの説明がありません。"
msgstr "Modの説明がありません"
msgid "Mod information:"
msgstr "Modの情報:"
@ -193,376 +223,123 @@ msgstr "選択したModパックを削除"
msgid "Uninstall selected mod"
msgstr "選択したModを削除"
msgid "Select Mod File:"
msgstr "Modファイルを選択"
msgid "Rename Modpack:"
msgstr "Modパックの名前を変更"
msgid "Mods"
msgstr "Mod"
msgid "Accept"
msgstr "了承"
msgid "Address / Port :"
msgstr "アドレスとポート:"
msgid "World:"
msgstr "ワールド:"
msgid "Name / Password :"
msgstr "名前とパスワード:"
msgid "Hide Game"
msgstr "内部Mod"
msgid "Public Serverlist"
msgstr "公開済みのサーバーの一覧"
msgid "Hide mp content"
msgstr "Modパックの簡略化"
msgid "Delete"
msgstr "削除"
msgid "Mod:"
msgstr "Mod名:"
msgid "Connect"
msgstr "接続"
msgid "Depends:"
msgstr "依存Mod:"
msgid "Creative mode"
msgstr "クリエイティブモード"
msgid "Save"
msgstr "保存"
msgid "Damage enabled"
msgstr "HPあり"
msgid "Enable MP"
msgstr "有効化"
msgid "PvP enabled"
msgstr "PvPあり"
msgid "Disable MP"
msgstr "無効化"
msgid "Client"
msgstr "クライアント"
msgid "enabled"
msgstr "有効化"
msgid "New"
msgstr "作成"
msgid "Enable all"
msgstr "全て有効化"
msgid "Configure"
msgstr "設定"
msgid "Modmgr: failed to delete \"$1\""
msgstr "Modmgr: \"$1\"の削除に失敗しました"
msgid "Start Game"
msgstr "ゲームスタート"
msgid "Modmgr: invalid modpath \"$1\""
msgstr "Modmgr: \"$1\"は無効なModパスです"
msgid "Select World:"
msgstr "ワールドを選択:"
msgid "Are you sure you want to delete \"$1\"?"
msgstr "\"$1\"を削除してよろしいですか?"
msgid "Creative Mode"
msgstr "クリエイティブモード"
msgid "No of course not!"
msgstr "違います!"
msgid "Enable Damage"
msgstr "ダメージあり"
msgid "Page $1 of $2"
msgstr "ページ $1/$2"
msgid "Public"
msgstr "サーバーを公開する"
msgid "Rating"
msgstr "評価"
msgid "Name/Password"
msgstr "名前とパスワード"
msgid "re-Install"
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 "Install"
msgstr "インストール"
msgid "Item textures..."
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 "終了中..."
msgstr "アイテムのテクスチャ設定中..."
msgid "Loading..."
msgstr "読み込み中..."
msgstr "ロード中..."
msgid "Creating server..."
msgstr "サーバー作成中..."
msgstr "サーバー構築中..."
msgid "Creating client..."
msgstr "クライアント作成中..."
msgstr "クライアント作成中..."
msgid "Resolving address..."
msgstr "アドレス解決中..."
msgstr "アドレス解決中..."
msgid "Connecting to server..."
msgstr "サーバー接続中..."
msgstr "サーバー接続中..."
msgid "Item definitions..."
msgstr "アイテム定義中..."
msgstr "アイテム定義中..."
msgid "Node definitions..."
msgstr "ノード定義中..."
msgstr "ノード定義中..."
msgid "Media..."
msgstr "..."
msgid " KB/s"
msgstr " KB/秒"
msgid " MB/s"
msgstr " MB/秒"
msgid "Shutting down..."
msgstr "終了中..."
msgid ""
"\n"
"Check debug.txt for details."
msgstr ""
"\n"
"詳細はdebug.txtを覧ください。"
"詳細はdebug.txtを御覧ください。"
msgid "Enter "
msgstr "Enter"
msgid "You died."
msgstr "You died!"
msgid "ok"
msgid "Respawn"
msgstr "Respawn"
msgid "Proceed"
msgstr "決定"
msgid "Keybindings. (If this menu screws up, remove stuff from minetest.conf)"
msgstr "操作の設定を変更します。"
msgstr "キーバインド"
msgid "\"Use\" = climb down"
msgstr "「使用」で降りる"
msgstr "「使う」キーで降りる"
msgid "Double tap \"jump\" to toggle fly"
msgstr "「ジャンプ」二回押しで飛行モード"
msgstr "ジャンプの二回押しで飛行"
msgid "Key already in use"
msgstr "すでに使われているキーです。"
msgstr "既に使われているキーです"
msgid "press key"
msgstr "キー入力待ち"
@ -574,19 +351,19 @@ msgid "Backward"
msgstr "後退"
msgid "Left"
msgstr "左進む"
msgstr "左進む"
msgid "Right"
msgstr "右進む"
msgstr "右進む"
msgid "Use"
msgstr "使"
msgstr "使"
msgid "Jump"
msgstr "ジャンプ"
msgid "Sneak"
msgstr "スニーク"
msgstr "こっそり進む"
msgid "Drop"
msgstr "落とす"
@ -604,16 +381,16 @@ msgid "Console"
msgstr "コンソール"
msgid "Toggle fly"
msgstr "飛行モード"
msgstr "飛行"
msgid "Toggle fast"
msgstr "高速移動モード"
msgstr "高速移動"
msgid "Toggle noclip"
msgstr "すり抜けモード"
msgstr "すり抜け"
msgid "Range select"
msgstr "視野範囲変更"
msgstr "視野切り替え"
msgid "Print stacks"
msgstr "スタックの表示"
@ -631,13 +408,53 @@ msgid "Change"
msgstr "変更"
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: "
msgstr "音量:"
msgstr "音量"
msgid "Exit"
msgstr "閉じる"
msgstr "る"
msgid "Left Button"
msgstr "左ボタン"
@ -854,3 +671,56 @@ msgstr "PA1"
msgid "Zoom"
msgstr "ズーム"
msgid "needs_fallback_font"
msgstr "yes"
msgid "Main Menu"
msgstr "メインメニュー"
msgid "No world selected and no address provided. Nothing to do."
msgstr ""
"ワールドが選択できていないか、アドレスが入力されていません。そのため実行されませ"
"ん。"
msgid "Could not find or load game \""
msgstr "読み込みか検索に失敗: \""
msgid "Invalid gamespec."
msgstr "無効なgamespecです"
msgid "Connection error (timed out?)"
msgstr "接続エラー(タイムアウト)"
msgid "Bumpmapping"
msgstr "バンプマッピング"
msgid "Generate Normalmaps"
msgstr "法線マッピング"
msgid "Parallax Occlusion"
msgstr "視差オクルージョンマッピング"
msgid "Waving Water"
msgstr "揺れる水"
msgid "Waving Leaves"
msgstr "揺れる葉"
msgid "Waving Plants"
msgstr "揺れる草花"
msgid "GUI scale factor"
msgstr "メニューの大きさ"
msgid "Unsorted"
msgstr "未分類"
msgid "Search"
msgstr "検索"
msgid "Close store"
msgstr "閉じる"
msgid "Change Keys"
msgstr "操作変更"

File diff suppressed because it is too large Load Diff

View File

@ -352,19 +352,16 @@ add_custom_target(GenerateVersion
WORKING_DIRECTORY "${CMAKE_CURRENT_SOURCE_DIR}")
add_subdirectory(jthread)
add_subdirectory(network)
add_subdirectory(script)
add_subdirectory(util)
set (unittests_SRCS
test.cpp
)
set(common_SRCS
ban.cpp
base64.cpp
cavegen.cpp
clientiface.cpp
collision.cpp
connection.cpp
content_abm.cpp
content_mapnode.cpp
content_nodemeta.cpp
@ -421,20 +418,20 @@ set(common_SRCS
serverlist.cpp
serverobject.cpp
settings.cpp
sha1.cpp
socket.cpp
sound.cpp
staticobject.cpp
subgame.cpp
test.cpp
tool.cpp
treegen.cpp
version.cpp
voxel.cpp
voxelalgorithms.cpp
${common_network_SRCS}
${JTHREAD_SRCS}
${common_SCRIPT_SRCS}
${UTIL_SRCS}
${unittests_SRCS}
)
# This gives us the icon and file version information
@ -457,16 +454,9 @@ if(WIN32)
endif()
# Client sources
if (BUILD_CLIENT)
add_subdirectory(client)
endif(BUILD_CLIENT)
set(minetest_SRCS
${common_SRCS}
${sound_SRCS}
${client_SRCS}
${client_network_SRCS}
camera.cpp
chat.cpp
client.cpp
@ -499,6 +489,7 @@ set(minetest_SRCS
particles.cpp
shader.cpp
sky.cpp
tile.cpp
wieldmesh.cpp
${minetest_SCRIPT_SRCS}
)

View File

@ -23,22 +23,7 @@ with this program; if not, write to the Free Software Foundation, Inc.,
#include "irr_aabb3d.h"
#include <string>
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,
};
#define ACTIVEOBJECT_TYPE_INVALID 0
// Other types are defined in content_object.h
struct ActiveObjectMessage
@ -75,7 +60,7 @@ public:
m_id = id;
}
virtual ActiveObjectType getType() const = 0;
virtual u8 getType() const = 0;
virtual bool getCollisionBox(aabb3f *toset) = 0;
virtual bool collideWithObjects() = 0;
protected:

View File

@ -23,7 +23,7 @@ with this program; if not, write to the Free Software Foundation, Inc.,
#include "irrlichttypes_extrabloated.h"
#include "inventory.h"
#include "mesh.h"
#include "client/tile.h"
#include "tile.h"
#include "util/numeric.h"
#include <ICameraSceneNode.h>

View File

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

View File

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

View File

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

View File

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

File diff suppressed because it is too large Load Diff

View File

@ -20,7 +20,7 @@ with this program; if not, write to the Free Software Foundation, Inc.,
#ifndef CLIENT_HEADER
#define CLIENT_HEADER
#include "network/connection.h"
#include "connection.h"
#include "environment.h"
#include "irrlichttypes_extrabloated.h"
#include "jthread/jmutex.h"
@ -34,7 +34,6 @@ with this program; if not, write to the Free Software Foundation, Inc.,
#include "localplayer.h"
#include "hud.h"
#include "particles.h"
#include "network/networkpacket.h"
struct MeshMakeData;
class MapBlockMesh;
@ -48,6 +47,7 @@ struct MapDrawControl;
class MtEventManager;
struct PointedThing;
class Database;
class Server;
struct QueuedMeshUpdate
{
@ -341,61 +341,11 @@ public:
*/
void step(float dtime);
/*
* Command Handlers
*/
void handleCommand(NetworkPacket* pkt);
void handleCommand_Null(NetworkPacket* pkt) {};
void handleCommand_Deprecated(NetworkPacket* pkt);
void handleCommand_Init(NetworkPacket* pkt);
void handleCommand_AccessDenied(NetworkPacket* pkt);
void handleCommand_RemoveNode(NetworkPacket* pkt);
void handleCommand_AddNode(NetworkPacket* pkt);
void handleCommand_BlockData(NetworkPacket* pkt);
void handleCommand_Inventory(NetworkPacket* pkt);
void handleCommand_TimeOfDay(NetworkPacket* pkt);
void handleCommand_ChatMessage(NetworkPacket* pkt);
void handleCommand_ActiveObjectRemoveAdd(NetworkPacket* pkt);
void handleCommand_ActiveObjectMessages(NetworkPacket* pkt);
void handleCommand_Movement(NetworkPacket* pkt);
void handleCommand_HP(NetworkPacket* pkt);
void handleCommand_Breath(NetworkPacket* pkt);
void handleCommand_MovePlayer(NetworkPacket* pkt);
void handleCommand_PlayerItem(NetworkPacket* pkt);
void handleCommand_DeathScreen(NetworkPacket* pkt);
void handleCommand_AnnounceMedia(NetworkPacket* pkt);
void handleCommand_Media(NetworkPacket* pkt);
void handleCommand_ToolDef(NetworkPacket* pkt);
void handleCommand_NodeDef(NetworkPacket* pkt);
void handleCommand_CraftItemDef(NetworkPacket* pkt);
void handleCommand_ItemDef(NetworkPacket* pkt);
void handleCommand_PlaySound(NetworkPacket* pkt);
void handleCommand_StopSound(NetworkPacket* pkt);
void handleCommand_Privileges(NetworkPacket* pkt);
void handleCommand_InventoryFormSpec(NetworkPacket* pkt);
void handleCommand_DetachedInventory(NetworkPacket* pkt);
void handleCommand_ShowFormSpec(NetworkPacket* pkt);
void handleCommand_SpawnParticle(NetworkPacket* pkt);
void handleCommand_AddParticleSpawner(NetworkPacket* pkt);
void handleCommand_DeleteParticleSpawner(NetworkPacket* pkt);
void handleCommand_HudAdd(NetworkPacket* pkt);
void handleCommand_HudRemove(NetworkPacket* pkt);
void handleCommand_HudChange(NetworkPacket* pkt);
void handleCommand_HudSetFlags(NetworkPacket* pkt);
void handleCommand_HudSetParam(NetworkPacket* pkt);
void handleCommand_HudSetSky(NetworkPacket* pkt);
void handleCommand_OverrideDayNightRatio(NetworkPacket* pkt);
void handleCommand_LocalPlayerAnimations(NetworkPacket* pkt);
void handleCommand_EyeOffset(NetworkPacket* pkt);
void ProcessData(u8 *data, u32 datasize, u16 sender_peer_id);
// Returns true if something was received
bool AsyncProcessPacket();
bool AsyncProcessData();
void Send(NetworkPacket* pkt);
void Send(u16 channelnum, SharedBuffer<u8> data, bool reliable);
void interact(u8 action, const PointedThing& pointed);
@ -515,7 +465,7 @@ public:
// Insert a media file appropriately into the appropriate manager
bool loadMedia(const std::string &data, const std::string &filename);
// Send a request for conventional media transfer
void request_media(const std::vector<std::string> &file_requests);
void request_media(const std::list<std::string> &file_requests);
// Send a notification that no conventional media transfer is needed
void received_media();
@ -577,13 +527,13 @@ private:
// 0 <= m_daynight_i < DAYNIGHT_CACHE_COUNT
//s32 m_daynight_i;
//u32 m_daynight_ratio;
std::queue<std::wstring> m_chat_queue;
Queue<std::wstring> m_chat_queue;
// The seed returned by the server in TOCLIENT_INIT is stored here
u64 m_map_seed;
std::string m_password;
bool m_access_denied;
std::wstring m_access_denied_reason;
std::queue<ClientEvent> m_client_event_queue;
Queue<ClientEvent> m_client_event_queue;
bool m_itemdef_received;
bool m_nodedef_received;
ClientMediaDownloader *m_media_downloader;
@ -619,13 +569,12 @@ private:
LocalClientState m_state;
// Used for saving server map to disk client-side
Database *m_localdb;
IntervalLimiter m_localdb_save_interval;
u16 m_cache_save_interval;
Database *localdb;
Server *localserver;
// TODO: Add callback to update these when g_settings changes
// TODO: Add callback to update this when g_settings changes
bool m_cache_smooth_lighting;
bool m_cache_enable_shaders;
};
#endif // !CLIENT_HEADER

View File

@ -1,5 +0,0 @@
set(client_SRCS
${CMAKE_CURRENT_SOURCE_DIR}/clientlauncher.cpp
${CMAKE_CURRENT_SOURCE_DIR}/tile.cpp
PARENT_SCOPE
)

View File

@ -1,709 +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.
*/
#include "main.h"
#include "mainmenumanager.h"
#include "debug.h"
#include "clouds.h"
#include "server.h"
#include "filesys.h"
#include "guiMainMenu.h"
#include "game.h"
#include "chat.h"
#include "gettext.h"
#include "profiler.h"
#include "log.h"
#include "serverlist.h"
#include "guiEngine.h"
#include "player.h"
#include "fontengine.h"
#include "clientlauncher.h"
// A pointer to a global instance of the time getter
// TODO: why?
TimeGetter *g_timegetter = NULL;
u32 getTimeMs()
{
if (g_timegetter == NULL)
return 0;
return g_timegetter->getTime(PRECISION_MILLI);
}
u32 getTime(TimePrecision prec) {
if (g_timegetter == NULL)
return 0;
return g_timegetter->getTime(prec);
}
ClientLauncher::~ClientLauncher()
{
if (receiver)
delete receiver;
if (input)
delete input;
if (g_fontengine)
delete g_fontengine;
if (device)
device->drop();
}
bool ClientLauncher::run(GameParams &game_params, const Settings &cmd_args)
{
init_args(game_params, cmd_args);
// List video modes if requested
if (list_video_modes)
return print_video_modes();
if (!init_engine(game_params.log_level)) {
errorstream << "Could not initialize game engine." << std::endl;
return false;
}
// Speed tests (done after irrlicht is loaded to get timer)
if (cmd_args.getFlag("speedtests")) {
dstream << "Running speed tests" << std::endl;
speed_tests();
return true;
}
video::IVideoDriver *video_driver = device->getVideoDriver();
if (video_driver == NULL) {
errorstream << "Could not initialize video driver." << std::endl;
return false;
}
porting::setXorgClassHint(video_driver->getExposedVideoData(), "Minetest");
/*
This changes the minimum allowed number of vertices in a VBO.
Default is 500.
*/
//driver->setMinHardwareBufferVertexCount(50);
// Create time getter
g_timegetter = new IrrlichtTimeGetter(device);
// Create game callback for menus
g_gamecallback = new MainGameCallback(device);
device->setResizable(true);
if (random_input)
input = new RandomInputHandler();
else
input = new RealInputHandler(device, receiver);
smgr = device->getSceneManager();
smgr->getParameters()->setAttribute(scene::ALLOW_ZWRITE_ON_TRANSPARENT, true);
guienv = device->getGUIEnvironment();
skin = guienv->getSkin();
skin->setColor(gui::EGDC_BUTTON_TEXT, video::SColor(255, 255, 255, 255));
skin->setColor(gui::EGDC_3D_LIGHT, video::SColor(0, 0, 0, 0));
skin->setColor(gui::EGDC_3D_HIGH_LIGHT, video::SColor(255, 30, 30, 30));
skin->setColor(gui::EGDC_3D_SHADOW, video::SColor(255, 0, 0, 0));
skin->setColor(gui::EGDC_HIGH_LIGHT, video::SColor(255, 70, 120, 50));
skin->setColor(gui::EGDC_HIGH_LIGHT_TEXT, video::SColor(255, 255, 255, 255));
g_fontengine = new FontEngine(g_settings, guienv);
assert(g_fontengine != NULL);
#if (IRRLICHT_VERSION_MAJOR >= 1 && IRRLICHT_VERSION_MINOR >= 8) || IRRLICHT_VERSION_MAJOR >= 2
// Irrlicht 1.8 input colours
skin->setColor(gui::EGDC_EDITABLE, video::SColor(255, 128, 128, 128));
skin->setColor(gui::EGDC_FOCUSED_EDITABLE, video::SColor(255, 96, 134, 49));
#endif
// Create the menu clouds
if (!g_menucloudsmgr)
g_menucloudsmgr = smgr->createNewSceneManager();
if (!g_menuclouds)
g_menuclouds = new Clouds(g_menucloudsmgr->getRootSceneNode(),
g_menucloudsmgr, -1, rand(), 100);
g_menuclouds->update(v2f(0, 0), video::SColor(255, 200, 200, 255));
scene::ICameraSceneNode* camera;
camera = g_menucloudsmgr->addCameraSceneNode(0,
v3f(0, 0, 0), v3f(0, 60, 100));
camera->setFarValue(10000);
/*
GUI stuff
*/
ChatBackend chat_backend;
// If an error occurs, this is set to something by menu().
// It is then displayed before the menu shows on the next call to menu()
std::wstring error_message = L"";
bool first_loop = true;
/*
Menu-game loop
*/
bool retval = true;
bool *kill = porting::signal_handler_killstatus();
while (device->run() && !*kill && !g_gamecallback->shutdown_requested)
{
// Set the window caption
const wchar_t *text = wgettext("Main Menu");
device->setWindowCaption((std::wstring(L"Minetest [") + text + L"]").c_str());
delete[] text;
try { // This is used for catching disconnects
guienv->clear();
/*
We need some kind of a root node to be able to add
custom gui elements directly on the screen.
Otherwise they won't be automatically drawn.
*/
guiroot = guienv->addStaticText(L"", core::rect<s32>(0, 0, 10000, 10000));
bool game_has_run = launch_game(&error_message, game_params, cmd_args);
// If skip_main_menu, we only want to startup once
if (skip_main_menu && !first_loop)
break;
first_loop = false;
if (!game_has_run) {
if (skip_main_menu)
break;
else
continue;
}
// Break out of menu-game loop to shut down cleanly
if (!device->run() || *kill) {
if (g_settings_path != "")
g_settings->updateConfigFile(g_settings_path.c_str());
break;
}
if (current_playername.length() > PLAYERNAME_SIZE-1) {
error_message = wgettext("Player name too long.");
playername = current_playername.substr(0, PLAYERNAME_SIZE-1);
g_settings->set("name", playername);
continue;
}
device->getVideoDriver()->setTextureCreationFlag(
video::ETCF_CREATE_MIP_MAPS, g_settings->getBool("mip_map"));
#ifdef HAVE_TOUCHSCREENGUI
receiver->m_touchscreengui = new TouchScreenGUI(device, receiver);
g_touchscreengui = receiver->m_touchscreengui;
#endif
the_game(
kill,
random_input,
input,
device,
worldspec.path,
current_playername,
current_password,
current_address,
current_port,
error_message,
chat_backend,
gamespec,
simple_singleplayer_mode
);
smgr->clear();
#ifdef HAVE_TOUCHSCREENGUI
delete g_touchscreengui;
g_touchscreengui = NULL;
receiver->m_touchscreengui = NULL;
#endif
} //try
catch (con::PeerNotFoundException &e) {
error_message = wgettext("Connection error (timed out?)");
errorstream << wide_to_narrow(error_message) << std::endl;
}
#ifdef NDEBUG
catch (std::exception &e) {
std::string narrow_message = "Some exception: \"";
narrow_message += e.what();
narrow_message += "\"";
errorstream << narrow_message << std::endl;
error_message = narrow_to_wide(narrow_message);
}
#endif
// If no main menu, show error and exit
if (skip_main_menu) {
if (error_message != L"") {
verbosestream << "error_message = "
<< wide_to_narrow(error_message) << std::endl;
retval = false;
}
break;
}
} // Menu-game loop
g_menuclouds->drop();
g_menucloudsmgr->drop();
return retval;
}
void ClientLauncher::init_args(GameParams &game_params, const Settings &cmd_args)
{
skip_main_menu = cmd_args.getFlag("go");
// FIXME: This is confusing (but correct)
/* If world_path is set then override it unless skipping the main menu using
* the --go command line param. Else, give preference to the address
* supplied on the command line
*/
address = g_settings->get("address");
if (game_params.world_path != "" && !skip_main_menu)
address = "";
else if (cmd_args.exists("address"))
address = cmd_args.get("address");
playername = g_settings->get("name");
if (cmd_args.exists("name"))
playername = cmd_args.get("name");
list_video_modes = cmd_args.getFlag("videomodes");
use_freetype = g_settings->getBool("freetype");
random_input = g_settings->getBool("random_input")
|| cmd_args.getFlag("random-input");
}
bool ClientLauncher::init_engine(int log_level)
{
receiver = new MyEventReceiver();
create_engine_device(log_level);
return device != NULL;
}
bool ClientLauncher::launch_game(std::wstring *error_message,
GameParams &game_params, const Settings &cmd_args)
{
// Initialize menu data
MainMenuData menudata;
menudata.address = address;
menudata.name = playername;
menudata.port = itos(game_params.socket_port);
menudata.errormessage = wide_to_narrow(*error_message);
*error_message = L"";
if (cmd_args.exists("password"))
menudata.password = cmd_args.get("password");
menudata.enable_public = g_settings->getBool("server_announce");
// If a world was commanded, append and select it
if (game_params.world_path != "") {
worldspec.gameid = getWorldGameId(game_params.world_path, true);
worldspec.name = _("[--world parameter]");
if (worldspec.gameid == "") { // Create new
worldspec.gameid = g_settings->get("default_game");
worldspec.name += " [new]";
}
worldspec.path = game_params.world_path;
}
/* Show the GUI menu
*/
if (!skip_main_menu) {
main_menu(&menudata);
// Skip further loading if there was an exit signal.
if (*porting::signal_handler_killstatus())
return false;
address = menudata.address;
int newport = stoi(menudata.port);
if (newport != 0)
game_params.socket_port = newport;
simple_singleplayer_mode = menudata.simple_singleplayer_mode;
std::vector<WorldSpec> worldspecs = getAvailableWorlds();
if (menudata.selected_world >= 0
&& menudata.selected_world < (int)worldspecs.size()) {
g_settings->set("selected_world_path",
worldspecs[menudata.selected_world].path);
worldspec = worldspecs[menudata.selected_world];
}
}
if (menudata.errormessage != "") {
/* The calling function will pass this back into this function upon the
* next iteration (if any) causing it to be displayed by the GUI
*/
*error_message = narrow_to_wide(menudata.errormessage);
return false;
}
if (menudata.name == "")
menudata.name = std::string("Guest") + itos(myrand_range(1000, 9999));
else
playername = menudata.name;
password = translatePassword(playername, narrow_to_wide(menudata.password));
g_settings->set("name", playername);
current_playername = playername;
current_password = password;
current_address = address;
current_port = game_params.socket_port;
// If using simple singleplayer mode, override
if (simple_singleplayer_mode) {
assert(skip_main_menu == false);
current_playername = "singleplayer";
current_password = "";
current_address = "";
current_port = myrand_range(49152, 65535);
} else if (address != "") {
ServerListSpec server;
server["name"] = menudata.servername;
server["address"] = menudata.address;
server["port"] = menudata.port;
server["description"] = menudata.serverdescription;
ServerList::insert(server);
}
infostream << "Selected world: " << worldspec.name
<< " [" << worldspec.path << "]" << std::endl;
if (current_address == "") { // If local game
if (worldspec.path == "") {
*error_message = wgettext("No world selected and no address "
"provided. Nothing to do.");
errorstream << wide_to_narrow(*error_message) << std::endl;
return false;
}
if (!fs::PathExists(worldspec.path)) {
*error_message = wgettext("Provided world path doesn't exist: ")
+ narrow_to_wide(worldspec.path);
errorstream << wide_to_narrow(*error_message) << std::endl;
return false;
}
// Load gamespec for required game
gamespec = findWorldSubgame(worldspec.path);
if (!gamespec.isValid() && !game_params.game_spec.isValid()) {
*error_message = wgettext("Could not find or load game \"")
+ narrow_to_wide(worldspec.gameid) + L"\"";
errorstream << wide_to_narrow(*error_message) << std::endl;
return false;
}
if (porting::signal_handler_killstatus())
return true;
if (game_params.game_spec.isValid() &&
game_params.game_spec.id != worldspec.gameid) {
errorstream << "WARNING: Overriding gamespec from \""
<< worldspec.gameid << "\" to \""
<< game_params.game_spec.id << "\"" << std::endl;
gamespec = game_params.game_spec;
}
if (!gamespec.isValid()) {
*error_message = wgettext("Invalid gamespec.");
*error_message += L" (world_gameid="
+ narrow_to_wide(worldspec.gameid) + L")";
errorstream << wide_to_narrow(*error_message) << std::endl;
return false;
}
}
return true;
}
void ClientLauncher::main_menu(MainMenuData *menudata)
{
bool *kill = porting::signal_handler_killstatus();
video::IVideoDriver *driver = device->getVideoDriver();
infostream << "Waiting for other menus" << std::endl;
while (device->run() && *kill == false) {
if (noMenuActive())
break;
driver->beginScene(true, true, video::SColor(255, 128, 128, 128));
guienv->drawAll();
driver->endScene();
// On some computers framerate doesn't seem to be automatically limited
sleep_ms(25);
}
infostream << "Waited for other menus" << std::endl;
// Cursor can be non-visible when coming from the game
#ifndef ANDROID
device->getCursorControl()->setVisible(true);
#endif
/* show main menu */
GUIEngine mymenu(device, guiroot, &g_menumgr, smgr, menudata, *kill);
smgr->clear(); /* leave scene manager in a clean state */
}
bool ClientLauncher::create_engine_device(int log_level)
{
static const irr::ELOG_LEVEL irr_log_level[5] = {
ELL_NONE,
ELL_ERROR,
ELL_WARNING,
ELL_INFORMATION,
#if (IRRLICHT_VERSION_MAJOR == 1 && IRRLICHT_VERSION_MINOR < 8)
ELL_INFORMATION
#else
ELL_DEBUG
#endif
};
// Resolution selection
bool fullscreen = g_settings->getBool("fullscreen");
u16 screenW = g_settings->getU16("screenW");
u16 screenH = g_settings->getU16("screenH");
// bpp, fsaa, vsync
bool vsync = g_settings->getBool("vsync");
u16 bits = g_settings->getU16("fullscreen_bpp");
u16 fsaa = g_settings->getU16("fsaa");
// Determine driver
video::E_DRIVER_TYPE driverType = video::EDT_OPENGL;
std::string driverstring = g_settings->get("video_driver");
std::vector<video::E_DRIVER_TYPE> drivers
= porting::getSupportedVideoDrivers();
u32 i;
for (i = 0; i != drivers.size(); i++) {
if (!strcasecmp(driverstring.c_str(),
porting::getVideoDriverName(drivers[i]))) {
driverType = drivers[i];
break;
}
}
if (i == drivers.size()) {
errorstream << "Invalid video_driver specified; "
"defaulting to opengl" << std::endl;
}
SIrrlichtCreationParameters params = SIrrlichtCreationParameters();
params.DriverType = driverType;
params.WindowSize = core::dimension2d<u32>(screenW, screenH);
params.Bits = bits;
params.AntiAlias = fsaa;
params.Fullscreen = fullscreen;
params.Stencilbuffer = false;
params.Vsync = vsync;
params.EventReceiver = receiver;
params.HighPrecisionFPU = g_settings->getBool("high_precision_fpu");
#ifdef __ANDROID__
params.PrivateData = porting::app_global;
params.OGLES2ShaderPath = std::string(porting::path_user + DIR_DELIM +
"media" + DIR_DELIM + "Shaders" + DIR_DELIM).c_str();
#endif
device = createDeviceEx(params);
if (device) {
// Map our log level to irrlicht engine one.
ILogger* irr_logger = device->getLogger();
irr_logger->setLogLevel(irr_log_level[log_level]);
porting::initIrrlicht(device);
}
return device != NULL;
}
void ClientLauncher::speed_tests()
{
// volatile to avoid some potential compiler optimisations
volatile static s16 temp16;
volatile static f32 tempf;
static v3f tempv3f1;
static v3f tempv3f2;
static std::string tempstring;
static std::string tempstring2;
tempv3f1 = v3f();
tempv3f2 = v3f();
tempstring = std::string();
tempstring2 = std::string();
{
infostream << "The following test should take around 20ms." << std::endl;
TimeTaker timer("Testing std::string speed");
const u32 jj = 10000;
for (u32 j = 0; j < jj; j++) {
tempstring = "";
tempstring2 = "";
const u32 ii = 10;
for (u32 i = 0; i < ii; i++) {
tempstring2 += "asd";
}
for (u32 i = 0; i < ii+1; i++) {
tempstring += "asd";
if (tempstring == tempstring2)
break;
}
}
}
infostream << "All of the following tests should take around 100ms each."
<< std::endl;
{
TimeTaker timer("Testing floating-point conversion speed");
tempf = 0.001;
for (u32 i = 0; i < 4000000; i++) {
temp16 += tempf;
tempf += 0.001;
}
}
{
TimeTaker timer("Testing floating-point vector speed");
tempv3f1 = v3f(1, 2, 3);
tempv3f2 = v3f(4, 5, 6);
for (u32 i = 0; i < 10000000; i++) {
tempf += tempv3f1.dotProduct(tempv3f2);
tempv3f2 += v3f(7, 8, 9);
}
}
{
TimeTaker timer("Testing std::map speed");
std::map<v2s16, f32> map1;
tempf = -324;
const s16 ii = 300;
for (s16 y = 0; y < ii; y++) {
for (s16 x = 0; x < ii; x++) {
map1[v2s16(x, y)] = tempf;
tempf += 1;
}
}
for (s16 y = ii - 1; y >= 0; y--) {
for (s16 x = 0; x < ii; x++) {
tempf = map1[v2s16(x, y)];
}
}
}
{
infostream << "Around 5000/ms should do well here." << std::endl;
TimeTaker timer("Testing mutex speed");
JMutex m;
u32 n = 0;
u32 i = 0;
do {
n += 10000;
for (; i < n; i++) {
m.Lock();
m.Unlock();
}
}
// Do at least 10ms
while(timer.getTimerTime() < 10);
u32 dtime = timer.stop();
u32 per_ms = n / dtime;
infostream << "Done. " << dtime << "ms, " << per_ms << "/ms" << std::endl;
}
}
bool ClientLauncher::print_video_modes()
{
IrrlichtDevice *nulldevice;
bool vsync = g_settings->getBool("vsync");
u16 fsaa = g_settings->getU16("fsaa");
MyEventReceiver* receiver = new MyEventReceiver();
SIrrlichtCreationParameters params = SIrrlichtCreationParameters();
params.DriverType = video::EDT_NULL;
params.WindowSize = core::dimension2d<u32>(640, 480);
params.Bits = 24;
params.AntiAlias = fsaa;
params.Fullscreen = false;
params.Stencilbuffer = false;
params.Vsync = vsync;
params.EventReceiver = receiver;
params.HighPrecisionFPU = g_settings->getBool("high_precision_fpu");
nulldevice = createDeviceEx(params);
if (nulldevice == NULL) {
delete receiver;
return false;
}
dstream << _("Available video modes (WxHxD):") << std::endl;
video::IVideoModeList *videomode_list = nulldevice->getVideoModeList();
if (videomode_list != NULL) {
s32 videomode_count = videomode_list->getVideoModeCount();
core::dimension2d<u32> videomode_res;
s32 videomode_depth;
for (s32 i = 0; i < videomode_count; ++i) {
videomode_res = videomode_list->getVideoModeResolution(i);
videomode_depth = videomode_list->getVideoModeDepth(i);
dstream << videomode_res.Width << "x" << videomode_res.Height
<< "x" << videomode_depth << std::endl;
}
dstream << _("Active video mode (WxHxD):") << std::endl;
videomode_res = videomode_list->getDesktopResolution();
videomode_depth = videomode_list->getDesktopDepth();
dstream << videomode_res.Width << "x" << videomode_res.Height
<< "x" << videomode_depth << std::endl;
}
nulldevice->drop();
delete receiver;
return videomode_list != NULL;
}

View File

@ -1,129 +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 __CLIENT_LAUNCHER_H__
#define __CLIENT_LAUNCHER_H__
#include "irrlichttypes_extrabloated.h"
#include "client/inputhandler.h"
#include "gameparams.h"
// A small helper class
class TimeGetter
{
public:
virtual u32 getTime(TimePrecision prec) = 0;
};
// A precise irrlicht one
class IrrlichtTimeGetter: public TimeGetter
{
public:
IrrlichtTimeGetter(IrrlichtDevice *device):
m_device(device)
{}
u32 getTime(TimePrecision prec)
{
if (prec == PRECISION_MILLI) {
if (m_device == NULL)
return 0;
return m_device->getTimer()->getRealTime();
} else {
return porting::getTime(prec);
}
}
private:
IrrlichtDevice *m_device;
};
// Not so precise one which works without irrlicht
class SimpleTimeGetter: public TimeGetter
{
public:
u32 getTime(TimePrecision prec)
{
return porting::getTime(prec);
}
};
class ClientLauncher
{
public:
ClientLauncher() :
list_video_modes(false),
skip_main_menu(false),
use_freetype(false),
random_input(false),
address(""),
playername(""),
password(""),
device(NULL),
input(NULL),
receiver(NULL),
skin(NULL),
font(NULL),
simple_singleplayer_mode(false),
current_playername("inv£lid"),
current_password(""),
current_address("does-not-exist"),
current_port(0)
{}
~ClientLauncher();
bool run(GameParams &game_params, const Settings &cmd_args);
protected:
void init_args(GameParams &game_params, const Settings &cmd_args);
bool init_engine(int log_level);
bool launch_game(std::wstring *error_message, GameParams &game_params,
const Settings &cmd_args);
void main_menu(MainMenuData *menudata);
bool create_engine_device(int log_level);
void speed_tests();
bool print_video_modes();
bool list_video_modes;
bool skip_main_menu;
bool use_freetype;
bool random_input;
std::string address;
std::string playername;
std::string password;
IrrlichtDevice *device;
InputHandler *input;
MyEventReceiver *receiver;
gui::IGUISkin *skin;
gui::IGUIFont *font;
scene::ISceneManager *smgr;
SubgameSpec gamespec;
WorldSpec worldspec;
bool simple_singleplayer_mode;
// These are set up based on the menu and other things
// TODO: Are these required since there's already playername, password, etc
std::string current_playername;
std::string current_password;
std::string current_address;
int current_port;
};
#endif

View File

@ -1,428 +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 __INPUT_HANDLER_H__
#define __INPUT_HANDLER_H__
#include "irrlichttypes_extrabloated.h"
class MyEventReceiver : public IEventReceiver
{
public:
// This is the one method that we have to implement
virtual bool OnEvent(const SEvent& event)
{
/*
React to nothing here if a menu is active
*/
if (noMenuActive() == false) {
#ifdef HAVE_TOUCHSCREENGUI
if (m_touchscreengui != 0) {
m_touchscreengui->Toggle(false);
}
#endif
return g_menumgr.preprocessEvent(event);
}
// Remember whether each key is down or up
if (event.EventType == irr::EET_KEY_INPUT_EVENT) {
if (event.KeyInput.PressedDown) {
keyIsDown.set(event.KeyInput);
keyWasDown.set(event.KeyInput);
} else {
keyIsDown.unset(event.KeyInput);
}
}
#ifdef HAVE_TOUCHSCREENGUI
// case of touchscreengui we have to handle different events
if ((m_touchscreengui != 0) &&
(event.EventType == irr::EET_TOUCH_INPUT_EVENT)) {
m_touchscreengui->translateEvent(event);
return true;
}
#endif
// handle mouse events
if (event.EventType == irr::EET_MOUSE_INPUT_EVENT) {
if (noMenuActive() == false) {
left_active = false;
middle_active = false;
right_active = false;
} else {
left_active = event.MouseInput.isLeftPressed();
middle_active = event.MouseInput.isMiddlePressed();
right_active = event.MouseInput.isRightPressed();
if (event.MouseInput.Event == EMIE_LMOUSE_PRESSED_DOWN) {
leftclicked = true;
}
if (event.MouseInput.Event == EMIE_RMOUSE_PRESSED_DOWN) {
rightclicked = true;
}
if (event.MouseInput.Event == EMIE_LMOUSE_LEFT_UP) {
leftreleased = true;
}
if (event.MouseInput.Event == EMIE_RMOUSE_LEFT_UP) {
rightreleased = true;
}
if (event.MouseInput.Event == EMIE_MOUSE_WHEEL) {
mouse_wheel += event.MouseInput.Wheel;
}
}
}
if (event.EventType == irr::EET_LOG_TEXT_EVENT) {
dstream << std::string("Irrlicht log: ") + std::string(event.LogEvent.Text)
<< std::endl;
return true;
}
/* always return false in order to continue processing events */
return false;
}
bool IsKeyDown(const KeyPress &keyCode) const
{
return keyIsDown[keyCode];
}
// Checks whether a key was down and resets the state
bool WasKeyDown(const KeyPress &keyCode)
{
bool b = keyWasDown[keyCode];
if (b)
keyWasDown.unset(keyCode);
return b;
}
s32 getMouseWheel()
{
s32 a = mouse_wheel;
mouse_wheel = 0;
return a;
}
void clearInput()
{
keyIsDown.clear();
keyWasDown.clear();
leftclicked = false;
rightclicked = false;
leftreleased = false;
rightreleased = false;
left_active = false;
middle_active = false;
right_active = false;
mouse_wheel = 0;
}
MyEventReceiver()
{
clearInput();
#ifdef HAVE_TOUCHSCREENGUI
m_touchscreengui = NULL;
#endif
}
bool leftclicked;
bool rightclicked;
bool leftreleased;
bool rightreleased;
bool left_active;
bool middle_active;
bool right_active;
s32 mouse_wheel;
#ifdef HAVE_TOUCHSCREENGUI
TouchScreenGUI* m_touchscreengui;
#endif
private:
// The current state of keys
KeyList keyIsDown;
// Whether a key has been pressed or not
KeyList keyWasDown;
};
/*
Separated input handler
*/
class RealInputHandler : public InputHandler
{
public:
RealInputHandler(IrrlichtDevice *device, MyEventReceiver *receiver):
m_device(device),
m_receiver(receiver),
m_mousepos(0,0)
{
}
virtual bool isKeyDown(const KeyPress &keyCode)
{
return m_receiver->IsKeyDown(keyCode);
}
virtual bool wasKeyDown(const KeyPress &keyCode)
{
return m_receiver->WasKeyDown(keyCode);
}
virtual v2s32 getMousePos()
{
if (m_device->getCursorControl()) {
return m_device->getCursorControl()->getPosition();
}
else {
return m_mousepos;
}
}
virtual void setMousePos(s32 x, s32 y)
{
if (m_device->getCursorControl()) {
m_device->getCursorControl()->setPosition(x, y);
}
else {
m_mousepos = v2s32(x,y);
}
}
virtual bool getLeftState()
{
return m_receiver->left_active;
}
virtual bool getRightState()
{
return m_receiver->right_active;
}
virtual bool getLeftClicked()
{
return m_receiver->leftclicked;
}
virtual bool getRightClicked()
{
return m_receiver->rightclicked;
}
virtual void resetLeftClicked()
{
m_receiver->leftclicked = false;
}
virtual void resetRightClicked()
{
m_receiver->rightclicked = false;
}
virtual bool getLeftReleased()
{
return m_receiver->leftreleased;
}
virtual bool getRightReleased()
{
return m_receiver->rightreleased;
}
virtual void resetLeftReleased()
{
m_receiver->leftreleased = false;
}
virtual void resetRightReleased()
{
m_receiver->rightreleased = false;
}
virtual s32 getMouseWheel()
{
return m_receiver->getMouseWheel();
}
void clear()
{
m_receiver->clearInput();
}
private:
IrrlichtDevice *m_device;
MyEventReceiver *m_receiver;
v2s32 m_mousepos;
};
class RandomInputHandler : public InputHandler
{
public:
RandomInputHandler()
{
leftdown = false;
rightdown = false;
leftclicked = false;
rightclicked = false;
leftreleased = false;
rightreleased = false;
keydown.clear();
}
virtual bool isKeyDown(const KeyPress &keyCode)
{
return keydown[keyCode];
}
virtual bool wasKeyDown(const KeyPress &keyCode)
{
return false;
}
virtual v2s32 getMousePos()
{
return mousepos;
}
virtual void setMousePos(s32 x, s32 y)
{
mousepos = v2s32(x, y);
}
virtual bool getLeftState()
{
return leftdown;
}
virtual bool getRightState()
{
return rightdown;
}
virtual bool getLeftClicked()
{
return leftclicked;
}
virtual bool getRightClicked()
{
return rightclicked;
}
virtual void resetLeftClicked()
{
leftclicked = false;
}
virtual void resetRightClicked()
{
rightclicked = false;
}
virtual bool getLeftReleased()
{
return leftreleased;
}
virtual bool getRightReleased()
{
return rightreleased;
}
virtual void resetLeftReleased()
{
leftreleased = false;
}
virtual void resetRightReleased()
{
rightreleased = false;
}
virtual s32 getMouseWheel()
{
return 0;
}
virtual void step(float dtime)
{
{
static float counter1 = 0;
counter1 -= dtime;
if (counter1 < 0.0) {
counter1 = 0.1 * Rand(1, 40);
keydown.toggle(getKeySetting("keymap_jump"));
}
}
{
static float counter1 = 0;
counter1 -= dtime;
if (counter1 < 0.0) {
counter1 = 0.1 * Rand(1, 40);
keydown.toggle(getKeySetting("keymap_special1"));
}
}
{
static float counter1 = 0;
counter1 -= dtime;
if (counter1 < 0.0) {
counter1 = 0.1 * Rand(1, 40);
keydown.toggle(getKeySetting("keymap_forward"));
}
}
{
static float counter1 = 0;
counter1 -= dtime;
if (counter1 < 0.0) {
counter1 = 0.1 * Rand(1, 40);
keydown.toggle(getKeySetting("keymap_left"));
}
}
{
static float counter1 = 0;
counter1 -= dtime;
if (counter1 < 0.0) {
counter1 = 0.1 * Rand(1, 20);
mousespeed = v2s32(Rand(-20, 20), Rand(-15, 20));
}
}
{
static float counter1 = 0;
counter1 -= dtime;
if (counter1 < 0.0) {
counter1 = 0.1 * Rand(1, 30);
leftdown = !leftdown;
if (leftdown)
leftclicked = true;
if (!leftdown)
leftreleased = true;
}
}
{
static float counter1 = 0;
counter1 -= dtime;
if (counter1 < 0.0) {
counter1 = 0.1 * Rand(1, 15);
rightdown = !rightdown;
if (rightdown)
rightclicked = true;
if (!rightdown)
rightreleased = true;
}
}
mousepos += mousespeed;
}
s32 Rand(s32 min, s32 max)
{
return (myrand()%(max-min+1))+min;
}
private:
KeyList keydown;
v2s32 mousepos;
v2s32 mousespeed;
bool leftdown;
bool rightdown;
bool leftclicked;
bool rightclicked;
bool leftreleased;
bool rightreleased;
};
#endif

View File

@ -25,7 +25,7 @@ with this program; if not, write to the Free Software Foundation, Inc.,
#include "player.h"
#include "settings.h"
#include "mapblock.h"
#include "network/connection.h"
#include "connection.h"
#include "environment.h"
#include "map.h"
#include "emerge.h"
@ -59,7 +59,7 @@ void RemoteClient::ResendBlockIfOnWire(v3s16 p)
}
}
void RemoteClient::GetNextBlocks (
void RemoteClient::GetNextBlocks(
ServerEnvironment *env,
EmergeManager * emerge,
float dtime,
@ -182,15 +182,18 @@ void RemoteClient::GetNextBlocks (
//bool queue_is_full = false;
s16 d;
for(d = d_start; d <= d_max; d++) {
for(d = d_start; d <= d_max; d++)
{
/*
Get the border/face dot coordinates of a "d-radiused"
box
*/
std::vector<v3s16> list = FacePositionCache::getFacePositions(d);
std::list<v3s16> list;
getFacePositions(list, d);
std::vector<v3s16>::iterator li;
for(li = list.begin(); li != list.end(); ++li) {
std::list<v3s16>::iterator li;
for(li=list.begin(); li!=list.end(); ++li)
{
v3s16 p = *li + center;
/*
@ -560,9 +563,9 @@ ClientInterface::~ClientInterface()
}
}
std::vector<u16> ClientInterface::getClientIDs(ClientState min_state)
std::list<u16> ClientInterface::getClientIDs(ClientState min_state)
{
std::vector<u16> reply;
std::list<u16> reply;
JMutexAutoLock clientslock(m_clients_mutex);
for(std::map<u16, RemoteClient*>::iterator
@ -596,22 +599,20 @@ void ClientInterface::UpdatePlayerList()
{
if (m_env != NULL)
{
std::vector<u16> clients = getClientIDs();
std::list<u16> clients = getClientIDs();
m_clients_names.clear();
if(!clients.empty())
infostream<<"Players:"<<std::endl;
for(std::vector<u16>::iterator
for(std::list<u16>::iterator
i = clients.begin();
i != clients.end(); ++i) {
i != clients.end(); ++i)
{
Player *player = m_env->getPlayer(*i);
if (player == NULL)
if(player==NULL)
continue;
infostream << "* " << player->getName() << "\t";
infostream<<"* "<<player->getName()<<"\t";
{
JMutexAutoLock clientslock(m_clients_mutex);
@ -619,36 +620,32 @@ void ClientInterface::UpdatePlayerList()
if(client != NULL)
client->PrintInfo(infostream);
}
m_clients_names.push_back(player->getName());
}
}
}
void ClientInterface::send(u16 peer_id, u8 channelnum,
NetworkPacket* pkt, bool reliable, bool deletepkt)
void ClientInterface::send(u16 peer_id,u8 channelnum,
SharedBuffer<u8> data, bool reliable)
{
m_con->Send(peer_id, channelnum, pkt, reliable);
if (deletepkt)
delete pkt;
m_con->Send(peer_id, channelnum, data, reliable);
}
void ClientInterface::sendToAll(u16 channelnum,
NetworkPacket* pkt, bool reliable)
SharedBuffer<u8> data, bool reliable)
{
JMutexAutoLock clientslock(m_clients_mutex);
for(std::map<u16, RemoteClient*>::iterator
i = m_clients.begin();
i != m_clients.end(); ++i) {
i != m_clients.end(); ++i)
{
RemoteClient *client = i->second;
if (client->net_proto_version != 0) {
m_con->Send(client->peer_id, channelnum, pkt, reliable);
if (client->net_proto_version != 0)
{
m_con->Send(client->peer_id, channelnum, data, reliable);
}
}
delete pkt;
}
RemoteClient* ClientInterface::getClientNoEx(u16 peer_id, ClientState state_min)

View File

@ -24,7 +24,6 @@ with this program; if not, write to the Free Software Foundation, Inc.,
#include "constants.h"
#include "serialization.h" // for SER_FMT_VER_INVALID
#include "jthread/jmutex.h"
#include "network/networkpacket.h"
#include <list>
#include <vector>
@ -388,16 +387,16 @@ public:
void step(float dtime);
/* get list of active client id's */
std::vector<u16> getClientIDs(ClientState min_state=CS_Active);
std::list<u16> getClientIDs(ClientState min_state=CS_Active);
/* get list of client player names */
std::vector<std::string> getPlayerNames();
/* send message to client */
void send(u16 peer_id, u8 channelnum, NetworkPacket* pkt, bool reliable, bool deletepkt=true);
void send(u16 peer_id, u8 channelnum, SharedBuffer<u8> data, bool reliable);
/* send to all clients */
void sendToAll(u16 channelnum, NetworkPacket* pkt, bool reliable);
void sendToAll(u16 channelnum, SharedBuffer<u8> data, bool reliable);
/* delete a client */
void DeleteClient(u16 peer_id);
@ -458,7 +457,7 @@ private:
JMutex m_env_mutex;
float m_print_info_timer;
static const char *statenames[];
};

View File

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

View File

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

View File

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

View File

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

View File

@ -17,8 +17,8 @@ with this program; if not, write to the Free Software Foundation, Inc.,
51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
*/
#ifndef NETWORKPROTOCOL_HEADER
#define NETWORKPROTOCOL_HEADER
#ifndef CLIENTSERVER_HEADER
#define CLIENTSERVER_HEADER
#include "util/string.h"
/*
@ -556,8 +556,6 @@ enum ToClientCommand
v3f1000 first
v3f1000 third
*/
TOCLIENT_NUM_MSG_TYPES = 0x53,
};
enum ToServerCommand
@ -661,7 +659,7 @@ enum ToServerCommand
TOSERVER_INVENTORY_ACTION = 0x31,
/*
See InventoryAction in inventorymanager.h
See InventoryAction in inventory.h
*/
TOSERVER_CHAT_MESSAGE = 0x32,
@ -797,8 +795,7 @@ enum ToServerCommand
u16 len
u8[len] full_version_string
*/
TOSERVER_NUM_MSG_TYPES = 0x44,
};
#endif

View File

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

File diff suppressed because it is too large Load Diff

View File

@ -24,7 +24,6 @@ with this program; if not, write to the Free Software Foundation, Inc.,
#include "socket.h"
#include "exceptions.h"
#include "constants.h"
#include "network/networkpacket.h"
#include "util/pointer.h"
#include "util/container.h"
#include "util/thread.h"
@ -131,14 +130,14 @@ inline bool seqnum_higher(u16 totest, u16 base)
{
if (totest > base)
{
if ((totest - base) > (SEQNUM_MAX/2))
if((totest - base) > (SEQNUM_MAX/2))
return false;
else
return true;
}
else
{
if ((base - totest) > (SEQNUM_MAX/2))
if((base - totest) > (SEQNUM_MAX/2))
return true;
else
return false;
@ -363,9 +362,9 @@ public:
packet is constructed. If not, returns one of length 0.
*/
SharedBuffer<u8> insert(BufferedPacket &p, bool reliable);
void removeUnreliableTimedOuts(float dtime, float timeout);
private:
// Key is seqnum
std::map<u16, IncomingSplitPacket*> m_buf;
@ -496,7 +495,7 @@ public:
u16 readNextSplitSeqNum();
void setNextSplitSeqNum(u16 seqnum);
// This is for buffering the incoming packets that are coming in
// the wrong order
ReliablePacketBuffer incoming_reliables;
@ -505,10 +504,10 @@ public:
ReliablePacketBuffer outgoing_reliables_sent;
//queued reliable packets
std::queue<BufferedPacket> queued_reliables;
Queue<BufferedPacket> queued_reliables;
//queue commands prior splitting to packets
std::queue<ConnectionCommand> queued_commands;
Queue<ConnectionCommand> queued_commands;
IncomingSplitBuffer incoming_splits;
@ -874,7 +873,7 @@ struct ConnectionEvent
std::string describe()
{
switch(type) {
switch(type){
case CONNEVENT_NONE:
return "CONNEVENT_NONE";
case CONNEVENT_DATA_RECEIVED:
@ -888,7 +887,7 @@ struct ConnectionEvent
}
return "Invalid ConnectionEvent";
}
void dataReceived(u16 peer_id_, SharedBuffer<u8> data_)
{
type = CONNEVENT_DATA_RECEIVED;
@ -964,7 +963,7 @@ private:
Connection* m_connection;
unsigned int m_max_packet_size;
float m_timeout;
std::queue<OutgoingPacket> m_outgoing_queue;
Queue<OutgoingPacket> m_outgoing_queue;
JSemaphore m_send_sleep_semaphore;
unsigned int m_iteration_packets_avaialble;
@ -1026,15 +1025,16 @@ public:
ConnectionEvent getEvent();
ConnectionEvent waitEvent(u32 timeout_ms);
void putCommand(ConnectionCommand &c);
void SetTimeoutMs(int timeout) { m_bc_receive_timeout = timeout; }
void SetTimeoutMs(int timeout){ m_bc_receive_timeout = timeout; }
void Serve(Address bind_addr);
void Connect(Address address);
bool Connected();
void Disconnect();
u32 Receive(u16 &peer_id, SharedBuffer<u8> &data);
void Send(u16 peer_id, u8 channelnum, NetworkPacket* pkt, bool reliable);
u16 GetPeerID() { return m_peer_id; }
void SendToAll(u8 channelnum, SharedBuffer<u8> data, bool reliable);
void Send(u16 peer_id, u8 channelnum, SharedBuffer<u8> data, bool reliable);
u16 GetPeerID(){ return m_peer_id; }
Address GetPeerAddress(u16 peer_id);
float getPeerStat(u16 peer_id, rtt_stat_type type);
float getLocalStat(rate_stat_type type);
@ -1051,14 +1051,14 @@ protected:
UDPPeer* createServerPeer(Address& sender);
bool deletePeer(u16 peer_id, bool timeout);
void SetPeerID(u16 id) { m_peer_id = id; }
void SetPeerID(u16 id){ m_peer_id = id; }
void sendAck(u16 peer_id, u8 channelnum, u16 seqnum);
void PrintInfo(std::ostream &out);
void PrintInfo();
std::list<u16> getPeerIDs() { return m_peer_ids; }
std::list<u16> getPeerIDs();
UDPSocket m_udpSocket;
MutexedQueue<ConnectionCommand> m_command_queue;
@ -1074,9 +1074,8 @@ private:
u16 m_peer_id;
u32 m_protocol_id;
std::map<u16, Peer*> m_peers;
std::list<u16> m_peer_ids;
JMutex m_peers_mutex;
ConnectionSendThread m_sendThread;
@ -1096,3 +1095,4 @@ private:
} // namespace
#endif

View File

@ -100,13 +100,7 @@ with this program; if not, write to the Free Software Foundation, Inc.,
/*
GUI related things
*/
// 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 TTF_DEFAULT_FONT_SIZE (14)
#define DEFAULT_FONT_SIZE (10)
#endif

View File

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

View File

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

View File

@ -19,7 +19,7 @@ with this program; if not, write to the Free Software Foundation, Inc.,
#include "content_cso.h"
#include <IBillboardSceneNode.h>
#include "client/tile.h"
#include "tile.h"
#include "environment.h"
#include "gamedef.h"
#include "log.h"

View File

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

View File

@ -17,17 +17,23 @@ with this program; if not, write to the Free Software Foundation, Inc.,
51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
*/
#ifndef __GAME_PARAMS_H__
#define __GAME_PARAMS_H__
#ifndef CONTENT_OBJECT_HEADER
#define CONTENT_OBJECT_HEADER
#include "irrlichttypes_extrabloated.h"
#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
struct GameParams {
u16 socket_port;
std::string world_path;
SubgameSpec game_spec;
bool is_dedicated_server;
int log_level;
};
#define ACTIVEOBJECT_TYPE_LUAENTITY 7
// Special type, not stored as a static object
#define ACTIVEOBJECT_TYPE_PLAYER 100
// Special type, only exists as CAO
#define ACTIVEOBJECT_TYPE_GENERIC 101
#endif

View File

@ -29,13 +29,60 @@ with this program; if not, write to the Free Software Foundation, Inc.,
#include "tool.h" // For ToolCapabilities
#include "gamedef.h"
#include "player.h"
#include "server.h"
#include "scripting_game.h"
#include "genericobject.h"
#include "log.h"
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
*/
@ -50,7 +97,7 @@ public:
{
ServerActiveObject::registerType(getType(), create);
}
ActiveObjectType getType() const
u8 getType() const
{ return ACTIVEOBJECT_TYPE_TEST; }
static ServerActiveObject* create(ServerEnvironment *env, v3f pos,
@ -91,7 +138,7 @@ public:
data += itos(m_base_position.Z);
ActiveObjectMessage aom(getId(), false, data);
m_messages_out.push(aom);
m_messages_out.push_back(aom);
}
}
@ -111,6 +158,203 @@ private:
// Prototype (registers item for deserialization)
TestSAO proto_TestSAO(NULL, v3f(0,0,0));
/*
ItemSAO
DEPRECATED: New dropped items are implemented in Lua; see
builtin/item_entity.lua.
*/
class ItemSAO : public ServerActiveObject
{
public:
u8 getType() const
{ return ACTIVEOBJECT_TYPE_ITEM; }
float getMinimumSavedMovement()
{ return 0.1*BS; }
static ServerActiveObject* create(ServerEnvironment *env, v3f pos,
const std::string &data)
{
std::istringstream is(data, std::ios::binary);
char buf[1];
// read version
is.read(buf, 1);
u8 version = buf[0];
// check if version is supported
if(version != 0)
return NULL;
std::string itemstring = deSerializeString(is);
infostream<<"create(): Creating item \""
<<itemstring<<"\""<<std::endl;
return new ItemSAO(env, pos, itemstring);
}
ItemSAO(ServerEnvironment *env, v3f pos,
const std::string &itemstring):
ServerActiveObject(env, pos),
m_itemstring(itemstring),
m_itemstring_changed(false),
m_speed_f(0,0,0),
m_last_sent_position(0,0,0)
{
ServerActiveObject::registerType(getType(), create);
}
void step(float dtime, bool send_recommended)
{
ScopeProfiler sp2(g_profiler, "step avg", SPT_AVG);
assert(m_env);
const float interval = 0.2;
if(m_move_interval.step(dtime, interval)==false)
return;
dtime = interval;
core::aabbox3d<f32> box(-BS/3.,0.0,-BS/3., BS/3.,BS*2./3.,BS/3.);
collisionMoveResult moveresult;
// Apply gravity
m_speed_f += v3f(0, -dtime*9.81*BS, 0);
// Maximum movement without glitches
f32 pos_max_d = BS*0.25;
// Limit speed
if(m_speed_f.getLength()*dtime > pos_max_d)
m_speed_f *= pos_max_d / (m_speed_f.getLength()*dtime);
v3f pos_f = getBasePosition();
v3f accel_f = v3f(0,0,0);
f32 stepheight = 0;
moveresult = collisionMoveSimple(m_env,m_env->getGameDef(),
pos_max_d, box, stepheight, dtime,
pos_f, m_speed_f, accel_f);
if(send_recommended == false)
return;
if(pos_f.getDistanceFrom(m_last_sent_position) > 0.05*BS)
{
setBasePosition(pos_f);
m_last_sent_position = pos_f;
std::ostringstream os(std::ios::binary);
// command (0 = update position)
writeU8(os, 0);
// pos
writeV3F1000(os, m_base_position);
// create message and add to list
ActiveObjectMessage aom(getId(), false, os.str());
m_messages_out.push_back(aom);
}
if(m_itemstring_changed)
{
m_itemstring_changed = false;
std::ostringstream os(std::ios::binary);
// command (1 = update itemstring)
writeU8(os, 1);
// itemstring
os<<serializeString(m_itemstring);
// create message and add to list
ActiveObjectMessage aom(getId(), false, os.str());
m_messages_out.push_back(aom);
}
}
std::string getClientInitializationData(u16 protocol_version)
{
std::ostringstream os(std::ios::binary);
// version
writeU8(os, 0);
// pos
writeV3F1000(os, m_base_position);
// itemstring
os<<serializeString(m_itemstring);
return os.str();
}
std::string getStaticData()
{
infostream<<__FUNCTION_NAME<<std::endl;
std::ostringstream os(std::ios::binary);
// version
writeU8(os, 0);
// itemstring
os<<serializeString(m_itemstring);
return os.str();
}
ItemStack createItemStack()
{
try{
IItemDefManager *idef = m_env->getGameDef()->idef();
ItemStack item;
item.deSerialize(m_itemstring, idef);
infostream<<__FUNCTION_NAME<<": m_itemstring=\""<<m_itemstring
<<"\" -> item=\""<<item.getItemString()<<"\""
<<std::endl;
return item;
}
catch(SerializationError &e)
{
infostream<<__FUNCTION_NAME<<": serialization error: "
<<"m_itemstring=\""<<m_itemstring<<"\""<<std::endl;
return ItemStack();
}
}
int punch(v3f dir,
const ToolCapabilities *toolcap,
ServerActiveObject *puncher,
float time_from_last_punch)
{
// Take item into inventory
ItemStack item = createItemStack();
Inventory *inv = puncher->getInventory();
if(inv != NULL)
{
std::string wieldlist = puncher->getWieldList();
ItemStack leftover = inv->addItem(wieldlist, item);
puncher->setInventoryModified();
if(leftover.empty())
{
m_removed = true;
}
else
{
m_itemstring = leftover.getItemString();
m_itemstring_changed = true;
}
}
return 0;
}
bool getCollisionBox(aabb3f *toset) {
return false;
}
bool collideWithObjects() {
return false;
}
private:
std::string m_itemstring;
bool m_itemstring_changed;
v3f m_speed_f;
v3f m_last_sent_position;
IntervalLimiter m_move_interval;
};
// Prototype (registers item for deserialization)
ItemSAO proto_ItemSAO(NULL, v3f(0,0,0), "");
ServerActiveObject* createItemSAO(ServerEnvironment *env, v3f pos,
const std::string &itemstring)
{
return new ItemSAO(env, pos, itemstring);
}
/*
LuaEntitySAO
*/
@ -233,7 +477,7 @@ void LuaEntitySAO::step(float dtime, bool send_recommended)
std::string str = getPropertyPacket();
// create message and add to list
ActiveObjectMessage aom(getId(), true, str);
m_messages_out.push(aom);
m_messages_out.push_back(aom);
}
// If attached, check that our parent is still there. If it isn't, detach.
@ -320,7 +564,7 @@ void LuaEntitySAO::step(float dtime, bool send_recommended)
m_armor_groups);
// create message and add to list
ActiveObjectMessage aom(getId(), true, str);
m_messages_out.push(aom);
m_messages_out.push_back(aom);
}
if(m_animation_sent == false){
@ -328,7 +572,7 @@ void LuaEntitySAO::step(float dtime, bool send_recommended)
std::string str = gob_cmd_update_animation(m_animation_range, m_animation_speed, m_animation_blend);
// create message and add to list
ActiveObjectMessage aom(getId(), true, str);
m_messages_out.push(aom);
m_messages_out.push_back(aom);
}
if(m_bone_position_sent == false){
@ -337,7 +581,7 @@ void LuaEntitySAO::step(float dtime, bool send_recommended)
std::string str = gob_cmd_update_bone_position((*ii).first, (*ii).second.X, (*ii).second.Y);
// create message and add to list
ActiveObjectMessage aom(getId(), true, str);
m_messages_out.push(aom);
m_messages_out.push_back(aom);
}
}
@ -346,7 +590,7 @@ void LuaEntitySAO::step(float dtime, bool send_recommended)
std::string str = gob_cmd_update_attachment(m_attachment_parent_id, m_attachment_bone, m_attachment_position, m_attachment_rotation);
// create message and add to list
ActiveObjectMessage aom(getId(), true, str);
m_messages_out.push(aom);
m_messages_out.push_back(aom);
}
}
@ -461,7 +705,7 @@ int LuaEntitySAO::punch(v3f dir,
std::string str = gob_cmd_punched(result.damage, getHP());
// create message and add to list
ActiveObjectMessage aom(getId(), true, str);
m_messages_out.push(aom);
m_messages_out.push_back(aom);
}
if(getHP() == 0)
@ -610,7 +854,7 @@ void LuaEntitySAO::setTextureMod(const std::string &mod)
std::string str = gob_cmd_set_texture_mod(mod);
// create message and add to list
ActiveObjectMessage aom(getId(), true, str);
m_messages_out.push(aom);
m_messages_out.push_back(aom);
}
void LuaEntitySAO::setSprite(v2s16 p, int num_frames, float framelength,
@ -624,7 +868,7 @@ void LuaEntitySAO::setSprite(v2s16 p, int num_frames, float framelength,
);
// create message and add to list
ActiveObjectMessage aom(getId(), true, str);
m_messages_out.push(aom);
m_messages_out.push_back(aom);
}
std::string LuaEntitySAO::getName()
@ -664,7 +908,7 @@ void LuaEntitySAO::sendPosition(bool do_interpolate, bool is_movement_end)
);
// create message and add to list
ActiveObjectMessage aom(getId(), false, str);
m_messages_out.push(aom);
m_messages_out.push_back(aom);
}
bool LuaEntitySAO::getCollisionBox(aabb3f *toset) {
@ -717,6 +961,11 @@ PlayerSAO::PlayerSAO(ServerEnvironment *env_, Player *player_, u16 peer_id_,
m_attachment_parent_id(0),
m_attachment_sent(false),
// public
m_moved(false),
m_inventory_not_sent(false),
m_hp_not_sent(false),
m_breath_not_sent(false),
m_wielded_item_not_sent(false),
m_physics_override_speed(1),
m_physics_override_jump(1),
m_physics_override_gravity(1),
@ -856,7 +1105,7 @@ void PlayerSAO::step(float dtime, bool send_recommended)
std::string str = getPropertyPacket();
// create message and add to list
ActiveObjectMessage aom(getId(), true, str);
m_messages_out.push(aom);
m_messages_out.push_back(aom);
}
// If attached, check that our parent is still there. If it isn't, detach.
@ -867,7 +1116,7 @@ void PlayerSAO::step(float dtime, bool send_recommended)
m_attachment_position = v3f(0,0,0);
m_attachment_rotation = v3f(0,0,0);
m_player->setPosition(m_last_good_position);
((Server*)m_env->getGameDef())->SendMovePlayer(m_peer_id);
m_moved = true;
}
//dstream<<"PlayerSAO::step: dtime: "<<dtime<<std::endl;
@ -919,16 +1168,22 @@ void PlayerSAO::step(float dtime, bool send_recommended)
);
// create message and add to list
ActiveObjectMessage aom(getId(), false, str);
m_messages_out.push(aom);
m_messages_out.push_back(aom);
}
if(m_armor_groups_sent == false) {
if(m_wielded_item_not_sent)
{
m_wielded_item_not_sent = false;
// GenericCAO has no special way to show this
}
if(m_armor_groups_sent == false){
m_armor_groups_sent = true;
std::string str = gob_cmd_update_armor_groups(
m_armor_groups);
// create message and add to list
ActiveObjectMessage aom(getId(), true, str);
m_messages_out.push(aom);
m_messages_out.push_back(aom);
}
if(m_physics_override_sent == false){
@ -938,7 +1193,7 @@ void PlayerSAO::step(float dtime, bool send_recommended)
m_physics_override_sneak, m_physics_override_sneak_glitch);
// create message and add to list
ActiveObjectMessage aom(getId(), true, str);
m_messages_out.push(aom);
m_messages_out.push_back(aom);
}
if(m_animation_sent == false){
@ -946,7 +1201,7 @@ void PlayerSAO::step(float dtime, bool send_recommended)
std::string str = gob_cmd_update_animation(m_animation_range, m_animation_speed, m_animation_blend);
// create message and add to list
ActiveObjectMessage aom(getId(), true, str);
m_messages_out.push(aom);
m_messages_out.push_back(aom);
}
if(m_bone_position_sent == false){
@ -955,7 +1210,7 @@ void PlayerSAO::step(float dtime, bool send_recommended)
std::string str = gob_cmd_update_bone_position((*ii).first, (*ii).second.X, (*ii).second.Y);
// create message and add to list
ActiveObjectMessage aom(getId(), true, str);
m_messages_out.push(aom);
m_messages_out.push_back(aom);
}
}
@ -964,7 +1219,7 @@ void PlayerSAO::step(float dtime, bool send_recommended)
std::string str = gob_cmd_update_attachment(m_attachment_parent_id, m_attachment_bone, m_attachment_position, m_attachment_rotation);
// create message and add to list
ActiveObjectMessage aom(getId(), true, str);
m_messages_out.push(aom);
m_messages_out.push_back(aom);
}
}
@ -982,7 +1237,8 @@ void PlayerSAO::setPos(v3f pos)
m_player->setPosition(pos);
// Movement caused by this command is always valid
m_last_good_position = pos;
((Server*)m_env->getGameDef())->SendMovePlayer(m_peer_id);
// Force position change on client
m_moved = true;
}
void PlayerSAO::moveTo(v3f pos, bool continuous)
@ -992,19 +1248,22 @@ void PlayerSAO::moveTo(v3f pos, bool continuous)
m_player->setPosition(pos);
// Movement caused by this command is always valid
m_last_good_position = pos;
((Server*)m_env->getGameDef())->SendMovePlayer(m_peer_id);
// Force position change on client
m_moved = true;
}
void PlayerSAO::setYaw(float yaw)
{
m_player->setYaw(yaw);
((Server*)m_env->getGameDef())->SendMovePlayer(m_peer_id);
// Force change on client
m_moved = true;
}
void PlayerSAO::setPitch(float pitch)
{
m_player->setPitch(pitch);
((Server*)m_env->getGameDef())->SendMovePlayer(m_peer_id);
// Force change on client
m_moved = true;
}
int PlayerSAO::punch(v3f dir,
@ -1025,7 +1284,7 @@ int PlayerSAO::punch(v3f dir,
std::string str = gob_cmd_punched(0, getHP());
// create message and add to list
ActiveObjectMessage aom(getId(), true, str);
m_messages_out.push(aom);
m_messages_out.push_back(aom);
return 0;
}
}
@ -1067,18 +1326,27 @@ void PlayerSAO::setHP(s16 hp)
{
s16 oldhp = m_player->hp;
if (hp < 0)
if(hp < 0)
hp = 0;
else if (hp > PLAYER_MAX_HP)
else if(hp > PLAYER_MAX_HP)
hp = PLAYER_MAX_HP;
if(hp < oldhp && g_settings->getBool("enable_damage") == false)
{
m_hp_not_sent = true; // fix wrong prediction on client
return;
}
m_player->hp = hp;
if (oldhp > hp)
m_damage += (oldhp - hp);
if(hp != oldhp) {
m_hp_not_sent = true;
if(oldhp > hp)
m_damage += oldhp - hp;
}
// Update properties on death
if ((hp == 0) != (oldhp == 0))
if((hp == 0) != (oldhp == 0))
m_properties_sent = false;
}
@ -1157,6 +1425,11 @@ InventoryLocation PlayerSAO::getInventoryLocation() const
return loc;
}
void PlayerSAO::setInventoryModified()
{
m_inventory_not_sent = true;
}
std::string PlayerSAO::getWieldList() const
{
return "main";
@ -1169,8 +1442,10 @@ int PlayerSAO::getWieldIndex() const
void PlayerSAO::setWieldIndex(int i)
{
if(i != m_wield_index) {
if(i != m_wield_index)
{
m_wield_index = i;
m_wielded_item_not_sent = true;
}
}
@ -1237,6 +1512,7 @@ bool PlayerSAO::checkMovementCheat()
<<" moved too fast; resetting position"
<<std::endl;
m_player->setPosition(m_last_good_position);
m_moved = true;
cheated = true;
}
}

View File

@ -21,10 +21,14 @@ with this program; if not, write to the Free Software Foundation, Inc.,
#define CONTENT_SAO_HEADER
#include "serverobject.h"
#include "content_object.h"
#include "itemgroup.h"
#include "player.h"
#include "object_properties.h"
ServerActiveObject* createItemSAO(ServerEnvironment *env, v3f pos,
const std::string &itemstring);
/*
LuaEntitySAO needs some internals exposed.
*/
@ -35,9 +39,9 @@ public:
LuaEntitySAO(ServerEnvironment *env, v3f pos,
const std::string &name, const std::string &state);
~LuaEntitySAO();
ActiveObjectType getType() const
u8 getType() const
{ return ACTIVEOBJECT_TYPE_LUAENTITY; }
ActiveObjectType getSendType() const
u8 getSendType() const
{ return ACTIVEOBJECT_TYPE_GENERIC; }
virtual void addedToEnvironment(u32 dtime_s);
static ServerActiveObject* create(ServerEnvironment *env, v3f pos,
@ -154,9 +158,9 @@ public:
PlayerSAO(ServerEnvironment *env_, Player *player_, u16 peer_id_,
const std::set<std::string> &privs, bool is_singleplayer);
~PlayerSAO();
ActiveObjectType getType() const
u8 getType() const
{ return ACTIVEOBJECT_TYPE_PLAYER; }
ActiveObjectType getSendType() const
u8 getSendType() const
{ return ACTIVEOBJECT_TYPE_GENERIC; }
std::string getDescription();
@ -205,6 +209,7 @@ public:
Inventory* getInventory();
const Inventory* getInventory() const;
InventoryLocation getInventoryLocation() const;
void setInventoryModified();
std::string getWieldList() const;
int getWieldIndex() const;
void setWieldIndex(int i);
@ -314,6 +319,13 @@ private:
bool m_attachment_sent;
public:
// Some flags used by Server
bool m_moved;
bool m_inventory_not_sent;
bool m_hp_not_sent;
bool m_breath_not_sent;
bool m_wielded_item_not_sent;
float m_physics_override_speed;
float m_physics_override_jump;
float m_physics_override_gravity;

View File

@ -418,28 +418,27 @@ bool CraftDefinitionShaped::check(const CraftInput &input, IGameDef *gamedef) co
return false; // it was empty
// Different sizes?
if(inp_max_x - inp_min_x != rec_max_x - rec_min_x ||
inp_max_y - inp_min_y != rec_max_y - rec_min_y)
if(inp_max_x - inp_min_x != rec_max_x - rec_min_x)
return false;
if(inp_max_y - inp_min_y != rec_max_y - rec_min_y)
return false;
// Verify that all item names in the bounding box are equal
unsigned int w = inp_max_x - inp_min_x + 1;
unsigned int h = inp_max_y - inp_min_y + 1;
for(unsigned int y=0; y<h; y++)
for(unsigned int x=0; x<w; x++)
{
unsigned int inp_x = inp_min_x + x;
unsigned int inp_y = inp_min_y + y;
unsigned int rec_x = rec_min_x + x;
unsigned int rec_y = rec_min_y + y;
for(unsigned int y=0; y < h; y++) {
unsigned int inp_y = (inp_min_y + y) * inp_width;
unsigned int rec_y = (rec_min_y + y) * rec_width;
for(unsigned int x=0; x < w; x++) {
unsigned int inp_x = inp_min_x + x;
unsigned int rec_x = rec_min_x + x;
if(!inputItemMatchesRecipe(
inp_names[inp_y + inp_x],
rec_names[rec_y + rec_x], gamedef->idef())
) {
return false;
}
if(!inputItemMatchesRecipe(
inp_names[inp_y * inp_width + inp_x],
rec_names[rec_y * rec_width + rec_x], gamedef->idef())
){
return false;
}
}

View File

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

View File

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

View File

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

View File

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

View File

@ -20,78 +20,84 @@ with this program; if not, write to the Free Software Foundation, Inc.,
#include "config.h"
#if USE_REDIS
/*
Redis databases
*/
#include "database-redis.h"
#include <hiredis.h>
#include "map.h"
#include "mapsector.h"
#include "mapblock.h"
#include "serialization.h"
#include "main.h"
#include "settings.h"
#include "log.h"
#include "exceptions.h"
#include "util/string.h"
#include <hiredis.h>
#include <cassert>
#include "filesys.h"
Database_Redis::Database_Redis(Settings &conf)
Database_Redis::Database_Redis(ServerMap *map, std::string savedir)
{
Settings conf;
conf.readConfigFile((std::string(savedir) + DIR_DELIM + "world.mt").c_str());
std::string tmp;
try {
tmp = conf.get("redis_address");
hash = conf.get("redis_hash");
} catch (SettingNotFoundException) {
throw SettingNotFoundException("Set redis_address and "
"redis_hash in world.mt to use the redis backend");
tmp = conf.get("redis_address");
hash = conf.get("redis_hash");
} catch(SettingNotFoundException e) {
throw SettingNotFoundException("Set redis_address and redis_hash in world.mt to use the redis backend");
}
const char *addr = tmp.c_str();
int port = conf.exists("redis_port") ? conf.getU16("redis_port") : 6379;
ctx = redisConnect(addr, port);
if (!ctx) {
if(!ctx)
throw FileNotGoodException("Cannot allocate redis context");
} else if(ctx->err) {
else if(ctx->err) {
std::string err = std::string("Connection error: ") + ctx->errstr;
redisFree(ctx);
throw FileNotGoodException(err);
}
srvmap = map;
}
Database_Redis::~Database_Redis()
int Database_Redis::Initialized(void)
{
redisFree(ctx);
return 1;
}
void Database_Redis::beginSave() {
redisReply *reply = static_cast<redisReply *>(redisCommand(ctx, "MULTI"));
if (!reply) {
throw FileNotGoodException(std::string(
"Redis command 'MULTI' failed: ") + ctx->errstr);
}
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 = static_cast<redisReply *>(redisCommand(ctx, "EXEC"));
if (!reply) {
throw FileNotGoodException(std::string(
"Redis command 'EXEC' failed: ") + ctx->errstr);
}
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(const v3s16 &pos, const std::string &data)
bool Database_Redis::saveBlock(v3s16 blockpos, std::string &data)
{
std::string tmp = i64tos(getBlockAsInteger(pos));
std::string tmp = i64tos(getBlockAsInteger(blockpos));
redisReply *reply = static_cast<redisReply *>(redisCommand(ctx, "HSET %s %s %b",
hash.c_str(), tmp.c_str(), data.c_str(), data.size()));
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(pos) << ": " << ctx->errstr << std::endl;
"block " << PP(blockpos) << ": " << ctx->errstr << std::endl;
freeReplyObject(reply);
return false;
}
if (reply->type == REDIS_REPLY_ERROR) {
errorstream << "WARNING: saveBlock: saving block " << PP(pos)
errorstream << "WARNING: saveBlock: saving block " << PP(blockpos)
<< "failed" << std::endl;
freeReplyObject(reply);
return false;
@ -101,36 +107,38 @@ bool Database_Redis::saveBlock(const v3s16 &pos, const std::string &data)
return true;
}
std::string Database_Redis::loadBlock(const v3s16 &pos)
std::string Database_Redis::loadBlock(v3s16 blockpos)
{
std::string tmp = i64tos(getBlockAsInteger(pos));
redisReply *reply = static_cast<redisReply *>(redisCommand(ctx,
"HGET %s %s", hash.c_str(), tmp.c_str()));
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);
} else if (reply->type != REDIS_REPLY_STRING) {
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(const v3s16 &pos)
bool Database_Redis::deleteBlock(v3s16 blockpos)
{
std::string tmp = i64tos(getBlockAsInteger(pos));
std::string tmp = i64tos(getBlockAsInteger(blockpos));
redisReply *reply = static_cast<redisReply *>(redisCommand(ctx,
"HDEL %s %s", hash.c_str(), tmp.c_str()));
redisReply *reply = (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;
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;
}
@ -139,21 +147,24 @@ bool Database_Redis::deleteBlock(const v3s16 &pos)
return true;
}
void Database_Redis::listAllLoadableBlocks(std::vector<v3s16> &dst)
void Database_Redis::listAllLoadableBlocks(std::list<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) {
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++) {
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
Database_Redis::~Database_Redis()
{
redisFree(ctx);
}
#endif

View File

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

View File

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

View File

@ -27,43 +27,35 @@ extern "C" {
#include "sqlite3.h"
}
class ServerMap;
class Database_SQLite3 : public Database
{
public:
Database_SQLite3(const std::string &savedir);
Database_SQLite3(ServerMap *map, std::string savedir);
virtual void beginSave();
virtual void endSave();
virtual bool saveBlock(const v3s16 &pos, const std::string &data);
virtual std::string loadBlock(const v3s16 &pos);
virtual bool deleteBlock(const v3s16 &pos);
virtual void listAllLoadableBlocks(std::vector<v3s16> &dst);
virtual bool initialized() const { return m_initialized; }
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_SQLite3();
private:
// Open the database
void openDatabase();
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;
// Create the database structure
void createDatabase();
// Open and initialize the database if needed
// Verify we can read/write to the database
void verifyDatabase();
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;
void createDirs(std::string path);
};
#endif

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

@ -20,7 +20,7 @@ with this program; if not, write to the Free Software Foundation, Inc.,
#include "filecache.h"
#include "network/networkprotocol.h"
#include "clientserver.h"
#include "log.h"
#include "filesys.h"
#include <string>

View File

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

View File

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

View File

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

View File

@ -26,7 +26,7 @@ with this program; if not, write to the Free Software Foundation, Inc.,
#include "settings.h"
#include "main.h" // for g_settings
#include "porting.h"
#include "client/tile.h"
#include "tile.h"
#include "fontengine.h"
#include "log.h"
#include "gettext.h"
@ -99,7 +99,7 @@ GUIChatConsole::GUIChatConsole(
{
core::dimension2d<u32> dim = m_font->getDimension(L"M");
m_fontsize = v2u32(dim.Width, dim.Height);
m_font->grab();
dstream << "Font size: " << m_fontsize.X << " " << m_fontsize.Y << std::endl;
}
m_fontsize.X = MYMAX(m_fontsize.X, 1);
m_fontsize.Y = MYMAX(m_fontsize.Y, 1);
@ -109,10 +109,7 @@ GUIChatConsole::GUIChatConsole(
}
GUIChatConsole::~GUIChatConsole()
{
if (m_font)
m_font->drop();
}
{}
void GUIChatConsole::openConsole(f32 height)
{

View File

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

View File

@ -38,7 +38,7 @@ with this program; if not, write to the Free Software Foundation, Inc.,
#include "fontengine.h"
#ifdef __ANDROID__
#include "client/tile.h"
#include "tile.h"
#include <GLES/gl.h>
#endif

View File

@ -27,7 +27,7 @@ with this program; if not, write to the Free Software Foundation, Inc.,
#include "modalMenu.h"
#include "guiFormSpecMenu.h"
#include "sound.h"
#include "client/tile.h"
#include "tile.h"
/******************************************************************************/
/* Typedefs and macros */

View File

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

View File

@ -28,7 +28,7 @@ with this program; if not, write to the Free Software Foundation, Inc.,
#include "inventorymanager.h"
#include "modalMenu.h"
#include "guiTable.h"
#include "network/networkprotocol.h"
#include "clientserver.h"
class IGameDef;
class InventoryManager;
@ -246,20 +246,13 @@ public:
m_allowclose = value;
}
void lockSize(bool lock,v2u32 basescreensize=v2u32(0,0))
{
void lockSize(bool lock,v2u32 basescreensize=v2u32(0,0)) {
m_lock = lock;
m_lockscreensize = basescreensize;
}
void removeChildren();
void setInitialFocus();
void setFocus(std::wstring elementname)
{
m_focused_element = elementname;
}
/*
Remove and re-add (or reposition) stuff
*/
@ -355,7 +348,6 @@ private:
IFormSource *m_form_src;
TextDest *m_text_dst;
unsigned int m_formspec_version;
std::wstring m_focused_element;
typedef struct {
bool explicit_size;

View File

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

View File

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

View File

@ -28,7 +28,7 @@ with this program; if not, write to the Free Software Foundation, Inc.,
#include <IGUIScrollBar.h>
#include "debug.h"
#include "log.h"
#include "client/tile.h"
#include "tile.h"
#include "gettime.h"
#include "util/string.h"
#include "util/numeric.h"

View File

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

View File

@ -27,7 +27,7 @@ with this program; if not, write to the Free Software Foundation, Inc.,
#include "gamedef.h"
#include "itemdef.h"
#include "inventory.h"
#include "client/tile.h"
#include "tile.h"
#include "localplayer.h"
#include "camera.h"
#include "porting.h"

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

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