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

View File

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

View File

@ -19,4 +19,9 @@ core.EMERGE_FROM_DISK = 3
core.EMERGE_GENERATED = 4
-- constants.h
-- Size of mapblocks in nodes
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 d = {x = 0, y = 0, z = 0}
if def.paramtype2 == "wallmounted" then
d = core.wallmounted_to_dir(n.param2)
-- The fallback vector here is in case 'wallmounted to dir' is nil due
-- to voxelmanip placing a wallmounted node without resetting a
-- pre-existing param2 value that is out-of-range for wallmounted.
-- The fallback vector corresponds to param2 = 0.
d = core.wallmounted_to_dir(n.param2) or {x = 0, y = 1, z = 0}
else
d.y = -1
end

View File

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

View File

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

View File

@ -127,6 +127,11 @@ function core.register_item(name, itemdef)
fixed = {-1/8, -1/2, -1/8, 1/8, 1/2, 1/8},
}
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})
core.registered_nodes[itemdef.name] = itemdef
elseif itemdef.type == "craft" then

View File

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

View File

@ -73,7 +73,7 @@ local function get_formspec(tabview, name, tabdata)
if not file_exists(infofile) then
infofile = current_texture_path .. DIR_DELIM .. "info.txt"
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

View File

@ -561,13 +561,13 @@ freetype (Freetype fonts) bool true
# Path to TrueTypeFont or bitmap.
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 (Font shadow) int 1
# 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
@ -774,6 +774,15 @@ time_speed (Time speed) int 72
# Interval of saving important changes in the world, stated in seconds.
server_map_save_interval (Map save interval) float 5.3
# Set the maximum character length of a chat message sent by clients.
# chat_message_max_size int 500
# Limit a single player to send X messages per 10 seconds.
# chat_message_limit_per_10sec float 10.0
# Kick player if send more than X messages per 10 seconds.
# chat_message_limit_trigger_kick int 50
[**Physics]
movement_acceleration_default (Default acceleration) float 3

View File

@ -263,7 +263,17 @@ Textures can be grouped together by enclosing them in `(` and `)`.
Example: `cobble.png^(thing1.png^thing2.png)`
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
@ -308,6 +318,15 @@ Example:
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`
Brightens the texture.
@ -351,7 +370,7 @@ Example:
default_stone.png^[transformFXR90
#### `[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.
@ -1450,6 +1469,15 @@ examples.
* `fixed_size`: `true`/`false` (optional)
* deprecated: `invsize[<W>,<H>;]`
#### `container[<X>,<Y>]`
* Start of a container block, moves all physical elements in the container by (X, Y)
* Must have matching container_end
* Containers can be nested, in which case the offsets are added
(child containers are relative to parent containers)
#### `container_end[]`
* End of a container, following elements are no longer relative to this container
#### `list[<inventory location>;<list name>;<X>,<Y>;<W>,<H>;]`
* Show an inventory list
@ -2594,13 +2622,17 @@ These functions return the leftover itemstack.
the creative mode setting, and checks for "sneak" to set the `invert_wall`
parameter.
* `minetest.forceload_block(pos)`
* `minetest.forceload_block(pos[, transient])`
* forceloads the position `pos`.
* returns `true` if area could be forceloaded
* Please note that forceloaded areas are saved when the server restarts.
* If `transient` is `false` or absent, the forceload will be persistent
(saved between server runs). If `true`, the forceload will be transient
(not saved between server runs).
* `minetest.forceload_free_block(pos)`
* `minetest.forceload_free_block(pos[, transient])`
* stops forceloading the position `pos`
* If `transient` is `false` or absent, frees a persistent forceload.
If `true`, frees a transient forceload.
* `minetest.request_insecure_environment()`: returns an environment containing
insecure functions if the calling mod has been listed as trusted in the
@ -2886,6 +2918,7 @@ chosen for you.
#### Methods
* `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.
Returns nil if specified area id does not exist.
* `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
what's copied.
@ -3328,13 +3361,15 @@ Registered entities
* It has the member `.object`, which is an `ObjectRef` pointing to the object
* The original prototype stuff is visible directly via a metatable
* Callbacks:
* `on_activate(self, staticdata)`
* `on_activate(self, staticdata, dtime_s)`
* 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)`
* Called on every server tick, after movement and collision processing.
`dtime` is usually 0.1 seconds, as per the `dedicated_server_step` setting
`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.
* Note that you probably want to handle most punches using the
automatic armor group system.
@ -3462,7 +3497,7 @@ Definition tables
on_activate = function(self, staticdata, dtime_s),
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),
get_staticdata = function(self),
-- ^ 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. ]]
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
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
node_box = {type="regular"}, -- See "Node boxes"
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"
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,
-- ^ 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.
@ -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.
-- ^ This parameter refers to the `y` position of the decoration base, so
-- 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 for all decoration types.
-- ^ "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,
-- ^ Number of nodes the decoration can be at maximum.
-- ^ 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 = "foobar.mts",

View File

@ -655,7 +655,7 @@
# font_path = fonts/liberationsans.ttf
# type: int
# font_size = 15
# font_size = 16
# Font shadow offset, if 0 then shadow will not be drawn.
# type: int
@ -663,7 +663,7 @@
# Font shadow alpha (opaqueness, between 0 and 255).
# type: int min: 0 max: 255
# font_shadow_alpha = 128
# font_shadow_alpha = 127
# type: path
# mono_font_path = fonts/liberationmono.ttf
@ -933,6 +933,18 @@
# type: float
# server_map_save_interval = 5.3
# Set the maximum character length of a chat message sent by clients. (0 to disable)
# type: integer
# chat_message_max_size = 500
# Limit a single player to send X messages per 10 seconds. (0 to disable)
# type: float
# chat_message_limit_per_10sec = 8.0
# Kick player if send more than X messages per 10 seconds. (0 to disable)
# type: integer
# chat_message_limit_trigger_kick = 50
### Physics
# type: float
@ -1099,6 +1111,25 @@
# type: int
# num_emerge_threads = 1
#### Noise parameters and formats
# Noise parameters can be specified as a set of positional values, for example:
# Offset, scale, (spread factors), seed offset, number of octaves, persistence, lacunarity
# mgv6_np_terrain_base = -4, 20, (250, 250, 250), 82341, 5, 0.6, 2.0
# Or the group format can be used instead, for example:
# mgv6_np_terrain_base = {
# offset = -4,
# scale = 20,
# spread = (250, 250, 250),
# seed = 82341,
# octaves = 5,
# persistence = 0.6,
# lacunarity = 2.0,
# flags = "defaults"
# }
# Only the group format supports noise flags which are needed for eased noise.
# Mgv5 uses eased noise for np_ground so this is shown in group format below.
# Noise parameters for biome API temperature, humidity and biome blend.
# type: noise_params
# mg_biome_np_heat = 50, 50, (750, 750, 750), 5349, 3, 0.5, 2.0
@ -1133,6 +1164,20 @@
# type: noise_params
# mgv5_np_cave2 = 0, 12, (50, 50, 50), 10325, 4, 0.5, 2.0
# Noise parameters in group format, unsupported by advanced settings
# menu but settable in minetest.conf.
# See documentation of noise parameter formats above.
# mgv5_np_ground = {
# offset = 0,
# scale = 40,
# spread = (80, 80, 80),
# seed = 983240,
# octaves = 4,
# persistence = 0.55,
# lacunarity = 2.0,
# flags = "eased"
# }
#### Mapgen v6
# Map generation attributes specific to Mapgen v6.
@ -1490,7 +1535,7 @@
# profiler.default_report_format = txt
# The file path relative to your worldpath in which profiles will be saved to.
#
#
# type: string
# profiler.report_path = ""

