Merge branch 'master' into sphere

master
Jeija 2016-10-06 11:50:44 +02:00
commit 7b9cf89c1d
72 changed files with 1378 additions and 899 deletions

View File

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

View File

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

View File

@ -19,4 +19,9 @@ core.EMERGE_FROM_DISK = 3
core.EMERGE_GENERATED = 4 core.EMERGE_GENERATED = 4
-- constants.h -- constants.h
-- Size of mapblocks in nodes
core.MAP_BLOCKSIZE = 16 core.MAP_BLOCKSIZE = 16
-- light.h
-- Maximum value for node 'light_source' parameter
core.LIGHT_MAX = 14

View File

@ -130,7 +130,11 @@ function check_attached_node(p, n)
local def = core.registered_nodes[n.name] local def = core.registered_nodes[n.name]
local d = {x = 0, y = 0, z = 0} local d = {x = 0, y = 0, z = 0}
if def.paramtype2 == "wallmounted" then 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 else
d.y = -1 d.y = -1
end end

View File

@ -5,6 +5,7 @@ core.forceload_block = nil
core.forceload_free_block = nil core.forceload_free_block = nil
local blocks_forceloaded local blocks_forceloaded
local blocks_temploaded = {}
local total_forceloaded = 0 local total_forceloaded = 0
local BLOCKSIZE = core.MAP_BLOCKSIZE local BLOCKSIZE = core.MAP_BLOCKSIZE
@ -15,32 +16,52 @@ local function get_blockpos(pos)
z = math.floor(pos.z/BLOCKSIZE)} z = math.floor(pos.z/BLOCKSIZE)}
end 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 blockpos = get_blockpos(pos)
local hash = core.hash_node_position(blockpos) local hash = core.hash_node_position(blockpos)
if blocks_forceloaded[hash] ~= nil then local relevant_table, other_table = get_relevant_tables(transient)
blocks_forceloaded[hash] = blocks_forceloaded[hash] + 1 if relevant_table[hash] ~= nil then
relevant_table[hash] = relevant_table[hash] + 1
return true return true
elseif other_table[hash] ~= nil then
relevant_table[hash] = 1
else else
if total_forceloaded >= (tonumber(core.setting_get("max_forceloaded_blocks")) or 16) then if total_forceloaded >= (tonumber(core.setting_get("max_forceloaded_blocks")) or 16) then
return false return false
end end
total_forceloaded = total_forceloaded+1 total_forceloaded = total_forceloaded+1
blocks_forceloaded[hash] = 1 relevant_table[hash] = 1
forceload_block(blockpos) forceload_block(blockpos)
return true return true
end end
end end
function core.forceload_free_block(pos) function core.forceload_free_block(pos, transient)
local blockpos = get_blockpos(pos) local blockpos = get_blockpos(pos)
local hash = core.hash_node_position(blockpos) local hash = core.hash_node_position(blockpos)
if blocks_forceloaded[hash] == nil then return end local relevant_table, other_table = get_relevant_tables(transient)
if blocks_forceloaded[hash] > 1 then if relevant_table[hash] == nil then return end
blocks_forceloaded[hash] = blocks_forceloaded[hash] - 1 if relevant_table[hash] > 1 then
relevant_table[hash] = relevant_table[hash] - 1
elseif other_table[hash] ~= nil then
relevant_table[hash] = nil
else else
total_forceloaded = total_forceloaded-1 total_forceloaded = total_forceloaded-1
blocks_forceloaded[hash] = nil relevant_table[hash] = nil
forceload_free_block(blockpos) forceload_free_block(blockpos)
end end
end end

View File

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

View File

@ -127,6 +127,11 @@ function core.register_item(name, itemdef)
fixed = {-1/8, -1/2, -1/8, 1/8, 1/2, 1/8}, fixed = {-1/8, -1/2, -1/8, 1/8, 1/2, 1/8},
} }
end end
if itemdef.light_source and itemdef.light_source > core.LIGHT_MAX then
itemdef.light_source = core.LIGHT_MAX
core.log("warning", "Node 'light_source' value exceeds maximum," ..
" limiting to maximum: " ..name)
end
setmetatable(itemdef, {__index = core.nodedef_default}) setmetatable(itemdef, {__index = core.nodedef_default})
core.registered_nodes[itemdef.name] = itemdef core.registered_nodes[itemdef.name] = itemdef
elseif itemdef.type == "craft" then elseif itemdef.type == "craft" then

View File

@ -659,5 +659,12 @@ function create_adv_settings_dlg()
return dlg return dlg
end 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)) --assert(loadfile(core.get_mainmenu_path()..DIR_DELIM.."generate_from_settingtypes.lua"))(parse_config_file(true, false))

View File

@ -73,7 +73,7 @@ local function get_formspec(tabview, name, tabdata)
if not file_exists(infofile) then if not file_exists(infofile) then
infofile = current_texture_path .. DIR_DELIM .. "info.txt" infofile = current_texture_path .. DIR_DELIM .. "info.txt"
if file_exists(infofile) then if file_exists(infofile) then
core.log("info.txt is depreciated. description.txt should be used instead.") core.log("deprecated", "info.txt is deprecated. description.txt should be used instead.")
end end
end end

View File

@ -561,13 +561,13 @@ freetype (Freetype fonts) bool true
# Path to TrueTypeFont or bitmap. # Path to TrueTypeFont or bitmap.
font_path (Font path) path fonts/liberationsans.ttf font_path (Font path) path fonts/liberationsans.ttf
font_size (Font size) int 15 font_size (Font size) int 16
# Font shadow offset, if 0 then shadow will not be drawn. # Font shadow offset, if 0 then shadow will not be drawn.
font_shadow (Font shadow) int 1 font_shadow (Font shadow) int 1
# Font shadow alpha (opaqueness, between 0 and 255). # Font shadow alpha (opaqueness, between 0 and 255).
font_shadow_alpha (Font shadow alpha) int 128 0 255 font_shadow_alpha (Font shadow alpha) int 127 0 255
mono_font_path (Monospace font path) path fonts/liberationmono.ttf mono_font_path (Monospace font path) path fonts/liberationmono.ttf
@ -774,6 +774,15 @@ time_speed (Time speed) int 72
# Interval of saving important changes in the world, stated in seconds. # Interval of saving important changes in the world, stated in seconds.
server_map_save_interval (Map save interval) float 5.3 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] [**Physics]
movement_acceleration_default (Default acceleration) float 3 movement_acceleration_default (Default acceleration) float 3

View File

