Merge remote-tracking branch 'minetest/master'

Conflicts:
	doc/lua_api.txt
	src/client.h
	src/content_sao.cpp
	src/environment.cpp
	src/environment.h
	src/keycode.cpp
	src/map.cpp
	src/network/clientpackethandler.cpp
	src/particles.cpp
	src/particles.h
	src/script/lua_api/l_particles.cpp
	src/server.cpp
	src/server.h
	src/serverobject.cpp
	src/serverobject.h
	src/threading/thread.h
master
Brandon 2016-10-29 15:09:28 -05:00
commit 4cb44572a5
118 changed files with 3162 additions and 2561 deletions

View File

@ -1,14 +1,4 @@
language: cpp
compiler:
- gcc
- clang
os:
- osx
- linux
env:
- PLATFORM=Win32
- PLATFORM=Win64
- PLATFORM=Unix
before_install: ./util/travis/before_install.sh
script: ./util/travis/script.sh
sudo: required
@ -16,14 +6,26 @@ notifications:
email: false
matrix:
fast_finish: true
exclude:
include:
- env: PLATFORM=Win32
compiler: clang
compiler: gcc
os: linux
- env: PLATFORM=Win64
compiler: gcc
os: linux
- env: PLATFORM=Unix COMPILER=clang
compiler: clang
- env: PLATFORM=Win32
os: osx
- env: PLATFORM=Win64
os: osx
- compiler: gcc
os: osx
- env: PLATFORM=Unix COMPILER=g++
compiler: gcc
os: linux
- env: PLATFORM=Unix COMPILER=clang
compiler: clang
os: linux
- env: PLATFORM=Unix COMPILER=g++-6
compiler: gcc
os: linux
addons:
apt:
sources: &sources
- ubuntu-toolchain-r-test

View File

@ -29,39 +29,47 @@ This game is not finished
- Don't expect it to work as well as a finished game will.
- Please report any bugs. When doing that, debug.txt is useful.
Default Controls
Default controls
-----------------
- WASD: move
- Space: jump/climb
- Shift: sneak/go down
- Q: drop itemstack (+ SHIFT for single item)
- I: inventory
- Mouse: turn/look
- Mouse left: dig/punch
- Mouse right: place/use
- Mouse wheel: select item
- T: chat
- 1-8: select item
- Move mouse: Look around
- W, A, S, D: Move
- Space: Jump/move up
- Shift: Sneak/move down
- Q: Drop itemstack
- Shift + Q: Drop single item
- Left mouse button: Dig/punch/take item
- Right mouse button: Place/use
- Shift + right mouse button: Build (without using)
- I: Inventory menu
- Mouse wheel: Select item
- 0-9: Select item
- Z: Zoom (needs zoom privilege)
- T: Chat
- /: Commad
- Esc: pause menu (pauses only singleplayer game)
- R: Enable/Disable full range view
- Esc: Pause menu/abort/exit (pauses only singleplayer game)
- R: Enable/disable full range view
- +: Increase view range
- -: Decrease view range
- K: Enable/Disable fly (needs fly privilege)
- J: Enable/Disable fast (needs fast privilege)
- H: Enable/Disable noclip (needs noclip privilege)
- K: Enable/disable fly mode (needs fly privilege)
- J: Enable/disable fast mode (needs fast privilege)
- H: Enable/disable noclip mode (needs noclip privilege)
- F1: Hide/Show HUD
- F2: Hide/Show Chat
- F3: Disable/Enable Fog
- F4: Disable/Enable Camera update (Mapblocks are not updated anymore when disabled)
- F5: Toogle through debug info screens
- F6: Toogle through output data
- F7: Toggle through camera modes
- F10: Show/Hide console
- F1: Hide/show HUD
- F2: Hide/show chat
- F3: Disable/enable fog
- F4: Disable/enable camera update (Mapblocks are not updated anymore when disabled, disabled in release builds)
- F5: Cycle through debug info screens
- F6: Cycle through profiler info screens
- F7: Cycle through camera modes
- F8: Toggle cinematic mode
- F9: Cycle through minimap modes
- Shift + F9: Change minimap orientation
- F10: Show/hide console
- F12: Take screenshot
- P: Write stack traces into debug.txt
- Settable in the configuration file, see the section below.
Most controls are settable in the configuration file, see the section below.
Paths
------
@ -395,6 +403,9 @@ Authors of media files
Everything not listed in here:
Copyright (C) 2010-2012 celeron55, Perttu Ahola <celeron55@gmail.com>
ShadowNinja:
textures/base/pack/smoke_puff.png
Paramat:
textures/base/pack/menu_header.png

View File

@ -203,6 +203,7 @@ LOCAL_SRC_FILES := \
jni/src/porting.cpp \
jni/src/profiler.cpp \
jni/src/quicktune.cpp \
jni/src/remoteplayer.cpp \
jni/src/rollback.cpp \
jni/src/rollback_interface.cpp \
jni/src/serialization.cpp \

View File

@ -31,6 +31,14 @@ function vector.normalize(v)
end
end
function vector.floor(v)
return {
x = math.floor(v.x),
y = math.floor(v.y),
z = math.floor(v.z)
}
end
function vector.round(v)
return {
x = math.floor(v.x + 0.5),
@ -130,4 +138,3 @@ function vector.divide(a, b)
z = a.z / b}
end
end

View File

@ -147,60 +147,79 @@ core.register_chatcommand("help", {
core.register_chatcommand("privs", {
params = "<name>",
description = "print out privileges of player",
func = function(name, param)
param = (param ~= "" and param or name)
return true, "Privileges of " .. param .. ": "
func = function(caller, param)
param = param:trim()
local name = (param ~= "" and param or caller)
return true, "Privileges of " .. name .. ": "
.. core.privs_to_string(
core.get_player_privs(param), ' ')
core.get_player_privs(name), ' ')
end,
})
local function handle_grant_command(caller, grantname, grantprivstr)
local caller_privs = minetest.get_player_privs(caller)
if not (caller_privs.privs or caller_privs.basic_privs) then
return false, "Your privileges are insufficient."
end
if not core.auth_table[grantname] then
return false, "Player " .. grantname .. " does not exist."
end
local grantprivs = core.string_to_privs(grantprivstr)
if grantprivstr == "all" then
grantprivs = core.registered_privileges
end
local privs = core.get_player_privs(grantname)
local privs_unknown = ""
local basic_privs =
core.string_to_privs(core.setting_get("basic_privs") or "interact,shout")
for priv, _ in pairs(grantprivs) do
if not basic_privs[priv] and not caller_privs.privs then
return false, "Your privileges are insufficient."
end
if not core.registered_privileges[priv] then
privs_unknown = privs_unknown .. "Unknown privilege: " .. priv .. "\n"
end
privs[priv] = true
end
if privs_unknown ~= "" then
return false, privs_unknown
end
core.set_player_privs(grantname, privs)
core.log("action", caller..' granted ('..core.privs_to_string(grantprivs, ', ')..') privileges to '..grantname)
if grantname ~= caller then
core.chat_send_player(grantname, caller
.. " granted you privileges: "
.. core.privs_to_string(grantprivs, ' '))
end
return true, "Privileges of " .. grantname .. ": "
.. core.privs_to_string(
core.get_player_privs(grantname), ' ')
end
core.register_chatcommand("grant", {
params = "<name> <privilege>|all",
description = "Give privilege to player",
func = function(name, param)
if not core.check_player_privs(name, {privs=true}) and
not core.check_player_privs(name, {basic_privs=true}) then
return false, "Your privileges are insufficient."
end
local grantname, grantprivstr = string.match(param, "([^ ]+) (.+)")
if not grantname or not grantprivstr then
return false, "Invalid parameters (see /help grant)"
elseif not core.auth_table[grantname] then
return false, "Player " .. grantname .. " does not exist."
end
local grantprivs = core.string_to_privs(grantprivstr)
if grantprivstr == "all" then
grantprivs = core.registered_privileges
end
local privs = core.get_player_privs(grantname)
local privs_unknown = ""
local basic_privs =
core.string_to_privs(core.setting_get("basic_privs") or "interact,shout")
for priv, _ in pairs(grantprivs) do
if not basic_privs[priv] and
not core.check_player_privs(name, {privs=true}) then
return false, "Your privileges are insufficient."
end
if not core.registered_privileges[priv] then
privs_unknown = privs_unknown .. "Unknown privilege: " .. priv .. "\n"
end
privs[priv] = true
end
if privs_unknown ~= "" then
return false, privs_unknown
end
core.set_player_privs(grantname, privs)
core.log("action", name..' granted ('..core.privs_to_string(grantprivs, ', ')..') privileges to '..grantname)
if grantname ~= name then
core.chat_send_player(grantname, name
.. " granted you privileges: "
.. core.privs_to_string(grantprivs, ' '))
end
return true, "Privileges of " .. grantname .. ": "
.. core.privs_to_string(
core.get_player_privs(grantname), ' ')
end
return handle_grant_command(name, grantname, grantprivstr)
end,
})
core.register_chatcommand("grantme", {
params = "<privilege>|all",
description = "Grant privileges to yourself",
func = function(name, param)
if param == "" then
return false, "Invalid parameters (see /help grantme)"
end
return handle_grant_command(name, name, param)
end,
})
core.register_chatcommand("revoke", {
params = "<name> <privilege>|all",
description = "Remove privilege from player",

View File

@ -41,7 +41,7 @@ core.register_entity(":__builtin:falling_node", {
end,
on_step = function(self, dtime)
-- Set gravity
-- Set gravity
local acceleration = self.object:getacceleration()
if not vector.equals(acceleration, {x = 0, y = -10, z = 0}) then
self.object:setacceleration({x = 0, y = -10, z = 0})
@ -52,10 +52,9 @@ core.register_entity(":__builtin:falling_node", {
local bcn = core.get_node(bcp)
local bcd = core.registered_nodes[bcn.name]
-- Note: walkable is in the node definition, not in item groups
if not bcd or
(bcd.walkable or
if not bcd or bcd.walkable or
(core.get_item_group(self.node.name, "float") ~= 0 and
bcd.liquidtype ~= "none")) then
bcd.liquidtype ~= "none") then
if bcd and bcd.leveled and
bcn.name == self.node.name then
local addlevel = self.node.level
@ -75,20 +74,20 @@ core.register_entity(":__builtin:falling_node", {
local np = {x = bcp.x, y = bcp.y + 1, z = bcp.z}
-- Check what's here
local n2 = core.get_node(np)
local nd = core.registered_nodes[n2.name]
-- If it's not air or liquid, remove node and replace it with
-- it's drops
if n2.name ~= "air" and (not core.registered_nodes[n2.name] or
core.registered_nodes[n2.name].liquidtype == "none") then
if n2.name ~= "air" and (not nd or nd.liquidtype == "none") then
core.remove_node(np)
if core.registered_nodes[n2.name].buildable_to == false then
if nd.buildable_to == false then
-- Add dropped items
local drops = core.get_node_drops(n2.name, "")
for _, dropped_item in ipairs(drops) do
for _, dropped_item in pairs(drops) do
core.add_item(np, dropped_item)
end
end
-- Run script hook
for _, callback in ipairs(core.registered_on_dignodes) do
for _, callback in pairs(core.registered_on_dignodes) do
callback(np, n2)
end
end
@ -116,7 +115,7 @@ end
function drop_attached_node(p)
local nn = core.get_node(p).name
core.remove_node(p)
for _, item in ipairs(core.get_node_drops(nn, "")) do
for _, item in pairs(core.get_node_drops(nn, "")) do
local pos = {
x = p.x + math.random()/2 - 0.25,
y = p.y + math.random()/2 - 0.25,
@ -130,7 +129,11 @@ function check_attached_node(p, n)
local def = core.registered_nodes[n.name]
local d = {x = 0, y = 0, z = 0}
if def.paramtype2 == "wallmounted" then
d = core.wallmounted_to_dir(n.param2)
-- The fallback vector here is in case 'wallmounted to dir' is nil due
-- to voxelmanip placing a wallmounted node without resetting a
-- pre-existing param2 value that is out-of-range for wallmounted.
-- The fallback vector corresponds to param2 = 0.
d = core.wallmounted_to_dir(n.param2) or {x = 0, y = 1, z = 0}
else
d.y = -1
end
@ -152,14 +155,15 @@ function nodeupdate_single(p)
if core.get_item_group(n.name, "falling_node") ~= 0 then
local p_bottom = {x = p.x, y = p.y - 1, z = p.z}
local n_bottom = core.get_node(p_bottom)
local d_bottom = core.registered_nodes[n_bottom.name]
-- Note: walkable is in the node definition, not in item groups
if core.registered_nodes[n_bottom.name] and
if d_bottom and
(core.get_item_group(n.name, "float") == 0 or
core.registered_nodes[n_bottom.name].liquidtype == "none") and
(n.name ~= n_bottom.name or (core.registered_nodes[n_bottom.name].leveled and
d_bottom.liquidtype == "none") and
(n.name ~= n_bottom.name or (d_bottom.leveled and
core.get_node_level(p_bottom) < core.get_node_max_level(p_bottom))) and
(not core.registered_nodes[n_bottom.name].walkable or
core.registered_nodes[n_bottom.name].buildable_to) then
(not d_bottom.walkable or
d_bottom.buildable_to) then
n.level = core.get_node_level(p)
core.remove_node(p)
spawn_falling_node(p, n)

View File

@ -5,6 +5,7 @@ core.forceload_block = nil
core.forceload_free_block = nil
local blocks_forceloaded
local blocks_temploaded = {}
local total_forceloaded = 0
local BLOCKSIZE = core.MAP_BLOCKSIZE
@ -15,32 +16,52 @@ local function get_blockpos(pos)
z = math.floor(pos.z/BLOCKSIZE)}
end
function core.forceload_block(pos)
-- When we create/free a forceload, it's either transient or persistent. We want
-- to add to/remove from the table that corresponds to the type of forceload, but
-- we also need the other table because whether we forceload a block depends on
-- both tables.
-- This function returns the "primary" table we are adding to/removing from, and
-- the other table.
local function get_relevant_tables(transient)
if transient then
return blocks_temploaded, blocks_forceloaded
else
return blocks_forceloaded, blocks_temploaded
end
end
function core.forceload_block(pos, transient)
local blockpos = get_blockpos(pos)
local hash = core.hash_node_position(blockpos)
if blocks_forceloaded[hash] ~= nil then
blocks_forceloaded[hash] = blocks_forceloaded[hash] + 1
local relevant_table, other_table = get_relevant_tables(transient)
if relevant_table[hash] ~= nil then
relevant_table[hash] = relevant_table[hash] + 1
return true
elseif other_table[hash] ~= nil then
relevant_table[hash] = 1
else
if total_forceloaded >= (tonumber(core.setting_get("max_forceloaded_blocks")) or 16) then
return false
end
total_forceloaded = total_forceloaded+1
blocks_forceloaded[hash] = 1
relevant_table[hash] = 1
forceload_block(blockpos)
return true
end
end
function core.forceload_free_block(pos)
function core.forceload_free_block(pos, transient)
local blockpos = get_blockpos(pos)
local hash = core.hash_node_position(blockpos)
if blocks_forceloaded[hash] == nil then return end
if blocks_forceloaded[hash] > 1 then
blocks_forceloaded[hash] = blocks_forceloaded[hash] - 1
local relevant_table, other_table = get_relevant_tables(transient)
if relevant_table[hash] == nil then return end
if relevant_table[hash] > 1 then
relevant_table[hash] = relevant_table[hash] - 1
elseif other_table[hash] ~= nil then
relevant_table[hash] = nil
else
total_forceloaded = total_forceloaded-1
blocks_forceloaded[hash] = nil
relevant_table[hash] = nil
forceload_free_block(blockpos)
end
end

View File

@ -38,7 +38,7 @@ core.register_globalstep(function(dtime)
end)
function core.after(after, func, ...)
assert(tonumber(time) and type(func) == "function",
assert(tonumber(after) and type(func) == "function",
"Invalid core.after invocation")
jobs[#jobs + 1] = {
func = func,

View File

@ -50,7 +50,7 @@ end
function VoxelArea:position(i)
local p = {}
local MinEdge = self.MinEdge
i = i - 1
p.z = math.floor(i / self.zstride) + MinEdge.z
@ -84,23 +84,46 @@ end
function VoxelArea:iter(minx, miny, minz, maxx, maxy, maxz)
local i = self:index(minx, miny, minz) - 1
local last = self:index(maxx, maxy, maxz)
local ystride = self.ystride
local zstride = self.zstride
local yoff = (last+1) % ystride
local zoff = (last+1) % zstride
local ystridediff = (i - last) % ystride
local zstridediff = (i - last) % zstride
local xrange = maxx - minx + 1
local nextaction = i + 1 + xrange
local y = 0
local yrange = maxy - miny + 1
local yreqstride = self.ystride - xrange
local z = 0
local zrange = maxz - minz + 1
local multistride = self.zstride - ((yrange - 1) * self.ystride + xrange)
return function()
-- continue i until it needs to jump
i = i + 1
if i % zstride == zoff then
i = i + zstridediff
elseif i % ystride == yoff then
i = i + ystridediff
end
if i <= last then
if i ~= nextaction then
return i
end
-- continue y until maxy is exceeded
y = y + 1
if y ~= yrange then
-- set i to index(minx, miny + y, minz + z) - 1
i = i + yreqstride
nextaction = i + xrange
return i
end
-- continue z until maxz is exceeded
z = z + 1
if z == zrange then
-- cuboid finished, return nil
return
end
-- set i to index(minx, miny, minz + z) - 1
i = i + multistride
y = 0
nextaction = i + xrange
return i
end
end

View File

@ -16,6 +16,9 @@
--51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
--------------------------------------------------------------------------------
local enabled_all = false
local function modname_valid(name)
return not name:find("[^a-z0-9_]")
end
@ -80,11 +83,15 @@ local function get_formspec(data)
end
end
end
retval = retval ..
"button[8.75,0.125;2.5,0.5;btn_all_mods;" .. fgettext("Enable all") .. "]" ..
"textlist[5.5,0.75;5.75,5.25;world_config_modlist;"
if enabled_all then
retval = retval ..
"button[8.75,0.125;2.5,0.5;btn_disable_all_mods;" .. fgettext("Disable all") .. "]" ..
"textlist[5.5,0.75;5.75,5.25;world_config_modlist;"
else
retval = retval ..
"button[8.75,0.125;2.5,0.5;btn_enable_all_mods;" .. fgettext("Enable all") .. "]" ..
"textlist[5.5,0.75;5.75,5.25;world_config_modlist;"
end
retval = retval .. modmgr.render_modlist(data.list)
retval = retval .. ";" .. data.selected_mod .."]"
@ -229,15 +236,27 @@ local function handle_buttons(this, fields)
return true
end
if fields["btn_all_mods"] then
if fields.btn_enable_all_mods then
local list = this.data.list:get_raw_list()
for i=1,#list,1 do
if list[i].typ ~= "game_mod" and
not list[i].is_modpack then
for i = 1, #list do
if list[i].typ ~= "game_mod" and not list[i].is_modpack then
list[i].enabled = true
end
end
enabled_all = true
return true
end
if fields.btn_disable_all_mods then
local list = this.data.list:get_raw_list()
for i = 1, #list do
if list[i].typ ~= "game_mod" and not list[i].is_modpack then
list[i].enabled = false
end
end
enabled_all = false
return true
end

View File

@ -659,5 +659,12 @@ function create_adv_settings_dlg()
return dlg
end
-- generate minetest.conf.example and settings_translation_file.cpp:
-- Generate minetest.conf.example and settings_translation_file.cpp
-- *** Please note ***
-- There is text in minetest.conf.example that will not be generated from
-- settingtypes.txt but must be preserved:
-- The documentation of mapgen noise parameter formats (title plus 16 lines)
-- Noise parameter 'mgv5_np_ground' in group format (13 lines)
--assert(loadfile(core.get_mainmenu_path()..DIR_DELIM.."generate_from_settingtypes.lua"))(parse_config_file(true, false))

View File

@ -774,6 +774,15 @@ time_speed (Time speed) int 72
# Interval of saving important changes in the world, stated in seconds.
server_map_save_interval (Map save interval) float 5.3
# Set the maximum character length of a chat message sent by clients.
# chat_message_max_size int 500
# Limit a single player to send X messages per 10 seconds.
# chat_message_limit_per_10sec float 10.0
# Kick player if send more than X messages per 10 seconds.
# chat_message_limit_trigger_kick int 50
[**Physics]
movement_acceleration_default (Default acceleration) float 3
@ -808,7 +817,7 @@ max_clearobjects_extra_loaded_blocks (Max. clearobjects extra blocks) int 4096
server_unload_unused_data_timeout (Unload unused server data) int 29
# Maximum number of statically stored objects in a block.
max_objects_per_block (Maximum objects per block) int 49
max_objects_per_block (Maximum objects per block) int 64
# See http://www.sqlite.org/pragma.html#pragma_synchronous
sqlite_synchronous (Synchronous SQLite) enum 2 0,1,2
@ -1152,7 +1161,7 @@ mgvalleys_np_inter_valley_slope (Valley Slope) noise_params 0.5, 0.5, (128, 128,
[*Security]
# Prevent mods from doing insecure things like running shell commands.
secure.enable_security (Enable mod security) bool false
secure.enable_security (Enable mod security) bool true
# Comma-separated list of trusted mods that are allowed to access insecure
# functions even when mod security is on (via request_insecure_environment()).
@ -1216,7 +1225,7 @@ name (Player name) string
# Set the language. Leave empty to use the system language.
# A restart is required after changing this.
language (Language) enum ,be,cs,da,de,eo,es,et,fr,hu,id,it,ja,jbo,ko,ky,lt,nb,nl,pl,pt,pt_BR,ro,ru,tr,uk,zh_CN,zh_TW
language (Language) enum ,be,ca,cs,da,de,en,eo,es,et,fr,he,hu,id,it,ja,jbo,ko,ky,lt,nb,nl,pl,pt,pt_BR,ro,ru,sr_Cyrl,tr,uk,zh_CN,zh_TW
# Level of logging to be written to debug.txt:
# - <nothing> (no logging)

View File

@ -194,24 +194,15 @@ void main(void)
vec4 col = vec4(color.rgb * gl_Color.rgb, 1.0);
#if MATERIAL_TYPE == TILE_MATERIAL_LIQUID_TRANSPARENT
float alpha = gl_Color.a;
if (fogDistance != 0.0) {
float d = max(0.0, min(vPosition.z / fogDistance * 1.5 - 0.6, 1.0));
alpha = mix(alpha, 0.0, d);
}
col = vec4(col.rgb, alpha);
#else
if (fogDistance != 0.0) {
float d = max(0.0, min(vPosition.z / fogDistance * 1.5 - 0.6, 1.0));
col = mix(col, skyBgColor, d);
}
col = vec4(col.rgb, base.a);
#ifdef ENABLE_TONE_MAPPING
col = applyToneMapping(col);
#endif
#ifdef ENABLE_TONE_MAPPING
gl_FragColor = applyToneMapping(col);
#else
if (fogDistance != 0.0) {
float d = clamp((fogDistance - length(eyeVec)) / (fogDistance * 0.6), 0.0, 1.0);
col = mix(skyBgColor, col, d);
}
col = vec4(col.rgb, base.a);
gl_FragColor = col;
#endif
}

View File

@ -150,24 +150,15 @@ vec4 base = texture2D(baseTexture, uv).rgba;
vec4 col = vec4(color.rgb * gl_Color.rgb, 1.0);
#if MATERIAL_TYPE == TILE_MATERIAL_LIQUID_TRANSPARENT || MATERIAL_TYPE == TILE_MATERIAL_LIQUID_OPAQUE
float alpha = gl_Color.a;
if (fogDistance != 0.0) {
float d = max(0.0, min(vPosition.z / fogDistance * 1.5 - 0.6, 1.0));
alpha = mix(alpha, 0.0, d);
}
col = vec4(col.rgb, alpha);
#else
if (fogDistance != 0.0) {
float d = max(0.0, min(vPosition.z / fogDistance * 1.5 - 0.6, 1.0));
col = mix(col, skyBgColor, d);
}
col = vec4(col.rgb, base.a);
#ifdef ENABLE_TONE_MAPPING
col = applyToneMapping(col);
#endif
#ifdef ENABLE_TONE_MAPPING
gl_FragColor = applyToneMapping(col);
#else
if (fogDistance != 0.0) {
float d = clamp((fogDistance - length(eyeVec)) / (fogDistance * 0.6), 0.0, 1.0);
col = mix(skyBgColor, col, d);
}
col = vec4(col.rgb, base.a);
gl_FragColor = col;
#endif
}

View File

@ -107,8 +107,8 @@ void main(void)
vec4 col = vec4(color.rgb, base.a);
col *= gl_Color;
if (fogDistance != 0.0) {
float d = max(0.0, min(vPosition.z / fogDistance * 1.5 - 0.6, 1.0));
col = mix(col, skyBgColor, d);
float d = clamp((fogDistance - length(eyeVec)) / (fogDistance * 0.6), 0.0, 1.0);
col = mix(skyBgColor, col, d);
}
gl_FragColor = vec4(col.rgb, base.a);
}

View File

@ -1471,6 +1471,15 @@ examples.
* `fixed_size`: `true`/`false` (optional)
* deprecated: `invsize[<W>,<H>;]`
#### `container[<X>,<Y>]`
* Start of a container block, moves all physical elements in the container by (X, Y)
* Must have matching container_end
* Containers can be nested, in which case the offsets are added
(child containers are relative to parent containers)
#### `container_end[]`
* End of a container, following elements are no longer relative to this container
#### `list[<inventory location>;<list name>;<X>,<Y>;<W>,<H>;]`
* Show an inventory list
@ -1535,7 +1544,7 @@ examples.
* If `true` the background is clipped to formspec size
(`x` and `y` are used as offset values, `w` and `h` are ignored)
#### `pwdfield[<X>,<Y>;<W>,<H>;<name>;<label>;<close_on_enter>]`
#### `pwdfield[<X>,<Y>;<W>,<H>;<name>;<label>]`
* Textual password style field; will be sent to server when a button is clicked
* When enter is pressed in field, fields.key_enter_field will be sent with the name
of this field.
@ -1545,10 +1554,9 @@ examples.
* Position and size units are inventory slots
* `name` is the name of the field as returned in fields to `on_receive_fields`
* `label`, if not blank, will be text printed on the top left above the field
* `close_on_enter` (optional) is whether the form should accept and close when enter is
pressed in this field. Defaults to true.
* See field_close_on_enter to stop enter closing the formspec
#### `field[<X>,<Y>;<W>,<H>;<name>;<label>;<default>;<close_on_enter>]`
#### `field[<X>,<Y>;<W>,<H>;<name>;<label>;<default>]`
* Textual field; will be sent to server when a button is clicked
* When enter is pressed in field, fields.key_enter_field will be sent with the name
of this field.
@ -1562,18 +1570,21 @@ examples.
* `default` may contain variable references such as `${text}'` which
will fill the value from the metadata value `text`
* **Note**: no extra text or more than a single variable is supported ATM.
* `close_on_enter` (optional) is whether the form should accept and close when enter is
pressed in this field. Defaults to true.
* See field_close_on_enter to stop enter closing the formspec
#### `field[<name>;<label>;<default>;<close_on_enter>]`
#### `field[<name>;<label>;<default>]`
* As above, but without position/size units
* When enter is pressed in field, fields.key_enter_field will be sent with the name
of this field.
* Special field for creating simple forms, such as sign text input
* Must be used without a `size[]` element
* A "Proceed" button will be added automatically
* `close_on_enter` (optional) is whether the form should accept and close when enter is
pressed in this field. Defaults to true.
* See field_close_on_enter to stop enter closing the formspec
#### `field_close_on_enter[<name>;<close_on_enter>]`
* <name> is the name of the field
* if <close_on_enter> is false, pressing enter in the field will submit the form but not close it
* defaults to true when not specified (ie: no tag for a field)
#### `textarea[<X>,<Y>;<W>,<H>;<name>;<label>;<default>]`
* Same as fields above, but with multi-line input
@ -1803,7 +1814,8 @@ Spatial Vectors
* `vector.distance(p1, p2)`: returns a number
* `vector.length(v)`: returns a number
* `vector.normalize(v)`: returns a vector
* `vector.round(v)`: returns a vector, each dimension rounded to floor
* `vector.floor(v)`: returns a vector, each dimension rounded down
* `vector.round(v)`: returns a vector, each dimension rounded to nearest int
* `vector.apply(v, func)`: returns a vector
* `vector.equals(v1, v2)`: returns a boolean
@ -1928,13 +1940,14 @@ Call these functions only at load time!
* Warning! The type field ("shaped","cooking" or any other) will be ignored if the recipe
contains output. Erasing is then done independently from the crafting method.
* `minetest.register_ore(ore definition)`
* `minetest.register_biome(biome definition)`
* `minetest.register_decoration(decoration definition)`
* `minetest.override_item(name, redefinition)`
* Overrides fields of an item registered with register_node/tool/craftitem.
* Note: Item must already be defined, (opt)depend on the mod defining it.
* Example: `minetest.override_item("default:mese", {light_source=LIGHT_MAX})`
* `minetest.clear_registered_ores()`
* `minetest.clear_registered_biomes()`
* `minetest.clear_registered_decorations()`
### Global callback registration functions
@ -2191,13 +2204,14 @@ and `minetest.auth_reload` call the authetification handler.
* `minetest.get_mapgen_setting_noiseparams(name)`
* Same as above, but returns the value as a NoiseParams table if the setting `name` exists
and is a valid NoiseParams
* `minetest.set_mapgen_setting(name, value, [override_meta=false])`
* `minetest.set_mapgen_setting(name, value, [override_meta])`
* Sets a mapgen param to `value`, and will take effect if the corresponding mapgen setting
is not already present in map_meta.txt. If the optional boolean override_meta is set to true,
this setting will become the active setting regardless of the map metafile contents.
is not already present in map_meta.txt.
* `override_meta` is an optional boolean (default: `false`). If this is set to true,
the setting will become the active setting regardless of the map metafile contents.
* Note: to set the seed, use "seed", not "fixed_map_seed"
* `minetest.set_mapgen_setting_noiseparams(name, value, [override_meta=false])`
* Same as above, except value is a NoiseParams table
* `minetest.set_mapgen_setting_noiseparams(name, value, [override_meta])`
* Same as above, except value is a NoiseParams table.
* `minetest.set_noiseparams(name, noiseparams, set_default)`
* Sets the noiseparams setting of `name` to the noiseparams table specified in `noiseparams`.
* `set_default` is an optional boolean (default: `true`) that specifies whether the setting
@ -2263,6 +2277,11 @@ and `minetest.auth_reload` call the authetification handler.
* increase level of leveled node by level, default `level` equals `1`
* if `totallevel > maxlevel`, returns rest (`total-max`)
* can be negative for decreasing
* `nodeupdate_single(pos)`
* causes an unsupported `group:falling_node` node to fall and causes an
unattached `group:attached_node` node to fall.
* does not spread these updates to neighbours
* a helper function, not officially part of the API, but useful
### Inventory
`minetest.get_inventory(location)`: returns an `InvRef`
@ -2619,13 +2638,17 @@ These functions return the leftover itemstack.
the creative mode setting, and checks for "sneak" to set the `invert_wall`
parameter.
* `minetest.forceload_block(pos)`
* `minetest.forceload_block(pos[, transient])`
* forceloads the position `pos`.
* returns `true` if area could be forceloaded
* Please note that forceloaded areas are saved when the server restarts.
* If `transient` is `false` or absent, the forceload will be persistent
(saved between server runs). If `true`, the forceload will be transient
(not saved between server runs).
* `minetest.forceload_free_block(pos)`
* `minetest.forceload_free_block(pos[, transient])`
* stops forceloading the position `pos`
* If `transient` is `false` or absent, frees a persistent forceload.
If `true`, frees a transient forceload.
* `minetest.request_insecure_environment()`: returns an environment containing
insecure functions if the calling mod has been listed as trusted in the
@ -2951,13 +2974,11 @@ an itemstring, a table or `nil`.
#### Methods
* `is_empty()`: Returns `true` if stack is empty.
* `get_name()`: Returns item name (e.g. `"default:stone"`).
* `set_name(item_name)`: Returns boolean success.
Clears item on failure.
* `set_name(item_name)`: Returns boolean whether item was cleared
* `get_count()`: Returns number of items on the stack.
* `set_count(count)`
* `set_count(count)`: Returns boolean whether item was cleared
* `get_wear()`: Returns tool wear (`0`-`65535`), `0` for non-tools.
* `set_wear(wear)`: Returns boolean success.
Clears item on failure.
* `set_wear(wear)`: Returns boolean whether item was cleared
* `get_metadata()`: Returns metadata (a string attached to an item stack).
* `set_metadata(metadata)`: Returns true.
* `clear()`: removes all items from the stack, making it empty.
@ -3578,15 +3599,18 @@ Definition tables
on_place = func(itemstack, placer, pointed_thing),
--[[
^ Shall place item and return the leftover itemstack
^ The placer may be any ObjectRef or nil.
^ default: minetest.item_place ]]
on_secondary_use = func(itemstack, user, pointed_thing),
--[[
^ Same as on_place but called when pointing at nothing.
^ The user may be any ObjectRef or nil.
^ pointed_thing : always { type = "nothing" }
]]
on_drop = func(itemstack, dropper, pos),
--[[
^ Shall drop item and return the leftover itemstack
^ The dropper may be any ObjectRef or nil.
^ default: minetest.item_drop ]]
on_use = func(itemstack, user, pointed_thing),
--[[
@ -3595,6 +3619,7 @@ Definition tables
inventory, or an itemstack to replace the original itemstack.
e.g. itemstack:take_item(); return itemstack
^ Otherwise, the function is free to do what it wants.
^ The user may be any ObjectRef or nil.
^ The default functions handle regular use cases.
]]
after_use = func(itemstack, user, node, digparams),
@ -3607,6 +3632,7 @@ Definition tables
itemstack:add_wear(digparams.wear)
return itemstack
end
^ The user may be any ObjectRef or nil.
]]
}
@ -4105,7 +4131,7 @@ The Biome API is still in an experimental phase and subject to change.
collision_removal = false,
-- ^ collision_removal: if true then particle is removed when it collides,
-- ^ requires collisiondetection = true to have any effect
attached = ObjectRef,
attached = ObjectRef,
-- ^ attached: if defined, makes particle positions relative to this object.
vertical = false,
-- ^ vertical: if true faces player using y axis only

View File

@ -933,6 +933,18 @@
# type: float
# server_map_save_interval = 5.3
# Set the maximum character length of a chat message sent by clients. (0 to disable)
# type: integer
# chat_message_max_size = 500
# Limit a single player to send X messages per 10 seconds. (0 to disable)
# type: float
# chat_message_limit_per_10sec = 8.0
# Kick player if send more than X messages per 10 seconds. (0 to disable)
# type: integer
# chat_message_limit_trigger_kick = 50
### Physics
# type: float
@ -996,7 +1008,7 @@
# Maximum number of statically stored objects in a block.
# type: int
# max_objects_per_block = 49
# max_objects_per_block = 64
# See http://www.sqlite.org/pragma.html#pragma_synchronous
# type: enum values: 0, 1, 2
@ -1099,6 +1111,25 @@
# type: int
# num_emerge_threads = 1
#### Noise parameters and formats
# Noise parameters can be specified as a set of positional values, for example:
# Offset, scale, (spread factors), seed offset, number of octaves, persistence, lacunarity
# mgv6_np_terrain_base = -4, 20, (250, 250, 250), 82341, 5, 0.6, 2.0
# Or the group format can be used instead, for example:
# mgv6_np_terrain_base = {
# offset = -4,
# scale = 20,
# spread = (250, 250, 250),
# seed = 82341,
# octaves = 5,
# persistence = 0.6,
# lacunarity = 2.0,
# 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 below.
# Noise parameters for biome API temperature, humidity and biome blend.
# type: noise_params
# mg_biome_np_heat = 50, 50, (750, 750, 750), 5349, 3, 0.5, 2.0
@ -1133,6 +1164,20 @@
# type: noise_params
# mgv5_np_cave2 = 0, 12, (50, 50, 50), 10325, 4, 0.5, 2.0
# Noise parameters in group format, unsupported by advanced settings
# menu but settable in minetest.conf.
# See documentation of noise parameter formats above.
# mgv5_np_ground = {
# offset = 0,
# scale = 40,
# spread = (80, 80, 80),
# seed = 983240,
# octaves = 4,
# persistence = 0.55,
# lacunarity = 2.0,
# flags = "eased"
# }
#### Mapgen v6
# Map generation attributes specific to Mapgen v6.
@ -1462,7 +1507,7 @@
# Prevent mods from doing insecure things like running shell commands.
# type: bool
# secure.enable_security = false
# secure.enable_security = true
# Comma-separated list of trusted mods that are allowed to access insecure
# functions even when mod security is on (via request_insecure_environment()).
@ -1490,7 +1535,7 @@
# profiler.default_report_format = txt
# The file path relative to your worldpath in which profiles will be saved to.
#
#
# type: string
# profiler.report_path = ""
@ -1543,7 +1588,7 @@
# Set the language. Leave empty to use the system language.
# A restart is required after changing this.
# type: enum values: , be, cs, da, de, eo, es, et, fr, hu, id, it, ja, jbo, ko, ky, lt, nb, nl, pl, pt, pt_BR, ro, ru, tr, uk, zh_CN, zh_TW
# type: enum values: , be, ca, cs, da, de, en, eo, es, et, fr, he, hu, id, it, ja, jbo, ko, ky, lt, nb, nl, pl, pt, pt_BR, ro, ru, sr_Cyrl, tr, uk, zh_CN, zh_TW
# language =
# Level of logging to be written to debug.txt:

View File

@ -445,6 +445,7 @@ set(common_SRCS
porting.cpp
profiler.cpp
quicktune.cpp
remoteplayer.cpp
rollback.cpp
rollback_interface.cpp
serialization.cpp
@ -539,6 +540,7 @@ set(client_SRCS
sky.cpp
wieldmesh.cpp
${client_SCRIPT_SRCS}
${UNITTEST_CLIENT_SRCS}
)
list(SORT client_SRCS)
@ -725,7 +727,7 @@ else()
set(OTHER_FLAGS "${OTHER_FLAGS} -Wsign-compare")
endif()
if(NOT ZLIBWAPI_DLL AND CMAKE_SIZEOF_VOID_P EQUAL 4)
if(WIN32 AND NOT ZLIBWAPI_DLL AND CMAKE_SIZEOF_VOID_P EQUAL 4)
set(OTHER_FLAGS "${OTHER_FLAGS} -DWIN32_NO_ZLIB_WINAPI")
message(WARNING "Defaulting to cdecl for zlib on win32 because ZLIBWAPI_DLL"
" isn't set, ensure that ZLIBWAPI_DLL is set if you want stdcall.")

View File

@ -552,7 +552,7 @@ void Camera::drawNametags()
// shadow can remain.
continue;
}
v3f pos = nametag->parent_node->getPosition() + v3f(0.0, 1.1 * BS, 0.0);
v3f pos = nametag->parent_node->getAbsolutePosition() + v3f(0.0, 1.1 * BS, 0.0);
f32 transformed_pos[4] = { pos.X, pos.Y, pos.Z, 1.0f };
trans.multiplyWith1x4Matrix(transformed_pos);
if (transformed_pos[3] > 0) {

View File

@ -260,7 +260,7 @@ Client::Client(
m_localdb(NULL)
{
// Add local player
m_env.addPlayer(new LocalPlayer(this, playername));
m_env.setLocalPlayer(new LocalPlayer(this, playername));
m_mapper = new Mapper(device, this);
m_cache_save_interval = g_settings->getU16("server_map_save_interval");
@ -309,7 +309,7 @@ Client::~Client()
delete m_inventory_from_server;
// Delete detached inventories
for (std::map<std::string, Inventory*>::iterator
for (UNORDERED_MAP<std::string, Inventory*>::iterator
i = m_detached_inventories.begin();
i != m_detached_inventories.end(); ++i) {
delete i->second;
@ -389,7 +389,7 @@ void Client::step(float dtime)
if(counter <= 0.0) {
counter = 2.0;
Player *myplayer = m_env.getLocalPlayer();
LocalPlayer *myplayer = m_env.getLocalPlayer();
FATAL_ERROR_IF(myplayer == NULL, "Local player not found in environment.");
u16 proto_version_min = g_settings->getFlag("send_pre_v25_init") ?
@ -624,7 +624,7 @@ void Client::step(float dtime)
{
// Do this every <interval> seconds after TOCLIENT_INVENTORY
// Reset the locally changed inventory to the authoritative inventory
Player *player = m_env.getLocalPlayer();
LocalPlayer *player = m_env.getLocalPlayer();
player->inventory = *m_inventory_from_server;
m_inventory_updated = true;
}
@ -634,10 +634,8 @@ void Client::step(float dtime)
Update positions of sounds attached to objects
*/
{
for(std::map<int, u16>::iterator
i = m_sounds_to_objects.begin();
i != m_sounds_to_objects.end(); ++i)
{
for(UNORDERED_MAP<int, u16>::iterator i = m_sounds_to_objects.begin();
i != m_sounds_to_objects.end(); ++i) {
int client_id = i->first;
u16 object_id = i->second;
ClientActiveObject *cao = m_env.getActiveObject(object_id);
@ -656,8 +654,7 @@ void Client::step(float dtime)
m_removed_sounds_check_timer = 0;
// Find removed sounds and clear references to them
std::vector<s32> removed_server_ids;
for(std::map<s32, int>::iterator
i = m_sounds_server_to_client.begin();
for(UNORDERED_MAP<s32, int>::iterator i = m_sounds_server_to_client.begin();
i != m_sounds_server_to_client.end();) {
s32 server_id = i->first;
int client_id = i->second;
@ -1205,7 +1202,7 @@ void Client::sendChatMessage(const std::wstring &message)
void Client::sendChangePassword(const std::string &oldpassword,
const std::string &newpassword)
{
Player *player = m_env.getLocalPlayer();
LocalPlayer *player = m_env.getLocalPlayer();
if (player == NULL)
return;
@ -1331,7 +1328,7 @@ void Client::sendPlayerPos()
void Client::sendPlayerItem(u16 item)
{
Player *myplayer = m_env.getLocalPlayer();
LocalPlayer *myplayer = m_env.getLocalPlayer();
if(myplayer == NULL)
return;
@ -1412,7 +1409,7 @@ bool Client::getLocalInventoryUpdated()
// Copies the inventory of the local player to parameter
void Client::getLocalInventory(Inventory &dst)
{
Player *player = m_env.getLocalPlayer();
LocalPlayer *player = m_env.getLocalPlayer();
assert(player != NULL);
dst = player->inventory;
}
@ -1425,15 +1422,16 @@ Inventory* Client::getInventory(const InventoryLocation &loc)
break;
case InventoryLocation::CURRENT_PLAYER:
{
Player *player = m_env.getLocalPlayer();
LocalPlayer *player = m_env.getLocalPlayer();
assert(player != NULL);
return &player->inventory;
}
break;
case InventoryLocation::PLAYER:
{
Player *player = m_env.getPlayer(loc.name.c_str());
if(!player)
// Check if we are working with local player inventory
LocalPlayer *player = m_env.getLocalPlayer();
if (!player || strcmp(player->getName(), loc.name.c_str()) != 0)
return NULL;
return &player->inventory;
}
@ -1448,7 +1446,7 @@ Inventory* Client::getInventory(const InventoryLocation &loc)
break;
case InventoryLocation::DETACHED:
{
if(m_detached_inventories.count(loc.name) == 0)
if (m_detached_inventories.count(loc.name) == 0)
return NULL;
return m_detached_inventories[loc.name];
}
@ -1514,11 +1512,6 @@ ClientActiveObject * Client::getSelectedActiveObject(
return NULL;
}
std::list<std::string> Client::getConnectedPlayerNames()
{
return m_env.getPlayerNames();
}
float Client::getAnimationTime()
{
return m_animation_time;
@ -1551,18 +1544,11 @@ void Client::setCrack(int level, v3s16 pos)
u16 Client::getHP()
{
Player *player = m_env.getLocalPlayer();
LocalPlayer *player = m_env.getLocalPlayer();
assert(player != NULL);
return player->hp;
}
u16 Client::getBreath()
{
Player *player = m_env.getLocalPlayer();
assert(player != NULL);
return player->getBreath();
}
bool Client::getChatMessage(std::wstring &message)
{
if(m_chat_queue.size() == 0)
@ -1685,7 +1671,7 @@ void Client::addUpdateMeshTaskForNode(v3s16 nodepos, bool ack_to_server, bool ur
ClientEvent Client::getClientEvent()
{
ClientEvent event;
if(m_client_event_queue.size() == 0) {
if (m_client_event_queue.empty()) {
event.type = CE_NONE;
}
else {

View File

@ -203,7 +203,7 @@ struct ClientEvent
f32 maxsize;
bool collisiondetection;
bool collision_removal;
s32 attached_id;
u16 attached_id;
bool vertical;
std::string *texture;
u32 id;
@ -456,7 +456,10 @@ public:
core::line3d<f32> shootline_on_map
);
std::list<std::string> getConnectedPlayerNames();
const std::list<std::string> &getConnectedPlayerNames()
{
return m_env.getPlayerNames();
}
float getAnimationTime();
@ -464,9 +467,8 @@ public:
void setCrack(int level, v3s16 pos);
u16 getHP();
u16 getBreath();
bool checkPrivilege(const std::string &priv)
bool checkPrivilege(const std::string &priv) const
{ return (m_privileges.count(priv) != 0); }
bool getChatMessage(std::wstring &message);
@ -668,18 +670,18 @@ private:
// Sounds
float m_removed_sounds_check_timer;
// Mapping from server sound ids to our sound ids
std::map<s32, int> m_sounds_server_to_client;
UNORDERED_MAP<s32, int> m_sounds_server_to_client;
// And the other way!
std::map<int, s32> m_sounds_client_to_server;
UNORDERED_MAP<int, s32> m_sounds_client_to_server;
// And relations to objects
std::map<int, u16> m_sounds_to_objects;
UNORDERED_MAP<int, u16> m_sounds_to_objects;
// Privileges
std::set<std::string> m_privileges;
UNORDERED_SET<std::string> m_privileges;
// Detached inventories
// key = name
std::map<std::string, Inventory*> m_detached_inventories;
UNORDERED_MAP<std::string, Inventory*> m_detached_inventories;
// Storage for mesh data for creating multiple instances of the same mesh
StringMap m_mesh_data;

View File

@ -22,7 +22,7 @@ with this program; if not, write to the Free Software Foundation, Inc.,
#include "clientiface.h"
#include "util/numeric.h"
#include "util/mathconstants.h"
#include "player.h"
#include "remoteplayer.h"
#include "settings.h"
#include "mapblock.h"
#include "network/connection.h"
@ -77,9 +77,9 @@ void RemoteClient::GetNextBlocks (
if(m_nothing_to_send_pause_timer >= 0)
return;
Player *player = env->getPlayer(peer_id);
RemotePlayer *player = env->getPlayer(peer_id);
// This can happen sometimes; clients and players are not in perfect sync.
if(player == NULL)
if (player == NULL)
return;
// Won't send anything if already sending
@ -605,11 +605,8 @@ ClientInterface::~ClientInterface()
{
MutexAutoLock clientslock(m_clients_mutex);
for(std::map<u16, RemoteClient*>::iterator
i = m_clients.begin();
i != m_clients.end(); ++i)
{
for (UNORDERED_MAP<u16, RemoteClient*>::iterator i = m_clients.begin();
i != m_clients.end(); ++i) {
// Delete client
delete i->second;
}
@ -621,10 +618,8 @@ std::vector<u16> ClientInterface::getClientIDs(ClientState min_state)
std::vector<u16> reply;
MutexAutoLock clientslock(m_clients_mutex);
for(std::map<u16, RemoteClient*>::iterator
i = m_clients.begin();
i != m_clients.end(); ++i)
{
for(UNORDERED_MAP<u16, RemoteClient*>::iterator i = m_clients.begin();
i != m_clients.end(); ++i) {
if (i->second->getState() >= min_state)
reply.push_back(i->second->peer_id);
}
@ -632,12 +627,6 @@ std::vector<u16> ClientInterface::getClientIDs(ClientState min_state)
return reply;
}
std::vector<std::string> ClientInterface::getPlayerNames()
{
return m_clients_names;
}
void ClientInterface::step(float dtime)
{
m_print_info_timer += dtime;
@ -650,8 +639,7 @@ void ClientInterface::step(float dtime)
void ClientInterface::UpdatePlayerList()
{
if (m_env != NULL)
{
if (m_env != NULL) {
std::vector<u16> clients = getClientIDs();
m_clients_names.clear();
@ -659,10 +647,8 @@ void ClientInterface::UpdatePlayerList()
if(!clients.empty())
infostream<<"Players:"<<std::endl;
for(std::vector<u16>::iterator
i = clients.begin();
i != clients.end(); ++i) {
Player *player = m_env->getPlayer(*i);
for (std::vector<u16>::iterator i = clients.begin(); i != clients.end(); ++i) {
RemotePlayer *player = m_env->getPlayer(*i);
if (player == NULL)
continue;
@ -691,8 +677,7 @@ void ClientInterface::sendToAll(u16 channelnum,
NetworkPacket* pkt, bool reliable)
{
MutexAutoLock clientslock(m_clients_mutex);
for(std::map<u16, RemoteClient*>::iterator
i = m_clients.begin();
for(UNORDERED_MAP<u16, RemoteClient*>::iterator i = m_clients.begin();
i != m_clients.end(); ++i) {
RemoteClient *client = i->second;
@ -705,11 +690,10 @@ void ClientInterface::sendToAll(u16 channelnum,
RemoteClient* ClientInterface::getClientNoEx(u16 peer_id, ClientState state_min)
{
MutexAutoLock clientslock(m_clients_mutex);
std::map<u16, RemoteClient*>::iterator n;
n = m_clients.find(peer_id);
UNORDERED_MAP<u16, RemoteClient*>::iterator n = m_clients.find(peer_id);
// The client may not exist; clients are immediately removed if their
// access is denied, and this event occurs later then.
if(n == m_clients.end())
if (n == m_clients.end())
return NULL;
if (n->second->getState() >= state_min)
@ -720,11 +704,10 @@ RemoteClient* ClientInterface::getClientNoEx(u16 peer_id, ClientState state_min)
RemoteClient* ClientInterface::lockedGetClientNoEx(u16 peer_id, ClientState state_min)
{
std::map<u16, RemoteClient*>::iterator n;
n = m_clients.find(peer_id);
UNORDERED_MAP<u16, RemoteClient*>::iterator n = m_clients.find(peer_id);
// The client may not exist; clients are immediately removed if their
// access is denied, and this event occurs later then.
if(n == m_clients.end())
if (n == m_clients.end())
return NULL;
if (n->second->getState() >= state_min)
@ -736,11 +719,10 @@ RemoteClient* ClientInterface::lockedGetClientNoEx(u16 peer_id, ClientState stat
ClientState ClientInterface::getClientState(u16 peer_id)
{
MutexAutoLock clientslock(m_clients_mutex);
std::map<u16, RemoteClient*>::iterator n;
n = m_clients.find(peer_id);
UNORDERED_MAP<u16, RemoteClient*>::iterator n = m_clients.find(peer_id);
// The client may not exist; clients are immediately removed if their
// access is denied, and this event occurs later then.
if(n == m_clients.end())
if (n == m_clients.end())
return CS_Invalid;
return n->second->getState();
@ -749,11 +731,10 @@ ClientState ClientInterface::getClientState(u16 peer_id)
void ClientInterface::setPlayerName(u16 peer_id,std::string name)
{
MutexAutoLock clientslock(m_clients_mutex);
std::map<u16, RemoteClient*>::iterator n;
n = m_clients.find(peer_id);
UNORDERED_MAP<u16, RemoteClient*>::iterator n = m_clients.find(peer_id);
// The client may not exist; clients are immediately removed if their
// access is denied, and this event occurs later then.
if(n != m_clients.end())
if (n != m_clients.end())
n->second->setName(name);
}
@ -762,11 +743,10 @@ void ClientInterface::DeleteClient(u16 peer_id)
MutexAutoLock conlock(m_clients_mutex);
// Error check
std::map<u16, RemoteClient*>::iterator n;
n = m_clients.find(peer_id);
UNORDERED_MAP<u16, RemoteClient*>::iterator n = m_clients.find(peer_id);
// The client may not exist; clients are immediately removed if their
// access is denied, and this event occurs later then.
if(n == m_clients.end())
if (n == m_clients.end())
return;
/*
@ -797,10 +777,9 @@ void ClientInterface::CreateClient(u16 peer_id)
MutexAutoLock conlock(m_clients_mutex);
// Error check
std::map<u16, RemoteClient*>::iterator n;
n = m_clients.find(peer_id);
UNORDERED_MAP<u16, RemoteClient*>::iterator n = m_clients.find(peer_id);
// The client shouldn't already exist
if(n != m_clients.end()) return;
if (n != m_clients.end()) return;
// Create client
RemoteClient *client = new RemoteClient();
@ -814,8 +793,7 @@ void ClientInterface::event(u16 peer_id, ClientStateEvent event)
MutexAutoLock clientlock(m_clients_mutex);
// Error check
std::map<u16, RemoteClient*>::iterator n;
n = m_clients.find(peer_id);
UNORDERED_MAP<u16, RemoteClient*>::iterator n = m_clients.find(peer_id);
// No client to deliver event
if (n == m_clients.end())
@ -836,8 +814,7 @@ u16 ClientInterface::getProtocolVersion(u16 peer_id)
MutexAutoLock conlock(m_clients_mutex);
// Error check
std::map<u16, RemoteClient*>::iterator n;
n = m_clients.find(peer_id);
UNORDERED_MAP<u16, RemoteClient*>::iterator n = m_clients.find(peer_id);
// No client to get version
if (n == m_clients.end())
@ -851,8 +828,7 @@ void ClientInterface::setClientVersion(u16 peer_id, u8 major, u8 minor, u8 patch
MutexAutoLock conlock(m_clients_mutex);
// Error check
std::map<u16, RemoteClient*>::iterator n;
n = m_clients.find(peer_id);
UNORDERED_MAP<u16, RemoteClient*>::iterator n = m_clients.find(peer_id);
// No client to set versions
if (n == m_clients.end())

View File

@ -25,10 +25,10 @@ with this program; if not, write to the Free Software Foundation, Inc.,
#include "serialization.h" // for SER_FMT_VER_INVALID
#include "threading/mutex.h"
#include "network/networkpacket.h"
#include "util/cpp11_container.h"
#include <list>
#include <vector>
#include <map>
#include <set>
class MapBlock;
@ -453,7 +453,7 @@ public:
std::vector<u16> getClientIDs(ClientState min_state=CS_Active);
/* get list of client player names */
std::vector<std::string> getPlayerNames();
const std::vector<std::string> &getPlayerNames() const { return m_clients_names; }
/* send message to client */
void send(u16 peer_id, u8 channelnum, NetworkPacket* pkt, bool reliable);
@ -502,8 +502,7 @@ protected:
void lock() { m_clients_mutex.lock(); }
void unlock() { m_clients_mutex.unlock(); }
std::map<u16, RemoteClient*>& getClientList()
{ return m_clients; }
UNORDERED_MAP<u16, RemoteClient*>& getClientList() { return m_clients; }
private:
/* update internal player list */
@ -513,7 +512,7 @@ private:
con::Connection* m_con;
Mutex m_clients_mutex;
// Connected clients (behind the con mutex)
std::map<u16, RemoteClient*> m_clients;
UNORDERED_MAP<u16, RemoteClient*> m_clients;
std::vector<std::string> m_clients_names; //for announcing masterserver
// Environment

View File

@ -43,12 +43,11 @@ ClientActiveObject* ClientActiveObject::create(ActiveObjectType type,
IGameDef *gamedef, ClientEnvironment *env)
{
// Find factory function
std::map<u16, Factory>::iterator n;
n = m_types.find(type);
UNORDERED_MAP<u16, Factory>::iterator n = m_types.find(type);
if(n == m_types.end()) {
// If factory is not found, just return.
warningstream<<"ClientActiveObject: No factory for type="
<<(int)type<<std::endl;
warningstream << "ClientActiveObject: No factory for type="
<< (int)type << std::endl;
return NULL;
}
@ -59,8 +58,7 @@ ClientActiveObject* ClientActiveObject::create(ActiveObjectType type,
void ClientActiveObject::registerType(u16 type, Factory f)
{
std::map<u16, Factory>::iterator n;
n = m_types.find(type);
UNORDERED_MAP<u16, Factory>::iterator n = m_types.find(type);
if(n != m_types.end())
return;
m_types[type] = f;

View File

@ -23,6 +23,7 @@ with this program; if not, write to the Free Software Foundation, Inc.,
#include "irrlichttypes_extrabloated.h"
#include "activeobject.h"
#include <map>
#include "util/cpp11_container.h"
/*
@ -103,7 +104,7 @@ protected:
ClientEnvironment *m_env;
private:
// Used for creating objects based on type
static std::map<u16, Factory> m_types;
static UNORDERED_MAP<u16, Factory> m_types;
};
struct DistanceSortedActiveObject

View File

@ -51,7 +51,7 @@ struct ToolCapabilities;
#define PP(x) "("<<(x).X<<","<<(x).Y<<","<<(x).Z<<")"
std::map<u16, ClientActiveObject::Factory> ClientActiveObject::m_types;
UNORDERED_MAP<u16, ClientActiveObject::Factory> ClientActiveObject::m_types;
SmoothTranslator::SmoothTranslator():
vect_old(0,0,0),
@ -566,7 +566,7 @@ GenericCAO::GenericCAO(IGameDef *gamedef, ClientEnvironment *env):
m_animation_speed(15),
m_animation_blend(0),
m_animation_loop(true),
m_bone_position(std::map<std::string, core::vector2d<v3f> >()),
m_bone_position(UNORDERED_MAP<std::string, core::vector2d<v3f> >()),
m_attachment_bone(""),
m_attachment_position(v3f(0,0,0)),
m_attachment_rotation(v3f(0,0,0)),
@ -613,13 +613,28 @@ bool GenericCAO::collideWithObjects()
void GenericCAO::initialize(const std::string &data)
{
infostream<<"GenericCAO: Got init data"<<std::endl;
processInitData(data);
if (m_is_player) {
// Check if it's the current player
LocalPlayer *player = m_env->getLocalPlayer();
if (player && strcmp(player->getName(), m_name.c_str()) == 0) {
m_is_local_player = true;
m_is_visible = false;
player->setCAO(this);
}
m_env->addPlayerName(m_name.c_str());
}
}
void GenericCAO::processInitData(const std::string &data)
{
std::istringstream is(data, std::ios::binary);
int num_messages = 0;
// version
u8 version = readU8(is);
// check version
if(version == 1) // In PROTOCOL_VERSION 14
{
if (version == 1) { // In PROTOCOL_VERSION 14
m_name = deSerializeString(is);
m_is_player = readU8(is);
m_id = readS16(is);
@ -627,46 +642,26 @@ void GenericCAO::initialize(const std::string &data)
m_yaw = readF1000(is);
m_hp = readS16(is);
num_messages = readU8(is);
}
else if(version == 0) // In PROTOCOL_VERSION 13
{
} else if (version == 0) { // In PROTOCOL_VERSION 13
m_name = deSerializeString(is);
m_is_player = readU8(is);
m_position = readV3F1000(is);
m_yaw = readF1000(is);
m_hp = readS16(is);
num_messages = readU8(is);
}
else
{
} else {
errorstream<<"GenericCAO: Unsupported init data version"
<<std::endl;
return;
}
for(int i=0; i<num_messages; i++)
{
for (int i = 0; i < num_messages; i++) {
std::string message = deSerializeLongString(is);
processMessage(message);
}
pos_translator.init(m_position);
updateNodePos();
if(m_is_player)
{
Player *player = m_env->getPlayer(m_name.c_str());
if(player && player->isLocal())
{
m_is_local_player = true;
m_is_visible = false;
LocalPlayer* localplayer = dynamic_cast<LocalPlayer*>(player);
assert( localplayer != NULL );
localplayer->setCAO(this);
}
m_env->addPlayerName(m_name.c_str());
}
}
GenericCAO::~GenericCAO()
@ -1505,10 +1500,8 @@ void GenericCAO::updateBonePosition()
return;
m_animated_meshnode->setJointMode(irr::scene::EJUOR_CONTROL); // To write positions to the mesh on render
for(std::map<std::string,
core::vector2d<v3f> >::const_iterator ii = m_bone_position.begin();
ii != m_bone_position.end(); ++ii)
{
for(UNORDERED_MAP<std::string, core::vector2d<v3f> >::const_iterator
ii = m_bone_position.begin(); ii != m_bone_position.end(); ++ii) {
std::string bone_name = (*ii).first;
v3f bone_pos = (*ii).second.X;
v3f bone_rot = (*ii).second.Y;
@ -1569,8 +1562,7 @@ void GenericCAO::processMessage(const std::string &data)
std::istringstream is(data, std::ios::binary);
// command
u8 cmd = readU8(is);
if(cmd == GENERIC_CMD_SET_PROPERTIES)
{
if (cmd == GENERIC_CMD_SET_PROPERTIES) {
m_prop = gob_read_set_properties(is);
m_selection_box = m_prop.collisionbox;
@ -1589,9 +1581,7 @@ void GenericCAO::processMessage(const std::string &data)
m_prop.nametag = m_name;
expireVisuals();
}
else if(cmd == GENERIC_CMD_UPDATE_POSITION)
{
} else if (cmd == GENERIC_CMD_UPDATE_POSITION) {
// Not sent by the server if this object is an attachment.
// We might however get here if the server notices the object being detached before the client.
m_position = readV3F1000(is);
@ -1621,12 +1611,10 @@ void GenericCAO::processMessage(const std::string &data)
pos_translator.init(m_position);
}
updateNodePos();
}
else if(cmd == GENERIC_CMD_SET_TEXTURE_MOD) {
} else if (cmd == GENERIC_CMD_SET_TEXTURE_MOD) {
std::string mod = deSerializeString(is);
updateTextures(mod);
}
else if(cmd == GENERIC_CMD_SET_SPRITE) {
} else if (cmd == GENERIC_CMD_SET_SPRITE) {
v2s16 p = readV2S16(is);
int num_frames = readU16(is);
float framelength = readF1000(is);
@ -1638,8 +1626,7 @@ void GenericCAO::processMessage(const std::string &data)
m_tx_select_horiz_by_yawpitch = select_horiz_by_yawpitch;
updateTexturePos();
}
else if(cmd == GENERIC_CMD_SET_PHYSICS_OVERRIDE) {
} else if (cmd == GENERIC_CMD_SET_PHYSICS_OVERRIDE) {
float override_speed = readF1000(is);
float override_jump = readF1000(is);
float override_gravity = readF1000(is);
@ -1657,8 +1644,7 @@ void GenericCAO::processMessage(const std::string &data)
player->physics_override_sneak = sneak;
player->physics_override_sneak_glitch = sneak_glitch;
}
}
else if(cmd == GENERIC_CMD_SET_ANIMATION) {
} else if (cmd == GENERIC_CMD_SET_ANIMATION) {
// TODO: change frames send as v2s32 value
v2f range = readV2F1000(is);
if (!m_is_local_player) {
@ -1692,8 +1678,7 @@ void GenericCAO::processMessage(const std::string &data)
updateAnimation();
}
}
}
else if(cmd == GENERIC_CMD_SET_BONE_POSITION) {
} else if (cmd == GENERIC_CMD_SET_BONE_POSITION) {
std::string bone = deSerializeString(is);
v3f position = readV3F1000(is);
v3f rotation = readV3F1000(is);
@ -1726,8 +1711,7 @@ void GenericCAO::processMessage(const std::string &data)
}
updateAttachments();
}
else if(cmd == GENERIC_CMD_PUNCHED) {
} else if (cmd == GENERIC_CMD_PUNCHED) {
/*s16 damage =*/ readS16(is);
s16 result_hp = readS16(is);
@ -1755,8 +1739,7 @@ void GenericCAO::processMessage(const std::string &data)
updateTextures("^[brighten");
}
}
}
else if(cmd == GENERIC_CMD_UPDATE_ARMOR_GROUPS) {
} else if (cmd == GENERIC_CMD_UPDATE_ARMOR_GROUPS) {
m_armor_groups.clear();
int armor_groups_size = readU16(is);
for(int i=0; i<armor_groups_size; i++)
@ -1772,6 +1755,19 @@ void GenericCAO::processMessage(const std::string &data)
if (m_nametag != NULL) {
m_nametag->nametag_color = m_prop.nametag_color;
}
} else if (cmd == GENERIC_CMD_SPAWN_INFANT) {
u16 child_id = readU16(is);
u8 type = readU8(is);
if (GenericCAO *childobj = m_env->getGenericCAO(child_id)) {
childobj->processInitData(deSerializeLongString(is));
} else {
m_env->addActiveObject(child_id, type, deSerializeLongString(is));
}
} else {
warningstream << FUNCTION_NAME
<< ": unknown command or outdated client \""
<< cmd << std::endl;
}
}

View File

@ -90,7 +90,7 @@ private:
int m_animation_speed;
int m_animation_blend;
bool m_animation_loop;
std::map<std::string, core::vector2d<v3f> > m_bone_position; // stores position and rotation for each bone name
UNORDERED_MAP<std::string, core::vector2d<v3f> > m_bone_position; // stores position and rotation for each bone name
std::string m_attachment_bone;
v3f m_attachment_position;
v3f m_attachment_rotation;
@ -125,6 +125,8 @@ public:
void initialize(const std::string &data);
void processInitData(const std::string &data);
ClientActiveObject *getParent();
bool getCollisionBox(aabb3f *toset);

View File

@ -172,6 +172,15 @@ static inline void getNeighborConnectingFace(v3s16 p, INodeDefManager *nodedef,
*neighbors |= v;
}
// For use in mapblock_mesh_generate_special
// X,Y,Z of position must be -1,0,1
// This expression is a simplification of
// 3 * 3 * (pos.X + 1) + 3 * (pos.Y + 1) + (pos.Z + 1)
static inline int NeighborToIndex(const v3s16 &pos)
{
return 9 * pos.X + 3 * pos.Y + pos.Z + 13;
}
/*
TODO: Fix alpha blending for special nodes
Currently only the last element rendered is blended correct
@ -401,9 +410,14 @@ void mapblock_mesh_generate_special(MeshMakeData *data,
// Neighbor liquid levels (key = relative position)
// Includes current node
std::map<v3s16, f32> neighbor_levels;
std::map<v3s16, content_t> neighbor_contents;
std::map<v3s16, u8> neighbor_flags;
struct NeighborData {
f32 level;
content_t content;
u8 flags;
};
NeighborData neighbor_data_matrix[27];
const u8 neighborflag_top_is_same_liquid = 0x01;
v3s16 neighbor_dirs[9] = {
v3s16(0,0,0),
@ -449,9 +463,12 @@ void mapblock_mesh_generate_special(MeshMakeData *data,
flags |= neighborflag_top_is_same_liquid;
}
neighbor_levels[neighbor_dirs[i]] = level;
neighbor_contents[neighbor_dirs[i]] = content;
neighbor_flags[neighbor_dirs[i]] = flags;
NeighborData &neighbor_data =
neighbor_data_matrix[NeighborToIndex(neighbor_dirs[i])];
neighbor_data.level = level;
neighbor_data.content = content;
neighbor_data.flags = flags;
}
// Corner heights (average between four liquids)
@ -472,10 +489,12 @@ void mapblock_mesh_generate_special(MeshMakeData *data,
for(u32 j=0; j<4; j++)
{
v3s16 neighbordir = cornerdir - halfdirs[j];
content_t content = neighbor_contents[neighbordir];
NeighborData &neighbor_data =
neighbor_data_matrix[NeighborToIndex(neighbordir)];
content_t content = neighbor_data.content;
// If top is liquid, draw starting from top of node
if(neighbor_flags[neighbordir] &
neighborflag_top_is_same_liquid)
if (neighbor_data.flags & neighborflag_top_is_same_liquid)
{
cornerlevel = 0.5*BS;
valid_count = 1;
@ -491,7 +510,7 @@ void mapblock_mesh_generate_special(MeshMakeData *data,
// Flowing liquid has level information
else if(content == c_flowing)
{
cornerlevel += neighbor_levels[neighbordir];
cornerlevel += neighbor_data.level;
valid_count++;
}
else if(content == CONTENT_AIR)
@ -526,15 +545,17 @@ void mapblock_mesh_generate_special(MeshMakeData *data,
{
v3s16 dir = side_dirs[i];
NeighborData& neighbor_data =
neighbor_data_matrix[NeighborToIndex(dir)];
/*
If our topside is liquid and neighbor's topside
is liquid, don't draw side face
*/
if(top_is_same_liquid &&
neighbor_flags[dir] & neighborflag_top_is_same_liquid)
if (top_is_same_liquid &&
neighbor_data.flags & neighborflag_top_is_same_liquid)
continue;
content_t neighbor_content = neighbor_contents[dir];
content_t neighbor_content = neighbor_data.content;
const ContentFeatures &n_feat = nodedef->get(neighbor_content);
// Don't draw face if neighbor is blocking the view
@ -1506,8 +1527,8 @@ void mapblock_mesh_generate_special(MeshMakeData *data,
continue;
MapNode n_xy = data->m_vmanip.getNodeNoEx(blockpos_nodes + v3s16(x + xz, y + y0, z));
MapNode n_zy = data->m_vmanip.getNodeNoEx(blockpos_nodes + v3s16(x, y + y0, z + xz));
ContentFeatures def_xy = nodedef->get(n_xy);
ContentFeatures def_zy = nodedef->get(n_zy);
const ContentFeatures &def_xy = nodedef->get(n_xy);
const ContentFeatures &def_zy = nodedef->get(n_zy);
// Check if current node would connect with the rail
is_rail_x[index] = ((def_xy.drawtype == NDT_RAILLIKE

View File

@ -26,7 +26,7 @@ with this program; if not, write to the Free Software Foundation, Inc.,
#include "serialization.h" // For compressZlib
#include "tool.h" // For ToolCapabilities
#include "gamedef.h"
#include "player.h"
#include "remoteplayer.h"
#include "server.h"
#include "scripting_game.h"
#include "genericobject.h"
@ -157,10 +157,8 @@ LuaEntitySAO::~LuaEntitySAO()
m_env->getScriptIface()->luaentity_Remove(m_id);
}
std::set<u32>::iterator it;
std::set<u32>::iterator begin = m_attached_particle_spawners.begin();
std::set<u32>::iterator end = m_attached_particle_spawners.end();
for (it = begin; it != end; ++it) {
for (UNORDERED_SET<u32>::iterator it = m_attached_particle_spawners.begin();
it != m_attached_particle_spawners.end(); ++it) {
m_env->deleteParticleSpawner(*it, false);
}
}
@ -354,8 +352,10 @@ void LuaEntitySAO::step(float dtime, bool send_recommended)
if(m_bone_position_sent == false){
m_bone_position_sent = true;
for(std::map<std::string, core::vector2d<v3f> >::const_iterator ii = m_bone_position.begin(); ii != m_bone_position.end(); ++ii){
std::string str = gob_cmd_update_bone_position((*ii).first, (*ii).second.X, (*ii).second.Y);
for (UNORDERED_MAP<std::string, core::vector2d<v3f> >::const_iterator
ii = m_bone_position.begin(); ii != m_bone_position.end(); ++ii){
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);
@ -385,15 +385,23 @@ std::string LuaEntitySAO::getClientInitializationData(u16 protocol_version)
writeF1000(os, m_yaw);
writeS16(os, m_hp);
writeU8(os, 4 + m_bone_position.size()); // number of messages stuffed in here
writeU8(os, 4 + m_bone_position.size() + m_attachment_child_ids.size()); // number of messages stuffed in here
os<<serializeLongString(getPropertyPacket()); // message 1
os<<serializeLongString(gob_cmd_update_armor_groups(m_armor_groups)); // 2
os<<serializeLongString(gob_cmd_update_animation(
m_animation_range, m_animation_speed, m_animation_blend, m_animation_loop)); // 3
for(std::map<std::string, core::vector2d<v3f> >::const_iterator ii = m_bone_position.begin(); ii != m_bone_position.end(); ++ii){
os<<serializeLongString(gob_cmd_update_bone_position((*ii).first, (*ii).second.X, (*ii).second.Y)); // m_bone_position.size
for (UNORDERED_MAP<std::string, core::vector2d<v3f> >::const_iterator
ii = m_bone_position.begin(); ii != m_bone_position.end(); ++ii) {
os << serializeLongString(gob_cmd_update_bone_position((*ii).first,
(*ii).second.X, (*ii).second.Y)); // m_bone_position.size
}
os<<serializeLongString(gob_cmd_update_attachment(m_attachment_parent_id, m_attachment_bone, m_attachment_position, m_attachment_rotation)); // 4
for (UNORDERED_SET<int>::const_iterator ii = m_attachment_child_ids.begin();
(ii != m_attachment_child_ids.end()); ++ii) {
if (ServerActiveObject *obj = m_env->getActiveObject(*ii)) {
os << serializeLongString(gob_cmd_update_infant(*ii, obj->getSendType(), obj->getClientInitializationData(protocol_version)));
}
}
}
else
{
@ -621,7 +629,7 @@ void LuaEntitySAO::removeAttachmentChild(int child_id)
m_attachment_child_ids.erase(child_id);
}
std::set<int> LuaEntitySAO::getAttachmentChildIds()
UNORDERED_SET<int> LuaEntitySAO::getAttachmentChildIds()
{
return m_attachment_child_ids;
}
@ -754,7 +762,7 @@ bool LuaEntitySAO::collideWithObjects(){
// No prototype, PlayerSAO does not need to be deserialized
PlayerSAO::PlayerSAO(ServerEnvironment *env_, Player *player_, u16 peer_id_,
PlayerSAO::PlayerSAO(ServerEnvironment *env_, RemotePlayer *player_, u16 peer_id_,
const std::set<std::string> &privs, bool is_singleplayer):
ServerActiveObject(env_, v3f(0,0,0)),
m_player(player_),
@ -814,7 +822,6 @@ PlayerSAO::~PlayerSAO()
{
if(m_inventory != &m_player->inventory)
delete m_inventory;
}
std::string PlayerSAO::getDescription()
@ -836,16 +843,13 @@ void PlayerSAO::addedToEnvironment(u32 dtime_s)
void PlayerSAO::removingFromEnvironment()
{
ServerActiveObject::removingFromEnvironment();
if(m_player->getPlayerSAO() == this)
{
if (m_player->getPlayerSAO() == this) {
m_player->setPlayerSAO(NULL);
m_player->peer_id = 0;
m_env->savePlayer((RemotePlayer*)m_player);
m_env->savePlayer(m_player);
m_env->removePlayer(m_player);
std::set<u32>::iterator it;
std::set<u32>::iterator begin = m_attached_particle_spawners.begin();
std::set<u32>::iterator end = m_attached_particle_spawners.end();
for (it = begin; it != end; ++it) {
for (UNORDERED_SET<u32>::iterator it = m_attached_particle_spawners.begin();
it != m_attached_particle_spawners.end(); ++it) {
m_env->deleteParticleSpawner(*it, false);
}
}
@ -870,12 +874,13 @@ std::string PlayerSAO::getClientInitializationData(u16 protocol_version)
writeF1000(os, m_player->getYaw());
writeS16(os, getHP());
writeU8(os, 6 + m_bone_position.size()); // number of messages stuffed in here
writeU8(os, 6 + m_bone_position.size() + m_attachment_child_ids.size()); // number of messages stuffed in here
os<<serializeLongString(getPropertyPacket()); // message 1
os<<serializeLongString(gob_cmd_update_armor_groups(m_armor_groups)); // 2
os<<serializeLongString(gob_cmd_update_animation(
m_animation_range, m_animation_speed, m_animation_blend, m_animation_loop)); // 3
for(std::map<std::string, core::vector2d<v3f> >::const_iterator ii = m_bone_position.begin(); ii != m_bone_position.end(); ++ii){
for (UNORDERED_MAP<std::string, core::vector2d<v3f> >::const_iterator
ii = m_bone_position.begin(); ii != m_bone_position.end(); ++ii) {
os<<serializeLongString(gob_cmd_update_bone_position((*ii).first, (*ii).second.X, (*ii).second.Y)); // m_bone_position.size
}
os<<serializeLongString(gob_cmd_update_attachment(m_attachment_parent_id, m_attachment_bone, m_attachment_position, m_attachment_rotation)); // 4
@ -883,6 +888,12 @@ std::string PlayerSAO::getClientInitializationData(u16 protocol_version)
m_physics_override_jump, m_physics_override_gravity, m_physics_override_sneak,
m_physics_override_sneak_glitch)); // 5
os << serializeLongString(gob_cmd_update_nametag_attributes(m_prop.nametag_color)); // 6 (GENERIC_CMD_UPDATE_NAMETAG_ATTRIBUTES) : Deprecated, for backwards compatibility only.
for (UNORDERED_SET<int>::const_iterator ii = m_attachment_child_ids.begin();
ii != m_attachment_child_ids.end(); ++ii) {
if (ServerActiveObject *obj = m_env->getActiveObject(*ii)) {
os << serializeLongString(gob_cmd_update_infant(*ii, obj->getSendType(), obj->getClientInitializationData(protocol_version)));
}
}
}
else
{
@ -1020,19 +1031,22 @@ void PlayerSAO::step(float dtime, bool send_recommended)
m_messages_out.push(aom);
}
if(m_bone_position_sent == false){
if (!m_bone_position_sent) {
m_bone_position_sent = true;
for(std::map<std::string, core::vector2d<v3f> >::const_iterator ii = m_bone_position.begin(); ii != m_bone_position.end(); ++ii){
std::string str = gob_cmd_update_bone_position((*ii).first, (*ii).second.X, (*ii).second.Y);
for (UNORDERED_MAP<std::string, core::vector2d<v3f> >::const_iterator
ii = m_bone_position.begin(); ii != m_bone_position.end(); ++ii) {
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);
}
}
if(m_attachment_sent == false){
if (!m_attachment_sent){
m_attachment_sent = true;
std::string str = gob_cmd_update_attachment(m_attachment_parent_id, m_attachment_bone, m_attachment_position, m_attachment_rotation);
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);
@ -1272,7 +1286,7 @@ void PlayerSAO::removeAttachmentChild(int child_id)
m_attachment_child_ids.erase(child_id);
}
std::set<int> PlayerSAO::getAttachmentChildIds()
UNORDERED_SET<int> PlayerSAO::getAttachmentChildIds()
{
return m_attachment_child_ids;
}

View File

@ -22,7 +22,6 @@ with this program; if not, write to the Free Software Foundation, Inc.,
#include "serverobject.h"
#include "itemgroup.h"
#include "player.h"
#include "object_properties.h"
/*
@ -67,7 +66,7 @@ public:
void getAttachment(int *parent_id, std::string *bone, v3f *position, v3f *rotation);
void addAttachmentChild(int child_id);
void removeAttachmentChild(int child_id);
std::set<int> getAttachmentChildIds();
UNORDERED_SET<int> getAttachmentChildIds();
ObjectProperties* accessObjectProperties();
void notifyObjectPropertiesModified();
/* LuaEntitySAO-specific */
@ -112,11 +111,11 @@ private:
bool m_animation_loop;
bool m_animation_sent;
std::map<std::string, core::vector2d<v3f> > m_bone_position;
UNORDERED_MAP<std::string, core::vector2d<v3f> > m_bone_position;
bool m_bone_position_sent;
int m_attachment_parent_id;
std::set<int> m_attachment_child_ids;
UNORDERED_SET<int> m_attachment_child_ids;
std::string m_attachment_bone;
v3f m_attachment_position;
v3f m_attachment_rotation;
@ -157,10 +156,12 @@ public:
}
};
class RemotePlayer;
class PlayerSAO : public ServerActiveObject
{
public:
PlayerSAO(ServerEnvironment *env_, Player *player_, u16 peer_id_,
PlayerSAO(ServerEnvironment *env_, RemotePlayer *player_, u16 peer_id_,
const std::set<std::string> &privs, bool is_singleplayer);
~PlayerSAO();
ActiveObjectType getType() const
@ -210,7 +211,7 @@ public:
void getAttachment(int *parent_id, std::string *bone, v3f *position, v3f *rotation);
void addAttachmentChild(int child_id);
void removeAttachmentChild(int child_id);
std::set<int> getAttachmentChildIds();
UNORDERED_SET<int> getAttachmentChildIds();
ObjectProperties* accessObjectProperties();
void notifyObjectPropertiesModified();
@ -231,14 +232,8 @@ public:
void disconnected();
Player* getPlayer()
{
return m_player;
}
u16 getPeerID() const
{
return m_peer_id;
}
RemotePlayer *getPlayer() { return m_player; }
u16 getPeerID() const { return m_peer_id; }
// Cheat prevention
@ -291,7 +286,7 @@ public:
private:
std::string getPropertyPacket();
Player *m_player;
RemotePlayer *m_player;
u16 m_peer_id;
Inventory *m_inventory;
s16 m_damage;
@ -321,11 +316,12 @@ private:
bool m_animation_loop;
bool m_animation_sent;
std::map<std::string, core::vector2d<v3f> > m_bone_position; // Stores position and rotation for each bone name
// Stores position and rotation for each bone name
UNORDERED_MAP<std::string, core::vector2d<v3f> > m_bone_position;
bool m_bone_position_sent;
int m_attachment_parent_id;
std::set<int> m_attachment_child_ids;
UNORDERED_SET<int> m_attachment_child_ids;
std::string m_attachment_bone;
v3f m_attachment_position;
v3f m_attachment_rotation;

View File

@ -285,8 +285,11 @@ void set_default_settings(Settings *settings)
settings->setDefault("time_send_interval", "5");
settings->setDefault("time_speed", "72");
settings->setDefault("server_unload_unused_data_timeout", "29");
settings->setDefault("max_objects_per_block", "49");
settings->setDefault("max_objects_per_block", "64");
settings->setDefault("server_map_save_interval", "5.3");
settings->setDefault("chat_message_max_size", "500");
settings->setDefault("chat_message_limit_per_10sec", "8.0");
settings->setDefault("chat_message_limit_trigger_kick", "50");
settings->setDefault("sqlite_synchronous", "2");
settings->setDefault("full_block_send_enable_min_time_from_building", "2.0");
settings->setDefault("dedicated_server_step", "0.1");
@ -300,7 +303,7 @@ void set_default_settings(Settings *settings)
settings->setDefault("emergequeue_limit_diskonly", "32");
settings->setDefault("emergequeue_limit_generate", "32");
settings->setDefault("num_emerge_threads", "1");
settings->setDefault("secure.enable_security", "false");
settings->setDefault("secure.enable_security", "true");
settings->setDefault("secure.trusted_mods", "");
settings->setDefault("secure.http_mods", "");

View File

@ -369,12 +369,10 @@ bool EmergeManager::pushBlockEmergeData(
}
bool EmergeManager::popBlockEmergeData(
v3s16 pos,
BlockEmergeData *bedata)
bool EmergeManager::popBlockEmergeData(v3s16 pos, BlockEmergeData *bedata)
{
std::map<v3s16, BlockEmergeData>::iterator it;
std::map<u16, u16>::iterator it2;
UNORDERED_MAP<u16, u16>::iterator it2;
it = m_blocks_enqueued.find(pos);
if (it == m_blocks_enqueued.end())

View File

@ -156,7 +156,7 @@ private:
Mutex m_queue_mutex;
std::map<v3s16, BlockEmergeData> m_blocks_enqueued;
std::map<u16, u16> m_peer_queue_count;
UNORDERED_MAP<u16, u16> m_peer_queue_count;
u16 m_qlimit_total;
u16 m_qlimit_diskonly;

View File

@ -69,121 +69,6 @@ Environment::Environment():
Environment::~Environment()
{
// Deallocate players
for(std::vector<Player*>::iterator i = m_players.begin();
i != m_players.end(); ++i) {
delete (*i);
}
}
void Environment::addPlayer(Player *player)
{
DSTACK(FUNCTION_NAME);
/*
Check that peer_ids are unique.
Also check that names are unique.
Exception: there can be multiple players with peer_id=0
*/
// If peer id is non-zero, it has to be unique.
if(player->peer_id != 0)
FATAL_ERROR_IF(getPlayer(player->peer_id) != NULL, "Peer id not unique");
// Name has to be unique.
FATAL_ERROR_IF(getPlayer(player->getName()) != NULL, "Player name not unique");
// Add.
m_players.push_back(player);
}
void Environment::removePlayer(Player* player)
{
for (std::vector<Player*>::iterator it = m_players.begin();
it != m_players.end(); ++it) {
if ((*it) == player) {
delete *it;
m_players.erase(it);
return;
}
}
}
Player * Environment::getPlayer(u16 peer_id)
{
for(std::vector<Player*>::iterator i = m_players.begin();
i != m_players.end(); ++i) {
Player *player = *i;
if(player->peer_id == peer_id)
return player;
}
return NULL;
}
Player * Environment::getPlayer(const char *name)
{
for(std::vector<Player*>::iterator i = m_players.begin();
i != m_players.end(); ++i) {
Player *player = *i;
if(strcmp(player->getName(), name) == 0)
return player;
}
return NULL;
}
Player * Environment::getRandomConnectedPlayer()
{
std::vector<Player*> connected_players = getPlayers(true);
u32 chosen_one = myrand() % connected_players.size();
u32 j = 0;
for(std::vector<Player*>::iterator
i = connected_players.begin();
i != connected_players.end(); ++i) {
if(j == chosen_one) {
Player *player = *i;
return player;
}
j++;
}
return NULL;
}
Player * Environment::getNearestConnectedPlayer(v3f pos)
{
std::vector<Player*> connected_players = getPlayers(true);
f32 nearest_d = 0;
Player *nearest_player = NULL;
for(std::vector<Player*>::iterator
i = connected_players.begin();
i != connected_players.end(); ++i) {
Player *player = *i;
f32 d = player->getPosition().getDistanceFrom(pos);
if(d < nearest_d || nearest_player == NULL) {
nearest_d = d;
nearest_player = player;
}
}
return nearest_player;
}
std::vector<Player*> Environment::getPlayers()
{
return m_players;
}
std::vector<Player*> Environment::getPlayers(bool ignore_disconnected)
{
std::vector<Player*> newlist;
for(std::vector<Player*>::iterator
i = m_players.begin();
i != m_players.end(); ++i) {
Player *player = *i;
if(ignore_disconnected) {
// Ignore disconnected players
if(player->peer_id == 0)
continue;
}
newlist.push_back(player);
}
return newlist;
}
u32 Environment::getDayNightRatio()
@ -199,11 +84,6 @@ void Environment::setTimeOfDaySpeed(float speed)
m_time_of_day_speed = speed;
}
float Environment::getTimeOfDaySpeed()
{
return m_time_of_day_speed;
}
void Environment::setDayNightRatioOverride(bool enable, u32 value)
{
MutexAutoLock lock(this->m_time_lock);
@ -609,10 +489,16 @@ ServerEnvironment::~ServerEnvironment()
m_map->drop();
// Delete ActiveBlockModifiers
for(std::vector<ABMWithState>::iterator
for (std::vector<ABMWithState>::iterator
i = m_abms.begin(); i != m_abms.end(); ++i){
delete i->abm;
}
// Deallocate players
for (std::vector<RemotePlayer *>::iterator i = m_players.begin();
i != m_players.end(); ++i) {
delete (*i);
}
}
Map & ServerEnvironment::getMap()
@ -625,6 +511,57 @@ ServerMap & ServerEnvironment::getServerMap()
return *m_map;
}
RemotePlayer *ServerEnvironment::getPlayer(const u16 peer_id)
{
for (std::vector<RemotePlayer *>::iterator i = m_players.begin();
i != m_players.end(); ++i) {
RemotePlayer *player = *i;
if (player->peer_id == peer_id)
return player;
}
return NULL;
}
RemotePlayer *ServerEnvironment::getPlayer(const char* name)
{
for (std::vector<RemotePlayer *>::iterator i = m_players.begin();
i != m_players.end(); ++i) {
RemotePlayer *player = *i;
if (strcmp(player->getName(), name) == 0)
return player;
}
return NULL;
}
void ServerEnvironment::addPlayer(RemotePlayer *player)
{
DSTACK(FUNCTION_NAME);
/*
Check that peer_ids are unique.
Also check that names are unique.
Exception: there can be multiple players with peer_id=0
*/
// If peer id is non-zero, it has to be unique.
if (player->peer_id != 0)
FATAL_ERROR_IF(getPlayer(player->peer_id) != NULL, "Peer id not unique");
// Name has to be unique.
FATAL_ERROR_IF(getPlayer(player->getName()) != NULL, "Player name not unique");
// Add.
m_players.push_back(player);
}
void ServerEnvironment::removePlayer(RemotePlayer *player)
{
for (std::vector<RemotePlayer *>::iterator it = m_players.begin();
it != m_players.end(); ++it) {
if ((*it) == player) {
delete *it;
m_players.erase(it);
return;
}
}
}
bool ServerEnvironment::line_of_sight(v3f pos1, v3f pos2, float stepsize, v3s16 *p)
{
float distance = pos1.getDistanceFrom(pos2);
@ -655,12 +592,11 @@ bool ServerEnvironment::line_of_sight(v3f pos1, v3f pos2, float stepsize, v3s16
void ServerEnvironment::kickAllPlayers(AccessDeniedCode reason,
const std::string &str_reason, bool reconnect)
{
for (std::vector<Player*>::iterator it = m_players.begin();
it != m_players.end();
++it) {
((Server*)m_gamedef)->DenyAccessVerCompliant((*it)->peer_id,
(*it)->protocol_version, (AccessDeniedCode)reason,
str_reason, reconnect);
for (std::vector<RemotePlayer *>::iterator it = m_players.begin();
it != m_players.end(); ++it) {
RemotePlayer *player = dynamic_cast<RemotePlayer *>(*it);
((Server*)m_gamedef)->DenyAccessVerCompliant(player->peer_id,
player->protocol_version, reason, str_reason, reconnect);
}
}
@ -669,12 +605,12 @@ 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::vector<RemotePlayer *>::iterator it = m_players.begin();
it != m_players.end();
++it) {
RemotePlayer *player = static_cast<RemotePlayer*>(*it);
if (player->checkModified()) {
player->save(players_path);
player->save(players_path, m_gamedef);
}
}
}
@ -684,19 +620,19 @@ void ServerEnvironment::savePlayer(RemotePlayer *player)
std::string players_path = m_path_world + DIR_DELIM "players";
fs::CreateDir(players_path);
player->save(players_path);
player->save(players_path, m_gamedef);
}
Player *ServerEnvironment::loadPlayer(const std::string &playername)
RemotePlayer *ServerEnvironment::loadPlayer(const std::string &playername)
{
bool newplayer = false;
bool found = false;
std::string players_path = m_path_world + DIR_DELIM "players" DIR_DELIM;
std::string path = players_path + playername;
RemotePlayer *player = static_cast<RemotePlayer *>(getPlayer(playername.c_str()));
RemotePlayer *player = getPlayer(playername.c_str());
if (!player) {
player = new RemotePlayer(m_gamedef, "");
player = new RemotePlayer("", m_gamedef->idef());
newplayer = true;
}
@ -1124,14 +1060,12 @@ bool ServerEnvironment::swapNode(v3s16 p, const MapNode &n)
void ServerEnvironment::getObjectsInsideRadius(std::vector<u16> &objects, v3f pos, float radius)
{
for(std::map<u16, ServerActiveObject*>::iterator
i = m_active_objects.begin();
i != m_active_objects.end(); ++i)
{
for (ActiveObjectMap::iterator i = m_active_objects.begin();
i != m_active_objects.end(); ++i) {
ServerActiveObject* obj = i->second;
u16 id = i->first;
v3f objectpos = obj->getBasePosition();
if(objectpos.getDistanceFrom(pos) > radius)
if (objectpos.getDistanceFrom(pos) > radius)
continue;
objects.push_back(id);
}
@ -1142,8 +1076,7 @@ void ServerEnvironment::clearObjects(ClearObjectsMode mode)
infostream << "ServerEnvironment::clearObjects(): "
<< "Removing all active objects" << std::endl;
std::vector<u16> objects_to_remove;
for (std::map<u16, ServerActiveObject*>::iterator
i = m_active_objects.begin();
for (ActiveObjectMap::iterator i = m_active_objects.begin();
i != m_active_objects.end(); ++i) {
ServerActiveObject* obj = i->second;
if (obj->getType() == ACTIVEOBJECT_TYPE_PLAYER)
@ -1311,10 +1244,10 @@ void ServerEnvironment::step(float dtime)
*/
{
ScopeProfiler sp(g_profiler, "SEnv: handle players avg", SPT_AVG);
for(std::vector<Player*>::iterator i = m_players.begin();
i != m_players.end(); ++i)
{
Player *player = *i;
for (std::vector<RemotePlayer *>::iterator i = m_players.begin();
i != m_players.end(); ++i) {
RemotePlayer *player = dynamic_cast<RemotePlayer *>(*i);
assert(player);
// Ignore disconnected players
if(player->peer_id == 0)
@ -1334,12 +1267,12 @@ void ServerEnvironment::step(float dtime)
Get player block positions
*/
std::vector<v3s16> players_blockpos;
for(std::vector<Player*>::iterator
i = m_players.begin();
for (std::vector<RemotePlayer *>::iterator i = m_players.begin();
i != m_players.end(); ++i) {
Player *player = *i;
RemotePlayer *player = dynamic_cast<RemotePlayer *>(*i);
assert(player);
// Ignore disconnected players
if(player->peer_id == 0)
if (player->peer_id == 0)
continue;
v3s16 blockpos = getNodeBlockPos(
@ -1439,8 +1372,7 @@ void ServerEnvironment::step(float dtime)
block->m_node_timers.step(m_cache_nodetimer_interval);
if (!elapsed_timers.empty()) {
MapNode n;
for (std::vector<NodeTimer>::iterator
i = elapsed_timers.begin();
for (std::vector<NodeTimer>::iterator i = elapsed_timers.begin();
i != elapsed_timers.end(); ++i) {
n = block->getNodeNoEx(i->position);
p = i->position + block->getPosRelative();
@ -1480,10 +1412,8 @@ void ServerEnvironment::step(float dtime)
send_recommended = true;
}
for(std::map<u16, ServerActiveObject*>::iterator
i = m_active_objects.begin();
i != m_active_objects.end(); ++i)
{
for(ActiveObjectMap::iterator i = m_active_objects.begin();
i != m_active_objects.end(); ++i) {
ServerActiveObject* obj = i->second;
// Don't step if is to be removed or stored statically
if(obj->m_removed || obj->m_pending_deactivation)
@ -1516,7 +1446,7 @@ void ServerEnvironment::step(float dtime)
Manage particle spawner expiration
*/
if (m_particle_management_interval.step(dtime, 1.0)) {
for (std::map<u32, float>::iterator i = m_particle_spawners.begin();
for (UNORDERED_MAP<u32, float>::iterator i = m_particle_spawners.begin();
i != m_particle_spawners.end(); ) {
//non expiring spawners
if (i->second == PARTICLE_SPAWNER_NO_EXPIRY) {
@ -1541,8 +1471,7 @@ u32 ServerEnvironment::addParticleSpawner(float exptime)
u32 id = 0;
for (;;) { // look for unused particlespawner id
id++;
std::map<u32, float>::iterator f;
f = m_particle_spawners.find(id);
UNORDERED_MAP<u32, float>::iterator f = m_particle_spawners.find(id);
if (f == m_particle_spawners.end()) {
m_particle_spawners[id] = time;
break;
@ -1555,47 +1484,41 @@ u32 ServerEnvironment::addParticleSpawner(float exptime, u16 attached_id)
{
u32 id = addParticleSpawner(exptime);
m_particle_spawner_attachments[id] = attached_id;
ServerActiveObject *obj = getActiveObject(attached_id);
if (obj != NULL) {
if (ServerActiveObject *obj = getActiveObject(attached_id)) {
obj->attachParticleSpawner(id);
}
return id;
}
void ServerEnvironment::deleteParticleSpawner(u32 id,
bool remove_from_object)
void ServerEnvironment::deleteParticleSpawner(u32 id, bool remove_from_object)
{
m_particle_spawners.erase(id);
try {
u16 obj_id = m_particle_spawner_attachments.at(id);
UNORDERED_MAP<u32, u16>::iterator it = m_particle_spawner_attachments.find(id);
if (it != m_particle_spawner_attachments.end()) {
u16 obj_id = (*it).second;
ServerActiveObject *sao = getActiveObject(obj_id);
if (sao != NULL && remove_from_object) {
sao->detachParticleSpawner(id);
}
} catch (...) {}
m_particle_spawner_attachments.erase(id);
m_particle_spawner_attachments.erase(id);
}
}
ServerActiveObject* ServerEnvironment::getActiveObject(u16 id)
{
std::map<u16, ServerActiveObject*>::iterator n;
n = m_active_objects.find(id);
if(n == m_active_objects.end())
return NULL;
return n->second;
ActiveObjectMap::iterator n = m_active_objects.find(id);
return (n != m_active_objects.end() ? n->second : NULL);
}
bool isFreeServerActiveObjectId(u16 id,
std::map<u16, ServerActiveObject*> &objects)
bool isFreeServerActiveObjectId(u16 id, ActiveObjectMap &objects)
{
if(id == 0)
if (id == 0)
return false;
return objects.find(id) == objects.end();
}
u16 getFreeServerActiveObjectId(
std::map<u16, ServerActiveObject*> &objects)
u16 getFreeServerActiveObjectId(ActiveObjectMap &objects)
{
//try to reuse id's as late as possible
static u16 last_used_id = 0;
@ -1623,7 +1546,7 @@ u16 ServerEnvironment::addActiveObject(ServerActiveObject *object)
Finds out what new objects have been added to
inside a radius around a position
*/
void ServerEnvironment::getAddedActiveObjects(Player *player, s16 radius,
void ServerEnvironment::getAddedActiveObjects(RemotePlayer *player, s16 radius,
s16 player_radius,
std::set<u16> &current_objects,
std::queue<u16> &added_objects)
@ -1641,8 +1564,7 @@ void ServerEnvironment::getAddedActiveObjects(Player *player, s16 radius,
- discard objects that are found in current_objects.
- add remaining objects to added_objects
*/
for(std::map<u16, ServerActiveObject*>::iterator
i = m_active_objects.begin();
for(ActiveObjectMap::iterator i = m_active_objects.begin();
i != m_active_objects.end(); ++i) {
u16 id = i->first;
@ -1677,7 +1599,7 @@ void ServerEnvironment::getAddedActiveObjects(Player *player, s16 radius,
Finds out what objects have been removed from
inside a radius around a position
*/
void ServerEnvironment::getRemovedActiveObjects(Player *player, s16 radius,
void ServerEnvironment::getRemovedActiveObjects(RemotePlayer *player, s16 radius,
s16 player_radius,
std::set<u16> &current_objects,
std::queue<u16> &removed_objects)
@ -1738,8 +1660,7 @@ void ServerEnvironment::setStaticForActiveObjectsInBlock(
so_it = block->m_static_objects.m_active.begin();
so_it != block->m_static_objects.m_active.end(); ++so_it) {
// Get the ServerActiveObject counterpart to this StaticObject
std::map<u16, ServerActiveObject *>::iterator ao_it;
ao_it = m_active_objects.find(so_it->first);
ActiveObjectMap::iterator ao_it = m_active_objects.find(so_it->first);
if (ao_it == m_active_objects.end()) {
// If this ever happens, there must be some kind of nasty bug.
errorstream << "ServerEnvironment::setStaticForObjectsInBlock(): "
@ -1788,8 +1709,8 @@ u16 ServerEnvironment::addActiveObjectRaw(ServerActiveObject *object,
verbosestream<<"ServerEnvironment::addActiveObjectRaw(): "
<<"supplied with id "<<object->getId()<<std::endl;
}
if(isFreeServerActiveObjectId(object->getId(), m_active_objects) == false)
{
if(!isFreeServerActiveObjectId(object->getId(), m_active_objects)) {
errorstream<<"ServerEnvironment::addActiveObjectRaw(): "
<<"id is not free ("<<object->getId()<<")"<<std::endl;
if(object->environmentDeletes())
@ -1857,8 +1778,7 @@ u16 ServerEnvironment::addActiveObjectRaw(ServerActiveObject *object,
void ServerEnvironment::removeRemovedObjects()
{
std::vector<u16> objects_to_remove;
for(std::map<u16, ServerActiveObject*>::iterator
i = m_active_objects.begin();
for(ActiveObjectMap::iterator i = m_active_objects.begin();
i != m_active_objects.end(); ++i) {
u16 id = i->first;
ServerActiveObject* obj = i->second;
@ -1876,7 +1796,7 @@ void ServerEnvironment::removeRemovedObjects()
We will delete objects that are marked as removed or thatare
waiting for deletion after deactivation
*/
if(obj->m_removed == false && obj->m_pending_deactivation == false)
if (!obj->m_removed && !obj->m_pending_deactivation)
continue;
/*
@ -2076,8 +1996,7 @@ void ServerEnvironment::activateObjects(MapBlock *block, u32 dtime_s)
void ServerEnvironment::deactivateFarObjects(bool force_delete)
{
std::vector<u16> objects_to_remove;
for(std::map<u16, ServerActiveObject*>::iterator
i = m_active_objects.begin();
for(ActiveObjectMap::iterator i = m_active_objects.begin();
i != m_active_objects.end(); ++i) {
ServerActiveObject* obj = i->second;
assert(obj);
@ -2218,13 +2137,13 @@ void ServerEnvironment::deactivateFarObjects(bool force_delete)
if(block)
{
if(block->m_static_objects.m_stored.size() >= g_settings->getU16("max_objects_per_block")){
errorstream<<"ServerEnv: Trying to store id="<<obj->getId()
<<" statically but block "<<PP(blockpos)
<<" already contains "
<<block->m_static_objects.m_stored.size()
<<" objects."
<<" Forcing delete."<<std::endl;
if (block->m_static_objects.m_stored.size() >= g_settings->getU16("max_objects_per_block")) {
warningstream << "ServerEnv: Trying to store id = " << obj->getId()
<< " statically but block " << PP(blockpos)
<< " already contains "
<< block->m_static_objects.m_stored.size()
<< " objects."
<< " Forcing delete." << std::endl;
force_delete = true;
} else {
// If static counterpart already exists in target block,
@ -2313,6 +2232,7 @@ ClientEnvironment::ClientEnvironment(ClientMap *map, scene::ISceneManager *smgr,
ITextureSource *texturesource, IGameDef *gamedef,
IrrlichtDevice *irr):
m_map(map),
m_local_player(NULL),
m_smgr(smgr),
m_texturesource(texturesource),
m_gamedef(gamedef),
@ -2325,10 +2245,8 @@ ClientEnvironment::ClientEnvironment(ClientMap *map, scene::ISceneManager *smgr,
ClientEnvironment::~ClientEnvironment()
{
// delete active objects
for(std::map<u16, ClientActiveObject*>::iterator
i = m_active_objects.begin();
i != m_active_objects.end(); ++i)
{
for (UNORDERED_MAP<u16, ClientActiveObject*>::iterator i = m_active_objects.begin();
i != m_active_objects.end(); ++i) {
delete i->second;
}
@ -2351,28 +2269,16 @@ ClientMap & ClientEnvironment::getClientMap()
return *m_map;
}
void ClientEnvironment::addPlayer(Player *player)
void ClientEnvironment::setLocalPlayer(LocalPlayer *player)
{
DSTACK(FUNCTION_NAME);
/*
It is a failure if player is local and there already is a local
player
It is a failure if already is a local player
*/
FATAL_ERROR_IF(player->isLocal() == true && getLocalPlayer() != NULL,
"Player is local but there is already a local player");
FATAL_ERROR_IF(m_local_player != NULL,
"Local player already allocated");
Environment::addPlayer(player);
}
LocalPlayer * ClientEnvironment::getLocalPlayer()
{
for(std::vector<Player*>::iterator i = m_players.begin();
i != m_players.end(); ++i) {
Player *player = *i;
if(player->isLocal())
return (LocalPlayer*)player;
}
return NULL;
m_local_player = player;
}
void ClientEnvironment::step(float dtime)
@ -2453,11 +2359,11 @@ void ClientEnvironment::step(float dtime)
{
// Apply physics
if(free_move == false && is_climbing == false)
if(!free_move && !is_climbing)
{
// Gravity
v3f speed = lplayer->getSpeed();
if(lplayer->in_liquid == false)
if(!lplayer->in_liquid)
speed.Y -= lplayer->movement_gravity * lplayer->physics_override_gravity * dtime_part * 2;
// Liquid floating / sinking
@ -2609,23 +2515,6 @@ 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) {
Player *player = *i;
/*
Handle non-local players
*/
if(player->isLocal() == false) {
// Move
player->move(dtime, this, 100*BS);
}
}
// Update lighting on local player (used for wield item)
u32 day_night_ratio = getDayNightRatio();
{
@ -2650,10 +2539,8 @@ void ClientEnvironment::step(float dtime)
g_profiler->avg("CEnv: num of objects", m_active_objects.size());
bool update_lighting = m_active_object_light_update_interval.step(dtime, 0.21);
for(std::map<u16, ClientActiveObject*>::iterator
i = m_active_objects.begin();
i != m_active_objects.end(); ++i)
{
for (UNORDERED_MAP<u16, ClientActiveObject*>::iterator i = m_active_objects.begin();
i != m_active_objects.end(); ++i) {
ClientActiveObject* obj = i->second;
// Step object
obj->step(dtime, this);
@ -2712,15 +2599,14 @@ GenericCAO* ClientEnvironment::getGenericCAO(u16 id)
ClientActiveObject* ClientEnvironment::getActiveObject(u16 id)
{
std::map<u16, ClientActiveObject*>::iterator n;
n = m_active_objects.find(id);
if(n == m_active_objects.end())
UNORDERED_MAP<u16, ClientActiveObject*>::iterator n = m_active_objects.find(id);
if (n == m_active_objects.end())
return NULL;
return n->second;
}
bool isFreeClientActiveObjectId(u16 id,
std::map<u16, ClientActiveObject*> &objects)
bool isFreeClientActiveObjectId(const u16 id,
UNORDERED_MAP<u16, ClientActiveObject*> &objects)
{
if(id == 0)
return false;
@ -2728,19 +2614,17 @@ bool isFreeClientActiveObjectId(u16 id,
return objects.find(id) == objects.end();
}
u16 getFreeClientActiveObjectId(
std::map<u16, ClientActiveObject*> &objects)
u16 getFreeClientActiveObjectId(UNORDERED_MAP<u16, ClientActiveObject*> &objects)
{
//try to reuse id's as late as possible
static u16 last_used_id = 0;
u16 startid = last_used_id;
for(;;)
{
for(;;) {
last_used_id ++;
if(isFreeClientActiveObjectId(last_used_id, objects))
if (isFreeClientActiveObjectId(last_used_id, objects))
return last_used_id;
if(last_used_id == startid)
if (last_used_id == startid)
return 0;
}
}
@ -2760,8 +2644,7 @@ u16 ClientEnvironment::addActiveObject(ClientActiveObject *object)
}
object->setId(new_id);
}
if(isFreeClientActiveObjectId(object->getId(), m_active_objects) == false)
{
if (!isFreeClientActiveObjectId(object->getId(), m_active_objects)) {
infostream<<"ClientEnvironment::addActiveObject(): "
<<"id is not free ("<<object->getId()<<")"<<std::endl;
delete object;
@ -2825,8 +2708,7 @@ void ClientEnvironment::removeActiveObject(u16 id)
verbosestream<<"ClientEnvironment::removeActiveObject(): "
<<"id="<<id<<std::endl;
ClientActiveObject* obj = getActiveObject(id);
if(obj == NULL)
{
if (obj == NULL) {
infostream<<"ClientEnvironment::removeActiveObject(): "
<<"id="<<id<<" not found"<<std::endl;
return;
@ -2894,10 +2776,8 @@ void ClientEnvironment::updateLocalPlayerBreath(u16 breath)
void ClientEnvironment::getActiveObjects(v3f origin, f32 max_d,
std::vector<DistanceSortedActiveObject> &dest)
{
for(std::map<u16, ClientActiveObject*>::iterator
i = m_active_objects.begin();
i != m_active_objects.end(); ++i)
{
for (UNORDERED_MAP<u16, ClientActiveObject*>::iterator i = m_active_objects.begin();
i != m_active_objects.end(); ++i) {
ClientActiveObject* obj = i->second;
f32 d = (obj->getPosition() - origin).getLength();

View File

@ -72,15 +72,6 @@ public:
virtual Map & getMap() = 0;
virtual void addPlayer(Player *player);
void removePlayer(Player *player);
Player * getPlayer(u16 peer_id);
Player * getPlayer(const char *name);
Player * getRandomConnectedPlayer();
Player * getNearestConnectedPlayer(v3f pos);
std::vector<Player*> getPlayers();
std::vector<Player*> getPlayers(bool ignore_disconnected);
u32 getDayNightRatio();
// 0-23999
@ -91,7 +82,6 @@ public:
void stepTimeOfDay(float dtime);
void setTimeOfDaySpeed(float speed);
float getTimeOfDaySpeed();
void setDayNightRatioOverride(bool enable, u32 value);
@ -101,9 +91,6 @@ public:
u32 m_added_objects;
protected:
// peer_ids in here should be unique, except that there may be many 0s
std::vector<Player*> m_players;
GenericAtomic<float> m_time_of_day_speed;
/*
@ -300,6 +287,8 @@ enum ClearObjectsMode {
This is not thread-safe. Server uses an environment mutex.
*/
typedef UNORDERED_MAP<u16, ServerActiveObject *> ActiveObjectMap;
class ServerEnvironment : public Environment
{
public:
@ -326,7 +315,9 @@ public:
// Save players
void saveLoadedPlayers();
void savePlayer(RemotePlayer *player);
Player *loadPlayer(const std::string &playername);
RemotePlayer *loadPlayer(const std::string &playername);
void addPlayer(RemotePlayer *player);
void removePlayer(RemotePlayer *player);
/*
Save and load time of day and game timer
@ -371,7 +362,7 @@ public:
Find out what new objects have been added to
inside a radius around a position
*/
void getAddedActiveObjects(Player *player, s16 radius,
void getAddedActiveObjects(RemotePlayer *player, s16 radius,
s16 player_radius,
std::set<u16> &current_objects,
std::queue<u16> &added_objects);
@ -380,7 +371,7 @@ public:
Find out what new objects have been removed from
inside a radius around a position
*/
void getRemovedActiveObjects(Player* player, s16 radius,
void getRemovedActiveObjects(RemotePlayer *player, s16 radius,
s16 player_radius,
std::set<u16> &current_objects,
std::queue<u16> &removed_objects);
@ -439,6 +430,8 @@ public:
void setStaticForActiveObjectsInBlock(v3s16 blockpos,
bool static_exists, v3s16 static_block=v3s16(0,0,0));
RemotePlayer *getPlayer(const u16 peer_id);
RemotePlayer *getPlayer(const char* name);
private:
/*
@ -492,7 +485,7 @@ private:
// World path
const std::string m_path_world;
// Active object list
std::map<u16, ServerActiveObject*> m_active_objects;
ActiveObjectMap m_active_objects;
// Outgoing network message buffer for active objects
std::queue<ActiveObjectMessage> m_active_object_messages;
// Some timers
@ -521,10 +514,13 @@ private:
// Can raise to high values like 15s with eg. map generation mods.
float m_max_lag_estimate;
// peer_ids in here should be unique, except that there may be many 0s
std::vector<RemotePlayer*> m_players;
// Particles
IntervalLimiter m_particle_management_interval;
std::map<u32, float> m_particle_spawners;
std::map<u32, u16> m_particle_spawner_attachments;
UNORDERED_MAP<u32, float> m_particle_spawners;
UNORDERED_MAP<u32, u16> m_particle_spawner_attachments;
};
#ifndef SERVER
@ -581,8 +577,8 @@ public:
void step(f32 dtime);
virtual void addPlayer(Player *player);
LocalPlayer * getLocalPlayer();
virtual void setLocalPlayer(LocalPlayer *player);
LocalPlayer *getLocalPlayer() { return m_local_player; }
/*
ClientSimpleObjects
@ -632,24 +628,20 @@ public:
u16 attachement_parent_ids[USHRT_MAX + 1];
std::list<std::string> getPlayerNames()
{ return m_player_names; }
void addPlayerName(std::string name)
{ m_player_names.push_back(name); }
void removePlayerName(std::string name)
{ m_player_names.remove(name); }
const std::list<std::string> &getPlayerNames() { return m_player_names; }
void addPlayerName(const std::string &name) { m_player_names.push_back(name); }
void removePlayerName(const std::string &name) { m_player_names.remove(name); }
void updateCameraOffset(v3s16 camera_offset)
{ m_camera_offset = camera_offset; }
v3s16 getCameraOffset()
{ return m_camera_offset; }
v3s16 getCameraOffset() const { return m_camera_offset; }
private:
ClientMap *m_map;
LocalPlayer *m_local_player;
scene::ISceneManager *m_smgr;
ITextureSource *m_texturesource;
IGameDef *m_gamedef;
IrrlichtDevice *m_irr;
std::map<u16, ClientActiveObject*> m_active_objects;
UNORDERED_MAP<u16, ClientActiveObject*> m_active_objects;
std::vector<ClientSimpleObject*> m_simple_objects;
std::queue<ClientEnvEvent> m_client_event_queue;
IntervalLimiter m_active_object_light_update_interval;

View File

@ -605,6 +605,8 @@ public:
void draw(s32 x_left, s32 y_bottom, video::IVideoDriver *driver,
gui::IGUIFont *font) const
{
// Do *not* use UNORDERED_MAP here as the order needs
// to be the same for each call to prevent flickering
std::map<std::string, Meta> m_meta;
for (std::deque<Piece>::const_iterator k = m_log.begin();
@ -615,8 +617,7 @@ public:
i != piece.values.end(); ++i) {
const std::string &id = i->first;
const float &value = i->second;
std::map<std::string, Meta>::iterator j =
m_meta.find(id);
std::map<std::string, Meta>::iterator j = m_meta.find(id);
if (j == m_meta.end()) {
m_meta[id] = Meta(value);
@ -1740,6 +1741,8 @@ private:
bool m_cache_enable_joysticks;
bool m_cache_enable_particles;
bool m_cache_enable_fog;
bool m_cache_enable_noclip;
bool m_cache_enable_free_move;
f32 m_cache_mouse_sensitivity;
f32 m_cache_joystick_frustum_sensitivity;
f32 m_repeat_right_click_time;
@ -1789,6 +1792,10 @@ Game::Game() :
&settingChangedCallback, this);
g_settings->registerChangedCallback("repeat_rightclick_time",
&settingChangedCallback, this);
g_settings->registerChangedCallback("noclip",
&settingChangedCallback, this);
g_settings->registerChangedCallback("free_move",
&settingChangedCallback, this);
readSettings();
@ -1838,6 +1845,10 @@ Game::~Game()
&settingChangedCallback, this);
g_settings->deregisterChangedCallback("repeat_rightclick_time",
&settingChangedCallback, this);
g_settings->deregisterChangedCallback("noclip",
&settingChangedCallback, this);
g_settings->deregisterChangedCallback("free_move",
&settingChangedCallback, this);
}
bool Game::startup(bool *kill,
@ -2572,7 +2583,7 @@ inline bool Game::handleCallbacks()
if (g_gamecallback->changevolume_requested) {
(new GUIVolumeChange(guienv, guiroot, -1,
&g_menumgr, client))->drop();
&g_menumgr))->drop();
g_gamecallback->changevolume_requested = false;
}
@ -2903,7 +2914,7 @@ void Game::processItemSelection(u16 *new_playeritem)
s32 wheel = input->getMouseWheel();
u16 max_item = MYMIN(PLAYER_INVENTORY_SIZE - 1,
player->hud_hotbar_itemcount - 1);
player->hud_hotbar_itemcount - 1);
s32 dir = wheel;
@ -3414,12 +3425,12 @@ void Game::processClientEvents(CameraOrientation *cam, float *damage_flash)
//u16 damage = event.player_damage.amount;
//infostream<<"Player damage: "<<damage<<std::endl;
*damage_flash += 100.0;
*damage_flash += 8.0 * event.player_damage.amount;
*damage_flash += 95.0 + 3.2 * event.player_damage.amount;
*damage_flash = MYMIN(*damage_flash, 127.0);
player->hurt_tilt_timer = 1.5;
player->hurt_tilt_strength = event.player_damage.amount / 4;
player->hurt_tilt_strength = rangelim(player->hurt_tilt_strength, 1.0, 4.0);
player->hurt_tilt_strength =
rangelim(event.player_damage.amount / 4, 1.0, 4.0);
MtEvent *e = new SimpleTriggerEvent("PlayerDamage");
gamedef->event()->put(e);
@ -4154,7 +4165,7 @@ void Game::updateFrame(ProfilerGraph *graph, RunStats *stats,
float direct_brightness;
bool sunlight_seen;
if (g_settings->getBool("free_move")) {
if (m_cache_enable_noclip && m_cache_enable_free_move) {
direct_brightness = time_brightness;
sunlight_seen = true;
} else {
@ -4225,7 +4236,7 @@ void Game::updateFrame(ProfilerGraph *graph, RunStats *stats,
runData->fog_range * 1.0,
0.01,
false, // pixel fog
false // range fog
true // range fog
);
} else {
driver->setFog(
@ -4332,10 +4343,7 @@ void Game::updateFrame(ProfilerGraph *graph, RunStats *stats,
Damage flash
*/
if (runData->damage_flash > 0.0) {
video::SColor color(std::min(runData->damage_flash, 180.0f),
180,
0,
0);
video::SColor color(runData->damage_flash, 180, 0, 0);
driver->draw2DRectangle(color,
core::rect<s32>(0, 0, screensize.X, screensize.Y),
NULL);
@ -4602,6 +4610,9 @@ void Game::readSettings()
m_cache_joystick_frustum_sensitivity = g_settings->getFloat("joystick_frustum_sensitivity");
m_repeat_right_click_time = g_settings->getFloat("repeat_rightclick_time");
m_cache_enable_noclip = g_settings->getBool("noclip");
m_cache_enable_free_move = g_settings->getBool("free_move");
m_cache_mouse_sensitivity = rangelim(m_cache_mouse_sensitivity, 0.001, 100.0);
}

View File

@ -182,3 +182,15 @@ std::string gob_cmd_update_nametag_attributes(video::SColor color)
writeARGB8(os, color);
return os.str();
}
std::string gob_cmd_update_infant(u16 id, u8 type, std::string client_initialization_data)
{
std::ostringstream os(std::ios::binary);
// command
writeU8(os, GENERIC_CMD_SPAWN_INFANT);
// parameters
writeU16(os, id);
writeU8(os, type);
os<<serializeLongString(client_initialization_data);
return os.str();
}

View File

@ -35,7 +35,8 @@ enum GenericCMD {
GENERIC_CMD_SET_BONE_POSITION,
GENERIC_CMD_ATTACH_TO,
GENERIC_CMD_SET_PHYSICS_OVERRIDE,
GENERIC_CMD_UPDATE_NAMETAG_ATTRIBUTES
GENERIC_CMD_UPDATE_NAMETAG_ATTRIBUTES,
GENERIC_CMD_SPAWN_INFANT
};
#include "object_properties.h"
@ -77,5 +78,7 @@ std::string gob_cmd_update_attachment(int parent_id, std::string bone, v3f posit
std::string gob_cmd_update_nametag_attributes(video::SColor color);
std::string gob_cmd_update_infant(u16 id, u8 type, std::string client_initialization_data);
#endif

View File

@ -279,6 +279,32 @@ void GUIFormSpecMenu::parseSize(parserData* data,std::string element)
errorstream<< "Invalid size element (" << parts.size() << "): '" << element << "'" << std::endl;
}
void GUIFormSpecMenu::parseContainer(parserData* data, std::string element)
{
std::vector<std::string> parts = split(element, ',');
if (parts.size() >= 2) {
if (parts[1].find(';') != std::string::npos)
parts[1] = parts[1].substr(0, parts[1].find(';'));
container_stack.push(pos_offset);
pos_offset.X += MYMAX(0, stof(parts[0]));
pos_offset.Y += MYMAX(0, stof(parts[1]));
return;
}
errorstream<< "Invalid container start element (" << parts.size() << "): '" << element << "'" << std::endl;
}
void GUIFormSpecMenu::parseContainerEnd(parserData* data)
{
if (container_stack.empty()) {
errorstream<< "Invalid container end element, no matching container start element" << std::endl;
} else {
pos_offset = container_stack.top();
container_stack.pop();
}
}
void GUIFormSpecMenu::parseList(parserData* data,std::string element)
{
if (m_gamedef == 0) {
@ -309,7 +335,7 @@ void GUIFormSpecMenu::parseList(parserData* data,std::string element)
else
loc.deSerialize(location);
v2s32 pos = padding + AbsoluteRect.UpperLeftCorner;
v2s32 pos = padding + AbsoluteRect.UpperLeftCorner + pos_offset * spacing;
pos.X += stof(v_pos[0]) * (float)spacing.X;
pos.Y += stof(v_pos[1]) * (float)spacing.Y;
@ -386,7 +412,7 @@ void GUIFormSpecMenu::parseCheckbox(parserData* data,std::string element)
MY_CHECKPOS("checkbox",0);
v2s32 pos = padding;
v2s32 pos = padding + pos_offset * spacing;
pos.X += stof(v_pos[0]) * (float) spacing.X;
pos.Y += stof(v_pos[1]) * (float) spacing.Y;
@ -437,7 +463,7 @@ void GUIFormSpecMenu::parseScrollBar(parserData* data, std::string element)
MY_CHECKPOS("scrollbar",0);
v2s32 pos = padding;
v2s32 pos = padding + pos_offset * spacing;
pos.X += stof(v_pos[0]) * (float) spacing.X;
pos.Y += stof(v_pos[1]) * (float) spacing.Y;
@ -495,10 +521,10 @@ void GUIFormSpecMenu::parseImage(parserData* data,std::string element)
std::vector<std::string> v_geom = split(parts[1],',');
std::string name = unescape_string(parts[2]);
MY_CHECKPOS("image",0);
MY_CHECKGEOM("image",1);
MY_CHECKPOS("image", 0);
MY_CHECKGEOM("image", 1);
v2s32 pos = padding + AbsoluteRect.UpperLeftCorner;
v2s32 pos = padding + AbsoluteRect.UpperLeftCorner + pos_offset * spacing;
pos.X += stof(v_pos[0]) * (float) spacing.X;
pos.Y += stof(v_pos[1]) * (float) spacing.Y;
@ -506,23 +532,21 @@ void GUIFormSpecMenu::parseImage(parserData* data,std::string element)
geom.X = stof(v_geom[0]) * (float)imgsize.X;
geom.Y = stof(v_geom[1]) * (float)imgsize.Y;
if(!data->explicit_size)
if (!data->explicit_size)
warningstream<<"invalid use of image without a size[] element"<<std::endl;
m_images.push_back(ImageDrawSpec(name, pos, geom));
return;
}
if (parts.size() == 2) {
} else if (parts.size() == 2) {
std::vector<std::string> v_pos = split(parts[0],',');
std::string name = unescape_string(parts[1]);
MY_CHECKPOS("image",0);
MY_CHECKPOS("image", 0);
v2s32 pos = padding + AbsoluteRect.UpperLeftCorner;
v2s32 pos = padding + AbsoluteRect.UpperLeftCorner + pos_offset * spacing;
pos.X += stof(v_pos[0]) * (float) spacing.X;
pos.Y += stof(v_pos[1]) * (float) spacing.Y;
if(!data->explicit_size)
if (!data->explicit_size)
warningstream<<"invalid use of image without a size[] element"<<std::endl;
m_images.push_back(ImageDrawSpec(name, pos));
return;
@ -544,7 +568,7 @@ void GUIFormSpecMenu::parseItemImage(parserData* data,std::string element)
MY_CHECKPOS("itemimage",0);
MY_CHECKGEOM("itemimage",1);
v2s32 pos = padding + AbsoluteRect.UpperLeftCorner;
v2s32 pos = padding + AbsoluteRect.UpperLeftCorner + pos_offset * spacing;
pos.X += stof(v_pos[0]) * (float) spacing.X;
pos.Y += stof(v_pos[1]) * (float) spacing.Y;
@ -576,7 +600,7 @@ void GUIFormSpecMenu::parseButton(parserData* data,std::string element,
MY_CHECKPOS("button",0);
MY_CHECKGEOM("button",1);
v2s32 pos = padding;
v2s32 pos = padding + pos_offset * spacing;
pos.X += stof(v_pos[0]) * (float)spacing.X;
pos.Y += stof(v_pos[1]) * (float)spacing.Y;
@ -629,9 +653,9 @@ void GUIFormSpecMenu::parseBackground(parserData* data,std::string element)
MY_CHECKPOS("background",0);
MY_CHECKGEOM("background",1);
v2s32 pos = padding + AbsoluteRect.UpperLeftCorner;
pos.X += stof(v_pos[0]) * (float)spacing.X - ((float)spacing.X-(float)imgsize.X)/2;
pos.Y += stof(v_pos[1]) * (float)spacing.Y - ((float)spacing.Y-(float)imgsize.Y)/2;
v2s32 pos = padding + AbsoluteRect.UpperLeftCorner + pos_offset * spacing;
pos.X += stof(v_pos[0]) * (float)spacing.X - ((float)spacing.X - (float)imgsize.X)/2;
pos.Y += stof(v_pos[1]) * (float)spacing.Y - ((float)spacing.Y - (float)imgsize.Y)/2;
v2s32 geom;
geom.X = stof(v_geom[0]) * (float)spacing.X;
@ -705,7 +729,7 @@ void GUIFormSpecMenu::parseTable(parserData* data,std::string element)
MY_CHECKPOS("table",0);
MY_CHECKGEOM("table",1);
v2s32 pos = padding;
v2s32 pos = padding + pos_offset * spacing;
pos.X += stof(v_pos[0]) * (float)spacing.X;
pos.Y += stof(v_pos[1]) * (float)spacing.Y;
@ -776,7 +800,7 @@ void GUIFormSpecMenu::parseTextList(parserData* data,std::string element)
MY_CHECKPOS("textlist",0);
MY_CHECKGEOM("textlist",1);
v2s32 pos = padding;
v2s32 pos = padding + pos_offset * spacing;
pos.X += stof(v_pos[0]) * (float)spacing.X;
pos.Y += stof(v_pos[1]) * (float)spacing.Y;
@ -841,7 +865,7 @@ void GUIFormSpecMenu::parseDropDown(parserData* data,std::string element)
MY_CHECKPOS("dropdown",0);
v2s32 pos = padding;
v2s32 pos = padding + pos_offset * spacing;
pos.X += stof(v_pos[0]) * (float)spacing.X;
pos.Y += stof(v_pos[1]) * (float)spacing.Y;
@ -890,6 +914,16 @@ void GUIFormSpecMenu::parseDropDown(parserData* data,std::string element)
<< element << "'" << std::endl;
}
void GUIFormSpecMenu::parseFieldCloseOnEnter(parserData *data,
const std::string &element)
{
std::vector<std::string> parts = split(element,';');
if (parts.size() == 2 ||
(parts.size() > 2 && m_formspec_version > FORMSPEC_API_VERSION)) {
field_close_on_enter[parts[0]] = is_yes(parts[1]);
}
}
void GUIFormSpecMenu::parsePwdField(parserData* data,std::string element)
{
std::vector<std::string> parts = split(element,';');
@ -905,7 +939,7 @@ void GUIFormSpecMenu::parsePwdField(parserData* data,std::string element)
MY_CHECKPOS("pwdfield",0);
MY_CHECKGEOM("pwdfield",1);
v2s32 pos;
v2s32 pos = pos_offset * spacing;
pos.X += stof(v_pos[0]) * (float)spacing.X;
pos.Y += stof(v_pos[1]) * (float)spacing.Y;
@ -953,8 +987,11 @@ void GUIFormSpecMenu::parsePwdField(parserData* data,std::string element)
evt.KeyInput.PressedDown = true;
e->OnEvent(evt);
if (parts.size() >= 5 && !is_yes(parts[4])) {
spec.close_on_enter = false;
if (parts.size() >= 5) {
// TODO: remove after 2016-11-03
warningstream << "pwdfield: use field_close_on_enter[name, enabled]" <<
" instead of the 5th param" << std::endl;
field_close_on_enter[name] = is_yes(parts[4]);
}
m_fields.push_back(spec);
@ -975,7 +1012,7 @@ void GUIFormSpecMenu::parseSimpleField(parserData* data,
if(data->explicit_size)
warningstream<<"invalid use of unpositioned \"field\" in inventory"<<std::endl;
v2s32 pos = padding + AbsoluteRect.UpperLeftCorner;
v2s32 pos = padding + AbsoluteRect.UpperLeftCorner + pos_offset * spacing;
pos.Y = ((m_fields.size()+2)*60);
v2s32 size = DesiredRect.getSize();
@ -1038,8 +1075,11 @@ void GUIFormSpecMenu::parseSimpleField(parserData* data,
}
}
if (parts.size() >= 4 && !is_yes(parts[3])) {
spec.close_on_enter = false;
if (parts.size() >= 4) {
// TODO: remove after 2016-11-03
warningstream << "field/simple: use field_close_on_enter[name, enabled]" <<
" instead of the 4th param" << std::endl;
field_close_on_enter[name] = is_yes(parts[3]);
}
m_fields.push_back(spec);
@ -1058,9 +1098,9 @@ void GUIFormSpecMenu::parseTextArea(parserData* data,
MY_CHECKPOS(type,0);
MY_CHECKGEOM(type,1);
v2s32 pos;
pos.X = stof(v_pos[0]) * (float) spacing.X;
pos.Y = stof(v_pos[1]) * (float) spacing.Y;
v2s32 pos = pos_offset * spacing;
pos.X += stof(v_pos[0]) * (float) spacing.X;
pos.Y += stof(v_pos[1]) * (float) spacing.Y;
v2s32 geom;
@ -1147,8 +1187,11 @@ void GUIFormSpecMenu::parseTextArea(parserData* data,
}
}
if (parts.size() >= 6 && !is_yes(parts[5])) {
spec.close_on_enter = false;
if (parts.size() >= 6) {
// TODO: remove after 2016-11-03
warningstream << "field/textarea: use field_close_on_enter[name, enabled]" <<
" instead of the 6th param" << std::endl;
field_close_on_enter[name] = is_yes(parts[5]);
}
m_fields.push_back(spec);
@ -1185,7 +1228,7 @@ void GUIFormSpecMenu::parseLabel(parserData* data,std::string element)
MY_CHECKPOS("label",0);
v2s32 pos = padding;
v2s32 pos = padding + pos_offset * spacing;
pos.X += stof(v_pos[0]) * (float)spacing.X;
pos.Y += (stof(v_pos[1]) + 7.0/30.0) * (float)spacing.Y;
@ -1242,7 +1285,7 @@ void GUIFormSpecMenu::parseVertLabel(parserData* data,std::string element)
MY_CHECKPOS("vertlabel",1);
v2s32 pos = padding;
v2s32 pos = padding + pos_offset * spacing;
pos.X += stof(v_pos[0]) * (float)spacing.X;
pos.Y += stof(v_pos[1]) * (float)spacing.Y;
@ -1296,7 +1339,7 @@ void GUIFormSpecMenu::parseImageButton(parserData* data,std::string element,
MY_CHECKPOS("imagebutton",0);
MY_CHECKGEOM("imagebutton",1);
v2s32 pos = padding;
v2s32 pos = padding + pos_offset * spacing;
pos.X += stof(v_pos[0]) * (float)spacing.X;
pos.Y += stof(v_pos[1]) * (float)spacing.Y;
v2s32 geom;
@ -1401,7 +1444,7 @@ void GUIFormSpecMenu::parseTabHeader(parserData* data,std::string element)
spec.ftype = f_TabHeader;
v2s32 pos(0,0);
v2s32 pos = pos_offset * spacing;
pos.X += stof(v_pos[0]) * (float)spacing.X;
pos.Y += stof(v_pos[1]) * (float)spacing.Y - m_btn_height * 2;
v2s32 geom;
@ -1466,7 +1509,7 @@ void GUIFormSpecMenu::parseItemImageButton(parserData* data,std::string element)
MY_CHECKPOS("itemimagebutton",0);
MY_CHECKGEOM("itemimagebutton",1);
v2s32 pos = padding;
v2s32 pos = padding + pos_offset * spacing;
pos.X += stof(v_pos[0]) * (float)spacing.X;
pos.Y += stof(v_pos[1]) * (float)spacing.Y;
v2s32 geom;
@ -1504,7 +1547,7 @@ void GUIFormSpecMenu::parseItemImageButton(parserData* data,std::string element)
rect+=data->basepos-padding;
spec.rect=rect;
m_fields.push_back(spec);
pos = padding + AbsoluteRect.UpperLeftCorner;
pos = padding + AbsoluteRect.UpperLeftCorner + pos_offset * spacing;
pos.X += stof(v_pos[0]) * (float) spacing.X;
pos.Y += stof(v_pos[1]) * (float) spacing.Y;
m_itemimages.push_back(ImageDrawSpec("", item_name, e, pos, geom));
@ -1527,7 +1570,7 @@ void GUIFormSpecMenu::parseBox(parserData* data,std::string element)
MY_CHECKPOS("box",0);
MY_CHECKGEOM("box",1);
v2s32 pos = padding + AbsoluteRect.UpperLeftCorner;
v2s32 pos = padding + AbsoluteRect.UpperLeftCorner + pos_offset * spacing;
pos.X += stof(v_pos[0]) * (float) spacing.X;
pos.Y += stof(v_pos[1]) * (float) spacing.Y;
@ -1689,8 +1732,18 @@ void GUIFormSpecMenu::parseElement(parserData* data, std::string element)
std::string type = trim(parts[0]);
std::string description = trim(parts[1]);
if (type == "container") {
parseContainer(data, description);
return;
}
if (type == "container_end") {
parseContainerEnd(data);
return;
}
if (type == "list") {
parseList(data,description);
parseList(data, description);
return;
}
@ -1700,22 +1753,22 @@ void GUIFormSpecMenu::parseElement(parserData* data, std::string element)
}
if (type == "checkbox") {
parseCheckbox(data,description);
parseCheckbox(data, description);
return;
}
if (type == "image") {
parseImage(data,description);
parseImage(data, description);
return;
}
if (type == "item_image") {
parseItemImage(data,description);
parseItemImage(data, description);
return;
}
if ((type == "button") || (type == "button_exit")) {
parseButton(data,description,type);
if (type == "button" || type == "button_exit") {
parseButton(data, description, type);
return;
}
@ -1749,6 +1802,11 @@ void GUIFormSpecMenu::parseElement(parserData* data, std::string element)
return;
}
if (type == "field_close_on_enter") {
parseFieldCloseOnEnter(data, description);
return;
}
if (type == "pwdfield") {
parsePwdField(data,description);
return;
@ -2036,10 +2094,16 @@ void GUIFormSpecMenu::regenerateGui(v2u32 screensize)
gui::IGUIFont *old_font = skin->getFont();
skin->setFont(m_font);
pos_offset = v2s32();
for (; i< elements.size(); i++) {
parseElement(&mydata, elements[i]);
}
if (!container_stack.empty()) {
errorstream << "Invalid formspec string: container was never closed!"
<< std::endl;
}
// If there are fields without explicit size[], add a "Proceed"
// button and adjust size to fit all the fields.
if (m_fields.size() && !mydata.explicit_size) {
@ -3649,7 +3713,11 @@ bool GUIFormSpecMenu::OnEvent(const SEvent& event)
if (s.ftype == f_Unknown &&
s.fid == event.GUIEvent.Caller->getID()) {
current_field_enter_pending = s.fname;
close_on_enter = s.close_on_enter;
UNORDERED_MAP<std::string, bool>::const_iterator it =
field_close_on_enter.find(s.fname);
if (it != field_close_on_enter.end())
close_on_enter = (*it).second;
break;
}
}

View File

@ -22,6 +22,7 @@ with this program; if not, write to the Free Software Foundation, Inc.,
#define GUIINVENTORYMENU_HEADER
#include <utility>
#include <stack>
#include "irrlichttypes_extrabloated.h"
#include "inventory.h"
@ -211,7 +212,6 @@ class GUIFormSpecMenu : public GUIModalMenu
flabel(label),
fid(id),
send(false),
close_on_enter(false),
ftype(f_Unknown),
is_exit(false)
{
@ -223,7 +223,6 @@ class GUIFormSpecMenu : public GUIModalMenu
std::wstring fdefault;
int fid;
bool send;
bool close_on_enter; // used by text fields
FormspecFieldType ftype;
bool is_exit;
core::rect<s32> rect;
@ -380,6 +379,8 @@ protected:
v2s32 spacing;
v2s32 imgsize;
v2s32 offset;
v2s32 pos_offset;
std::stack<v2s32> container_stack;
irr::IrrlichtDevice* m_device;
InventoryManager *m_invmgr;
@ -397,6 +398,7 @@ protected:
std::vector<ImageDrawSpec> m_images;
std::vector<ImageDrawSpec> m_itemimages;
std::vector<BoxDrawSpec> m_boxes;
UNORDERED_MAP<std::string, bool> field_close_on_enter;
std::vector<FieldSpec> m_fields;
std::vector<StaticTextSpec> m_static_texts;
std::vector<std::pair<FieldSpec,GUITable*> > m_tables;
@ -406,8 +408,6 @@ protected:
std::vector<std::pair<FieldSpec, std::vector<std::string> > > m_dropdowns;
ItemSpec *m_selected_item;
f32 m_timer1;
f32 m_timer2;
u32 m_selected_amount;
bool m_selected_dragging;
@ -461,7 +461,7 @@ private:
GUITable::TableOptions table_options;
GUITable::TableColumns table_columns;
// used to restore table selection/scroll/treeview state
std::map<std::string, GUITable::DynamicData> table_dyndata;
UNORDERED_MAP<std::string, GUITable::DynamicData> table_dyndata;
} parserData;
typedef struct {
@ -474,13 +474,15 @@ private:
fs_key_pendig current_keys_pending;
std::string current_field_enter_pending;
void parseElement(parserData* data,std::string element);
void parseElement(parserData* data, std::string element);
void parseSize(parserData* data,std::string element);
void parseList(parserData* data,std::string element);
void parseListRing(parserData* data,std::string element);
void parseCheckbox(parserData* data,std::string element);
void parseImage(parserData* data,std::string element);
void parseSize(parserData* data, std::string element);
void parseContainer(parserData* data, std::string element);
void parseContainerEnd(parserData* data);
void parseList(parserData* data, std::string element);
void parseListRing(parserData* data, std::string element);
void parseCheckbox(parserData* data, std::string element);
void parseImage(parserData* data, std::string element);
void parseItemImage(parserData* data,std::string element);
void parseButton(parserData* data,std::string element,std::string typ);
void parseBackground(parserData* data,std::string element);
@ -489,6 +491,7 @@ private:
void parseTable(parserData* data,std::string element);
void parseTextList(parserData* data,std::string element);
void parseDropDown(parserData* data,std::string element);
void parseFieldCloseOnEnter(parserData *data, const std::string &element);
void parsePwdField(parserData* data,std::string element);
void parseField(parserData* data,std::string element,std::string type);
void parseSimpleField(parserData* data,std::vector<std::string> &parts);

View File

@ -565,10 +565,8 @@ void GUITable::setSelected(s32 index)
--index; // Switch from 1-based indexing to 0-based indexing
s32 rowcount = m_rows.size();
if (rowcount == 0) {
if (rowcount == 0 || index < 0) {
return;
} else if (index < 0) {
index = 0;
} else if (index >= rowcount) {
index = rowcount - 1;
}

View File

@ -37,8 +37,7 @@ const int ID_soundSlider = 266;
GUIVolumeChange::GUIVolumeChange(gui::IGUIEnvironment* env,
gui::IGUIElement* parent, s32 id,
IMenuManager *menumgr,
Client* client
IMenuManager *menumgr
):
GUIModalMenu(env, parent, id, menumgr)
{
@ -51,26 +50,17 @@ GUIVolumeChange::~GUIVolumeChange()
void GUIVolumeChange::removeChildren()
{
{
gui::IGUIElement *e = getElementFromId(ID_soundText1);
if(e != NULL)
e->remove();
}
{
gui::IGUIElement *e = getElementFromId(ID_soundText2);
if(e != NULL)
e->remove();
}
{
gui::IGUIElement *e = getElementFromId(ID_soundExitButton);
if(e != NULL)
e->remove();
}
{
gui::IGUIElement *e = getElementFromId(ID_soundSlider);
if(e != NULL)
e->remove();
}
if (gui::IGUIElement *e = getElementFromId(ID_soundText1))
e->remove();
if (gui::IGUIElement *e = getElementFromId(ID_soundText2))
e->remove();
if (gui::IGUIElement *e = getElementFromId(ID_soundExitButton))
e->remove();
if (gui::IGUIElement *e = getElementFromId(ID_soundSlider))
e->remove();
}
void GUIVolumeChange::regenerateGui(v2u32 screensize)
@ -95,7 +85,7 @@ void GUIVolumeChange::regenerateGui(v2u32 screensize)
v2s32 size = rect.getSize();
v2s32 topleft_client(40, 0);
int volume=(int)(g_settings->getFloat("sound_volume")*100);
int volume = (int)(g_settings->getFloat("sound_volume")*100);
/*
Add stuff
*/
@ -137,45 +127,43 @@ void GUIVolumeChange::drawMenu()
if (!skin)
return;
video::IVideoDriver* driver = Environment->getVideoDriver();
video::SColor bgcolor(140,0,0,0);
video::SColor bgcolor(140, 0, 0, 0);
driver->draw2DRectangle(bgcolor, AbsoluteRect, &AbsoluteClippingRect);
gui::IGUIElement::draw();
}
bool GUIVolumeChange::OnEvent(const SEvent& event)
{
if(event.EventType==EET_KEY_INPUT_EVENT)
{
if(event.KeyInput.Key==KEY_ESCAPE && event.KeyInput.PressedDown)
{
if (event.EventType == EET_KEY_INPUT_EVENT) {
if (event.KeyInput.Key == KEY_ESCAPE && event.KeyInput.PressedDown) {
quitMenu();
return true;
}
if(event.KeyInput.Key==KEY_RETURN && event.KeyInput.PressedDown)
{
if (event.KeyInput.Key == KEY_RETURN && event.KeyInput.PressedDown) {
quitMenu();
return true;
}
}
if(event.GUIEvent.EventType==gui::EGET_BUTTON_CLICKED)
{
if (event.GUIEvent.Caller->getID() == ID_soundExitButton)
{
quitMenu();
return true;
}
if (event.GUIEvent.EventType == gui::EGET_BUTTON_CLICKED) {
if (event.GUIEvent.Caller->getID() == ID_soundExitButton) {
quitMenu();
return true;
}
if(event.GUIEvent.EventType==gui::EGET_SCROLL_BAR_CHANGED)
{
if (event.GUIEvent.Caller->getID() == ID_soundSlider)
{
s32 pos = ((gui::IGUIScrollBar*)event.GUIEvent.Caller)->getPos();
g_settings->setFloat("sound_volume",(float)pos/100);
gui::IGUIElement *e = getElementFromId(ID_soundText2);
e->setText( core::stringw(pos).c_str() );
return true;
}
}
if (event.GUIEvent.EventType == gui::EGET_SCROLL_BAR_CHANGED) {
if (event.GUIEvent.Caller->getID() == ID_soundSlider) {
s32 pos = ((gui::IGUIScrollBar*)event.GUIEvent.Caller)->getPos();
g_settings->setFloat("sound_volume", (float)pos/100);
gui::IGUIElement *e = getElementFromId(ID_soundText2);
e->setText(core::stringw(pos).c_str());
return true;
}
}
return Parent ? Parent->OnEvent(event) : false;
}

View File

@ -30,8 +30,7 @@ class GUIVolumeChange : public GUIModalMenu
public:
GUIVolumeChange(gui::IGUIEnvironment* env,
gui::IGUIElement* parent, s32 id,
IMenuManager *menumgr,
Client* client);
IMenuManager *menumgr);
~GUIVolumeChange();
void removeChildren();

View File

@ -146,9 +146,9 @@ void ItemDefinition::serialize(std::ostream &os, u16 protocol_version) const
}
os<<serializeString(tool_capabilities_s);
writeU16(os, groups.size());
for(std::map<std::string, int>::const_iterator
for (ItemGroupList::const_iterator
i = groups.begin(); i != groups.end(); ++i){
os<<serializeString(i->first);
os << serializeString(i->first);
writeS16(os, i->second);
}
os<<serializeString(node_placement_prediction);

View File

@ -21,14 +21,14 @@ with this program; if not, write to the Free Software Foundation, Inc.,
#define ITEMGROUP_HEADER
#include <string>
#include <map>
#include "util/cpp11_container.h"
typedef std::map<std::string, int> ItemGroupList;
typedef UNORDERED_MAP<std::string, int> ItemGroupList;
static inline int itemgroup_get(const ItemGroupList &groups,
const std::string &name)
{
std::map<std::string, int>::const_iterator i = groups.find(name);
ItemGroupList::const_iterator i = groups.find(name);
if(i == groups.end())
return 0;
return i->second;

View File

@ -23,6 +23,7 @@ with this program; if not, write to the Free Software Foundation, Inc.,
#include "log.h"
#include "debug.h"
#include "util/hex.h"
#include "util/string.h"
#include "util/string.h"
@ -33,321 +34,335 @@ public:
BaseException(s) {};
};
#define CHECKKEY(x){if(strcmp(name, #x)==0) return irr::x;}
struct table_key {
const char *Name;
irr::EKEY_CODE Key;
wchar_t Char; // L'\0' means no character assigned
const char *LangName; // NULL means it doesn't have a human description
};
irr::EKEY_CODE keyname_to_keycode(const char *name)
#define DEFINEKEY1(x, lang) /* Irrlicht key without character */ \
{ #x, irr::x, L'\0', lang },
#define DEFINEKEY2(x, ch, lang) /* Irrlicht key with character */ \
{ #x, irr::x, ch, lang },
#define DEFINEKEY3(ch) /* single Irrlicht key (e.g. KEY_KEY_X) */ \
{ "KEY_KEY_" TOSTRING(ch), irr::KEY_KEY_ ## ch, (wchar_t) *TOSTRING(ch), TOSTRING(ch) },
#define DEFINEKEY4(ch) /* single Irrlicht function key (e.g. KEY_F3) */ \
{ "KEY_F" TOSTRING(ch), irr::KEY_F ## ch, L'\0', "F" TOSTRING(ch) },
#define DEFINEKEY5(ch) /* key without Irrlicht keycode */ \
{ ch, irr::KEY_KEY_CODES_COUNT, (wchar_t) *ch, ch },
#define N_(text) text
static const struct table_key table[] = {
// Keys that can be reliably mapped between Char and Key
DEFINEKEY3(0)
DEFINEKEY3(1)
DEFINEKEY3(2)
DEFINEKEY3(3)
DEFINEKEY3(4)
DEFINEKEY3(5)
DEFINEKEY3(6)
DEFINEKEY3(7)
DEFINEKEY3(8)
DEFINEKEY3(9)
DEFINEKEY3(A)
DEFINEKEY3(B)
DEFINEKEY3(C)
DEFINEKEY3(D)
DEFINEKEY3(E)
DEFINEKEY3(F)
DEFINEKEY3(G)
DEFINEKEY3(H)
DEFINEKEY3(I)
DEFINEKEY3(J)
DEFINEKEY3(K)
DEFINEKEY3(L)
DEFINEKEY3(M)
DEFINEKEY3(N)
DEFINEKEY3(O)
DEFINEKEY3(P)
DEFINEKEY3(Q)
DEFINEKEY3(R)
DEFINEKEY3(S)
DEFINEKEY3(T)
DEFINEKEY3(U)
DEFINEKEY3(V)
DEFINEKEY3(W)
DEFINEKEY3(X)
DEFINEKEY3(Y)
DEFINEKEY3(Z)
DEFINEKEY2(KEY_PLUS, L'+', "+")
DEFINEKEY2(KEY_COMMA, L',', ",")
DEFINEKEY2(KEY_MINUS, L'-', "-")
DEFINEKEY2(KEY_PERIOD, L'.', ".")
// Keys without a Char
DEFINEKEY1(KEY_LBUTTON, N_("Left Button"))
DEFINEKEY1(KEY_RBUTTON, N_("Right Button"))
DEFINEKEY1(KEY_CANCEL, N_("Cancel"))
DEFINEKEY1(KEY_MBUTTON, N_("Middle Button"))
DEFINEKEY1(KEY_XBUTTON1, N_("X Button 1"))
DEFINEKEY1(KEY_XBUTTON2, N_("X Button 2"))
DEFINEKEY1(KEY_BACK, N_("Back"))
DEFINEKEY1(KEY_TAB, N_("Tab"))
DEFINEKEY1(KEY_CLEAR, N_("Clear"))
DEFINEKEY1(KEY_RETURN, N_("Return"))
DEFINEKEY1(KEY_SHIFT, N_("Shift"))
DEFINEKEY1(KEY_CONTROL, N_("Control"))
DEFINEKEY1(KEY_MENU, N_("Menu"))
DEFINEKEY1(KEY_PAUSE, N_("Pause"))
DEFINEKEY1(KEY_CAPITAL, N_("Caps Lock"))
DEFINEKEY1(KEY_SPACE, N_("Space"))
DEFINEKEY1(KEY_PRIOR, N_("Prior"))
DEFINEKEY1(KEY_NEXT, N_("Next"))
DEFINEKEY1(KEY_END, N_("End"))
DEFINEKEY1(KEY_HOME, N_("Home"))
DEFINEKEY1(KEY_LEFT, N_("Left"))
DEFINEKEY1(KEY_UP, N_("Up"))
DEFINEKEY1(KEY_RIGHT, N_("Right"))
DEFINEKEY1(KEY_DOWN, N_("Down"))
DEFINEKEY1(KEY_SELECT, N_("Select"))
DEFINEKEY1(KEY_PRINT, N_("Print"))
DEFINEKEY1(KEY_EXECUT, N_("Execute"))
DEFINEKEY1(KEY_SNAPSHOT, N_("Snapshot"))
DEFINEKEY1(KEY_INSERT, N_("Insert"))
DEFINEKEY1(KEY_DELETE, N_("Delete"))
DEFINEKEY1(KEY_HELP, N_("Help"))
DEFINEKEY1(KEY_LWIN, N_("Left Windows"))
DEFINEKEY1(KEY_RWIN, N_("Right Windows"))
DEFINEKEY1(KEY_NUMPAD0, N_("Numpad 0")) // These are not assigned to a char
DEFINEKEY1(KEY_NUMPAD1, N_("Numpad 1")) // to prevent interference with KEY_KEY_[0-9].
DEFINEKEY1(KEY_NUMPAD2, N_("Numpad 2"))
DEFINEKEY1(KEY_NUMPAD3, N_("Numpad 3"))
DEFINEKEY1(KEY_NUMPAD4, N_("Numpad 4"))
DEFINEKEY1(KEY_NUMPAD5, N_("Numpad 5"))
DEFINEKEY1(KEY_NUMPAD6, N_("Numpad 6"))
DEFINEKEY1(KEY_NUMPAD7, N_("Numpad 7"))
DEFINEKEY1(KEY_NUMPAD8, N_("Numpad 8"))
DEFINEKEY1(KEY_NUMPAD9, N_("Numpad 9"))
DEFINEKEY1(KEY_MULTIPLY, N_("Numpad *"))
DEFINEKEY1(KEY_ADD, N_("Numpad +"))
DEFINEKEY1(KEY_SEPARATOR, N_("Numpad ."))
DEFINEKEY1(KEY_SUBTRACT, N_("Numpad -"))
DEFINEKEY1(KEY_DECIMAL, NULL)
DEFINEKEY1(KEY_DIVIDE, N_("Numpad /"))
DEFINEKEY4(1)
DEFINEKEY4(2)
DEFINEKEY4(3)
DEFINEKEY4(4)
DEFINEKEY4(5)
DEFINEKEY4(6)
DEFINEKEY4(7)
DEFINEKEY4(8)
DEFINEKEY4(9)
DEFINEKEY4(10)
DEFINEKEY4(11)
DEFINEKEY4(12)
DEFINEKEY4(13)
DEFINEKEY4(14)
DEFINEKEY4(15)
DEFINEKEY4(16)
DEFINEKEY4(17)
DEFINEKEY4(18)
DEFINEKEY4(19)
DEFINEKEY4(20)
DEFINEKEY4(21)
DEFINEKEY4(22)
DEFINEKEY4(23)
DEFINEKEY4(24)
DEFINEKEY1(KEY_NUMLOCK, N_("Num Lock"))
DEFINEKEY1(KEY_SCROLL, N_("Scroll Lock"))
DEFINEKEY1(KEY_LSHIFT, N_("Left Shift"))
DEFINEKEY1(KEY_RSHIFT, N_("Right Shift"))
DEFINEKEY1(KEY_LCONTROL, N_("Left Control"))
DEFINEKEY1(KEY_RCONTROL, N_("Right Control"))
DEFINEKEY1(KEY_LMENU, N_("Left Menu"))
DEFINEKEY1(KEY_RMENU, N_("Right Menu"))
// Rare/weird keys
DEFINEKEY1(KEY_KANA, "Kana")
DEFINEKEY1(KEY_HANGUEL, "Hangul")
DEFINEKEY1(KEY_HANGUL, "Hangul")
DEFINEKEY1(KEY_JUNJA, "Junja")
DEFINEKEY1(KEY_FINAL, "Final")
DEFINEKEY1(KEY_KANJI, "Kanji")
DEFINEKEY1(KEY_HANJA, "Hanja")
DEFINEKEY1(KEY_ESCAPE, N_("IME Escape"))
DEFINEKEY1(KEY_CONVERT, N_("IME Convert"))
DEFINEKEY1(KEY_NONCONVERT, N_("IME Nonconvert"))
DEFINEKEY1(KEY_ACCEPT, N_("IME Accept"))
DEFINEKEY1(KEY_MODECHANGE, N_("IME Mode Change"))
DEFINEKEY1(KEY_APPS, N_("Apps"))
DEFINEKEY1(KEY_SLEEP, N_("Sleep"))
#if !(IRRLICHT_VERSION_MAJOR <= 1 && IRRLICHT_VERSION_MINOR <= 7 && IRRLICHT_VERSION_REVISION < 3)
DEFINEKEY1(KEY_OEM_1, "OEM 1") // KEY_OEM_[0-9] and KEY_OEM_102 are assigned to multiple
DEFINEKEY1(KEY_OEM_2, "OEM 2") // different chars (on different platforms too) and thus w/o char
DEFINEKEY1(KEY_OEM_3, "OEM 3")
DEFINEKEY1(KEY_OEM_4, "OEM 4")
DEFINEKEY1(KEY_OEM_5, "OEM 5")
DEFINEKEY1(KEY_OEM_6, "OEM 6")
DEFINEKEY1(KEY_OEM_7, "OEM 7")
DEFINEKEY1(KEY_OEM_8, "OEM 8")
DEFINEKEY1(KEY_OEM_AX, "OEM AX")
DEFINEKEY1(KEY_OEM_102, "OEM 102")
#endif
DEFINEKEY1(KEY_ATTN, "Attn")
DEFINEKEY1(KEY_CRSEL, "CrSel")
DEFINEKEY1(KEY_EXSEL, "ExSel")
DEFINEKEY1(KEY_EREOF, N_("Erase EOF"))
DEFINEKEY1(KEY_PLAY, N_("Play"))
DEFINEKEY1(KEY_ZOOM, N_("Zoom"))
DEFINEKEY1(KEY_PA1, "PA1")
DEFINEKEY1(KEY_OEM_CLEAR, N_("OEM Clear"))
// Keys without Irrlicht keycode
DEFINEKEY5("!")
DEFINEKEY5("\"")
DEFINEKEY5("#")
DEFINEKEY5("$")
DEFINEKEY5("%")
DEFINEKEY5("&")
DEFINEKEY5("'")
DEFINEKEY5("(")
DEFINEKEY5(")")
DEFINEKEY5("*")
DEFINEKEY5("/")
DEFINEKEY5(":")
DEFINEKEY5(";")
DEFINEKEY5("<")
DEFINEKEY5("=")
DEFINEKEY5(">")
DEFINEKEY5("?")
DEFINEKEY5("@")
DEFINEKEY5("[")
DEFINEKEY5("\\")
DEFINEKEY5("]")
DEFINEKEY5("^")
DEFINEKEY5("_")
};
#undef N_
#define ARRAYSIZE(a) (sizeof(a) / sizeof((a)[0]))
struct table_key lookup_keyname(const char *name)
{
CHECKKEY(KEY_LBUTTON)
CHECKKEY(KEY_RBUTTON)
CHECKKEY(KEY_CANCEL)
CHECKKEY(KEY_MBUTTON)
CHECKKEY(KEY_XBUTTON1)
CHECKKEY(KEY_XBUTTON2)
CHECKKEY(KEY_BACK)
CHECKKEY(KEY_TAB)
CHECKKEY(KEY_CLEAR)
CHECKKEY(KEY_RETURN)
CHECKKEY(KEY_SHIFT)
CHECKKEY(KEY_CONTROL)
CHECKKEY(KEY_MENU)
CHECKKEY(KEY_PAUSE)
CHECKKEY(KEY_CAPITAL)
CHECKKEY(KEY_KANA)
CHECKKEY(KEY_HANGUEL)
CHECKKEY(KEY_HANGUL)
CHECKKEY(KEY_JUNJA)
CHECKKEY(KEY_FINAL)
CHECKKEY(KEY_HANJA)
CHECKKEY(KEY_KANJI)
CHECKKEY(KEY_ESCAPE)
CHECKKEY(KEY_CONVERT)
CHECKKEY(KEY_NONCONVERT)
CHECKKEY(KEY_ACCEPT)
CHECKKEY(KEY_MODECHANGE)
CHECKKEY(KEY_SPACE)
CHECKKEY(KEY_PRIOR)
CHECKKEY(KEY_NEXT)
CHECKKEY(KEY_END)
CHECKKEY(KEY_HOME)
CHECKKEY(KEY_LEFT)
CHECKKEY(KEY_UP)
CHECKKEY(KEY_RIGHT)
CHECKKEY(KEY_DOWN)
CHECKKEY(KEY_SELECT)
CHECKKEY(KEY_PRINT)
CHECKKEY(KEY_EXECUT)
CHECKKEY(KEY_SNAPSHOT)
CHECKKEY(KEY_INSERT)
CHECKKEY(KEY_DELETE)
CHECKKEY(KEY_HELP)
CHECKKEY(KEY_KEY_0)
CHECKKEY(KEY_KEY_1)
CHECKKEY(KEY_KEY_2)
CHECKKEY(KEY_KEY_3)
CHECKKEY(KEY_KEY_4)
CHECKKEY(KEY_KEY_5)
CHECKKEY(KEY_KEY_6)
CHECKKEY(KEY_KEY_7)
CHECKKEY(KEY_KEY_8)
CHECKKEY(KEY_KEY_9)
CHECKKEY(KEY_KEY_A)
CHECKKEY(KEY_KEY_B)
CHECKKEY(KEY_KEY_C)
CHECKKEY(KEY_KEY_D)
CHECKKEY(KEY_KEY_E)
CHECKKEY(KEY_KEY_F)
CHECKKEY(KEY_KEY_G)
CHECKKEY(KEY_KEY_H)
CHECKKEY(KEY_KEY_I)
CHECKKEY(KEY_KEY_J)
CHECKKEY(KEY_KEY_K)
CHECKKEY(KEY_KEY_L)
CHECKKEY(KEY_KEY_M)
CHECKKEY(KEY_KEY_N)
CHECKKEY(KEY_KEY_O)
CHECKKEY(KEY_KEY_P)
CHECKKEY(KEY_KEY_Q)
CHECKKEY(KEY_KEY_R)
CHECKKEY(KEY_KEY_S)
CHECKKEY(KEY_KEY_T)
CHECKKEY(KEY_KEY_U)
CHECKKEY(KEY_KEY_V)
CHECKKEY(KEY_KEY_W)
CHECKKEY(KEY_KEY_X)
CHECKKEY(KEY_KEY_Y)
CHECKKEY(KEY_KEY_Z)
CHECKKEY(KEY_LWIN)
CHECKKEY(KEY_RWIN)
CHECKKEY(KEY_APPS)
CHECKKEY(KEY_SLEEP)
CHECKKEY(KEY_NUMPAD0)
CHECKKEY(KEY_NUMPAD1)
CHECKKEY(KEY_NUMPAD2)
CHECKKEY(KEY_NUMPAD3)
CHECKKEY(KEY_NUMPAD4)
CHECKKEY(KEY_NUMPAD5)
CHECKKEY(KEY_NUMPAD6)
CHECKKEY(KEY_NUMPAD7)
CHECKKEY(KEY_NUMPAD8)
CHECKKEY(KEY_NUMPAD9)
CHECKKEY(KEY_MULTIPLY)
CHECKKEY(KEY_ADD)
CHECKKEY(KEY_SEPARATOR)
CHECKKEY(KEY_SUBTRACT)
CHECKKEY(KEY_DECIMAL)
CHECKKEY(KEY_DIVIDE)
CHECKKEY(KEY_F1)
CHECKKEY(KEY_F2)
CHECKKEY(KEY_F3)
CHECKKEY(KEY_F4)
CHECKKEY(KEY_F5)
CHECKKEY(KEY_F6)
CHECKKEY(KEY_F7)
CHECKKEY(KEY_F8)
CHECKKEY(KEY_F9)
CHECKKEY(KEY_F10)
CHECKKEY(KEY_F11)
CHECKKEY(KEY_F12)
CHECKKEY(KEY_F13)
CHECKKEY(KEY_F14)
CHECKKEY(KEY_F15)
CHECKKEY(KEY_F16)
CHECKKEY(KEY_F17)
CHECKKEY(KEY_F18)
CHECKKEY(KEY_F19)
CHECKKEY(KEY_F20)
CHECKKEY(KEY_F21)
CHECKKEY(KEY_F22)
CHECKKEY(KEY_F23)
CHECKKEY(KEY_F24)
CHECKKEY(KEY_NUMLOCK)
CHECKKEY(KEY_SCROLL)
CHECKKEY(KEY_LSHIFT)
CHECKKEY(KEY_RSHIFT)
CHECKKEY(KEY_LCONTROL)
CHECKKEY(KEY_RCONTROL)
CHECKKEY(KEY_LMENU)
CHECKKEY(KEY_RMENU)
CHECKKEY(KEY_PLUS)
CHECKKEY(KEY_COMMA)
CHECKKEY(KEY_MINUS)
CHECKKEY(KEY_PERIOD)
CHECKKEY(KEY_ATTN)
CHECKKEY(KEY_CRSEL)
CHECKKEY(KEY_EXSEL)
CHECKKEY(KEY_EREOF)
CHECKKEY(KEY_PLAY)
CHECKKEY(KEY_ZOOM)
CHECKKEY(KEY_PA1)
CHECKKEY(KEY_OEM_CLEAR)
for (u16 i = 0; i < ARRAYSIZE(table); i++) {
if (strcmp(table[i].Name, name) == 0)
return table[i];
}
throw UnknownKeycode(name);
}
static const char *KeyNames[] =
{ "-", "KEY_LBUTTON", "KEY_RBUTTON", "KEY_CANCEL", "KEY_MBUTTON", "KEY_XBUTTON1",
"KEY_XBUTTON2", "-", "KEY_BACK", "KEY_TAB", "-", "-", "KEY_CLEAR", "KEY_RETURN", "-",
"-", "KEY_SHIFT", "KEY_CONTROL", "KEY_MENU", "KEY_PAUSE", "KEY_CAPITAL", "KEY_KANA", "-",
"KEY_JUNJA", "KEY_FINAL", "KEY_KANJI", "-", "KEY_ESCAPE", "KEY_CONVERT", "KEY_NONCONVERT",
"KEY_ACCEPT", "KEY_MODECHANGE", "KEY_SPACE", "KEY_PRIOR", "KEY_NEXT", "KEY_END",
"KEY_HOME", "KEY_LEFT", "KEY_UP", "KEY_RIGHT", "KEY_DOWN", "KEY_SELECT", "KEY_PRINT",
"KEY_EXECUTE", "KEY_SNAPSHOT", "KEY_INSERT", "KEY_DELETE", "KEY_HELP", "KEY_KEY_0",
"KEY_KEY_1", "KEY_KEY_2", "KEY_KEY_3", "KEY_KEY_4", "KEY_KEY_5",
"KEY_KEY_6", "KEY_KEY_7", "KEY_KEY_8", "KEY_KEY_9", "-", "-", "-", "-",
"-", "-", "-", "KEY_KEY_A", "KEY_KEY_B", "KEY_KEY_C", "KEY_KEY_D",
"KEY_KEY_E", "KEY_KEY_F", "KEY_KEY_G", "KEY_KEY_H", "KEY_KEY_I",
"KEY_KEY_J", "KEY_KEY_K", "KEY_KEY_L", "KEY_KEY_M", "KEY_KEY_N",
"KEY_KEY_O", "KEY_KEY_P", "KEY_KEY_Q", "KEY_KEY_R", "KEY_KEY_S",
"KEY_KEY_T", "KEY_KEY_U", "KEY_KEY_V", "KEY_KEY_W", "KEY_KEY_X",
"KEY_KEY_Y", "KEY_KEY_Z", "KEY_LWIN", "KEY_RWIN", "KEY_APPS", "-",
"KEY_SLEEP", "KEY_NUMPAD0", "KEY_NUMPAD1", "KEY_NUMPAD2", "KEY_NUMPAD3",
"KEY_NUMPAD4", "KEY_NUMPAD5", "KEY_NUMPAD6", "KEY_NUMPAD7",
"KEY_NUMPAD8", "KEY_NUMPAD9", "KEY_MULTIPLY", "KEY_ADD", "KEY_SEPERATOR",
"KEY_SUBTRACT", "KEY_DECIMAL", "KEY_DIVIDE", "KEY_F1", "KEY_F2", "KEY_F3",
"KEY_F4", "KEY_F5", "KEY_F6", "KEY_F7", "KEY_F8", "KEY_F9", "KEY_F10",
"KEY_F11", "KEY_F12", "KEY_F13", "KEY_F14", "KEY_F15", "KEY_F16",
"KEY_F17", "KEY_F18", "KEY_F19", "KEY_F20", "KEY_F21", "KEY_F22",
"KEY_F23", "KEY_F24", "-", "-", "-", "-", "-", "-", "-", "-",
"KEY_NUMLOCK", "KEY_SCROLL", "-", "-", "-", "-", "-", "-", "-", "-", "-",
"-", "-", "-", "-", "-", "KEY_LSHIFT", "KEY_RSHIFT", "KEY_LCONTROL",
"KEY_RCONTROL", "KEY_LMENU", "KEY_RMENU", "-", "-", "-", "-", "-",
"-", "-", "-", "-", "-", "-", "-", "-", "-", "-", "-", "-", "-", "-",
"-", "-", "KEY_PLUS", "KEY_COMMA", "KEY_MINUS", "KEY_PERIOD", "-", "-", "-", "-", "-",
"-", "-", "-", "-", "-", "-", "-", "-", "-", "-", "-", "-", "-", "-",
"-", "-", "-", "-", "-", "-", "-", "-", "-", "-", "-", "-", "-", "-",
"-", "-", "-", "-", "-", "-", "-", "-", "-", "-", "-", "-", "-", "-",
"-", "-", "-", "-", "-", "-", "-", "-", "KEY_ATTN", "KEY_CRSEL", "KEY_EXSEL",
"KEY_EREOF", "KEY_PLAY", "KEY_ZOOM", "KEY_PA1", "KEY_OEM_CLEAR", "-" };
struct table_key lookup_keykey(irr::EKEY_CODE key)
{
for (u16 i = 0; i < ARRAYSIZE(table); i++) {
if (table[i].Key == key)
return table[i];
}
#define N_(text) text
std::ostringstream os;
os << "<Keycode " << (int) key << ">";
throw UnknownKeycode(os.str().c_str());
}
static const char *KeyNamesLang[] =
{ "-", N_("Left Button"), N_("Right Button"), N_("Cancel"), N_("Middle Button"), N_("X Button 1"),
N_("X Button 2"), "-", N_("Back"), N_("Tab"), "-", "-", N_("Clear"), N_("Return"), "-",
"-", N_("Shift"), N_("Control"), N_("Menu"), N_("Pause"), N_("Capital"), N_("Kana"), "-",
N_("Junja"), N_("Final"), N_("Kanji"), "-", N_("Escape"), N_("Convert"), N_("Nonconvert"),
N_("Accept"), N_("Mode Change"), N_("Space"), N_("Prior"), N_("Next"), N_("End"), N_("Home"),
N_("Left"), N_("Up"), N_("Right"), N_("Down"), N_("Select"), N_("Print"), N_("Execute"),
N_("Snapshot"), N_("Insert"), N_("Delete"), N_("Help"), "0", "1", "2", "3", "4", "5",
"6", "7", "8", "9", "-", "-", "-", "-", "-", "-", "-", "A", "B", "C",
"D", "E", "F", "G", "H", "I", "J", "K", "L", "M", "N", "O", "P", "Q",
"R", "S", "T", "U", "V", "W", "X", "Y", "Z", N_("Left Windows"),
N_("Right Windows"), N_("Apps"), "-", N_("Sleep"), N_("Numpad 0"), N_("Numpad 1"),
N_("Numpad 2"), N_("Numpad 3"), N_("Numpad 4"), N_("Numpad 5"), N_("Numpad 6"), N_("Numpad 7"),
N_("Numpad 8"), N_("Numpad 9"), N_("Numpad *"), N_("Numpad +"), N_("Numpad /"), N_("Numpad -"),
"Numpad .", "Numpad /", "F1", "F2", "F3", "F4", "F5", "F6", "F7", "F8",
"F9", "F10", "F11", "F12", "F13", "F14", "F15", "F16", "F17", "F18",
"F19", "F20", "F21", "F22", "F23", "F24", "-", "-", "-", "-", "-", "-",
"-", "-", N_("Num Lock"), N_("Scroll Lock"), "-", "-", "-", "-", "-", "-", "-",
"-", "-", "-", "-", "-", "-", "-", N_("Left Shift"), N_("Right Shift"),
N_("Left Control"), N_("Right Control"), N_("Left Menu"), N_("Right Menu"), "-", "-",
"-", "-", "-", "-", "-", "-", "-", "-", "-", "-", "-", "-", "-", "-",
"-", "-", "-", "-", "-", N_("Plus"), N_("Comma"), N_("Minus"), N_("Period"), "-", "-",
"-", "-", "-", "-", "-", "-", "-", "-", "-", "-", "-", "-", "-", "-",
"-", "-", "-", "-", "-", "-", "-", "-", "-", "-", "-", "-", "-", "-",
"-", "-", "-", "-", "-", "-", "-", "-", "-", "-", "-", "-", "-", "-",
"-", "-", "-", "-", "-", "-", "-", "-", "-", "-", "-", N_("Attn"), N_("CrSel"),
N_("ExSel"), N_("Erase OEF"), N_("Play"), N_("Zoom"), N_("PA1"), N_("OEM Clear"), "-" };
struct table_key lookup_keychar(wchar_t Char)
{
for (u16 i = 0; i < ARRAYSIZE(table); i++) {
if (table[i].Char == Char)
return table[i];
}
#undef N_
std::ostringstream os;
os << "<Char " << hex_encode((char*) &Char, sizeof(wchar_t)) << ">";
throw UnknownKeycode(os.str().c_str());
}
KeyPress::KeyPress() :
Key(irr::KEY_KEY_CODES_COUNT),
Char(L'\0')
Char(L'\0'),
m_name("")
{}
KeyPress::KeyPress(const char *name)
{
if (name[0] == 0) {
if (strlen(name) == 0) {
Key = irr::KEY_KEY_CODES_COUNT;
Char = L'\0';
m_name = "";
return;
} else if (strlen(name) > 4) {
} else if (strlen(name) <= 4) {
// Lookup by resulting character
int chars_read = mbtowc(&Char, name, 1);
FATAL_ERROR_IF(chars_read != 1, "Unexpected multibyte character");
try {
Key = keyname_to_keycode(name);
m_name = name;
if (strlen(name) > 8 && strncmp(name, "KEY_KEY_", 8) == 0) {
int chars_read = mbtowc(&Char, name + 8, 1);
FATAL_ERROR_IF(chars_read != 1, "Unexpected multibyte character");
} else
Char = L'\0';
struct table_key k = lookup_keychar(Char);
m_name = k.Name;
Key = k.Key;
return;
} catch (UnknownKeycode &e) {};
} else {
// see if we can set it up as a KEY_KEY_something
m_name = "KEY_KEY_";
m_name += name;
// Lookup by name
m_name = name;
try {
Key = keyname_to_keycode(m_name.c_str());
int chars_read = mbtowc(&Char, name, 1);
FATAL_ERROR_IF(chars_read != 1, "Unexpected multibyte character");
struct table_key k = lookup_keyname(name);
Key = k.Key;
Char = k.Char;
return;
} catch (UnknownKeycode &e) {};
}
// it's not a (known) key, just take the first char and use that
// It's not a known key, complain and try to do something
Key = irr::KEY_KEY_CODES_COUNT;
int mbtowc_ret = mbtowc(&Char, name, 1);
FATAL_ERROR_IF(mbtowc_ret != 1, "Unexpected multibyte character");
m_name = name[0];
int chars_read = mbtowc(&Char, name, 1);
FATAL_ERROR_IF(chars_read != 1, "Unexpected multibyte character");
m_name = "";
warningstream << "KeyPress: Unknown key '" << name << "', falling back to first char.";
}
KeyPress::KeyPress(const irr::SEvent::SKeyInput &in, bool prefer_character)
{
Key = in.Key;
if (prefer_character)
Key = irr::KEY_KEY_CODES_COUNT;
else
Key = in.Key;
Char = in.Char;
if(prefer_character){
m_name.resize(MB_CUR_MAX+1, '\0');
int written = wctomb(&m_name[0], Char);
if(written > 0){
infostream<<"KeyPress: Preferring character for "<<m_name<<std::endl;
Key = irr::KEY_KEY_CODES_COUNT;
return;
}
}
if (valid_kcode(Key)) {
m_name = KeyNames[Key];
} else {
m_name.resize(MB_CUR_MAX+1, '\0');
int written = wctomb(&m_name[0], Char);
if(written < 0){
std::string hexstr = hex_encode((const char*)&Char, sizeof(Char));
errorstream<<"KeyPress: Unexpected multibyte character "<<hexstr<<std::endl;
}
}
try {
if (valid_kcode(Key))
m_name = lookup_keykey(Key).Name;
else
m_name = lookup_keychar(Char).Name;
} catch (UnknownKeycode &e) {
m_name = "";
};
}
const char *KeyPress::sym() const
{
if (Key && Key < irr::KEY_KEY_CODES_COUNT)
return KeyNames[Key];
else {
return m_name.c_str();
}
return m_name.c_str();
}
const char *KeyPress::name() const
{
if (Key && Key < irr::KEY_KEY_CODES_COUNT)
return KeyNamesLang[Key];
else {
return m_name.c_str();
}
if (m_name == "")
return "";
const char *ret;
if (valid_kcode(Key))
ret = lookup_keykey(Key).LangName;
else
ret = lookup_keychar(Char).LangName;
return ret ? ret : "<Unnamed key>";
}
const KeyPress EscapeKey("KEY_ESCAPE");
const KeyPress CancelKey("KEY_CANCEL");
const KeyPress NumberKey[] = {
KeyPress("KEY_KEY_0"), KeyPress("KEY_KEY_1"), KeyPress("KEY_KEY_2"),
KeyPress("KEY_KEY_3"), KeyPress("KEY_KEY_4"), KeyPress("KEY_KEY_5"),
KeyPress("KEY_KEY_6"), KeyPress("KEY_KEY_7"), KeyPress("KEY_KEY_8"),
KeyPress("KEY_KEY_9")};
KeyPress("0"), KeyPress("1"), KeyPress("2"), KeyPress("3"), KeyPress("4"),
KeyPress("5"), KeyPress("6"), KeyPress("7"), KeyPress("8"), KeyPress("9")
};
/*
Key config
@ -362,8 +377,10 @@ KeyPress getKeySetting(const char *settingname)
n = g_key_setting_cache.find(settingname);
if(n != g_key_setting_cache.end())
return n->second;
g_key_setting_cache[settingname] = g_settings->get(settingname).c_str();
return g_key_setting_cache.find(settingname)->second;
KeyPress k(g_settings->get(settingname).c_str());
g_key_setting_cache[settingname] = k;
return k;
}
void clearKeyCache()
@ -371,6 +388,7 @@ void clearKeyCache()
g_key_setting_cache.clear();
}
/*
Config to Command key aliases
@ -433,3 +451,8 @@ void clearCommandKeyCache() //TODO: Not used, probably should be...
g_command_key_setting_cache.clear();
command_key_cache_loaded=false;
}
irr::EKEY_CODE keyname_to_keycode(const char *name)
{
return lookup_keyname(name).Key;
}

View File

@ -44,8 +44,6 @@ public:
const char *sym() const;
const char *name() const;
std::string debug() const;
protected:
static bool valid_kcode(irr::EKEY_CODE k)
{

View File

@ -26,16 +26,29 @@ with this program; if not, write to the Free Software Foundation, Inc.,
#include "settings.h"
#include "environment.h"
#include "map.h"
#include "util/numeric.h"
#include "client.h"
/*
LocalPlayer
*/
LocalPlayer::LocalPlayer(IGameDef *gamedef, const char *name):
Player(gamedef, name),
LocalPlayer::LocalPlayer(Client *gamedef, const char *name):
Player(name, gamedef->idef()),
parent(0),
got_teleported(false),
isAttached(false),
touching_ground(false),
in_liquid(false),
in_liquid_stable(false),
liquid_viscosity(0),
is_climbing(false),
swimming_vertical(false),
// Movement overrides are multipliers and must be 1 by default
physics_override_speed(1.0f),
physics_override_jump(1.0f),
physics_override_gravity(1.0f),
physics_override_sneak(true),
physics_override_sneak_glitch(true),
overridePosition(v3f(0,0,0)),
last_position(v3f(0,0,0)),
last_speed(v3f(0,0,0)),
@ -47,6 +60,8 @@ LocalPlayer::LocalPlayer(IGameDef *gamedef, const char *name):
hotbar_image(""),
hotbar_selected_image(""),
light_color(255,255,255,255),
hurt_tilt_timer(0.0f),
hurt_tilt_strength(0.0f),
m_sneak_node(32767,32767,32767),
m_sneak_node_exists(false),
m_need_to_get_new_sneak_node(true),
@ -54,7 +69,8 @@ LocalPlayer::LocalPlayer(IGameDef *gamedef, const char *name):
m_old_node_below(32767,32767,32767),
m_old_node_below_type("air"),
m_can_jump(false),
m_cao(NULL)
m_cao(NULL),
m_gamedef(gamedef)
{
// Initialize hp to 0, so that no hearts will be shown if server
// doesn't support health points

View File

@ -21,28 +21,42 @@ with this program; if not, write to the Free Software Foundation, Inc.,
#define LOCALPLAYER_HEADER
#include "player.h"
#include "environment.h"
#include <list>
class Client;
class Environment;
class GenericCAO;
class ClientActiveObject;
class IGameDef;
enum LocalPlayerAnimations {NO_ANIM, WALK_ANIM, DIG_ANIM, WD_ANIM}; // no local animation, walking, digging, both
class LocalPlayer : public Player
{
public:
LocalPlayer(IGameDef *gamedef, const char *name);
LocalPlayer(Client *gamedef, const char *name);
virtual ~LocalPlayer();
bool isLocal() const
{
return true;
}
ClientActiveObject *parent;
bool got_teleported;
bool isAttached;
bool touching_ground;
// This oscillates so that the player jumps a bit above the surface
bool in_liquid;
// This is more stable and defines the maximum speed of the player
bool in_liquid_stable;
// Gets the viscosity of water to calculate friction
u8 liquid_viscosity;
bool is_climbing;
bool swimming_vertical;
float physics_override_speed;
float physics_override_jump;
float physics_override_gravity;
bool physics_override_sneak;
bool physics_override_sneak_glitch;
v3f overridePosition;
@ -71,6 +85,9 @@ public:
video::SColor light_color;
float hurt_tilt_timer;
float hurt_tilt_strength;
GenericCAO* getCAO() const {
return m_cao;
}
@ -80,6 +97,8 @@ public:
m_cao = toset;
}
u32 maxHudId() const { return hud.size(); }
private:
void accelerateHorizontal(const v3f &target_speed, const f32 max_increase);
void accelerateVertical(const v3f &target_speed, const f32 max_increase);
@ -100,6 +119,7 @@ private:
bool m_can_jump;
GenericCAO* m_cao;
Client *m_gamedef;
};
#endif

View File

@ -17,15 +17,8 @@ with this program; if not, write to the Free Software Foundation, Inc.,
51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
*/
#ifdef _MSC_VER
#ifndef SERVER // Dedicated server isn't linked with Irrlicht
#pragma comment(lib, "Irrlicht.lib")
// This would get rid of the console window
//#pragma comment(linker, "/subsystem:windows /ENTRY:mainCRTStartup")
#endif
#pragma comment(lib, "zlibwapi.lib")
#pragma comment(lib, "Shell32.lib")
#endif
// This would get rid of the console window
//#pragma comment(linker, "/subsystem:windows /ENTRY:mainCRTStartup")
#include "irrlicht.h" // createDevice

View File

@ -22,6 +22,7 @@ with this program; if not, write to the Free Software Foundation, Inc.,
#include "mapblock.h"
#include "filesys.h"
#include "voxel.h"
#include "voxelalgorithms.h"
#include "porting.h"
#include "serialization.h"
#include "nodemetadata.h"
@ -234,7 +235,6 @@ void Map::setNode(v3s16 p, MapNode & n)
block->setNodeNoCheck(relpos, n);
}
/*
Goes recursively through the neighbours of the node.
@ -413,20 +413,6 @@ void Map::unspreadLight(enum LightBank bank,
unspreadLight(bank, unlighted_nodes, light_sources, modified_blocks);
}
/*
A single-node wrapper of the above
*/
void Map::unLightNeighbors(enum LightBank bank,
v3s16 pos, u8 lightwas,
std::set<v3s16> & light_sources,
std::map<v3s16, MapBlock*> & modified_blocks)
{
std::map<v3s16, u8> from_nodes;
from_nodes[pos] = lightwas;
unspreadLight(bank, from_nodes, light_sources, modified_blocks);
}
/*
Lights neighbors of from_nodes, collects all them and then
goes on recursively.
@ -572,108 +558,6 @@ void Map::spreadLight(enum LightBank bank,
spreadLight(bank, lighted_nodes, modified_blocks);
}
/*
A single-node source variation of the above.
*/
void Map::lightNeighbors(enum LightBank bank,
v3s16 pos,
std::map<v3s16, MapBlock*> & modified_blocks)
{
std::vector<v3s16> from_nodes;
from_nodes.push_back(pos);
spreadLight(bank, from_nodes, modified_blocks);
}
v3s16 Map::getBrightestNeighbour(enum LightBank bank, v3s16 p)
{
INodeDefManager *nodemgr = m_gamedef->ndef();
v3s16 dirs[6] = {
v3s16(0,0,1), // back
v3s16(0,1,0), // top
v3s16(1,0,0), // right
v3s16(0,0,-1), // front
v3s16(0,-1,0), // bottom
v3s16(-1,0,0), // left
};
u8 brightest_light = 0;
v3s16 brightest_pos(0,0,0);
bool found_something = false;
// Loop through 6 neighbors
for(u16 i=0; i<6; i++){
// Get the position of the neighbor node
v3s16 n2pos = p + dirs[i];
MapNode n2;
bool is_valid_position;
n2 = getNodeNoEx(n2pos, &is_valid_position);
if (!is_valid_position)
continue;
if(n2.getLight(bank, nodemgr) > brightest_light || found_something == false){
brightest_light = n2.getLight(bank, nodemgr);
brightest_pos = n2pos;
found_something = true;
}
}
if(found_something == false)
throw InvalidPositionException();
return brightest_pos;
}
/*
Propagates sunlight down from a node.
Starting point gets sunlight.
Returns the lowest y value of where the sunlight went.
Mud is turned into grass in where the sunlight stops.
*/
s16 Map::propagateSunlight(v3s16 start,
std::map<v3s16, MapBlock*> & modified_blocks)
{
INodeDefManager *nodemgr = m_gamedef->ndef();
s16 y = start.Y;
for(; ; y--)
{
v3s16 pos(start.X, y, start.Z);
v3s16 blockpos = getNodeBlockPos(pos);
MapBlock *block;
try{
block = getBlockNoCreate(blockpos);
}
catch(InvalidPositionException &e)
{
break;
}
v3s16 relpos = pos - blockpos*MAP_BLOCKSIZE;
bool is_valid_position;
MapNode n = block->getNode(relpos, &is_valid_position);
if (!is_valid_position)
break;
if(nodemgr->get(n).sunlight_propagates)
{
n.setLight(LIGHTBANK_DAY, LIGHT_SUN, nodemgr);
block->setNode(relpos, n);
modified_blocks[blockpos] = block;
}
else
{
// Sunlight goes no further
break;
}
}
return y + 1;
}
void Map::updateLighting(enum LightBank bank,
std::map<v3s16, MapBlock*> & a_blocks,
std::map<v3s16, MapBlock*> & modified_blocks)
@ -927,151 +811,34 @@ void Map::updateLighting(std::map<v3s16, MapBlock*> & a_blocks,
}
}
/*
*/
void Map::addNodeAndUpdate(v3s16 p, MapNode n,
std::map<v3s16, MapBlock*> &modified_blocks,
bool remove_metadata)
{
INodeDefManager *ndef = m_gamedef->ndef();
/*PrintInfo(m_dout);
m_dout<<"Map::addNodeAndUpdate(): p=("
<<p.X<<","<<p.Y<<","<<p.Z<<")"<<std::endl;*/
/*
From this node to nodes underneath:
If lighting is sunlight (1.0), unlight neighbours and
set lighting to 0.
Else discontinue.
*/
v3s16 toppos = p + v3s16(0,1,0);
//v3s16 bottompos = p + v3s16(0,-1,0);
bool node_under_sunlight = true;
std::set<v3s16> light_sources;
/*
Collect old node for rollback
*/
// Collect old node for rollback
RollbackNode rollback_oldnode(this, p, m_gamedef);
/*
If there is a node at top and it doesn't have sunlight,
there has not been any sunlight going down.
// This is needed for updating the lighting
MapNode oldnode = getNodeNoEx(p);
Otherwise there probably is.
*/
bool is_valid_position;
MapNode topnode = getNodeNoEx(toppos, &is_valid_position);
if(is_valid_position && topnode.getLight(LIGHTBANK_DAY, ndef) != LIGHT_SUN)
node_under_sunlight = false;
/*
Remove all light that has come out of this node
*/
enum LightBank banks[] =
{
LIGHTBANK_DAY,
LIGHTBANK_NIGHT
};
for(s32 i=0; i<2; i++)
{
enum LightBank bank = banks[i];
u8 lightwas = getNodeNoEx(p).getLight(bank, ndef);
// Add the block of the added node to modified_blocks
v3s16 blockpos = getNodeBlockPos(p);
MapBlock * block = getBlockNoCreate(blockpos);
assert(block != NULL);
modified_blocks[blockpos] = block;
assert(isValidPosition(p));
// Unlight neighbours of node.
// This means setting light of all consequent dimmer nodes
// to 0.
// This also collects the nodes at the border which will spread
// light again into this.
unLightNeighbors(bank, p, lightwas, light_sources, modified_blocks);
n.setLight(bank, 0, ndef);
}
/*
If node lets sunlight through and is under sunlight, it has
sunlight too.
*/
if(node_under_sunlight && ndef->get(n).sunlight_propagates)
{
n.setLight(LIGHTBANK_DAY, LIGHT_SUN, ndef);
}
/*
Remove node metadata
*/
// Remove node metadata
if (remove_metadata) {
removeNodeMetadata(p);
}
/*
Set the node on the map
*/
// Set the node on the map
// Ignore light (because calling voxalgo::update_lighting_nodes)
n.setLight(LIGHTBANK_DAY, 0, ndef);
n.setLight(LIGHTBANK_NIGHT, 0, ndef);
setNode(p, n);
/*
If node is under sunlight and doesn't let sunlight through,
take all sunlighted nodes under it and clear light from them
and from where the light has been spread.
TODO: This could be optimized by mass-unlighting instead
of looping
*/
if(node_under_sunlight && !ndef->get(n).sunlight_propagates)
{
s16 y = p.Y - 1;
for(;; y--){
//m_dout<<"y="<<y<<std::endl;
v3s16 n2pos(p.X, y, p.Z);
// Update lighting
std::vector<std::pair<v3s16, MapNode> > oldnodes;
oldnodes.push_back(std::pair<v3s16, MapNode>(p, oldnode));
voxalgo::update_lighting_nodes(this, ndef, oldnodes, modified_blocks);
MapNode n2;
n2 = getNodeNoEx(n2pos, &is_valid_position);
if (!is_valid_position)
break;
if(n2.getLight(LIGHTBANK_DAY, ndef) == LIGHT_SUN)
{
unLightNeighbors(LIGHTBANK_DAY,
n2pos, n2.getLight(LIGHTBANK_DAY, ndef),
light_sources, modified_blocks);
n2.setLight(LIGHTBANK_DAY, 0, ndef);
setNode(n2pos, n2);
}
else
break;
}
}
for(s32 i=0; i<2; i++)
{
enum LightBank bank = banks[i];
/*
Spread light from all nodes that might be capable of doing so
*/
std::vector<v3s16> light_sources_vec(light_sources.begin(), light_sources.end());
spreadLight(bank, light_sources_vec, modified_blocks);
}
/*
Update information about whether day and night light differ
*/
for(std::map<v3s16, MapBlock*>::iterator
i = modified_blocks.begin();
i != modified_blocks.end(); ++i)
@ -1079,188 +846,7 @@ void Map::addNodeAndUpdate(v3s16 p, MapNode n,
i->second->expireDayNightDiff();
}
/*
Report for rollback
*/
if(m_gamedef->rollback())
{
RollbackNode rollback_newnode(this, p, m_gamedef);
RollbackAction action;
action.setSetNode(p, rollback_oldnode, rollback_newnode);
m_gamedef->rollback()->reportAction(action);
}
/*
Add neighboring liquid nodes and the node itself if it is
liquid (=water node was added) to transform queue.
*/
v3s16 dirs[7] = {
v3s16(0,0,0), // self
v3s16(0,0,1), // back
v3s16(0,1,0), // top
v3s16(1,0,0), // right
v3s16(0,0,-1), // front
v3s16(0,-1,0), // bottom
v3s16(-1,0,0), // left
};
for(u16 i=0; i<7; i++)
{
v3s16 p2 = p + dirs[i];
MapNode n2 = getNodeNoEx(p2, &is_valid_position);
if(is_valid_position
&& (ndef->get(n2).isLiquid() || n2.getContent() == CONTENT_AIR))
{
m_transforming_liquid.push_back(p2);
}
}
}
/*
*/
void Map::removeNodeAndUpdate(v3s16 p,
std::map<v3s16, MapBlock*> &modified_blocks)
{
INodeDefManager *ndef = m_gamedef->ndef();
/*PrintInfo(m_dout);
m_dout<<"Map::removeNodeAndUpdate(): p=("
<<p.X<<","<<p.Y<<","<<p.Z<<")"<<std::endl;*/
bool node_under_sunlight = true;
v3s16 toppos = p + v3s16(0,1,0);
// Node will be replaced with this
content_t replace_material = CONTENT_AIR;
/*
Collect old node for rollback
*/
RollbackNode rollback_oldnode(this, p, m_gamedef);
/*
If there is a node at top and it doesn't have sunlight,
there will be no sunlight going down.
*/
bool is_valid_position;
MapNode topnode = getNodeNoEx(toppos, &is_valid_position);
if(is_valid_position && topnode.getLight(LIGHTBANK_DAY, ndef) != LIGHT_SUN)
node_under_sunlight = false;
std::set<v3s16> light_sources;
enum LightBank banks[] =
{
LIGHTBANK_DAY,
LIGHTBANK_NIGHT
};
for(s32 i=0; i<2; i++)
{
enum LightBank bank = banks[i];
/*
Unlight neighbors (in case the node is a light source)
*/
unLightNeighbors(bank, p,
getNodeNoEx(p).getLight(bank, ndef),
light_sources, modified_blocks);
}
/*
Remove node metadata
*/
removeNodeMetadata(p);
/*
Remove the node.
This also clears the lighting.
*/
MapNode n(replace_material);
setNode(p, n);
for(s32 i=0; i<2; i++)
{
enum LightBank bank = banks[i];
/*
Recalculate lighting
*/
std::vector<v3s16> light_sources_vec(light_sources.begin(), light_sources.end());
spreadLight(bank, light_sources_vec, modified_blocks);
}
// Add the block of the removed node to modified_blocks
v3s16 blockpos = getNodeBlockPos(p);
MapBlock * block = getBlockNoCreate(blockpos);
assert(block != NULL);
modified_blocks[blockpos] = block;
/*
If the removed node was under sunlight, propagate the
sunlight down from it and then light all neighbors
of the propagated blocks.
*/
if(node_under_sunlight)
{
s16 ybottom = propagateSunlight(p, modified_blocks);
/*m_dout<<"Node was under sunlight. "
"Propagating sunlight";
m_dout<<" -> ybottom="<<ybottom<<std::endl;*/
s16 y = p.Y;
for(; y >= ybottom; y--)
{
v3s16 p2(p.X, y, p.Z);
/*m_dout<<"lighting neighbors of node ("
<<p2.X<<","<<p2.Y<<","<<p2.Z<<")"
<<std::endl;*/
lightNeighbors(LIGHTBANK_DAY, p2, modified_blocks);
}
}
else
{
// Set the lighting of this node to 0
// TODO: Is this needed? Lighting is cleared up there already.
MapNode n = getNodeNoEx(p, &is_valid_position);
if (is_valid_position) {
n.setLight(LIGHTBANK_DAY, 0, ndef);
setNode(p, n);
} else {
FATAL_ERROR("Invalid position");
}
}
for(s32 i=0; i<2; i++)
{
enum LightBank bank = banks[i];
// Get the brightest neighbour node and propagate light from it
v3s16 n2p = getBrightestNeighbour(bank, p);
try{
//MapNode n2 = getNode(n2p);
lightNeighbors(bank, n2p, modified_blocks);
}
catch(InvalidPositionException &e)
{
}
}
/*
Update information about whether day and night light differ
*/
for(std::map<v3s16, MapBlock*>::iterator
i = modified_blocks.begin();
i != modified_blocks.end(); ++i)
{
i->second->expireDayNightDiff();
}
/*
Report for rollback
*/
// Report for rollback
if(m_gamedef->rollback())
{
RollbackNode rollback_newnode(this, p, m_gamedef);
@ -1271,8 +857,8 @@ void Map::removeNodeAndUpdate(v3s16 p,
/*
Add neighboring liquid nodes and this node to transform queue.
(it's vital for the node itself to get updated last.)
*/
(it's vital for the node itself to get updated last, if it was removed.)
*/
v3s16 dirs[7] = {
v3s16(0,0,1), // back
v3s16(0,1,0), // top
@ -1286,9 +872,9 @@ void Map::removeNodeAndUpdate(v3s16 p,
{
v3s16 p2 = p + dirs[i];
bool is_position_valid;
MapNode n2 = getNodeNoEx(p2, &is_position_valid);
if (is_position_valid
bool is_valid_position;
MapNode n2 = getNodeNoEx(p2, &is_valid_position);
if(is_valid_position
&& (ndef->get(n2).isLiquid() || n2.getContent() == CONTENT_AIR))
{
m_transforming_liquid.push_back(p2);
@ -1296,6 +882,12 @@ void Map::removeNodeAndUpdate(v3s16 p,
}
}
void Map::removeNodeAndUpdate(v3s16 p,
std::map<v3s16, MapBlock*> &modified_blocks)
{
addNodeAndUpdate(p, MapNode(CONTENT_AIR), modified_blocks, true);
}
bool Map::addNodeWithEvent(v3s16 p, MapNode n, bool remove_metadata)
{
MapEditEvent event;
@ -1640,8 +1232,7 @@ void Map::transformLiquids(std::map<v3s16, MapBlock*> &modified_blocks)
// list of nodes that due to viscosity have not reached their max level height
std::deque<v3s16> must_reflow;
// List of MapBlocks that will require a lighting update (due to lava)
std::map<v3s16, MapBlock *> lighting_modified_blocks;
std::vector<std::pair<v3s16, MapNode> > changed_nodes;
u32 liquid_loop_max = g_settings->getS32("liquid_loop_max");
u32 loop_max = liquid_loop_max;
@ -1682,7 +1273,11 @@ void Map::transformLiquids(std::map<v3s16, MapBlock*> &modified_blocks)
Collect information about current node
*/
s8 liquid_level = -1;
// The liquid node which will be placed there if
// the liquid flows into this node.
content_t liquid_kind = CONTENT_IGNORE;
// The node which will be placed there if liquid
// can't flow into this node.
content_t floodable_node = CONTENT_AIR;
const ContentFeatures &cf = nodemgr->get(n0);
LiquidType liquid_type = cf.liquid_type;
@ -1874,6 +1469,10 @@ void Map::transformLiquids(std::map<v3s16, MapBlock*> &modified_blocks)
}
n0.setContent(new_node_content);
// Ignore light (because calling voxalgo::update_lighting_nodes)
n0.setLight(LIGHTBANK_DAY, 0, nodemgr);
n0.setLight(LIGHTBANK_NIGHT, 0, nodemgr);
// Find out whether there is a suspect for this action
std::string suspect;
if (m_gamedef->rollback())
@ -1900,10 +1499,7 @@ void Map::transformLiquids(std::map<v3s16, MapBlock*> &modified_blocks)
MapBlock *block = getBlockNoCreateNoEx(blockpos);
if (block != NULL) {
modified_blocks[blockpos] = block;
// If new or old node emits light, MapBlock requires lighting update
if (nodemgr->get(n0).light_source != 0 ||
nodemgr->get(n00).light_source != 0)
lighting_modified_blocks[block->getPos()] = block;
changed_nodes.push_back(std::pair<v3s16, MapNode>(p0, n00));
}
/*
@ -1932,7 +1528,7 @@ void Map::transformLiquids(std::map<v3s16, MapBlock*> &modified_blocks)
for (std::deque<v3s16>::iterator iter = must_reflow.begin(); iter != must_reflow.end(); ++iter)
m_transforming_liquid.push_back(*iter);
updateLighting(lighting_modified_blocks, modified_blocks);
voxalgo::update_lighting_nodes(this, nodemgr, changed_nodes, modified_blocks);
/* ----------------------------------------------------------------------

View File

@ -32,6 +32,7 @@ with this program; if not, write to the Free Software Foundation, Inc.,
#include "voxel.h"
#include "modifiedstate.h"
#include "util/container.h"
#include "util/cpp11_container.h"
#include "nodetimer.h"
#include "map_settings_manager.h"
@ -210,24 +211,10 @@ public:
std::set<v3s16> & light_sources,
std::map<v3s16, MapBlock*> & modified_blocks);
void unLightNeighbors(enum LightBank bank,
v3s16 pos, u8 lightwas,
std::set<v3s16> & light_sources,
std::map<v3s16, MapBlock*> & modified_blocks);
void spreadLight(enum LightBank bank,
std::vector<v3s16> & from_nodes,
std::map<v3s16, MapBlock*> & modified_blocks);
void lightNeighbors(enum LightBank bank,
v3s16 pos,
std::map<v3s16, MapBlock*> & modified_blocks);
v3s16 getBrightestNeighbour(enum LightBank bank, v3s16 p);
s16 propagateSunlight(v3s16 start,
std::map<v3s16, MapBlock*> & modified_blocks);
void updateLighting(enum LightBank bank,
std::map<v3s16, MapBlock*> & a_blocks,
std::map<v3s16, MapBlock*> & modified_blocks);

View File

@ -1033,7 +1033,7 @@ MapBlockMesh::MapBlockMesh(MeshMakeData *data, v3s16 camera_offset):
m_enable_shaders = data->m_use_shaders;
m_use_tangent_vertices = data->m_use_tangent_vertices;
m_enable_vbo = g_settings->getBool("enable_vbo");
if (g_settings->getBool("enable_minimap")) {
m_minimap_mapblock = new MinimapMapblock;
m_minimap_mapblock->getMinimapNodes(
@ -1298,10 +1298,8 @@ bool MapBlockMesh::animate(bool faraway, float time, int crack, u32 daynight_rat
// Cracks
if(crack != m_last_crack)
{
for(std::map<u32, std::string>::iterator
i = m_crack_materials.begin();
i != m_crack_materials.end(); ++i)
{
for (UNORDERED_MAP<u32, std::string>::iterator i = m_crack_materials.begin();
i != m_crack_materials.end(); ++i) {
scene::IMeshBuffer *buf = m_mesh->getMeshBuffer(i->first);
std::string basename = i->second;
@ -1315,9 +1313,9 @@ bool MapBlockMesh::animate(bool faraway, float time, int crack, u32 daynight_rat
// If the current material is also animated,
// update animation info
std::map<u32, TileSpec>::iterator anim_iter =
m_animation_tiles.find(i->first);
if(anim_iter != m_animation_tiles.end()){
UNORDERED_MAP<u32, TileSpec>::iterator anim_iter =
m_animation_tiles.find(i->first);
if (anim_iter != m_animation_tiles.end()){
TileSpec &tile = anim_iter->second;
tile.texture = new_texture;
tile.texture_id = new_texture_id;
@ -1330,10 +1328,8 @@ bool MapBlockMesh::animate(bool faraway, float time, int crack, u32 daynight_rat
}
// Texture animation
for(std::map<u32, TileSpec>::iterator
i = m_animation_tiles.begin();
i != m_animation_tiles.end(); ++i)
{
for (UNORDERED_MAP<u32, TileSpec>::iterator i = m_animation_tiles.begin();
i != m_animation_tiles.end(); ++i) {
const TileSpec &tile = i->second;
// Figure out current frame
int frameoffset = m_animation_frame_offsets[i->first];
@ -1443,7 +1439,7 @@ void MeshCollector::append(const TileSpec &tile,
vertices[i].Color, vertices[i].TCoords);
p->vertices.push_back(vert);
}
}
}
for (u32 i = 0; i < numIndices; i++) {
u32 j = indices[i] + vertex_count;
@ -1499,7 +1495,7 @@ void MeshCollector::append(const TileSpec &tile,
vertices[i].Normal, c, vertices[i].TCoords);
p->vertices.push_back(vert);
}
}
}
for (u32 i = 0; i < numIndices; i++) {
u32 j = indices[i] + vertex_count;

View File

@ -23,6 +23,7 @@ with this program; if not, write to the Free Software Foundation, Inc.,
#include "irrlichttypes_extrabloated.h"
#include "client/tile.h"
#include "voxel.h"
#include "util/cpp11_container.h"
#include <map>
class IGameDef;
@ -121,7 +122,7 @@ public:
if(m_animation_force_timer > 0)
m_animation_force_timer--;
}
void updateCameraOffset(v3s16 camera_offset);
private:
@ -144,20 +145,20 @@ private:
// Last crack value passed to animate()
int m_last_crack;
// Maps mesh buffer (i.e. material) indices to base texture names
std::map<u32, std::string> m_crack_materials;
UNORDERED_MAP<u32, std::string> m_crack_materials;
// Animation info: texture animationi
// Maps meshbuffers to TileSpecs
std::map<u32, TileSpec> m_animation_tiles;
std::map<u32, int> m_animation_frames; // last animation frame
std::map<u32, int> m_animation_frame_offsets;
UNORDERED_MAP<u32, TileSpec> m_animation_tiles;
UNORDERED_MAP<u32, int> m_animation_frames; // last animation frame
UNORDERED_MAP<u32, int> m_animation_frame_offsets;
// Animation info: day/night transitions
// Last daynight_ratio value passed to animate()
u32 m_last_daynight_ratio;
// For each meshbuffer, maps vertex indices to (day,night) pairs
std::map<u32, std::map<u32, std::pair<u8, u8> > > m_daynight_diffs;
// Camera offset info -> do we have to translate the mesh?
v3s16 m_camera_offset;
};

View File

@ -154,17 +154,27 @@ int MapgenV7::getSpawnLevelAtPoint(v2s16 p)
// Base terrain calculation
s16 y = baseTerrainLevelAtPoint(p.X, p.Y);
// Ridge/river terrain calculation
float width = 0.2;
float uwatern = NoisePerlin2D(&noise_ridge_uwater->np, p.X, p.Y, seed) * 2;
// if inside a river this is an unsuitable spawn point
if (fabs(uwatern) <= width)
return MAX_MAP_GENERATION_LIMIT;
// If enabled, check if inside a river
if (spflags & MGV7_RIDGES) {
float width = 0.2;
float uwatern = NoisePerlin2D(&noise_ridge_uwater->np, p.X, p.Y, seed) * 2;
if (fabs(uwatern) <= width)
return MAX_MAP_GENERATION_LIMIT; // Unsuitable spawn point
}
// If mountains are disabled, terrain level is base terrain level
// Avoids spawn on non-existant mountain terrain
if (!(spflags & MGV7_MOUNTAINS)) {
if (y <= water_level || y > water_level + 16)
return MAX_MAP_GENERATION_LIMIT; // Unsuitable spawn point
else
return y;
}
// Mountain terrain calculation
int iters = 128;
while (iters--) {
if (!getMountainTerrainAtPoint(p.X, y + 1, p.Y)) { // Air, y is ground level
if (!getMountainTerrainAtPoint(p.X, y + 1, p.Y)) { // If air above
if (y <= water_level || y > water_level + 16)
return MAX_MAP_GENERATION_LIMIT; // Unsuitable spawn point
else
@ -173,7 +183,7 @@ int MapgenV7::getSpawnLevelAtPoint(v2s16 p)
y++;
}
// Unsuitable spawn point, no ground surface found
// Unsuitable spawn point, no mountain surface found
return MAX_MAP_GENERATION_LIMIT;
}

View File

@ -54,10 +54,10 @@ MapNode::MapNode(INodeDefManager *ndef, const std::string &name,
param2 = a_param2;
}
void MapNode::setLight(enum LightBank bank, u8 a_light, INodeDefManager *nodemgr)
void MapNode::setLight(enum LightBank bank, u8 a_light, const ContentFeatures &f)
{
// If node doesn't contain light data, ignore this
if(nodemgr->get(*this).param_type != CPT_LIGHT)
if(f.param_type != CPT_LIGHT)
return;
if(bank == LIGHTBANK_DAY)
{
@ -73,6 +73,11 @@ void MapNode::setLight(enum LightBank bank, u8 a_light, INodeDefManager *nodemgr
assert("Invalid light bank" == NULL);
}
void MapNode::setLight(enum LightBank bank, u8 a_light, INodeDefManager *nodemgr)
{
setLight(bank, a_light, nodemgr->get(*this));
}
bool MapNode::isLightDayNightEq(INodeDefManager *nodemgr) const
{
const ContentFeatures &f = nodemgr->get(*this);
@ -103,6 +108,13 @@ u8 MapNode::getLight(enum LightBank bank, INodeDefManager *nodemgr) const
return MYMAX(f.light_source, light);
}
u8 MapNode::getLightRaw(enum LightBank bank, const ContentFeatures &f) const
{
if(f.param_type == CPT_LIGHT)
return bank == LIGHTBANK_DAY ? param1 & 0x0f : (param1 >> 4) & 0x0f;
return 0;
}
u8 MapNode::getLightNoChecks(enum LightBank bank, const ContentFeatures *f) const
{
return MYMAX(f->light_source,

View File

@ -191,6 +191,8 @@ struct MapNode
param2 = p;
}
void setLight(enum LightBank bank, u8 a_light, const ContentFeatures &f);
void setLight(enum LightBank bank, u8 a_light, INodeDefManager *nodemgr);
/**
@ -202,6 +204,13 @@ struct MapNode
u8 getLight(enum LightBank bank, INodeDefManager *nodemgr) const;
/*!
* Returns the node's light level from param1.
* If the node emits light, it is ignored.
* \param f the ContentFeatures of this node.
*/
u8 getLightRaw(enum LightBank bank, const ContentFeatures &f) const;
/**
* This function differs from getLight(enum LightBank bank, INodeDefManager *nodemgr)
* in that the ContentFeatures of the node in question are not retrieved by

View File

@ -42,9 +42,8 @@ void MapSector::deleteBlocks()
m_block_cache = NULL;
// Delete all
for(std::map<s16, MapBlock*>::iterator i = m_blocks.begin();
i != m_blocks.end(); ++i)
{
for (UNORDERED_MAP<s16, MapBlock*>::iterator i = m_blocks.begin();
i != m_blocks.end(); ++i) {
delete i->second;
}
@ -56,20 +55,13 @@ MapBlock * MapSector::getBlockBuffered(s16 y)
{
MapBlock *block;
if(m_block_cache != NULL && y == m_block_cache_y){
if (m_block_cache != NULL && y == m_block_cache_y) {
return m_block_cache;
}
// If block doesn't exist, return NULL
std::map<s16, MapBlock*>::iterator n = m_blocks.find(y);
if(n == m_blocks.end())
{
block = NULL;
}
// If block exists, return it
else{
block = n->second;
}
UNORDERED_MAP<s16, MapBlock*>::iterator n = m_blocks.find(y);
block = (n != m_blocks.end() ? n->second : NULL);
// Cache the last result
m_block_cache_y = y;
@ -135,18 +127,12 @@ void MapSector::deleteBlock(MapBlock *block)
void MapSector::getBlocks(MapBlockVect &dest)
{
for(std::map<s16, MapBlock*>::iterator bi = m_blocks.begin();
bi != m_blocks.end(); ++bi)
{
for (UNORDERED_MAP<s16, MapBlock*>::iterator bi = m_blocks.begin();
bi != m_blocks.end(); ++bi) {
dest.push_back(bi->second);
}
}
bool MapSector::empty()
{
return m_blocks.empty();
}
/*
ServerMapSector
*/

View File

@ -63,7 +63,7 @@ public:
void getBlocks(MapBlockVect &dest);
bool empty();
bool empty() const { return m_blocks.empty(); }
// Always false at the moment, because sector contains no metadata.
bool differs_from_disk;
@ -71,7 +71,7 @@ public:
protected:
// The pile of MapBlocks
std::map<s16, MapBlock*> m_blocks;
UNORDERED_MAP<s16, MapBlock*> m_blocks;
Map *m_parent;
// Position on parent (in MapBlock widths)

View File

@ -564,14 +564,14 @@ void Schematic::applyProbabilities(v3s16 p0,
void generate_nodelist_and_update_ids(MapNode *nodes, size_t nodecount,
std::vector<std::string> *usednodes, INodeDefManager *ndef)
{
std::map<content_t, content_t> nodeidmap;
UNORDERED_MAP<content_t, content_t> nodeidmap;
content_t numids = 0;
for (size_t i = 0; i != nodecount; i++) {
content_t id;
content_t c = nodes[i].getContent();
std::map<content_t, content_t>::const_iterator it = nodeidmap.find(c);
UNORDERED_MAP<content_t, content_t>::const_iterator it = nodeidmap.find(c);
if (it == nodeidmap.end()) {
id = numids;
numids++;

View File

@ -110,7 +110,7 @@ void Client::handleCommand_AuthAccept(NetworkPacket* pkt)
playerpos -= v3f(0, BS / 2, 0);
// Set player position
Player *player = m_env.getLocalPlayer();
LocalPlayer *player = m_env.getLocalPlayer();
assert(player != NULL);
player->setPosition(playerpos);
@ -176,7 +176,7 @@ void Client::handleCommand_InitLegacy(NetworkPacket* pkt)
// Set player position
Player *player = m_env.getLocalPlayer();
LocalPlayer *player = m_env.getLocalPlayer();
assert(player != NULL);
player->setPosition(playerpos_f);
@ -333,7 +333,7 @@ void Client::handleCommand_Inventory(NetworkPacket* pkt)
std::string datastring(pkt->getString(0), pkt->getSize());
std::istringstream is(datastring, std::ios_base::binary);
Player *player = m_env.getLocalPlayer();
LocalPlayer *player = m_env.getLocalPlayer();
assert(player != NULL);
player->inventory.deSerialize(is);
@ -486,7 +486,7 @@ void Client::handleCommand_ActiveObjectMessages(NetworkPacket* pkt)
void Client::handleCommand_Movement(NetworkPacket* pkt)
{
Player *player = m_env.getLocalPlayer();
LocalPlayer *player = m_env.getLocalPlayer();
assert(player != NULL);
float mad, maa, maf, msw, mscr, msf, mscl, msj, lf, lfs, ls, g;
@ -511,7 +511,7 @@ void Client::handleCommand_Movement(NetworkPacket* pkt)
void Client::handleCommand_HP(NetworkPacket* pkt)
{
Player *player = m_env.getLocalPlayer();
LocalPlayer *player = m_env.getLocalPlayer();
assert(player != NULL);
u8 oldhp = player->hp;
@ -532,7 +532,7 @@ void Client::handleCommand_HP(NetworkPacket* pkt)
void Client::handleCommand_Breath(NetworkPacket* pkt)
{
Player *player = m_env.getLocalPlayer();
LocalPlayer *player = m_env.getLocalPlayer();
assert(player != NULL);
u16 breath;
@ -544,7 +544,7 @@ void Client::handleCommand_Breath(NetworkPacket* pkt)
void Client::handleCommand_MovePlayer(NetworkPacket* pkt)
{
Player *player = m_env.getLocalPlayer();
LocalPlayer *player = m_env.getLocalPlayer();
assert(player != NULL);
v3f pos;
@ -813,9 +813,7 @@ void Client::handleCommand_StopSound(NetworkPacket* pkt)
*pkt >> server_id;
std::map<s32, int>::iterator i =
m_sounds_server_to_client.find(server_id);
UNORDERED_MAP<s32, int>::iterator i = m_sounds_server_to_client.find(server_id);
if (i != m_sounds_server_to_client.end()) {
int client_id = i->second;
m_sound->stopSound(client_id);
@ -863,7 +861,7 @@ void Client::handleCommand_Privileges(NetworkPacket* pkt)
void Client::handleCommand_InventoryFormSpec(NetworkPacket* pkt)
{
Player *player = m_env.getLocalPlayer();
LocalPlayer *player = m_env.getLocalPlayer();
assert(player != NULL);
// Store formspec in LocalPlayer
@ -967,7 +965,7 @@ void Client::handleCommand_AddParticleSpawner(NetworkPacket* pkt)
bool vertical = false;
bool collision_removal = false;
s32 attached_id = -1;
u16 attached_id = 0;
try {
*pkt >> vertical;
*pkt >> collision_removal;
@ -1124,7 +1122,7 @@ void Client::handleCommand_HudSetFlags(NetworkPacket* pkt)
*pkt >> flags >> mask;
Player *player = m_env.getLocalPlayer();
LocalPlayer *player = m_env.getLocalPlayer();
assert(player != NULL);
bool was_minimap_visible = player->hud_flags & HUD_FLAG_MINIMAP_VISIBLE;
@ -1148,7 +1146,7 @@ void Client::handleCommand_HudSetParam(NetworkPacket* pkt)
*pkt >> param >> value;
Player *player = m_env.getLocalPlayer();
LocalPlayer *player = m_env.getLocalPlayer();
assert(player != NULL);
if (param == HUD_PARAM_HOTBAR_ITEMCOUNT && value.size() == 4) {
@ -1157,10 +1155,10 @@ void Client::handleCommand_HudSetParam(NetworkPacket* pkt)
player->hud_hotbar_itemcount = hotbar_itemcount;
}
else if (param == HUD_PARAM_HOTBAR_IMAGE) {
((LocalPlayer *) player)->hotbar_image = value;
player->hotbar_image = value;
}
else if (param == HUD_PARAM_HOTBAR_SELECTED_IMAGE) {
((LocalPlayer *) player)->hotbar_selected_image = value;
player->hotbar_selected_image = value;
}
}

View File

@ -800,7 +800,7 @@ void Server::handleCommand_PlayerPos(NetworkPacket* pkt)
pitch = modulo360f(pitch);
yaw = modulo360f(yaw);
Player *player = m_env->getPlayer(pkt->getPeerId());
RemotePlayer *player = m_env->getPlayer(pkt->getPeerId());
if (player == NULL) {
errorstream << "Server::ProcessData(): Canceling: "
"No player for peer_id=" << pkt->getPeerId()
@ -879,7 +879,8 @@ void Server::handleCommand_DeletedBlocks(NetworkPacket* pkt)
void Server::handleCommand_InventoryAction(NetworkPacket* pkt)
{
Player *player = m_env->getPlayer(pkt->getPeerId());
RemotePlayer *player = m_env->getPlayer(pkt->getPeerId());
if (player == NULL) {
errorstream << "Server::ProcessData(): Canceling: "
"No player for peer_id=" << pkt->getPeerId()
@ -1051,7 +1052,7 @@ void Server::handleCommand_ChatMessage(NetworkPacket* pkt)
message += (wchar_t)tmp_wchar;
}
Player *player = m_env->getPlayer(pkt->getPeerId());
RemotePlayer *player = m_env->getPlayer(pkt->getPeerId());
if (player == NULL) {
errorstream << "Server::ProcessData(): Canceling: "
"No player for peer_id=" << pkt->getPeerId()
@ -1065,7 +1066,7 @@ void Server::handleCommand_ChatMessage(NetworkPacket* pkt)
std::wstring wname = narrow_to_wide(name);
std::wstring answer_to_sender = handleChat(name, wname, message,
true, pkt->getPeerId());
true, dynamic_cast<RemotePlayer *>(player));
if (!answer_to_sender.empty()) {
// Send the answer to sender
SendChatMessage(pkt->getPeerId(), answer_to_sender);
@ -1078,7 +1079,8 @@ void Server::handleCommand_Damage(NetworkPacket* pkt)
*pkt >> damage;
Player *player = m_env->getPlayer(pkt->getPeerId());
RemotePlayer *player = m_env->getPlayer(pkt->getPeerId());
if (player == NULL) {
errorstream << "Server::ProcessData(): Canceling: "
"No player for peer_id=" << pkt->getPeerId()
@ -1112,7 +1114,8 @@ void Server::handleCommand_Breath(NetworkPacket* pkt)
*pkt >> breath;
Player *player = m_env->getPlayer(pkt->getPeerId());
RemotePlayer *player = m_env->getPlayer(pkt->getPeerId());
if (player == NULL) {
errorstream << "Server::ProcessData(): Canceling: "
"No player for peer_id=" << pkt->getPeerId()
@ -1176,7 +1179,7 @@ void Server::handleCommand_Password(NetworkPacket* pkt)
newpwd += c;
}
Player *player = m_env->getPlayer(pkt->getPeerId());
RemotePlayer *player = m_env->getPlayer(pkt->getPeerId());
if (player == NULL) {
errorstream << "Server::ProcessData(): Canceling: "
"No player for peer_id=" << pkt->getPeerId()
@ -1224,7 +1227,8 @@ void Server::handleCommand_PlayerItem(NetworkPacket* pkt)
if (pkt->getSize() < 2)
return;
Player *player = m_env->getPlayer(pkt->getPeerId());
RemotePlayer *player = m_env->getPlayer(pkt->getPeerId());
if (player == NULL) {
errorstream << "Server::ProcessData(): Canceling: "
"No player for peer_id=" << pkt->getPeerId()
@ -1251,7 +1255,7 @@ void Server::handleCommand_PlayerItem(NetworkPacket* pkt)
void Server::handleCommand_Respawn(NetworkPacket* pkt)
{
Player *player = m_env->getPlayer(pkt->getPeerId());
RemotePlayer *player = m_env->getPlayer(pkt->getPeerId());
if (player == NULL) {
errorstream << "Server::ProcessData(): Canceling: "
"No player for peer_id=" << pkt->getPeerId()
@ -1299,7 +1303,8 @@ void Server::handleCommand_Interact(NetworkPacket* pkt)
verbosestream << "TOSERVER_INTERACT: action=" << (int)action << ", item="
<< item_i << ", pointed=" << pointed.dump() << std::endl;
Player *player = m_env->getPlayer(pkt->getPeerId());
RemotePlayer *player = m_env->getPlayer(pkt->getPeerId());
if (player == NULL) {
errorstream << "Server::ProcessData(): Canceling: "
"No player for peer_id=" << pkt->getPeerId()
@ -1656,16 +1661,16 @@ void Server::handleCommand_Interact(NetworkPacket* pkt)
}
} // action == 4
/*
5: rightclick air
*/
else if (action == 5) {
ItemStack item = playersao->getWieldedItem();
actionstream << player->getName() << " activates "
actionstream << player->getName() << " activates "
<< item.name << std::endl;
if (m_script->item_OnSecondaryUse(
item, playersao)) {
if( playersao->setWieldedItem(item)) {
@ -1693,9 +1698,7 @@ void Server::handleCommand_RemovedSounds(NetworkPacket* pkt)
*pkt >> id;
std::map<s32, ServerPlayingSound>::iterator i =
m_playing_sounds.find(id);
UNORDERED_MAP<s32, ServerPlayingSound>::iterator i = m_playing_sounds.find(id);
if (i == m_playing_sounds.end())
continue;
@ -1721,7 +1724,8 @@ void Server::handleCommand_NodeMetaFields(NetworkPacket* pkt)
fields[fieldname] = pkt->readLongString();
}
Player *player = m_env->getPlayer(pkt->getPeerId());
RemotePlayer *player = m_env->getPlayer(pkt->getPeerId());
if (player == NULL) {
errorstream << "Server::ProcessData(): Canceling: "
"No player for peer_id=" << pkt->getPeerId()
@ -1771,7 +1775,8 @@ void Server::handleCommand_InventoryFields(NetworkPacket* pkt)
fields[fieldname] = pkt->readLongString();
}
Player *player = m_env->getPlayer(pkt->getPeerId());
RemotePlayer *player = m_env->getPlayer(pkt->getPeerId());
if (player == NULL) {
errorstream << "Server::ProcessData(): Canceling: "
"No player for peer_id=" << pkt->getPeerId()

View File

@ -810,12 +810,12 @@ private:
// item aliases too. Updated by updateAliases()
// Note: Not serialized.
std::map<std::string, content_t> m_name_id_mapping_with_aliases;
UNORDERED_MAP<std::string, content_t> m_name_id_mapping_with_aliases;
// A mapping from groups to a list of content_ts (and their levels)
// that belong to it. Necessary for a direct lookup in getIds().
// Note: Not serialized.
std::map<std::string, GroupItems> m_group_to_items;
UNORDERED_MAP<std::string, GroupItems> m_group_to_items;
// Next possibly free id
content_t m_next_id;
@ -938,7 +938,7 @@ inline const ContentFeatures& CNodeDefManager::get(const MapNode &n) const
bool CNodeDefManager::getId(const std::string &name, content_t &result) const
{
std::map<std::string, content_t>::const_iterator
UNORDERED_MAP<std::string, content_t>::const_iterator
i = m_name_id_mapping_with_aliases.find(name);
if(i == m_name_id_mapping_with_aliases.end())
return false;
@ -968,7 +968,7 @@ bool CNodeDefManager::getIds(const std::string &name,
}
std::string group = name.substr(6);
std::map<std::string, GroupItems>::const_iterator
UNORDERED_MAP<std::string, GroupItems>::const_iterator
i = m_group_to_items.find(group);
if (i == m_group_to_items.end())
return true;
@ -1050,7 +1050,7 @@ content_t CNodeDefManager::set(const std::string &name, const ContentFeatures &d
i != def.groups.end(); ++i) {
std::string group_name = i->first;
std::map<std::string, GroupItems>::iterator
UNORDERED_MAP<std::string, GroupItems>::iterator
j = m_group_to_items.find(group_name);
if (j == m_group_to_items.end()) {
m_group_to_items[group_name].push_back(
@ -1086,7 +1086,7 @@ void CNodeDefManager::removeNode(const std::string &name)
}
// Erase node content from all groups it belongs to
for (std::map<std::string, GroupItems>::iterator iter_groups =
for (UNORDERED_MAP<std::string, GroupItems>::iterator iter_groups =
m_group_to_items.begin();
iter_groups != m_group_to_items.end();) {
GroupItems &items = iter_groups->second;
@ -1144,13 +1144,8 @@ void CNodeDefManager::applyTextureOverrides(const std::string &override_filepath
}
content_t id;
if (!getId(splitted[0], id)) {
infostream << override_filepath
<< ":" << line_c << " Could not apply texture override \""
<< line << "\": Unknown node \""
<< splitted[0] << "\"" << std::endl;
continue;
}
if (!getId(splitted[0], id))
continue; // Ignore unknown node
ContentFeatures &nodedef = m_content_features[id];

View File

@ -213,7 +213,7 @@ ParticleSpawner::ParticleSpawner(IGameDef* gamedef, scene::ISceneManager *smgr,
u16 amount, float time,
v3f minpos, v3f maxpos, v3f minvel, v3f maxvel, v3f minacc, v3f maxacc,
float minexptime, float maxexptime, float minsize, float maxsize,
bool collisiondetection, bool collision_removal, s32 attached_id, bool vertical,
bool collisiondetection, bool collision_removal, u16 attached_id, bool vertical,
video::ITexture *texture, u32 id, ParticleManager *p_manager) :
m_particlemanager(p_manager)
{
@ -254,14 +254,11 @@ void ParticleSpawner::step(float dtime, ClientEnvironment* env)
bool unloaded = false;
v3f attached_offset = v3f(0,0,0);
if (m_attached_id != -1) {
ClientActiveObject *attached =
env->getActiveObject(m_attached_id);
if (attached != NULL) {
if (m_attached_id != 0) {
if (ClientActiveObject *attached = env->getActiveObject(m_attached_id))
attached_offset = attached->getPosition() / BS;
} else {
else
unloaded = true;
}
}
if (m_spawntime != 0) // Spawner exists for a predefined timespan
@ -277,14 +274,11 @@ void ParticleSpawner::step(float dtime, ClientEnvironment* env)
// particle if it is attached to an unloaded
// object.
if (!unloaded) {
v3f pos = random_v3f(m_minpos, m_maxpos)
+ attached_offset;
v3f pos = random_v3f(m_minpos, m_maxpos);
v3f vel = random_v3f(m_minvel, m_maxvel);
v3f acc = random_v3f(m_minacc, m_maxacc);
// Make relative to offest
pos += attached_offset;
float exptime = rand()/(float)RAND_MAX
*(m_maxexptime-m_minexptime)
+m_minexptime;

View File

@ -119,7 +119,7 @@ class ParticleSpawner
float minsize, float maxsize,
bool collisiondetection,
bool collision_removal,
s32 attached_id,
u16 attached_id,
bool vertical,
video::ITexture *texture,
u32 id,
@ -155,7 +155,7 @@ class ParticleSpawner
bool m_collisiondetection;
bool m_collision_removal;
bool m_vertical;
s32 m_attached_id;
u16 m_attached_id;
};
/**

View File

@ -19,44 +19,29 @@ with this program; if not, write to the Free Software Foundation, Inc.,
#include "player.h"
#include <fstream>
#include "threading/mutex_auto_lock.h"
#include "util/numeric.h"
#include "hud.h"
#include "constants.h"
#include "gamedef.h"
#include "settings.h"
#include "content_sao.h"
#include "filesys.h"
#include "log.h"
#include "porting.h" // strlcpy
Player::Player(IGameDef *gamedef, const char *name):
got_teleported(false),
touching_ground(false),
in_liquid(false),
in_liquid_stable(false),
liquid_viscosity(0),
is_climbing(false),
swimming_vertical(false),
Player::Player(const char *name, IItemDefManager *idef):
camera_barely_in_ceiling(false),
inventory(gamedef->idef()),
inventory(idef),
hp(PLAYER_MAX_HP),
hurt_tilt_timer(0),
hurt_tilt_strength(0),
protocol_version(0),
peer_id(PEER_ID_INEXISTENT),
keyPressed(0),
// protected
m_gamedef(gamedef),
m_breath(PLAYER_MAX_BREATH),
m_pitch(0),
m_yaw(0),
m_speed(0,0,0),
m_position(0,0,0),
m_collisionbox(-BS*0.30,0.0,-BS*0.30,BS*0.30,BS*1.75,BS*0.30),
m_dirty(false)
m_collisionbox(-BS*0.30,0.0,-BS*0.30,BS*0.30,BS*1.75,BS*0.30)
{
strlcpy(m_name, name, PLAYERNAME_SIZE);
@ -92,13 +77,6 @@ Player::Player(IGameDef *gamedef, const char *name):
movement_gravity = 9.81 * BS;
local_animation_speed = 0.0;
// Movement overrides are multipliers and must be 1 by default
physics_override_speed = 1;
physics_override_jump = 1;
physics_override_gravity = 1;
physics_override_sneak = true;
physics_override_sneak_glitch = true;
hud_flags =
HUD_FLAG_HOTBAR_VISIBLE | HUD_FLAG_HEALTHBAR_VISIBLE |
HUD_FLAG_CROSSHAIR_VISIBLE | HUD_FLAG_WIELDITEM_VISIBLE |
@ -117,70 +95,6 @@ v3s16 Player::getLightPosition() const
return floatToInt(m_position + v3f(0,BS+BS/2,0), BS);
}
void Player::serialize(std::ostream &os)
{
// Utilize a Settings object for storing values
Settings args;
args.setS32("version", 1);
args.set("name", m_name);
//args.set("password", m_password);
args.setFloat("pitch", m_pitch);
args.setFloat("yaw", m_yaw);
args.setV3F("position", m_position);
args.setS32("hp", hp);
args.setS32("breath", m_breath);
args.writeLines(os);
os<<"PlayerArgsEnd\n";
inventory.serialize(os);
}
void Player::deSerialize(std::istream &is, std::string playername)
{
Settings args;
if (!args.parseConfigLines(is, "PlayerArgsEnd")) {
throw SerializationError("PlayerArgsEnd of player " +
playername + " not found!");
}
m_dirty = true;
//args.getS32("version"); // Version field value not used
std::string name = args.get("name");
strlcpy(m_name, name.c_str(), PLAYERNAME_SIZE);
setPitch(args.getFloat("pitch"));
setYaw(args.getFloat("yaw"));
setPosition(args.getV3F("position"));
try{
hp = args.getS32("hp");
}catch(SettingNotFoundException &e) {
hp = PLAYER_MAX_HP;
}
try{
m_breath = args.getS32("breath");
}catch(SettingNotFoundException &e) {
m_breath = PLAYER_MAX_BREATH;
}
inventory.deSerialize(is);
if(inventory.getList("craftpreview") == NULL) {
// Convert players without craftpreview
inventory.addList("craftpreview", 1);
bool craftresult_is_preview = true;
if(args.exists("craftresult_is_preview"))
craftresult_is_preview = args.getBool("craftresult_is_preview");
if(craftresult_is_preview)
{
// Clear craftresult
inventory.getList("craftresult")->changeItem(0, ItemStack());
}
}
}
u32 Player::addHud(HudElement *toadd)
{
MutexAutoLock lock(m_mutex);
@ -226,81 +140,3 @@ void Player::clearHud()
hud.pop_back();
}
}
RemotePlayer::RemotePlayer(IGameDef *gamedef, const char *name):
Player(gamedef, name),
m_sao(NULL)
{
movement_acceleration_default = g_settings->getFloat("movement_acceleration_default") * BS;
movement_acceleration_air = g_settings->getFloat("movement_acceleration_air") * BS;
movement_acceleration_fast = g_settings->getFloat("movement_acceleration_fast") * BS;
movement_speed_walk = g_settings->getFloat("movement_speed_walk") * BS;
movement_speed_crouch = g_settings->getFloat("movement_speed_crouch") * BS;
movement_speed_fast = g_settings->getFloat("movement_speed_fast") * BS;
movement_speed_climb = g_settings->getFloat("movement_speed_climb") * BS;
movement_speed_jump = g_settings->getFloat("movement_speed_jump") * BS;
movement_liquid_fluidity = g_settings->getFloat("movement_liquid_fluidity") * BS;
movement_liquid_fluidity_smooth = g_settings->getFloat("movement_liquid_fluidity_smooth") * BS;
movement_liquid_sink = g_settings->getFloat("movement_liquid_sink") * BS;
movement_gravity = g_settings->getFloat("movement_gravity") * BS;
}
void RemotePlayer::save(std::string savedir)
{
/*
* We have to open all possible player files in the players directory
* and check their player names because some file systems are not
* case-sensitive and player names are case-sensitive.
*/
// A player to deserialize files into to check their names
RemotePlayer testplayer(m_gamedef, "");
savedir += DIR_DELIM;
std::string path = savedir + m_name;
for (u32 i = 0; i < PLAYER_FILE_ALTERNATE_TRIES; i++) {
if (!fs::PathExists(path)) {
// Open file and serialize
std::ostringstream ss(std::ios_base::binary);
serialize(ss);
if (!fs::safeWriteToFile(path, ss.str())) {
infostream << "Failed to write " << path << std::endl;
}
setModified(false);
return;
}
// Open file and deserialize
std::ifstream is(path.c_str(), std::ios_base::binary);
if (!is.good()) {
infostream << "Failed to open " << path << std::endl;
return;
}
testplayer.deSerialize(is, path);
is.close();
if (strcmp(testplayer.getName(), m_name) == 0) {
// Open file and serialize
std::ostringstream ss(std::ios_base::binary);
serialize(ss);
if (!fs::safeWriteToFile(path, ss.str())) {
infostream << "Failed to write " << path << std::endl;
}
setModified(false);
return;
}
path = savedir + m_name + itos(i);
}
infostream << "Didn't find free file for player " << m_name << std::endl;
return;
}
/*
RemotePlayer
*/
void RemotePlayer::setPosition(const v3f &position)
{
Player::setPosition(position);
if(m_sao)
m_sao->setBasePosition(position);
}

View File

@ -99,9 +99,7 @@ struct PlayerControl
};
class Map;
class IGameDef;
struct CollisionInfo;
class PlayerSAO;
struct HudElement;
class Environment;
@ -112,7 +110,7 @@ class Player
{
public:
Player(IGameDef *gamedef, const char *name);
Player(const char *name, IItemDefManager *idef);
virtual ~Player() = 0;
virtual void move(f32 dtime, Environment *env, f32 pos_max_d)
@ -151,80 +149,32 @@ public:
virtual void setPosition(const v3f &position)
{
if (position != m_position)
m_dirty = true;
m_position = position;
}
void setPitch(f32 pitch)
virtual void setPitch(f32 pitch)
{
if (pitch != m_pitch)
m_dirty = true;
m_pitch = pitch;
}
virtual void setYaw(f32 yaw)
{
if (yaw != m_yaw)
m_dirty = true;
m_yaw = yaw;
}
f32 getPitch()
{
return m_pitch;
}
f32 getPitch() const { return m_pitch; }
f32 getYaw() const { return m_yaw; }
u16 getBreath() const { return m_breath; }
f32 getYaw()
{
return m_yaw;
}
virtual void setBreath(u16 breath) { m_breath = breath; }
u16 getBreath()
{
return m_breath;
}
f32 getRadPitch() const { return m_pitch * core::DEGTORAD; }
f32 getRadYaw() const { return m_yaw * core::DEGTORAD; }
const char *getName() const { return m_name; }
aabb3f getCollisionbox() const { return m_collisionbox; }
virtual void setBreath(u16 breath)
u32 getFreeHudID()
{
if (breath != m_breath)
m_dirty = true;
m_breath = breath;
}
// Deprecated
f32 getRadPitchDep()
{
return -1.0 * m_pitch * core::DEGTORAD;
}
// Deprecated
f32 getRadYawDep()
{
return (m_yaw + 90.) * core::DEGTORAD;
}
f32 getRadPitch()
{
return m_pitch * core::DEGTORAD;
}
f32 getRadYaw()
{
return m_yaw * core::DEGTORAD;
}
const char *getName() const
{
return m_name;
}
aabb3f getCollisionbox()
{
return m_collisionbox;
}
u32 getFreeHudID() {
size_t size = hud.size();
for (size_t i = 0; i != size; i++) {
if (!hud[i])
@ -233,125 +183,6 @@ public:
return size;
}
void setHotbarItemcount(s32 hotbar_itemcount)
{
hud_hotbar_itemcount = hotbar_itemcount;
}
s32 getHotbarItemcount()
{
return hud_hotbar_itemcount;
}
void setHotbarImage(const std::string &name)
{
hud_hotbar_image = name;
}
std::string getHotbarImage()
{
return hud_hotbar_image;
}
void setHotbarSelectedImage(const std::string &name)
{
hud_hotbar_selected_image = name;
}
std::string getHotbarSelectedImage() {
return hud_hotbar_selected_image;
}
void setSky(const video::SColor &bgcolor, const std::string &type,
const std::vector<std::string> &params)
{
m_sky_bgcolor = bgcolor;
m_sky_type = type;
m_sky_params = params;
}
void getSky(video::SColor *bgcolor, std::string *type,
std::vector<std::string> *params)
{
*bgcolor = m_sky_bgcolor;
*type = m_sky_type;
*params = m_sky_params;
}
void overrideDayNightRatio(bool do_override, float ratio)
{
m_day_night_ratio_do_override = do_override;
m_day_night_ratio = ratio;
}
void getDayNightRatio(bool *do_override, float *ratio)
{
*do_override = m_day_night_ratio_do_override;
*ratio = m_day_night_ratio;
}
void setLocalAnimations(v2s32 frames[4], float frame_speed)
{
for (int i = 0; i < 4; i++)
local_animations[i] = frames[i];
local_animation_speed = frame_speed;
}
void getLocalAnimations(v2s32 *frames, float *frame_speed)
{
for (int i = 0; i < 4; i++)
frames[i] = local_animations[i];
*frame_speed = local_animation_speed;
}
virtual bool isLocal() const
{
return false;
}
virtual PlayerSAO *getPlayerSAO()
{
return NULL;
}
virtual void setPlayerSAO(PlayerSAO *sao)
{
FATAL_ERROR("FIXME");
}
/*
serialize() writes a bunch of text that can contain
any characters except a '\0', and such an ending that
deSerialize stops reading exactly at the right point.
*/
void serialize(std::ostream &os);
void deSerialize(std::istream &is, std::string playername);
bool checkModified() const
{
return m_dirty || inventory.checkModified();
}
void setModified(const bool x)
{
m_dirty = x;
if (x == false)
inventory.setModified(x);
}
// Use a function, if isDead can be defined by other conditions
bool isDead() { return hp == 0; }
bool got_teleported;
bool touching_ground;
// This oscillates so that the player jumps a bit above the surface
bool in_liquid;
// This is more stable and defines the maximum speed of the player
bool in_liquid_stable;
// Gets the viscosity of water to calculate friction
u8 liquid_viscosity;
bool is_climbing;
bool swimming_vertical;
bool camera_barely_in_ceiling;
v3f eye_offset_first;
v3f eye_offset_third;
@ -371,49 +202,28 @@ public:
f32 movement_liquid_sink;
f32 movement_gravity;
float physics_override_speed;
float physics_override_jump;
float physics_override_gravity;
bool physics_override_sneak;
bool physics_override_sneak_glitch;
v2s32 local_animations[4];
float local_animation_speed;
u16 hp;
float hurt_tilt_timer;
float hurt_tilt_strength;
u16 protocol_version;
u16 peer_id;
std::string inventory_formspec;
PlayerControl control;
PlayerControl getPlayerControl()
{
return control;
}
const PlayerControl& getPlayerControl() { return control; }
u32 keyPressed;
HudElement* getHud(u32 id);
u32 addHud(HudElement* hud);
HudElement* removeHud(u32 id);
void clearHud();
u32 maxHudId() {
return hud.size();
}
u32 hud_flags;
s32 hud_hotbar_itemcount;
std::string hud_hotbar_image;
std::string hud_hotbar_selected_image;
protected:
IGameDef *m_gamedef;
char m_name[PLAYERNAME_SIZE];
u16 m_breath;
f32 m_pitch;
@ -422,16 +232,7 @@ protected:
v3f m_position;
aabb3f m_collisionbox;
bool m_dirty;
std::vector<HudElement *> hud;
std::string m_sky_type;
video::SColor m_sky_bgcolor;
std::vector<std::string> m_sky_params;
bool m_day_night_ratio_do_override;
float m_day_night_ratio;
private:
// Protect some critical areas
// hud for example can be modified by EmergeThread
@ -439,27 +240,5 @@ private:
Mutex m_mutex;
};
/*
Player on the server
*/
class RemotePlayer : public Player
{
public:
RemotePlayer(IGameDef *gamedef, const char *name);
virtual ~RemotePlayer() {}
void save(std::string savedir);
PlayerSAO *getPlayerSAO()
{ return m_sao; }
void setPlayerSAO(PlayerSAO *sao)
{ m_sao = sao; }
void setPosition(const v3f &position);
private:
PlayerSAO *m_sao;
};
#endif

View File

@ -613,10 +613,11 @@ void setXorgClassHint(const video::SExposedVideoData &video_data,
bool setXorgWindowIcon(IrrlichtDevice *device)
{
#if RUN_IN_PLACE
#ifdef XORG_USED
# if RUN_IN_PLACE
return setXorgWindowIconFromPath(device,
path_share + "/misc/" PROJECT_NAME "-xorg-icon-128.png");
#else
# else
// We have semi-support for reading in-place data if we are
// compiled with RUN_IN_PLACE. Don't break with this and
// also try the path_share location.
@ -625,6 +626,9 @@ bool setXorgWindowIcon(IrrlichtDevice *device)
ICON_DIR "/hicolor/128x128/apps/" PROJECT_NAME ".png") ||
setXorgWindowIconFromPath(device,
path_share + "/misc/" PROJECT_NAME "-xorg-icon-128.png");
# endif
#else
return false;
#endif
}

230
src/remoteplayer.cpp Normal file
View File

@ -0,0 +1,230 @@
/*
Minetest
Copyright (C) 2010-2016 celeron55, Perttu Ahola <celeron55@gmail.com>
Copyright (C) 2014-2016 nerzhul, Loic Blot <loic.blot@unix-experience.fr>
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 "remoteplayer.h"
#include "content_sao.h"
#include "filesys.h"
#include "gamedef.h"
#include "porting.h" // strlcpy
#include "settings.h"
/*
RemotePlayer
*/
// static config cache for remoteplayer
bool RemotePlayer::m_setting_cache_loaded = false;
float RemotePlayer::m_setting_chat_message_limit_per_10sec = 0.0f;
u16 RemotePlayer::m_setting_chat_message_limit_trigger_kick = 0;
RemotePlayer::RemotePlayer(const char *name, IItemDefManager *idef):
Player(name, idef),
protocol_version(0),
m_sao(NULL),
m_dirty(false),
m_last_chat_message_sent(time(NULL)),
m_chat_message_allowance(5.0f),
m_message_rate_overhead(0),
hud_hotbar_image(""),
hud_hotbar_selected_image("")
{
if (!RemotePlayer::m_setting_cache_loaded) {
RemotePlayer::m_setting_chat_message_limit_per_10sec =
g_settings->getFloat("chat_message_limit_per_10sec");
RemotePlayer::m_setting_chat_message_limit_trigger_kick =
g_settings->getU16("chat_message_limit_trigger_kick");
RemotePlayer::m_setting_cache_loaded = true;
}
movement_acceleration_default = g_settings->getFloat("movement_acceleration_default") * BS;
movement_acceleration_air = g_settings->getFloat("movement_acceleration_air") * BS;
movement_acceleration_fast = g_settings->getFloat("movement_acceleration_fast") * BS;
movement_speed_walk = g_settings->getFloat("movement_speed_walk") * BS;
movement_speed_crouch = g_settings->getFloat("movement_speed_crouch") * BS;
movement_speed_fast = g_settings->getFloat("movement_speed_fast") * BS;
movement_speed_climb = g_settings->getFloat("movement_speed_climb") * BS;
movement_speed_jump = g_settings->getFloat("movement_speed_jump") * BS;
movement_liquid_fluidity = g_settings->getFloat("movement_liquid_fluidity") * BS;
movement_liquid_fluidity_smooth = g_settings->getFloat("movement_liquid_fluidity_smooth") * BS;
movement_liquid_sink = g_settings->getFloat("movement_liquid_sink") * BS;
movement_gravity = g_settings->getFloat("movement_gravity") * BS;
}
void RemotePlayer::save(std::string savedir, IGameDef *gamedef)
{
/*
* We have to open all possible player files in the players directory
* and check their player names because some file systems are not
* case-sensitive and player names are case-sensitive.
*/
// A player to deserialize files into to check their names
RemotePlayer testplayer("", gamedef->idef());
savedir += DIR_DELIM;
std::string path = savedir + m_name;
for (u32 i = 0; i < PLAYER_FILE_ALTERNATE_TRIES; i++) {
if (!fs::PathExists(path)) {
// Open file and serialize
std::ostringstream ss(std::ios_base::binary);
serialize(ss);
if (!fs::safeWriteToFile(path, ss.str())) {
infostream << "Failed to write " << path << std::endl;
}
setModified(false);
return;
}
// Open file and deserialize
std::ifstream is(path.c_str(), std::ios_base::binary);
if (!is.good()) {
infostream << "Failed to open " << path << std::endl;
return;
}
testplayer.deSerialize(is, path);
is.close();
if (strcmp(testplayer.getName(), m_name) == 0) {
// Open file and serialize
std::ostringstream ss(std::ios_base::binary);
serialize(ss);
if (!fs::safeWriteToFile(path, ss.str())) {
infostream << "Failed to write " << path << std::endl;
}
setModified(false);
return;
}
path = savedir + m_name + itos(i);
}
infostream << "Didn't find free file for player " << m_name << std::endl;
return;
}
void RemotePlayer::deSerialize(std::istream &is, const std::string &playername)
{
Settings args;
if (!args.parseConfigLines(is, "PlayerArgsEnd")) {
throw SerializationError("PlayerArgsEnd of player " +
playername + " not found!");
}
m_dirty = true;
//args.getS32("version"); // Version field value not used
std::string name = args.get("name");
strlcpy(m_name, name.c_str(), PLAYERNAME_SIZE);
setPitch(args.getFloat("pitch"));
setYaw(args.getFloat("yaw"));
setPosition(args.getV3F("position"));
try {
hp = args.getS32("hp");
} catch(SettingNotFoundException &e) {
hp = PLAYER_MAX_HP;
}
try {
m_breath = args.getS32("breath");
} catch(SettingNotFoundException &e) {
m_breath = PLAYER_MAX_BREATH;
}
inventory.deSerialize(is);
if(inventory.getList("craftpreview") == NULL) {
// Convert players without craftpreview
inventory.addList("craftpreview", 1);
bool craftresult_is_preview = true;
if(args.exists("craftresult_is_preview"))
craftresult_is_preview = args.getBool("craftresult_is_preview");
if(craftresult_is_preview)
{
// Clear craftresult
inventory.getList("craftresult")->changeItem(0, ItemStack());
}
}
}
void RemotePlayer::serialize(std::ostream &os)
{
// Utilize a Settings object for storing values
Settings args;
args.setS32("version", 1);
args.set("name", m_name);
//args.set("password", m_password);
args.setFloat("pitch", m_pitch);
args.setFloat("yaw", m_yaw);
args.setV3F("position", m_position);
args.setS32("hp", hp);
args.setS32("breath", m_breath);
args.writeLines(os);
os<<"PlayerArgsEnd\n";
inventory.serialize(os);
}
void RemotePlayer::setPosition(const v3f &position)
{
if (position != m_position)
m_dirty = true;
Player::setPosition(position);
if(m_sao)
m_sao->setBasePosition(position);
}
const RemotePlayerChatResult RemotePlayer::canSendChatMessage()
{
// Rate limit messages
u32 now = time(NULL);
float time_passed = now - m_last_chat_message_sent;
m_last_chat_message_sent = now;
// If this feature is disabled
if (m_setting_chat_message_limit_per_10sec <= 0.0) {
return RPLAYER_CHATRESULT_OK;
}
m_chat_message_allowance += time_passed * (m_setting_chat_message_limit_per_10sec / 8.0f);
if (m_chat_message_allowance > m_setting_chat_message_limit_per_10sec) {
m_chat_message_allowance = m_setting_chat_message_limit_per_10sec;
}
if (m_chat_message_allowance < 1.0f) {
infostream << "Player " << m_name
<< " chat limited due to excessive message amount." << std::endl;
// Kick player if flooding is too intensive
m_message_rate_overhead++;
if (m_message_rate_overhead > RemotePlayer::m_setting_chat_message_limit_trigger_kick) {
return RPLAYER_CHATRESULT_KICK;
}
return RPLAYER_CHATRESULT_FLOODING;
}
// Reinit message overhead
if (m_message_rate_overhead > 0) {
m_message_rate_overhead = 0;
}
m_chat_message_allowance -= 1.0f;
return RPLAYER_CHATRESULT_OK;
}

189
src/remoteplayer.h Normal file
View File

@ -0,0 +1,189 @@
/*
Minetest
Copyright (C) 2010-2016 celeron55, Perttu Ahola <celeron55@gmail.com>
Copyright (C) 2014-2016 nerzhul, Loic Blot <loic.blot@unix-experience.fr>
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 REMOTEPLAYER_HEADER
#define REMOTEPLAYER_HEADER
#include "player.h"
class PlayerSAO;
enum RemotePlayerChatResult {
RPLAYER_CHATRESULT_OK,
RPLAYER_CHATRESULT_FLOODING,
RPLAYER_CHATRESULT_KICK,
};
/*
Player on the server
*/
class RemotePlayer : public Player
{
public:
RemotePlayer(const char *name, IItemDefManager *idef);
virtual ~RemotePlayer() {}
void save(std::string savedir, IGameDef *gamedef);
void deSerialize(std::istream &is, const std::string &playername);
PlayerSAO *getPlayerSAO() { return m_sao; }
void setPlayerSAO(PlayerSAO *sao) { m_sao = sao; }
void setPosition(const v3f &position);
const RemotePlayerChatResult canSendChatMessage();
void setHotbarItemcount(s32 hotbar_itemcount)
{
hud_hotbar_itemcount = hotbar_itemcount;
}
s32 getHotbarItemcount() const { return hud_hotbar_itemcount; }
void overrideDayNightRatio(bool do_override, float ratio)
{
m_day_night_ratio_do_override = do_override;
m_day_night_ratio = ratio;
}
void getDayNightRatio(bool *do_override, float *ratio)
{
*do_override = m_day_night_ratio_do_override;
*ratio = m_day_night_ratio;
}
// Use a function, if isDead can be defined by other conditions
bool isDead() const { return hp == 0; }
void setHotbarImage(const std::string &name)
{
hud_hotbar_image = name;
}
std::string getHotbarImage() const
{
return hud_hotbar_image;
}
void setHotbarSelectedImage(const std::string &name)
{
hud_hotbar_selected_image = name;
}
const std::string &getHotbarSelectedImage() const
{
return hud_hotbar_selected_image;
}
// Deprecated
f32 getRadPitchDep() const { return -1.0 * m_pitch * core::DEGTORAD; }
// Deprecated
f32 getRadYawDep() const { return (m_yaw + 90.) * core::DEGTORAD; }
void setSky(const video::SColor &bgcolor, const std::string &type,
const std::vector<std::string> &params)
{
m_sky_bgcolor = bgcolor;
m_sky_type = type;
m_sky_params = params;
}
void getSky(video::SColor *bgcolor, std::string *type,
std::vector<std::string> *params)
{
*bgcolor = m_sky_bgcolor;
*type = m_sky_type;
*params = m_sky_params;
}
bool checkModified() const { return m_dirty || inventory.checkModified(); }
void setModified(const bool x)
{
m_dirty = x;
if (!x)
inventory.setModified(x);
}
virtual void setBreath(u16 breath)
{
if (breath != m_breath)
m_dirty = true;
Player::setBreath(breath);
}
virtual void setPitch(f32 pitch)
{
if (pitch != m_pitch)
m_dirty = true;
Player::setPitch(pitch);
}
virtual void setYaw(f32 yaw)
{
if (yaw != m_yaw)
m_dirty = true;
Player::setYaw(yaw);
}
void setLocalAnimations(v2s32 frames[4], float frame_speed)
{
for (int i = 0; i < 4; i++)
local_animations[i] = frames[i];
local_animation_speed = frame_speed;
}
void getLocalAnimations(v2s32 *frames, float *frame_speed)
{
for (int i = 0; i < 4; i++)
frames[i] = local_animations[i];
*frame_speed = local_animation_speed;
}
u16 protocol_version;
private:
/*
serialize() writes a bunch of text that can contain
any characters except a '\0', and such an ending that
deSerialize stops reading exactly at the right point.
*/
void serialize(std::ostream &os);
PlayerSAO *m_sao;
bool m_dirty;
static bool m_setting_cache_loaded;
static float m_setting_chat_message_limit_per_10sec;
static u16 m_setting_chat_message_limit_trigger_kick;
u32 m_last_chat_message_sent;
float m_chat_message_allowance;
u16 m_message_rate_overhead;
bool m_day_night_ratio_do_override;
float m_day_night_ratio;
std::string hud_hotbar_image;
std::string hud_hotbar_selected_image;
std::string m_sky_type;
video::SColor m_sky_bgcolor;
std::vector<std::string> m_sky_params;
};
#endif

View File

@ -831,20 +831,18 @@ void push_tool_capabilities(lua_State *L,
// Create groupcaps table
lua_newtable(L);
// For each groupcap
for(std::map<std::string, ToolGroupCap>::const_iterator
i = toolcap.groupcaps.begin(); i != toolcap.groupcaps.end(); i++){
for (ToolGCMap::const_iterator i = toolcap.groupcaps.begin();
i != toolcap.groupcaps.end(); i++) {
// Create groupcap table
lua_newtable(L);
const std::string &name = i->first;
const ToolGroupCap &groupcap = i->second;
// Create subtable "times"
lua_newtable(L);
for(std::map<int, float>::const_iterator
i = groupcap.times.begin(); i != groupcap.times.end(); i++){
int rating = i->first;
float time = i->second;
lua_pushinteger(L, rating);
lua_pushnumber(L, time);
for (UNORDERED_MAP<int, float>::const_iterator
i = groupcap.times.begin(); i != groupcap.times.end(); i++) {
lua_pushinteger(L, i->first);
lua_pushnumber(L, i->second);
lua_settable(L, -3);
}
// Set subtable "times"
@ -860,8 +858,8 @@ void push_tool_capabilities(lua_State *L,
//Create damage_groups table
lua_newtable(L);
// For each damage group
for(std::map<std::string, s16>::const_iterator
i = toolcap.damageGroups.begin(); i != toolcap.damageGroups.end(); i++){
for (DamageGroup::const_iterator i = toolcap.damageGroups.begin();
i != toolcap.damageGroups.end(); i++) {
// Create damage group table
lua_pushinteger(L, i->second);
lua_setfield(L, -2, i->first.c_str());
@ -1067,8 +1065,7 @@ void push_flags_string(lua_State *L, FlagDesc *flagdesc, u32 flags, u32 flagmask
/******************************************************************************/
/******************************************************************************/
void read_groups(lua_State *L, int index,
std::map<std::string, int> &result)
void read_groups(lua_State *L, int index, ItemGroupList &result)
{
if (!lua_istable(L,index))
return;
@ -1087,11 +1084,10 @@ void read_groups(lua_State *L, int index,
}
/******************************************************************************/
void push_groups(lua_State *L, const std::map<std::string, int> &groups)
void push_groups(lua_State *L, const ItemGroupList &groups)
{
lua_newtable(L);
std::map<std::string, int>::const_iterator it;
for (it = groups.begin(); it != groups.end(); ++it) {
for (ItemGroupList::const_iterator it = groups.begin(); it != groups.end(); ++it) {
lua_pushnumber(L, it->second);
lua_setfield(L, -2, it->first.c_str());
}

View File

@ -33,11 +33,11 @@ extern "C" {
}
#include <iostream>
#include <map>
#include <vector>
#include "irrlichttypes_bloated.h"
#include "util/string.h"
#include "itemgroup.h"
namespace Json { class Value; }
@ -106,10 +106,10 @@ void pushnode (lua_State *L, const MapNode &n,
NodeBox read_nodebox (lua_State *L, int index);
void read_groups (lua_State *L, int index,
std::map<std::string, int> &result);
ItemGroupList &result);
void push_groups (lua_State *L,
const std::map<std::string, int> &groups);
const ItemGroupList &groups);
//TODO rename to "read_enum_field"
int getenumfield (lua_State *L, int table,

View File

@ -23,6 +23,7 @@ extern "C" {
}
#include "util/numeric.h"
#include "util/serialize.h"
#include "util/string.h"
#include "common/c_converter.h"
#include "constants.h"
@ -37,6 +38,14 @@ extern "C" {
} \
} while(0)
#define CHECK_POS_COORD(name) CHECK_TYPE(-1, "position coordinate '" name "'", LUA_TNUMBER)
#define CHECK_FLOAT_RANGE(value, name) \
if (value < F1000_MIN || value > F1000_MAX) { \
std::ostringstream error_text; \
error_text << "Invalid float vector dimension range '" name "' " << \
"(expected " << F1000_MIN << " < " name " < " << F1000_MAX << \
" got " << value << ")." << std::endl; \
throw LuaError(error_text.str()); \
}
#define CHECK_POS_TAB(index) CHECK_TYPE(index, "position", LUA_TTABLE)
@ -170,14 +179,17 @@ v3f check_v3f(lua_State *L, int index)
lua_getfield(L, index, "x");
CHECK_POS_COORD("x");
pos.X = lua_tonumber(L, -1);
CHECK_FLOAT_RANGE(pos.X, "x")
lua_pop(L, 1);
lua_getfield(L, index, "y");
CHECK_POS_COORD("y");
pos.Y = lua_tonumber(L, -1);
CHECK_FLOAT_RANGE(pos.Y, "y")
lua_pop(L, 1);
lua_getfield(L, index, "z");
CHECK_POS_COORD("z");
pos.Z = lua_tonumber(L, -1);
CHECK_FLOAT_RANGE(pos.Z, "z")
lua_pop(L, 1);
return pos;
}

View File

@ -28,7 +28,7 @@ with this program; if not, write to the Free Software Foundation, Inc.,
#define C_CONVERTER_H_
#include <vector>
#include <map>
#include "util/cpp11_container.h"
#include "irrlichttypes_bloated.h"
#include "common/c_types.h"
@ -60,7 +60,7 @@ bool getintfield(lua_State *L, int table,
bool getintfield(lua_State *L, int table,
const char *fieldname, u32 &result);
void read_groups(lua_State *L, int index,
std::map<std::string, int> &result);
UNORDERED_MAP<std::string, int> &result);
bool getboolfield(lua_State *L, int table,
const char *fieldname, bool &result);
bool getfloatfield(lua_State *L, int table,

View File

@ -81,6 +81,7 @@ bool AsyncEngine::registerFunction(const char* name, lua_CFunction func)
if (initDone) {
return false;
}
functionList[name] = func;
return true;
}
@ -203,7 +204,7 @@ void AsyncEngine::pushFinishedJobs(lua_State* L) {
/******************************************************************************/
void AsyncEngine::prepareEnvironment(lua_State* L, int top)
{
for (std::map<std::string, lua_CFunction>::iterator it = functionList.begin();
for (UNORDERED_MAP<std::string, lua_CFunction>::iterator it = functionList.begin();
it != functionList.end(); it++) {
lua_pushstring(L, it->first.c_str());
lua_pushcfunction(L, it->second);

View File

@ -132,7 +132,7 @@ private:
bool initDone;
// Internal store for registred functions
std::map<std::string, lua_CFunction> functionList;
UNORDERED_MAP<std::string, lua_CFunction> functionList;
// Internal counter to create job IDs
unsigned int jobIdCounter;

View File

@ -212,11 +212,13 @@ void ScriptApiEnv::on_emerge_area_completion(
{
Server *server = getServer();
// This function should be executed with envlock held.
// The caller (LuaEmergeAreaCallback in src/script/lua_api/l_env.cpp)
// should have obtained the lock.
// Note that the order of these locks is important! Envlock must *ALWAYS*
// be acquired before attempting to acquire scriptlock, or else ServerThread
// will try to acquire scriptlock after it already owns envlock, thus
// deadlocking EmergeThread and ServerThread
MutexAutoLock envlock(server->m_env_mutex);
SCRIPTAPI_PRECHECKHEADER

View File

@ -137,6 +137,10 @@ void LuaEmergeAreaCallback(v3s16 blockpos, EmergeAction action, void *param)
assert(state->script != NULL);
assert(state->refcount > 0);
// state must be protected by envlock
Server *server = state->script->getServer();
MutexAutoLock envlock(server->m_env_mutex);
state->refcount--;
state->script->on_emerge_area_completion(blockpos, action, state);
@ -494,8 +498,8 @@ int ModApiEnvMod::l_get_player_by_name(lua_State *L)
// Do it
const char *name = luaL_checkstring(L, 1);
Player *player = env->getPlayer(name);
if(player == NULL){
RemotePlayer *player = dynamic_cast<RemotePlayer *>(env->getPlayer(name));
if (player == NULL){
lua_pushnil(L);
return 1;
}

View File

@ -420,7 +420,7 @@ void InvRef::create(lua_State *L, const InventoryLocation &loc)
luaL_getmetatable(L, className);
lua_setmetatable(L, -2);
}
void InvRef::createPlayer(lua_State *L, Player *player)
void InvRef::createPlayer(lua_State *L, RemotePlayer *player)
{
NO_MAP_LOCK_REQUIRED;
InventoryLocation loc;

View File

@ -25,7 +25,7 @@ with this program; if not, write to the Free Software Foundation, Inc.,
#include "inventory.h"
#include "inventorymanager.h"
class Player;
class RemotePlayer;
/*
InvRef
@ -112,7 +112,7 @@ public:
// Creates an InvRef and leaves it on top of stack
// Not callable from Lua; all references are created on the C side.
static void create(lua_State *L, const InventoryLocation &loc);
static void createPlayer(lua_State *L, Player *player);
static void createPlayer(lua_State *L, RemotePlayer *player);
static void createNodeMeta(lua_State *L, v3s16 p);
static void Register(lua_State *L);
};
@ -123,11 +123,6 @@ private:
static int l_get_inventory(lua_State *L);
static void inventory_set_list_from_lua(Inventory *inv, const char *name,
lua_State *L, int tableindex, int forcesize);
static void inventory_get_list_to_lua(Inventory *inv, const char *name,
lua_State *L);
public:
static void Initialize(lua_State *L, int top);
};

View File

@ -244,7 +244,7 @@ bool read_schematic_def(lua_State *L, int index,
schem->schemdata = new MapNode[numnodes];
size_t names_base = names->size();
std::map<std::string, content_t> name_id_map;
UNORDERED_MAP<std::string, content_t> name_id_map;
u32 i = 0;
for (lua_pushnil(L); lua_next(L, -2); i++, lua_pop(L, 1)) {
@ -266,7 +266,7 @@ bool read_schematic_def(lua_State *L, int index,
u8 param2 = getintfield_default(L, -1, "param2", 0);
//// Find or add new nodename-to-ID mapping
std::map<std::string, content_t>::iterator it = name_id_map.find(name);
UNORDERED_MAP<std::string, content_t>::iterator it = name_id_map.find(name);
content_t name_index;
if (it != name_id_map.end()) {
name_index = it->second;

View File

@ -107,7 +107,7 @@ PlayerSAO* ObjectRef::getplayersao(ObjectRef *ref)
return (PlayerSAO*)obj;
}
Player* ObjectRef::getplayer(ObjectRef *ref)
RemotePlayer *ObjectRef::getplayer(ObjectRef *ref)
{
PlayerSAO *playersao = getplayersao(ref);
if (playersao == NULL)
@ -137,8 +137,8 @@ int ObjectRef::l_remove(lua_State *L)
if (co->getType() == ACTIVEOBJECT_TYPE_PLAYER)
return 0;
std::set<int> child_ids = co->getAttachmentChildIds();
std::set<int>::iterator it;
UNORDERED_SET<int> child_ids = co->getAttachmentChildIds();
UNORDERED_SET<int>::iterator it;
for (it = child_ids.begin(); it != child_ids.end(); ++it) {
ServerActiveObject *child = env->getActiveObject(*it);
child->setAttachment(0, "", v3f(0, 0, 0), v3f(0, 0, 0));
@ -508,7 +508,7 @@ int ObjectRef::l_set_local_animation(lua_State *L)
{
NO_MAP_LOCK_REQUIRED;
ObjectRef *ref = checkobject(L, 1);
Player *player = getplayer(ref);
RemotePlayer *player = getplayer(ref);
if (player == NULL)
return 0;
// Do it
@ -533,7 +533,7 @@ int ObjectRef::l_get_local_animation(lua_State *L)
{
NO_MAP_LOCK_REQUIRED
ObjectRef *ref = checkobject(L, 1);
Player *player = getplayer(ref);
RemotePlayer *player = getplayer(ref);
if (player == NULL)
return 0;
@ -554,7 +554,7 @@ int ObjectRef::l_set_eye_offset(lua_State *L)
{
NO_MAP_LOCK_REQUIRED;
ObjectRef *ref = checkobject(L, 1);
Player *player = getplayer(ref);
RemotePlayer *player = getplayer(ref);
if (player == NULL)
return 0;
// Do it
@ -584,7 +584,7 @@ int ObjectRef::l_get_eye_offset(lua_State *L)
{
NO_MAP_LOCK_REQUIRED;
ObjectRef *ref = checkobject(L, 1);
Player *player = getplayer(ref);
RemotePlayer *player = getplayer(ref);
if (player == NULL)
return 0;
// Do it
@ -606,10 +606,10 @@ int ObjectRef::l_set_bone_position(lua_State *L)
bone = lua_tostring(L, 2);
v3f position = v3f(0, 0, 0);
if (!lua_isnil(L, 3))
position = read_v3f(L, 3);
position = check_v3f(L, 3);
v3f rotation = v3f(0, 0, 0);
if (!lua_isnil(L, 4))
rotation = read_v3f(L, 4);
rotation = check_v3f(L, 4);
co->setBonePosition(bone, position, rotation);
return 0;
}
@ -762,7 +762,7 @@ int ObjectRef::l_is_player(lua_State *L)
{
NO_MAP_LOCK_REQUIRED;
ObjectRef *ref = checkobject(L, 1);
Player *player = getplayer(ref);
RemotePlayer *player = getplayer(ref);
lua_pushboolean(L, (player != NULL));
return 1;
}
@ -973,7 +973,7 @@ int ObjectRef::l_is_player_connected(lua_State *L)
{
NO_MAP_LOCK_REQUIRED;
ObjectRef *ref = checkobject(L, 1);
Player *player = getplayer(ref);
RemotePlayer *player = getplayer(ref);
lua_pushboolean(L, (player != NULL && player->peer_id != 0));
return 1;
}
@ -983,7 +983,7 @@ int ObjectRef::l_get_player_name(lua_State *L)
{
NO_MAP_LOCK_REQUIRED;
ObjectRef *ref = checkobject(L, 1);
Player *player = getplayer(ref);
RemotePlayer *player = getplayer(ref);
if (player == NULL) {
lua_pushlstring(L, "", 0);
return 1;
@ -998,7 +998,7 @@ int ObjectRef::l_get_player_velocity(lua_State *L)
{
NO_MAP_LOCK_REQUIRED;
ObjectRef *ref = checkobject(L, 1);
Player *player = getplayer(ref);
RemotePlayer *player = getplayer(ref);
if (player == NULL) {
lua_pushnil(L);
return 1;
@ -1013,7 +1013,7 @@ int ObjectRef::l_get_look_dir(lua_State *L)
{
NO_MAP_LOCK_REQUIRED;
ObjectRef *ref = checkobject(L, 1);
Player *player = getplayer(ref);
RemotePlayer *player = getplayer(ref);
if (player == NULL) return 0;
// Do it
float pitch = player->getRadPitchDep();
@ -1033,7 +1033,7 @@ int ObjectRef::l_get_look_pitch(lua_State *L)
"Deprecated call to get_look_pitch, use get_look_vertical instead");
ObjectRef *ref = checkobject(L, 1);
Player *player = getplayer(ref);
RemotePlayer *player = getplayer(ref);
if (player == NULL) return 0;
// Do it
lua_pushnumber(L, player->getRadPitchDep());
@ -1050,7 +1050,7 @@ int ObjectRef::l_get_look_yaw(lua_State *L)
"Deprecated call to get_look_yaw, use get_look_horizontal instead");
ObjectRef *ref = checkobject(L, 1);
Player *player = getplayer(ref);
RemotePlayer *player = getplayer(ref);
if (player == NULL) return 0;
// Do it
lua_pushnumber(L, player->getRadYawDep());
@ -1062,7 +1062,7 @@ int ObjectRef::l_get_look_vertical(lua_State *L)
{
NO_MAP_LOCK_REQUIRED;
ObjectRef *ref = checkobject(L, 1);
Player *player = getplayer(ref);
RemotePlayer *player = getplayer(ref);
if (player == NULL) return 0;
// Do it
lua_pushnumber(L, player->getRadPitch());
@ -1074,7 +1074,7 @@ int ObjectRef::l_get_look_horizontal(lua_State *L)
{
NO_MAP_LOCK_REQUIRED;
ObjectRef *ref = checkobject(L, 1);
Player *player = getplayer(ref);
RemotePlayer *player = getplayer(ref);
if (player == NULL) return 0;
// Do it
lua_pushnumber(L, player->getRadYaw());
@ -1179,7 +1179,7 @@ int ObjectRef::l_set_inventory_formspec(lua_State *L)
{
NO_MAP_LOCK_REQUIRED;
ObjectRef *ref = checkobject(L, 1);
Player *player = getplayer(ref);
RemotePlayer *player = getplayer(ref);
if (player == NULL) return 0;
std::string formspec = luaL_checkstring(L, 2);
@ -1194,7 +1194,7 @@ int ObjectRef::l_get_inventory_formspec(lua_State *L)
{
NO_MAP_LOCK_REQUIRED;
ObjectRef *ref = checkobject(L, 1);
Player *player = getplayer(ref);
RemotePlayer *player = getplayer(ref);
if (player == NULL) return 0;
std::string formspec = player->inventory_formspec;
@ -1207,13 +1207,13 @@ int ObjectRef::l_get_player_control(lua_State *L)
{
NO_MAP_LOCK_REQUIRED;
ObjectRef *ref = checkobject(L, 1);
Player *player = getplayer(ref);
RemotePlayer *player = getplayer(ref);
if (player == NULL) {
lua_pushlstring(L, "", 0);
return 1;
}
// Do it
PlayerControl control = player->getPlayerControl();
const PlayerControl &control = player->getPlayerControl();
lua_newtable(L);
lua_pushboolean(L, control.up);
lua_setfield(L, -2, "up");
@ -1241,7 +1241,7 @@ int ObjectRef::l_get_player_control_bits(lua_State *L)
{
NO_MAP_LOCK_REQUIRED;
ObjectRef *ref = checkobject(L, 1);
Player *player = getplayer(ref);
RemotePlayer *player = getplayer(ref);
if (player == NULL) {
lua_pushlstring(L, "", 0);
return 1;
@ -1256,7 +1256,7 @@ int ObjectRef::l_hud_add(lua_State *L)
{
NO_MAP_LOCK_REQUIRED;
ObjectRef *ref = checkobject(L, 1);
Player *player = getplayer(ref);
RemotePlayer *player = getplayer(ref);
if (player == NULL)
return 0;
@ -1319,7 +1319,7 @@ int ObjectRef::l_hud_remove(lua_State *L)
{
NO_MAP_LOCK_REQUIRED;
ObjectRef *ref = checkobject(L, 1);
Player *player = getplayer(ref);
RemotePlayer *player = getplayer(ref);
if (player == NULL)
return 0;
@ -1339,7 +1339,7 @@ int ObjectRef::l_hud_change(lua_State *L)
{
NO_MAP_LOCK_REQUIRED;
ObjectRef *ref = checkobject(L, 1);
Player *player = getplayer(ref);
RemotePlayer *player = getplayer(ref);
if (player == NULL)
return 0;
@ -1416,7 +1416,7 @@ int ObjectRef::l_hud_get(lua_State *L)
{
NO_MAP_LOCK_REQUIRED;
ObjectRef *ref = checkobject(L, 1);
Player *player = getplayer(ref);
RemotePlayer *player = getplayer(ref);
if (player == NULL)
return 0;
@ -1467,7 +1467,7 @@ int ObjectRef::l_hud_set_flags(lua_State *L)
{
NO_MAP_LOCK_REQUIRED;
ObjectRef *ref = checkobject(L, 1);
Player *player = getplayer(ref);
RemotePlayer *player = getplayer(ref);
if (player == NULL)
return 0;
@ -1493,7 +1493,7 @@ int ObjectRef::l_hud_get_flags(lua_State *L)
{
NO_MAP_LOCK_REQUIRED;
ObjectRef *ref = checkobject(L, 1);
Player *player = getplayer(ref);
RemotePlayer *player = getplayer(ref);
if (player == NULL)
return 0;
@ -1519,7 +1519,7 @@ int ObjectRef::l_hud_set_hotbar_itemcount(lua_State *L)
{
NO_MAP_LOCK_REQUIRED;
ObjectRef *ref = checkobject(L, 1);
Player *player = getplayer(ref);
RemotePlayer *player = getplayer(ref);
if (player == NULL)
return 0;
@ -1537,7 +1537,7 @@ int ObjectRef::l_hud_get_hotbar_itemcount(lua_State *L)
{
NO_MAP_LOCK_REQUIRED;
ObjectRef *ref = checkobject(L, 1);
Player *player = getplayer(ref);
RemotePlayer *player = getplayer(ref);
if (player == NULL)
return 0;
@ -1552,7 +1552,7 @@ int ObjectRef::l_hud_set_hotbar_image(lua_State *L)
{
NO_MAP_LOCK_REQUIRED;
ObjectRef *ref = checkobject(L, 1);
Player *player = getplayer(ref);
RemotePlayer *player = getplayer(ref);
if (player == NULL)
return 0;
@ -1567,7 +1567,7 @@ int ObjectRef::l_hud_get_hotbar_image(lua_State *L)
{
NO_MAP_LOCK_REQUIRED;
ObjectRef *ref = checkobject(L, 1);
Player *player = getplayer(ref);
RemotePlayer *player = getplayer(ref);
if (player == NULL)
return 0;
@ -1581,7 +1581,7 @@ int ObjectRef::l_hud_set_hotbar_selected_image(lua_State *L)
{
NO_MAP_LOCK_REQUIRED;
ObjectRef *ref = checkobject(L, 1);
Player *player = getplayer(ref);
RemotePlayer *player = getplayer(ref);
if (player == NULL)
return 0;
@ -1596,11 +1596,11 @@ int ObjectRef::l_hud_get_hotbar_selected_image(lua_State *L)
{
NO_MAP_LOCK_REQUIRED;
ObjectRef *ref = checkobject(L, 1);
Player *player = getplayer(ref);
RemotePlayer *player = getplayer(ref);
if (player == NULL)
return 0;
std::string name = getServer(L)->hudGetHotbarSelectedImage(player);
const std::string &name = getServer(L)->hudGetHotbarSelectedImage(player);
lua_pushlstring(L, name.c_str(), name.size());
return 1;
}
@ -1610,7 +1610,7 @@ int ObjectRef::l_set_sky(lua_State *L)
{
NO_MAP_LOCK_REQUIRED;
ObjectRef *ref = checkobject(L, 1);
Player *player = getplayer(ref);
RemotePlayer *player = getplayer(ref);
if (player == NULL)
return 0;
@ -1649,7 +1649,7 @@ int ObjectRef::l_get_sky(lua_State *L)
{
NO_MAP_LOCK_REQUIRED;
ObjectRef *ref = checkobject(L, 1);
Player *player = getplayer(ref);
RemotePlayer *player = getplayer(ref);
if (player == NULL)
return 0;
video::SColor bgcolor(255, 255, 255, 255);
@ -1677,7 +1677,7 @@ int ObjectRef::l_override_day_night_ratio(lua_State *L)
{
NO_MAP_LOCK_REQUIRED;
ObjectRef *ref = checkobject(L, 1);
Player *player = getplayer(ref);
RemotePlayer *player = getplayer(ref);
if (player == NULL)
return 0;
@ -1700,7 +1700,7 @@ int ObjectRef::l_get_day_night_ratio(lua_State *L)
{
NO_MAP_LOCK_REQUIRED;
ObjectRef *ref = checkobject(L, 1);
Player *player = getplayer(ref);
RemotePlayer *player = getplayer(ref);
if (player == NULL)
return 0;

View File

@ -26,7 +26,7 @@ with this program; if not, write to the Free Software Foundation, Inc.,
class ServerActiveObject;
class LuaEntitySAO;
class PlayerSAO;
class Player;
class RemotePlayer;
/*
ObjectRef
@ -47,7 +47,7 @@ private:
static PlayerSAO* getplayersao(ObjectRef *ref);
static Player* getplayer(ObjectRef *ref);
static RemotePlayer *getplayer(ObjectRef *ref);
// Exported functions

View File

@ -207,7 +207,7 @@ int ModApiParticles::l_add_particlespawner(lua_State *L)
lua_pop(L, 1);
attached = ObjectRef::getobject(ref);
}
vertical = getboolfield_default(L, 1, "vertical", vertical);
texture = getstringfield_default(L, 1, "texture", "");
playername = getstringfield_default(L, 1, "playername", "");

View File

@ -106,7 +106,7 @@ int ModApiServer::l_get_player_ip(lua_State *L)
{
NO_MAP_LOCK_REQUIRED;
const char * name = luaL_checkstring(L, 1);
Player *player = getEnv(L)->getPlayer(name);
RemotePlayer *player = dynamic_cast<ServerEnvironment *>(getEnv(L))->getPlayer(name);
if(player == NULL)
{
lua_pushnil(L); // no such player
@ -133,9 +133,8 @@ int ModApiServer::l_get_player_information(lua_State *L)
NO_MAP_LOCK_REQUIRED;
const char * name = luaL_checkstring(L, 1);
Player *player = getEnv(L)->getPlayer(name);
if(player == NULL)
{
RemotePlayer *player = dynamic_cast<ServerEnvironment *>(getEnv(L))->getPlayer(name);
if (player == NULL) {
lua_pushnil(L); // no such player
return 1;
}
@ -278,15 +277,15 @@ int ModApiServer::l_ban_player(lua_State *L)
{
NO_MAP_LOCK_REQUIRED;
const char * name = luaL_checkstring(L, 1);
Player *player = getEnv(L)->getPlayer(name);
if(player == NULL)
{
RemotePlayer *player = dynamic_cast<ServerEnvironment *>(getEnv(L))->getPlayer(name);
if (player == NULL) {
lua_pushboolean(L, false); // no such player
return 1;
}
try
{
Address addr = getServer(L)->getPeerAddress(getEnv(L)->getPlayer(name)->peer_id);
Address addr = getServer(L)->getPeerAddress(
dynamic_cast<ServerEnvironment *>(getEnv(L))->getPlayer(name)->peer_id);
std::string ip_str = addr.serializeString();
getServer(L)->setIpBanned(ip_str, name);
}
@ -314,9 +313,9 @@ int ModApiServer::l_kick_player(lua_State *L)
{
message = "Kicked.";
}
Player *player = getEnv(L)->getPlayer(name);
if (player == NULL)
{
RemotePlayer *player = dynamic_cast<ServerEnvironment *>(getEnv(L))->getPlayer(name);
if (player == NULL) {
lua_pushboolean(L, false); // No such player
return 1;
}

View File

@ -220,7 +220,7 @@ int ModApiUtil::l_write_json(lua_State *L)
int ModApiUtil::l_get_dig_params(lua_State *L)
{
NO_MAP_LOCK_REQUIRED;
std::map<std::string, int> groups;
ItemGroupList groups;
read_groups(L, 1, groups);
ToolCapabilities tp = read_tool_capabilities(L, 2);
if(lua_isnoneornil(L, 3))
@ -235,7 +235,7 @@ int ModApiUtil::l_get_dig_params(lua_State *L)
int ModApiUtil::l_get_hit_params(lua_State *L)
{
NO_MAP_LOCK_REQUIRED;
std::map<std::string, int> groups;
UNORDERED_MAP<std::string, int> groups;
read_groups(L, 1, groups);
ToolCapabilities tp = read_tool_capabilities(L, 2);
if(lua_isnoneornil(L, 3))

View File

@ -184,9 +184,7 @@ Server::Server(
{
m_liquid_transform_timer = 0.0;
m_liquid_transform_every = 1.0;
m_print_info_timer = 0.0;
m_masterserver_timer = 0.0;
m_objectdata_timer = 0.0;
m_emergethread_trigger_timer = 0.0;
m_savemap_timer = 0.0;
@ -358,6 +356,7 @@ Server::Server(
add_legacy_abms(m_env, m_nodedef);
m_liquid_transform_every = g_settings->getFloat("liquid_update");
m_max_chatmessage_length = g_settings->getU16("chat_message_max_size");
}
Server::~Server()
@ -670,7 +669,7 @@ void Server::AsyncRunStep(bool initial_step)
MutexAutoLock envlock(m_env_mutex);
m_clients.lock();
std::map<u16, RemoteClient*> clients = m_clients.getClientList();
UNORDERED_MAP<u16, RemoteClient*> clients = m_clients.getClientList();
ScopeProfiler sp(g_profiler, "Server: checking added and deleted objs");
// Radius inside which objects are active
@ -686,8 +685,7 @@ void Server::AsyncRunStep(bool initial_step)
if (player_radius == 0 && is_transfer_limited)
player_radius = radius;
for (std::map<u16, RemoteClient*>::iterator
i = clients.begin();
for (UNORDERED_MAP<u16, RemoteClient*>::iterator i = clients.begin();
i != clients.end(); ++i) {
RemoteClient *client = i->second;
@ -696,8 +694,8 @@ void Server::AsyncRunStep(bool initial_step)
if (client->getState() < CS_DefinitionsSent)
continue;
Player *player = m_env->getPlayer(client->peer_id);
if(player == NULL) {
RemotePlayer *player = m_env->getPlayer(client->peer_id);
if (player == NULL) {
// This can happen if the client timeouts somehow
/*warningstream<<FUNCTION_NAME<<": Client "
<<client->peer_id
@ -796,7 +794,7 @@ void Server::AsyncRunStep(bool initial_step)
// Key = object id
// Value = data sent by object
std::map<u16, std::vector<ActiveObjectMessage>* > buffered_messages;
UNORDERED_MAP<u16, std::vector<ActiveObjectMessage>* > buffered_messages;
// Get active object messages from environment
for(;;) {
@ -805,7 +803,7 @@ void Server::AsyncRunStep(bool initial_step)
break;
std::vector<ActiveObjectMessage>* message_list = NULL;
std::map<u16, std::vector<ActiveObjectMessage>* >::iterator n;
UNORDERED_MAP<u16, std::vector<ActiveObjectMessage>* >::iterator n;
n = buffered_messages.find(aom.id);
if (n == buffered_messages.end()) {
message_list = new std::vector<ActiveObjectMessage>;
@ -818,16 +816,15 @@ void Server::AsyncRunStep(bool initial_step)
}
m_clients.lock();
std::map<u16, RemoteClient*> clients = m_clients.getClientList();
UNORDERED_MAP<u16, RemoteClient*> clients = m_clients.getClientList();
// Route data to every client
for (std::map<u16, RemoteClient*>::iterator
i = clients.begin();
for (UNORDERED_MAP<u16, RemoteClient*>::iterator i = clients.begin();
i != clients.end(); ++i) {
RemoteClient *client = i->second;
std::string reliable_data;
std::string unreliable_data;
// Go through all objects in message buffer
for (std::map<u16, std::vector<ActiveObjectMessage>* >::iterator
for (UNORDERED_MAP<u16, std::vector<ActiveObjectMessage>* >::iterator
j = buffered_messages.begin();
j != buffered_messages.end(); ++j) {
// If object is not known by client, skip it
@ -871,7 +868,7 @@ void Server::AsyncRunStep(bool initial_step)
m_clients.unlock();
// Clear buffered_messages
for(std::map<u16, std::vector<ActiveObjectMessage>* >::iterator
for (UNORDERED_MAP<u16, std::vector<ActiveObjectMessage>* >::iterator
i = buffered_messages.begin();
i != buffered_messages.end(); ++i) {
delete i->second;
@ -1113,7 +1110,7 @@ PlayerSAO* Server::StageTwoClientInit(u16 peer_id)
SendPlayerBreath(peer_id);
// Show death screen if necessary
if(player->isDead())
if (player->isDead())
SendDeathscreen(peer_id, false, v3f(0,0,0));
// Note things in chat if not in simple singleplayer mode
@ -1128,11 +1125,11 @@ PlayerSAO* Server::StageTwoClientInit(u16 peer_id)
Print out action
*/
{
std::vector<std::string> names = m_clients.getPlayerNames();
const std::vector<std::string> &names = m_clients.getPlayerNames();
actionstream<<player->getName() <<" joins game. List of players: ";
actionstream << player->getName() << " joins game. List of players: ";
for (std::vector<std::string>::iterator i = names.begin();
for (std::vector<std::string>::const_iterator i = names.begin();
i != names.end(); ++i) {
actionstream << *i << " ";
}
@ -1259,7 +1256,7 @@ Inventory* Server::getInventory(const InventoryLocation &loc)
break;
case InventoryLocation::PLAYER:
{
Player *player = m_env->getPlayer(loc.name.c_str());
RemotePlayer *player = dynamic_cast<RemotePlayer *>(m_env->getPlayer(loc.name.c_str()));
if(!player)
return NULL;
PlayerSAO *playersao = player->getPlayerSAO();
@ -1299,9 +1296,12 @@ void Server::setInventoryModified(const InventoryLocation &loc, bool playerSend)
if (!playerSend)
return;
Player *player = m_env->getPlayer(loc.name.c_str());
if(!player)
RemotePlayer *player =
dynamic_cast<RemotePlayer *>(m_env->getPlayer(loc.name.c_str()));
if (!player)
return;
PlayerSAO *playersao = player->getPlayerSAO();
if(!playersao)
return;
@ -1680,7 +1680,7 @@ void Server::SendSpawnParticle(u16 peer_id, v3f pos, v3f velocity, v3f accelerat
void Server::SendAddParticleSpawner(u16 peer_id, u16 amount, float spawntime, v3f minpos, v3f maxpos,
v3f minvel, v3f maxvel, v3f minacc, v3f maxacc, float minexptime, float maxexptime,
float minsize, float maxsize, bool collisiondetection, bool collision_removal,
s32 attached_id, bool vertical, const std::string &texture, u32 id)
u16 attached_id, bool vertical, const std::string &texture, u32 id)
{
DSTACK(FUNCTION_NAME);
@ -1860,7 +1860,7 @@ void Server::SendPlayerBreath(u16 peer_id)
void Server::SendMovePlayer(u16 peer_id)
{
DSTACK(FUNCTION_NAME);
Player *player = m_env->getPlayer(peer_id);
RemotePlayer *player = m_env->getPlayer(peer_id);
assert(player);
NetworkPacket pkt(TOCLIENT_MOVE_PLAYER, sizeof(v3f) + sizeof(f32) * 2, peer_id);
@ -1899,7 +1899,7 @@ void Server::SendEyeOffset(u16 peer_id, v3f first, v3f third)
}
void Server::SendPlayerPrivileges(u16 peer_id)
{
Player *player = m_env->getPlayer(peer_id);
RemotePlayer *player = m_env->getPlayer(peer_id);
assert(player);
if(player->peer_id == PEER_ID_INEXISTENT)
return;
@ -1920,7 +1920,7 @@ void Server::SendPlayerPrivileges(u16 peer_id)
void Server::SendPlayerInventoryFormspec(u16 peer_id)
{
Player *player = m_env->getPlayer(peer_id);
RemotePlayer *player = m_env->getPlayer(peer_id);
assert(player);
if(player->peer_id == PEER_ID_INEXISTENT)
return;
@ -1965,7 +1965,7 @@ s32 Server::playSound(const SimpleSoundSpec &spec,
std::vector<u16> dst_clients;
if(params.to_player != "")
{
Player *player = m_env->getPlayer(params.to_player.c_str());
RemotePlayer *player = m_env->getPlayer(params.to_player.c_str());
if(!player){
infostream<<"Server::playSound: Player \""<<params.to_player
<<"\" not found"<<std::endl;
@ -1981,13 +1981,12 @@ s32 Server::playSound(const SimpleSoundSpec &spec,
else {
std::vector<u16> clients = m_clients.getClientIDs();
for(std::vector<u16>::iterator
i = clients.begin(); i != clients.end(); ++i) {
Player *player = m_env->getPlayer(*i);
if(!player)
for (std::vector<u16>::iterator i = clients.begin(); i != clients.end(); ++i) {
RemotePlayer *player = m_env->getPlayer(*i);
if (!player)
continue;
if(pos_exists) {
if (pos_exists) {
if(player->getPosition().getDistanceFrom(pos) >
params.max_hear_distance)
continue;
@ -2020,16 +2019,15 @@ s32 Server::playSound(const SimpleSoundSpec &spec,
void Server::stopSound(s32 handle)
{
// Get sound reference
std::map<s32, ServerPlayingSound>::iterator i =
m_playing_sounds.find(handle);
if(i == m_playing_sounds.end())
UNORDERED_MAP<s32, ServerPlayingSound>::iterator i = m_playing_sounds.find(handle);
if (i == m_playing_sounds.end())
return;
ServerPlayingSound &psound = i->second;
NetworkPacket pkt(TOCLIENT_STOP_SOUND, 4);
pkt << handle;
for(std::set<u16>::iterator i = psound.clients.begin();
for (UNORDERED_SET<u16>::iterator i = psound.clients.begin();
i != psound.clients.end(); ++i) {
// Send as reliable
m_clients.send(*i, 0, &pkt, true);
@ -2073,7 +2071,7 @@ void Server::sendRemoveNode(v3s16 p, u16 ignore_id,
i != clients.end(); ++i) {
if (far_players) {
// Get player
if(Player *player = m_env->getPlayer(*i)) {
if (RemotePlayer *player = m_env->getPlayer(*i)) {
// If player is far away, only set modified blocks not sent
v3f player_pos = player->getPosition();
if(player_pos.getDistanceFrom(p_f) > maxd) {
@ -2101,7 +2099,7 @@ void Server::sendAddNode(v3s16 p, MapNode n, u16 ignore_id,
if(far_players) {
// Get player
if(Player *player = m_env->getPlayer(*i)) {
if (RemotePlayer *player = m_env->getPlayer(*i)) {
// If player is far away, only set modified blocks not sent
v3f player_pos = player->getPosition();
if(player_pos.getDistanceFrom(p_f) > maxd) {
@ -2347,7 +2345,7 @@ void Server::sendMediaAnnouncement(u16 peer_id)
NetworkPacket pkt(TOCLIENT_ANNOUNCE_MEDIA, 0, peer_id);
pkt << (u16) m_media.size();
for (std::map<std::string, MediaInfo>::iterator i = m_media.begin();
for (UNORDERED_MAP<std::string, MediaInfo>::iterator i = m_media.begin();
i != m_media.end(); ++i) {
pkt << i->first << i->second.sha1_digest;
}
@ -2392,7 +2390,7 @@ void Server::sendRequestedMedia(u16 peer_id,
i != tosend.end(); ++i) {
const std::string &name = *i;
if(m_media.find(name) == m_media.end()) {
if (m_media.find(name) == m_media.end()) {
errorstream<<"Server::sendRequestedMedia(): Client asked for "
<<"unknown file \""<<(name)<<"\""<<std::endl;
continue;
@ -2653,31 +2651,26 @@ void Server::DeleteClient(u16 peer_id, ClientDeletionReason reason)
/*
Clear references to playing sounds
*/
for(std::map<s32, ServerPlayingSound>::iterator
i = m_playing_sounds.begin();
i != m_playing_sounds.end();)
{
for (UNORDERED_MAP<s32, ServerPlayingSound>::iterator
i = m_playing_sounds.begin(); i != m_playing_sounds.end();) {
ServerPlayingSound &psound = i->second;
psound.clients.erase(peer_id);
if(psound.clients.empty())
if (psound.clients.empty())
m_playing_sounds.erase(i++);
else
++i;
}
Player *player = m_env->getPlayer(peer_id);
RemotePlayer *player = m_env->getPlayer(peer_id);
/* Run scripts and remove from environment */
{
if(player != NULL)
{
PlayerSAO *playersao = player->getPlayerSAO();
assert(playersao);
if(player != NULL) {
PlayerSAO *playersao = player->getPlayerSAO();
assert(playersao);
m_script->on_leaveplayer(playersao, reason == CDR_TIMEOUT);
m_script->on_leaveplayer(playersao, reason == CDR_TIMEOUT);
playersao->disconnected();
}
playersao->disconnected();
}
/*
@ -2691,8 +2684,8 @@ void Server::DeleteClient(u16 peer_id, ClientDeletionReason reason)
for(std::vector<u16>::iterator i = clients.begin();
i != clients.end(); ++i) {
// Get player
Player *player = m_env->getPlayer(*i);
if(!player)
RemotePlayer *player = m_env->getPlayer(*i);
if (!player)
continue;
// Get name of player
@ -2719,7 +2712,7 @@ void Server::DeleteClient(u16 peer_id, ClientDeletionReason reason)
SendChatMessage(PEER_ID_INEXISTENT,message);
}
void Server::UpdateCrafting(Player* player)
void Server::UpdateCrafting(RemotePlayer *player)
{
DSTACK(FUNCTION_NAME);
@ -2729,7 +2722,8 @@ void Server::UpdateCrafting(Player* player)
loc.setPlayer(player->getName());
std::vector<ItemStack> output_replacements;
getCraftingResult(&player->inventory, preview, output_replacements, false, this);
m_env->getScriptIface()->item_CraftPredict(preview, player->getPlayerSAO(), (&player->inventory)->getList("craft"), loc);
m_env->getScriptIface()->item_CraftPredict(preview, player->getPlayerSAO(),
(&player->inventory)->getList("craft"), loc);
// Put the new preview in
InventoryList *plist = player->inventory.getList("craftpreview");
@ -2758,8 +2752,7 @@ void Server::handleChatInterfaceEvent(ChatEvent *evt)
}
std::wstring Server::handleChat(const std::string &name, const std::wstring &wname,
const std::wstring &wmessage, bool check_shout_priv,
u16 peer_id_to_avoid_sending)
const std::wstring &wmessage, bool check_shout_priv, RemotePlayer *player)
{
// If something goes wrong, this player is to blame
RollbackScopeActor rollback_scope(m_rollback,
@ -2777,6 +2770,28 @@ std::wstring Server::handleChat(const std::string &name, const std::wstring &wna
if (ate)
return L"";
if (player) {
switch (player->canSendChatMessage()) {
case RPLAYER_CHATRESULT_FLOODING: {
std::wstringstream ws;
ws << L"You cannot send more messages. You are limited to "
<< g_settings->getFloat("chat_message_limit_per_10sec")
<< L" messages per 10 seconds.";
return ws.str();
}
case RPLAYER_CHATRESULT_KICK:
DenyAccess_Legacy(player->peer_id, L"You have been kicked due to message flooding.");
return L"";
case RPLAYER_CHATRESULT_OK: break;
default: FATAL_ERROR("Unhandled chat filtering result found.");
}
}
if (m_max_chatmessage_length > 0 && wmessage.length() > m_max_chatmessage_length) {
return L"Your message exceed the maximum chat message limit set on the server. "
L"It was refused. Send a shorter message";
}
// Commands are implemented in Lua, so only catch invalid
// commands that were not "eaten" and send an error back
if (wmessage[0] == L'/') {
@ -2811,6 +2826,7 @@ std::wstring Server::handleChat(const std::string &name, const std::wstring &wna
std::vector<u16> clients = m_clients.getClientIDs();
u16 peer_id_to_avoid_sending = (player ? player->peer_id : PEER_ID_INEXISTENT);
for (u16 i = 0; i < clients.size(); i++) {
u16 cid = clients[i];
if (cid != peer_id_to_avoid_sending)
@ -2849,16 +2865,16 @@ RemoteClient* Server::getClientNoEx(u16 peer_id, ClientState state_min)
std::string Server::getPlayerName(u16 peer_id)
{
Player *player = m_env->getPlayer(peer_id);
if(player == NULL)
RemotePlayer *player = m_env->getPlayer(peer_id);
if (player == NULL)
return "[id="+itos(peer_id)+"]";
return player->getName();
}
PlayerSAO* Server::getPlayerSAO(u16 peer_id)
{
Player *player = m_env->getPlayer(peer_id);
if(player == NULL)
RemotePlayer *player = m_env->getPlayer(peer_id);
if (player == NULL)
return NULL;
return player->getPlayerSAO();
}
@ -2877,13 +2893,12 @@ std::wstring Server::getStatusString()
bool first = true;
os<<L", clients={";
std::vector<u16> clients = m_clients.getClientIDs();
for(std::vector<u16>::iterator i = clients.begin();
i != clients.end(); ++i) {
for (std::vector<u16>::iterator i = clients.begin(); i != clients.end(); ++i) {
// Get player
Player *player = m_env->getPlayer(*i);
RemotePlayer *player = m_env->getPlayer(*i);
// Get name of player
std::wstring name = L"unknown";
if(player != NULL)
if (player != NULL)
name = narrow_to_wide(player->getName());
// Add name to information string
if(!first)
@ -2919,12 +2934,12 @@ void Server::reportPrivsModified(const std::string &name)
std::vector<u16> clients = m_clients.getClientIDs();
for(std::vector<u16>::iterator i = clients.begin();
i != clients.end(); ++i) {
Player *player = m_env->getPlayer(*i);
RemotePlayer *player = m_env->getPlayer(*i);
reportPrivsModified(player->getName());
}
} else {
Player *player = m_env->getPlayer(name.c_str());
if(!player)
RemotePlayer *player = m_env->getPlayer(name.c_str());
if (!player)
return;
SendPlayerPrivileges(player->peer_id);
PlayerSAO *sao = player->getPlayerSAO();
@ -2938,8 +2953,8 @@ void Server::reportPrivsModified(const std::string &name)
void Server::reportInventoryFormspecModified(const std::string &name)
{
Player *player = m_env->getPlayer(name.c_str());
if(!player)
RemotePlayer *player = m_env->getPlayer(name.c_str());
if (!player)
return;
SendPlayerInventoryFormspec(player->peer_id);
}
@ -2969,7 +2984,7 @@ void Server::notifyPlayer(const char *name, const std::wstring &msg)
m_admin_chat->outgoing_queue.push_back(new ChatEventChat("", msg));
}
Player *player = m_env->getPlayer(name);
RemotePlayer *player = m_env->getPlayer(name);
if (!player) {
return;
}
@ -2987,7 +3002,7 @@ bool Server::showFormspec(const char *playername, const std::string &formspec,
if (!m_env)
return false;
Player *player = m_env->getPlayer(playername);
RemotePlayer *player = m_env->getPlayer(playername);
if (!player)
return false;
@ -2995,7 +3010,7 @@ bool Server::showFormspec(const char *playername, const std::string &formspec,
return true;
}
u32 Server::hudAdd(Player *player, HudElement *form)
u32 Server::hudAdd(RemotePlayer *player, HudElement *form)
{
if (!player)
return -1;
@ -3007,7 +3022,7 @@ u32 Server::hudAdd(Player *player, HudElement *form)
return id;
}
bool Server::hudRemove(Player *player, u32 id) {
bool Server::hudRemove(RemotePlayer *player, u32 id) {
if (!player)
return false;
@ -3022,7 +3037,7 @@ bool Server::hudRemove(Player *player, u32 id) {
return true;
}
bool Server::hudChange(Player *player, u32 id, HudElementStat stat, void *data)
bool Server::hudChange(RemotePlayer *player, u32 id, HudElementStat stat, void *data)
{
if (!player)
return false;
@ -3031,7 +3046,7 @@ bool Server::hudChange(Player *player, u32 id, HudElementStat stat, void *data)
return true;
}
bool Server::hudSetFlags(Player *player, u32 flags, u32 mask)
bool Server::hudSetFlags(RemotePlayer *player, u32 flags, u32 mask)
{
if (!player)
return false;
@ -3049,10 +3064,11 @@ bool Server::hudSetFlags(Player *player, u32 flags, u32 mask)
return true;
}
bool Server::hudSetHotbarItemcount(Player *player, s32 hotbar_itemcount)
bool Server::hudSetHotbarItemcount(RemotePlayer *player, s32 hotbar_itemcount)
{
if (!player)
return false;
if (hotbar_itemcount <= 0 || hotbar_itemcount > HUD_HOTBAR_ITEMCOUNT_MAX)
return false;
@ -3063,14 +3079,7 @@ bool Server::hudSetHotbarItemcount(Player *player, s32 hotbar_itemcount)
return true;
}
s32 Server::hudGetHotbarItemcount(Player *player)
{
if (!player)
return 0;
return player->getHotbarItemcount();
}
void Server::hudSetHotbarImage(Player *player, std::string name)
void Server::hudSetHotbarImage(RemotePlayer *player, std::string name)
{
if (!player)
return;
@ -3079,14 +3088,14 @@ void Server::hudSetHotbarImage(Player *player, std::string name)
SendHUDSetParam(player->peer_id, HUD_PARAM_HOTBAR_IMAGE, name);
}
std::string Server::hudGetHotbarImage(Player *player)
std::string Server::hudGetHotbarImage(RemotePlayer *player)
{
if (!player)
return "";
return player->getHotbarImage();
}
void Server::hudSetHotbarSelectedImage(Player *player, std::string name)
void Server::hudSetHotbarSelectedImage(RemotePlayer *player, std::string name)
{
if (!player)
return;
@ -3095,16 +3104,8 @@ void Server::hudSetHotbarSelectedImage(Player *player, std::string name)
SendHUDSetParam(player->peer_id, HUD_PARAM_HOTBAR_SELECTED_IMAGE, name);
}
std::string Server::hudGetHotbarSelectedImage(Player *player)
{
if (!player)
return "";
return player->getHotbarSelectedImage();
}
bool Server::setLocalPlayerAnimations(Player *player,
v2s32 animation_frames[4], f32 frame_speed)
bool Server::setLocalPlayerAnimations(RemotePlayer *player,
v2s32 animation_frames[4], f32 frame_speed)
{
if (!player)
return false;
@ -3114,7 +3115,7 @@ bool Server::setLocalPlayerAnimations(Player *player,
return true;
}
bool Server::setPlayerEyeOffset(Player *player, v3f first, v3f third)
bool Server::setPlayerEyeOffset(RemotePlayer *player, v3f first, v3f third)
{
if (!player)
return false;
@ -3125,7 +3126,7 @@ bool Server::setPlayerEyeOffset(Player *player, v3f first, v3f third)
return true;
}
bool Server::setSky(Player *player, const video::SColor &bgcolor,
bool Server::setSky(RemotePlayer *player, const video::SColor &bgcolor,
const std::string &type, const std::vector<std::string> &params)
{
if (!player)
@ -3136,7 +3137,7 @@ bool Server::setSky(Player *player, const video::SColor &bgcolor,
return true;
}
bool Server::overrideDayNightRatio(Player *player, bool do_override,
bool Server::overrideDayNightRatio(RemotePlayer *player, bool do_override,
float ratio)
{
if (!player)
@ -3164,7 +3165,7 @@ void Server::spawnParticle(const std::string &playername, v3f pos,
u16 peer_id = PEER_ID_INEXISTENT;
if (playername != "") {
Player* player = m_env->getPlayer(playername.c_str());
RemotePlayer *player = m_env->getPlayer(playername.c_str());
if (!player)
return;
@ -3189,20 +3190,20 @@ u32 Server::addParticleSpawner(u16 amount, float spawntime,
u16 peer_id = PEER_ID_INEXISTENT;
if (playername != "") {
Player* player = m_env->getPlayer(playername.c_str());
RemotePlayer *player = m_env->getPlayer(playername.c_str());
if (!player)
return -1;
peer_id = player->peer_id;
}
s32 attached_id = attached == NULL ? -1 : attached->getId();
u16 attached_id = attached ? attached->getId() : 0;
u32 id;
if (attached_id == -1) {
if (attached_id == 0)
id = m_env->addParticleSpawner(spawntime);
} else {
else
id = m_env->addParticleSpawner(spawntime, attached_id);
}
SendAddParticleSpawner(peer_id, amount, spawntime,
minpos, maxpos, minvel, maxvel, minacc, maxacc,
minexptime, maxexptime, minsize, maxsize,
@ -3220,7 +3221,7 @@ void Server::deleteParticleSpawner(const std::string &playername, u32 id)
u16 peer_id = PEER_ID_INEXISTENT;
if (playername != "") {
Player* player = m_env->getPlayer(playername.c_str());
RemotePlayer *player = m_env->getPlayer(playername.c_str());
if (!player)
return;
peer_id = player->peer_id;
@ -3230,12 +3231,6 @@ void Server::deleteParticleSpawner(const std::string &playername, u32 id)
SendDeleteParticleSpawner(peer_id, id);
}
void Server::deleteParticleSpawnerAll(u32 id)
{
m_env->deleteParticleSpawner(id);
SendDeleteParticleSpawner(PEER_ID_INEXISTENT, id);
}
Inventory* Server::createDetachedInventory(const std::string &name)
{
if(m_detached_inventories.count(name) > 0){
@ -3438,11 +3433,10 @@ PlayerSAO* Server::emergePlayer(const char *name, u16 peer_id, u16 proto_version
/*
Try to get an existing player
*/
RemotePlayer *player = static_cast<RemotePlayer*>(m_env->getPlayer(name));
RemotePlayer *player = m_env->getPlayer(name);
// If player is already connected, cancel
if(player != NULL && player->peer_id != 0)
{
if (player != NULL && player->peer_id != 0) {
infostream<<"emergePlayer(): Player already connected"<<std::endl;
return NULL;
}
@ -3450,8 +3444,7 @@ PlayerSAO* Server::emergePlayer(const char *name, u16 peer_id, u16 proto_version
/*
If player with the wanted peer_id already exists, cancel.
*/
if(m_env->getPlayer(peer_id) != NULL)
{
if (m_env->getPlayer(peer_id) != NULL) {
infostream<<"emergePlayer(): Player with wrong name but same"
" peer_id already exists"<<std::endl;
return NULL;
@ -3459,13 +3452,13 @@ PlayerSAO* Server::emergePlayer(const char *name, u16 peer_id, u16 proto_version
// Load player if it isn't already loaded
if (!player) {
player = static_cast<RemotePlayer*>(m_env->loadPlayer(name));
player = m_env->loadPlayer(name);
}
// Create player if it doesn't exist
if (!player) {
newplayer = true;
player = new RemotePlayer(this, name);
player = new RemotePlayer(name, this->idef());
// Set player position
infostream<<"Server: Finding spawn place for player \""
<<name<<"\""<<std::endl;

View File

@ -34,6 +34,7 @@ with this program; if not, write to the Free Software Foundation, Inc.,
#include "environment.h"
#include "chat_interface.h"
#include "clientiface.h"
#include "remoteplayer.h"
#include "network/networkpacket.h"
#include <string>
#include <list>
@ -48,7 +49,6 @@ class IWritableCraftDefManager;
class BanManager;
class EventManager;
class Inventory;
class Player;
class PlayerSAO;
class IRollbackManager;
struct RollbackAction;
@ -64,31 +64,6 @@ enum ClientDeletionReason {
CDR_DENY
};
class MapEditEventIgnorer
{
public:
MapEditEventIgnorer(bool *flag):
m_flag(flag)
{
if(*m_flag == false)
*m_flag = true;
else
m_flag = NULL;
}
~MapEditEventIgnorer()
{
if(m_flag)
{
assert(*m_flag);
*m_flag = false;
}
}
private:
bool *m_flag;
};
class MapEditEventAreaIgnorer
{
public:
@ -159,7 +134,7 @@ struct ServerSoundParams
struct ServerPlayingSound
{
ServerSoundParams params;
std::set<u16> clients; // peer ids
UNORDERED_SET<u16> clients; // peer ids
};
class Server : public con::PeerHandler, public MapEventReceiver,
@ -245,11 +220,9 @@ public:
std::wstring getStatusString();
// read shutdown state
inline bool getShutdownRequested()
{ return m_shutdown_requested; }
inline bool getShutdownRequested() const { return m_shutdown_requested; }
// request server to shutdown
inline void requestShutdown() { m_shutdown_requested = true; }
void requestShutdown(const std::string &msg, bool reconnect)
{
m_shutdown_requested = true;
@ -293,7 +266,6 @@ public:
const std::string &playername);
void deleteParticleSpawner(const std::string &playername, u32 id);
void deleteParticleSpawnerAll(u32 id);
// Creates or resets inventory
Inventory* createDetachedInventory(const std::string &name);
@ -327,8 +299,7 @@ public:
const ModSpec* getModSpec(const std::string &modname) const;
void getModNames(std::vector<std::string> &modlist);
std::string getBuiltinLuaPath();
inline std::string getWorldPath() const
{ return m_path_world; }
inline std::string getWorldPath() const { return m_path_world; }
inline bool isSingleplayer()
{ return m_simple_singleplayer_mode; }
@ -340,28 +311,32 @@ public:
Map & getMap() { return m_env->getMap(); }
ServerEnvironment & getEnv() { return *m_env; }
u32 hudAdd(Player *player, HudElement *element);
bool hudRemove(Player *player, u32 id);
bool hudChange(Player *player, u32 id, HudElementStat stat, void *value);
bool hudSetFlags(Player *player, u32 flags, u32 mask);
bool hudSetHotbarItemcount(Player *player, s32 hotbar_itemcount);
s32 hudGetHotbarItemcount(Player *player);
void hudSetHotbarImage(Player *player, std::string name);
std::string hudGetHotbarImage(Player *player);
void hudSetHotbarSelectedImage(Player *player, std::string name);
std::string hudGetHotbarSelectedImage(Player *player);
u32 hudAdd(RemotePlayer *player, HudElement *element);
bool hudRemove(RemotePlayer *player, u32 id);
bool hudChange(RemotePlayer *player, u32 id, HudElementStat stat, void *value);
bool hudSetFlags(RemotePlayer *player, u32 flags, u32 mask);
bool hudSetHotbarItemcount(RemotePlayer *player, s32 hotbar_itemcount);
s32 hudGetHotbarItemcount(RemotePlayer *player) const
{ return player->getHotbarItemcount(); }
void hudSetHotbarImage(RemotePlayer *player, std::string name);
std::string hudGetHotbarImage(RemotePlayer *player);
void hudSetHotbarSelectedImage(RemotePlayer *player, std::string name);
const std::string &hudGetHotbarSelectedImage(RemotePlayer *player) const
{
return player->getHotbarSelectedImage();
}
inline Address getPeerAddress(u16 peer_id)
{ return m_con.GetPeerAddress(peer_id); }
bool setLocalPlayerAnimations(Player *player, v2s32 animation_frames[4], f32 frame_speed);
bool setPlayerEyeOffset(Player *player, v3f first, v3f third);
bool setLocalPlayerAnimations(RemotePlayer *player, v2s32 animation_frames[4],
f32 frame_speed);
bool setPlayerEyeOffset(RemotePlayer *player, v3f first, v3f third);
bool setSky(Player *player, const video::SColor &bgcolor,
bool setSky(RemotePlayer *player, const video::SColor &bgcolor,
const std::string &type, const std::vector<std::string> &params);
bool overrideDayNightRatio(Player *player, bool do_override,
float brightness);
bool overrideDayNightRatio(RemotePlayer *player, bool do_override, float brightness);
/* con::PeerHandler implementation. */
void peerAdded(con::Peer *peer);
@ -463,7 +438,7 @@ private:
float minexptime, float maxexptime,
float minsize, float maxsize,
bool collisiondetection, bool collision_removal,
s32 attached_id,
u16 attached_id,
bool vertical, const std::string &texture, u32 id);
void SendDeleteParticleSpawner(u16 peer_id, u32 id);
@ -484,7 +459,7 @@ private:
void DiePlayer(u16 peer_id);
void RespawnPlayer(u16 peer_id);
void DeleteClient(u16 peer_id, ClientDeletionReason reason);
void UpdateCrafting(Player *player);
void UpdateCrafting(RemotePlayer *player);
void handleChatInterfaceEvent(ChatEvent *evt);
@ -492,7 +467,7 @@ private:
std::wstring handleChat(const std::string &name, const std::wstring &wname,
const std::wstring &wmessage,
bool check_shout_priv = false,
u16 peer_id_to_avoid_sending = PEER_ID_INEXISTENT);
RemotePlayer *player = NULL);
void handleAdminChat(const ChatEventChat *evt);
v3f findSpawnPos();
@ -527,6 +502,7 @@ private:
// If true, do not allow multiple players and hide some multiplayer
// functionality
bool m_simple_singleplayer_mode;
u16 m_max_chatmessage_length;
// Thread can set; step() will throw as ServerError
MutexedVariable<std::string> m_async_fatal_error;
@ -534,9 +510,7 @@ private:
// Some timers
float m_liquid_transform_timer;
float m_liquid_transform_every;
float m_print_info_timer;
float m_masterserver_timer;
float m_objectdata_timer;
float m_emergethread_trigger_timer;
float m_savemap_timer;
IntervalLimiter m_map_timer_and_unload_interval;
@ -658,12 +632,12 @@ private:
u16 m_ignore_map_edit_events_peer_id;
// media files known to server
std::map<std::string,MediaInfo> m_media;
UNORDERED_MAP<std::string, MediaInfo> m_media;
/*
Sounds
*/
std::map<s32, ServerPlayingSound> m_playing_sounds;
UNORDERED_MAP<s32, ServerPlayingSound> m_playing_sounds;
s32 m_next_sound_id;
/*

View File

@ -82,7 +82,7 @@ ItemStack ServerActiveObject::getWieldedItem() const
if(inv)
{
const InventoryList *list = inv->getList(getWieldList());
if(list && (getWieldIndex() < (s32)list->getSize()))
if(list && (getWieldIndex() < (s32)list->getSize()))
return list->getItem(getWieldIndex());
}
return ItemStack();
@ -98,13 +98,3 @@ bool ServerActiveObject::setWieldedItem(const ItemStack &item)
}
return false;
}
void ServerActiveObject::attachParticleSpawner(u32 id)
{
m_attached_particle_spawners.insert(id);
}
void ServerActiveObject::detachParticleSpawner(u32 id)
{
m_attached_particle_spawners.erase(id);
}

View File

@ -44,7 +44,6 @@ Some planning
class ServerEnvironment;
struct ItemStack;
class Player;
struct ToolCapabilities;
struct ObjectProperties;
@ -69,23 +68,23 @@ public:
// environment
virtual bool environmentDeletes() const
{ return true; }
// Create a certain type of ServerActiveObject
static ServerActiveObject* create(ActiveObjectType type,
ServerEnvironment *env, u16 id, v3f pos,
const std::string &data);
/*
Some simple getters/setters
*/
v3f getBasePosition(){ return m_base_position; }
void setBasePosition(v3f pos){ m_base_position = pos; }
ServerEnvironment* getEnv(){ return m_env; }
/*
Some more dynamic interface
*/
virtual void setPos(v3f pos)
{ setBasePosition(pos); }
// continuous: if true, object does not stop immediately at pos
@ -96,7 +95,7 @@ public:
virtual float getMinimumSavedMovement();
virtual std::string getDescription(){return "SAO";}
/*
Step object in time.
Messages added to messages are sent to client over network.
@ -108,13 +107,13 @@ public:
packet.
*/
virtual void step(float dtime, bool send_recommended){}
/*
The return value of this is passed to the client-side object
when it is created
*/
virtual std::string getClientInitializationData(u16 protocol_version){return "";}
/*
The return value of this is passed to the server-side object
when it is created (converted from static to active - actually
@ -131,7 +130,7 @@ public:
*/
virtual bool isStaticAllowed() const
{return true;}
// Returns tool wear
virtual int punch(v3f dir,
const ToolCapabilities *toolcap=NULL,
@ -167,8 +166,8 @@ public:
{}
virtual void removeAttachmentChild(int child_id)
{}
virtual std::set<int> getAttachmentChildIds()
{ return std::set<int>(); }
virtual UNORDERED_SET<int> getAttachmentChildIds()
{ return UNORDERED_SET<int>(); }
virtual ObjectProperties* accessObjectProperties()
{ return NULL; }
virtual void notifyObjectPropertiesModified()
@ -189,8 +188,14 @@ public:
{ return 0; }
virtual ItemStack getWieldedItem() const;
virtual bool setWieldedItem(const ItemStack &item);
void attachParticleSpawner(u32 id);
void detachParticleSpawner(u32 id);
inline void attachParticleSpawner(u32 id)
{
m_attached_particle_spawners.insert(id);
}
inline void detachParticleSpawner(u32 id)
{
m_attached_particle_spawners.erase(id);
}
/*
Number of players which know about this object. Object won't be
@ -209,7 +214,7 @@ public:
- This can be set to true by anything else too.
*/
bool m_removed;
/*
This is set to true when an object should be removed from the active
object list but couldn't be removed because the id has to be
@ -220,7 +225,7 @@ public:
list.
*/
bool m_pending_deactivation;
/*
Whether the object's static data has been stored to a block
*/
@ -230,12 +235,12 @@ public:
a copy of the static data resides.
*/
v3s16 m_static_block;
/*
Queue of messages to be sent to the client
*/
std::queue<ActiveObjectMessage> m_messages_out;
protected:
// Used for creating objects based on type
typedef ServerActiveObject* (*Factory)
@ -245,7 +250,11 @@ protected:
ServerEnvironment *m_env;
v3f m_base_position;
<<<<<<< HEAD
std::set<u32> m_attached_particle_spawners;
=======
UNORDERED_SET<u32> m_attached_particle_spawners;
>>>>>>> minetest/master
private:
// Used for creating objects based on type

View File

@ -196,9 +196,8 @@ void Settings::writeLines(std::ostream &os, u32 tab_depth) const
{
MutexAutoLock lock(m_mutex);
for (std::map<std::string, SettingsEntry>::const_iterator
it = m_settings.begin();
it != m_settings.end(); ++it)
for (SettingEntries::const_iterator it = m_settings.begin();
it != m_settings.end(); ++it)
printEntry(os, it->first, it->second, tab_depth);
}
@ -231,7 +230,7 @@ void Settings::printEntry(std::ostream &os, const std::string &name,
bool Settings::updateConfigObject(std::istream &is, std::ostream &os,
const std::string &end, u32 tab_depth)
{
std::map<std::string, SettingsEntry>::const_iterator it;
SettingEntries::const_iterator it;
std::set<std::string> present_entries;
std::string line, name, value;
bool was_modified = false;
@ -381,7 +380,7 @@ const SettingsEntry &Settings::getEntry(const std::string &name) const
{
MutexAutoLock lock(m_mutex);
std::map<std::string, SettingsEntry>::const_iterator n;
SettingEntries::const_iterator n;
if ((n = m_settings.find(name)) == m_settings.end()) {
if ((n = m_defaults.find(name)) == m_defaults.end())
throw SettingNotFoundException("Setting [" + name + "] not found.");
@ -572,9 +571,8 @@ bool Settings::exists(const std::string &name) const
std::vector<std::string> Settings::getNames() const
{
std::vector<std::string> names;
for (std::map<std::string, SettingsEntry>::const_iterator
i = m_settings.begin();
i != m_settings.end(); ++i) {
for (SettingEntries::const_iterator i = m_settings.begin();
i != m_settings.end(); ++i) {
names.push_back(i->first);
}
return names;
@ -880,7 +878,7 @@ bool Settings::remove(const std::string &name)
{
MutexAutoLock lock(m_mutex);
std::map<std::string, SettingsEntry>::iterator it = m_settings.find(name);
SettingEntries::iterator it = m_settings.find(name);
if (it != m_settings.end()) {
delete it->second.group;
m_settings.erase(it);
@ -912,7 +910,6 @@ void Settings::updateValue(const Settings &other, const std::string &name)
try {
std::string val = other.get(name);
m_settings[name] = val;
} catch (SettingNotFoundException &e) {
}
@ -968,8 +965,9 @@ void Settings::updateNoLock(const Settings &other)
void Settings::clearNoLock()
{
std::map<std::string, SettingsEntry>::const_iterator it;
for (it = m_settings.begin(); it != m_settings.end(); ++it)
for (SettingEntries::const_iterator it = m_settings.begin();
it != m_settings.end(); ++it)
delete it->second.group;
m_settings.clear();
@ -978,8 +976,8 @@ void Settings::clearNoLock()
void Settings::clearDefaultsNoLock()
{
std::map<std::string, SettingsEntry>::const_iterator it;
for (it = m_defaults.begin(); it != m_defaults.end(); ++it)
for (SettingEntries::const_iterator it = m_defaults.begin();
it != m_defaults.end(); ++it)
delete it->second.group;
m_defaults.clear();
}

View File

@ -24,7 +24,7 @@ with this program; if not, write to the Free Software Foundation, Inc.,
#include "util/string.h"
#include "threading/mutex.h"
#include <string>
#include <map>
#include "util/cpp11_container.h"
#include <list>
#include <set>
@ -45,7 +45,7 @@ typedef std::vector<
>
> SettingsCallbackList;
typedef std::map<std::string, SettingsCallbackList> SettingsCallbackMap;
typedef UNORDERED_MAP<std::string, SettingsCallbackList> SettingsCallbackMap;
enum ValueType {
VALUETYPE_STRING,
@ -98,6 +98,8 @@ struct SettingsEntry {
bool is_group;
};
typedef UNORDERED_MAP<std::string, SettingsEntry> SettingEntries;
class Settings {
public:
Settings() {}
@ -231,8 +233,8 @@ private:
void doCallbacks(const std::string &name) const;
std::map<std::string, SettingsEntry> m_settings;
std::map<std::string, SettingsEntry> m_defaults;
SettingEntries m_settings;
SettingEntries m_defaults;
SettingsCallbackMap m_callbacks;

View File

@ -41,9 +41,9 @@ with this program; ifnot, write to the Free Software Foundation, Inc.,
#include "log.h"
#include "util/numeric.h" // myrand()
#include "porting.h"
#include <map>
#include <vector>
#include <fstream>
#include "util/cpp11_container.h"
#define BUFFER_SIZE 30000
@ -271,8 +271,8 @@ private:
ALCdevice *m_device;
ALCcontext *m_context;
int m_next_id;
std::map<std::string, std::vector<SoundBuffer*> > m_buffers;
std::map<int, PlayingSound*> m_sounds_playing;
UNORDERED_MAP<std::string, std::vector<SoundBuffer*> > m_buffers;
UNORDERED_MAP<int, PlayingSound*> m_sounds_playing;
v3f m_listener_pos;
struct fade_status {
fade_status() {}
@ -350,7 +350,7 @@ public:
alcCloseDevice(m_device);
m_device = NULL;
for (std::map<std::string, std::vector<SoundBuffer*> >::iterator i = m_buffers.begin();
for (UNORDERED_MAP<std::string, std::vector<SoundBuffer*> >::iterator i = m_buffers.begin();
i != m_buffers.end(); ++i) {
for (std::vector<SoundBuffer*>::iterator iter = (*i).second.begin();
iter != (*i).second.end(); ++iter) {
@ -368,7 +368,7 @@ public:
void addBuffer(const std::string &name, SoundBuffer *buf)
{
std::map<std::string, std::vector<SoundBuffer*> >::iterator i =
UNORDERED_MAP<std::string, std::vector<SoundBuffer*> >::iterator i =
m_buffers.find(name);
if(i != m_buffers.end()){
i->second.push_back(buf);
@ -382,7 +382,7 @@ public:
SoundBuffer* getBuffer(const std::string &name)
{
std::map<std::string, std::vector<SoundBuffer*> >::iterator i =
UNORDERED_MAP<std::string, std::vector<SoundBuffer*> >::iterator i =
m_buffers.find(name);
if(i == m_buffers.end())
return NULL;
@ -460,8 +460,7 @@ public:
void deleteSound(int id)
{
std::map<int, PlayingSound*>::iterator i =
m_sounds_playing.find(id);
UNORDERED_MAP<int, PlayingSound*>::iterator i = m_sounds_playing.find(id);
if(i == m_sounds_playing.end())
return;
PlayingSound *sound = i->second;
@ -501,10 +500,8 @@ public:
// <<m_sounds_playing.size()<<" playing sounds, "
// <<m_buffers.size()<<" sound names loaded"<<std::endl;
std::set<int> del_list;
for(std::map<int, PlayingSound*>::iterator
i = m_sounds_playing.begin();
i != m_sounds_playing.end(); ++i)
{
for(UNORDERED_MAP<int, PlayingSound*>::iterator i = m_sounds_playing.begin();
i != m_sounds_playing.end(); ++i) {
int id = i->first;
PlayingSound *sound = i->second;
// If not playing, remove it
@ -646,9 +643,8 @@ public:
}
void updateSoundPosition(int id, v3f pos)
{
std::map<int, PlayingSound*>::iterator i =
m_sounds_playing.find(id);
if(i == m_sounds_playing.end())
UNORDERED_MAP<int, PlayingSound*>::iterator i = m_sounds_playing.find(id);
if (i == m_sounds_playing.end())
return;
PlayingSound *sound = i->second;

View File

@ -27,8 +27,8 @@ DEALINGS IN THE SOFTWARE.
Event::Event()
{
#if __cplusplus < 201103L
# ifdef _WIN32
#ifndef USE_CPP11_MUTEX
# if USE_WIN_MUTEX
event = CreateEvent(NULL, false, false, NULL);
# else
pthread_cond_init(&cv, NULL);
@ -38,10 +38,10 @@ Event::Event()
#endif
}
#if __cplusplus < 201103L
#ifndef USE_CPP11_MUTEX
Event::~Event()
{
#ifdef _WIN32
#if USE_WIN_MUTEX
CloseHandle(event);
#else
pthread_cond_destroy(&cv);
@ -53,13 +53,13 @@ Event::~Event()
void Event::wait()
{
#if __cplusplus >= 201103L
#if USE_CPP11_MUTEX
MutexAutoLock lock(mutex);
while (!notified) {
cv.wait(lock);
}
notified = false;
#elif defined(_WIN32)
#elif USE_WIN_MUTEX
WaitForSingleObject(event, INFINITE);
#else
pthread_mutex_lock(&mutex);
@ -74,11 +74,11 @@ void Event::wait()
void Event::signal()
{
#if __cplusplus >= 201103L
#if USE_CPP11_MUTEX
MutexAutoLock lock(mutex);
notified = true;
cv.notify_one();
#elif defined(_WIN32)
#elif USE_WIN_MUTEX
SetEvent(event);
#else
pthread_mutex_lock(&mutex);

View File

@ -26,17 +26,12 @@ DEALINGS IN THE SOFTWARE.
#ifndef THREADING_EVENT_H
#define THREADING_EVENT_H
#if __cplusplus >= 201103L
#include "threads.h"
#if USE_CPP11_MUTEX
#include <condition_variable>
#include "threading/mutex.h"
#include "threading/mutex_auto_lock.h"
#elif defined(_WIN32)
#ifndef WIN32_LEAN_AND_MEAN
#define WIN32_LEAN_AND_MEAN
#endif
#include <windows.h>
#else
#include <pthread.h>
#endif
@ -49,18 +44,18 @@ DEALINGS IN THE SOFTWARE.
class Event {
public:
Event();
#if __cplusplus < 201103L
#ifndef USE_CPP11_MUTEX
~Event();
#endif
void wait();
void signal();
private:
#if __cplusplus >= 201103L
#if USE_CPP11_MUTEX
std::condition_variable cv;
Mutex mutex;
bool notified;
#elif defined(_WIN32)
#elif USE_WIN_MUTEX
HANDLE event;
#else
pthread_cond_t cv;

View File

@ -23,14 +23,13 @@ FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
DEALINGS IN THE SOFTWARE.
*/
// Windows std::mutex is much slower than the critical section API
#if __cplusplus < 201103L || defined(_WIN32)
#include "threads.h"
#ifndef USE_CPP11_MUTEX
#include "threading/mutex.h"
#ifndef _WIN32
#include <cassert>
#endif
#include <cassert>
#define UNUSED(expr) do { (void)(expr); } while (0)
@ -47,7 +46,7 @@ Mutex::Mutex(bool recursive)
void Mutex::init_mutex(bool recursive)
{
#ifdef _WIN32
#if USE_WIN_MUTEX
// Windows critical sections are recursive by default
UNUSED(recursive);
@ -69,7 +68,7 @@ void Mutex::init_mutex(bool recursive)
Mutex::~Mutex()
{
#ifdef _WIN32
#if USE_WIN_MUTEX
DeleteCriticalSection(&mutex);
#else
int ret = pthread_mutex_destroy(&mutex);
@ -80,7 +79,7 @@ Mutex::~Mutex()
void Mutex::lock()
{
#ifdef _WIN32
#if USE_WIN_MUTEX
EnterCriticalSection(&mutex);
#else
int ret = pthread_mutex_lock(&mutex);
@ -91,7 +90,7 @@ void Mutex::lock()
void Mutex::unlock()
{
#ifdef _WIN32
#if USE_WIN_MUTEX
LeaveCriticalSection(&mutex);
#else
int ret = pthread_mutex_unlock(&mutex);
@ -104,5 +103,5 @@ RecursiveMutex::RecursiveMutex()
: Mutex(true)
{}
#endif
#endif // C++11

View File

@ -26,14 +26,15 @@ DEALINGS IN THE SOFTWARE.
#ifndef THREADING_MUTEX_H
#define THREADING_MUTEX_H
// Windows std::mutex is much slower than the critical section API
#if __cplusplus >= 201103L && !defined(_WIN32)
#include "threads.h"
#if USE_CPP11_MUTEX
#include <mutex>
using Mutex = std::mutex;
using RecursiveMutex = std::recursive_mutex;
#else
#ifdef _WIN32
#if USE_WIN_MUTEX
#ifndef _WIN32_WINNT
#define _WIN32_WINNT 0x0501
#endif
@ -41,7 +42,7 @@ DEALINGS IN THE SOFTWARE.
#define WIN32_LEAN_AND_MEAN
#endif
#include <windows.h>
#else // pthread
#else
#include <pthread.h>
#endif
@ -59,9 +60,9 @@ protected:
Mutex(bool recursive);
void init_mutex(bool recursive);
private:
#ifdef _WIN32
#if USE_WIN_MUTEX
CRITICAL_SECTION mutex;
#else // pthread
#else
pthread_mutex_t mutex;
#endif
@ -76,6 +77,6 @@ public:
DISABLE_CLASS_COPY(RecursiveMutex);
};
#endif // C++11
#endif // C++11
#endif

View File

@ -26,7 +26,9 @@ DEALINGS IN THE SOFTWARE.
#ifndef THREADING_MUTEX_AUTO_LOCK_H
#define THREADING_MUTEX_AUTO_LOCK_H
#if __cplusplus >= 201103L
#include "threads.h"
#if USE_CPP11_MUTEX
#include <mutex>
using MutexAutoLock = std::unique_lock<std::mutex>;
using RecursiveMutexAutoLock = std::unique_lock<std::recursive_mutex>;

View File

@ -198,7 +198,7 @@ bool Thread::kill()
m_running = false;
#ifdef _WIN32
#if USE_WIN_THREADS
TerminateThread(m_thread_handle, 0);
CloseHandle(m_thread_handle);
#else
@ -310,10 +310,16 @@ void Thread::setName(const std::string &name)
unsigned int Thread::getNumberOfProcessors()
{
#if __cplusplus >= 201103L
#if USE_CPP11_THREADS
return std::thread::hardware_concurrency();
#elif USE_WIN_THREADS
SYSTEM_INFO sysinfo;
GetSystemInfo(&sysinfo);
return sysinfo.dwNumberOfProcessors;
#elif defined(_SC_NPROCESSORS_ONLN)
return sysconf(_SC_NPROCESSORS_ONLN);
@ -335,12 +341,6 @@ unsigned int Thread::getNumberOfProcessors()
return get_nprocs();
#elif defined(_WIN32)
SYSTEM_INFO sysinfo;
GetSystemInfo(&sysinfo);
return sysinfo.dwNumberOfProcessors;
#elif defined(PTW32_VERSION) || defined(__hpux)
return pthread_num_processors_np();
@ -359,7 +359,7 @@ bool Thread::bindToProcessor(unsigned int proc_number)
return false;
#elif defined(_WIN32)
#elif USE_WIN_THREADS
return SetThreadAffinityMask(getThreadHandle(), 1 << proc_number);
@ -407,7 +407,7 @@ bool Thread::bindToProcessor(unsigned int proc_number)
bool Thread::setPriority(int prio)
{
#if defined(_WIN32)
#if USE_WIN_THREADS
return SetThreadPriority(getThreadHandle(), prio);

View File

@ -32,9 +32,6 @@ DEALINGS IN THE SOFTWARE.
#include "threads.h"
#include <string>
#if USE_CPP11_THREADS
#include <thread> // for std::thread
#endif
#ifdef _AIX
#include <sys/thread.h> // for tid_t
#endif
@ -157,9 +154,11 @@ private:
Atomic<bool> m_running;
Mutex m_mutex;
#ifndef USE_CPP11_THREADS
#if USE_CPP11_THREADS
std::thread *m_thread_obj;
#else
threadhandle_t m_thread_handle;
# if _WIN32
# if USE_WIN_THREADS
threadid_t m_thread_id;
# endif
#endif
@ -172,6 +171,7 @@ private:
tid_t m_kernel_thread_id;
#endif
#if USE_CPP11_THREADS
std::thread *m_thread_obj;
#endif

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