View File

@ -3,6 +3,7 @@ cmake_minimum_required(VERSION 2.6)
project(minetest)
INCLUDE(CheckIncludeFiles)
INCLUDE(CheckLibraryExists)
# Add custom SemiDebug build mode
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"
CACHE PATH "Zlib include directory")
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"
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"
CACHE PATH "irrlicht dir")
if(USE_FREETYPE)
@ -536,6 +538,7 @@ set(client_SRCS
sky.cpp
wieldmesh.cpp
${client_SCRIPT_SRCS}
${UNITTEST_CLIENT_SRCS}
)
list(SORT client_SRCS)
@ -722,8 +725,14 @@ else()
set(OTHER_FLAGS "${OTHER_FLAGS} -Wsign-compare")
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)
set(OTHER_FLAGS "-mthreads -fexceptions")
set(OTHER_FLAGS "${OTHER_FLAGS} -mthreads -fexceptions")
endif()
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 detached inventories
for (std::map<std::string, Inventory*>::iterator
for (UNORDERED_MAP<std::string, Inventory*>::iterator
i = m_detached_inventories.begin();
i != m_detached_inventories.end(); ++i) {
delete i->second;
@ -1437,7 +1437,7 @@ Inventory* Client::getInventory(const InventoryLocation &loc)
break;
case InventoryLocation::DETACHED:
{
if(m_detached_inventories.count(loc.name) == 0)
if (m_detached_inventories.count(loc.name) == 0)
return NULL;
return m_detached_inventories[loc.name];
}

View File

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

View File

@ -948,11 +948,10 @@ video::ITexture* TextureSource::generateTextureFromMesh(
video::IImage* TextureSource::generateImage(const std::string &name)
{
/*
Get the base image
*/
// Get the base image
const char separator = '^';
const char escape = '\\';
const char paren_open = '(';
const char paren_close = ')';
@ -960,7 +959,9 @@ video::IImage* TextureSource::generateImage(const std::string &name)
s32 last_separator_pos = -1;
u8 paren_bal = 0;
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:
if (paren_bal == 0) {
last_separator_pos = i;
@ -1028,10 +1029,12 @@ video::IImage* TextureSource::generateImage(const std::string &name)
return NULL;
}
core::dimension2d<u32> dim = tmp->getDimension();
if (!baseimg)
baseimg = driver->createImage(video::ECF_A8R8G8B8, dim);
blit_with_alpha(tmp, baseimg, v2s32(0, 0), v2s32(0, 0), dim);
tmp->drop();
if (baseimg) {
blit_with_alpha(tmp, baseimg, v2s32(0, 0), v2s32(0, 0), dim);
tmp->drop();
} else {
baseimg = tmp;
}
} else if (!generateImagePart(last_part_of_name, baseimg)) {
// Generate image according to part of name
errorstream << "generateImage(): "
@ -1099,9 +1102,27 @@ video::IImage * Align2Npot2(video::IImage * image,
#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,
video::IImage *& baseimg)
{
const char escape = '\\'; // same as in generateImage()
video::IVideoDriver* driver = m_device->getVideoDriver();
sanity_check(driver);
@ -1251,7 +1272,7 @@ bool TextureSource::generateImagePart(std::string part_of_name,
}
/*
[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"))
{
@ -1259,7 +1280,6 @@ bool TextureSource::generateImagePart(std::string part_of_name,
sf.next(":");
u32 w0 = stoi(sf.next("x"));
u32 h0 = stoi(sf.next(":"));
//infostream<<"combined w="<<w0<<" h="<<h0<<std::endl;
core::dimension2d<u32> dim(w0,h0);
if (baseimg == NULL) {
baseimg = driver->createImage(video::ECF_A8R8G8B8, dim);
@ -1268,11 +1288,11 @@ bool TextureSource::generateImagePart(std::string part_of_name,
while (sf.at_end() == false) {
u32 x = 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
<<"\" to combined ("<<x<<","<<y<<")"
<<std::endl;
video::IImage *img = m_sourcecache.getOrLoad(filename, m_device);
video::IImage *img = generateImage(filename);
if (img) {
core::dimension2d<u32> dim = img->getDimension();
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"))
{
@ -1309,7 +1329,7 @@ bool TextureSource::generateImagePart(std::string part_of_name,
brighten(baseimg);
}
/*
"[noalpha"
[noalpha
Make image completely opaque.
Used for the leaves texture when in old leaves mode, so
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.
*/
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.
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);
sf.next(":");
u32 percent = stoi(sf.next(":"));
std::string filename = sf.next(":");
//infostream<<"power part "<<percent<<"%% of "<<filename<<std::endl;
std::string filename = unescape_string(sf.next_esc(":", escape), escape);
if (baseimg == NULL)
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)
{
core::dimension2d<u32> dim = img->getDimension();
@ -1628,9 +1647,9 @@ bool TextureSource::generateImagePart(std::string part_of_name,
}
Strfnd sf(part_of_name);
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) {
apply_mask(img, baseimg, v2s32(0, 0), v2s32(0, 0),
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);
}
/*
[applyfiltersformesh
Internal modifier
*/
else if (str_starts_with(part_of_name, "[applyfiltersformesh"))
{
// 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 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));
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

View File

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

View File

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

View File

@ -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
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:
// 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
@ -160,7 +181,7 @@ int axisAlignedCollision(
// Helper function:
// Checks if moving the movingbox up by the given distance would hit a ceiling.
bool wouldCollideWithCeiling(
const std::vector<aabb3f> &staticboxes,
const std::vector<NearbyCollisionInfo> &cinfo,
const aabb3f &movingbox,
f32 y_increase, f32 d)
{
@ -168,12 +189,10 @@ bool wouldCollideWithCeiling(
assert(y_increase >= 0); // pre-condition
for(std::vector<aabb3f>::const_iterator
i = staticboxes.begin();
i != staticboxes.end(); ++i)
{
const aabb3f& staticbox = *i;
if((movingbox.MaxEdge.Y - d <= staticbox.MinEdge.Y) &&
for (std::vector<NearbyCollisionInfo>::const_iterator it = cinfo.begin();
it != cinfo.end(); ++it) {
const aabb3f &staticbox = it->box;
if ((movingbox.MaxEdge.Y - d <= staticbox.MinEdge.Y) &&
(movingbox.MaxEdge.Y + y_increase > staticbox.MinEdge.Y) &&
(movingbox.MinEdge.X < staticbox.MaxEdge.X) &&
(movingbox.MaxEdge.X > staticbox.MinEdge.X) &&
@ -234,12 +253,7 @@ collisionMoveResult collisionMoveSimple(Environment *env, IGameDef *gamedef,
/*
Collect node boxes in movement range
*/
std::vector<aabb3f> cboxes;
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;
std::vector<NearbyCollisionInfo> cinfo;
{
//TimeTaker tt2("collisionMoveSimple collect boxes");
ScopeProfiler sp(g_profiler, "collisionMoveSimple collect boxes avg", SPT_AVG);
@ -318,23 +332,13 @@ collisionMoveResult collisionMoveSimple(Environment *env, IGameDef *gamedef,
aabb3f box = *i;
box.MinEdge += v3f(x, y, z)*BS;
box.MaxEdge += v3f(x, y, z)*BS;
cboxes.push_back(box);
is_unloaded.push_back(false);
is_step_up.push_back(false);
bouncy_values.push_back(n_bouncy_value);
node_positions.push_back(p);
is_object.push_back(false);
cinfo.push_back(NearbyCollisionInfo(false,
false, n_bouncy_value, p, box));
}
}
else {
} else {
// Collide with unloaded nodes
aabb3f box = getNodeBox(p, BS);
cboxes.push_back(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);
cinfo.push_back(NearbyCollisionInfo(true, false, 0, p, box));
}
}
@ -352,7 +356,7 @@ collisionMoveResult collisionMoveSimple(Environment *env, IGameDef *gamedef,
ScopeProfiler sp(g_profiler, "collisionMoveSimple objects avg", SPT_AVG);
//TimeTaker tt3("collisionMoveSimple collect object boxes");
/* add object boxes to cboxes */
/* add object boxes to cinfo */
std::vector<ActiveObject*> objects;
#ifndef SERVER
@ -392,23 +396,12 @@ collisionMoveResult collisionMoveSimple(Environment *env, IGameDef *gamedef,
aabb3f object_collisionbox;
if (object->getCollisionBox(&object_collisionbox) &&
object->collideWithObjects()) {
cboxes.push_back(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);
cinfo.push_back(NearbyCollisionInfo(false, true, 0, v3s16(), object_collisionbox));
}
}
}
} //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
*/
@ -448,15 +441,16 @@ collisionMoveResult collisionMoveSimple(Environment *env, IGameDef *gamedef,
/*
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.
if(is_step_up[boxindex])
if (box_info.is_step_up)
continue;
// Find nearest collision of the two boxes (raytracing-like)
f32 dtime_tmp;
int collided = axisAlignedCollision(
cboxes[boxindex], movingbox, *speed_f, d, &dtime_tmp);
int collided = axisAlignedCollision(box_info.box,
movingbox, *speed_f, d, &dtime_tmp);
if (collided == -1 || dtime_tmp >= nearest_dtime)
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
} else {
// Otherwise, a collision occurred.
const aabb3f& cbox = cboxes[nearest_boxindex];
NearbyCollisionInfo &nearest_info = cinfo[nearest_boxindex];
const aabb3f& cbox = nearest_info.box;
// Check for stairs.
bool step_up = (nearest_collided != 1) && // must not be Y direction
(movingbox.MinEdge.Y < cbox.MaxEdge.Y) &&
(movingbox.MinEdge.Y + stepheight > cbox.MaxEdge.Y) &&
(!wouldCollideWithCeiling(cboxes, movingbox,
(!wouldCollideWithCeiling(cinfo, movingbox,
cbox.MaxEdge.Y - movingbox.MinEdge.Y,
d));
// Get bounce multiplier
bool bouncy = (bouncy_values[nearest_boxindex] >= 1);
float bounce = -(float)bouncy_values[nearest_boxindex] / 100.0;
bool bouncy = (nearest_info.bouncy >= 1);
float bounce = -(float)nearest_info.bouncy / 100.0;
// Move to the point of collision and reduce dtime by nearest_dtime
if (nearest_dtime < 0) {
@ -503,39 +497,38 @@ collisionMoveResult collisionMoveSimple(Environment *env, IGameDef *gamedef,
}
bool is_collision = true;
if (is_unloaded[nearest_boxindex])
if (nearest_info.is_unloaded)
is_collision = false;
CollisionInfo info;
if (is_object[nearest_boxindex])
if (nearest_info.is_object)
info.type = COLLISION_OBJECT;
else
info.type = COLLISION_NODE;
info.node_p = node_positions[nearest_boxindex];
info.node_p = nearest_info.position;
info.bouncy = bouncy;
info.old_speed = *speed_f;
// Set the speed component that caused the collision to zero
if (step_up) {
// Special case: Handle stairs
is_step_up[nearest_boxindex] = true;
nearest_info.is_step_up = true;
is_collision = false;
} else if(nearest_collided == 0) { // X
} else if (nearest_collided == 0) { // X
if (fabs(speed_f->X) > BS * 3)
speed_f->X *= bounce;
else
speed_f->X = 0;
result.collides = true;
result.collides_xz = true;
}
else if(nearest_collided == 1) { // Y
if (fabs(speed_f->Y) > BS * 3)
} else if (nearest_collided == 1) { // Y
if(fabs(speed_f->Y) > BS * 3)
speed_f->Y *= bounce;
else
speed_f->Y = 0;
result.collides = true;
} else if(nearest_collided == 2) { // Z
} else if (nearest_collided == 2) { // Z
if (fabs(speed_f->Z) > BS * 3)
speed_f->Z *= bounce;
else
@ -560,8 +553,9 @@ collisionMoveResult collisionMoveSimple(Environment *env, IGameDef *gamedef,
aabb3f box = box_0;
box.MinEdge += *pos_f;
box.MaxEdge += *pos_f;
for (u32 boxindex = 0; boxindex < cboxes.size(); boxindex++) {
const aabb3f& cbox = cboxes[boxindex];
for (u32 boxindex = 0; boxindex < cinfo.size(); boxindex++) {
NearbyCollisionInfo &box_info = cinfo[boxindex];
const aabb3f &cbox = box_info.box;
/*
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 &&
cbox.MaxEdge.Z - d > box.MinEdge.Z &&
cbox.MinEdge.Z + d < box.MaxEdge.Z) {
if (is_step_up[boxindex]) {
pos_f->Y += (cbox.MaxEdge.Y - box.MinEdge.Y);
if (box_info.is_step_up) {
pos_f->Y += cbox.MaxEdge.Y - box.MinEdge.Y;
box = box_0;
box.MinEdge += *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) {
result.touching_ground = true;
if (is_object[boxindex])
if (box_info.is_object)
result.standing_on_object = true;
if (is_unloaded[boxindex])
if (box_info.is_unloaded)
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)
#define TTF_DEFAULT_FONT_SIZE (18)
#else
#define TTF_DEFAULT_FONT_SIZE (15)
#define TTF_DEFAULT_FONT_SIZE (16)
#endif
#define DEFAULT_FONT_SIZE (10)

View File

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

View File

@ -90,7 +90,7 @@ private:
int m_animation_speed;
int m_animation_blend;
bool m_animation_loop;
std::map<std::string, core::vector2d<v3f> > m_bone_position; // stores position and rotation for each bone name
UNORDERED_MAP<std::string, core::vector2d<v3f> > m_bone_position; // stores position and rotation for each bone name
std::string m_attachment_bone;
v3f m_attachment_position;
v3f m_attachment_rotation;

View File

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

View File

@ -213,7 +213,7 @@ void set_default_settings(Settings *settings)
settings->setDefault("freetype", "true");
settings->setDefault("font_path", porting::getDataPath("fonts" DIR_DELIM "liberationsans.ttf"));
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("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("max_objects_per_block", "49");
settings->setDefault("server_map_save_interval", "5.3");
settings->setDefault("chat_message_max_size", "500");
settings->setDefault("chat_message_limit_per_10sec", "8.0");
settings->setDefault("chat_message_limit_trigger_kick", "50");
settings->setDefault("sqlite_synchronous", "2");
settings->setDefault("full_block_send_enable_min_time_from_building", "2.0");
settings->setDefault("dedicated_server_step", "0.1");

View File

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

View File

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

View File

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

View File

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

View File

@ -605,7 +605,7 @@ public:
void draw(s32 x_left, s32 y_bottom, video::IVideoDriver *driver,
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();
k != m_log.end(); ++k) {
@ -615,8 +615,7 @@ public:
i != piece.values.end(); ++i) {
const std::string &id = i->first;
const float &value = i->second;
std::map<std::string, Meta>::iterator j =
m_meta.find(id);
UNORDERED_MAP<std::string, Meta>::iterator j = m_meta.find(id);
if (j == m_meta.end()) {
m_meta[id] = Meta(value);
@ -643,7 +642,7 @@ public:
sizeof(usable_colors) / sizeof(*usable_colors);
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) {
Meta &meta = i->second;
video::SColor color(255, 200, 200, 200);
@ -659,7 +658,7 @@ public:
s32 textx2 = textx + 200 - 15;
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) {
const std::string &id = i->first;
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;
}
void GUIFormSpecMenu::parseContainer(parserData* data, std::string element)
{
std::vector<std::string> parts = split(element, ',');
if (parts.size() >= 2) {
if (parts[1].find(';') != std::string::npos)
parts[1] = parts[1].substr(0, parts[1].find(';'));
container_stack.push(pos_offset);
pos_offset.X += MYMAX(0, stof(parts[0]));
pos_offset.Y += MYMAX(0, stof(parts[1]));
return;
}
errorstream<< "Invalid container start element (" << parts.size() << "): '" << element << "'" << std::endl;
}
void GUIFormSpecMenu::parseContainerEnd(parserData* data)
{
if (container_stack.empty()) {
errorstream<< "Invalid container end element, no matching container start element" << std::endl;
} else {
pos_offset = container_stack.top();
container_stack.pop();
}
}
void GUIFormSpecMenu::parseList(parserData* data,std::string element)
{
if (m_gamedef == 0) {
@ -309,7 +335,7 @@ void GUIFormSpecMenu::parseList(parserData* data,std::string element)
else
loc.deSerialize(location);
v2s32 pos = padding + AbsoluteRect.UpperLeftCorner;
v2s32 pos = padding + AbsoluteRect.UpperLeftCorner + pos_offset * spacing;
pos.X += stof(v_pos[0]) * (float)spacing.X;
pos.Y += stof(v_pos[1]) * (float)spacing.Y;
@ -386,7 +412,7 @@ void GUIFormSpecMenu::parseCheckbox(parserData* data,std::string element)
MY_CHECKPOS("checkbox",0);
v2s32 pos = padding;
v2s32 pos = padding + pos_offset * spacing;
pos.X += stof(v_pos[0]) * (float) spacing.X;
pos.Y += stof(v_pos[1]) * (float) spacing.Y;
@ -437,7 +463,7 @@ void GUIFormSpecMenu::parseScrollBar(parserData* data, std::string element)
MY_CHECKPOS("scrollbar",0);
v2s32 pos = padding;
v2s32 pos = padding + pos_offset * spacing;
pos.X += stof(v_pos[0]) * (float) spacing.X;
pos.Y += stof(v_pos[1]) * (float) spacing.Y;
@ -495,10 +521,10 @@ void GUIFormSpecMenu::parseImage(parserData* data,std::string element)
std::vector<std::string> v_geom = split(parts[1],',');
std::string name = unescape_string(parts[2]);
MY_CHECKPOS("image",0);
MY_CHECKGEOM("image",1);
MY_CHECKPOS("image", 0);
MY_CHECKGEOM("image", 1);
v2s32 pos = padding + AbsoluteRect.UpperLeftCorner;
v2s32 pos = padding + AbsoluteRect.UpperLeftCorner + pos_offset * spacing;
pos.X += stof(v_pos[0]) * (float) spacing.X;
pos.Y += stof(v_pos[1]) * (float) spacing.Y;
@ -506,23 +532,21 @@ void GUIFormSpecMenu::parseImage(parserData* data,std::string element)
geom.X = stof(v_geom[0]) * (float)imgsize.X;
geom.Y = stof(v_geom[1]) * (float)imgsize.Y;
if(!data->explicit_size)
if (!data->explicit_size)
warningstream<<"invalid use of image without a size[] element"<<std::endl;
m_images.push_back(ImageDrawSpec(name, pos, geom));
return;
}
if (parts.size() == 2) {
} else if (parts.size() == 2) {
std::vector<std::string> v_pos = split(parts[0],',');
std::string name = unescape_string(parts[1]);
MY_CHECKPOS("image",0);
MY_CHECKPOS("image", 0);
v2s32 pos = padding + AbsoluteRect.UpperLeftCorner;
v2s32 pos = padding + AbsoluteRect.UpperLeftCorner + pos_offset * spacing;
pos.X += stof(v_pos[0]) * (float) spacing.X;
pos.Y += stof(v_pos[1]) * (float) spacing.Y;
if(!data->explicit_size)
if (!data->explicit_size)
warningstream<<"invalid use of image without a size[] element"<<std::endl;
m_images.push_back(ImageDrawSpec(name, pos));
return;
@ -544,7 +568,7 @@ void GUIFormSpecMenu::parseItemImage(parserData* data,std::string element)
MY_CHECKPOS("itemimage",0);
MY_CHECKGEOM("itemimage",1);
v2s32 pos = padding + AbsoluteRect.UpperLeftCorner;
v2s32 pos = padding + AbsoluteRect.UpperLeftCorner + pos_offset * spacing;
pos.X += stof(v_pos[0]) * (float) spacing.X;
pos.Y += stof(v_pos[1]) * (float) spacing.Y;
@ -576,7 +600,7 @@ void GUIFormSpecMenu::parseButton(parserData* data,std::string element,
MY_CHECKPOS("button",0);
MY_CHECKGEOM("button",1);
v2s32 pos = padding;
v2s32 pos = padding + pos_offset * spacing;
pos.X += stof(v_pos[0]) * (float)spacing.X;
pos.Y += stof(v_pos[1]) * (float)spacing.Y;
@ -629,9 +653,9 @@ void GUIFormSpecMenu::parseBackground(parserData* data,std::string element)
MY_CHECKPOS("background",0);
MY_CHECKGEOM("background",1);
v2s32 pos = padding + AbsoluteRect.UpperLeftCorner;
pos.X += stof(v_pos[0]) * (float)spacing.X - ((float)spacing.X-(float)imgsize.X)/2;
pos.Y += stof(v_pos[1]) * (float)spacing.Y - ((float)spacing.Y-(float)imgsize.Y)/2;
v2s32 pos = padding + AbsoluteRect.UpperLeftCorner + pos_offset * spacing;
pos.X += stof(v_pos[0]) * (float)spacing.X - ((float)spacing.X - (float)imgsize.X)/2;
pos.Y += stof(v_pos[1]) * (float)spacing.Y - ((float)spacing.Y - (float)imgsize.Y)/2;
v2s32 geom;
geom.X = stof(v_geom[0]) * (float)spacing.X;
@ -705,7 +729,7 @@ void GUIFormSpecMenu::parseTable(parserData* data,std::string element)
MY_CHECKPOS("table",0);
MY_CHECKGEOM("table",1);
v2s32 pos = padding;
v2s32 pos = padding + pos_offset * spacing;
pos.X += stof(v_pos[0]) * (float)spacing.X;
pos.Y += stof(v_pos[1]) * (float)spacing.Y;
@ -776,7 +800,7 @@ void GUIFormSpecMenu::parseTextList(parserData* data,std::string element)
MY_CHECKPOS("textlist",0);
MY_CHECKGEOM("textlist",1);
v2s32 pos = padding;
v2s32 pos = padding + pos_offset * spacing;
pos.X += stof(v_pos[0]) * (float)spacing.X;
pos.Y += stof(v_pos[1]) * (float)spacing.Y;
@ -841,7 +865,7 @@ void GUIFormSpecMenu::parseDropDown(parserData* data,std::string element)
MY_CHECKPOS("dropdown",0);
v2s32 pos = padding;
v2s32 pos = padding + pos_offset * spacing;
pos.X += stof(v_pos[0]) * (float)spacing.X;
pos.Y += stof(v_pos[1]) * (float)spacing.Y;
@ -905,7 +929,7 @@ void GUIFormSpecMenu::parsePwdField(parserData* data,std::string element)
MY_CHECKPOS("pwdfield",0);
MY_CHECKGEOM("pwdfield",1);
v2s32 pos;
v2s32 pos = pos_offset * spacing;
pos.X += stof(v_pos[0]) * (float)spacing.X;
pos.Y += stof(v_pos[1]) * (float)spacing.Y;
@ -975,7 +999,7 @@ void GUIFormSpecMenu::parseSimpleField(parserData* data,
if(data->explicit_size)
warningstream<<"invalid use of unpositioned \"field\" in inventory"<<std::endl;
v2s32 pos = padding + AbsoluteRect.UpperLeftCorner;
v2s32 pos = padding + AbsoluteRect.UpperLeftCorner + pos_offset * spacing;
pos.Y = ((m_fields.size()+2)*60);
v2s32 size = DesiredRect.getSize();
@ -1058,9 +1082,9 @@ void GUIFormSpecMenu::parseTextArea(parserData* data,
MY_CHECKPOS(type,0);
MY_CHECKGEOM(type,1);
v2s32 pos;
pos.X = stof(v_pos[0]) * (float) spacing.X;
pos.Y = stof(v_pos[1]) * (float) spacing.Y;
v2s32 pos = pos_offset * spacing;
pos.X += stof(v_pos[0]) * (float) spacing.X;
pos.Y += stof(v_pos[1]) * (float) spacing.Y;
v2s32 geom;
@ -1185,7 +1209,7 @@ void GUIFormSpecMenu::parseLabel(parserData* data,std::string element)
MY_CHECKPOS("label",0);
v2s32 pos = padding;
v2s32 pos = padding + pos_offset * spacing;
pos.X += stof(v_pos[0]) * (float)spacing.X;
pos.Y += (stof(v_pos[1]) + 7.0/30.0) * (float)spacing.Y;
@ -1242,7 +1266,7 @@ void GUIFormSpecMenu::parseVertLabel(parserData* data,std::string element)
MY_CHECKPOS("vertlabel",1);
v2s32 pos = padding;
v2s32 pos = padding + pos_offset * spacing;
pos.X += stof(v_pos[0]) * (float)spacing.X;
pos.Y += stof(v_pos[1]) * (float)spacing.Y;
@ -1296,7 +1320,7 @@ void GUIFormSpecMenu::parseImageButton(parserData* data,std::string element,
MY_CHECKPOS("imagebutton",0);
MY_CHECKGEOM("imagebutton",1);
v2s32 pos = padding;
v2s32 pos = padding + pos_offset * spacing;
pos.X += stof(v_pos[0]) * (float)spacing.X;
pos.Y += stof(v_pos[1]) * (float)spacing.Y;
v2s32 geom;
@ -1401,7 +1425,7 @@ void GUIFormSpecMenu::parseTabHeader(parserData* data,std::string element)
spec.ftype = f_TabHeader;
v2s32 pos(0,0);
v2s32 pos = pos_offset * spacing;
pos.X += stof(v_pos[0]) * (float)spacing.X;
pos.Y += stof(v_pos[1]) * (float)spacing.Y - m_btn_height * 2;
v2s32 geom;
@ -1466,7 +1490,7 @@ void GUIFormSpecMenu::parseItemImageButton(parserData* data,std::string element)
MY_CHECKPOS("itemimagebutton",0);
MY_CHECKGEOM("itemimagebutton",1);
v2s32 pos = padding;
v2s32 pos = padding + pos_offset * spacing;
pos.X += stof(v_pos[0]) * (float)spacing.X;
pos.Y += stof(v_pos[1]) * (float)spacing.Y;
v2s32 geom;
@ -1504,7 +1528,7 @@ void GUIFormSpecMenu::parseItemImageButton(parserData* data,std::string element)
rect+=data->basepos-padding;
spec.rect=rect;
m_fields.push_back(spec);
pos = padding + AbsoluteRect.UpperLeftCorner;
pos = padding + AbsoluteRect.UpperLeftCorner + pos_offset * spacing;
pos.X += stof(v_pos[0]) * (float) spacing.X;
pos.Y += stof(v_pos[1]) * (float) spacing.Y;
m_itemimages.push_back(ImageDrawSpec("", item_name, e, pos, geom));
@ -1527,7 +1551,7 @@ void GUIFormSpecMenu::parseBox(parserData* data,std::string element)
MY_CHECKPOS("box",0);
MY_CHECKGEOM("box",1);
v2s32 pos = padding + AbsoluteRect.UpperLeftCorner;
v2s32 pos = padding + AbsoluteRect.UpperLeftCorner + pos_offset * spacing;
pos.X += stof(v_pos[0]) * (float) spacing.X;
pos.Y += stof(v_pos[1]) * (float) spacing.Y;
@ -1689,8 +1713,18 @@ void GUIFormSpecMenu::parseElement(parserData* data, std::string element)
std::string type = trim(parts[0]);
std::string description = trim(parts[1]);
if (type == "container") {
parseContainer(data, description);
return;
}
if (type == "container_end") {
parseContainerEnd(data);
return;
}
if (type == "list") {
parseList(data,description);
parseList(data, description);
return;
}
@ -1700,22 +1734,22 @@ void GUIFormSpecMenu::parseElement(parserData* data, std::string element)
}
if (type == "checkbox") {
parseCheckbox(data,description);
parseCheckbox(data, description);
return;
}
if (type == "image") {
parseImage(data,description);
parseImage(data, description);
return;
}
if (type == "item_image") {
parseItemImage(data,description);
parseItemImage(data, description);
return;
}
if ((type == "button") || (type == "button_exit")) {
parseButton(data,description,type);
if (type == "button" || type == "button_exit") {
parseButton(data, description, type);
return;
}
@ -2036,10 +2070,16 @@ void GUIFormSpecMenu::regenerateGui(v2u32 screensize)
gui::IGUIFont *old_font = skin->getFont();
skin->setFont(m_font);
pos_offset = v2s32();
for (; i< elements.size(); i++) {
parseElement(&mydata, elements[i]);
}
if (!container_stack.empty()) {
errorstream << "Invalid formspec string: container was never closed!"
<< std::endl;
}
// If there are fields without explicit size[], add a "Proceed"
// button and adjust size to fit all the fields.
if (m_fields.size() && !mydata.explicit_size) {

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

@ -26,12 +26,12 @@ with this program; if not, write to the Free Software Foundation, Inc.,
#include "util/numeric.h"
FlagDesc flagdesc_deco[] = {
{"place_center_x", DECO_PLACE_CENTER_X},
{"place_center_y", DECO_PLACE_CENTER_Y},
{"place_center_z", DECO_PLACE_CENTER_Z},
{"place_center_x", DECO_PLACE_CENTER_X},
{"place_center_y", DECO_PLACE_CENTER_Y},
{"place_center_z", DECO_PLACE_CENTER_Z},
{"force_placement", DECO_FORCE_PLACEMENT},
{"liquid_surface", DECO_LIQUID_SURFACE},
{NULL, 0}
{"liquid_surface", DECO_LIQUID_SURFACE},
{NULL, 0}
};
@ -82,6 +82,56 @@ Decoration::~Decoration()
void Decoration::resolveNodeNames()
{
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();
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)
{
// Don't bother if there aren't any decorations to place
if (c_decos.size() == 0)
return 0;
if (!canPlaceDecoration(vm, p))
return 0;
@ -345,9 +344,7 @@ size_t DecoSchematic::generate(MMVManip *vm, PcgRandom *pr, v3s16 p)
if (schematic == NULL)
return 0;
u32 vi = vm->m_area.index(p);
content_t c = vm->m_data[vi].getContent();
if (!CONTAINS(c_place_on, c))
if (!canPlaceDecoration(vm, p))
return 0;
if (flags & DECO_PLACE_CENTER_X)

View File

@ -68,6 +68,7 @@ public:
virtual void resolveNodeNames();
bool canPlaceDecoration(MMVManip *vm, v3s16 p);
size_t placeDeco(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;
float fill_ratio;
NoiseParams np;
std::vector<content_t> c_spawnby;
s16 nspawnby;
UNORDERED_SET<u8> biomes;
//std::list<CutoffData> cutoffs;
@ -90,17 +93,13 @@ public:
class DecoSimple : public Decoration {
public:
virtual void resolveNodeNames();
virtual size_t generate(MMVManip *vm, PcgRandom *pr, v3s16 p);
bool canPlaceDecoration(MMVManip *vm, v3s16 p);
virtual int getHeight();
virtual void resolveNodeNames();
std::vector<content_t> c_decos;
std::vector<content_t> c_spawnby;
s16 deco_height;
s16 deco_height_max;
s16 nspawnby;
};
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,
std::vector<std::string> *usednodes, INodeDefManager *ndef)
{
std::map<content_t, content_t> nodeidmap;
UNORDERED_MAP<content_t, content_t> nodeidmap;
content_t numids = 0;
for (size_t i = 0; i != nodecount; i++) {
content_t id;
content_t c = nodes[i].getContent();
std::map<content_t, content_t>::const_iterator it = nodeidmap.find(c);
UNORDERED_MAP<content_t, content_t>::const_iterator it = nodeidmap.find(c);
if (it == nodeidmap.end()) {
id = numids;
numids++;

View File

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

View File

@ -74,6 +74,11 @@ void NodeMetadata::clear()
m_inventory->clear();
}
bool NodeMetadata::empty() const
{
return m_stringvars.size() == 0 && m_inventory->getLists().size() == 0;
}
/*
NodeMetadataList
*/
@ -84,14 +89,13 @@ void NodeMetadataList::serialize(std::ostream &os) const
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
return;
}
writeU8(os, 1); // version
u16 count = m_data.size();
writeU16(os, count);
for(std::map<v3s16, NodeMetadata*>::const_iterator
@ -100,6 +104,8 @@ void NodeMetadataList::serialize(std::ostream &os) const
{
v3s16 p = i->first;
NodeMetadata *data = i->second;
if (data->empty())
continue;
u16 p16 = p.Z * MAP_BLOCKSIZE * MAP_BLOCKSIZE + p.Y * MAP_BLOCKSIZE + p.X;
writeU16(os, p16);
@ -200,6 +206,17 @@ void NodeMetadataList::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,
unsigned short recursion) const
{

View File

@ -47,6 +47,7 @@ public:
void deSerialize(std::istream &is);
void clear();
bool empty() const;
// Generic key/value store
std::string getString(const std::string &name, unsigned short recursion = 0) const;
@ -94,6 +95,8 @@ public:
void clear();
private:
int countNonEmpty() const;
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):
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_air = g_settings->getFloat("movement_acceleration_air") * 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);
}
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;
};
enum RemotePlayerChatResult {
RPLAYER_CHATRESULT_OK,
RPLAYER_CHATRESULT_FLOODING,
RPLAYER_CHATRESULT_KICK,
};
/*
Player on the server
*/
@ -457,8 +461,18 @@ public:
{ m_sao = sao; }
void setPosition(const v3f &position);
const RemotePlayerChatResult canSendChatMessage();
private:
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

View File

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

View File

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

View File

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

View File

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

View File

@ -111,6 +111,9 @@ int LuaAreaStore::l_get_area(lua_State *L)
const Area *res;
res = ast->getArea(id);
if (!res)
return 0;
push_area(L, res, include_borders, include_data);
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->y_min = getintfield_default(L, index, "y_min", -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);
if (deco->sidelen <= 0) {
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;
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
bool success = false;
switch (decotype) {
@ -962,12 +971,10 @@ int ModApiMapgen::l_register_decoration(lua_State *L)
bool read_deco_simple(lua_State *L, DecoSimple *deco)
{
size_t nnames;
int index = 1;
deco->deco_height = getintfield_default(L, index, "height", 1);
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) {
errorstream << "register_decoration: simple decoration height"
@ -975,7 +982,7 @@ bool read_deco_simple(lua_State *L, DecoSimple *deco)
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);
if (nnames == 0) {
errorstream << "register_decoration: no decoration nodes "
@ -983,14 +990,6 @@ bool read_deco_simple(lua_State *L, DecoSimple *deco)
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;
}

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

@ -34,24 +34,23 @@ void ToolCapabilities::serialize(std::ostream &os, u16 protocol_version) const
writeF1000(os, full_punch_interval);
writeS16(os, max_drop_level);
writeU32(os, groupcaps.size());
for(std::map<std::string, ToolGroupCap>::const_iterator
i = groupcaps.begin(); i != groupcaps.end(); ++i){
for (ToolGCMap::const_iterator i = groupcaps.begin(); i != groupcaps.end(); ++i) {
const std::string *name = &i->first;
const ToolGroupCap *cap = &i->second;
os<<serializeString(*name);
writeS16(os, cap->uses);
writeS16(os, cap->maxlevel);
writeU32(os, cap->times.size());
for(std::map<int, float>::const_iterator
i = cap->times.begin(); i != cap->times.end(); ++i){
for (UNORDERED_MAP<int, float>::const_iterator
i = cap->times.begin(); i != cap->times.end(); ++i) {
writeS16(os, i->first);
writeF1000(os, i->second);
}
}
if(protocol_version > 17){
writeU32(os, damageGroups.size());
for(std::map<std::string, s16>::const_iterator
i = damageGroups.begin(); i != damageGroups.end(); ++i){
for (DamageGroup::const_iterator i = damageGroups.begin();
i != damageGroups.end(); ++i) {
os<<serializeString(i->first);
writeS16(os, i->second);
}
@ -106,7 +105,7 @@ DigParams getDigParams(const ItemGroupList &groups,
default:
break;
}
// Values to be returned (with a bit of conversion)
bool result_diggable = false;
float result_time = 0.0;
@ -115,8 +114,8 @@ DigParams getDigParams(const ItemGroupList &groups,
int level = itemgroup_get(groups, "level");
//infostream<<"level="<<level<<std::endl;
for(std::map<std::string, ToolGroupCap>::const_iterator
i = tp->groupcaps.begin(); i != tp->groupcaps.end(); ++i){
for (ToolGCMap::const_iterator i = tp->groupcaps.begin();
i != tp->groupcaps.end(); ++i) {
const std::string &name = i->first;
//infostream<<"group="<<name<<std::endl;
const ToolGroupCap &cap = i->second;
@ -163,8 +162,8 @@ HitParams getHitParams(const ItemGroupList &armor_groups,
s16 damage = 0;
float full_punch_interval = tp->full_punch_interval;
for(std::map<std::string, s16>::const_iterator
i = tp->damageGroups.begin(); i != tp->damageGroups.end(); ++i){
for (DamageGroup::const_iterator i = tp->damageGroups.begin();
i != tp->damageGroups.end(); ++i) {
s16 armor = itemgroup_get(armor_groups, i->first);
damage += i->second * rangelim(time_from_last_punch / full_punch_interval, 0.0, 1.0)
* armor / 100.0;
@ -197,7 +196,7 @@ PunchDamageResult getPunchDamage(
do_hit = false;
}
}
PunchDamageResult result;
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 <string>
#include <iostream>
#include <map>
#include "util/cpp11_container.h"
#include "itemgroup.h"
struct ToolGroupCap
{
std::map<int, float> times;
UNORDERED_MAP<int, float> times;
int maxlevel;
int uses;
@ -39,8 +39,8 @@ struct ToolGroupCap
bool getTime(int rating, float *time) const
{
std::map<int, float>::const_iterator i = times.find(rating);
if(i == times.end()){
UNORDERED_MAP<int, float>::const_iterator i = times.find(rating);
if (i == times.end()) {
*time = 0;
return false;
}
@ -50,22 +50,19 @@ struct ToolGroupCap
};
// CLANG SUCKS DONKEY BALLS
typedef std::map<std::string, struct ToolGroupCap> ToolGCMap;
typedef std::map<std::string, s16> DamageGroup;
typedef UNORDERED_MAP<std::string, struct ToolGroupCap> ToolGCMap;
typedef UNORDERED_MAP<std::string, s16> DamageGroup;
struct ToolCapabilities
{
float full_punch_interval;
int max_drop_level;
// CLANG SUCKS DONKEY BALLS
ToolGCMap groupcaps;
DamageGroup damageGroups;
ToolCapabilities(
float full_punch_interval_=1.4,
int max_drop_level_=1,
// CLANG SUCKS DONKEY BALLS
ToolGCMap groupcaps_=ToolGCMap(),
DamageGroup damageGroups_=DamageGroup()
):

View File

@ -23,3 +23,7 @@ set (UNITTEST_SRCS
${CMAKE_CURRENT_SOURCE_DIR}/test_voxelalgorithms.cpp
${CMAKE_CURRENT_SOURCE_DIR}/test_voxelmanipulator.cpp
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();
static const char *config_text_before;
static const char *config_text_after;
static const std::string config_text_after;
};
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"
"zoop = true";
const char *TestSettings::config_text_after =
const std::string TestSettings::config_text_after =
"leet = 1337\n"
"leetleet = 13371337\n"
"leetleet_neg = -13371337\n"
@ -197,7 +197,10 @@ void TestSettings::testAllSettings()
UASSERT(s.updateConfigObject(is, os, "", 0) == true);
//printf(">>>> expected config:\n%s\n", TEST_CONFIG_TEXT_AFTER);
//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);
#endif
} catch (SettingNotFoundException &e) {
UASSERT(!"Setting not found!");
}

View File

@ -163,6 +163,7 @@ private:
void TestThreading::testAtomicSemaphoreThread()
{
Atomic<u32> val;
val = 0;
Semaphore trigger;
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
toolchain_file=$dir/toolchain_mingw.cmake
irrlicht_version=1.8.1
ogg_version=1.2.1
vorbis_version=1.3.3
curl_version=7.38.0
irrlicht_version=1.8.4
ogg_version=1.3.2
vorbis_version=1.3.5
curl_version=7.50.3
gettext_version=0.14.4
freetype_version=2.3.5
sqlite3_version=3.8.7.4
freetype_version=2.7
sqlite3_version=3.14.2
luajit_version=2.0.1
leveldb_version=1.15
leveldb_version=1.18
zlib_version=1.2.8
mkdir -p $packagedir
@ -34,44 +34,38 @@ cd $builddir
-c -O $packagedir/irrlicht-$irrlicht_version.zip
[ -e $packagedir/zlib-$zlib_version.zip ] || wget http://minetest.kitsunemimi.pw/zlib-$zlib_version-win32.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 \
-c -O $packagedir/libogg-$ogg_version-dev.7z
[ -e $packagedir/libogg-$ogg_version-dll.7z ] || wget http://minetest.kitsunemimi.pw/libogg-$ogg_version-dll.7z \
-c -O $packagedir/libogg-$ogg_version-dll.7z
[ -e $packagedir/libvorbis-$vorbis_version-dev.7z ] || wget http://minetest.kitsunemimi.pw/libvorbis-$vorbis_version-dev.7z \
-c -O $packagedir/libvorbis-$vorbis_version-dev.7z
[ -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/libogg-$ogg_version.zip ] || wget http://minetest.kitsunemimi.pw/libogg-$ogg_version-win32.zip \
-c -O $packagedir/libogg-$ogg_version.zip
[ -e $packagedir/libvorbis-$vorbis_version.zip ] || wget http://minetest.kitsunemimi.pw/libvorbis-$vorbis_version-win32.zip \
-c -O $packagedir/libvorbis-$vorbis_version.zip
[ -e $packagedir/curl-$curl_version.zip ] || wget http://minetest.kitsunemimi.pw/curl-$curl_version-win32.zip \
-c -O $packagedir/curl-$curl_version.zip
[ -e $packagedir/gettext-$gettext_version.zip ] || wget http://minetest.kitsunemimi.pw/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 \
-c -O $packagedir/libfreetype-$freetype_version.zip
[ -e $packagedir/freetype2-$freetype_version.zip ] || wget http://minetest.kitsunemimi.pw/freetype2-$freetype_version-win32.zip \
-c -O $packagedir/freetype2-$freetype_version.zip
[ -e $packagedir/sqlite3-$sqlite3_version.zip ] || wget http://minetest.kitsunemimi.pw/sqlite3-$sqlite3_version-win32.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 \
-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 \
-c -O $packagedir/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.zip
[ -e $packagedir/openal_stripped.zip ] || wget http://minetest.kitsunemimi.pw/openal_stripped.zip \
-c -O $packagedir/openal_stripped.zip
# Extract stuff
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 libogg/include ] || 7z x -y -olibogg $packagedir/libogg-$ogg_version-dev.7z
[ -d libogg/bin ] || 7z x -y -olibogg $packagedir/libogg-$ogg_version-dll.7z
[ -d libvorbis/include ] || 7z x -y -olibvorbis $packagedir/libvorbis-$vorbis_version-dev.7z
[ -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 libogg ] || unzip -o $packagedir/libogg-$ogg_version.zip -d libogg
[ -d libvorbis ] || unzip -o $packagedir/libvorbis-$vorbis_version.zip -d libvorbis
[ -d libcurl ] || unzip -o $packagedir/curl-$curl_version.zip -d libcurl
[ -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 openal_stripped ] || unzip -o $packagedir/openal_stripped.zip
[ -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
cd $builddir
@ -107,14 +101,13 @@ cmake .. \
-DENABLE_FREETYPE=1 \
-DENABLE_LEVELDB=1 \
\
-DIRRLICHT_INCLUDE_DIR=$libdir/irrlicht-$irrlicht_version/include \
-DIRRLICHT_LIBRARY=$libdir/irrlicht-$irrlicht_version/lib/Win32-gcc/libIrrlicht.dll.a \
-DIRRLICHT_DLL=$libdir/irrlicht-$irrlicht_version/bin/Win32-gcc/Irrlicht.dll \
-DIRRLICHT_INCLUDE_DIR=$libdir/irrlicht/include \
-DIRRLICHT_LIBRARY=$libdir/irrlicht/lib/Win32-gcc/libIrrlicht.dll.a \
-DIRRLICHT_DLL=$libdir/irrlicht/bin/Win32-gcc/Irrlicht.dll \
\
-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 \
-DZLIBWAPI_DLL=$libdir/zlib/bin/zlibwapi.dll \
\
-DLUA_INCLUDE_DIR=$libdir/luajit/include \
-DLUA_LIBRARY=$libdir/luajit/libluajit.a \
@ -145,9 +138,9 @@ cmake .. \
-DGETTEXT_LIBRARY=$libdir/gettext/lib/libintl.dll.a \
\
-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_DLL=$libdir/freetype/bin/freetype6.dll \
-DFREETYPE_DLL=$libdir/freetype/bin/libfreetype-6.dll \
\
-DSQLITE3_INCLUDE_DIR=$libdir/sqlite3/include \
-DSQLITE3_LIBRARY=$libdir/sqlite3/lib/libsqlite3.dll.a \

View File

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

View File

@ -1,16 +1,8 @@
#!/bin/bash -e
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 install p7zip-full
sudo apt-get install p7zip-full $COMPILER
fi
if [[ $PLATFORM == "Unix" ]]; then
@ -25,7 +17,7 @@ if [[ $PLATFORM == "Unix" ]]; then
else
brew update
brew install freetype gettext hiredis irrlicht jpeg leveldb libogg libvorbis luajit
brew upgrade postgresql
#brew upgrade postgresql
fi
elif [[ $PLATFORM == "Win32" ]]; then
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
cd travisbuild || exit 1
CMAKE_FLAGS=''
if [[ $COMPILER == "g++-6" ]]; then
export CC=gcc-6
export CXX=g++-6
fi
# Clang builds with FreeType fail on Travis
if [[ $CC == "clang" ]]; then
CMAKE_FLAGS+=' -DENABLE_FREETYPE=FALSE'