@ -263,7 +263,17 @@ Textures can be grouped together by enclosing them in `(` and `)`.
Example: `cobble.png^(thing1.png^thing2.png)` Example: `cobble.png^(thing1.png^thing2.png)`
A texture for `thing1.png^thing2.png` is created and the resulting A texture for `thing1.png^thing2.png` is created and the resulting
texture is overlaid over `cobble.png`. texture is overlaid on top of `cobble.png`.
### Escaping
Modifiers that accept texture names (e.g. `[combine`) accept escaping to allow
passing complex texture names as arguments. Escaping is done with backslash and
is required for `^` and `:`.
Example: `cobble.png^[lowpart:50:color.png\^[mask\:trans.png`
The lower 50 percent of `color.png^[mask:trans.png` are overlaid
on top of `cobble.png`.
### Advanced texture modifiers ### Advanced texture modifiers
@ -308,6 +318,15 @@ Example:
default_sandstone.png^[opacity:127 default_sandstone.png^[opacity:127
#### `[invert:<mode>`
Inverts the given channels of the base image.
Mode may contain the characters "r", "g", "b", "a".
Only the channels that are mentioned in the mode string will be inverted.
Example:
default_apple.png^[invert:rgb
#### `[brighten` #### `[brighten`
Brightens the texture. Brightens the texture.
@ -351,7 +370,7 @@ Example:
default_stone.png^[transformFXR90 default_stone.png^[transformFXR90
#### `[inventorycube{<top>{<left>{<right>` #### `[inventorycube{<top>{<left>{<right>`
`^` is replaced by `&` in texture names. Escaping does not apply here and `^` is replaced by `&` in texture names instead.
Create an inventory cube texture using the side textures. Create an inventory cube texture using the side textures.
@ -1450,6 +1469,15 @@ examples.
* `fixed_size`: `true`/`false` (optional) * `fixed_size`: `true`/`false` (optional)
* deprecated: `invsize[<W>,<H>;]` * 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>;]` #### `list[<inventory location>;<list name>;<X>,<Y>;<W>,<H>;]`
* Show an inventory list * Show an inventory list
@ -2594,13 +2622,17 @@ These functions return the leftover itemstack.
the creative mode setting, and checks for "sneak" to set the `invert_wall` the creative mode setting, and checks for "sneak" to set the `invert_wall`
parameter. parameter.
* `minetest.forceload_block(pos)` * `minetest.forceload_block(pos[, transient])`
* forceloads the position `pos`. * forceloads the position `pos`.
* returns `true` if area could be forceloaded * 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` * 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 * `minetest.request_insecure_environment()`: returns an environment containing
insecure functions if the calling mod has been listed as trusted in the insecure functions if the calling mod has been listed as trusted in the
@ -2886,6 +2918,7 @@ chosen for you.
#### Methods #### Methods
* `get_area(id, include_borders, include_data)`: returns the area with the id `id`. * `get_area(id, include_borders, include_data)`: returns the area with the id `id`.
(optional) Boolean values `include_borders` and `include_data` control what's copied. (optional) Boolean values `include_borders` and `include_data` control what's copied.
Returns nil if specified area id does not exist.
* `get_areas_for_pos(pos, include_borders, include_data)`: returns all areas that contain * `get_areas_for_pos(pos, include_borders, include_data)`: returns all areas that contain
the position `pos`. (optional) Boolean values `include_borders` and `include_data` control the position `pos`. (optional) Boolean values `include_borders` and `include_data` control
what's copied. what's copied.
@ -3328,13 +3361,15 @@ Registered entities
* It has the member `.object`, which is an `ObjectRef` pointing to the object * It has the member `.object`, which is an `ObjectRef` pointing to the object
* The original prototype stuff is visible directly via a metatable * The original prototype stuff is visible directly via a metatable
* Callbacks: * Callbacks:
* `on_activate(self, staticdata)` * `on_activate(self, staticdata, dtime_s)`
* Called when the object is instantiated. * Called when the object is instantiated.
* `dtime_s` is the time passed since the object was unloaded, which can
be used for updating the entity state.
* `on_step(self, dtime)` * `on_step(self, dtime)`
* Called on every server tick, after movement and collision processing. * Called on every server tick, after movement and collision processing.
`dtime` is usually 0.1 seconds, as per the `dedicated_server_step` setting `dtime` is usually 0.1 seconds, as per the `dedicated_server_step` setting
`in minetest.conf`. `in minetest.conf`.
* `on_punch(self, puncher, time_from_last_punch, tool_capabilities, dir` * `on_punch(self, puncher, time_from_last_punch, tool_capabilities, dir)`
* Called when somebody punches the object. * Called when somebody punches the object.
* Note that you probably want to handle most punches using the * Note that you probably want to handle most punches using the
automatic armor group system. automatic armor group system.
@ -3462,7 +3497,7 @@ Definition tables
on_activate = function(self, staticdata, dtime_s), on_activate = function(self, staticdata, dtime_s),
on_step = function(self, dtime), on_step = function(self, dtime),
on_punch = function(self, hitter), on_punch = function(self, puncher, time_from_last_punch, tool_capabilities, dir),
on_rightclick = function(self, clicker), on_rightclick = function(self, clicker),
get_staticdata = function(self), get_staticdata = function(self),
-- ^ Called sometimes; the string returned is passed to on_activate when -- ^ Called sometimes; the string returned is passed to on_activate when
@ -3642,7 +3677,10 @@ Definition tables
^ Don't forget to use "leveled" type nodebox. ]] ^ Don't forget to use "leveled" type nodebox. ]]
liquid_range = 8, -- number of flowing nodes around source (max. 8) liquid_range = 8, -- number of flowing nodes around source (max. 8)
drowning = 0, -- Player will take this amount of damage if no bubbles are left drowning = 0, -- Player will take this amount of damage if no bubbles are left
light_source = 0, -- Amount of light emitted by node light_source = 0, --[[
^ Amount of light emitted by node.
^ To set the maximum (currently 14), use the value 'minetest.LIGHT_MAX'.
^ A value outside the range 0 to minetest.LIGHT_MAX causes undefined behavior.]]
damage_per_second = 0, -- If player is inside node, this damage is caused damage_per_second = 0, -- If player is inside node, this damage is caused
node_box = {type="regular"}, -- See "Node boxes" node_box = {type="regular"}, -- See "Node boxes"
connects_to = nodenames, --[[ connects_to = nodenames, --[[
@ -3896,7 +3934,7 @@ The Biome API is still in an experimental phase and subject to change.
{ {
deco_type = "simple", -- See "Decoration types" deco_type = "simple", -- See "Decoration types"
place_on = "default:dirt_with_grass", place_on = "default:dirt_with_grass",
-- ^ Node that decoration can be placed on -- ^ Node (or list of nodes) that the decoration can be placed on
sidelen = 8, sidelen = 8,
-- ^ Size of divisions made in the chunk being generated. -- ^ Size of divisions made in the chunk being generated.
-- ^ If the chunk size is not evenly divisible by sidelen, sidelen is made equal to the chunk size. -- ^ If the chunk size is not evenly divisible by sidelen, sidelen is made equal to the chunk size.
@ -3915,6 +3953,13 @@ The Biome API is still in an experimental phase and subject to change.
-- ^ Minimum and maximum `y` positions these decorations can be generated at. -- ^ Minimum and maximum `y` positions these decorations can be generated at.
-- ^ This parameter refers to the `y` position of the decoration base, so -- ^ This parameter refers to the `y` position of the decoration base, so
-- the actual maximum height would be `height_max + size.Y`. -- the actual maximum height would be `height_max + size.Y`.
spawn_by = "default:water",
-- ^ Node (or list of nodes) that the decoration only spawns next to.
-- ^ Checks two horizontal planes of neighbouring nodes (including diagonal neighbours),
-- ^ one plane at Y = surface and one plane at Y = surface = + 1.
num_spawn_by = 1,
-- ^ Number of spawn_by nodes that must be surrounding the decoration position to occur.
-- ^ If absent or -1, decorations occur next to any nodes.
flags = "liquid_surface, force_placement", flags = "liquid_surface, force_placement",
-- ^ Flags for all decoration types. -- ^ Flags for all decoration types.
-- ^ "liquid_surface": Instead of placement on the highest solid surface -- ^ "liquid_surface": Instead of placement on the highest solid surface
@ -3932,13 +3977,6 @@ The Biome API is still in an experimental phase and subject to change.
height_max = 0, height_max = 0,
-- ^ Number of nodes the decoration can be at maximum. -- ^ Number of nodes the decoration can be at maximum.
-- ^ If absent, the parameter 'height' is used as a constant. -- ^ If absent, the parameter 'height' is used as a constant.
spawn_by = "default:water",
-- ^ Node that the decoration only spawns next to.
-- ^ The neighbours checked are the 8 nodes horizontally surrounding the lowest node of the
-- ^ decoration, and the 8 nodes horizontally surrounding the ground node below the decoration.
num_spawn_by = 1,
-- ^ Number of spawn_by nodes that must be surrounding the decoration position to occur.
-- ^ If absent or -1, decorations occur next to any nodes.
----- Schematic-type parameters ----- Schematic-type parameters
schematic = "foobar.mts", schematic = "foobar.mts",

View File

@ -655,7 +655,7 @@
# font_path = fonts/liberationsans.ttf # font_path = fonts/liberationsans.ttf
# type: int # type: int
# font_size = 15 # font_size = 16
# Font shadow offset, if 0 then shadow will not be drawn. # Font shadow offset, if 0 then shadow will not be drawn.
# type: int # type: int
@ -663,7 +663,7 @@
# Font shadow alpha (opaqueness, between 0 and 255). # Font shadow alpha (opaqueness, between 0 and 255).
# type: int min: 0 max: 255 # type: int min: 0 max: 255
# font_shadow_alpha = 128 # font_shadow_alpha = 127
# type: path # type: path
# mono_font_path = fonts/liberationmono.ttf # mono_font_path = fonts/liberationmono.ttf
@ -933,6 +933,18 @@
# type: float # type: float
# server_map_save_interval = 5.3 # 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 ### Physics
# type: float # type: float
@ -1099,6 +1111,25 @@
# type: int # type: int
# num_emerge_threads = 1 # 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. # Noise parameters for biome API temperature, humidity and biome blend.
# type: noise_params # type: noise_params
# mg_biome_np_heat = 50, 50, (750, 750, 750), 5349, 3, 0.5, 2.0 # mg_biome_np_heat = 50, 50, (750, 750, 750), 5349, 3, 0.5, 2.0
@ -1133,6 +1164,20 @@
# type: noise_params # type: noise_params
# mgv5_np_cave2 = 0, 12, (50, 50, 50), 10325, 4, 0.5, 2.0 # 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 #### Mapgen v6
# Map generation attributes specific to Mapgen v6. # Map generation attributes specific to Mapgen v6.
@ -1490,7 +1535,7 @@
# profiler.default_report_format = txt # profiler.default_report_format = txt
# The file path relative to your worldpath in which profiles will be saved to. # The file path relative to your worldpath in which profiles will be saved to.
# #
# type: string # type: string
# profiler.report_path = "" # profiler.report_path = ""

View File

@ -3,6 +3,7 @@ cmake_minimum_required(VERSION 2.6)
project(minetest) project(minetest)
INCLUDE(CheckIncludeFiles) INCLUDE(CheckIncludeFiles)
INCLUDE(CheckLibraryExists)
# Add custom SemiDebug build mode # Add custom SemiDebug build mode
set(CMAKE_CXX_FLAGS_SEMIDEBUG "-O1 -g -Wall -Wabi" CACHE STRING set(CMAKE_CXX_FLAGS_SEMIDEBUG "-O1 -g -Wall -Wabi" CACHE STRING
@ -292,9 +293,10 @@ if(WIN32)
set(ZLIB_INCLUDE_DIR "${PROJECT_SOURCE_DIR}/../../zlib/zlib-1.2.5" set(ZLIB_INCLUDE_DIR "${PROJECT_SOURCE_DIR}/../../zlib/zlib-1.2.5"
CACHE PATH "Zlib include directory") CACHE PATH "Zlib include directory")
set(ZLIB_LIBRARIES "${PROJECT_SOURCE_DIR}/../../zlib125dll/dll32/zlibwapi.lib" set(ZLIB_LIBRARIES "${PROJECT_SOURCE_DIR}/../../zlib125dll/dll32/zlibwapi.lib"
CACHE FILEPATH "Path to zlibwapi.lib") CACHE FILEPATH "Path to zlib library (usually zlibwapi.lib)")
set(ZLIB_DLL "${PROJECT_SOURCE_DIR}/../../zlib125dll/dll32/zlibwapi.dll" set(ZLIB_DLL "${PROJECT_SOURCE_DIR}/../../zlib125dll/dll32/zlibwapi.dll"
CACHE FILEPATH "Path to zlibwapi.dll (for installation)") CACHE FILEPATH "Path to zlib DLL (for installation)")
set(ZLIBWAPI_DLL "" CACHE FILEPATH "Path to zlibwapi DLL")
set(IRRLICHT_SOURCE_DIR "${PROJECT_SOURCE_DIR}/../../irrlicht-1.7.2" set(IRRLICHT_SOURCE_DIR "${PROJECT_SOURCE_DIR}/../../irrlicht-1.7.2"
CACHE PATH "irrlicht dir") CACHE PATH "irrlicht dir")
if(USE_FREETYPE) if(USE_FREETYPE)
@ -536,6 +538,7 @@ set(client_SRCS
sky.cpp sky.cpp
wieldmesh.cpp wieldmesh.cpp
${client_SCRIPT_SRCS} ${client_SCRIPT_SRCS}
${UNITTEST_CLIENT_SRCS}
) )
list(SORT client_SRCS) list(SORT client_SRCS)
@ -722,8 +725,14 @@ else()
set(OTHER_FLAGS "${OTHER_FLAGS} -Wsign-compare") set(OTHER_FLAGS "${OTHER_FLAGS} -Wsign-compare")
endif() endif()
if(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.")
endif()
if(MINGW) if(MINGW)
set(OTHER_FLAGS "-mthreads -fexceptions") set(OTHER_FLAGS "${OTHER_FLAGS} -mthreads -fexceptions")
endif() endif()
set(CMAKE_CXX_FLAGS_RELEASE "-DNDEBUG ${RELEASE_WARNING_FLAGS} ${WARNING_FLAGS} ${OTHER_FLAGS} -ffast-math -Wall -pipe -funroll-loops") set(CMAKE_CXX_FLAGS_RELEASE "-DNDEBUG ${RELEASE_WARNING_FLAGS} ${WARNING_FLAGS} ${OTHER_FLAGS} -ffast-math -Wall -pipe -funroll-loops")

View File

@ -303,7 +303,7 @@ Client::~Client()
delete m_inventory_from_server; delete m_inventory_from_server;
// Delete detached inventories // 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.begin();
i != m_detached_inventories.end(); ++i) { i != m_detached_inventories.end(); ++i) {
delete i->second; delete i->second;
@ -1437,7 +1437,7 @@ Inventory* Client::getInventory(const InventoryLocation &loc)
break; break;
case InventoryLocation::DETACHED: case InventoryLocation::DETACHED:
{ {
if(m_detached_inventories.count(loc.name) == 0) if (m_detached_inventories.count(loc.name) == 0)
return NULL; return NULL;
return m_detached_inventories[loc.name]; return m_detached_inventories[loc.name];
} }

View File

@ -462,7 +462,7 @@ public:
u16 getHP(); u16 getHP();
u16 getBreath(); u16 getBreath();
bool checkPrivilege(const std::string &priv) bool checkPrivilege(const std::string &priv) const
{ return (m_privileges.count(priv) != 0); } { return (m_privileges.count(priv) != 0); }
bool getChatMessage(std::wstring &message); bool getChatMessage(std::wstring &message);
@ -670,11 +670,11 @@ private:
std::map<int, u16> m_sounds_to_objects; std::map<int, u16> m_sounds_to_objects;
// Privileges // Privileges
std::set<std::string> m_privileges; UNORDERED_SET<std::string> m_privileges;
// Detached inventories // Detached inventories
// key = name // 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 // Storage for mesh data for creating multiple instances of the same mesh
StringMap m_mesh_data; StringMap m_mesh_data;

View File

@ -948,11 +948,10 @@ video::ITexture* TextureSource::generateTextureFromMesh(
video::IImage* TextureSource::generateImage(const std::string &name) video::IImage* TextureSource::generateImage(const std::string &name)
{ {
/* // Get the base image
Get the base image
*/
const char separator = '^'; const char separator = '^';
const char escape = '\\';
const char paren_open = '('; const char paren_open = '(';
const char paren_close = ')'; const char paren_close = ')';
@ -960,7 +959,9 @@ video::IImage* TextureSource::generateImage(const std::string &name)
s32 last_separator_pos = -1; s32 last_separator_pos = -1;
u8 paren_bal = 0; u8 paren_bal = 0;
for (s32 i = name.size() - 1; i >= 0; i--) { for (s32 i = name.size() - 1; i >= 0; i--) {
switch(name[i]) { if (i > 0 && name[i-1] == escape)
continue;
switch (name[i]) {
case separator: case separator:
if (paren_bal == 0) { if (paren_bal == 0) {
last_separator_pos = i; last_separator_pos = i;
@ -1028,10 +1029,12 @@ video::IImage* TextureSource::generateImage(const std::string &name)
return NULL; return NULL;
} }
core::dimension2d<u32> dim = tmp->getDimension(); core::dimension2d<u32> dim = tmp->getDimension();
if (!baseimg) if (baseimg) {
baseimg = driver->createImage(video::ECF_A8R8G8B8, dim); blit_with_alpha(tmp, baseimg, v2s32(0, 0), v2s32(0, 0), dim);
blit_with_alpha(tmp, baseimg, v2s32(0, 0), v2s32(0, 0), dim); tmp->drop();
tmp->drop(); } else {
baseimg = tmp;
}
} else if (!generateImagePart(last_part_of_name, baseimg)) { } else if (!generateImagePart(last_part_of_name, baseimg)) {
// Generate image according to part of name // Generate image according to part of name
errorstream << "generateImage(): " errorstream << "generateImage(): "
@ -1099,9 +1102,27 @@ video::IImage * Align2Npot2(video::IImage * image,
#endif #endif
static std::string unescape_string(const std::string &str, const char esc = '\\')
{
std::string out;
size_t pos = 0, cpos;
out.reserve(str.size());
while (1) {
cpos = str.find_first_of(esc, pos);
if (cpos == std::string::npos) {
out += str.substr(pos);
break;
}
out += str.substr(pos, cpos - pos) + str[cpos + 1];
pos = cpos + 2;
}
return out;
}
bool TextureSource::generateImagePart(std::string part_of_name, bool TextureSource::generateImagePart(std::string part_of_name,
video::IImage *& baseimg) video::IImage *& baseimg)
{ {
const char escape = '\\'; // same as in generateImage()
video::IVideoDriver* driver = m_device->getVideoDriver(); video::IVideoDriver* driver = m_device->getVideoDriver();
sanity_check(driver); sanity_check(driver);
@ -1251,7 +1272,7 @@ bool TextureSource::generateImagePart(std::string part_of_name,
} }
/* /*
[combine:WxH:X,Y=filename:X,Y=filename2 [combine:WxH:X,Y=filename:X,Y=filename2
Creates a bigger texture from an amount of smaller ones Creates a bigger texture from any amount of smaller ones
*/ */
else if (str_starts_with(part_of_name, "[combine")) else if (str_starts_with(part_of_name, "[combine"))
{ {
@ -1259,7 +1280,6 @@ bool TextureSource::generateImagePart(std::string part_of_name,
sf.next(":"); sf.next(":");
u32 w0 = stoi(sf.next("x")); u32 w0 = stoi(sf.next("x"));
u32 h0 = stoi(sf.next(":")); u32 h0 = stoi(sf.next(":"));
//infostream<<"combined w="<<w0<<" h="<<h0<<std::endl;
core::dimension2d<u32> dim(w0,h0); core::dimension2d<u32> dim(w0,h0);
if (baseimg == NULL) { if (baseimg == NULL) {
baseimg = driver->createImage(video::ECF_A8R8G8B8, dim); baseimg = driver->createImage(video::ECF_A8R8G8B8, dim);
@ -1268,11 +1288,11 @@ bool TextureSource::generateImagePart(std::string part_of_name,
while (sf.at_end() == false) { while (sf.at_end() == false) {
u32 x = stoi(sf.next(",")); u32 x = stoi(sf.next(","));
u32 y = stoi(sf.next("=")); u32 y = stoi(sf.next("="));
std::string filename = sf.next(":"); std::string filename = unescape_string(sf.next_esc(":", escape), escape);
infostream<<"Adding \""<<filename infostream<<"Adding \""<<filename
<<"\" to combined ("<<x<<","<<y<<")" <<"\" to combined ("<<x<<","<<y<<")"
<<std::endl; <<std::endl;
video::IImage *img = m_sourcecache.getOrLoad(filename, m_device); video::IImage *img = generateImage(filename);
if (img) { if (img) {
core::dimension2d<u32> dim = img->getDimension(); core::dimension2d<u32> dim = img->getDimension();
infostream<<"Size "<<dim.Width infostream<<"Size "<<dim.Width
@ -1295,7 +1315,7 @@ bool TextureSource::generateImagePart(std::string part_of_name,
} }
} }
/* /*
"[brighten" [brighten
*/ */
else if (str_starts_with(part_of_name, "[brighten")) else if (str_starts_with(part_of_name, "[brighten"))
{ {
@ -1309,7 +1329,7 @@ bool TextureSource::generateImagePart(std::string part_of_name,
brighten(baseimg); brighten(baseimg);
} }
/* /*
"[noalpha" [noalpha
Make image completely opaque. Make image completely opaque.
Used for the leaves texture when in old leaves mode, so Used for the leaves texture when in old leaves mode, so
that the transparent parts don't look completely black that the transparent parts don't look completely black
@ -1336,7 +1356,7 @@ bool TextureSource::generateImagePart(std::string part_of_name,
} }
} }
/* /*
"[makealpha:R,G,B" [makealpha:R,G,B
Convert one color to transparent. Convert one color to transparent.
*/ */
else if (str_starts_with(part_of_name, "[makealpha:")) else if (str_starts_with(part_of_name, "[makealpha:"))
@ -1375,7 +1395,7 @@ bool TextureSource::generateImagePart(std::string part_of_name,
} }
} }
/* /*
"[transformN" [transformN
Rotates and/or flips the image. Rotates and/or flips the image.
N can be a number (between 0 and 7) or a transform name. N can be a number (between 0 and 7) or a transform name.
@ -1543,12 +1563,11 @@ bool TextureSource::generateImagePart(std::string part_of_name,
Strfnd sf(part_of_name); Strfnd sf(part_of_name);
sf.next(":"); sf.next(":");
u32 percent = stoi(sf.next(":")); u32 percent = stoi(sf.next(":"));
std::string filename = sf.next(":"); std::string filename = unescape_string(sf.next_esc(":", escape), escape);
//infostream<<"power part "<<percent<<"%% of "<<filename<<std::endl;
if (baseimg == NULL) if (baseimg == NULL)
baseimg = driver->createImage(video::ECF_A8R8G8B8, v2u32(16,16)); baseimg = driver->createImage(video::ECF_A8R8G8B8, v2u32(16,16));
video::IImage *img = m_sourcecache.getOrLoad(filename, m_device); video::IImage *img = generateImage(filename);
if (img) if (img)
{ {
core::dimension2d<u32> dim = img->getDimension(); core::dimension2d<u32> dim = img->getDimension();
@ -1628,9 +1647,9 @@ bool TextureSource::generateImagePart(std::string part_of_name,
} }
Strfnd sf(part_of_name); Strfnd sf(part_of_name);
sf.next(":"); sf.next(":");
std::string filename = sf.next(":"); std::string filename = unescape_string(sf.next_esc(":", escape), escape);
video::IImage *img = m_sourcecache.getOrLoad(filename, m_device); video::IImage *img = generateImage(filename);
if (img) { if (img) {
apply_mask(img, baseimg, v2s32(0, 0), v2s32(0, 0), apply_mask(img, baseimg, v2s32(0, 0), v2s32(0, 0),
img->getDimension()); img->getDimension());
@ -1673,6 +1692,10 @@ bool TextureSource::generateImagePart(std::string part_of_name,
apply_colorize(baseimg, v2u32(0, 0), baseimg->getDimension(), color, ratio, keep_alpha); apply_colorize(baseimg, v2u32(0, 0), baseimg->getDimension(), color, ratio, keep_alpha);
} }
/*
[applyfiltersformesh
Internal modifier
*/
else if (str_starts_with(part_of_name, "[applyfiltersformesh")) else if (str_starts_with(part_of_name, "[applyfiltersformesh"))
{ {
// Apply the "clean transparent" filter, if configured. // Apply the "clean transparent" filter, if configured.
@ -1760,9 +1783,48 @@ bool TextureSource::generateImagePart(std::string part_of_name,
for (u32 y = 0; y < dim.Height; y++) for (u32 y = 0; y < dim.Height; y++)
for (u32 x = 0; x < dim.Width; x++) for (u32 x = 0; x < dim.Width; x++)
{ {
video::SColor c = baseimg->getPixel(x,y); video::SColor c = baseimg->getPixel(x, y);
c.setAlpha(floor((c.getAlpha() * ratio) / 255 + 0.5)); c.setAlpha(floor((c.getAlpha() * ratio) / 255 + 0.5));
baseimg->setPixel(x,y,c); baseimg->setPixel(x, y, c);
}
}
/*
[invert:mode
Inverts the given channels of the base image.
Mode may contain the characters "r", "g", "b", "a".
Only the channels that are mentioned in the mode string
will be inverted.
*/
else if (str_starts_with(part_of_name, "[invert:")) {
if (baseimg == NULL) {
errorstream << "generateImagePart(): baseimg == NULL "
<< "for part_of_name=\"" << part_of_name
<< "\", cancelling." << std::endl;
return false;
}
Strfnd sf(part_of_name);
sf.next(":");
std::string mode = sf.next("");
u32 mask = 0;
if (mode.find("a") != std::string::npos)
mask |= 0xff000000UL;
if (mode.find("r") != std::string::npos)
mask |= 0x00ff0000UL;
if (mode.find("g") != std::string::npos)
mask |= 0x0000ff00UL;
if (mode.find("b") != std::string::npos)
mask |= 0x000000ffUL;
core::dimension2d<u32> dim = baseimg->getDimension();
for (u32 y = 0; y < dim.Height; y++)
for (u32 x = 0; x < dim.Width; x++)
{
video::SColor c = baseimg->getPixel(x, y);
c.color ^= mask;
baseimg->setPixel(x, y, c);
} }
} }
else else

View File

@ -617,11 +617,8 @@ ClientInterface::~ClientInterface()
{ {
MutexAutoLock clientslock(m_clients_mutex); MutexAutoLock clientslock(m_clients_mutex);
for(std::map<u16, RemoteClient*>::iterator for (UNORDERED_MAP<u16, RemoteClient*>::iterator i = m_clients.begin();
i = m_clients.begin(); i != m_clients.end(); ++i) {
i != m_clients.end(); ++i)
{
// Delete client // Delete client
delete i->second; delete i->second;
} }
@ -633,10 +630,8 @@ std::vector<u16> ClientInterface::getClientIDs(ClientState min_state)
std::vector<u16> reply; std::vector<u16> reply;
MutexAutoLock clientslock(m_clients_mutex); MutexAutoLock clientslock(m_clients_mutex);
for(std::map<u16, RemoteClient*>::iterator for(UNORDERED_MAP<u16, RemoteClient*>::iterator i = m_clients.begin();
i = m_clients.begin(); i != m_clients.end(); ++i) {
i != m_clients.end(); ++i)
{
if (i->second->getState() >= min_state) if (i->second->getState() >= min_state)
reply.push_back(i->second->peer_id); reply.push_back(i->second->peer_id);
} }
@ -703,8 +698,7 @@ void ClientInterface::sendToAll(u16 channelnum,
NetworkPacket* pkt, bool reliable) NetworkPacket* pkt, bool reliable)
{ {
MutexAutoLock clientslock(m_clients_mutex); MutexAutoLock clientslock(m_clients_mutex);
for(std::map<u16, RemoteClient*>::iterator for(UNORDERED_MAP<u16, RemoteClient*>::iterator i = m_clients.begin();
i = m_clients.begin();
i != m_clients.end(); ++i) { i != m_clients.end(); ++i) {
RemoteClient *client = i->second; RemoteClient *client = i->second;
@ -717,11 +711,10 @@ void ClientInterface::sendToAll(u16 channelnum,
RemoteClient* ClientInterface::getClientNoEx(u16 peer_id, ClientState state_min) RemoteClient* ClientInterface::getClientNoEx(u16 peer_id, ClientState state_min)
{ {
MutexAutoLock clientslock(m_clients_mutex); MutexAutoLock clientslock(m_clients_mutex);
std::map<u16, RemoteClient*>::iterator n; UNORDERED_MAP<u16, RemoteClient*>::iterator n = m_clients.find(peer_id);
n = m_clients.find(peer_id);
// The client may not exist; clients are immediately removed if their // The client may not exist; clients are immediately removed if their
// access is denied, and this event occurs later then. // access is denied, and this event occurs later then.
if(n == m_clients.end()) if (n == m_clients.end())
return NULL; return NULL;
if (n->second->getState() >= state_min) if (n->second->getState() >= state_min)
@ -732,11 +725,10 @@ RemoteClient* ClientInterface::getClientNoEx(u16 peer_id, ClientState state_min)
RemoteClient* ClientInterface::lockedGetClientNoEx(u16 peer_id, ClientState state_min) RemoteClient* ClientInterface::lockedGetClientNoEx(u16 peer_id, ClientState state_min)
{ {
std::map<u16, RemoteClient*>::iterator n; UNORDERED_MAP<u16, RemoteClient*>::iterator n = m_clients.find(peer_id);
n = m_clients.find(peer_id);
// The client may not exist; clients are immediately removed if their // The client may not exist; clients are immediately removed if their
// access is denied, and this event occurs later then. // access is denied, and this event occurs later then.
if(n == m_clients.end()) if (n == m_clients.end())
return NULL; return NULL;
if (n->second->getState() >= state_min) if (n->second->getState() >= state_min)
@ -748,11 +740,10 @@ RemoteClient* ClientInterface::lockedGetClientNoEx(u16 peer_id, ClientState stat
ClientState ClientInterface::getClientState(u16 peer_id) ClientState ClientInterface::getClientState(u16 peer_id)
{ {
MutexAutoLock clientslock(m_clients_mutex); MutexAutoLock clientslock(m_clients_mutex);
std::map<u16, RemoteClient*>::iterator n; UNORDERED_MAP<u16, RemoteClient*>::iterator n = m_clients.find(peer_id);
n = m_clients.find(peer_id);
// The client may not exist; clients are immediately removed if their // The client may not exist; clients are immediately removed if their
// access is denied, and this event occurs later then. // access is denied, and this event occurs later then.
if(n == m_clients.end()) if (n == m_clients.end())
return CS_Invalid; return CS_Invalid;
return n->second->getState(); return n->second->getState();
@ -761,11 +752,10 @@ ClientState ClientInterface::getClientState(u16 peer_id)
void ClientInterface::setPlayerName(u16 peer_id,std::string name) void ClientInterface::setPlayerName(u16 peer_id,std::string name)
{ {
MutexAutoLock clientslock(m_clients_mutex); MutexAutoLock clientslock(m_clients_mutex);
std::map<u16, RemoteClient*>::iterator n; UNORDERED_MAP<u16, RemoteClient*>::iterator n = m_clients.find(peer_id);
n = m_clients.find(peer_id);
// The client may not exist; clients are immediately removed if their // The client may not exist; clients are immediately removed if their
// access is denied, and this event occurs later then. // access is denied, and this event occurs later then.
if(n != m_clients.end()) if (n != m_clients.end())
n->second->setName(name); n->second->setName(name);
} }
@ -774,11 +764,10 @@ void ClientInterface::DeleteClient(u16 peer_id)
MutexAutoLock conlock(m_clients_mutex); MutexAutoLock conlock(m_clients_mutex);
// Error check // Error check
std::map<u16, RemoteClient*>::iterator n; UNORDERED_MAP<u16, RemoteClient*>::iterator n = m_clients.find(peer_id);
n = m_clients.find(peer_id);
// The client may not exist; clients are immediately removed if their // The client may not exist; clients are immediately removed if their
// access is denied, and this event occurs later then. // access is denied, and this event occurs later then.
if(n == m_clients.end()) if (n == m_clients.end())
return; return;
/* /*
@ -809,10 +798,9 @@ void ClientInterface::CreateClient(u16 peer_id)
MutexAutoLock conlock(m_clients_mutex); MutexAutoLock conlock(m_clients_mutex);
// Error check // Error check
std::map<u16, RemoteClient*>::iterator n; UNORDERED_MAP<u16, RemoteClient*>::iterator n = m_clients.find(peer_id);
n = m_clients.find(peer_id);
// The client shouldn't already exist // The client shouldn't already exist
if(n != m_clients.end()) return; if (n != m_clients.end()) return;
// Create client // Create client
RemoteClient *client = new RemoteClient(); RemoteClient *client = new RemoteClient();
@ -826,8 +814,7 @@ void ClientInterface::event(u16 peer_id, ClientStateEvent event)
MutexAutoLock clientlock(m_clients_mutex); MutexAutoLock clientlock(m_clients_mutex);
// Error check // Error check
std::map<u16, RemoteClient*>::iterator n; UNORDERED_MAP<u16, RemoteClient*>::iterator n = m_clients.find(peer_id);
n = m_clients.find(peer_id);
// No client to deliver event // No client to deliver event
if (n == m_clients.end()) if (n == m_clients.end())
@ -848,8 +835,7 @@ u16 ClientInterface::getProtocolVersion(u16 peer_id)
MutexAutoLock conlock(m_clients_mutex); MutexAutoLock conlock(m_clients_mutex);
// Error check // Error check
std::map<u16, RemoteClient*>::iterator n; UNORDERED_MAP<u16, RemoteClient*>::iterator n = m_clients.find(peer_id);
n = m_clients.find(peer_id);
// No client to get version // No client to get version
if (n == m_clients.end()) if (n == m_clients.end())
@ -863,8 +849,7 @@ void ClientInterface::setClientVersion(u16 peer_id, u8 major, u8 minor, u8 patch
MutexAutoLock conlock(m_clients_mutex); MutexAutoLock conlock(m_clients_mutex);
// Error check // Error check
std::map<u16, RemoteClient*>::iterator n; UNORDERED_MAP<u16, RemoteClient*>::iterator n = m_clients.find(peer_id);
n = m_clients.find(peer_id);
// No client to set versions // No client to set versions
if (n == m_clients.end()) if (n == m_clients.end())

View File

@ -25,10 +25,10 @@ with this program; if not, write to the Free Software Foundation, Inc.,
#include "serialization.h" // for SER_FMT_VER_INVALID #include "serialization.h" // for SER_FMT_VER_INVALID
#include "threading/mutex.h" #include "threading/mutex.h"
#include "network/networkpacket.h" #include "network/networkpacket.h"
#include "util/cpp11_container.h"
#include <list> #include <list>
#include <vector> #include <vector>
#include <map>
#include <set> #include <set>
class MapBlock; class MapBlock;
@ -502,8 +502,7 @@ protected:
void lock() { m_clients_mutex.lock(); } void lock() { m_clients_mutex.lock(); }
void unlock() { m_clients_mutex.unlock(); } void unlock() { m_clients_mutex.unlock(); }
std::map<u16, RemoteClient*>& getClientList() UNORDERED_MAP<u16, RemoteClient*>& getClientList() { return m_clients; }
{ return m_clients; }
private: private:
/* update internal player list */ /* update internal player list */
@ -513,7 +512,7 @@ private:
con::Connection* m_con; con::Connection* m_con;
Mutex m_clients_mutex; Mutex m_clients_mutex;
// Connected clients (behind the con 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 std::vector<std::string> m_clients_names; //for announcing masterserver
// Environment // Environment

View File

@ -34,6 +34,27 @@ with this program; if not, write to the Free Software Foundation, Inc.,
//#define COLL_ZERO 0.032 // broken unit tests //#define COLL_ZERO 0.032 // broken unit tests
#define COLL_ZERO 0 #define COLL_ZERO 0
struct NearbyCollisionInfo {
NearbyCollisionInfo(bool is_ul, bool is_obj, int bouncy,
const v3s16 &pos, const aabb3f &box) :
is_unloaded(is_ul),
is_step_up(false),
is_object(is_obj),
bouncy(bouncy),
position(pos),
box(box)
{}
bool is_unloaded;
bool is_step_up;
bool is_object;
int bouncy;
v3s16 position;
aabb3f box;
};
// Helper function: // Helper function:
// Checks for collision of a moving aabbox with a static aabbox // Checks for collision of a moving aabbox with a static aabbox
// Returns -1 if no collision, 0 if X collision, 1 if Y collision, 2 if Z collision // Returns -1 if no collision, 0 if X collision, 1 if Y collision, 2 if Z collision
@ -160,7 +181,7 @@ int axisAlignedCollision(
// Helper function: // Helper function:
// Checks if moving the movingbox up by the given distance would hit a ceiling. // Checks if moving the movingbox up by the given distance would hit a ceiling.
bool wouldCollideWithCeiling( bool wouldCollideWithCeiling(
const std::vector<aabb3f> &staticboxes, const std::vector<NearbyCollisionInfo> &cinfo,
const aabb3f &movingbox, const aabb3f &movingbox,
f32 y_increase, f32 d) f32 y_increase, f32 d)
{ {
@ -168,12 +189,10 @@ bool wouldCollideWithCeiling(
assert(y_increase >= 0); // pre-condition assert(y_increase >= 0); // pre-condition
for(std::vector<aabb3f>::const_iterator for (std::vector<NearbyCollisionInfo>::const_iterator it = cinfo.begin();
i = staticboxes.begin(); it != cinfo.end(); ++it) {
i != staticboxes.end(); ++i) const aabb3f &staticbox = it->box;
{ if ((movingbox.MaxEdge.Y - d <= staticbox.MinEdge.Y) &&
const aabb3f& staticbox = *i;
if((movingbox.MaxEdge.Y - d <= staticbox.MinEdge.Y) &&
(movingbox.MaxEdge.Y + y_increase > staticbox.MinEdge.Y) && (movingbox.MaxEdge.Y + y_increase > staticbox.MinEdge.Y) &&
(movingbox.MinEdge.X < staticbox.MaxEdge.X) && (movingbox.MinEdge.X < staticbox.MaxEdge.X) &&
(movingbox.MaxEdge.X > staticbox.MinEdge.X) && (movingbox.MaxEdge.X > staticbox.MinEdge.X) &&
@ -234,12 +253,7 @@ collisionMoveResult collisionMoveSimple(Environment *env, IGameDef *gamedef,
/* /*
Collect node boxes in movement range Collect node boxes in movement range
*/ */
std::vector<aabb3f> cboxes; std::vector<NearbyCollisionInfo> cinfo;
std::vector<bool> is_unloaded;
std::vector<bool> is_step_up;
std::vector<bool> is_object;
std::vector<int> bouncy_values;
std::vector<v3s16> node_positions;
{ {
//TimeTaker tt2("collisionMoveSimple collect boxes"); //TimeTaker tt2("collisionMoveSimple collect boxes");
ScopeProfiler sp(g_profiler, "collisionMoveSimple collect boxes avg", SPT_AVG); ScopeProfiler sp(g_profiler, "collisionMoveSimple collect boxes avg", SPT_AVG);
@ -318,23 +332,13 @@ collisionMoveResult collisionMoveSimple(Environment *env, IGameDef *gamedef,
aabb3f box = *i; aabb3f box = *i;
box.MinEdge += v3f(x, y, z)*BS; box.MinEdge += v3f(x, y, z)*BS;
box.MaxEdge += v3f(x, y, z)*BS; box.MaxEdge += v3f(x, y, z)*BS;
cboxes.push_back(box); cinfo.push_back(NearbyCollisionInfo(false,
is_unloaded.push_back(false); false, n_bouncy_value, p, box));
is_step_up.push_back(false);
bouncy_values.push_back(n_bouncy_value);
node_positions.push_back(p);
is_object.push_back(false);
} }
} } else {
else {
// Collide with unloaded nodes // Collide with unloaded nodes
aabb3f box = getNodeBox(p, BS); aabb3f box = getNodeBox(p, BS);
cboxes.push_back(box); cinfo.push_back(NearbyCollisionInfo(true, false, 0, p, box));
is_unloaded.push_back(true);
is_step_up.push_back(false);
bouncy_values.push_back(0);
node_positions.push_back(p);
is_object.push_back(false);
} }
} }
@ -352,7 +356,7 @@ collisionMoveResult collisionMoveSimple(Environment *env, IGameDef *gamedef,
ScopeProfiler sp(g_profiler, "collisionMoveSimple objects avg", SPT_AVG); ScopeProfiler sp(g_profiler, "collisionMoveSimple objects avg", SPT_AVG);
//TimeTaker tt3("collisionMoveSimple collect object boxes"); //TimeTaker tt3("collisionMoveSimple collect object boxes");
/* add object boxes to cboxes */ /* add object boxes to cinfo */
std::vector<ActiveObject*> objects; std::vector<ActiveObject*> objects;
#ifndef SERVER #ifndef SERVER
@ -392,23 +396,12 @@ collisionMoveResult collisionMoveSimple(Environment *env, IGameDef *gamedef,
aabb3f object_collisionbox; aabb3f object_collisionbox;
if (object->getCollisionBox(&object_collisionbox) && if (object->getCollisionBox(&object_collisionbox) &&
object->collideWithObjects()) { object->collideWithObjects()) {
cboxes.push_back(object_collisionbox); cinfo.push_back(NearbyCollisionInfo(false, true, 0, v3s16(), object_collisionbox));
is_unloaded.push_back(false);
is_step_up.push_back(false);
bouncy_values.push_back(0);
node_positions.push_back(v3s16(0,0,0));
is_object.push_back(true);
} }
} }
} }
} //tt3 } //tt3
assert(cboxes.size() == is_unloaded.size()); // post-condition
assert(cboxes.size() == is_step_up.size()); // post-condition
assert(cboxes.size() == bouncy_values.size()); // post-condition
assert(cboxes.size() == node_positions.size()); // post-condition
assert(cboxes.size() == is_object.size()); // post-condition
/* /*
Collision detection Collision detection
*/ */
@ -448,15 +441,16 @@ collisionMoveResult collisionMoveSimple(Environment *env, IGameDef *gamedef,
/* /*
Go through every nodebox, find nearest collision Go through every nodebox, find nearest collision
*/ */
for (u32 boxindex = 0; boxindex < cboxes.size(); boxindex++) { for (u32 boxindex = 0; boxindex < cinfo.size(); boxindex++) {
NearbyCollisionInfo box_info = cinfo[boxindex];
// Ignore if already stepped up this nodebox. // Ignore if already stepped up this nodebox.
if(is_step_up[boxindex]) if (box_info.is_step_up)
continue; continue;
// Find nearest collision of the two boxes (raytracing-like) // Find nearest collision of the two boxes (raytracing-like)
f32 dtime_tmp; f32 dtime_tmp;
int collided = axisAlignedCollision( int collided = axisAlignedCollision(box_info.box,
cboxes[boxindex], movingbox, *speed_f, d, &dtime_tmp); movingbox, *speed_f, d, &dtime_tmp);
if (collided == -1 || dtime_tmp >= nearest_dtime) if (collided == -1 || dtime_tmp >= nearest_dtime)
continue; continue;
@ -472,19 +466,19 @@ collisionMoveResult collisionMoveSimple(Environment *env, IGameDef *gamedef,
dtime = 0; // Set to 0 to avoid "infinite" loop due to small FP numbers dtime = 0; // Set to 0 to avoid "infinite" loop due to small FP numbers
} else { } else {
// Otherwise, a collision occurred. // Otherwise, a collision occurred.
NearbyCollisionInfo &nearest_info = cinfo[nearest_boxindex];
const aabb3f& cbox = cboxes[nearest_boxindex]; const aabb3f& cbox = nearest_info.box;
// Check for stairs. // Check for stairs.
bool step_up = (nearest_collided != 1) && // must not be Y direction bool step_up = (nearest_collided != 1) && // must not be Y direction
(movingbox.MinEdge.Y < cbox.MaxEdge.Y) && (movingbox.MinEdge.Y < cbox.MaxEdge.Y) &&
(movingbox.MinEdge.Y + stepheight > cbox.MaxEdge.Y) && (movingbox.MinEdge.Y + stepheight > cbox.MaxEdge.Y) &&
(!wouldCollideWithCeiling(cboxes, movingbox, (!wouldCollideWithCeiling(cinfo, movingbox,
cbox.MaxEdge.Y - movingbox.MinEdge.Y, cbox.MaxEdge.Y - movingbox.MinEdge.Y,
d)); d));
// Get bounce multiplier // Get bounce multiplier
bool bouncy = (bouncy_values[nearest_boxindex] >= 1); bool bouncy = (nearest_info.bouncy >= 1);
float bounce = -(float)bouncy_values[nearest_boxindex] / 100.0; float bounce = -(float)nearest_info.bouncy / 100.0;
// Move to the point of collision and reduce dtime by nearest_dtime // Move to the point of collision and reduce dtime by nearest_dtime
if (nearest_dtime < 0) { if (nearest_dtime < 0) {
@ -503,39 +497,38 @@ collisionMoveResult collisionMoveSimple(Environment *env, IGameDef *gamedef,
} }
bool is_collision = true; bool is_collision = true;
if (is_unloaded[nearest_boxindex]) if (nearest_info.is_unloaded)
is_collision = false; is_collision = false;
CollisionInfo info; CollisionInfo info;
if (is_object[nearest_boxindex]) if (nearest_info.is_object)
info.type = COLLISION_OBJECT; info.type = COLLISION_OBJECT;
else else
info.type = COLLISION_NODE; info.type = COLLISION_NODE;
info.node_p = node_positions[nearest_boxindex]; info.node_p = nearest_info.position;
info.bouncy = bouncy; info.bouncy = bouncy;
info.old_speed = *speed_f; info.old_speed = *speed_f;
// Set the speed component that caused the collision to zero // Set the speed component that caused the collision to zero
if (step_up) { if (step_up) {
// Special case: Handle stairs // Special case: Handle stairs
is_step_up[nearest_boxindex] = true; nearest_info.is_step_up = true;
is_collision = false; is_collision = false;
} else if(nearest_collided == 0) { // X } else if (nearest_collided == 0) { // X
if (fabs(speed_f->X) > BS * 3) if (fabs(speed_f->X) > BS * 3)
speed_f->X *= bounce; speed_f->X *= bounce;
else else
speed_f->X = 0; speed_f->X = 0;
result.collides = true; result.collides = true;
result.collides_xz = true; result.collides_xz = true;
} } else if (nearest_collided == 1) { // Y
else if(nearest_collided == 1) { // Y if(fabs(speed_f->Y) > BS * 3)
if (fabs(speed_f->Y) > BS * 3)
speed_f->Y *= bounce; speed_f->Y *= bounce;
else else
speed_f->Y = 0; speed_f->Y = 0;
result.collides = true; result.collides = true;
} else if(nearest_collided == 2) { // Z } else if (nearest_collided == 2) { // Z
if (fabs(speed_f->Z) > BS * 3) if (fabs(speed_f->Z) > BS * 3)
speed_f->Z *= bounce; speed_f->Z *= bounce;
else else
@ -560,8 +553,9 @@ collisionMoveResult collisionMoveSimple(Environment *env, IGameDef *gamedef,
aabb3f box = box_0; aabb3f box = box_0;
box.MinEdge += *pos_f; box.MinEdge += *pos_f;
box.MaxEdge += *pos_f; box.MaxEdge += *pos_f;
for (u32 boxindex = 0; boxindex < cboxes.size(); boxindex++) { for (u32 boxindex = 0; boxindex < cinfo.size(); boxindex++) {
const aabb3f& cbox = cboxes[boxindex]; NearbyCollisionInfo &box_info = cinfo[boxindex];
const aabb3f &cbox = box_info.box;
/* /*
See if the object is touching ground. See if the object is touching ground.
@ -575,8 +569,8 @@ collisionMoveResult collisionMoveSimple(Environment *env, IGameDef *gamedef,
if (cbox.MaxEdge.X - d > box.MinEdge.X && cbox.MinEdge.X + d < box.MaxEdge.X && if (cbox.MaxEdge.X - d > box.MinEdge.X && cbox.MinEdge.X + d < box.MaxEdge.X &&
cbox.MaxEdge.Z - d > box.MinEdge.Z && cbox.MaxEdge.Z - d > box.MinEdge.Z &&
cbox.MinEdge.Z + d < box.MaxEdge.Z) { cbox.MinEdge.Z + d < box.MaxEdge.Z) {
if (is_step_up[boxindex]) { if (box_info.is_step_up) {
pos_f->Y += (cbox.MaxEdge.Y - box.MinEdge.Y); pos_f->Y += cbox.MaxEdge.Y - box.MinEdge.Y;
box = box_0; box = box_0;
box.MinEdge += *pos_f; box.MinEdge += *pos_f;
box.MaxEdge += *pos_f; box.MaxEdge += *pos_f;
@ -584,9 +578,9 @@ collisionMoveResult collisionMoveSimple(Environment *env, IGameDef *gamedef,
if (fabs(cbox.MaxEdge.Y - box.MinEdge.Y) < 0.15 * BS) { if (fabs(cbox.MaxEdge.Y - box.MinEdge.Y) < 0.15 * BS) {
result.touching_ground = true; result.touching_ground = true;
if (is_object[boxindex]) if (box_info.is_object)
result.standing_on_object = true; result.standing_on_object = true;
if (is_unloaded[boxindex]) if (box_info.is_unloaded)
result.standing_on_unloaded = true; result.standing_on_unloaded = true;
} }
} }

View File

@ -112,7 +112,7 @@ with this program; if not, write to the Free Software Foundation, Inc.,
#if defined(_WIN32) #if defined(_WIN32)
#define TTF_DEFAULT_FONT_SIZE (18) #define TTF_DEFAULT_FONT_SIZE (18)
#else #else
#define TTF_DEFAULT_FONT_SIZE (15) #define TTF_DEFAULT_FONT_SIZE (16)
#endif #endif
#define DEFAULT_FONT_SIZE (10) #define DEFAULT_FONT_SIZE (10)

View File

@ -566,7 +566,7 @@ GenericCAO::GenericCAO(IGameDef *gamedef, ClientEnvironment *env):
m_animation_speed(15), m_animation_speed(15),
m_animation_blend(0), m_animation_blend(0),
m_animation_loop(true), 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_bone(""),
m_attachment_position(v3f(0,0,0)), m_attachment_position(v3f(0,0,0)),
m_attachment_rotation(v3f(0,0,0)), m_attachment_rotation(v3f(0,0,0)),
@ -1573,10 +1573,8 @@ void GenericCAO::updateBonePosition()
return; return;
m_animated_meshnode->setJointMode(irr::scene::EJUOR_CONTROL); // To write positions to the mesh on render m_animated_meshnode->setJointMode(irr::scene::EJUOR_CONTROL); // To write positions to the mesh on render
for(std::map<std::string, for(UNORDERED_MAP<std::string, core::vector2d<v3f> >::const_iterator
core::vector2d<v3f> >::const_iterator ii = m_bone_position.begin(); ii = m_bone_position.begin(); ii != m_bone_position.end(); ++ii) {
ii != m_bone_position.end(); ++ii)
{
std::string bone_name = (*ii).first; std::string bone_name = (*ii).first;
v3f bone_pos = (*ii).second.X; v3f bone_pos = (*ii).second.X;
v3f bone_rot = (*ii).second.Y; v3f bone_rot = (*ii).second.Y;

View File

@ -90,7 +90,7 @@ private:
int m_animation_speed; int m_animation_speed;
int m_animation_blend; int m_animation_blend;
bool m_animation_loop; 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; std::string m_attachment_bone;
v3f m_attachment_position; v3f m_attachment_position;
v3f m_attachment_rotation; v3f m_attachment_rotation;

View File

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

View File

@ -213,7 +213,7 @@ void set_default_settings(Settings *settings)
settings->setDefault("freetype", "true"); settings->setDefault("freetype", "true");
settings->setDefault("font_path", porting::getDataPath("fonts" DIR_DELIM "liberationsans.ttf")); settings->setDefault("font_path", porting::getDataPath("fonts" DIR_DELIM "liberationsans.ttf"));
settings->setDefault("font_shadow", "1"); settings->setDefault("font_shadow", "1");
settings->setDefault("font_shadow_alpha", "128"); settings->setDefault("font_shadow_alpha", "127");
settings->setDefault("mono_font_path", porting::getDataPath("fonts" DIR_DELIM "liberationmono.ttf")); settings->setDefault("mono_font_path", porting::getDataPath("fonts" DIR_DELIM "liberationmono.ttf"));
settings->setDefault("fallback_font_path", porting::getDataPath("fonts" DIR_DELIM "DroidSansFallbackFull.ttf")); settings->setDefault("fallback_font_path", porting::getDataPath("fonts" DIR_DELIM "DroidSansFallbackFull.ttf"));
@ -285,6 +285,9 @@ void set_default_settings(Settings *settings)
settings->setDefault("server_unload_unused_data_timeout", "29"); settings->setDefault("server_unload_unused_data_timeout", "29");
settings->setDefault("max_objects_per_block", "49"); settings->setDefault("max_objects_per_block", "49");
settings->setDefault("server_map_save_interval", "5.3"); 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("sqlite_synchronous", "2");
settings->setDefault("full_block_send_enable_min_time_from_building", "2.0"); settings->setDefault("full_block_send_enable_min_time_from_building", "2.0");
settings->setDefault("dedicated_server_step", "0.1"); settings->setDefault("dedicated_server_step", "0.1");

View File

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

View File

@ -156,7 +156,7 @@ private:
Mutex m_queue_mutex; Mutex m_queue_mutex;
std::map<v3s16, BlockEmergeData> m_blocks_enqueued; 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_total;
u16 m_qlimit_diskonly; u16 m_qlimit_diskonly;

View File

@ -1146,14 +1146,12 @@ bool ServerEnvironment::swapNode(v3s16 p, const MapNode &n)
void ServerEnvironment::getObjectsInsideRadius(std::vector<u16> &objects, v3f pos, float radius) void ServerEnvironment::getObjectsInsideRadius(std::vector<u16> &objects, v3f pos, float radius)
{ {
for(std::map<u16, ServerActiveObject*>::iterator for (ActiveObjectMap::iterator i = m_active_objects.begin();
i = m_active_objects.begin(); i != m_active_objects.end(); ++i) {
i != m_active_objects.end(); ++i)
{
ServerActiveObject* obj = i->second; ServerActiveObject* obj = i->second;
u16 id = i->first; u16 id = i->first;
v3f objectpos = obj->getBasePosition(); v3f objectpos = obj->getBasePosition();
if(objectpos.getDistanceFrom(pos) > radius) if (objectpos.getDistanceFrom(pos) > radius)
continue; continue;
objects.push_back(id); objects.push_back(id);
} }
@ -1164,8 +1162,7 @@ void ServerEnvironment::clearObjects(ClearObjectsMode mode)
infostream << "ServerEnvironment::clearObjects(): " infostream << "ServerEnvironment::clearObjects(): "
<< "Removing all active objects" << std::endl; << "Removing all active objects" << std::endl;
std::vector<u16> objects_to_remove; std::vector<u16> objects_to_remove;
for (std::map<u16, ServerActiveObject*>::iterator for (ActiveObjectMap::iterator i = m_active_objects.begin();
i = m_active_objects.begin();
i != m_active_objects.end(); ++i) { i != m_active_objects.end(); ++i) {
ServerActiveObject* obj = i->second; ServerActiveObject* obj = i->second;
if (obj->getType() == ACTIVEOBJECT_TYPE_PLAYER) if (obj->getType() == ACTIVEOBJECT_TYPE_PLAYER)
@ -1540,10 +1537,8 @@ void ServerEnvironment::step(float dtime)
send_recommended = true; send_recommended = true;
} }
for(std::map<u16, ServerActiveObject*>::iterator for(ActiveObjectMap::iterator i = m_active_objects.begin();
i = m_active_objects.begin(); i != m_active_objects.end(); ++i) {
i != m_active_objects.end(); ++i)
{
ServerActiveObject* obj = i->second; ServerActiveObject* obj = i->second;
// Don't step if is to be removed or stored statically // Don't step if is to be removed or stored statically
if(obj->m_removed || obj->m_pending_deactivation) if(obj->m_removed || obj->m_pending_deactivation)
@ -1576,7 +1571,7 @@ void ServerEnvironment::step(float dtime)
Manage particle spawner expiration Manage particle spawner expiration
*/ */
if (m_particle_management_interval.step(dtime, 1.0)) { 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(); ) { i != m_particle_spawners.end(); ) {
//non expiring spawners //non expiring spawners
if (i->second == PARTICLE_SPAWNER_NO_EXPIRY) { if (i->second == PARTICLE_SPAWNER_NO_EXPIRY) {
@ -1601,8 +1596,7 @@ u32 ServerEnvironment::addParticleSpawner(float exptime)
u32 id = 0; u32 id = 0;
for (;;) { // look for unused particlespawner id for (;;) { // look for unused particlespawner id
id++; id++;
std::map<u32, float>::iterator f; UNORDERED_MAP<u32, float>::iterator f = m_particle_spawners.find(id);
f = m_particle_spawners.find(id);
if (f == m_particle_spawners.end()) { if (f == m_particle_spawners.end()) {
m_particle_spawners[id] = time; m_particle_spawners[id] = time;
break; break;
@ -1611,31 +1605,21 @@ u32 ServerEnvironment::addParticleSpawner(float exptime)
return id; return id;
} }
void ServerEnvironment::deleteParticleSpawner(u32 id)
{
m_particle_spawners.erase(id);
}
ServerActiveObject* ServerEnvironment::getActiveObject(u16 id) ServerActiveObject* ServerEnvironment::getActiveObject(u16 id)
{ {
std::map<u16, ServerActiveObject*>::iterator n; ActiveObjectMap::iterator n = m_active_objects.find(id);
n = m_active_objects.find(id); return (n != m_active_objects.end() ? n->second : NULL);
if(n == m_active_objects.end())
return NULL;
return n->second;
} }
bool isFreeServerActiveObjectId(u16 id, bool isFreeServerActiveObjectId(u16 id, ActiveObjectMap &objects)
std::map<u16, ServerActiveObject*> &objects)
{ {
if(id == 0) if (id == 0)
return false; return false;
return objects.find(id) == objects.end(); return objects.find(id) == objects.end();
} }
u16 getFreeServerActiveObjectId( u16 getFreeServerActiveObjectId(ActiveObjectMap &objects)
std::map<u16, ServerActiveObject*> &objects)
{ {
//try to reuse id's as late as possible //try to reuse id's as late as possible
static u16 last_used_id = 0; static u16 last_used_id = 0;
@ -1684,8 +1668,7 @@ void ServerEnvironment::getAddedActiveObjects(Player *player, s16 radius,
- discard objects that are found in current_objects. - discard objects that are found in current_objects.
- add remaining objects to added_objects - add remaining objects to added_objects
*/ */
for(std::map<u16, ServerActiveObject*>::iterator for(ActiveObjectMap::iterator i = m_active_objects.begin();
i = m_active_objects.begin();
i != m_active_objects.end(); ++i) { i != m_active_objects.end(); ++i) {
u16 id = i->first; u16 id = i->first;
@ -1810,8 +1793,7 @@ void ServerEnvironment::setStaticForActiveObjectsInBlock(
so_it = block->m_static_objects.m_active.begin(); so_it = block->m_static_objects.m_active.begin();
so_it != block->m_static_objects.m_active.end(); ++so_it) { so_it != block->m_static_objects.m_active.end(); ++so_it) {
// Get the ServerActiveObject counterpart to this StaticObject // Get the ServerActiveObject counterpart to this StaticObject
std::map<u16, ServerActiveObject *>::iterator ao_it; ActiveObjectMap::iterator ao_it = m_active_objects.find(so_it->first);
ao_it = m_active_objects.find(so_it->first);
if (ao_it == m_active_objects.end()) { if (ao_it == m_active_objects.end()) {
// If this ever happens, there must be some kind of nasty bug. // If this ever happens, there must be some kind of nasty bug.
errorstream << "ServerEnvironment::setStaticForObjectsInBlock(): " errorstream << "ServerEnvironment::setStaticForObjectsInBlock(): "
@ -1860,8 +1842,8 @@ u16 ServerEnvironment::addActiveObjectRaw(ServerActiveObject *object,
verbosestream<<"ServerEnvironment::addActiveObjectRaw(): " verbosestream<<"ServerEnvironment::addActiveObjectRaw(): "
<<"supplied with id "<<object->getId()<<std::endl; <<"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(): " errorstream<<"ServerEnvironment::addActiveObjectRaw(): "
<<"id is not free ("<<object->getId()<<")"<<std::endl; <<"id is not free ("<<object->getId()<<")"<<std::endl;
if(object->environmentDeletes()) if(object->environmentDeletes())
@ -1929,8 +1911,7 @@ u16 ServerEnvironment::addActiveObjectRaw(ServerActiveObject *object,
void ServerEnvironment::removeRemovedObjects() void ServerEnvironment::removeRemovedObjects()
{ {
std::vector<u16> objects_to_remove; std::vector<u16> objects_to_remove;
for(std::map<u16, ServerActiveObject*>::iterator for(ActiveObjectMap::iterator i = m_active_objects.begin();
i = m_active_objects.begin();
i != m_active_objects.end(); ++i) { i != m_active_objects.end(); ++i) {
u16 id = i->first; u16 id = i->first;
ServerActiveObject* obj = i->second; ServerActiveObject* obj = i->second;
@ -1948,7 +1929,7 @@ void ServerEnvironment::removeRemovedObjects()
We will delete objects that are marked as removed or thatare We will delete objects that are marked as removed or thatare
waiting for deletion after deactivation waiting for deletion after deactivation
*/ */
if(obj->m_removed == false && obj->m_pending_deactivation == false) if (!obj->m_removed && !obj->m_pending_deactivation)
continue; continue;
/* /*
@ -2148,8 +2129,7 @@ void ServerEnvironment::activateObjects(MapBlock *block, u32 dtime_s)
void ServerEnvironment::deactivateFarObjects(bool force_delete) void ServerEnvironment::deactivateFarObjects(bool force_delete)
{ {
std::vector<u16> objects_to_remove; std::vector<u16> objects_to_remove;
for(std::map<u16, ServerActiveObject*>::iterator for(ActiveObjectMap::iterator i = m_active_objects.begin();
i = m_active_objects.begin();
i != m_active_objects.end(); ++i) { i != m_active_objects.end(); ++i) {
ServerActiveObject* obj = i->second; ServerActiveObject* obj = i->second;
assert(obj); assert(obj);

View File

@ -300,6 +300,8 @@ enum ClearObjectsMode {
This is not thread-safe. Server uses an environment mutex. This is not thread-safe. Server uses an environment mutex.
*/ */
typedef UNORDERED_MAP<u16, ServerActiveObject *> ActiveObjectMap;
class ServerEnvironment : public Environment class ServerEnvironment : public Environment
{ {
public: public:
@ -338,7 +340,7 @@ public:
void loadDefaultMeta(); void loadDefaultMeta();
u32 addParticleSpawner(float exptime); u32 addParticleSpawner(float exptime);
void deleteParticleSpawner(u32 id); void deleteParticleSpawner(u32 id) { m_particle_spawners.erase(id); }
/* /*
External ActiveObject interface External ActiveObject interface
@ -491,7 +493,7 @@ private:
// World path // World path
const std::string m_path_world; const std::string m_path_world;
// Active object list // Active object list
std::map<u16, ServerActiveObject*> m_active_objects; ActiveObjectMap m_active_objects;
// Outgoing network message buffer for active objects // Outgoing network message buffer for active objects
std::queue<ActiveObjectMessage> m_active_object_messages; std::queue<ActiveObjectMessage> m_active_object_messages;
// Some timers // Some timers
@ -522,7 +524,7 @@ private:
// Particles // Particles
IntervalLimiter m_particle_management_interval; IntervalLimiter m_particle_management_interval;
std::map<u32, float> m_particle_spawners; UNORDERED_MAP<u32, float> m_particle_spawners;
}; };
#ifndef SERVER #ifndef SERVER

View File

@ -605,7 +605,7 @@ public:
void draw(s32 x_left, s32 y_bottom, video::IVideoDriver *driver, void draw(s32 x_left, s32 y_bottom, video::IVideoDriver *driver,
gui::IGUIFont *font) const gui::IGUIFont *font) const
{ {
std::map<std::string, Meta> m_meta; UNORDERED_MAP<std::string, Meta> m_meta;
for (std::deque<Piece>::const_iterator k = m_log.begin(); for (std::deque<Piece>::const_iterator k = m_log.begin();
k != m_log.end(); ++k) { k != m_log.end(); ++k) {
@ -615,8 +615,7 @@ public:
i != piece.values.end(); ++i) { i != piece.values.end(); ++i) {
const std::string &id = i->first; const std::string &id = i->first;
const float &value = i->second; const float &value = i->second;
std::map<std::string, Meta>::iterator j = UNORDERED_MAP<std::string, Meta>::iterator j = m_meta.find(id);
m_meta.find(id);
if (j == m_meta.end()) { if (j == m_meta.end()) {
m_meta[id] = Meta(value); m_meta[id] = Meta(value);
@ -643,7 +642,7 @@ public:
sizeof(usable_colors) / sizeof(*usable_colors); sizeof(usable_colors) / sizeof(*usable_colors);
u32 next_color_i = 0; u32 next_color_i = 0;
for (std::map<std::string, Meta>::iterator i = m_meta.begin(); for (UNORDERED_MAP<std::string, Meta>::iterator i = m_meta.begin();
i != m_meta.end(); ++i) { i != m_meta.end(); ++i) {
Meta &meta = i->second; Meta &meta = i->second;
video::SColor color(255, 200, 200, 200); video::SColor color(255, 200, 200, 200);
@ -659,7 +658,7 @@ public:
s32 textx2 = textx + 200 - 15; s32 textx2 = textx + 200 - 15;
s32 meta_i = 0; s32 meta_i = 0;
for (std::map<std::string, Meta>::const_iterator i = m_meta.begin(); for (UNORDERED_MAP<std::string, Meta>::const_iterator i = m_meta.begin();
i != m_meta.end(); ++i) { i != m_meta.end(); ++i) {
const std::string &id = i->first; const std::string &id = i->first;
const Meta &meta = i->second; const Meta &meta = i->second;

View File

@ -279,6 +279,32 @@ void GUIFormSpecMenu::parseSize(parserData* data,std::string element)
errorstream<< "Invalid size element (" << parts.size() << "): '" << element << "'" << std::endl; 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) void GUIFormSpecMenu::parseList(parserData* data,std::string element)
{ {
if (m_gamedef == 0) { if (m_gamedef == 0) {
@ -309,7 +335,7 @@ void GUIFormSpecMenu::parseList(parserData* data,std::string element)
else else
loc.deSerialize(location); 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.X += stof(v_pos[0]) * (float)spacing.X;
pos.Y += stof(v_pos[1]) * (float)spacing.Y; 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); MY_CHECKPOS("checkbox",0);
v2s32 pos = padding; v2s32 pos = padding + pos_offset * spacing;
pos.X += stof(v_pos[0]) * (float) spacing.X; pos.X += stof(v_pos[0]) * (float) spacing.X;
pos.Y += stof(v_pos[1]) * (float) spacing.Y; 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); MY_CHECKPOS("scrollbar",0);
v2s32 pos = padding; v2s32 pos = padding + pos_offset * spacing;
pos.X += stof(v_pos[0]) * (float) spacing.X; pos.X += stof(v_pos[0]) * (float) spacing.X;
pos.Y += stof(v_pos[1]) * (float) spacing.Y; 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::vector<std::string> v_geom = split(parts[1],',');
std::string name = unescape_string(parts[2]); std::string name = unescape_string(parts[2]);
MY_CHECKPOS("image",0); MY_CHECKPOS("image", 0);
MY_CHECKGEOM("image",1); 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.X += stof(v_pos[0]) * (float) spacing.X;
pos.Y += stof(v_pos[1]) * (float) spacing.Y; 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.X = stof(v_geom[0]) * (float)imgsize.X;
geom.Y = stof(v_geom[1]) * (float)imgsize.Y; 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; warningstream<<"invalid use of image without a size[] element"<<std::endl;
m_images.push_back(ImageDrawSpec(name, pos, geom)); m_images.push_back(ImageDrawSpec(name, pos, geom));
return; return;
} } else if (parts.size() == 2) {
if (parts.size() == 2) {
std::vector<std::string> v_pos = split(parts[0],','); std::vector<std::string> v_pos = split(parts[0],',');
std::string name = unescape_string(parts[1]); 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.X += stof(v_pos[0]) * (float) spacing.X;
pos.Y += stof(v_pos[1]) * (float) spacing.Y; 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; warningstream<<"invalid use of image without a size[] element"<<std::endl;
m_images.push_back(ImageDrawSpec(name, pos)); m_images.push_back(ImageDrawSpec(name, pos));
return; return;
@ -544,7 +568,7 @@ void GUIFormSpecMenu::parseItemImage(parserData* data,std::string element)
MY_CHECKPOS("itemimage",0); MY_CHECKPOS("itemimage",0);
MY_CHECKGEOM("itemimage",1); 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.X += stof(v_pos[0]) * (float) spacing.X;
pos.Y += stof(v_pos[1]) * (float) spacing.Y; 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_CHECKPOS("button",0);
MY_CHECKGEOM("button",1); MY_CHECKGEOM("button",1);
v2s32 pos = padding; v2s32 pos = padding + pos_offset * spacing;
pos.X += stof(v_pos[0]) * (float)spacing.X; pos.X += stof(v_pos[0]) * (float)spacing.X;
pos.Y += stof(v_pos[1]) * (float)spacing.Y; 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_CHECKPOS("background",0);
MY_CHECKGEOM("background",1); MY_CHECKGEOM("background",1);
v2s32 pos = padding + AbsoluteRect.UpperLeftCorner; 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.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; pos.Y += stof(v_pos[1]) * (float)spacing.Y - ((float)spacing.Y - (float)imgsize.Y)/2;
v2s32 geom; v2s32 geom;
geom.X = stof(v_geom[0]) * (float)spacing.X; 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_CHECKPOS("table",0);
MY_CHECKGEOM("table",1); MY_CHECKGEOM("table",1);
v2s32 pos = padding; v2s32 pos = padding + pos_offset * spacing;
pos.X += stof(v_pos[0]) * (float)spacing.X; pos.X += stof(v_pos[0]) * (float)spacing.X;
pos.Y += stof(v_pos[1]) * (float)spacing.Y; 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_CHECKPOS("textlist",0);
MY_CHECKGEOM("textlist",1); MY_CHECKGEOM("textlist",1);
v2s32 pos = padding; v2s32 pos = padding + pos_offset * spacing;
pos.X += stof(v_pos[0]) * (float)spacing.X; pos.X += stof(v_pos[0]) * (float)spacing.X;
pos.Y += stof(v_pos[1]) * (float)spacing.Y; 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); MY_CHECKPOS("dropdown",0);
v2s32 pos = padding; v2s32 pos = padding + pos_offset * spacing;
pos.X += stof(v_pos[0]) * (float)spacing.X; pos.X += stof(v_pos[0]) * (float)spacing.X;
pos.Y += stof(v_pos[1]) * (float)spacing.Y; pos.Y += stof(v_pos[1]) * (float)spacing.Y;
@ -905,7 +929,7 @@ void GUIFormSpecMenu::parsePwdField(parserData* data,std::string element)
MY_CHECKPOS("pwdfield",0); MY_CHECKPOS("pwdfield",0);
MY_CHECKGEOM("pwdfield",1); MY_CHECKGEOM("pwdfield",1);
v2s32 pos; v2s32 pos = pos_offset * spacing;
pos.X += stof(v_pos[0]) * (float)spacing.X; pos.X += stof(v_pos[0]) * (float)spacing.X;
pos.Y += stof(v_pos[1]) * (float)spacing.Y; pos.Y += stof(v_pos[1]) * (float)spacing.Y;
@ -975,7 +999,7 @@ void GUIFormSpecMenu::parseSimpleField(parserData* data,
if(data->explicit_size) if(data->explicit_size)
warningstream<<"invalid use of unpositioned \"field\" in inventory"<<std::endl; 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); pos.Y = ((m_fields.size()+2)*60);
v2s32 size = DesiredRect.getSize(); v2s32 size = DesiredRect.getSize();
@ -1058,9 +1082,9 @@ void GUIFormSpecMenu::parseTextArea(parserData* data,
MY_CHECKPOS(type,0); MY_CHECKPOS(type,0);
MY_CHECKGEOM(type,1); MY_CHECKGEOM(type,1);
v2s32 pos; v2s32 pos = pos_offset * spacing;
pos.X = stof(v_pos[0]) * (float) spacing.X; pos.X += stof(v_pos[0]) * (float) spacing.X;
pos.Y = stof(v_pos[1]) * (float) spacing.Y; pos.Y += stof(v_pos[1]) * (float) spacing.Y;
v2s32 geom; v2s32 geom;
@ -1185,7 +1209,7 @@ void GUIFormSpecMenu::parseLabel(parserData* data,std::string element)
MY_CHECKPOS("label",0); MY_CHECKPOS("label",0);
v2s32 pos = padding; v2s32 pos = padding + pos_offset * spacing;
pos.X += stof(v_pos[0]) * (float)spacing.X; pos.X += stof(v_pos[0]) * (float)spacing.X;
pos.Y += (stof(v_pos[1]) + 7.0/30.0) * (float)spacing.Y; pos.Y += (stof(v_pos[1]) + 7.0/30.0) * (float)spacing.Y;
@ -1242,7 +1266,7 @@ void GUIFormSpecMenu::parseVertLabel(parserData* data,std::string element)
MY_CHECKPOS("vertlabel",1); MY_CHECKPOS("vertlabel",1);
v2s32 pos = padding; v2s32 pos = padding + pos_offset * spacing;
pos.X += stof(v_pos[0]) * (float)spacing.X; pos.X += stof(v_pos[0]) * (float)spacing.X;
pos.Y += stof(v_pos[1]) * (float)spacing.Y; pos.Y += stof(v_pos[1]) * (float)spacing.Y;
@ -1296,7 +1320,7 @@ void GUIFormSpecMenu::parseImageButton(parserData* data,std::string element,
MY_CHECKPOS("imagebutton",0); MY_CHECKPOS("imagebutton",0);
MY_CHECKGEOM("imagebutton",1); MY_CHECKGEOM("imagebutton",1);
v2s32 pos = padding; v2s32 pos = padding + pos_offset * spacing;
pos.X += stof(v_pos[0]) * (float)spacing.X; pos.X += stof(v_pos[0]) * (float)spacing.X;
pos.Y += stof(v_pos[1]) * (float)spacing.Y; pos.Y += stof(v_pos[1]) * (float)spacing.Y;
v2s32 geom; v2s32 geom;
@ -1401,7 +1425,7 @@ void GUIFormSpecMenu::parseTabHeader(parserData* data,std::string element)
spec.ftype = f_TabHeader; spec.ftype = f_TabHeader;
v2s32 pos(0,0); v2s32 pos = pos_offset * spacing;
pos.X += stof(v_pos[0]) * (float)spacing.X; pos.X += stof(v_pos[0]) * (float)spacing.X;
pos.Y += stof(v_pos[1]) * (float)spacing.Y - m_btn_height * 2; pos.Y += stof(v_pos[1]) * (float)spacing.Y - m_btn_height * 2;
v2s32 geom; v2s32 geom;
@ -1466,7 +1490,7 @@ void GUIFormSpecMenu::parseItemImageButton(parserData* data,std::string element)
MY_CHECKPOS("itemimagebutton",0); MY_CHECKPOS("itemimagebutton",0);
MY_CHECKGEOM("itemimagebutton",1); MY_CHECKGEOM("itemimagebutton",1);
v2s32 pos = padding; v2s32 pos = padding + pos_offset * spacing;
pos.X += stof(v_pos[0]) * (float)spacing.X; pos.X += stof(v_pos[0]) * (float)spacing.X;
pos.Y += stof(v_pos[1]) * (float)spacing.Y; pos.Y += stof(v_pos[1]) * (float)spacing.Y;
v2s32 geom; v2s32 geom;
@ -1504,7 +1528,7 @@ void GUIFormSpecMenu::parseItemImageButton(parserData* data,std::string element)
rect+=data->basepos-padding; rect+=data->basepos-padding;
spec.rect=rect; spec.rect=rect;
m_fields.push_back(spec); 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.X += stof(v_pos[0]) * (float) spacing.X;
pos.Y += stof(v_pos[1]) * (float) spacing.Y; pos.Y += stof(v_pos[1]) * (float) spacing.Y;
m_itemimages.push_back(ImageDrawSpec("", item_name, e, pos, geom)); m_itemimages.push_back(ImageDrawSpec("", item_name, e, pos, geom));
@ -1527,7 +1551,7 @@ void GUIFormSpecMenu::parseBox(parserData* data,std::string element)
MY_CHECKPOS("box",0); MY_CHECKPOS("box",0);
MY_CHECKGEOM("box",1); 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.X += stof(v_pos[0]) * (float) spacing.X;
pos.Y += stof(v_pos[1]) * (float) spacing.Y; pos.Y += stof(v_pos[1]) * (float) spacing.Y;
@ -1689,8 +1713,18 @@ void GUIFormSpecMenu::parseElement(parserData* data, std::string element)
std::string type = trim(parts[0]); std::string type = trim(parts[0]);
std::string description = trim(parts[1]); std::string description = trim(parts[1]);
if (type == "container") {
parseContainer(data, description);
return;
}
if (type == "container_end") {
parseContainerEnd(data);
return;
}
if (type == "list") { if (type == "list") {
parseList(data,description); parseList(data, description);
return; return;
} }
@ -1700,22 +1734,22 @@ void GUIFormSpecMenu::parseElement(parserData* data, std::string element)
} }
if (type == "checkbox") { if (type == "checkbox") {
parseCheckbox(data,description); parseCheckbox(data, description);
return; return;
} }
if (type == "image") { if (type == "image") {
parseImage(data,description); parseImage(data, description);
return; return;
} }
if (type == "item_image") { if (type == "item_image") {
parseItemImage(data,description); parseItemImage(data, description);
return; return;
} }
if ((type == "button") || (type == "button_exit")) { if (type == "button" || type == "button_exit") {
parseButton(data,description,type); parseButton(data, description, type);
return; return;
} }
@ -2036,10 +2070,16 @@ void GUIFormSpecMenu::regenerateGui(v2u32 screensize)
gui::IGUIFont *old_font = skin->getFont(); gui::IGUIFont *old_font = skin->getFont();
skin->setFont(m_font); skin->setFont(m_font);
pos_offset = v2s32();
for (; i< elements.size(); i++) { for (; i< elements.size(); i++) {
parseElement(&mydata, elements[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" // If there are fields without explicit size[], add a "Proceed"
// button and adjust size to fit all the fields. // button and adjust size to fit all the fields.
if (m_fields.size() && !mydata.explicit_size) { if (m_fields.size() && !mydata.explicit_size) {

View File

@ -22,6 +22,7 @@ with this program; if not, write to the Free Software Foundation, Inc.,
#define GUIINVENTORYMENU_HEADER #define GUIINVENTORYMENU_HEADER
#include <utility> #include <utility>
#include <stack>
#include "irrlichttypes_extrabloated.h" #include "irrlichttypes_extrabloated.h"
#include "inventory.h" #include "inventory.h"
@ -380,6 +381,8 @@ protected:
v2s32 spacing; v2s32 spacing;
v2s32 imgsize; v2s32 imgsize;
v2s32 offset; v2s32 offset;
v2s32 pos_offset;
std::stack<v2s32> container_stack;
irr::IrrlichtDevice* m_device; irr::IrrlichtDevice* m_device;
InventoryManager *m_invmgr; InventoryManager *m_invmgr;
@ -472,13 +475,15 @@ private:
fs_key_pendig current_keys_pending; fs_key_pendig current_keys_pending;
std::string current_field_enter_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 parseSize(parserData* data, std::string element);
void parseList(parserData* data,std::string element); void parseContainer(parserData* data, std::string element);
void parseListRing(parserData* data,std::string element); void parseContainerEnd(parserData* data);
void parseCheckbox(parserData* data,std::string element); void parseList(parserData* data, std::string element);
void parseImage(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 parseItemImage(parserData* data,std::string element);
void parseButton(parserData* data,std::string element,std::string typ); void parseButton(parserData* data,std::string element,std::string typ);
void parseBackground(parserData* data,std::string element); void parseBackground(parserData* data,std::string element);

View File

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

View File

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

View File

@ -21,14 +21,14 @@ with this program; if not, write to the Free Software Foundation, Inc.,
#define ITEMGROUP_HEADER #define ITEMGROUP_HEADER
#include <string> #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, static inline int itemgroup_get(const ItemGroupList &groups,
const std::string &name) 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()) if(i == groups.end())
return 0; return 0;
return i->second; return i->second;

View File

@ -23,6 +23,7 @@ with this program; if not, write to the Free Software Foundation, Inc.,
#include "log.h" #include "log.h"
#include "debug.h" #include "debug.h"
#include "util/hex.h" #include "util/hex.h"
#include "util/string.h"
class UnknownKeycode : public BaseException class UnknownKeycode : public BaseException
{ {
@ -31,321 +32,335 @@ public:
BaseException(s) {}; 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) for (u16 i = 0; i < ARRAYSIZE(table); i++) {
CHECKKEY(KEY_RBUTTON) if (strcmp(table[i].Name, name) == 0)
CHECKKEY(KEY_CANCEL) return table[i];
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)
throw UnknownKeycode(name); throw UnknownKeycode(name);
} }
static const char *KeyNames[] = struct table_key lookup_keykey(irr::EKEY_CODE key)
{ "-", "KEY_LBUTTON", "KEY_RBUTTON", "KEY_CANCEL", "KEY_MBUTTON", "KEY_XBUTTON1", {
"KEY_XBUTTON2", "-", "KEY_BACK", "KEY_TAB", "-", "-", "KEY_CLEAR", "KEY_RETURN", "-", for (u16 i = 0; i < ARRAYSIZE(table); i++) {
"-", "KEY_SHIFT", "KEY_CONTROL", "KEY_MENU", "KEY_PAUSE", "KEY_CAPITAL", "KEY_KANA", "-", if (table[i].Key == key)
"KEY_JUNJA", "KEY_FINAL", "KEY_KANJI", "-", "KEY_ESCAPE", "KEY_CONVERT", "KEY_NONCONVERT", return table[i];
"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", "-" };
#define N_(text) text std::ostringstream os;
os << "<Keycode " << (int) key << ">";
throw UnknownKeycode(os.str().c_str());
}
static const char *KeyNamesLang[] = struct table_key lookup_keychar(wchar_t Char)
{ "-", 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"), "-", for (u16 i = 0; i < ARRAYSIZE(table); i++) {
"-", N_("Shift"), N_("Control"), N_("Menu"), N_("Pause"), N_("Capital"), N_("Kana"), "-", if (table[i].Char == Char)
N_("Junja"), N_("Final"), N_("Kanji"), "-", N_("Escape"), N_("Convert"), N_("Nonconvert"), return table[i];
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"), "-" };
#undef N_ std::ostringstream os;
os << "<Char " << hex_encode((char*) &Char, sizeof(wchar_t)) << ">";
throw UnknownKeycode(os.str().c_str());
}
KeyPress::KeyPress() : KeyPress::KeyPress() :
Key(irr::KEY_KEY_CODES_COUNT), Key(irr::KEY_KEY_CODES_COUNT),
Char(L'\0') Char(L'\0'),
m_name("")
{} {}
KeyPress::KeyPress(const char *name) KeyPress::KeyPress(const char *name)
{ {
if (name[0] == 0) { if (strlen(name) == 0) {
Key = irr::KEY_KEY_CODES_COUNT; Key = irr::KEY_KEY_CODES_COUNT;
Char = L'\0'; Char = L'\0';
m_name = "";
return; 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 { try {
Key = keyname_to_keycode(name); struct table_key k = lookup_keychar(Char);
m_name = name; m_name = k.Name;
if (strlen(name) > 8 && strncmp(name, "KEY_KEY_", 8) == 0) { Key = k.Key;
int chars_read = mbtowc(&Char, name + 8, 1);
FATAL_ERROR_IF(chars_read != 1, "Unexpected multibyte character");
} else
Char = L'\0';
return; return;
} catch (UnknownKeycode &e) {}; } catch (UnknownKeycode &e) {};
} else { } else {
// see if we can set it up as a KEY_KEY_something // Lookup by name
m_name = "KEY_KEY_"; m_name = name;
m_name += name;
try { try {
Key = keyname_to_keycode(m_name.c_str()); struct table_key k = lookup_keyname(name);
int chars_read = mbtowc(&Char, name, 1); Key = k.Key;
Char = k.Char;
FATAL_ERROR_IF(chars_read != 1, "Unexpected multibyte character");
return; return;
} catch (UnknownKeycode &e) {}; } 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; Key = irr::KEY_KEY_CODES_COUNT;
int chars_read = mbtowc(&Char, name, 1);
int mbtowc_ret = mbtowc(&Char, name, 1); FATAL_ERROR_IF(chars_read != 1, "Unexpected multibyte character");
FATAL_ERROR_IF(mbtowc_ret != 1, "Unexpected multibyte character"); m_name = "";
m_name = name[0]; warningstream << "KeyPress: Unknown key '" << name << "', falling back to first char.";
} }
KeyPress::KeyPress(const irr::SEvent::SKeyInput &in, bool prefer_character) 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; Char = in.Char;
if(prefer_character){ try {
m_name.resize(MB_CUR_MAX+1, '\0'); if (valid_kcode(Key))
int written = wctomb(&m_name[0], Char); m_name = lookup_keykey(Key).Name;
if(written > 0){ else
infostream<<"KeyPress: Preferring character for "<<m_name<<std::endl; m_name = lookup_keychar(Char).Name;
Key = irr::KEY_KEY_CODES_COUNT; } catch (UnknownKeycode &e) {
return; m_name = "";
} };
}
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;
}
}
} }
const char *KeyPress::sym() const const char *KeyPress::sym() const
{ {
if (Key && Key < irr::KEY_KEY_CODES_COUNT) return m_name.c_str();
return KeyNames[Key];
else {
return m_name.c_str();
}
} }
const char *KeyPress::name() const const char *KeyPress::name() const
{ {
if (Key && Key < irr::KEY_KEY_CODES_COUNT) if (m_name == "")
return KeyNamesLang[Key]; return "";
else { const char *ret;
return m_name.c_str(); 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 EscapeKey("KEY_ESCAPE");
const KeyPress CancelKey("KEY_CANCEL"); const KeyPress CancelKey("KEY_CANCEL");
const KeyPress NumberKey[] = { const KeyPress NumberKey[] = {
KeyPress("KEY_KEY_0"), KeyPress("KEY_KEY_1"), KeyPress("KEY_KEY_2"), KeyPress("0"), KeyPress("1"), KeyPress("2"), KeyPress("3"), KeyPress("4"),
KeyPress("KEY_KEY_3"), KeyPress("KEY_KEY_4"), KeyPress("KEY_KEY_5"), KeyPress("5"), KeyPress("6"), KeyPress("7"), KeyPress("8"), KeyPress("9")
KeyPress("KEY_KEY_6"), KeyPress("KEY_KEY_7"), KeyPress("KEY_KEY_8"), };
KeyPress("KEY_KEY_9")};
/* /*
Key config Key config
@ -360,8 +375,10 @@ KeyPress getKeySetting(const char *settingname)
n = g_key_setting_cache.find(settingname); n = g_key_setting_cache.find(settingname);
if(n != g_key_setting_cache.end()) if(n != g_key_setting_cache.end())
return n->second; 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() void clearKeyCache()

View File

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

View File

@ -27,8 +27,10 @@ with this program; if not, write to the Free Software Foundation, Inc.,
*/ */
// This directly sets the range of light. // This directly sets the range of light.
// Actually this is not the real maximum, and this is not the // Actually this is not the real maximum, and this is not the brightest, the
// brightest. The brightest is LIGHT_SUN. // brightest is LIGHT_SUN.
// If changed, this constant as defined in builtin/game/constants.lua must
// also be changed.
#define LIGHT_MAX 14 #define LIGHT_MAX 14
// Light is stored as 4 bits, thus 15 is the maximum. // Light is stored as 4 bits, thus 15 is the maximum.
// This brightness is reserved for sunlight // This brightness is reserved for sunlight

View File

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

View File

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

View File

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

View File

@ -26,12 +26,12 @@ with this program; if not, write to the Free Software Foundation, Inc.,
#include "util/numeric.h" #include "util/numeric.h"
FlagDesc flagdesc_deco[] = { FlagDesc flagdesc_deco[] = {
{"place_center_x", DECO_PLACE_CENTER_X}, {"place_center_x", DECO_PLACE_CENTER_X},
{"place_center_y", DECO_PLACE_CENTER_Y}, {"place_center_y", DECO_PLACE_CENTER_Y},
{"place_center_z", DECO_PLACE_CENTER_Z}, {"place_center_z", DECO_PLACE_CENTER_Z},
{"force_placement", DECO_FORCE_PLACEMENT}, {"force_placement", DECO_FORCE_PLACEMENT},
{"liquid_surface", DECO_LIQUID_SURFACE}, {"liquid_surface", DECO_LIQUID_SURFACE},
{NULL, 0} {NULL, 0}
}; };
@ -82,6 +82,56 @@ Decoration::~Decoration()
void Decoration::resolveNodeNames() void Decoration::resolveNodeNames()
{ {
getIdsFromNrBacklog(&c_place_on); getIdsFromNrBacklog(&c_place_on);
getIdsFromNrBacklog(&c_spawnby);
}
bool Decoration::canPlaceDecoration(MMVManip *vm, v3s16 p)
{
// Check if the decoration can be placed on this node
u32 vi = vm->m_area.index(p);
if (!CONTAINS(c_place_on, vm->m_data[vi].getContent()))
return false;
// Don't continue if there are no spawnby constraints
if (nspawnby == -1)
return true;
int nneighs = 0;
static const v3s16 dirs[16] = {
v3s16( 0, 0, 1),
v3s16( 0, 0, -1),
v3s16( 1, 0, 0),
v3s16(-1, 0, 0),
v3s16( 1, 0, 1),
v3s16(-1, 0, 1),
v3s16(-1, 0, -1),
v3s16( 1, 0, -1),
v3s16( 0, 1, 1),
v3s16( 0, 1, -1),
v3s16( 1, 1, 0),
v3s16(-1, 1, 0),
v3s16( 1, 1, 1),
v3s16(-1, 1, 1),
v3s16(-1, 1, -1),
v3s16( 1, 1, -1)
};
// Check these 16 neighbouring nodes for enough spawnby nodes
for (size_t i = 0; i != ARRLEN(dirs); i++) {
u32 index = vm->m_area.index(p + dirs[i]);
if (!vm->m_area.contains(index))
continue;
if (CONTAINS(c_spawnby, vm->m_data[index].getContent()))
nneighs++;
}
if (nneighs < nspawnby)
return false;
return true;
} }
@ -236,66 +286,15 @@ void DecoSimple::resolveNodeNames()
{ {
Decoration::resolveNodeNames(); Decoration::resolveNodeNames();
getIdsFromNrBacklog(&c_decos); getIdsFromNrBacklog(&c_decos);
getIdsFromNrBacklog(&c_spawnby);
}
bool DecoSimple::canPlaceDecoration(MMVManip *vm, v3s16 p)
{
// Don't bother if there aren't any decorations to place
if (c_decos.size() == 0)
return false;
u32 vi = vm->m_area.index(p);
// Check if the decoration can be placed on this node
if (!CONTAINS(c_place_on, vm->m_data[vi].getContent()))
return false;
// Don't continue if there are no spawnby constraints
if (nspawnby == -1)
return true;
int nneighs = 0;
v3s16 dirs[16] = {
v3s16( 0, 0, 1),
v3s16( 0, 0, -1),
v3s16( 1, 0, 0),
v3s16(-1, 0, 0),
v3s16( 1, 0, 1),
v3s16(-1, 0, 1),
v3s16(-1, 0, -1),
v3s16( 1, 0, -1),
v3s16( 0, 1, 1),
v3s16( 0, 1, -1),
v3s16( 1, 1, 0),
v3s16(-1, 1, 0),
v3s16( 1, 1, 1),
v3s16(-1, 1, 1),
v3s16(-1, 1, -1),
v3s16( 1, 1, -1)
};
// Check a Moore neighborhood if there are enough spawnby nodes
for (size_t i = 0; i != ARRLEN(dirs); i++) {
u32 index = vm->m_area.index(p + dirs[i]);
if (!vm->m_area.contains(index))
continue;
if (CONTAINS(c_spawnby, vm->m_data[index].getContent()))
nneighs++;
}
if (nneighs < nspawnby)
return false;
return true;
} }
size_t DecoSimple::generate(MMVManip *vm, PcgRandom *pr, v3s16 p) size_t DecoSimple::generate(MMVManip *vm, PcgRandom *pr, v3s16 p)
{ {
// Don't bother if there aren't any decorations to place
if (c_decos.size() == 0)
return 0;
if (!canPlaceDecoration(vm, p)) if (!canPlaceDecoration(vm, p))
return 0; return 0;
@ -345,9 +344,7 @@ size_t DecoSchematic::generate(MMVManip *vm, PcgRandom *pr, v3s16 p)
if (schematic == NULL) if (schematic == NULL)
return 0; return 0;
u32 vi = vm->m_area.index(p); if (!canPlaceDecoration(vm, p))
content_t c = vm->m_data[vi].getContent();
if (!CONTAINS(c_place_on, c))
return 0; return 0;
if (flags & DECO_PLACE_CENTER_X) if (flags & DECO_PLACE_CENTER_X)

View File

@ -68,6 +68,7 @@ public:
virtual void resolveNodeNames(); virtual void resolveNodeNames();
bool canPlaceDecoration(MMVManip *vm, v3s16 p);
size_t placeDeco(Mapgen *mg, u32 blockseed, v3s16 nmin, v3s16 nmax); size_t placeDeco(Mapgen *mg, u32 blockseed, v3s16 nmin, v3s16 nmax);
//size_t placeCutoffs(Mapgen *mg, u32 blockseed, v3s16 nmin, v3s16 nmax); //size_t placeCutoffs(Mapgen *mg, u32 blockseed, v3s16 nmin, v3s16 nmax);
@ -82,6 +83,8 @@ public:
s16 y_max; s16 y_max;
float fill_ratio; float fill_ratio;
NoiseParams np; NoiseParams np;
std::vector<content_t> c_spawnby;
s16 nspawnby;
UNORDERED_SET<u8> biomes; UNORDERED_SET<u8> biomes;
//std::list<CutoffData> cutoffs; //std::list<CutoffData> cutoffs;
@ -90,17 +93,13 @@ public:
class DecoSimple : public Decoration { class DecoSimple : public Decoration {
public: public:
virtual void resolveNodeNames();
virtual size_t generate(MMVManip *vm, PcgRandom *pr, v3s16 p); virtual size_t generate(MMVManip *vm, PcgRandom *pr, v3s16 p);
bool canPlaceDecoration(MMVManip *vm, v3s16 p);
virtual int getHeight(); virtual int getHeight();
virtual void resolveNodeNames();
std::vector<content_t> c_decos; std::vector<content_t> c_decos;
std::vector<content_t> c_spawnby;
s16 deco_height; s16 deco_height;
s16 deco_height_max; s16 deco_height_max;
s16 nspawnby;
}; };
class DecoSchematic : public Decoration { class DecoSchematic : public Decoration {

View File

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

View File

@ -1065,7 +1065,7 @@ void Server::handleCommand_ChatMessage(NetworkPacket* pkt)
std::wstring wname = narrow_to_wide(name); std::wstring wname = narrow_to_wide(name);
std::wstring answer_to_sender = handleChat(name, wname, message, std::wstring answer_to_sender = handleChat(name, wname, message,
true, pkt->getPeerId()); true, dynamic_cast<RemotePlayer *>(player));
if (!answer_to_sender.empty()) { if (!answer_to_sender.empty()) {
// Send the answer to sender // Send the answer to sender
SendChatMessage(pkt->getPeerId(), answer_to_sender); SendChatMessage(pkt->getPeerId(), answer_to_sender);
@ -1656,16 +1656,16 @@ void Server::handleCommand_Interact(NetworkPacket* pkt)
} }
} // action == 4 } // action == 4
/* /*
5: rightclick air 5: rightclick air
*/ */
else if (action == 5) { else if (action == 5) {
ItemStack item = playersao->getWieldedItem(); ItemStack item = playersao->getWieldedItem();
actionstream << player->getName() << " activates " actionstream << player->getName() << " activates "
<< item.name << std::endl; << item.name << std::endl;
if (m_script->item_OnSecondaryUse( if (m_script->item_OnSecondaryUse(
item, playersao)) { item, playersao)) {
if( playersao->setWieldedItem(item)) { if( playersao->setWieldedItem(item)) {

View File

@ -74,6 +74,11 @@ void NodeMetadata::clear()
m_inventory->clear(); m_inventory->clear();
} }
bool NodeMetadata::empty() const
{
return m_stringvars.size() == 0 && m_inventory->getLists().size() == 0;
}
/* /*
NodeMetadataList NodeMetadataList
*/ */
@ -84,14 +89,13 @@ void NodeMetadataList::serialize(std::ostream &os) const
Version 0 is a placeholder for "nothing to see here; go away." Version 0 is a placeholder for "nothing to see here; go away."
*/ */
if(m_data.empty()){ u16 count = countNonEmpty();
if (count == 0) {
writeU8(os, 0); // version writeU8(os, 0); // version
return; return;
} }
writeU8(os, 1); // version writeU8(os, 1); // version
u16 count = m_data.size();
writeU16(os, count); writeU16(os, count);
for(std::map<v3s16, NodeMetadata*>::const_iterator for(std::map<v3s16, NodeMetadata*>::const_iterator
@ -100,6 +104,8 @@ void NodeMetadataList::serialize(std::ostream &os) const
{ {
v3s16 p = i->first; v3s16 p = i->first;
NodeMetadata *data = i->second; NodeMetadata *data = i->second;
if (data->empty())
continue;
u16 p16 = p.Z * MAP_BLOCKSIZE * MAP_BLOCKSIZE + p.Y * MAP_BLOCKSIZE + p.X; u16 p16 = p.Z * MAP_BLOCKSIZE * MAP_BLOCKSIZE + p.Y * MAP_BLOCKSIZE + p.X;
writeU16(os, p16); writeU16(os, p16);
@ -200,6 +206,17 @@ void NodeMetadataList::clear()
m_data.clear(); m_data.clear();
} }
int NodeMetadataList::countNonEmpty() const
{
int n = 0;
std::map<v3s16, NodeMetadata*>::const_iterator it;
for (it = m_data.begin(); it != m_data.end(); ++it) {
if (!it->second->empty())
n++;
}
return n;
}
std::string NodeMetadata::getString(const std::string &name, std::string NodeMetadata::getString(const std::string &name,
unsigned short recursion) const unsigned short recursion) const
{ {

View File

@ -47,6 +47,7 @@ public:
void deSerialize(std::istream &is); void deSerialize(std::istream &is);
void clear(); void clear();
bool empty() const;
// Generic key/value store // Generic key/value store
std::string getString(const std::string &name, unsigned short recursion = 0) const; std::string getString(const std::string &name, unsigned short recursion = 0) const;
@ -94,6 +95,8 @@ public:
void clear(); void clear();
private: private:
int countNonEmpty() const;
std::map<v3s16, NodeMetadata *> m_data; std::map<v3s16, NodeMetadata *> m_data;
}; };

View File

@ -227,10 +227,25 @@ void Player::clearHud()
} }
} }
// 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(IGameDef *gamedef, const char *name): RemotePlayer::RemotePlayer(IGameDef *gamedef, const char *name):
Player(gamedef, name), Player(gamedef, name),
m_sao(NULL) m_sao(NULL),
m_last_chat_message_sent(time(NULL)),
m_chat_message_allowance(5.0f),
m_message_rate_overhead(0)
{ {
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_default = g_settings->getFloat("movement_acceleration_default") * BS;
movement_acceleration_air = g_settings->getFloat("movement_acceleration_air") * BS; movement_acceleration_air = g_settings->getFloat("movement_acceleration_air") * BS;
movement_acceleration_fast = g_settings->getFloat("movement_acceleration_fast") * BS; movement_acceleration_fast = g_settings->getFloat("movement_acceleration_fast") * BS;
@ -304,3 +319,42 @@ void RemotePlayer::setPosition(const v3f &position)
m_sao->setBasePosition(position); 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;
}

View File

@ -439,7 +439,11 @@ private:
Mutex m_mutex; Mutex m_mutex;
}; };
enum RemotePlayerChatResult {
RPLAYER_CHATRESULT_OK,
RPLAYER_CHATRESULT_FLOODING,
RPLAYER_CHATRESULT_KICK,
};
/* /*
Player on the server Player on the server
*/ */
@ -457,8 +461,18 @@ public:
{ m_sao = sao; } { m_sao = sao; }
void setPosition(const v3f &position); void setPosition(const v3f &position);
const RemotePlayerChatResult canSendChatMessage();
private: private:
PlayerSAO *m_sao; PlayerSAO *m_sao;
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;
}; };
#endif #endif

View File

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

View File

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

View File

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

View File

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

View File

@ -111,6 +111,9 @@ int LuaAreaStore::l_get_area(lua_State *L)
const Area *res; const Area *res;
res = ast->getArea(id); res = ast->getArea(id);
if (!res)
return 0;
push_area(L, res, include_borders, include_data); push_area(L, res, include_borders, include_data);
return 1; return 1;

View File

@ -902,6 +902,7 @@ int ModApiMapgen::l_register_decoration(lua_State *L)
deco->fill_ratio = getfloatfield_default(L, index, "fill_ratio", 0.02); deco->fill_ratio = getfloatfield_default(L, index, "fill_ratio", 0.02);
deco->y_min = getintfield_default(L, index, "y_min", -31000); deco->y_min = getintfield_default(L, index, "y_min", -31000);
deco->y_max = getintfield_default(L, index, "y_max", 31000); deco->y_max = getintfield_default(L, index, "y_max", 31000);
deco->nspawnby = getintfield_default(L, index, "num_spawn_by", -1);
deco->sidelen = getintfield_default(L, index, "sidelen", 8); deco->sidelen = getintfield_default(L, index, "sidelen", 8);
if (deco->sidelen <= 0) { if (deco->sidelen <= 0) {
errorstream << "register_decoration: sidelen must be " errorstream << "register_decoration: sidelen must be "
@ -929,6 +930,14 @@ int ModApiMapgen::l_register_decoration(lua_State *L)
errorstream << "register_decoration: couldn't get all biomes " << std::endl; errorstream << "register_decoration: couldn't get all biomes " << std::endl;
lua_pop(L, 1); lua_pop(L, 1);
//// Get node name(s) to 'spawn by'
size_t nnames = getstringlistfield(L, index, "spawn_by", &deco->m_nodenames);
deco->m_nnlistsizes.push_back(nnames);
if (nnames == 0 && deco->nspawnby != -1) {
errorstream << "register_decoration: no spawn_by nodes defined,"
" but num_spawn_by specified" << std::endl;
}
//// Handle decoration type-specific parameters //// Handle decoration type-specific parameters
bool success = false; bool success = false;
switch (decotype) { switch (decotype) {
@ -962,12 +971,10 @@ int ModApiMapgen::l_register_decoration(lua_State *L)
bool read_deco_simple(lua_State *L, DecoSimple *deco) bool read_deco_simple(lua_State *L, DecoSimple *deco)
{ {
size_t nnames;
int index = 1; int index = 1;
deco->deco_height = getintfield_default(L, index, "height", 1); deco->deco_height = getintfield_default(L, index, "height", 1);
deco->deco_height_max = getintfield_default(L, index, "height_max", 0); deco->deco_height_max = getintfield_default(L, index, "height_max", 0);
deco->nspawnby = getintfield_default(L, index, "num_spawn_by", -1);
if (deco->deco_height <= 0) { if (deco->deco_height <= 0) {
errorstream << "register_decoration: simple decoration height" errorstream << "register_decoration: simple decoration height"
@ -975,7 +982,7 @@ bool read_deco_simple(lua_State *L, DecoSimple *deco)
return false; return false;
} }
nnames = getstringlistfield(L, index, "decoration", &deco->m_nodenames); size_t nnames = getstringlistfield(L, index, "decoration", &deco->m_nodenames);
deco->m_nnlistsizes.push_back(nnames); deco->m_nnlistsizes.push_back(nnames);
if (nnames == 0) { if (nnames == 0) {
errorstream << "register_decoration: no decoration nodes " errorstream << "register_decoration: no decoration nodes "
@ -983,14 +990,6 @@ bool read_deco_simple(lua_State *L, DecoSimple *deco)
return false; return false;
} }
nnames = getstringlistfield(L, index, "spawn_by", &deco->m_nodenames);
deco->m_nnlistsizes.push_back(nnames);
if (nnames == 0 && deco->nspawnby != -1) {
errorstream << "register_decoration: no spawn_by nodes defined,"
" but num_spawn_by specified" << std::endl;
return false;
}
return true; return true;
} }

View File

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

View File

@ -20,7 +20,7 @@ with this program; if not, write to the Free Software Foundation, Inc.,
#include "serialization.h" #include "serialization.h"
#include "util/serialize.h" #include "util/serialize.h"
#ifdef _WIN32 #if defined(_WIN32) && !defined(WIN32_NO_ZLIB_WINAPI)
#define ZLIB_WINAPI #define ZLIB_WINAPI
#endif #endif
#include "zlib.h" #include "zlib.h"

View File

@ -358,6 +358,7 @@ Server::Server(
add_legacy_abms(m_env, m_nodedef); add_legacy_abms(m_env, m_nodedef);
m_liquid_transform_every = g_settings->getFloat("liquid_update"); m_liquid_transform_every = g_settings->getFloat("liquid_update");
m_max_chatmessage_length = g_settings->getU16("chat_message_max_size");
} }
Server::~Server() Server::~Server()
@ -668,7 +669,7 @@ void Server::AsyncRunStep(bool initial_step)
MutexAutoLock envlock(m_env_mutex); MutexAutoLock envlock(m_env_mutex);
m_clients.lock(); 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"); ScopeProfiler sp(g_profiler, "Server: checking added and deleted objs");
// Radius inside which objects are active // Radius inside which objects are active
@ -684,8 +685,7 @@ void Server::AsyncRunStep(bool initial_step)
if (player_radius == 0 && is_transfer_limited) if (player_radius == 0 && is_transfer_limited)
player_radius = radius; player_radius = radius;
for (std::map<u16, RemoteClient*>::iterator for (UNORDERED_MAP<u16, RemoteClient*>::iterator i = clients.begin();
i = clients.begin();
i != clients.end(); ++i) { i != clients.end(); ++i) {
RemoteClient *client = i->second; RemoteClient *client = i->second;
@ -695,7 +695,7 @@ void Server::AsyncRunStep(bool initial_step)
continue; continue;
Player *player = m_env->getPlayer(client->peer_id); Player *player = m_env->getPlayer(client->peer_id);
if(player == NULL) { if (player == NULL) {
// This can happen if the client timeouts somehow // This can happen if the client timeouts somehow
/*warningstream<<FUNCTION_NAME<<": Client " /*warningstream<<FUNCTION_NAME<<": Client "
<<client->peer_id <<client->peer_id
@ -816,10 +816,9 @@ void Server::AsyncRunStep(bool initial_step)
} }
m_clients.lock(); m_clients.lock();
std::map<u16, RemoteClient*> clients = m_clients.getClientList(); UNORDERED_MAP<u16, RemoteClient*> clients = m_clients.getClientList();
// Route data to every client // Route data to every client
for (std::map<u16, RemoteClient*>::iterator for (UNORDERED_MAP<u16, RemoteClient*>::iterator i = clients.begin();
i = clients.begin();
i != clients.end(); ++i) { i != clients.end(); ++i) {
RemoteClient *client = i->second; RemoteClient *client = i->second;
std::string reliable_data; std::string reliable_data;
@ -2734,8 +2733,7 @@ void Server::handleChatInterfaceEvent(ChatEvent *evt)
} }
std::wstring Server::handleChat(const std::string &name, const std::wstring &wname, std::wstring Server::handleChat(const std::string &name, const std::wstring &wname,
const std::wstring &wmessage, bool check_shout_priv, const std::wstring &wmessage, bool check_shout_priv, RemotePlayer *player)
u16 peer_id_to_avoid_sending)
{ {
// If something goes wrong, this player is to blame // If something goes wrong, this player is to blame
RollbackScopeActor rollback_scope(m_rollback, RollbackScopeActor rollback_scope(m_rollback,
@ -2753,6 +2751,28 @@ std::wstring Server::handleChat(const std::string &name, const std::wstring &wna
if (ate) if (ate)
return L""; 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")
<< " 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. "
"It was refused. Send a shorter message";
}
// Commands are implemented in Lua, so only catch invalid // Commands are implemented in Lua, so only catch invalid
// commands that were not "eaten" and send an error back // commands that were not "eaten" and send an error back
if (wmessage[0] == L'/') { if (wmessage[0] == L'/') {
@ -2787,6 +2807,7 @@ std::wstring Server::handleChat(const std::string &name, const std::wstring &wna
std::vector<u16> clients = m_clients.getClientIDs(); 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++) { for (u16 i = 0; i < clients.size(); i++) {
u16 cid = clients[i]; u16 cid = clients[i];
if (cid != peer_id_to_avoid_sending) if (cid != peer_id_to_avoid_sending)

View File

@ -487,7 +487,7 @@ private:
std::wstring handleChat(const std::string &name, const std::wstring &wname, std::wstring handleChat(const std::string &name, const std::wstring &wname,
const std::wstring &wmessage, const std::wstring &wmessage,
bool check_shout_priv = false, bool check_shout_priv = false,
u16 peer_id_to_avoid_sending = PEER_ID_INEXISTENT); RemotePlayer *player = NULL);
void handleAdminChat(const ChatEventChat *evt); void handleAdminChat(const ChatEventChat *evt);
v3f findSpawnPos(); v3f findSpawnPos();
@ -522,6 +522,7 @@ private:
// If true, do not allow multiple players and hide some multiplayer // If true, do not allow multiple players and hide some multiplayer
// functionality // functionality
bool m_simple_singleplayer_mode; bool m_simple_singleplayer_mode;
u16 m_max_chatmessage_length;
// Thread can set; step() will throw as ServerError // Thread can set; step() will throw as ServerError
MutexedVariable<std::string> m_async_fatal_error; MutexedVariable<std::string> m_async_fatal_error;

View File

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

View File

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

View File

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

View File

@ -34,24 +34,23 @@ void ToolCapabilities::serialize(std::ostream &os, u16 protocol_version) const
writeF1000(os, full_punch_interval); writeF1000(os, full_punch_interval);
writeS16(os, max_drop_level); writeS16(os, max_drop_level);
writeU32(os, groupcaps.size()); writeU32(os, groupcaps.size());
for(std::map<std::string, ToolGroupCap>::const_iterator for (ToolGCMap::const_iterator i = groupcaps.begin(); i != groupcaps.end(); ++i) {
i = groupcaps.begin(); i != groupcaps.end(); ++i){
const std::string *name = &i->first; const std::string *name = &i->first;
const ToolGroupCap *cap = &i->second; const ToolGroupCap *cap = &i->second;
os<<serializeString(*name); os<<serializeString(*name);
writeS16(os, cap->uses); writeS16(os, cap->uses);
writeS16(os, cap->maxlevel); writeS16(os, cap->maxlevel);
writeU32(os, cap->times.size()); writeU32(os, cap->times.size());
for(std::map<int, float>::const_iterator for (UNORDERED_MAP<int, float>::const_iterator
i = cap->times.begin(); i != cap->times.end(); ++i){ i = cap->times.begin(); i != cap->times.end(); ++i) {
writeS16(os, i->first); writeS16(os, i->first);
writeF1000(os, i->second); writeF1000(os, i->second);
} }
} }
if(protocol_version > 17){ if(protocol_version > 17){
writeU32(os, damageGroups.size()); writeU32(os, damageGroups.size());
for(std::map<std::string, s16>::const_iterator for (DamageGroup::const_iterator i = damageGroups.begin();
i = damageGroups.begin(); i != damageGroups.end(); ++i){ i != damageGroups.end(); ++i) {
os<<serializeString(i->first); os<<serializeString(i->first);
writeS16(os, i->second); writeS16(os, i->second);
} }
@ -106,7 +105,7 @@ DigParams getDigParams(const ItemGroupList &groups,
default: default:
break; break;
} }
// Values to be returned (with a bit of conversion) // Values to be returned (with a bit of conversion)
bool result_diggable = false; bool result_diggable = false;
float result_time = 0.0; float result_time = 0.0;
@ -115,8 +114,8 @@ DigParams getDigParams(const ItemGroupList &groups,
int level = itemgroup_get(groups, "level"); int level = itemgroup_get(groups, "level");
//infostream<<"level="<<level<<std::endl; //infostream<<"level="<<level<<std::endl;
for(std::map<std::string, ToolGroupCap>::const_iterator for (ToolGCMap::const_iterator i = tp->groupcaps.begin();
i = tp->groupcaps.begin(); i != tp->groupcaps.end(); ++i){ i != tp->groupcaps.end(); ++i) {
const std::string &name = i->first; const std::string &name = i->first;
//infostream<<"group="<<name<<std::endl; //infostream<<"group="<<name<<std::endl;
const ToolGroupCap &cap = i->second; const ToolGroupCap &cap = i->second;
@ -163,8 +162,8 @@ HitParams getHitParams(const ItemGroupList &armor_groups,
s16 damage = 0; s16 damage = 0;
float full_punch_interval = tp->full_punch_interval; float full_punch_interval = tp->full_punch_interval;
for(std::map<std::string, s16>::const_iterator for (DamageGroup::const_iterator i = tp->damageGroups.begin();
i = tp->damageGroups.begin(); i != tp->damageGroups.end(); ++i){ i != tp->damageGroups.end(); ++i) {
s16 armor = itemgroup_get(armor_groups, i->first); s16 armor = itemgroup_get(armor_groups, i->first);
damage += i->second * rangelim(time_from_last_punch / full_punch_interval, 0.0, 1.0) damage += i->second * rangelim(time_from_last_punch / full_punch_interval, 0.0, 1.0)
* armor / 100.0; * armor / 100.0;
@ -197,7 +196,7 @@ PunchDamageResult getPunchDamage(
do_hit = false; do_hit = false;
} }
} }
PunchDamageResult result; PunchDamageResult result;
if(do_hit) if(do_hit)
{ {

View File

@ -23,12 +23,12 @@ with this program; if not, write to the Free Software Foundation, Inc.,
#include "irrlichttypes.h" #include "irrlichttypes.h"
#include <string> #include <string>
#include <iostream> #include <iostream>
#include <map> #include "util/cpp11_container.h"
#include "itemgroup.h" #include "itemgroup.h"
struct ToolGroupCap struct ToolGroupCap
{ {
std::map<int, float> times; UNORDERED_MAP<int, float> times;
int maxlevel; int maxlevel;
int uses; int uses;
@ -39,8 +39,8 @@ struct ToolGroupCap
bool getTime(int rating, float *time) const bool getTime(int rating, float *time) const
{ {
std::map<int, float>::const_iterator i = times.find(rating); UNORDERED_MAP<int, float>::const_iterator i = times.find(rating);
if(i == times.end()){ if (i == times.end()) {
*time = 0; *time = 0;
return false; return false;
} }
@ -50,22 +50,19 @@ struct ToolGroupCap
}; };
// CLANG SUCKS DONKEY BALLS typedef UNORDERED_MAP<std::string, struct ToolGroupCap> ToolGCMap;
typedef std::map<std::string, struct ToolGroupCap> ToolGCMap; typedef UNORDERED_MAP<std::string, s16> DamageGroup;
typedef std::map<std::string, s16> DamageGroup;
struct ToolCapabilities struct ToolCapabilities
{ {
float full_punch_interval; float full_punch_interval;
int max_drop_level; int max_drop_level;
// CLANG SUCKS DONKEY BALLS
ToolGCMap groupcaps; ToolGCMap groupcaps;
DamageGroup damageGroups; DamageGroup damageGroups;
ToolCapabilities( ToolCapabilities(
float full_punch_interval_=1.4, float full_punch_interval_=1.4,
int max_drop_level_=1, int max_drop_level_=1,
// CLANG SUCKS DONKEY BALLS
ToolGCMap groupcaps_=ToolGCMap(), ToolGCMap groupcaps_=ToolGCMap(),
DamageGroup damageGroups_=DamageGroup() DamageGroup damageGroups_=DamageGroup()
): ):

View File

@ -23,3 +23,7 @@ set (UNITTEST_SRCS
${CMAKE_CURRENT_SOURCE_DIR}/test_voxelalgorithms.cpp ${CMAKE_CURRENT_SOURCE_DIR}/test_voxelalgorithms.cpp
${CMAKE_CURRENT_SOURCE_DIR}/test_voxelmanipulator.cpp ${CMAKE_CURRENT_SOURCE_DIR}/test_voxelmanipulator.cpp
PARENT_SCOPE) PARENT_SCOPE)
set (UNITTEST_CLIENT_SRCS
${CMAKE_CURRENT_SOURCE_DIR}/test_keycode.cpp
PARENT_SCOPE)

View File

@ -0,0 +1,129 @@
/*
Minetest
Copyright (C) 2016 sfan5 <sfan5@live.de>
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 "test.h"
#include <string>
#include "exceptions.h"
#include "keycode.h"
class TestKeycode : public TestBase {
public:
TestKeycode() { TestManager::registerTestModule(this); }
const char *getName() { return "TestKeycode"; }
void runTests(IGameDef *gamedef);
void testCreateFromString();
void testCreateFromSKeyInput();
void testCompare();
};
static TestKeycode g_test_instance;
void TestKeycode::runTests(IGameDef *gamedef)
{
TEST(testCreateFromString);
TEST(testCreateFromSKeyInput);
TEST(testCompare);
}
////////////////////////////////////////////////////////////////////////////////
#define UASSERTEQ_STR(one, two) UASSERT(strcmp(one, two) == 0)
void TestKeycode::testCreateFromString()
{
KeyPress k;
// Character key, from char
k = KeyPress("R");
UASSERTEQ_STR(k.sym(), "KEY_KEY_R");
UASSERTCMP(int, >, strlen(k.name()), 0); // should have human description
// Character key, from identifier
k = KeyPress("KEY_KEY_B");
UASSERTEQ_STR(k.sym(), "KEY_KEY_B");
UASSERTCMP(int, >, strlen(k.name()), 0);
// Non-Character key, from identifier
k = KeyPress("KEY_UP");
UASSERTEQ_STR(k.sym(), "KEY_UP");
UASSERTCMP(int, >, strlen(k.name()), 0);
k = KeyPress("KEY_F6");
UASSERTEQ_STR(k.sym(), "KEY_F6");
UASSERTCMP(int, >, strlen(k.name()), 0);
// Irrlicht-unknown key, from char
k = KeyPress("/");
UASSERTEQ_STR(k.sym(), "/");
UASSERTCMP(int, >, strlen(k.name()), 0);
}
void TestKeycode::testCreateFromSKeyInput()
{
KeyPress k;
irr::SEvent::SKeyInput in;
// Character key
in.Key = irr::KEY_KEY_3;
in.Char = L'3';
k = KeyPress(in);
UASSERTEQ_STR(k.sym(), "KEY_KEY_3");
// Non-Character key
in.Key = irr::KEY_RSHIFT;
in.Char = L'\0';
k = KeyPress(in);
UASSERTEQ_STR(k.sym(), "KEY_RSHIFT");
// Irrlicht-unknown key
in.Key = irr::KEY_KEY_CODES_COUNT;
in.Char = L'?';
k = KeyPress(in);
UASSERTEQ_STR(k.sym(), "?");
// prefer_character mode
in.Key = irr::KEY_COMMA;
in.Char = L'G';
k = KeyPress(in, true);
UASSERTEQ_STR(k.sym(), "KEY_KEY_G");
}
void TestKeycode::testCompare()
{
// Basic comparison
UASSERT(KeyPress("5") == KeyPress("KEY_KEY_5"));
UASSERT(!(KeyPress("5") == KeyPress("KEY_NUMPAD_5")));
// Matching char suffices
// note: This is a real-world example, Irrlicht maps XK_equal to irr::KEY_PLUS on Linux
irr::SEvent::SKeyInput in;
in.Key = irr::KEY_PLUS;
in.Char = L'=';
UASSERT(KeyPress("=") == KeyPress(in));
// Matching keycode suffices
irr::SEvent::SKeyInput in2;
in.Key = in2.Key = irr::KEY_OEM_CLEAR;
in.Char = L'\0';
in2.Char = L';';
UASSERT(KeyPress(in) == KeyPress(in2));
}

View File

@ -32,7 +32,7 @@ public:
void testAllSettings(); void testAllSettings();
static const char *config_text_before; static const char *config_text_before;
static const char *config_text_after; static const std::string config_text_after;
}; };
static TestSettings g_test_instance; static TestSettings g_test_instance;
@ -69,7 +69,7 @@ const char *TestSettings::config_text_before =
"np_terrain = 5, 40, (250, 250, 250), 12341, 5, 0.7, 2.4\n" "np_terrain = 5, 40, (250, 250, 250), 12341, 5, 0.7, 2.4\n"
"zoop = true"; "zoop = true";
const char *TestSettings::config_text_after = const std::string TestSettings::config_text_after =
"leet = 1337\n" "leet = 1337\n"
"leetleet = 13371337\n" "leetleet = 13371337\n"
"leetleet_neg = -13371337\n" "leetleet_neg = -13371337\n"
@ -197,7 +197,10 @@ void TestSettings::testAllSettings()
UASSERT(s.updateConfigObject(is, os, "", 0) == true); UASSERT(s.updateConfigObject(is, os, "", 0) == true);
//printf(">>>> expected config:\n%s\n", TEST_CONFIG_TEXT_AFTER); //printf(">>>> expected config:\n%s\n", TEST_CONFIG_TEXT_AFTER);
//printf(">>>> actual config:\n%s\n", os.str().c_str()); //printf(">>>> actual config:\n%s\n", os.str().c_str());
#if __cplusplus < 201103L
// This test only works in older C++ versions than C++11 because we use unordered_map
UASSERT(os.str() == config_text_after); UASSERT(os.str() == config_text_after);
#endif
} catch (SettingNotFoundException &e) { } catch (SettingNotFoundException &e) {
UASSERT(!"Setting not found!"); UASSERT(!"Setting not found!");
} }

View File

@ -163,6 +163,7 @@ private:
void TestThreading::testAtomicSemaphoreThread() void TestThreading::testAtomicSemaphoreThread()
{ {
Atomic<u32> val; Atomic<u32> val;
val = 0;
Semaphore trigger; Semaphore trigger;
static const u8 num_threads = 4; static const u8 num_threads = 4;

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.2 KiB

After

Width:  |  Height:  |  Size: 202 B

View File

@ -13,15 +13,15 @@ packagedir=$builddir/packages
libdir=$builddir/libs libdir=$builddir/libs
toolchain_file=$dir/toolchain_mingw.cmake toolchain_file=$dir/toolchain_mingw.cmake
irrlicht_version=1.8.1 irrlicht_version=1.8.4
ogg_version=1.2.1 ogg_version=1.3.2
vorbis_version=1.3.3 vorbis_version=1.3.5
curl_version=7.38.0 curl_version=7.50.3
gettext_version=0.14.4 gettext_version=0.14.4
freetype_version=2.3.5 freetype_version=2.7
sqlite3_version=3.8.7.4 sqlite3_version=3.14.2
luajit_version=2.0.1 luajit_version=2.0.1
leveldb_version=1.15 leveldb_version=1.18
zlib_version=1.2.8 zlib_version=1.2.8
mkdir -p $packagedir mkdir -p $packagedir
@ -34,44 +34,38 @@ cd $builddir
-c -O $packagedir/irrlicht-$irrlicht_version.zip -c -O $packagedir/irrlicht-$irrlicht_version.zip
[ -e $packagedir/zlib-$zlib_version.zip ] || wget http://minetest.kitsunemimi.pw/zlib-$zlib_version-win32.zip \ [ -e $packagedir/zlib-$zlib_version.zip ] || wget http://minetest.kitsunemimi.pw/zlib-$zlib_version-win32.zip \
-c -O $packagedir/zlib-$zlib_version.zip -c -O $packagedir/zlib-$zlib_version.zip
[ -e $packagedir/libogg-$ogg_version-dev.7z ] || wget http://minetest.kitsunemimi.pw/libogg-$ogg_version-dev.7z \ [ -e $packagedir/libogg-$ogg_version.zip ] || wget http://minetest.kitsunemimi.pw/libogg-$ogg_version-win32.zip \
-c -O $packagedir/libogg-$ogg_version-dev.7z -c -O $packagedir/libogg-$ogg_version.zip
[ -e $packagedir/libogg-$ogg_version-dll.7z ] || wget http://minetest.kitsunemimi.pw/libogg-$ogg_version-dll.7z \ [ -e $packagedir/libvorbis-$vorbis_version.zip ] || wget http://minetest.kitsunemimi.pw/libvorbis-$vorbis_version-win32.zip \
-c -O $packagedir/libogg-$ogg_version-dll.7z -c -O $packagedir/libvorbis-$vorbis_version.zip
[ -e $packagedir/libvorbis-$vorbis_version-dev.7z ] || wget http://minetest.kitsunemimi.pw/libvorbis-$vorbis_version-dev.7z \ [ -e $packagedir/curl-$curl_version.zip ] || wget http://minetest.kitsunemimi.pw/curl-$curl_version-win32.zip \
-c -O $packagedir/libvorbis-$vorbis_version-dev.7z -c -O $packagedir/curl-$curl_version.zip
[ -e $packagedir/libvorbis-$vorbis_version-dll.7z ] || wget http://minetest.kitsunemimi.pw/libvorbis-$vorbis_version-dll.7z \
-c -O $packagedir/libvorbis-$vorbis_version-dll.7z
[ -e $packagedir/libcurl-$curl_version.zip ] || wget http://minetest.kitsunemimi.pw/libcurl-$curl_version-win32.zip \
-c -O $packagedir/libcurl-$curl_version.zip
[ -e $packagedir/gettext-$gettext_version.zip ] || wget http://minetest.kitsunemimi.pw/gettext-$gettext_version.zip \ [ -e $packagedir/gettext-$gettext_version.zip ] || wget http://minetest.kitsunemimi.pw/gettext-$gettext_version.zip \
-c -O $packagedir/gettext-$gettext_version.zip -c -O $packagedir/gettext-$gettext_version.zip
[ -e $packagedir/libfreetype-$freetype_version.zip ] || wget http://minetest.kitsunemimi.pw/libfreetype-$freetype_version-win32.zip \ [ -e $packagedir/freetype2-$freetype_version.zip ] || wget http://minetest.kitsunemimi.pw/freetype2-$freetype_version-win32.zip \
-c -O $packagedir/libfreetype-$freetype_version.zip -c -O $packagedir/freetype2-$freetype_version.zip
[ -e $packagedir/sqlite3-$sqlite3_version.zip ] || wget http://minetest.kitsunemimi.pw/sqlite3-$sqlite3_version-win32.zip \ [ -e $packagedir/sqlite3-$sqlite3_version.zip ] || wget http://minetest.kitsunemimi.pw/sqlite3-$sqlite3_version-win32.zip \
-c -O $packagedir/sqlite3-$sqlite3_version.zip -c -O $packagedir/sqlite3-$sqlite3_version.zip
[ -e $packagedir/luajit-$luajit_version-static-win32.zip ] || wget http://minetest.kitsunemimi.pw/luajit-$luajit_version-static-win32.zip \ [ -e $packagedir/luajit-$luajit_version-static-win32.zip ] || wget http://minetest.kitsunemimi.pw/luajit-$luajit_version-static-win32.zip \
-c -O $packagedir/luajit-$luajit_version-static-win32.zip -c -O $packagedir/luajit-$luajit_version-static-win32.zip
[ -e $packagedir/libleveldb-$leveldb_version-win32.zip ] || wget http://minetest.kitsunemimi.pw/libleveldb-$leveldb_version-win32.zip \ [ -e $packagedir/libleveldb-$leveldb_version.zip ] || wget http://minetest.kitsunemimi.pw/libleveldb-$leveldb_version-win32.zip \
-c -O $packagedir/libleveldb-$leveldb_version-win32.zip -c -O $packagedir/libleveldb-$leveldb_version.zip
[ -e $packagedir/openal_stripped.zip ] || wget http://minetest.kitsunemimi.pw/openal_stripped.zip \ [ -e $packagedir/openal_stripped.zip ] || wget http://minetest.kitsunemimi.pw/openal_stripped.zip \
-c -O $packagedir/openal_stripped.zip -c -O $packagedir/openal_stripped.zip
# Extract stuff # Extract stuff
cd $libdir cd $libdir
[ -d irrlicht-$irrlicht_version ] || unzip -o $packagedir/irrlicht-$irrlicht_version.zip [ -d irrlicht ] || unzip -o $packagedir/irrlicht-$irrlicht_version.zip -d irrlicht
[ -d zlib ] || unzip -o $packagedir/zlib-$zlib_version.zip -d zlib [ -d zlib ] || unzip -o $packagedir/zlib-$zlib_version.zip -d zlib
[ -d libogg/include ] || 7z x -y -olibogg $packagedir/libogg-$ogg_version-dev.7z [ -d libogg ] || unzip -o $packagedir/libogg-$ogg_version.zip -d libogg
[ -d libogg/bin ] || 7z x -y -olibogg $packagedir/libogg-$ogg_version-dll.7z [ -d libvorbis ] || unzip -o $packagedir/libvorbis-$vorbis_version.zip -d libvorbis
[ -d libvorbis/include ] || 7z x -y -olibvorbis $packagedir/libvorbis-$vorbis_version-dev.7z [ -d libcurl ] || unzip -o $packagedir/curl-$curl_version.zip -d libcurl
[ -d libvorbis/bin ] || 7z x -y -olibvorbis $packagedir/libvorbis-$vorbis_version-dll.7z
[ -d libcurl ] || unzip -o $packagedir/libcurl-$curl_version.zip -d libcurl
[ -d gettext ] || unzip -o $packagedir/gettext-$gettext_version.zip -d gettext [ -d gettext ] || unzip -o $packagedir/gettext-$gettext_version.zip -d gettext
[ -d freetype ] || unzip -o $packagedir/libfreetype-$freetype_version.zip -d freetype [ -d freetype ] || unzip -o $packagedir/freetype2-$freetype_version.zip -d freetype
[ -d sqlite3 ] || unzip -o $packagedir/sqlite3-$sqlite3_version.zip -d sqlite3 [ -d sqlite3 ] || unzip -o $packagedir/sqlite3-$sqlite3_version.zip -d sqlite3
[ -d openal_stripped ] || unzip -o $packagedir/openal_stripped.zip [ -d openal_stripped ] || unzip -o $packagedir/openal_stripped.zip
[ -d luajit ] || unzip -o $packagedir/luajit-$luajit_version-static-win32.zip -d luajit [ -d luajit ] || unzip -o $packagedir/luajit-$luajit_version-static-win32.zip -d luajit
[ -d leveldb ] || unzip -o $packagedir/libleveldb-$leveldb_version-win32.zip -d leveldb [ -d leveldb ] || unzip -o $packagedir/libleveldb-$leveldb_version.zip -d leveldb
# Get minetest # Get minetest
cd $builddir cd $builddir
@ -107,14 +101,13 @@ cmake .. \
-DENABLE_FREETYPE=1 \ -DENABLE_FREETYPE=1 \
-DENABLE_LEVELDB=1 \ -DENABLE_LEVELDB=1 \
\ \
-DIRRLICHT_INCLUDE_DIR=$libdir/irrlicht-$irrlicht_version/include \ -DIRRLICHT_INCLUDE_DIR=$libdir/irrlicht/include \
-DIRRLICHT_LIBRARY=$libdir/irrlicht-$irrlicht_version/lib/Win32-gcc/libIrrlicht.dll.a \ -DIRRLICHT_LIBRARY=$libdir/irrlicht/lib/Win32-gcc/libIrrlicht.dll.a \
-DIRRLICHT_DLL=$libdir/irrlicht-$irrlicht_version/bin/Win32-gcc/Irrlicht.dll \ -DIRRLICHT_DLL=$libdir/irrlicht/bin/Win32-gcc/Irrlicht.dll \
\ \
-DZLIB_INCLUDE_DIR=$libdir/zlib/include \ -DZLIB_INCLUDE_DIR=$libdir/zlib/include \
-DZLIB_LIBRARIES=$libdir/zlib/lib/zlibwapi.dll.a \ -DZLIB_LIBRARIES=$libdir/zlib/lib/libz.dll.a \
-DZLIB_DLL=$libdir/zlib/bin/zlib1.dll \ -DZLIB_DLL=$libdir/zlib/bin/zlib1.dll \
-DZLIBWAPI_DLL=$libdir/zlib/bin/zlibwapi.dll \
\ \
-DLUA_INCLUDE_DIR=$libdir/luajit/include \ -DLUA_INCLUDE_DIR=$libdir/luajit/include \
-DLUA_LIBRARY=$libdir/luajit/libluajit.a \ -DLUA_LIBRARY=$libdir/luajit/libluajit.a \
@ -145,9 +138,9 @@ cmake .. \
-DGETTEXT_LIBRARY=$libdir/gettext/lib/libintl.dll.a \ -DGETTEXT_LIBRARY=$libdir/gettext/lib/libintl.dll.a \
\ \
-DFREETYPE_INCLUDE_DIR_freetype2=$libdir/freetype/include/freetype2 \ -DFREETYPE_INCLUDE_DIR_freetype2=$libdir/freetype/include/freetype2 \
-DFREETYPE_INCLUDE_DIR_ft2build=$libdir/freetype/include \ -DFREETYPE_INCLUDE_DIR_ft2build=$libdir/freetype/include/freetype2 \
-DFREETYPE_LIBRARY=$libdir/freetype/lib/libfreetype.dll.a \ -DFREETYPE_LIBRARY=$libdir/freetype/lib/libfreetype.dll.a \
-DFREETYPE_DLL=$libdir/freetype/bin/freetype6.dll \ -DFREETYPE_DLL=$libdir/freetype/bin/libfreetype-6.dll \
\ \
-DSQLITE3_INCLUDE_DIR=$libdir/sqlite3/include \ -DSQLITE3_INCLUDE_DIR=$libdir/sqlite3/include \
-DSQLITE3_LIBRARY=$libdir/sqlite3/lib/libsqlite3.dll.a \ -DSQLITE3_LIBRARY=$libdir/sqlite3/lib/libsqlite3.dll.a \

View File

@ -13,15 +13,15 @@ packagedir=$builddir/packages
libdir=$builddir/libs libdir=$builddir/libs
toolchain_file=$dir/toolchain_mingw64.cmake toolchain_file=$dir/toolchain_mingw64.cmake
irrlicht_version=1.8.1 irrlicht_version=1.8.4
ogg_version=1.3.1 ogg_version=1.3.2
vorbis_version=1.3.4 vorbis_version=1.3.5
curl_version=7.38.0 curl_version=7.50.3
gettext_version=0.18.2 gettext_version=0.18.2
freetype_version=2.5.3 freetype_version=2.7
sqlite3_version=3.8.7.4 sqlite3_version=3.14.2
luajit_version=2.0.3 luajit_version=2.0.3
leveldb_version=1.15 leveldb_version=1.18
zlib_version=1.2.8 zlib_version=1.2.8
mkdir -p $packagedir mkdir -p $packagedir
@ -38,12 +38,12 @@ cd $builddir
-c -O $packagedir/libogg-$ogg_version.zip -c -O $packagedir/libogg-$ogg_version.zip
[ -e $packagedir/libvorbis-$vorbis_version.zip ] || wget http://minetest.kitsunemimi.pw/libvorbis-$vorbis_version-win64.zip \ [ -e $packagedir/libvorbis-$vorbis_version.zip ] || wget http://minetest.kitsunemimi.pw/libvorbis-$vorbis_version-win64.zip \
-c -O $packagedir/libvorbis-$vorbis_version.zip -c -O $packagedir/libvorbis-$vorbis_version.zip
[ -e $packagedir/libcurl-$curl_version.zip ] || wget http://minetest.kitsunemimi.pw/libcurl-$curl_version-win64.zip \ [ -e $packagedir/curl-$curl_version.zip ] || wget http://minetest.kitsunemimi.pw/curl-$curl_version-win64.zip \
-c -O $packagedir/libcurl-$curl_version.zip -c -O $packagedir/curl-$curl_version.zip
[ -e $packagedir/gettext-$gettext_version.zip ] || wget http://minetest.kitsunemimi.pw/gettext-$gettext_version-win64.zip \ [ -e $packagedir/gettext-$gettext_version.zip ] || wget http://minetest.kitsunemimi.pw/gettext-$gettext_version-win64.zip \
-c -O $packagedir/gettext-$gettext_version.zip -c -O $packagedir/gettext-$gettext_version.zip
[ -e $packagedir/freetype-$freetype_version.zip ] || wget http://minetest.kitsunemimi.pw/libfreetype-$freetype_version-win64.zip \ [ -e $packagedir/freetype2-$freetype_version.zip ] || wget http://minetest.kitsunemimi.pw/freetype2-$freetype_version-win64.zip \
-c -O $packagedir/freetype-$freetype_version.zip -c -O $packagedir/freetype2-$freetype_version.zip
[ -e $packagedir/sqlite3-$sqlite3_version.zip ] || wget http://minetest.kitsunemimi.pw/sqlite3-$sqlite3_version-win64.zip \ [ -e $packagedir/sqlite3-$sqlite3_version.zip ] || wget http://minetest.kitsunemimi.pw/sqlite3-$sqlite3_version-win64.zip \
-c -O $packagedir/sqlite3-$sqlite3_version.zip -c -O $packagedir/sqlite3-$sqlite3_version.zip
[ -e $packagedir/luajit-$luajit_version.zip ] || wget http://minetest.kitsunemimi.pw/luajit-$luajit_version-static-win64.zip \ [ -e $packagedir/luajit-$luajit_version.zip ] || wget http://minetest.kitsunemimi.pw/luajit-$luajit_version-static-win64.zip \
@ -56,13 +56,13 @@ cd $builddir
# Extract stuff # Extract stuff
cd $libdir cd $libdir
[ -d irrlicht-$irrlicht_version ] || unzip -o $packagedir/irrlicht-$irrlicht_version.zip [ -d irrlicht ] || unzip -o $packagedir/irrlicht-$irrlicht_version.zip -d irrlicht
[ -d zlib ] || unzip -o $packagedir/zlib-$zlib_version.zip -d zlib [ -d zlib ] || unzip -o $packagedir/zlib-$zlib_version.zip -d zlib
[ -d libogg ] || unzip -o $packagedir/libogg-$ogg_version.zip -d libogg [ -d libogg ] || unzip -o $packagedir/libogg-$ogg_version.zip -d libogg
[ -d libvorbis ] || unzip -o $packagedir/libvorbis-$vorbis_version.zip -d libvorbis [ -d libvorbis ] || unzip -o $packagedir/libvorbis-$vorbis_version.zip -d libvorbis
[ -d libcurl ] || unzip -o $packagedir/libcurl-$curl_version.zip -d libcurl [ -d libcurl ] || unzip -o $packagedir/curl-$curl_version.zip -d libcurl
[ -d gettext ] || unzip -o $packagedir/gettext-$gettext_version.zip -d gettext [ -d gettext ] || unzip -o $packagedir/gettext-$gettext_version.zip -d gettext
[ -d freetype ] || unzip -o $packagedir/freetype-$freetype_version.zip -d freetype [ -d freetype ] || unzip -o $packagedir/freetype2-$freetype_version.zip -d freetype
[ -d sqlite3 ] || unzip -o $packagedir/sqlite3-$sqlite3_version.zip -d sqlite3 [ -d sqlite3 ] || unzip -o $packagedir/sqlite3-$sqlite3_version.zip -d sqlite3
[ -d openal_stripped ] || unzip -o $packagedir/openal_stripped.zip [ -d openal_stripped ] || unzip -o $packagedir/openal_stripped.zip
[ -d luajit ] || unzip -o $packagedir/luajit-$luajit_version.zip -d luajit [ -d luajit ] || unzip -o $packagedir/luajit-$luajit_version.zip -d luajit
@ -102,9 +102,9 @@ cmake .. \
-DENABLE_FREETYPE=1 \ -DENABLE_FREETYPE=1 \
-DENABLE_LEVELDB=1 \ -DENABLE_LEVELDB=1 \
\ \
-DIRRLICHT_INCLUDE_DIR=$libdir/irrlicht-$irrlicht_version/include \ -DIRRLICHT_INCLUDE_DIR=$libdir/irrlicht/include \
-DIRRLICHT_LIBRARY=$libdir/irrlicht-$irrlicht_version/lib/Win64-gcc/libIrrlicht.dll.a \ -DIRRLICHT_LIBRARY=$libdir/irrlicht/lib/Win64-gcc/libIrrlicht.dll.a \
-DIRRLICHT_DLL=$libdir/irrlicht-$irrlicht_version/bin/Win64-gcc/Irrlicht.dll \ -DIRRLICHT_DLL=$libdir/irrlicht/bin/Win64-gcc/Irrlicht.dll \
\ \
-DZLIB_INCLUDE_DIR=$libdir/zlib/include \ -DZLIB_INCLUDE_DIR=$libdir/zlib/include \
-DZLIB_LIBRARIES=$libdir/zlib/lib/libz.dll.a \ -DZLIB_LIBRARIES=$libdir/zlib/lib/libz.dll.a \
@ -131,6 +131,13 @@ cmake .. \
-DCURL_INCLUDE_DIR=$libdir/libcurl/include \ -DCURL_INCLUDE_DIR=$libdir/libcurl/include \
-DCURL_LIBRARY=$libdir/libcurl/lib/libcurl.dll.a \ -DCURL_LIBRARY=$libdir/libcurl/lib/libcurl.dll.a \
\ \
-DCUSTOM_GETTEXT_PATH=$libdir/gettext \
-DGETTEXT_MSGFMT=`which msgfmt` \
-DGETTEXT_DLL=$libdir/gettext/bin/libintl-8.dll \
-DGETTEXT_ICONV_DLL=$libdir/gettext/bin/libiconv-2.dll \
-DGETTEXT_INCLUDE_DIR=$libdir/gettext/include \
-DGETTEXT_LIBRARY=$libdir/gettext/lib/libintl.dll.a \
\
-DFREETYPE_INCLUDE_DIR_freetype2=$libdir/freetype/include/freetype2 \ -DFREETYPE_INCLUDE_DIR_freetype2=$libdir/freetype/include/freetype2 \
-DFREETYPE_INCLUDE_DIR_ft2build=$libdir/freetype/include/freetype2 \ -DFREETYPE_INCLUDE_DIR_ft2build=$libdir/freetype/include/freetype2 \
-DFREETYPE_LIBRARY=$libdir/freetype/lib/libfreetype.dll.a \ -DFREETYPE_LIBRARY=$libdir/freetype/lib/libfreetype.dll.a \
@ -142,14 +149,7 @@ cmake .. \
\ \
-DLEVELDB_INCLUDE_DIR=$libdir/leveldb/include \ -DLEVELDB_INCLUDE_DIR=$libdir/leveldb/include \
-DLEVELDB_LIBRARY=$libdir/leveldb/lib/libleveldb.dll.a \ -DLEVELDB_LIBRARY=$libdir/leveldb/lib/libleveldb.dll.a \
-DLEVELDB_DLL=$libdir/leveldb/bin/libleveldb.dll \ -DLEVELDB_DLL=$libdir/leveldb/bin/libleveldb.dll
\
-DCUSTOM_GETTEXT_PATH=$libdir/gettext \
-DGETTEXT_MSGFMT=`which msgfmt` \
-DGETTEXT_DLL=$libdir/gettext/bin/libintl-8.dll \
-DGETTEXT_ICONV_DLL=$libdir/gettext/bin/libiconv-2.dll \
-DGETTEXT_INCLUDE_DIR=$libdir/gettext/include \
-DGETTEXT_LIBRARY=$libdir/gettext/lib/libintl.dll.a
make package -j2 make package -j2

View File

@ -1,16 +1,8 @@
#!/bin/bash -e #!/bin/bash -e
if [[ $TRAVIS_OS_NAME == "linux" ]]; then if [[ $TRAVIS_OS_NAME == "linux" ]]; then
if [[ $CC == "clang" ]]; then
export PATH="/usr/bin/:$PATH"
sudo sh -c 'echo "deb http://ppa.launchpad.net/eudoxos/llvm-3.1/ubuntu precise main" >> /etc/apt/sources.list'
sudo apt-key adv --keyserver pool.sks-keyservers.net --recv-keys 92DE8183
sudo apt-get update
sudo apt-get install llvm-3.1
sudo apt-get install clang
fi
sudo apt-get update sudo apt-get update
sudo apt-get install p7zip-full sudo apt-get install p7zip-full $COMPILER
fi fi
if [[ $PLATFORM == "Unix" ]]; then if [[ $PLATFORM == "Unix" ]]; then
@ -25,7 +17,7 @@ if [[ $PLATFORM == "Unix" ]]; then
else else
brew update brew update
brew install freetype gettext hiredis irrlicht jpeg leveldb libogg libvorbis luajit brew install freetype gettext hiredis irrlicht jpeg leveldb libogg libvorbis luajit
brew upgrade postgresql #brew upgrade postgresql
fi fi
elif [[ $PLATFORM == "Win32" ]]; then elif [[ $PLATFORM == "Win32" ]]; then
wget http://minetest.kitsunemimi.pw/mingw_w64_i686_ubuntu12.04_4.9.1.7z -O mingw.7z wget http://minetest.kitsunemimi.pw/mingw_w64_i686_ubuntu12.04_4.9.1.7z -O mingw.7z

View File

@ -4,6 +4,10 @@ if [[ $PLATFORM == "Unix" ]]; then
mkdir -p travisbuild mkdir -p travisbuild
cd travisbuild || exit 1 cd travisbuild || exit 1
CMAKE_FLAGS='' CMAKE_FLAGS=''
if [[ $COMPILER == "g++-6" ]]; then
export CC=gcc-6
export CXX=g++-6
fi
# Clang builds with FreeType fail on Travis # Clang builds with FreeType fail on Travis
if [[ $CC == "clang" ]]; then if [[ $CC == "clang" ]]; then
CMAKE_FLAGS+=' -DENABLE_FREETYPE=FALSE' CMAKE_FLAGS+=' -DENABLE_FREETYPE=FALSE'