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.hmaster
commit
4cb44572a5
36
.travis.yml
36
.travis.yml
|
@ -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
|
||||
|
|
63
README.txt
63
README.txt
|
@ -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
|
||||
|
||||
|
|
|
@ -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 \
|
||||
|
|
|
@ -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
|
||||
|
||||
|
|
|
@ -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",
|
||||
|
|
|
@ -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)
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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,
|
||||
|
|
|
@ -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
|
||||
|
||||
|
|
|
@ -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
|
||||
|
||||
|
|
|
@ -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))
|
||||
|
|
|
@ -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)
|
||||
|
|
|
@ -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
|
||||
}
|
||||
|
|
|
@ -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
|
||||
}
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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:
|
||||
|
|
|
@ -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.")
|
||||
|
|
|
@ -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) {
|
||||
|
|
|
@ -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 {
|
||||
|
|
20
src/client.h
20
src/client.h
|
@ -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;
|
||||
|
|
|
@ -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())
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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", "");
|
||||
|
||||
|
|
|
@ -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())
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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> ¤t_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> ¤t_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();
|
||||
|
|
|
@ -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> ¤t_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> ¤t_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;
|
||||
|
|
39
src/game.cpp
39
src/game.cpp
|
@ -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);
|
||||
}
|
||||
|
||||
|
|
|
@ -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();
|
||||
}
|
||||
|
|
|
@ -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
|
||||
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
||||
|
|
|
@ -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();
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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;
|
||||
|
|
561
src/keycode.cpp
561
src/keycode.cpp
|
@ -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;
|
||||
}
|
||||
|
|
|
@ -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)
|
||||
{
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
|
11
src/main.cpp
11
src/main.cpp
|
@ -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
|
||||
|
||||
|
|
476
src/map.cpp
476
src/map.cpp
|
@ -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);
|
||||
|
||||
|
||||
/* ----------------------------------------------------------------------
|
||||
|
|
17
src/map.h
17
src/map.h
|
@ -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);
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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;
|
||||
};
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
||||
|
|
|
@ -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,
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
*/
|
||||
|
|
|
@ -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)
|
||||
|
|
|
@ -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++;
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -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()
|
||||
|
|
|
@ -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];
|
||||
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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;
|
||||
};
|
||||
|
||||
/**
|
||||
|
|
170
src/player.cpp
170
src/player.cpp
|
@ -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);
|
||||
}
|
||||
|
||||
|
|
245
src/player.h
245
src/player.h
|
@ -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> ¶ms)
|
||||
{
|
||||
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
|
||||
|
||||
|
|
|
@ -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
|
||||
}
|
||||
|
||||
|
|
|
@ -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;
|
||||
}
|
|
@ -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> ¶ms)
|
||||
{
|
||||
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
|
|
@ -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());
|
||||
}
|
||||
|
|
|
@ -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,
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
|
|
@ -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,
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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
|
||||
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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);
|
||||
};
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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;
|
||||
|
||||
|
|
|
@ -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
|
||||
|
||||
|
|
|
@ -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", "");
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
|
|
@ -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))
|
||||
|
|
237
src/server.cpp
237
src/server.cpp
|
@ -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> ¶ms)
|
||||
{
|
||||
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;
|
||||
|
|
84
src/server.h
84
src/server.h
|
@ -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> ¶ms);
|
||||
|
||||
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;
|
||||
|
||||
/*
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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();
|
||||
}
|
||||
|
|
|
@ -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;
|
||||
|
||||
|
|
|
@ -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;
|
||||
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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
|
||||
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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>;
|
||||
|
|
|
@ -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);
|
||||
|
||||
|
|
|
@ -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
Loading…
Reference in New Issue