Merge branch 'master' into sphere
commit
7b9cf89c1d
36
.travis.yml
36
.travis.yml
|
@ -1,14 +1,4 @@
|
||||||
language: cpp
|
language: cpp
|
||||||
compiler:
|
|
||||||
- gcc
|
|
||||||
- clang
|
|
||||||
os:
|
|
||||||
- osx
|
|
||||||
- linux
|
|
||||||
env:
|
|
||||||
- PLATFORM=Win32
|
|
||||||
- PLATFORM=Win64
|
|
||||||
- PLATFORM=Unix
|
|
||||||
before_install: ./util/travis/before_install.sh
|
before_install: ./util/travis/before_install.sh
|
||||||
script: ./util/travis/script.sh
|
script: ./util/travis/script.sh
|
||||||
sudo: required
|
sudo: required
|
||||||
|
@ -16,14 +6,26 @@ notifications:
|
||||||
email: false
|
email: false
|
||||||
matrix:
|
matrix:
|
||||||
fast_finish: true
|
fast_finish: true
|
||||||
exclude:
|
include:
|
||||||
- env: PLATFORM=Win32
|
- env: PLATFORM=Win32
|
||||||
compiler: clang
|
compiler: gcc
|
||||||
|
os: linux
|
||||||
- env: PLATFORM=Win64
|
- env: PLATFORM=Win64
|
||||||
|
compiler: gcc
|
||||||
|
os: linux
|
||||||
|
- env: PLATFORM=Unix COMPILER=clang
|
||||||
compiler: clang
|
compiler: clang
|
||||||
- env: PLATFORM=Win32
|
|
||||||
os: osx
|
|
||||||
- env: PLATFORM=Win64
|
|
||||||
os: osx
|
|
||||||
- compiler: gcc
|
|
||||||
os: osx
|
os: osx
|
||||||
|
- env: PLATFORM=Unix COMPILER=g++
|
||||||
|
compiler: gcc
|
||||||
|
os: linux
|
||||||
|
- env: PLATFORM=Unix COMPILER=clang
|
||||||
|
compiler: clang
|
||||||
|
os: linux
|
||||||
|
- env: PLATFORM=Unix COMPILER=g++-6
|
||||||
|
compiler: gcc
|
||||||
|
os: linux
|
||||||
|
addons:
|
||||||
|
apt:
|
||||||
|
sources: &sources
|
||||||
|
- ubuntu-toolchain-r-test
|
||||||
|
|
63
README.txt
63
README.txt
|
@ -27,39 +27,47 @@ This game is not finished
|
||||||
- Don't expect it to work as well as a finished game will.
|
- Don't expect it to work as well as a finished game will.
|
||||||
- Please report any bugs. When doing that, debug.txt is useful.
|
- Please report any bugs. When doing that, debug.txt is useful.
|
||||||
|
|
||||||
Default Controls
|
Default controls
|
||||||
-----------------
|
-----------------
|
||||||
- WASD: move
|
- Move mouse: Look around
|
||||||
- Space: jump/climb
|
- W, A, S, D: Move
|
||||||
- Shift: sneak/go down
|
- Space: Jump/move up
|
||||||
- Q: drop itemstack (+ SHIFT for single item)
|
- Shift: Sneak/move down
|
||||||
- I: inventory
|
- Q: Drop itemstack
|
||||||
- Mouse: turn/look
|
- Shift + Q: Drop single item
|
||||||
- Mouse left: dig/punch
|
- Left mouse button: Dig/punch/take item
|
||||||
- Mouse right: place/use
|
- Right mouse button: Place/use
|
||||||
- Mouse wheel: select item
|
- Shift + right mouse button: Build (without using)
|
||||||
- T: chat
|
- I: Inventory menu
|
||||||
- 1-8: select item
|
- Mouse wheel: Select item
|
||||||
|
- 0-9: Select item
|
||||||
|
- Z: Zoom (needs zoom privilege)
|
||||||
|
- T: Chat
|
||||||
|
- /: Commad
|
||||||
|
|
||||||
- Esc: pause menu (pauses only singleplayer game)
|
- Esc: Pause menu/abort/exit (pauses only singleplayer game)
|
||||||
- R: Enable/Disable full range view
|
- R: Enable/disable full range view
|
||||||
- +: Increase view range
|
- +: Increase view range
|
||||||
- -: Decrease view range
|
- -: Decrease view range
|
||||||
- K: Enable/Disable fly (needs fly privilege)
|
- K: Enable/disable fly mode (needs fly privilege)
|
||||||
- J: Enable/Disable fast (needs fast privilege)
|
- J: Enable/disable fast mode (needs fast privilege)
|
||||||
- H: Enable/Disable noclip (needs noclip privilege)
|
- H: Enable/disable noclip mode (needs noclip privilege)
|
||||||
|
|
||||||
- F1: Hide/Show HUD
|
- F1: Hide/show HUD
|
||||||
- F2: Hide/Show Chat
|
- F2: Hide/show chat
|
||||||
- F3: Disable/Enable Fog
|
- F3: Disable/enable fog
|
||||||
- F4: Disable/Enable Camera update (Mapblocks are not updated anymore when disabled)
|
- F4: Disable/enable camera update (Mapblocks are not updated anymore when disabled, disabled in release builds)
|
||||||
- F5: Toogle through debug info screens
|
- F5: Cycle through debug info screens
|
||||||
- F6: Toogle through output data
|
- F6: Cycle through profiler info screens
|
||||||
- F7: Toggle through camera modes
|
- F7: Cycle through camera modes
|
||||||
- F10: Show/Hide console
|
- F8: Toggle cinematic mode
|
||||||
|
- F9: Cycle through minimap modes
|
||||||
|
- Shift + F9: Change minimap orientation
|
||||||
|
- F10: Show/hide console
|
||||||
- F12: Take screenshot
|
- F12: Take screenshot
|
||||||
|
- P: Write stack traces into debug.txt
|
||||||
|
|
||||||
- Settable in the configuration file, see the section below.
|
Most controls are settable in the configuration file, see the section below.
|
||||||
|
|
||||||
Paths
|
Paths
|
||||||
------
|
------
|
||||||
|
@ -403,6 +411,9 @@ Authors of media files
|
||||||
Everything not listed in here:
|
Everything not listed in here:
|
||||||
Copyright (C) 2010-2012 celeron55, Perttu Ahola <celeron55@gmail.com>
|
Copyright (C) 2010-2012 celeron55, Perttu Ahola <celeron55@gmail.com>
|
||||||
|
|
||||||
|
ShadowNinja:
|
||||||
|
textures/base/pack/smoke_puff.png
|
||||||
|
|
||||||
Paramat:
|
Paramat:
|
||||||
textures/base/pack/menu_header.png
|
textures/base/pack/menu_header.png
|
||||||
|
|
||||||
|
|
|
@ -19,4 +19,9 @@ core.EMERGE_FROM_DISK = 3
|
||||||
core.EMERGE_GENERATED = 4
|
core.EMERGE_GENERATED = 4
|
||||||
|
|
||||||
-- constants.h
|
-- constants.h
|
||||||
|
-- Size of mapblocks in nodes
|
||||||
core.MAP_BLOCKSIZE = 16
|
core.MAP_BLOCKSIZE = 16
|
||||||
|
|
||||||
|
-- light.h
|
||||||
|
-- Maximum value for node 'light_source' parameter
|
||||||
|
core.LIGHT_MAX = 14
|
||||||
|
|
|
@ -130,7 +130,11 @@ function check_attached_node(p, n)
|
||||||
local def = core.registered_nodes[n.name]
|
local def = core.registered_nodes[n.name]
|
||||||
local d = {x = 0, y = 0, z = 0}
|
local d = {x = 0, y = 0, z = 0}
|
||||||
if def.paramtype2 == "wallmounted" then
|
if def.paramtype2 == "wallmounted" then
|
||||||
d = core.wallmounted_to_dir(n.param2)
|
-- The fallback vector here is in case 'wallmounted to dir' is nil due
|
||||||
|
-- to voxelmanip placing a wallmounted node without resetting a
|
||||||
|
-- pre-existing param2 value that is out-of-range for wallmounted.
|
||||||
|
-- The fallback vector corresponds to param2 = 0.
|
||||||
|
d = core.wallmounted_to_dir(n.param2) or {x = 0, y = 1, z = 0}
|
||||||
else
|
else
|
||||||
d.y = -1
|
d.y = -1
|
||||||
end
|
end
|
||||||
|
|
|
@ -5,6 +5,7 @@ core.forceload_block = nil
|
||||||
core.forceload_free_block = nil
|
core.forceload_free_block = nil
|
||||||
|
|
||||||
local blocks_forceloaded
|
local blocks_forceloaded
|
||||||
|
local blocks_temploaded = {}
|
||||||
local total_forceloaded = 0
|
local total_forceloaded = 0
|
||||||
|
|
||||||
local BLOCKSIZE = core.MAP_BLOCKSIZE
|
local BLOCKSIZE = core.MAP_BLOCKSIZE
|
||||||
|
@ -15,32 +16,52 @@ local function get_blockpos(pos)
|
||||||
z = math.floor(pos.z/BLOCKSIZE)}
|
z = math.floor(pos.z/BLOCKSIZE)}
|
||||||
end
|
end
|
||||||
|
|
||||||
function core.forceload_block(pos)
|
-- When we create/free a forceload, it's either transient or persistent. We want
|
||||||
|
-- to add to/remove from the table that corresponds to the type of forceload, but
|
||||||
|
-- we also need the other table because whether we forceload a block depends on
|
||||||
|
-- both tables.
|
||||||
|
-- This function returns the "primary" table we are adding to/removing from, and
|
||||||
|
-- the other table.
|
||||||
|
local function get_relevant_tables(transient)
|
||||||
|
if transient then
|
||||||
|
return blocks_temploaded, blocks_forceloaded
|
||||||
|
else
|
||||||
|
return blocks_forceloaded, blocks_temploaded
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
function core.forceload_block(pos, transient)
|
||||||
local blockpos = get_blockpos(pos)
|
local blockpos = get_blockpos(pos)
|
||||||
local hash = core.hash_node_position(blockpos)
|
local hash = core.hash_node_position(blockpos)
|
||||||
if blocks_forceloaded[hash] ~= nil then
|
local relevant_table, other_table = get_relevant_tables(transient)
|
||||||
blocks_forceloaded[hash] = blocks_forceloaded[hash] + 1
|
if relevant_table[hash] ~= nil then
|
||||||
|
relevant_table[hash] = relevant_table[hash] + 1
|
||||||
return true
|
return true
|
||||||
|
elseif other_table[hash] ~= nil then
|
||||||
|
relevant_table[hash] = 1
|
||||||
else
|
else
|
||||||
if total_forceloaded >= (tonumber(core.setting_get("max_forceloaded_blocks")) or 16) then
|
if total_forceloaded >= (tonumber(core.setting_get("max_forceloaded_blocks")) or 16) then
|
||||||
return false
|
return false
|
||||||
end
|
end
|
||||||
total_forceloaded = total_forceloaded+1
|
total_forceloaded = total_forceloaded+1
|
||||||
blocks_forceloaded[hash] = 1
|
relevant_table[hash] = 1
|
||||||
forceload_block(blockpos)
|
forceload_block(blockpos)
|
||||||
return true
|
return true
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
function core.forceload_free_block(pos)
|
function core.forceload_free_block(pos, transient)
|
||||||
local blockpos = get_blockpos(pos)
|
local blockpos = get_blockpos(pos)
|
||||||
local hash = core.hash_node_position(blockpos)
|
local hash = core.hash_node_position(blockpos)
|
||||||
if blocks_forceloaded[hash] == nil then return end
|
local relevant_table, other_table = get_relevant_tables(transient)
|
||||||
if blocks_forceloaded[hash] > 1 then
|
if relevant_table[hash] == nil then return end
|
||||||
blocks_forceloaded[hash] = blocks_forceloaded[hash] - 1
|
if relevant_table[hash] > 1 then
|
||||||
|
relevant_table[hash] = relevant_table[hash] - 1
|
||||||
|
elseif other_table[hash] ~= nil then
|
||||||
|
relevant_table[hash] = nil
|
||||||
else
|
else
|
||||||
total_forceloaded = total_forceloaded-1
|
total_forceloaded = total_forceloaded-1
|
||||||
blocks_forceloaded[hash] = nil
|
relevant_table[hash] = nil
|
||||||
forceload_free_block(blockpos)
|
forceload_free_block(blockpos)
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
|
@ -38,7 +38,7 @@ core.register_globalstep(function(dtime)
|
||||||
end)
|
end)
|
||||||
|
|
||||||
function core.after(after, func, ...)
|
function core.after(after, func, ...)
|
||||||
assert(tonumber(time) and type(func) == "function",
|
assert(tonumber(after) and type(func) == "function",
|
||||||
"Invalid core.after invocation")
|
"Invalid core.after invocation")
|
||||||
jobs[#jobs + 1] = {
|
jobs[#jobs + 1] = {
|
||||||
func = func,
|
func = func,
|
||||||
|
|
|
@ -127,6 +127,11 @@ function core.register_item(name, itemdef)
|
||||||
fixed = {-1/8, -1/2, -1/8, 1/8, 1/2, 1/8},
|
fixed = {-1/8, -1/2, -1/8, 1/8, 1/2, 1/8},
|
||||||
}
|
}
|
||||||
end
|
end
|
||||||
|
if itemdef.light_source and itemdef.light_source > core.LIGHT_MAX then
|
||||||
|
itemdef.light_source = core.LIGHT_MAX
|
||||||
|
core.log("warning", "Node 'light_source' value exceeds maximum," ..
|
||||||
|
" limiting to maximum: " ..name)
|
||||||
|
end
|
||||||
setmetatable(itemdef, {__index = core.nodedef_default})
|
setmetatable(itemdef, {__index = core.nodedef_default})
|
||||||
core.registered_nodes[itemdef.name] = itemdef
|
core.registered_nodes[itemdef.name] = itemdef
|
||||||
elseif itemdef.type == "craft" then
|
elseif itemdef.type == "craft" then
|
||||||
|
|
|
@ -659,5 +659,12 @@ function create_adv_settings_dlg()
|
||||||
return dlg
|
return dlg
|
||||||
end
|
end
|
||||||
|
|
||||||
-- generate minetest.conf.example and settings_translation_file.cpp:
|
-- Generate minetest.conf.example and settings_translation_file.cpp
|
||||||
|
|
||||||
|
-- *** Please note ***
|
||||||
|
-- There is text in minetest.conf.example that will not be generated from
|
||||||
|
-- settingtypes.txt but must be preserved:
|
||||||
|
-- The documentation of mapgen noise parameter formats (title plus 16 lines)
|
||||||
|
-- Noise parameter 'mgv5_np_ground' in group format (13 lines)
|
||||||
|
|
||||||
--assert(loadfile(core.get_mainmenu_path()..DIR_DELIM.."generate_from_settingtypes.lua"))(parse_config_file(true, false))
|
--assert(loadfile(core.get_mainmenu_path()..DIR_DELIM.."generate_from_settingtypes.lua"))(parse_config_file(true, false))
|
||||||
|
|
|
@ -73,7 +73,7 @@ local function get_formspec(tabview, name, tabdata)
|
||||||
if not file_exists(infofile) then
|
if not file_exists(infofile) then
|
||||||
infofile = current_texture_path .. DIR_DELIM .. "info.txt"
|
infofile = current_texture_path .. DIR_DELIM .. "info.txt"
|
||||||
if file_exists(infofile) then
|
if file_exists(infofile) then
|
||||||
core.log("info.txt is depreciated. description.txt should be used instead.")
|
core.log("deprecated", "info.txt is deprecated. description.txt should be used instead.")
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
|
|
@ -561,13 +561,13 @@ freetype (Freetype fonts) bool true
|
||||||
# Path to TrueTypeFont or bitmap.
|
# Path to TrueTypeFont or bitmap.
|
||||||
font_path (Font path) path fonts/liberationsans.ttf
|
font_path (Font path) path fonts/liberationsans.ttf
|
||||||
|
|
||||||
font_size (Font size) int 15
|
font_size (Font size) int 16
|
||||||
|
|
||||||
# Font shadow offset, if 0 then shadow will not be drawn.
|
# Font shadow offset, if 0 then shadow will not be drawn.
|
||||||
font_shadow (Font shadow) int 1
|
font_shadow (Font shadow) int 1
|
||||||
|
|
||||||
# Font shadow alpha (opaqueness, between 0 and 255).
|
# Font shadow alpha (opaqueness, between 0 and 255).
|
||||||
font_shadow_alpha (Font shadow alpha) int 128 0 255
|
font_shadow_alpha (Font shadow alpha) int 127 0 255
|
||||||
|
|
||||||
mono_font_path (Monospace font path) path fonts/liberationmono.ttf
|
mono_font_path (Monospace font path) path fonts/liberationmono.ttf
|
||||||
|
|
||||||
|
@ -774,6 +774,15 @@ time_speed (Time speed) int 72
|
||||||
# Interval of saving important changes in the world, stated in seconds.
|
# Interval of saving important changes in the world, stated in seconds.
|
||||||
server_map_save_interval (Map save interval) float 5.3
|
server_map_save_interval (Map save interval) float 5.3
|
||||||
|
|
||||||
|
# Set the maximum character length of a chat message sent by clients.
|
||||||
|
# chat_message_max_size int 500
|
||||||
|
|
||||||
|
# Limit a single player to send X messages per 10 seconds.
|
||||||
|
# chat_message_limit_per_10sec float 10.0
|
||||||
|
|
||||||
|
# Kick player if send more than X messages per 10 seconds.
|
||||||
|
# chat_message_limit_trigger_kick int 50
|
||||||
|
|
||||||
[**Physics]
|
[**Physics]
|
||||||
|
|
||||||
movement_acceleration_default (Default acceleration) float 3
|
movement_acceleration_default (Default acceleration) float 3
|
||||||
|
|
|
@ -263,7 +263,17 @@ Textures can be grouped together by enclosing them in `(` and `)`.
|
||||||
Example: `cobble.png^(thing1.png^thing2.png)`
|
Example: `cobble.png^(thing1.png^thing2.png)`
|
||||||
|
|
||||||
A texture for `thing1.png^thing2.png` is created and the resulting
|
A texture for `thing1.png^thing2.png` is created and the resulting
|
||||||
texture is overlaid over `cobble.png`.
|
texture is overlaid on top of `cobble.png`.
|
||||||
|
|
||||||
|
### Escaping
|
||||||
|
Modifiers that accept texture names (e.g. `[combine`) accept escaping to allow
|
||||||
|
passing complex texture names as arguments. Escaping is done with backslash and
|
||||||
|
is required for `^` and `:`.
|
||||||
|
|
||||||
|
Example: `cobble.png^[lowpart:50:color.png\^[mask\:trans.png`
|
||||||
|
|
||||||
|
The lower 50 percent of `color.png^[mask:trans.png` are overlaid
|
||||||
|
on top of `cobble.png`.
|
||||||
|
|
||||||
### Advanced texture modifiers
|
### Advanced texture modifiers
|
||||||
|
|
||||||
|
@ -308,6 +318,15 @@ Example:
|
||||||
|
|
||||||
default_sandstone.png^[opacity:127
|
default_sandstone.png^[opacity:127
|
||||||
|
|
||||||
|
#### `[invert:<mode>`
|
||||||
|
Inverts the given channels of the base image.
|
||||||
|
Mode may contain the characters "r", "g", "b", "a".
|
||||||
|
Only the channels that are mentioned in the mode string will be inverted.
|
||||||
|
|
||||||
|
Example:
|
||||||
|
|
||||||
|
default_apple.png^[invert:rgb
|
||||||
|
|
||||||
#### `[brighten`
|
#### `[brighten`
|
||||||
Brightens the texture.
|
Brightens the texture.
|
||||||
|
|
||||||
|
@ -351,7 +370,7 @@ Example:
|
||||||
default_stone.png^[transformFXR90
|
default_stone.png^[transformFXR90
|
||||||
|
|
||||||
#### `[inventorycube{<top>{<left>{<right>`
|
#### `[inventorycube{<top>{<left>{<right>`
|
||||||
`^` is replaced by `&` in texture names.
|
Escaping does not apply here and `^` is replaced by `&` in texture names instead.
|
||||||
|
|
||||||
Create an inventory cube texture using the side textures.
|
Create an inventory cube texture using the side textures.
|
||||||
|
|
||||||
|
@ -1450,6 +1469,15 @@ examples.
|
||||||
* `fixed_size`: `true`/`false` (optional)
|
* `fixed_size`: `true`/`false` (optional)
|
||||||
* deprecated: `invsize[<W>,<H>;]`
|
* deprecated: `invsize[<W>,<H>;]`
|
||||||
|
|
||||||
|
#### `container[<X>,<Y>]`
|
||||||
|
* Start of a container block, moves all physical elements in the container by (X, Y)
|
||||||
|
* Must have matching container_end
|
||||||
|
* Containers can be nested, in which case the offsets are added
|
||||||
|
(child containers are relative to parent containers)
|
||||||
|
|
||||||
|
#### `container_end[]`
|
||||||
|
* End of a container, following elements are no longer relative to this container
|
||||||
|
|
||||||
#### `list[<inventory location>;<list name>;<X>,<Y>;<W>,<H>;]`
|
#### `list[<inventory location>;<list name>;<X>,<Y>;<W>,<H>;]`
|
||||||
* Show an inventory list
|
* Show an inventory list
|
||||||
|
|
||||||
|
@ -2594,13 +2622,17 @@ These functions return the leftover itemstack.
|
||||||
the creative mode setting, and checks for "sneak" to set the `invert_wall`
|
the creative mode setting, and checks for "sneak" to set the `invert_wall`
|
||||||
parameter.
|
parameter.
|
||||||
|
|
||||||
* `minetest.forceload_block(pos)`
|
* `minetest.forceload_block(pos[, transient])`
|
||||||
* forceloads the position `pos`.
|
* forceloads the position `pos`.
|
||||||
* returns `true` if area could be forceloaded
|
* returns `true` if area could be forceloaded
|
||||||
* Please note that forceloaded areas are saved when the server restarts.
|
* If `transient` is `false` or absent, the forceload will be persistent
|
||||||
|
(saved between server runs). If `true`, the forceload will be transient
|
||||||
|
(not saved between server runs).
|
||||||
|
|
||||||
* `minetest.forceload_free_block(pos)`
|
* `minetest.forceload_free_block(pos[, transient])`
|
||||||
* stops forceloading the position `pos`
|
* stops forceloading the position `pos`
|
||||||
|
* If `transient` is `false` or absent, frees a persistent forceload.
|
||||||
|
If `true`, frees a transient forceload.
|
||||||
|
|
||||||
* `minetest.request_insecure_environment()`: returns an environment containing
|
* `minetest.request_insecure_environment()`: returns an environment containing
|
||||||
insecure functions if the calling mod has been listed as trusted in the
|
insecure functions if the calling mod has been listed as trusted in the
|
||||||
|
@ -2886,6 +2918,7 @@ chosen for you.
|
||||||
#### Methods
|
#### Methods
|
||||||
* `get_area(id, include_borders, include_data)`: returns the area with the id `id`.
|
* `get_area(id, include_borders, include_data)`: returns the area with the id `id`.
|
||||||
(optional) Boolean values `include_borders` and `include_data` control what's copied.
|
(optional) Boolean values `include_borders` and `include_data` control what's copied.
|
||||||
|
Returns nil if specified area id does not exist.
|
||||||
* `get_areas_for_pos(pos, include_borders, include_data)`: returns all areas that contain
|
* `get_areas_for_pos(pos, include_borders, include_data)`: returns all areas that contain
|
||||||
the position `pos`. (optional) Boolean values `include_borders` and `include_data` control
|
the position `pos`. (optional) Boolean values `include_borders` and `include_data` control
|
||||||
what's copied.
|
what's copied.
|
||||||
|
@ -3328,13 +3361,15 @@ Registered entities
|
||||||
* It has the member `.object`, which is an `ObjectRef` pointing to the object
|
* It has the member `.object`, which is an `ObjectRef` pointing to the object
|
||||||
* The original prototype stuff is visible directly via a metatable
|
* The original prototype stuff is visible directly via a metatable
|
||||||
* Callbacks:
|
* Callbacks:
|
||||||
* `on_activate(self, staticdata)`
|
* `on_activate(self, staticdata, dtime_s)`
|
||||||
* Called when the object is instantiated.
|
* Called when the object is instantiated.
|
||||||
|
* `dtime_s` is the time passed since the object was unloaded, which can
|
||||||
|
be used for updating the entity state.
|
||||||
* `on_step(self, dtime)`
|
* `on_step(self, dtime)`
|
||||||
* Called on every server tick, after movement and collision processing.
|
* Called on every server tick, after movement and collision processing.
|
||||||
`dtime` is usually 0.1 seconds, as per the `dedicated_server_step` setting
|
`dtime` is usually 0.1 seconds, as per the `dedicated_server_step` setting
|
||||||
`in minetest.conf`.
|
`in minetest.conf`.
|
||||||
* `on_punch(self, puncher, time_from_last_punch, tool_capabilities, dir`
|
* `on_punch(self, puncher, time_from_last_punch, tool_capabilities, dir)`
|
||||||
* Called when somebody punches the object.
|
* Called when somebody punches the object.
|
||||||
* Note that you probably want to handle most punches using the
|
* Note that you probably want to handle most punches using the
|
||||||
automatic armor group system.
|
automatic armor group system.
|
||||||
|
@ -3462,7 +3497,7 @@ Definition tables
|
||||||
|
|
||||||
on_activate = function(self, staticdata, dtime_s),
|
on_activate = function(self, staticdata, dtime_s),
|
||||||
on_step = function(self, dtime),
|
on_step = function(self, dtime),
|
||||||
on_punch = function(self, hitter),
|
on_punch = function(self, puncher, time_from_last_punch, tool_capabilities, dir),
|
||||||
on_rightclick = function(self, clicker),
|
on_rightclick = function(self, clicker),
|
||||||
get_staticdata = function(self),
|
get_staticdata = function(self),
|
||||||
-- ^ Called sometimes; the string returned is passed to on_activate when
|
-- ^ Called sometimes; the string returned is passed to on_activate when
|
||||||
|
@ -3642,7 +3677,10 @@ Definition tables
|
||||||
^ Don't forget to use "leveled" type nodebox. ]]
|
^ Don't forget to use "leveled" type nodebox. ]]
|
||||||
liquid_range = 8, -- number of flowing nodes around source (max. 8)
|
liquid_range = 8, -- number of flowing nodes around source (max. 8)
|
||||||
drowning = 0, -- Player will take this amount of damage if no bubbles are left
|
drowning = 0, -- Player will take this amount of damage if no bubbles are left
|
||||||
light_source = 0, -- Amount of light emitted by node
|
light_source = 0, --[[
|
||||||
|
^ Amount of light emitted by node.
|
||||||
|
^ To set the maximum (currently 14), use the value 'minetest.LIGHT_MAX'.
|
||||||
|
^ A value outside the range 0 to minetest.LIGHT_MAX causes undefined behavior.]]
|
||||||
damage_per_second = 0, -- If player is inside node, this damage is caused
|
damage_per_second = 0, -- If player is inside node, this damage is caused
|
||||||
node_box = {type="regular"}, -- See "Node boxes"
|
node_box = {type="regular"}, -- See "Node boxes"
|
||||||
connects_to = nodenames, --[[
|
connects_to = nodenames, --[[
|
||||||
|
@ -3896,7 +3934,7 @@ The Biome API is still in an experimental phase and subject to change.
|
||||||
{
|
{
|
||||||
deco_type = "simple", -- See "Decoration types"
|
deco_type = "simple", -- See "Decoration types"
|
||||||
place_on = "default:dirt_with_grass",
|
place_on = "default:dirt_with_grass",
|
||||||
-- ^ Node that decoration can be placed on
|
-- ^ Node (or list of nodes) that the decoration can be placed on
|
||||||
sidelen = 8,
|
sidelen = 8,
|
||||||
-- ^ Size of divisions made in the chunk being generated.
|
-- ^ Size of divisions made in the chunk being generated.
|
||||||
-- ^ If the chunk size is not evenly divisible by sidelen, sidelen is made equal to the chunk size.
|
-- ^ If the chunk size is not evenly divisible by sidelen, sidelen is made equal to the chunk size.
|
||||||
|
@ -3915,6 +3953,13 @@ The Biome API is still in an experimental phase and subject to change.
|
||||||
-- ^ Minimum and maximum `y` positions these decorations can be generated at.
|
-- ^ Minimum and maximum `y` positions these decorations can be generated at.
|
||||||
-- ^ This parameter refers to the `y` position of the decoration base, so
|
-- ^ This parameter refers to the `y` position of the decoration base, so
|
||||||
-- the actual maximum height would be `height_max + size.Y`.
|
-- the actual maximum height would be `height_max + size.Y`.
|
||||||
|
spawn_by = "default:water",
|
||||||
|
-- ^ Node (or list of nodes) that the decoration only spawns next to.
|
||||||
|
-- ^ Checks two horizontal planes of neighbouring nodes (including diagonal neighbours),
|
||||||
|
-- ^ one plane at Y = surface and one plane at Y = surface = + 1.
|
||||||
|
num_spawn_by = 1,
|
||||||
|
-- ^ Number of spawn_by nodes that must be surrounding the decoration position to occur.
|
||||||
|
-- ^ If absent or -1, decorations occur next to any nodes.
|
||||||
flags = "liquid_surface, force_placement",
|
flags = "liquid_surface, force_placement",
|
||||||
-- ^ Flags for all decoration types.
|
-- ^ Flags for all decoration types.
|
||||||
-- ^ "liquid_surface": Instead of placement on the highest solid surface
|
-- ^ "liquid_surface": Instead of placement on the highest solid surface
|
||||||
|
@ -3932,13 +3977,6 @@ The Biome API is still in an experimental phase and subject to change.
|
||||||
height_max = 0,
|
height_max = 0,
|
||||||
-- ^ Number of nodes the decoration can be at maximum.
|
-- ^ Number of nodes the decoration can be at maximum.
|
||||||
-- ^ If absent, the parameter 'height' is used as a constant.
|
-- ^ If absent, the parameter 'height' is used as a constant.
|
||||||
spawn_by = "default:water",
|
|
||||||
-- ^ Node that the decoration only spawns next to.
|
|
||||||
-- ^ The neighbours checked are the 8 nodes horizontally surrounding the lowest node of the
|
|
||||||
-- ^ decoration, and the 8 nodes horizontally surrounding the ground node below the decoration.
|
|
||||||
num_spawn_by = 1,
|
|
||||||
-- ^ Number of spawn_by nodes that must be surrounding the decoration position to occur.
|
|
||||||
-- ^ If absent or -1, decorations occur next to any nodes.
|
|
||||||
|
|
||||||
----- Schematic-type parameters
|
----- Schematic-type parameters
|
||||||
schematic = "foobar.mts",
|
schematic = "foobar.mts",
|
||||||
|
|
|
@ -655,7 +655,7 @@
|
||||||
# font_path = fonts/liberationsans.ttf
|
# font_path = fonts/liberationsans.ttf
|
||||||
|
|
||||||
# type: int
|
# type: int
|
||||||
# font_size = 15
|
# font_size = 16
|
||||||
|
|
||||||
# Font shadow offset, if 0 then shadow will not be drawn.
|
# Font shadow offset, if 0 then shadow will not be drawn.
|
||||||
# type: int
|
# type: int
|
||||||
|
@ -663,7 +663,7 @@
|
||||||
|
|
||||||
# Font shadow alpha (opaqueness, between 0 and 255).
|
# Font shadow alpha (opaqueness, between 0 and 255).
|
||||||
# type: int min: 0 max: 255
|
# type: int min: 0 max: 255
|
||||||
# font_shadow_alpha = 128
|
# font_shadow_alpha = 127
|
||||||
|
|
||||||
# type: path
|
# type: path
|
||||||
# mono_font_path = fonts/liberationmono.ttf
|
# mono_font_path = fonts/liberationmono.ttf
|
||||||
|
@ -933,6 +933,18 @@
|
||||||
# type: float
|
# type: float
|
||||||
# server_map_save_interval = 5.3
|
# server_map_save_interval = 5.3
|
||||||
|
|
||||||
|
# Set the maximum character length of a chat message sent by clients. (0 to disable)
|
||||||
|
# type: integer
|
||||||
|
# chat_message_max_size = 500
|
||||||
|
|
||||||
|
# Limit a single player to send X messages per 10 seconds. (0 to disable)
|
||||||
|
# type: float
|
||||||
|
# chat_message_limit_per_10sec = 8.0
|
||||||
|
|
||||||
|
# Kick player if send more than X messages per 10 seconds. (0 to disable)
|
||||||
|
# type: integer
|
||||||
|
# chat_message_limit_trigger_kick = 50
|
||||||
|
|
||||||
### Physics
|
### Physics
|
||||||
|
|
||||||
# type: float
|
# type: float
|
||||||
|
@ -1099,6 +1111,25 @@
|
||||||
# type: int
|
# type: int
|
||||||
# num_emerge_threads = 1
|
# num_emerge_threads = 1
|
||||||
|
|
||||||
|
#### Noise parameters and formats
|
||||||
|
|
||||||
|
# Noise parameters can be specified as a set of positional values, for example:
|
||||||
|
# Offset, scale, (spread factors), seed offset, number of octaves, persistence, lacunarity
|
||||||
|
# mgv6_np_terrain_base = -4, 20, (250, 250, 250), 82341, 5, 0.6, 2.0
|
||||||
|
# Or the group format can be used instead, for example:
|
||||||
|
# mgv6_np_terrain_base = {
|
||||||
|
# offset = -4,
|
||||||
|
# scale = 20,
|
||||||
|
# spread = (250, 250, 250),
|
||||||
|
# seed = 82341,
|
||||||
|
# octaves = 5,
|
||||||
|
# persistence = 0.6,
|
||||||
|
# lacunarity = 2.0,
|
||||||
|
# flags = "defaults"
|
||||||
|
# }
|
||||||
|
# Only the group format supports noise flags which are needed for eased noise.
|
||||||
|
# Mgv5 uses eased noise for np_ground so this is shown in group format below.
|
||||||
|
|
||||||
# Noise parameters for biome API temperature, humidity and biome blend.
|
# Noise parameters for biome API temperature, humidity and biome blend.
|
||||||
# type: noise_params
|
# type: noise_params
|
||||||
# mg_biome_np_heat = 50, 50, (750, 750, 750), 5349, 3, 0.5, 2.0
|
# mg_biome_np_heat = 50, 50, (750, 750, 750), 5349, 3, 0.5, 2.0
|
||||||
|
@ -1133,6 +1164,20 @@
|
||||||
# type: noise_params
|
# type: noise_params
|
||||||
# mgv5_np_cave2 = 0, 12, (50, 50, 50), 10325, 4, 0.5, 2.0
|
# mgv5_np_cave2 = 0, 12, (50, 50, 50), 10325, 4, 0.5, 2.0
|
||||||
|
|
||||||
|
# Noise parameters in group format, unsupported by advanced settings
|
||||||
|
# menu but settable in minetest.conf.
|
||||||
|
# See documentation of noise parameter formats above.
|
||||||
|
# mgv5_np_ground = {
|
||||||
|
# offset = 0,
|
||||||
|
# scale = 40,
|
||||||
|
# spread = (80, 80, 80),
|
||||||
|
# seed = 983240,
|
||||||
|
# octaves = 4,
|
||||||
|
# persistence = 0.55,
|
||||||
|
# lacunarity = 2.0,
|
||||||
|
# flags = "eased"
|
||||||
|
# }
|
||||||
|
|
||||||
#### Mapgen v6
|
#### Mapgen v6
|
||||||
|
|
||||||
# Map generation attributes specific to Mapgen v6.
|
# Map generation attributes specific to Mapgen v6.
|
||||||
|
@ -1490,7 +1535,7 @@
|
||||||
# profiler.default_report_format = txt
|
# profiler.default_report_format = txt
|
||||||
|
|
||||||
# The file path relative to your worldpath in which profiles will be saved to.
|
# The file path relative to your worldpath in which profiles will be saved to.
|
||||||
#
|
#
|
||||||
# type: string
|
# type: string
|
||||||
# profiler.report_path = ""
|
# profiler.report_path = ""
|
||||||
|
|
||||||
|
|
|
@ -3,6 +3,7 @@ cmake_minimum_required(VERSION 2.6)
|
||||||
project(minetest)
|
project(minetest)
|
||||||
|
|
||||||
INCLUDE(CheckIncludeFiles)
|
INCLUDE(CheckIncludeFiles)
|
||||||
|
INCLUDE(CheckLibraryExists)
|
||||||
|
|
||||||
# Add custom SemiDebug build mode
|
# Add custom SemiDebug build mode
|
||||||
set(CMAKE_CXX_FLAGS_SEMIDEBUG "-O1 -g -Wall -Wabi" CACHE STRING
|
set(CMAKE_CXX_FLAGS_SEMIDEBUG "-O1 -g -Wall -Wabi" CACHE STRING
|
||||||
|
@ -292,9 +293,10 @@ if(WIN32)
|
||||||
set(ZLIB_INCLUDE_DIR "${PROJECT_SOURCE_DIR}/../../zlib/zlib-1.2.5"
|
set(ZLIB_INCLUDE_DIR "${PROJECT_SOURCE_DIR}/../../zlib/zlib-1.2.5"
|
||||||
CACHE PATH "Zlib include directory")
|
CACHE PATH "Zlib include directory")
|
||||||
set(ZLIB_LIBRARIES "${PROJECT_SOURCE_DIR}/../../zlib125dll/dll32/zlibwapi.lib"
|
set(ZLIB_LIBRARIES "${PROJECT_SOURCE_DIR}/../../zlib125dll/dll32/zlibwapi.lib"
|
||||||
CACHE FILEPATH "Path to zlibwapi.lib")
|
CACHE FILEPATH "Path to zlib library (usually zlibwapi.lib)")
|
||||||
set(ZLIB_DLL "${PROJECT_SOURCE_DIR}/../../zlib125dll/dll32/zlibwapi.dll"
|
set(ZLIB_DLL "${PROJECT_SOURCE_DIR}/../../zlib125dll/dll32/zlibwapi.dll"
|
||||||
CACHE FILEPATH "Path to zlibwapi.dll (for installation)")
|
CACHE FILEPATH "Path to zlib DLL (for installation)")
|
||||||
|
set(ZLIBWAPI_DLL "" CACHE FILEPATH "Path to zlibwapi DLL")
|
||||||
set(IRRLICHT_SOURCE_DIR "${PROJECT_SOURCE_DIR}/../../irrlicht-1.7.2"
|
set(IRRLICHT_SOURCE_DIR "${PROJECT_SOURCE_DIR}/../../irrlicht-1.7.2"
|
||||||
CACHE PATH "irrlicht dir")
|
CACHE PATH "irrlicht dir")
|
||||||
if(USE_FREETYPE)
|
if(USE_FREETYPE)
|
||||||
|
@ -536,6 +538,7 @@ set(client_SRCS
|
||||||
sky.cpp
|
sky.cpp
|
||||||
wieldmesh.cpp
|
wieldmesh.cpp
|
||||||
${client_SCRIPT_SRCS}
|
${client_SCRIPT_SRCS}
|
||||||
|
${UNITTEST_CLIENT_SRCS}
|
||||||
)
|
)
|
||||||
list(SORT client_SRCS)
|
list(SORT client_SRCS)
|
||||||
|
|
||||||
|
@ -722,8 +725,14 @@ else()
|
||||||
set(OTHER_FLAGS "${OTHER_FLAGS} -Wsign-compare")
|
set(OTHER_FLAGS "${OTHER_FLAGS} -Wsign-compare")
|
||||||
endif()
|
endif()
|
||||||
|
|
||||||
|
if(NOT ZLIBWAPI_DLL AND CMAKE_SIZEOF_VOID_P EQUAL 4)
|
||||||
|
set(OTHER_FLAGS "${OTHER_FLAGS} -DWIN32_NO_ZLIB_WINAPI")
|
||||||
|
message(WARNING "Defaulting to cdecl for zlib on win32 because ZLIBWAPI_DLL"
|
||||||
|
" isn't set, ensure that ZLIBWAPI_DLL is set if you want stdcall.")
|
||||||
|
endif()
|
||||||
|
|
||||||
if(MINGW)
|
if(MINGW)
|
||||||
set(OTHER_FLAGS "-mthreads -fexceptions")
|
set(OTHER_FLAGS "${OTHER_FLAGS} -mthreads -fexceptions")
|
||||||
endif()
|
endif()
|
||||||
|
|
||||||
set(CMAKE_CXX_FLAGS_RELEASE "-DNDEBUG ${RELEASE_WARNING_FLAGS} ${WARNING_FLAGS} ${OTHER_FLAGS} -ffast-math -Wall -pipe -funroll-loops")
|
set(CMAKE_CXX_FLAGS_RELEASE "-DNDEBUG ${RELEASE_WARNING_FLAGS} ${WARNING_FLAGS} ${OTHER_FLAGS} -ffast-math -Wall -pipe -funroll-loops")
|
||||||
|
|
|
@ -303,7 +303,7 @@ Client::~Client()
|
||||||
delete m_inventory_from_server;
|
delete m_inventory_from_server;
|
||||||
|
|
||||||
// Delete detached inventories
|
// Delete detached inventories
|
||||||
for (std::map<std::string, Inventory*>::iterator
|
for (UNORDERED_MAP<std::string, Inventory*>::iterator
|
||||||
i = m_detached_inventories.begin();
|
i = m_detached_inventories.begin();
|
||||||
i != m_detached_inventories.end(); ++i) {
|
i != m_detached_inventories.end(); ++i) {
|
||||||
delete i->second;
|
delete i->second;
|
||||||
|
@ -1437,7 +1437,7 @@ Inventory* Client::getInventory(const InventoryLocation &loc)
|
||||||
break;
|
break;
|
||||||
case InventoryLocation::DETACHED:
|
case InventoryLocation::DETACHED:
|
||||||
{
|
{
|
||||||
if(m_detached_inventories.count(loc.name) == 0)
|
if (m_detached_inventories.count(loc.name) == 0)
|
||||||
return NULL;
|
return NULL;
|
||||||
return m_detached_inventories[loc.name];
|
return m_detached_inventories[loc.name];
|
||||||
}
|
}
|
||||||
|
|
|
@ -462,7 +462,7 @@ public:
|
||||||
u16 getHP();
|
u16 getHP();
|
||||||
u16 getBreath();
|
u16 getBreath();
|
||||||
|
|
||||||
bool checkPrivilege(const std::string &priv)
|
bool checkPrivilege(const std::string &priv) const
|
||||||
{ return (m_privileges.count(priv) != 0); }
|
{ return (m_privileges.count(priv) != 0); }
|
||||||
|
|
||||||
bool getChatMessage(std::wstring &message);
|
bool getChatMessage(std::wstring &message);
|
||||||
|
@ -670,11 +670,11 @@ private:
|
||||||
std::map<int, u16> m_sounds_to_objects;
|
std::map<int, u16> m_sounds_to_objects;
|
||||||
|
|
||||||
// Privileges
|
// Privileges
|
||||||
std::set<std::string> m_privileges;
|
UNORDERED_SET<std::string> m_privileges;
|
||||||
|
|
||||||
// Detached inventories
|
// Detached inventories
|
||||||
// key = name
|
// key = name
|
||||||
std::map<std::string, Inventory*> m_detached_inventories;
|
UNORDERED_MAP<std::string, Inventory*> m_detached_inventories;
|
||||||
|
|
||||||
// Storage for mesh data for creating multiple instances of the same mesh
|
// Storage for mesh data for creating multiple instances of the same mesh
|
||||||
StringMap m_mesh_data;
|
StringMap m_mesh_data;
|
||||||
|
|
|
@ -948,11 +948,10 @@ video::ITexture* TextureSource::generateTextureFromMesh(
|
||||||
|
|
||||||
video::IImage* TextureSource::generateImage(const std::string &name)
|
video::IImage* TextureSource::generateImage(const std::string &name)
|
||||||
{
|
{
|
||||||
/*
|
// Get the base image
|
||||||
Get the base image
|
|
||||||
*/
|
|
||||||
|
|
||||||
const char separator = '^';
|
const char separator = '^';
|
||||||
|
const char escape = '\\';
|
||||||
const char paren_open = '(';
|
const char paren_open = '(';
|
||||||
const char paren_close = ')';
|
const char paren_close = ')';
|
||||||
|
|
||||||
|
@ -960,7 +959,9 @@ video::IImage* TextureSource::generateImage(const std::string &name)
|
||||||
s32 last_separator_pos = -1;
|
s32 last_separator_pos = -1;
|
||||||
u8 paren_bal = 0;
|
u8 paren_bal = 0;
|
||||||
for (s32 i = name.size() - 1; i >= 0; i--) {
|
for (s32 i = name.size() - 1; i >= 0; i--) {
|
||||||
switch(name[i]) {
|
if (i > 0 && name[i-1] == escape)
|
||||||
|
continue;
|
||||||
|
switch (name[i]) {
|
||||||
case separator:
|
case separator:
|
||||||
if (paren_bal == 0) {
|
if (paren_bal == 0) {
|
||||||
last_separator_pos = i;
|
last_separator_pos = i;
|
||||||
|
@ -1028,10 +1029,12 @@ video::IImage* TextureSource::generateImage(const std::string &name)
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
core::dimension2d<u32> dim = tmp->getDimension();
|
core::dimension2d<u32> dim = tmp->getDimension();
|
||||||
if (!baseimg)
|
if (baseimg) {
|
||||||
baseimg = driver->createImage(video::ECF_A8R8G8B8, dim);
|
blit_with_alpha(tmp, baseimg, v2s32(0, 0), v2s32(0, 0), dim);
|
||||||
blit_with_alpha(tmp, baseimg, v2s32(0, 0), v2s32(0, 0), dim);
|
tmp->drop();
|
||||||
tmp->drop();
|
} else {
|
||||||
|
baseimg = tmp;
|
||||||
|
}
|
||||||
} else if (!generateImagePart(last_part_of_name, baseimg)) {
|
} else if (!generateImagePart(last_part_of_name, baseimg)) {
|
||||||
// Generate image according to part of name
|
// Generate image according to part of name
|
||||||
errorstream << "generateImage(): "
|
errorstream << "generateImage(): "
|
||||||
|
@ -1099,9 +1102,27 @@ video::IImage * Align2Npot2(video::IImage * image,
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
static std::string unescape_string(const std::string &str, const char esc = '\\')
|
||||||
|
{
|
||||||
|
std::string out;
|
||||||
|
size_t pos = 0, cpos;
|
||||||
|
out.reserve(str.size());
|
||||||
|
while (1) {
|
||||||
|
cpos = str.find_first_of(esc, pos);
|
||||||
|
if (cpos == std::string::npos) {
|
||||||
|
out += str.substr(pos);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
out += str.substr(pos, cpos - pos) + str[cpos + 1];
|
||||||
|
pos = cpos + 2;
|
||||||
|
}
|
||||||
|
return out;
|
||||||
|
}
|
||||||
|
|
||||||
bool TextureSource::generateImagePart(std::string part_of_name,
|
bool TextureSource::generateImagePart(std::string part_of_name,
|
||||||
video::IImage *& baseimg)
|
video::IImage *& baseimg)
|
||||||
{
|
{
|
||||||
|
const char escape = '\\'; // same as in generateImage()
|
||||||
video::IVideoDriver* driver = m_device->getVideoDriver();
|
video::IVideoDriver* driver = m_device->getVideoDriver();
|
||||||
sanity_check(driver);
|
sanity_check(driver);
|
||||||
|
|
||||||
|
@ -1251,7 +1272,7 @@ bool TextureSource::generateImagePart(std::string part_of_name,
|
||||||
}
|
}
|
||||||
/*
|
/*
|
||||||
[combine:WxH:X,Y=filename:X,Y=filename2
|
[combine:WxH:X,Y=filename:X,Y=filename2
|
||||||
Creates a bigger texture from an amount of smaller ones
|
Creates a bigger texture from any amount of smaller ones
|
||||||
*/
|
*/
|
||||||
else if (str_starts_with(part_of_name, "[combine"))
|
else if (str_starts_with(part_of_name, "[combine"))
|
||||||
{
|
{
|
||||||
|
@ -1259,7 +1280,6 @@ bool TextureSource::generateImagePart(std::string part_of_name,
|
||||||
sf.next(":");
|
sf.next(":");
|
||||||
u32 w0 = stoi(sf.next("x"));
|
u32 w0 = stoi(sf.next("x"));
|
||||||
u32 h0 = stoi(sf.next(":"));
|
u32 h0 = stoi(sf.next(":"));
|
||||||
//infostream<<"combined w="<<w0<<" h="<<h0<<std::endl;
|
|
||||||
core::dimension2d<u32> dim(w0,h0);
|
core::dimension2d<u32> dim(w0,h0);
|
||||||
if (baseimg == NULL) {
|
if (baseimg == NULL) {
|
||||||
baseimg = driver->createImage(video::ECF_A8R8G8B8, dim);
|
baseimg = driver->createImage(video::ECF_A8R8G8B8, dim);
|
||||||
|
@ -1268,11 +1288,11 @@ bool TextureSource::generateImagePart(std::string part_of_name,
|
||||||
while (sf.at_end() == false) {
|
while (sf.at_end() == false) {
|
||||||
u32 x = stoi(sf.next(","));
|
u32 x = stoi(sf.next(","));
|
||||||
u32 y = stoi(sf.next("="));
|
u32 y = stoi(sf.next("="));
|
||||||
std::string filename = sf.next(":");
|
std::string filename = unescape_string(sf.next_esc(":", escape), escape);
|
||||||
infostream<<"Adding \""<<filename
|
infostream<<"Adding \""<<filename
|
||||||
<<"\" to combined ("<<x<<","<<y<<")"
|
<<"\" to combined ("<<x<<","<<y<<")"
|
||||||
<<std::endl;
|
<<std::endl;
|
||||||
video::IImage *img = m_sourcecache.getOrLoad(filename, m_device);
|
video::IImage *img = generateImage(filename);
|
||||||
if (img) {
|
if (img) {
|
||||||
core::dimension2d<u32> dim = img->getDimension();
|
core::dimension2d<u32> dim = img->getDimension();
|
||||||
infostream<<"Size "<<dim.Width
|
infostream<<"Size "<<dim.Width
|
||||||
|
@ -1295,7 +1315,7 @@ bool TextureSource::generateImagePart(std::string part_of_name,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
/*
|
/*
|
||||||
"[brighten"
|
[brighten
|
||||||
*/
|
*/
|
||||||
else if (str_starts_with(part_of_name, "[brighten"))
|
else if (str_starts_with(part_of_name, "[brighten"))
|
||||||
{
|
{
|
||||||
|
@ -1309,7 +1329,7 @@ bool TextureSource::generateImagePart(std::string part_of_name,
|
||||||
brighten(baseimg);
|
brighten(baseimg);
|
||||||
}
|
}
|
||||||
/*
|
/*
|
||||||
"[noalpha"
|
[noalpha
|
||||||
Make image completely opaque.
|
Make image completely opaque.
|
||||||
Used for the leaves texture when in old leaves mode, so
|
Used for the leaves texture when in old leaves mode, so
|
||||||
that the transparent parts don't look completely black
|
that the transparent parts don't look completely black
|
||||||
|
@ -1336,7 +1356,7 @@ bool TextureSource::generateImagePart(std::string part_of_name,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
/*
|
/*
|
||||||
"[makealpha:R,G,B"
|
[makealpha:R,G,B
|
||||||
Convert one color to transparent.
|
Convert one color to transparent.
|
||||||
*/
|
*/
|
||||||
else if (str_starts_with(part_of_name, "[makealpha:"))
|
else if (str_starts_with(part_of_name, "[makealpha:"))
|
||||||
|
@ -1375,7 +1395,7 @@ bool TextureSource::generateImagePart(std::string part_of_name,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
/*
|
/*
|
||||||
"[transformN"
|
[transformN
|
||||||
Rotates and/or flips the image.
|
Rotates and/or flips the image.
|
||||||
|
|
||||||
N can be a number (between 0 and 7) or a transform name.
|
N can be a number (between 0 and 7) or a transform name.
|
||||||
|
@ -1543,12 +1563,11 @@ bool TextureSource::generateImagePart(std::string part_of_name,
|
||||||
Strfnd sf(part_of_name);
|
Strfnd sf(part_of_name);
|
||||||
sf.next(":");
|
sf.next(":");
|
||||||
u32 percent = stoi(sf.next(":"));
|
u32 percent = stoi(sf.next(":"));
|
||||||
std::string filename = sf.next(":");
|
std::string filename = unescape_string(sf.next_esc(":", escape), escape);
|
||||||
//infostream<<"power part "<<percent<<"%% of "<<filename<<std::endl;
|
|
||||||
|
|
||||||
if (baseimg == NULL)
|
if (baseimg == NULL)
|
||||||
baseimg = driver->createImage(video::ECF_A8R8G8B8, v2u32(16,16));
|
baseimg = driver->createImage(video::ECF_A8R8G8B8, v2u32(16,16));
|
||||||
video::IImage *img = m_sourcecache.getOrLoad(filename, m_device);
|
video::IImage *img = generateImage(filename);
|
||||||
if (img)
|
if (img)
|
||||||
{
|
{
|
||||||
core::dimension2d<u32> dim = img->getDimension();
|
core::dimension2d<u32> dim = img->getDimension();
|
||||||
|
@ -1628,9 +1647,9 @@ bool TextureSource::generateImagePart(std::string part_of_name,
|
||||||
}
|
}
|
||||||
Strfnd sf(part_of_name);
|
Strfnd sf(part_of_name);
|
||||||
sf.next(":");
|
sf.next(":");
|
||||||
std::string filename = sf.next(":");
|
std::string filename = unescape_string(sf.next_esc(":", escape), escape);
|
||||||
|
|
||||||
video::IImage *img = m_sourcecache.getOrLoad(filename, m_device);
|
video::IImage *img = generateImage(filename);
|
||||||
if (img) {
|
if (img) {
|
||||||
apply_mask(img, baseimg, v2s32(0, 0), v2s32(0, 0),
|
apply_mask(img, baseimg, v2s32(0, 0), v2s32(0, 0),
|
||||||
img->getDimension());
|
img->getDimension());
|
||||||
|
@ -1673,6 +1692,10 @@ bool TextureSource::generateImagePart(std::string part_of_name,
|
||||||
|
|
||||||
apply_colorize(baseimg, v2u32(0, 0), baseimg->getDimension(), color, ratio, keep_alpha);
|
apply_colorize(baseimg, v2u32(0, 0), baseimg->getDimension(), color, ratio, keep_alpha);
|
||||||
}
|
}
|
||||||
|
/*
|
||||||
|
[applyfiltersformesh
|
||||||
|
Internal modifier
|
||||||
|
*/
|
||||||
else if (str_starts_with(part_of_name, "[applyfiltersformesh"))
|
else if (str_starts_with(part_of_name, "[applyfiltersformesh"))
|
||||||
{
|
{
|
||||||
// Apply the "clean transparent" filter, if configured.
|
// Apply the "clean transparent" filter, if configured.
|
||||||
|
@ -1760,9 +1783,48 @@ bool TextureSource::generateImagePart(std::string part_of_name,
|
||||||
for (u32 y = 0; y < dim.Height; y++)
|
for (u32 y = 0; y < dim.Height; y++)
|
||||||
for (u32 x = 0; x < dim.Width; x++)
|
for (u32 x = 0; x < dim.Width; x++)
|
||||||
{
|
{
|
||||||
video::SColor c = baseimg->getPixel(x,y);
|
video::SColor c = baseimg->getPixel(x, y);
|
||||||
c.setAlpha(floor((c.getAlpha() * ratio) / 255 + 0.5));
|
c.setAlpha(floor((c.getAlpha() * ratio) / 255 + 0.5));
|
||||||
baseimg->setPixel(x,y,c);
|
baseimg->setPixel(x, y, c);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
/*
|
||||||
|
[invert:mode
|
||||||
|
Inverts the given channels of the base image.
|
||||||
|
Mode may contain the characters "r", "g", "b", "a".
|
||||||
|
Only the channels that are mentioned in the mode string
|
||||||
|
will be inverted.
|
||||||
|
*/
|
||||||
|
else if (str_starts_with(part_of_name, "[invert:")) {
|
||||||
|
if (baseimg == NULL) {
|
||||||
|
errorstream << "generateImagePart(): baseimg == NULL "
|
||||||
|
<< "for part_of_name=\"" << part_of_name
|
||||||
|
<< "\", cancelling." << std::endl;
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
Strfnd sf(part_of_name);
|
||||||
|
sf.next(":");
|
||||||
|
|
||||||
|
std::string mode = sf.next("");
|
||||||
|
u32 mask = 0;
|
||||||
|
if (mode.find("a") != std::string::npos)
|
||||||
|
mask |= 0xff000000UL;
|
||||||
|
if (mode.find("r") != std::string::npos)
|
||||||
|
mask |= 0x00ff0000UL;
|
||||||
|
if (mode.find("g") != std::string::npos)
|
||||||
|
mask |= 0x0000ff00UL;
|
||||||
|
if (mode.find("b") != std::string::npos)
|
||||||
|
mask |= 0x000000ffUL;
|
||||||
|
|
||||||
|
core::dimension2d<u32> dim = baseimg->getDimension();
|
||||||
|
|
||||||
|
for (u32 y = 0; y < dim.Height; y++)
|
||||||
|
for (u32 x = 0; x < dim.Width; x++)
|
||||||
|
{
|
||||||
|
video::SColor c = baseimg->getPixel(x, y);
|
||||||
|
c.color ^= mask;
|
||||||
|
baseimg->setPixel(x, y, c);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
|
|
|
@ -617,11 +617,8 @@ ClientInterface::~ClientInterface()
|
||||||
{
|
{
|
||||||
MutexAutoLock clientslock(m_clients_mutex);
|
MutexAutoLock clientslock(m_clients_mutex);
|
||||||
|
|
||||||
for(std::map<u16, RemoteClient*>::iterator
|
for (UNORDERED_MAP<u16, RemoteClient*>::iterator i = m_clients.begin();
|
||||||
i = m_clients.begin();
|
i != m_clients.end(); ++i) {
|
||||||
i != m_clients.end(); ++i)
|
|
||||||
{
|
|
||||||
|
|
||||||
// Delete client
|
// Delete client
|
||||||
delete i->second;
|
delete i->second;
|
||||||
}
|
}
|
||||||
|
@ -633,10 +630,8 @@ std::vector<u16> ClientInterface::getClientIDs(ClientState min_state)
|
||||||
std::vector<u16> reply;
|
std::vector<u16> reply;
|
||||||
MutexAutoLock clientslock(m_clients_mutex);
|
MutexAutoLock clientslock(m_clients_mutex);
|
||||||
|
|
||||||
for(std::map<u16, RemoteClient*>::iterator
|
for(UNORDERED_MAP<u16, RemoteClient*>::iterator i = m_clients.begin();
|
||||||
i = m_clients.begin();
|
i != m_clients.end(); ++i) {
|
||||||
i != m_clients.end(); ++i)
|
|
||||||
{
|
|
||||||
if (i->second->getState() >= min_state)
|
if (i->second->getState() >= min_state)
|
||||||
reply.push_back(i->second->peer_id);
|
reply.push_back(i->second->peer_id);
|
||||||
}
|
}
|
||||||
|
@ -703,8 +698,7 @@ void ClientInterface::sendToAll(u16 channelnum,
|
||||||
NetworkPacket* pkt, bool reliable)
|
NetworkPacket* pkt, bool reliable)
|
||||||
{
|
{
|
||||||
MutexAutoLock clientslock(m_clients_mutex);
|
MutexAutoLock clientslock(m_clients_mutex);
|
||||||
for(std::map<u16, RemoteClient*>::iterator
|
for(UNORDERED_MAP<u16, RemoteClient*>::iterator i = m_clients.begin();
|
||||||
i = m_clients.begin();
|
|
||||||
i != m_clients.end(); ++i) {
|
i != m_clients.end(); ++i) {
|
||||||
RemoteClient *client = i->second;
|
RemoteClient *client = i->second;
|
||||||
|
|
||||||
|
@ -717,11 +711,10 @@ void ClientInterface::sendToAll(u16 channelnum,
|
||||||
RemoteClient* ClientInterface::getClientNoEx(u16 peer_id, ClientState state_min)
|
RemoteClient* ClientInterface::getClientNoEx(u16 peer_id, ClientState state_min)
|
||||||
{
|
{
|
||||||
MutexAutoLock clientslock(m_clients_mutex);
|
MutexAutoLock clientslock(m_clients_mutex);
|
||||||
std::map<u16, RemoteClient*>::iterator n;
|
UNORDERED_MAP<u16, RemoteClient*>::iterator n = m_clients.find(peer_id);
|
||||||
n = m_clients.find(peer_id);
|
|
||||||
// The client may not exist; clients are immediately removed if their
|
// The client may not exist; clients are immediately removed if their
|
||||||
// access is denied, and this event occurs later then.
|
// access is denied, and this event occurs later then.
|
||||||
if(n == m_clients.end())
|
if (n == m_clients.end())
|
||||||
return NULL;
|
return NULL;
|
||||||
|
|
||||||
if (n->second->getState() >= state_min)
|
if (n->second->getState() >= state_min)
|
||||||
|
@ -732,11 +725,10 @@ RemoteClient* ClientInterface::getClientNoEx(u16 peer_id, ClientState state_min)
|
||||||
|
|
||||||
RemoteClient* ClientInterface::lockedGetClientNoEx(u16 peer_id, ClientState state_min)
|
RemoteClient* ClientInterface::lockedGetClientNoEx(u16 peer_id, ClientState state_min)
|
||||||
{
|
{
|
||||||
std::map<u16, RemoteClient*>::iterator n;
|
UNORDERED_MAP<u16, RemoteClient*>::iterator n = m_clients.find(peer_id);
|
||||||
n = m_clients.find(peer_id);
|
|
||||||
// The client may not exist; clients are immediately removed if their
|
// The client may not exist; clients are immediately removed if their
|
||||||
// access is denied, and this event occurs later then.
|
// access is denied, and this event occurs later then.
|
||||||
if(n == m_clients.end())
|
if (n == m_clients.end())
|
||||||
return NULL;
|
return NULL;
|
||||||
|
|
||||||
if (n->second->getState() >= state_min)
|
if (n->second->getState() >= state_min)
|
||||||
|
@ -748,11 +740,10 @@ RemoteClient* ClientInterface::lockedGetClientNoEx(u16 peer_id, ClientState stat
|
||||||
ClientState ClientInterface::getClientState(u16 peer_id)
|
ClientState ClientInterface::getClientState(u16 peer_id)
|
||||||
{
|
{
|
||||||
MutexAutoLock clientslock(m_clients_mutex);
|
MutexAutoLock clientslock(m_clients_mutex);
|
||||||
std::map<u16, RemoteClient*>::iterator n;
|
UNORDERED_MAP<u16, RemoteClient*>::iterator n = m_clients.find(peer_id);
|
||||||
n = m_clients.find(peer_id);
|
|
||||||
// The client may not exist; clients are immediately removed if their
|
// The client may not exist; clients are immediately removed if their
|
||||||
// access is denied, and this event occurs later then.
|
// access is denied, and this event occurs later then.
|
||||||
if(n == m_clients.end())
|
if (n == m_clients.end())
|
||||||
return CS_Invalid;
|
return CS_Invalid;
|
||||||
|
|
||||||
return n->second->getState();
|
return n->second->getState();
|
||||||
|
@ -761,11 +752,10 @@ ClientState ClientInterface::getClientState(u16 peer_id)
|
||||||
void ClientInterface::setPlayerName(u16 peer_id,std::string name)
|
void ClientInterface::setPlayerName(u16 peer_id,std::string name)
|
||||||
{
|
{
|
||||||
MutexAutoLock clientslock(m_clients_mutex);
|
MutexAutoLock clientslock(m_clients_mutex);
|
||||||
std::map<u16, RemoteClient*>::iterator n;
|
UNORDERED_MAP<u16, RemoteClient*>::iterator n = m_clients.find(peer_id);
|
||||||
n = m_clients.find(peer_id);
|
|
||||||
// The client may not exist; clients are immediately removed if their
|
// The client may not exist; clients are immediately removed if their
|
||||||
// access is denied, and this event occurs later then.
|
// access is denied, and this event occurs later then.
|
||||||
if(n != m_clients.end())
|
if (n != m_clients.end())
|
||||||
n->second->setName(name);
|
n->second->setName(name);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -774,11 +764,10 @@ void ClientInterface::DeleteClient(u16 peer_id)
|
||||||
MutexAutoLock conlock(m_clients_mutex);
|
MutexAutoLock conlock(m_clients_mutex);
|
||||||
|
|
||||||
// Error check
|
// Error check
|
||||||
std::map<u16, RemoteClient*>::iterator n;
|
UNORDERED_MAP<u16, RemoteClient*>::iterator n = m_clients.find(peer_id);
|
||||||
n = m_clients.find(peer_id);
|
|
||||||
// The client may not exist; clients are immediately removed if their
|
// The client may not exist; clients are immediately removed if their
|
||||||
// access is denied, and this event occurs later then.
|
// access is denied, and this event occurs later then.
|
||||||
if(n == m_clients.end())
|
if (n == m_clients.end())
|
||||||
return;
|
return;
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
@ -809,10 +798,9 @@ void ClientInterface::CreateClient(u16 peer_id)
|
||||||
MutexAutoLock conlock(m_clients_mutex);
|
MutexAutoLock conlock(m_clients_mutex);
|
||||||
|
|
||||||
// Error check
|
// Error check
|
||||||
std::map<u16, RemoteClient*>::iterator n;
|
UNORDERED_MAP<u16, RemoteClient*>::iterator n = m_clients.find(peer_id);
|
||||||
n = m_clients.find(peer_id);
|
|
||||||
// The client shouldn't already exist
|
// The client shouldn't already exist
|
||||||
if(n != m_clients.end()) return;
|
if (n != m_clients.end()) return;
|
||||||
|
|
||||||
// Create client
|
// Create client
|
||||||
RemoteClient *client = new RemoteClient();
|
RemoteClient *client = new RemoteClient();
|
||||||
|
@ -826,8 +814,7 @@ void ClientInterface::event(u16 peer_id, ClientStateEvent event)
|
||||||
MutexAutoLock clientlock(m_clients_mutex);
|
MutexAutoLock clientlock(m_clients_mutex);
|
||||||
|
|
||||||
// Error check
|
// Error check
|
||||||
std::map<u16, RemoteClient*>::iterator n;
|
UNORDERED_MAP<u16, RemoteClient*>::iterator n = m_clients.find(peer_id);
|
||||||
n = m_clients.find(peer_id);
|
|
||||||
|
|
||||||
// No client to deliver event
|
// No client to deliver event
|
||||||
if (n == m_clients.end())
|
if (n == m_clients.end())
|
||||||
|
@ -848,8 +835,7 @@ u16 ClientInterface::getProtocolVersion(u16 peer_id)
|
||||||
MutexAutoLock conlock(m_clients_mutex);
|
MutexAutoLock conlock(m_clients_mutex);
|
||||||
|
|
||||||
// Error check
|
// Error check
|
||||||
std::map<u16, RemoteClient*>::iterator n;
|
UNORDERED_MAP<u16, RemoteClient*>::iterator n = m_clients.find(peer_id);
|
||||||
n = m_clients.find(peer_id);
|
|
||||||
|
|
||||||
// No client to get version
|
// No client to get version
|
||||||
if (n == m_clients.end())
|
if (n == m_clients.end())
|
||||||
|
@ -863,8 +849,7 @@ void ClientInterface::setClientVersion(u16 peer_id, u8 major, u8 minor, u8 patch
|
||||||
MutexAutoLock conlock(m_clients_mutex);
|
MutexAutoLock conlock(m_clients_mutex);
|
||||||
|
|
||||||
// Error check
|
// Error check
|
||||||
std::map<u16, RemoteClient*>::iterator n;
|
UNORDERED_MAP<u16, RemoteClient*>::iterator n = m_clients.find(peer_id);
|
||||||
n = m_clients.find(peer_id);
|
|
||||||
|
|
||||||
// No client to set versions
|
// No client to set versions
|
||||||
if (n == m_clients.end())
|
if (n == m_clients.end())
|
||||||
|
|
|
@ -25,10 +25,10 @@ with this program; if not, write to the Free Software Foundation, Inc.,
|
||||||
#include "serialization.h" // for SER_FMT_VER_INVALID
|
#include "serialization.h" // for SER_FMT_VER_INVALID
|
||||||
#include "threading/mutex.h"
|
#include "threading/mutex.h"
|
||||||
#include "network/networkpacket.h"
|
#include "network/networkpacket.h"
|
||||||
|
#include "util/cpp11_container.h"
|
||||||
|
|
||||||
#include <list>
|
#include <list>
|
||||||
#include <vector>
|
#include <vector>
|
||||||
#include <map>
|
|
||||||
#include <set>
|
#include <set>
|
||||||
|
|
||||||
class MapBlock;
|
class MapBlock;
|
||||||
|
@ -502,8 +502,7 @@ protected:
|
||||||
void lock() { m_clients_mutex.lock(); }
|
void lock() { m_clients_mutex.lock(); }
|
||||||
void unlock() { m_clients_mutex.unlock(); }
|
void unlock() { m_clients_mutex.unlock(); }
|
||||||
|
|
||||||
std::map<u16, RemoteClient*>& getClientList()
|
UNORDERED_MAP<u16, RemoteClient*>& getClientList() { return m_clients; }
|
||||||
{ return m_clients; }
|
|
||||||
|
|
||||||
private:
|
private:
|
||||||
/* update internal player list */
|
/* update internal player list */
|
||||||
|
@ -513,7 +512,7 @@ private:
|
||||||
con::Connection* m_con;
|
con::Connection* m_con;
|
||||||
Mutex m_clients_mutex;
|
Mutex m_clients_mutex;
|
||||||
// Connected clients (behind the con mutex)
|
// Connected clients (behind the con mutex)
|
||||||
std::map<u16, RemoteClient*> m_clients;
|
UNORDERED_MAP<u16, RemoteClient*> m_clients;
|
||||||
std::vector<std::string> m_clients_names; //for announcing masterserver
|
std::vector<std::string> m_clients_names; //for announcing masterserver
|
||||||
|
|
||||||
// Environment
|
// Environment
|
||||||
|
|
|
@ -34,6 +34,27 @@ with this program; if not, write to the Free Software Foundation, Inc.,
|
||||||
//#define COLL_ZERO 0.032 // broken unit tests
|
//#define COLL_ZERO 0.032 // broken unit tests
|
||||||
#define COLL_ZERO 0
|
#define COLL_ZERO 0
|
||||||
|
|
||||||
|
|
||||||
|
struct NearbyCollisionInfo {
|
||||||
|
NearbyCollisionInfo(bool is_ul, bool is_obj, int bouncy,
|
||||||
|
const v3s16 &pos, const aabb3f &box) :
|
||||||
|
is_unloaded(is_ul),
|
||||||
|
is_step_up(false),
|
||||||
|
is_object(is_obj),
|
||||||
|
bouncy(bouncy),
|
||||||
|
position(pos),
|
||||||
|
box(box)
|
||||||
|
{}
|
||||||
|
|
||||||
|
bool is_unloaded;
|
||||||
|
bool is_step_up;
|
||||||
|
bool is_object;
|
||||||
|
int bouncy;
|
||||||
|
v3s16 position;
|
||||||
|
aabb3f box;
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
// Helper function:
|
// Helper function:
|
||||||
// Checks for collision of a moving aabbox with a static aabbox
|
// Checks for collision of a moving aabbox with a static aabbox
|
||||||
// Returns -1 if no collision, 0 if X collision, 1 if Y collision, 2 if Z collision
|
// Returns -1 if no collision, 0 if X collision, 1 if Y collision, 2 if Z collision
|
||||||
|
@ -160,7 +181,7 @@ int axisAlignedCollision(
|
||||||
// Helper function:
|
// Helper function:
|
||||||
// Checks if moving the movingbox up by the given distance would hit a ceiling.
|
// Checks if moving the movingbox up by the given distance would hit a ceiling.
|
||||||
bool wouldCollideWithCeiling(
|
bool wouldCollideWithCeiling(
|
||||||
const std::vector<aabb3f> &staticboxes,
|
const std::vector<NearbyCollisionInfo> &cinfo,
|
||||||
const aabb3f &movingbox,
|
const aabb3f &movingbox,
|
||||||
f32 y_increase, f32 d)
|
f32 y_increase, f32 d)
|
||||||
{
|
{
|
||||||
|
@ -168,12 +189,10 @@ bool wouldCollideWithCeiling(
|
||||||
|
|
||||||
assert(y_increase >= 0); // pre-condition
|
assert(y_increase >= 0); // pre-condition
|
||||||
|
|
||||||
for(std::vector<aabb3f>::const_iterator
|
for (std::vector<NearbyCollisionInfo>::const_iterator it = cinfo.begin();
|
||||||
i = staticboxes.begin();
|
it != cinfo.end(); ++it) {
|
||||||
i != staticboxes.end(); ++i)
|
const aabb3f &staticbox = it->box;
|
||||||
{
|
if ((movingbox.MaxEdge.Y - d <= staticbox.MinEdge.Y) &&
|
||||||
const aabb3f& staticbox = *i;
|
|
||||||
if((movingbox.MaxEdge.Y - d <= staticbox.MinEdge.Y) &&
|
|
||||||
(movingbox.MaxEdge.Y + y_increase > staticbox.MinEdge.Y) &&
|
(movingbox.MaxEdge.Y + y_increase > staticbox.MinEdge.Y) &&
|
||||||
(movingbox.MinEdge.X < staticbox.MaxEdge.X) &&
|
(movingbox.MinEdge.X < staticbox.MaxEdge.X) &&
|
||||||
(movingbox.MaxEdge.X > staticbox.MinEdge.X) &&
|
(movingbox.MaxEdge.X > staticbox.MinEdge.X) &&
|
||||||
|
@ -234,12 +253,7 @@ collisionMoveResult collisionMoveSimple(Environment *env, IGameDef *gamedef,
|
||||||
/*
|
/*
|
||||||
Collect node boxes in movement range
|
Collect node boxes in movement range
|
||||||
*/
|
*/
|
||||||
std::vector<aabb3f> cboxes;
|
std::vector<NearbyCollisionInfo> cinfo;
|
||||||
std::vector<bool> is_unloaded;
|
|
||||||
std::vector<bool> is_step_up;
|
|
||||||
std::vector<bool> is_object;
|
|
||||||
std::vector<int> bouncy_values;
|
|
||||||
std::vector<v3s16> node_positions;
|
|
||||||
{
|
{
|
||||||
//TimeTaker tt2("collisionMoveSimple collect boxes");
|
//TimeTaker tt2("collisionMoveSimple collect boxes");
|
||||||
ScopeProfiler sp(g_profiler, "collisionMoveSimple collect boxes avg", SPT_AVG);
|
ScopeProfiler sp(g_profiler, "collisionMoveSimple collect boxes avg", SPT_AVG);
|
||||||
|
@ -318,23 +332,13 @@ collisionMoveResult collisionMoveSimple(Environment *env, IGameDef *gamedef,
|
||||||
aabb3f box = *i;
|
aabb3f box = *i;
|
||||||
box.MinEdge += v3f(x, y, z)*BS;
|
box.MinEdge += v3f(x, y, z)*BS;
|
||||||
box.MaxEdge += v3f(x, y, z)*BS;
|
box.MaxEdge += v3f(x, y, z)*BS;
|
||||||
cboxes.push_back(box);
|
cinfo.push_back(NearbyCollisionInfo(false,
|
||||||
is_unloaded.push_back(false);
|
false, n_bouncy_value, p, box));
|
||||||
is_step_up.push_back(false);
|
|
||||||
bouncy_values.push_back(n_bouncy_value);
|
|
||||||
node_positions.push_back(p);
|
|
||||||
is_object.push_back(false);
|
|
||||||
}
|
}
|
||||||
}
|
} else {
|
||||||
else {
|
|
||||||
// Collide with unloaded nodes
|
// Collide with unloaded nodes
|
||||||
aabb3f box = getNodeBox(p, BS);
|
aabb3f box = getNodeBox(p, BS);
|
||||||
cboxes.push_back(box);
|
cinfo.push_back(NearbyCollisionInfo(true, false, 0, p, box));
|
||||||
is_unloaded.push_back(true);
|
|
||||||
is_step_up.push_back(false);
|
|
||||||
bouncy_values.push_back(0);
|
|
||||||
node_positions.push_back(p);
|
|
||||||
is_object.push_back(false);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -352,7 +356,7 @@ collisionMoveResult collisionMoveSimple(Environment *env, IGameDef *gamedef,
|
||||||
ScopeProfiler sp(g_profiler, "collisionMoveSimple objects avg", SPT_AVG);
|
ScopeProfiler sp(g_profiler, "collisionMoveSimple objects avg", SPT_AVG);
|
||||||
//TimeTaker tt3("collisionMoveSimple collect object boxes");
|
//TimeTaker tt3("collisionMoveSimple collect object boxes");
|
||||||
|
|
||||||
/* add object boxes to cboxes */
|
/* add object boxes to cinfo */
|
||||||
|
|
||||||
std::vector<ActiveObject*> objects;
|
std::vector<ActiveObject*> objects;
|
||||||
#ifndef SERVER
|
#ifndef SERVER
|
||||||
|
@ -392,23 +396,12 @@ collisionMoveResult collisionMoveSimple(Environment *env, IGameDef *gamedef,
|
||||||
aabb3f object_collisionbox;
|
aabb3f object_collisionbox;
|
||||||
if (object->getCollisionBox(&object_collisionbox) &&
|
if (object->getCollisionBox(&object_collisionbox) &&
|
||||||
object->collideWithObjects()) {
|
object->collideWithObjects()) {
|
||||||
cboxes.push_back(object_collisionbox);
|
cinfo.push_back(NearbyCollisionInfo(false, true, 0, v3s16(), object_collisionbox));
|
||||||
is_unloaded.push_back(false);
|
|
||||||
is_step_up.push_back(false);
|
|
||||||
bouncy_values.push_back(0);
|
|
||||||
node_positions.push_back(v3s16(0,0,0));
|
|
||||||
is_object.push_back(true);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
} //tt3
|
} //tt3
|
||||||
|
|
||||||
assert(cboxes.size() == is_unloaded.size()); // post-condition
|
|
||||||
assert(cboxes.size() == is_step_up.size()); // post-condition
|
|
||||||
assert(cboxes.size() == bouncy_values.size()); // post-condition
|
|
||||||
assert(cboxes.size() == node_positions.size()); // post-condition
|
|
||||||
assert(cboxes.size() == is_object.size()); // post-condition
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
Collision detection
|
Collision detection
|
||||||
*/
|
*/
|
||||||
|
@ -448,15 +441,16 @@ collisionMoveResult collisionMoveSimple(Environment *env, IGameDef *gamedef,
|
||||||
/*
|
/*
|
||||||
Go through every nodebox, find nearest collision
|
Go through every nodebox, find nearest collision
|
||||||
*/
|
*/
|
||||||
for (u32 boxindex = 0; boxindex < cboxes.size(); boxindex++) {
|
for (u32 boxindex = 0; boxindex < cinfo.size(); boxindex++) {
|
||||||
|
NearbyCollisionInfo box_info = cinfo[boxindex];
|
||||||
// Ignore if already stepped up this nodebox.
|
// Ignore if already stepped up this nodebox.
|
||||||
if(is_step_up[boxindex])
|
if (box_info.is_step_up)
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
// Find nearest collision of the two boxes (raytracing-like)
|
// Find nearest collision of the two boxes (raytracing-like)
|
||||||
f32 dtime_tmp;
|
f32 dtime_tmp;
|
||||||
int collided = axisAlignedCollision(
|
int collided = axisAlignedCollision(box_info.box,
|
||||||
cboxes[boxindex], movingbox, *speed_f, d, &dtime_tmp);
|
movingbox, *speed_f, d, &dtime_tmp);
|
||||||
|
|
||||||
if (collided == -1 || dtime_tmp >= nearest_dtime)
|
if (collided == -1 || dtime_tmp >= nearest_dtime)
|
||||||
continue;
|
continue;
|
||||||
|
@ -472,19 +466,19 @@ collisionMoveResult collisionMoveSimple(Environment *env, IGameDef *gamedef,
|
||||||
dtime = 0; // Set to 0 to avoid "infinite" loop due to small FP numbers
|
dtime = 0; // Set to 0 to avoid "infinite" loop due to small FP numbers
|
||||||
} else {
|
} else {
|
||||||
// Otherwise, a collision occurred.
|
// Otherwise, a collision occurred.
|
||||||
|
NearbyCollisionInfo &nearest_info = cinfo[nearest_boxindex];
|
||||||
const aabb3f& cbox = cboxes[nearest_boxindex];
|
const aabb3f& cbox = nearest_info.box;
|
||||||
// Check for stairs.
|
// Check for stairs.
|
||||||
bool step_up = (nearest_collided != 1) && // must not be Y direction
|
bool step_up = (nearest_collided != 1) && // must not be Y direction
|
||||||
(movingbox.MinEdge.Y < cbox.MaxEdge.Y) &&
|
(movingbox.MinEdge.Y < cbox.MaxEdge.Y) &&
|
||||||
(movingbox.MinEdge.Y + stepheight > cbox.MaxEdge.Y) &&
|
(movingbox.MinEdge.Y + stepheight > cbox.MaxEdge.Y) &&
|
||||||
(!wouldCollideWithCeiling(cboxes, movingbox,
|
(!wouldCollideWithCeiling(cinfo, movingbox,
|
||||||
cbox.MaxEdge.Y - movingbox.MinEdge.Y,
|
cbox.MaxEdge.Y - movingbox.MinEdge.Y,
|
||||||
d));
|
d));
|
||||||
|
|
||||||
// Get bounce multiplier
|
// Get bounce multiplier
|
||||||
bool bouncy = (bouncy_values[nearest_boxindex] >= 1);
|
bool bouncy = (nearest_info.bouncy >= 1);
|
||||||
float bounce = -(float)bouncy_values[nearest_boxindex] / 100.0;
|
float bounce = -(float)nearest_info.bouncy / 100.0;
|
||||||
|
|
||||||
// Move to the point of collision and reduce dtime by nearest_dtime
|
// Move to the point of collision and reduce dtime by nearest_dtime
|
||||||
if (nearest_dtime < 0) {
|
if (nearest_dtime < 0) {
|
||||||
|
@ -503,39 +497,38 @@ collisionMoveResult collisionMoveSimple(Environment *env, IGameDef *gamedef,
|
||||||
}
|
}
|
||||||
|
|
||||||
bool is_collision = true;
|
bool is_collision = true;
|
||||||
if (is_unloaded[nearest_boxindex])
|
if (nearest_info.is_unloaded)
|
||||||
is_collision = false;
|
is_collision = false;
|
||||||
|
|
||||||
CollisionInfo info;
|
CollisionInfo info;
|
||||||
if (is_object[nearest_boxindex])
|
if (nearest_info.is_object)
|
||||||
info.type = COLLISION_OBJECT;
|
info.type = COLLISION_OBJECT;
|
||||||
else
|
else
|
||||||
info.type = COLLISION_NODE;
|
info.type = COLLISION_NODE;
|
||||||
|
|
||||||
info.node_p = node_positions[nearest_boxindex];
|
info.node_p = nearest_info.position;
|
||||||
info.bouncy = bouncy;
|
info.bouncy = bouncy;
|
||||||
info.old_speed = *speed_f;
|
info.old_speed = *speed_f;
|
||||||
|
|
||||||
// Set the speed component that caused the collision to zero
|
// Set the speed component that caused the collision to zero
|
||||||
if (step_up) {
|
if (step_up) {
|
||||||
// Special case: Handle stairs
|
// Special case: Handle stairs
|
||||||
is_step_up[nearest_boxindex] = true;
|
nearest_info.is_step_up = true;
|
||||||
is_collision = false;
|
is_collision = false;
|
||||||
} else if(nearest_collided == 0) { // X
|
} else if (nearest_collided == 0) { // X
|
||||||
if (fabs(speed_f->X) > BS * 3)
|
if (fabs(speed_f->X) > BS * 3)
|
||||||
speed_f->X *= bounce;
|
speed_f->X *= bounce;
|
||||||
else
|
else
|
||||||
speed_f->X = 0;
|
speed_f->X = 0;
|
||||||
result.collides = true;
|
result.collides = true;
|
||||||
result.collides_xz = true;
|
result.collides_xz = true;
|
||||||
}
|
} else if (nearest_collided == 1) { // Y
|
||||||
else if(nearest_collided == 1) { // Y
|
if(fabs(speed_f->Y) > BS * 3)
|
||||||
if (fabs(speed_f->Y) > BS * 3)
|
|
||||||
speed_f->Y *= bounce;
|
speed_f->Y *= bounce;
|
||||||
else
|
else
|
||||||
speed_f->Y = 0;
|
speed_f->Y = 0;
|
||||||
result.collides = true;
|
result.collides = true;
|
||||||
} else if(nearest_collided == 2) { // Z
|
} else if (nearest_collided == 2) { // Z
|
||||||
if (fabs(speed_f->Z) > BS * 3)
|
if (fabs(speed_f->Z) > BS * 3)
|
||||||
speed_f->Z *= bounce;
|
speed_f->Z *= bounce;
|
||||||
else
|
else
|
||||||
|
@ -560,8 +553,9 @@ collisionMoveResult collisionMoveSimple(Environment *env, IGameDef *gamedef,
|
||||||
aabb3f box = box_0;
|
aabb3f box = box_0;
|
||||||
box.MinEdge += *pos_f;
|
box.MinEdge += *pos_f;
|
||||||
box.MaxEdge += *pos_f;
|
box.MaxEdge += *pos_f;
|
||||||
for (u32 boxindex = 0; boxindex < cboxes.size(); boxindex++) {
|
for (u32 boxindex = 0; boxindex < cinfo.size(); boxindex++) {
|
||||||
const aabb3f& cbox = cboxes[boxindex];
|
NearbyCollisionInfo &box_info = cinfo[boxindex];
|
||||||
|
const aabb3f &cbox = box_info.box;
|
||||||
|
|
||||||
/*
|
/*
|
||||||
See if the object is touching ground.
|
See if the object is touching ground.
|
||||||
|
@ -575,8 +569,8 @@ collisionMoveResult collisionMoveSimple(Environment *env, IGameDef *gamedef,
|
||||||
if (cbox.MaxEdge.X - d > box.MinEdge.X && cbox.MinEdge.X + d < box.MaxEdge.X &&
|
if (cbox.MaxEdge.X - d > box.MinEdge.X && cbox.MinEdge.X + d < box.MaxEdge.X &&
|
||||||
cbox.MaxEdge.Z - d > box.MinEdge.Z &&
|
cbox.MaxEdge.Z - d > box.MinEdge.Z &&
|
||||||
cbox.MinEdge.Z + d < box.MaxEdge.Z) {
|
cbox.MinEdge.Z + d < box.MaxEdge.Z) {
|
||||||
if (is_step_up[boxindex]) {
|
if (box_info.is_step_up) {
|
||||||
pos_f->Y += (cbox.MaxEdge.Y - box.MinEdge.Y);
|
pos_f->Y += cbox.MaxEdge.Y - box.MinEdge.Y;
|
||||||
box = box_0;
|
box = box_0;
|
||||||
box.MinEdge += *pos_f;
|
box.MinEdge += *pos_f;
|
||||||
box.MaxEdge += *pos_f;
|
box.MaxEdge += *pos_f;
|
||||||
|
@ -584,9 +578,9 @@ collisionMoveResult collisionMoveSimple(Environment *env, IGameDef *gamedef,
|
||||||
if (fabs(cbox.MaxEdge.Y - box.MinEdge.Y) < 0.15 * BS) {
|
if (fabs(cbox.MaxEdge.Y - box.MinEdge.Y) < 0.15 * BS) {
|
||||||
result.touching_ground = true;
|
result.touching_ground = true;
|
||||||
|
|
||||||
if (is_object[boxindex])
|
if (box_info.is_object)
|
||||||
result.standing_on_object = true;
|
result.standing_on_object = true;
|
||||||
if (is_unloaded[boxindex])
|
if (box_info.is_unloaded)
|
||||||
result.standing_on_unloaded = true;
|
result.standing_on_unloaded = true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -112,7 +112,7 @@ with this program; if not, write to the Free Software Foundation, Inc.,
|
||||||
#if defined(_WIN32)
|
#if defined(_WIN32)
|
||||||
#define TTF_DEFAULT_FONT_SIZE (18)
|
#define TTF_DEFAULT_FONT_SIZE (18)
|
||||||
#else
|
#else
|
||||||
#define TTF_DEFAULT_FONT_SIZE (15)
|
#define TTF_DEFAULT_FONT_SIZE (16)
|
||||||
#endif
|
#endif
|
||||||
#define DEFAULT_FONT_SIZE (10)
|
#define DEFAULT_FONT_SIZE (10)
|
||||||
|
|
||||||
|
|
|
@ -566,7 +566,7 @@ GenericCAO::GenericCAO(IGameDef *gamedef, ClientEnvironment *env):
|
||||||
m_animation_speed(15),
|
m_animation_speed(15),
|
||||||
m_animation_blend(0),
|
m_animation_blend(0),
|
||||||
m_animation_loop(true),
|
m_animation_loop(true),
|
||||||
m_bone_position(std::map<std::string, core::vector2d<v3f> >()),
|
m_bone_position(UNORDERED_MAP<std::string, core::vector2d<v3f> >()),
|
||||||
m_attachment_bone(""),
|
m_attachment_bone(""),
|
||||||
m_attachment_position(v3f(0,0,0)),
|
m_attachment_position(v3f(0,0,0)),
|
||||||
m_attachment_rotation(v3f(0,0,0)),
|
m_attachment_rotation(v3f(0,0,0)),
|
||||||
|
@ -1573,10 +1573,8 @@ void GenericCAO::updateBonePosition()
|
||||||
return;
|
return;
|
||||||
|
|
||||||
m_animated_meshnode->setJointMode(irr::scene::EJUOR_CONTROL); // To write positions to the mesh on render
|
m_animated_meshnode->setJointMode(irr::scene::EJUOR_CONTROL); // To write positions to the mesh on render
|
||||||
for(std::map<std::string,
|
for(UNORDERED_MAP<std::string, core::vector2d<v3f> >::const_iterator
|
||||||
core::vector2d<v3f> >::const_iterator ii = m_bone_position.begin();
|
ii = m_bone_position.begin(); ii != m_bone_position.end(); ++ii) {
|
||||||
ii != m_bone_position.end(); ++ii)
|
|
||||||
{
|
|
||||||
std::string bone_name = (*ii).first;
|
std::string bone_name = (*ii).first;
|
||||||
v3f bone_pos = (*ii).second.X;
|
v3f bone_pos = (*ii).second.X;
|
||||||
v3f bone_rot = (*ii).second.Y;
|
v3f bone_rot = (*ii).second.Y;
|
||||||
|
|
|
@ -90,7 +90,7 @@ private:
|
||||||
int m_animation_speed;
|
int m_animation_speed;
|
||||||
int m_animation_blend;
|
int m_animation_blend;
|
||||||
bool m_animation_loop;
|
bool m_animation_loop;
|
||||||
std::map<std::string, core::vector2d<v3f> > m_bone_position; // stores position and rotation for each bone name
|
UNORDERED_MAP<std::string, core::vector2d<v3f> > m_bone_position; // stores position and rotation for each bone name
|
||||||
std::string m_attachment_bone;
|
std::string m_attachment_bone;
|
||||||
v3f m_attachment_position;
|
v3f m_attachment_position;
|
||||||
v3f m_attachment_rotation;
|
v3f m_attachment_rotation;
|
||||||
|
|
|
@ -172,6 +172,15 @@ static inline void getNeighborConnectingFace(v3s16 p, INodeDefManager *nodedef,
|
||||||
*neighbors |= v;
|
*neighbors |= v;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// For use in mapblock_mesh_generate_special
|
||||||
|
// X,Y,Z of position must be -1,0,1
|
||||||
|
// This expression is a simplification of
|
||||||
|
// 3 * 3 * (pos.X + 1) + 3 * (pos.Y + 1) + (pos.Z + 1)
|
||||||
|
static inline int NeighborToIndex(const v3s16 &pos)
|
||||||
|
{
|
||||||
|
return 9 * pos.X + 3 * pos.Y + pos.Z + 13;
|
||||||
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
TODO: Fix alpha blending for special nodes
|
TODO: Fix alpha blending for special nodes
|
||||||
Currently only the last element rendered is blended correct
|
Currently only the last element rendered is blended correct
|
||||||
|
@ -401,9 +410,14 @@ void mapblock_mesh_generate_special(MeshMakeData *data,
|
||||||
|
|
||||||
// Neighbor liquid levels (key = relative position)
|
// Neighbor liquid levels (key = relative position)
|
||||||
// Includes current node
|
// Includes current node
|
||||||
std::map<v3s16, f32> neighbor_levels;
|
|
||||||
std::map<v3s16, content_t> neighbor_contents;
|
struct NeighborData {
|
||||||
std::map<v3s16, u8> neighbor_flags;
|
f32 level;
|
||||||
|
content_t content;
|
||||||
|
u8 flags;
|
||||||
|
};
|
||||||
|
NeighborData neighbor_data_matrix[27];
|
||||||
|
|
||||||
const u8 neighborflag_top_is_same_liquid = 0x01;
|
const u8 neighborflag_top_is_same_liquid = 0x01;
|
||||||
v3s16 neighbor_dirs[9] = {
|
v3s16 neighbor_dirs[9] = {
|
||||||
v3s16(0,0,0),
|
v3s16(0,0,0),
|
||||||
|
@ -449,9 +463,12 @@ void mapblock_mesh_generate_special(MeshMakeData *data,
|
||||||
flags |= neighborflag_top_is_same_liquid;
|
flags |= neighborflag_top_is_same_liquid;
|
||||||
}
|
}
|
||||||
|
|
||||||
neighbor_levels[neighbor_dirs[i]] = level;
|
NeighborData &neighbor_data =
|
||||||
neighbor_contents[neighbor_dirs[i]] = content;
|
neighbor_data_matrix[NeighborToIndex(neighbor_dirs[i])];
|
||||||
neighbor_flags[neighbor_dirs[i]] = flags;
|
|
||||||
|
neighbor_data.level = level;
|
||||||
|
neighbor_data.content = content;
|
||||||
|
neighbor_data.flags = flags;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Corner heights (average between four liquids)
|
// Corner heights (average between four liquids)
|
||||||
|
@ -472,10 +489,12 @@ void mapblock_mesh_generate_special(MeshMakeData *data,
|
||||||
for(u32 j=0; j<4; j++)
|
for(u32 j=0; j<4; j++)
|
||||||
{
|
{
|
||||||
v3s16 neighbordir = cornerdir - halfdirs[j];
|
v3s16 neighbordir = cornerdir - halfdirs[j];
|
||||||
content_t content = neighbor_contents[neighbordir];
|
|
||||||
|
NeighborData &neighbor_data =
|
||||||
|
neighbor_data_matrix[NeighborToIndex(neighbordir)];
|
||||||
|
content_t content = neighbor_data.content;
|
||||||
// If top is liquid, draw starting from top of node
|
// If top is liquid, draw starting from top of node
|
||||||
if(neighbor_flags[neighbordir] &
|
if (neighbor_data.flags & neighborflag_top_is_same_liquid)
|
||||||
neighborflag_top_is_same_liquid)
|
|
||||||
{
|
{
|
||||||
cornerlevel = 0.5*BS;
|
cornerlevel = 0.5*BS;
|
||||||
valid_count = 1;
|
valid_count = 1;
|
||||||
|
@ -491,7 +510,7 @@ void mapblock_mesh_generate_special(MeshMakeData *data,
|
||||||
// Flowing liquid has level information
|
// Flowing liquid has level information
|
||||||
else if(content == c_flowing)
|
else if(content == c_flowing)
|
||||||
{
|
{
|
||||||
cornerlevel += neighbor_levels[neighbordir];
|
cornerlevel += neighbor_data.level;
|
||||||
valid_count++;
|
valid_count++;
|
||||||
}
|
}
|
||||||
else if(content == CONTENT_AIR)
|
else if(content == CONTENT_AIR)
|
||||||
|
@ -526,15 +545,17 @@ void mapblock_mesh_generate_special(MeshMakeData *data,
|
||||||
{
|
{
|
||||||
v3s16 dir = side_dirs[i];
|
v3s16 dir = side_dirs[i];
|
||||||
|
|
||||||
|
NeighborData& neighbor_data =
|
||||||
|
neighbor_data_matrix[NeighborToIndex(dir)];
|
||||||
/*
|
/*
|
||||||
If our topside is liquid and neighbor's topside
|
If our topside is liquid and neighbor's topside
|
||||||
is liquid, don't draw side face
|
is liquid, don't draw side face
|
||||||
*/
|
*/
|
||||||
if(top_is_same_liquid &&
|
if (top_is_same_liquid &&
|
||||||
neighbor_flags[dir] & neighborflag_top_is_same_liquid)
|
neighbor_data.flags & neighborflag_top_is_same_liquid)
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
content_t neighbor_content = neighbor_contents[dir];
|
content_t neighbor_content = neighbor_data.content;
|
||||||
const ContentFeatures &n_feat = nodedef->get(neighbor_content);
|
const ContentFeatures &n_feat = nodedef->get(neighbor_content);
|
||||||
|
|
||||||
// Don't draw face if neighbor is blocking the view
|
// Don't draw face if neighbor is blocking the view
|
||||||
|
@ -1138,7 +1159,7 @@ void mapblock_mesh_generate_special(MeshMakeData *data,
|
||||||
u8 p2mesh = 0;
|
u8 p2mesh = 0;
|
||||||
if (f.param_type_2 == CPT2_DEGROTATE)
|
if (f.param_type_2 == CPT2_DEGROTATE)
|
||||||
rotate_degree = n.param2 * 2;
|
rotate_degree = n.param2 * 2;
|
||||||
else if (f.param_type_2 != CPT2_MESHOPTIONS) {
|
if (f.param_type_2 != CPT2_MESHOPTIONS) {
|
||||||
if (j == 0) {
|
if (j == 0) {
|
||||||
for (u16 i = 0; i < 4; i++)
|
for (u16 i = 0; i < 4; i++)
|
||||||
vertices[i].Pos.rotateXZBy(46 + rotate_degree);
|
vertices[i].Pos.rotateXZBy(46 + rotate_degree);
|
||||||
|
@ -1506,8 +1527,8 @@ void mapblock_mesh_generate_special(MeshMakeData *data,
|
||||||
continue;
|
continue;
|
||||||
MapNode n_xy = data->m_vmanip.getNodeNoEx(blockpos_nodes + v3s16(x + xz, y + y0, z));
|
MapNode n_xy = data->m_vmanip.getNodeNoEx(blockpos_nodes + v3s16(x + xz, y + y0, z));
|
||||||
MapNode n_zy = data->m_vmanip.getNodeNoEx(blockpos_nodes + v3s16(x, y + y0, z + xz));
|
MapNode n_zy = data->m_vmanip.getNodeNoEx(blockpos_nodes + v3s16(x, y + y0, z + xz));
|
||||||
ContentFeatures def_xy = nodedef->get(n_xy);
|
const ContentFeatures &def_xy = nodedef->get(n_xy);
|
||||||
ContentFeatures def_zy = nodedef->get(n_zy);
|
const ContentFeatures &def_zy = nodedef->get(n_zy);
|
||||||
|
|
||||||
// Check if current node would connect with the rail
|
// Check if current node would connect with the rail
|
||||||
is_rail_x[index] = ((def_xy.drawtype == NDT_RAILLIKE
|
is_rail_x[index] = ((def_xy.drawtype == NDT_RAILLIKE
|
||||||
|
|
|
@ -213,7 +213,7 @@ void set_default_settings(Settings *settings)
|
||||||
settings->setDefault("freetype", "true");
|
settings->setDefault("freetype", "true");
|
||||||
settings->setDefault("font_path", porting::getDataPath("fonts" DIR_DELIM "liberationsans.ttf"));
|
settings->setDefault("font_path", porting::getDataPath("fonts" DIR_DELIM "liberationsans.ttf"));
|
||||||
settings->setDefault("font_shadow", "1");
|
settings->setDefault("font_shadow", "1");
|
||||||
settings->setDefault("font_shadow_alpha", "128");
|
settings->setDefault("font_shadow_alpha", "127");
|
||||||
settings->setDefault("mono_font_path", porting::getDataPath("fonts" DIR_DELIM "liberationmono.ttf"));
|
settings->setDefault("mono_font_path", porting::getDataPath("fonts" DIR_DELIM "liberationmono.ttf"));
|
||||||
settings->setDefault("fallback_font_path", porting::getDataPath("fonts" DIR_DELIM "DroidSansFallbackFull.ttf"));
|
settings->setDefault("fallback_font_path", porting::getDataPath("fonts" DIR_DELIM "DroidSansFallbackFull.ttf"));
|
||||||
|
|
||||||
|
@ -285,6 +285,9 @@ void set_default_settings(Settings *settings)
|
||||||
settings->setDefault("server_unload_unused_data_timeout", "29");
|
settings->setDefault("server_unload_unused_data_timeout", "29");
|
||||||
settings->setDefault("max_objects_per_block", "49");
|
settings->setDefault("max_objects_per_block", "49");
|
||||||
settings->setDefault("server_map_save_interval", "5.3");
|
settings->setDefault("server_map_save_interval", "5.3");
|
||||||
|
settings->setDefault("chat_message_max_size", "500");
|
||||||
|
settings->setDefault("chat_message_limit_per_10sec", "8.0");
|
||||||
|
settings->setDefault("chat_message_limit_trigger_kick", "50");
|
||||||
settings->setDefault("sqlite_synchronous", "2");
|
settings->setDefault("sqlite_synchronous", "2");
|
||||||
settings->setDefault("full_block_send_enable_min_time_from_building", "2.0");
|
settings->setDefault("full_block_send_enable_min_time_from_building", "2.0");
|
||||||
settings->setDefault("dedicated_server_step", "0.1");
|
settings->setDefault("dedicated_server_step", "0.1");
|
||||||
|
|
|
@ -369,12 +369,10 @@ bool EmergeManager::pushBlockEmergeData(
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
bool EmergeManager::popBlockEmergeData(
|
bool EmergeManager::popBlockEmergeData(v3s16 pos, BlockEmergeData *bedata)
|
||||||
v3s16 pos,
|
|
||||||
BlockEmergeData *bedata)
|
|
||||||
{
|
{
|
||||||
std::map<v3s16, BlockEmergeData>::iterator it;
|
std::map<v3s16, BlockEmergeData>::iterator it;
|
||||||
std::map<u16, u16>::iterator it2;
|
UNORDERED_MAP<u16, u16>::iterator it2;
|
||||||
|
|
||||||
it = m_blocks_enqueued.find(pos);
|
it = m_blocks_enqueued.find(pos);
|
||||||
if (it == m_blocks_enqueued.end())
|
if (it == m_blocks_enqueued.end())
|
||||||
|
|
|
@ -156,7 +156,7 @@ private:
|
||||||
|
|
||||||
Mutex m_queue_mutex;
|
Mutex m_queue_mutex;
|
||||||
std::map<v3s16, BlockEmergeData> m_blocks_enqueued;
|
std::map<v3s16, BlockEmergeData> m_blocks_enqueued;
|
||||||
std::map<u16, u16> m_peer_queue_count;
|
UNORDERED_MAP<u16, u16> m_peer_queue_count;
|
||||||
|
|
||||||
u16 m_qlimit_total;
|
u16 m_qlimit_total;
|
||||||
u16 m_qlimit_diskonly;
|
u16 m_qlimit_diskonly;
|
||||||
|
|
|
@ -1146,14 +1146,12 @@ bool ServerEnvironment::swapNode(v3s16 p, const MapNode &n)
|
||||||
|
|
||||||
void ServerEnvironment::getObjectsInsideRadius(std::vector<u16> &objects, v3f pos, float radius)
|
void ServerEnvironment::getObjectsInsideRadius(std::vector<u16> &objects, v3f pos, float radius)
|
||||||
{
|
{
|
||||||
for(std::map<u16, ServerActiveObject*>::iterator
|
for (ActiveObjectMap::iterator i = m_active_objects.begin();
|
||||||
i = m_active_objects.begin();
|
i != m_active_objects.end(); ++i) {
|
||||||
i != m_active_objects.end(); ++i)
|
|
||||||
{
|
|
||||||
ServerActiveObject* obj = i->second;
|
ServerActiveObject* obj = i->second;
|
||||||
u16 id = i->first;
|
u16 id = i->first;
|
||||||
v3f objectpos = obj->getBasePosition();
|
v3f objectpos = obj->getBasePosition();
|
||||||
if(objectpos.getDistanceFrom(pos) > radius)
|
if (objectpos.getDistanceFrom(pos) > radius)
|
||||||
continue;
|
continue;
|
||||||
objects.push_back(id);
|
objects.push_back(id);
|
||||||
}
|
}
|
||||||
|
@ -1164,8 +1162,7 @@ void ServerEnvironment::clearObjects(ClearObjectsMode mode)
|
||||||
infostream << "ServerEnvironment::clearObjects(): "
|
infostream << "ServerEnvironment::clearObjects(): "
|
||||||
<< "Removing all active objects" << std::endl;
|
<< "Removing all active objects" << std::endl;
|
||||||
std::vector<u16> objects_to_remove;
|
std::vector<u16> objects_to_remove;
|
||||||
for (std::map<u16, ServerActiveObject*>::iterator
|
for (ActiveObjectMap::iterator i = m_active_objects.begin();
|
||||||
i = m_active_objects.begin();
|
|
||||||
i != m_active_objects.end(); ++i) {
|
i != m_active_objects.end(); ++i) {
|
||||||
ServerActiveObject* obj = i->second;
|
ServerActiveObject* obj = i->second;
|
||||||
if (obj->getType() == ACTIVEOBJECT_TYPE_PLAYER)
|
if (obj->getType() == ACTIVEOBJECT_TYPE_PLAYER)
|
||||||
|
@ -1540,10 +1537,8 @@ void ServerEnvironment::step(float dtime)
|
||||||
send_recommended = true;
|
send_recommended = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
for(std::map<u16, ServerActiveObject*>::iterator
|
for(ActiveObjectMap::iterator i = m_active_objects.begin();
|
||||||
i = m_active_objects.begin();
|
i != m_active_objects.end(); ++i) {
|
||||||
i != m_active_objects.end(); ++i)
|
|
||||||
{
|
|
||||||
ServerActiveObject* obj = i->second;
|
ServerActiveObject* obj = i->second;
|
||||||
// Don't step if is to be removed or stored statically
|
// Don't step if is to be removed or stored statically
|
||||||
if(obj->m_removed || obj->m_pending_deactivation)
|
if(obj->m_removed || obj->m_pending_deactivation)
|
||||||
|
@ -1576,7 +1571,7 @@ void ServerEnvironment::step(float dtime)
|
||||||
Manage particle spawner expiration
|
Manage particle spawner expiration
|
||||||
*/
|
*/
|
||||||
if (m_particle_management_interval.step(dtime, 1.0)) {
|
if (m_particle_management_interval.step(dtime, 1.0)) {
|
||||||
for (std::map<u32, float>::iterator i = m_particle_spawners.begin();
|
for (UNORDERED_MAP<u32, float>::iterator i = m_particle_spawners.begin();
|
||||||
i != m_particle_spawners.end(); ) {
|
i != m_particle_spawners.end(); ) {
|
||||||
//non expiring spawners
|
//non expiring spawners
|
||||||
if (i->second == PARTICLE_SPAWNER_NO_EXPIRY) {
|
if (i->second == PARTICLE_SPAWNER_NO_EXPIRY) {
|
||||||
|
@ -1601,8 +1596,7 @@ u32 ServerEnvironment::addParticleSpawner(float exptime)
|
||||||
u32 id = 0;
|
u32 id = 0;
|
||||||
for (;;) { // look for unused particlespawner id
|
for (;;) { // look for unused particlespawner id
|
||||||
id++;
|
id++;
|
||||||
std::map<u32, float>::iterator f;
|
UNORDERED_MAP<u32, float>::iterator f = m_particle_spawners.find(id);
|
||||||
f = m_particle_spawners.find(id);
|
|
||||||
if (f == m_particle_spawners.end()) {
|
if (f == m_particle_spawners.end()) {
|
||||||
m_particle_spawners[id] = time;
|
m_particle_spawners[id] = time;
|
||||||
break;
|
break;
|
||||||
|
@ -1611,31 +1605,21 @@ u32 ServerEnvironment::addParticleSpawner(float exptime)
|
||||||
return id;
|
return id;
|
||||||
}
|
}
|
||||||
|
|
||||||
void ServerEnvironment::deleteParticleSpawner(u32 id)
|
|
||||||
{
|
|
||||||
m_particle_spawners.erase(id);
|
|
||||||
}
|
|
||||||
|
|
||||||
ServerActiveObject* ServerEnvironment::getActiveObject(u16 id)
|
ServerActiveObject* ServerEnvironment::getActiveObject(u16 id)
|
||||||
{
|
{
|
||||||
std::map<u16, ServerActiveObject*>::iterator n;
|
ActiveObjectMap::iterator n = m_active_objects.find(id);
|
||||||
n = m_active_objects.find(id);
|
return (n != m_active_objects.end() ? n->second : NULL);
|
||||||
if(n == m_active_objects.end())
|
|
||||||
return NULL;
|
|
||||||
return n->second;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
bool isFreeServerActiveObjectId(u16 id,
|
bool isFreeServerActiveObjectId(u16 id, ActiveObjectMap &objects)
|
||||||
std::map<u16, ServerActiveObject*> &objects)
|
|
||||||
{
|
{
|
||||||
if(id == 0)
|
if (id == 0)
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
return objects.find(id) == objects.end();
|
return objects.find(id) == objects.end();
|
||||||
}
|
}
|
||||||
|
|
||||||
u16 getFreeServerActiveObjectId(
|
u16 getFreeServerActiveObjectId(ActiveObjectMap &objects)
|
||||||
std::map<u16, ServerActiveObject*> &objects)
|
|
||||||
{
|
{
|
||||||
//try to reuse id's as late as possible
|
//try to reuse id's as late as possible
|
||||||
static u16 last_used_id = 0;
|
static u16 last_used_id = 0;
|
||||||
|
@ -1684,8 +1668,7 @@ void ServerEnvironment::getAddedActiveObjects(Player *player, s16 radius,
|
||||||
- discard objects that are found in current_objects.
|
- discard objects that are found in current_objects.
|
||||||
- add remaining objects to added_objects
|
- add remaining objects to added_objects
|
||||||
*/
|
*/
|
||||||
for(std::map<u16, ServerActiveObject*>::iterator
|
for(ActiveObjectMap::iterator i = m_active_objects.begin();
|
||||||
i = m_active_objects.begin();
|
|
||||||
i != m_active_objects.end(); ++i) {
|
i != m_active_objects.end(); ++i) {
|
||||||
u16 id = i->first;
|
u16 id = i->first;
|
||||||
|
|
||||||
|
@ -1810,8 +1793,7 @@ void ServerEnvironment::setStaticForActiveObjectsInBlock(
|
||||||
so_it = block->m_static_objects.m_active.begin();
|
so_it = block->m_static_objects.m_active.begin();
|
||||||
so_it != block->m_static_objects.m_active.end(); ++so_it) {
|
so_it != block->m_static_objects.m_active.end(); ++so_it) {
|
||||||
// Get the ServerActiveObject counterpart to this StaticObject
|
// Get the ServerActiveObject counterpart to this StaticObject
|
||||||
std::map<u16, ServerActiveObject *>::iterator ao_it;
|
ActiveObjectMap::iterator ao_it = m_active_objects.find(so_it->first);
|
||||||
ao_it = m_active_objects.find(so_it->first);
|
|
||||||
if (ao_it == m_active_objects.end()) {
|
if (ao_it == m_active_objects.end()) {
|
||||||
// If this ever happens, there must be some kind of nasty bug.
|
// If this ever happens, there must be some kind of nasty bug.
|
||||||
errorstream << "ServerEnvironment::setStaticForObjectsInBlock(): "
|
errorstream << "ServerEnvironment::setStaticForObjectsInBlock(): "
|
||||||
|
@ -1860,8 +1842,8 @@ u16 ServerEnvironment::addActiveObjectRaw(ServerActiveObject *object,
|
||||||
verbosestream<<"ServerEnvironment::addActiveObjectRaw(): "
|
verbosestream<<"ServerEnvironment::addActiveObjectRaw(): "
|
||||||
<<"supplied with id "<<object->getId()<<std::endl;
|
<<"supplied with id "<<object->getId()<<std::endl;
|
||||||
}
|
}
|
||||||
if(isFreeServerActiveObjectId(object->getId(), m_active_objects) == false)
|
|
||||||
{
|
if(!isFreeServerActiveObjectId(object->getId(), m_active_objects)) {
|
||||||
errorstream<<"ServerEnvironment::addActiveObjectRaw(): "
|
errorstream<<"ServerEnvironment::addActiveObjectRaw(): "
|
||||||
<<"id is not free ("<<object->getId()<<")"<<std::endl;
|
<<"id is not free ("<<object->getId()<<")"<<std::endl;
|
||||||
if(object->environmentDeletes())
|
if(object->environmentDeletes())
|
||||||
|
@ -1929,8 +1911,7 @@ u16 ServerEnvironment::addActiveObjectRaw(ServerActiveObject *object,
|
||||||
void ServerEnvironment::removeRemovedObjects()
|
void ServerEnvironment::removeRemovedObjects()
|
||||||
{
|
{
|
||||||
std::vector<u16> objects_to_remove;
|
std::vector<u16> objects_to_remove;
|
||||||
for(std::map<u16, ServerActiveObject*>::iterator
|
for(ActiveObjectMap::iterator i = m_active_objects.begin();
|
||||||
i = m_active_objects.begin();
|
|
||||||
i != m_active_objects.end(); ++i) {
|
i != m_active_objects.end(); ++i) {
|
||||||
u16 id = i->first;
|
u16 id = i->first;
|
||||||
ServerActiveObject* obj = i->second;
|
ServerActiveObject* obj = i->second;
|
||||||
|
@ -1948,7 +1929,7 @@ void ServerEnvironment::removeRemovedObjects()
|
||||||
We will delete objects that are marked as removed or thatare
|
We will delete objects that are marked as removed or thatare
|
||||||
waiting for deletion after deactivation
|
waiting for deletion after deactivation
|
||||||
*/
|
*/
|
||||||
if(obj->m_removed == false && obj->m_pending_deactivation == false)
|
if (!obj->m_removed && !obj->m_pending_deactivation)
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
@ -2148,8 +2129,7 @@ void ServerEnvironment::activateObjects(MapBlock *block, u32 dtime_s)
|
||||||
void ServerEnvironment::deactivateFarObjects(bool force_delete)
|
void ServerEnvironment::deactivateFarObjects(bool force_delete)
|
||||||
{
|
{
|
||||||
std::vector<u16> objects_to_remove;
|
std::vector<u16> objects_to_remove;
|
||||||
for(std::map<u16, ServerActiveObject*>::iterator
|
for(ActiveObjectMap::iterator i = m_active_objects.begin();
|
||||||
i = m_active_objects.begin();
|
|
||||||
i != m_active_objects.end(); ++i) {
|
i != m_active_objects.end(); ++i) {
|
||||||
ServerActiveObject* obj = i->second;
|
ServerActiveObject* obj = i->second;
|
||||||
assert(obj);
|
assert(obj);
|
||||||
|
|
|
@ -300,6 +300,8 @@ enum ClearObjectsMode {
|
||||||
This is not thread-safe. Server uses an environment mutex.
|
This is not thread-safe. Server uses an environment mutex.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
typedef UNORDERED_MAP<u16, ServerActiveObject *> ActiveObjectMap;
|
||||||
|
|
||||||
class ServerEnvironment : public Environment
|
class ServerEnvironment : public Environment
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
|
@ -338,7 +340,7 @@ public:
|
||||||
void loadDefaultMeta();
|
void loadDefaultMeta();
|
||||||
|
|
||||||
u32 addParticleSpawner(float exptime);
|
u32 addParticleSpawner(float exptime);
|
||||||
void deleteParticleSpawner(u32 id);
|
void deleteParticleSpawner(u32 id) { m_particle_spawners.erase(id); }
|
||||||
|
|
||||||
/*
|
/*
|
||||||
External ActiveObject interface
|
External ActiveObject interface
|
||||||
|
@ -491,7 +493,7 @@ private:
|
||||||
// World path
|
// World path
|
||||||
const std::string m_path_world;
|
const std::string m_path_world;
|
||||||
// Active object list
|
// Active object list
|
||||||
std::map<u16, ServerActiveObject*> m_active_objects;
|
ActiveObjectMap m_active_objects;
|
||||||
// Outgoing network message buffer for active objects
|
// Outgoing network message buffer for active objects
|
||||||
std::queue<ActiveObjectMessage> m_active_object_messages;
|
std::queue<ActiveObjectMessage> m_active_object_messages;
|
||||||
// Some timers
|
// Some timers
|
||||||
|
@ -522,7 +524,7 @@ private:
|
||||||
|
|
||||||
// Particles
|
// Particles
|
||||||
IntervalLimiter m_particle_management_interval;
|
IntervalLimiter m_particle_management_interval;
|
||||||
std::map<u32, float> m_particle_spawners;
|
UNORDERED_MAP<u32, float> m_particle_spawners;
|
||||||
};
|
};
|
||||||
|
|
||||||
#ifndef SERVER
|
#ifndef SERVER
|
||||||
|
|
|
@ -605,7 +605,7 @@ public:
|
||||||
void draw(s32 x_left, s32 y_bottom, video::IVideoDriver *driver,
|
void draw(s32 x_left, s32 y_bottom, video::IVideoDriver *driver,
|
||||||
gui::IGUIFont *font) const
|
gui::IGUIFont *font) const
|
||||||
{
|
{
|
||||||
std::map<std::string, Meta> m_meta;
|
UNORDERED_MAP<std::string, Meta> m_meta;
|
||||||
|
|
||||||
for (std::deque<Piece>::const_iterator k = m_log.begin();
|
for (std::deque<Piece>::const_iterator k = m_log.begin();
|
||||||
k != m_log.end(); ++k) {
|
k != m_log.end(); ++k) {
|
||||||
|
@ -615,8 +615,7 @@ public:
|
||||||
i != piece.values.end(); ++i) {
|
i != piece.values.end(); ++i) {
|
||||||
const std::string &id = i->first;
|
const std::string &id = i->first;
|
||||||
const float &value = i->second;
|
const float &value = i->second;
|
||||||
std::map<std::string, Meta>::iterator j =
|
UNORDERED_MAP<std::string, Meta>::iterator j = m_meta.find(id);
|
||||||
m_meta.find(id);
|
|
||||||
|
|
||||||
if (j == m_meta.end()) {
|
if (j == m_meta.end()) {
|
||||||
m_meta[id] = Meta(value);
|
m_meta[id] = Meta(value);
|
||||||
|
@ -643,7 +642,7 @@ public:
|
||||||
sizeof(usable_colors) / sizeof(*usable_colors);
|
sizeof(usable_colors) / sizeof(*usable_colors);
|
||||||
u32 next_color_i = 0;
|
u32 next_color_i = 0;
|
||||||
|
|
||||||
for (std::map<std::string, Meta>::iterator i = m_meta.begin();
|
for (UNORDERED_MAP<std::string, Meta>::iterator i = m_meta.begin();
|
||||||
i != m_meta.end(); ++i) {
|
i != m_meta.end(); ++i) {
|
||||||
Meta &meta = i->second;
|
Meta &meta = i->second;
|
||||||
video::SColor color(255, 200, 200, 200);
|
video::SColor color(255, 200, 200, 200);
|
||||||
|
@ -659,7 +658,7 @@ public:
|
||||||
s32 textx2 = textx + 200 - 15;
|
s32 textx2 = textx + 200 - 15;
|
||||||
s32 meta_i = 0;
|
s32 meta_i = 0;
|
||||||
|
|
||||||
for (std::map<std::string, Meta>::const_iterator i = m_meta.begin();
|
for (UNORDERED_MAP<std::string, Meta>::const_iterator i = m_meta.begin();
|
||||||
i != m_meta.end(); ++i) {
|
i != m_meta.end(); ++i) {
|
||||||
const std::string &id = i->first;
|
const std::string &id = i->first;
|
||||||
const Meta &meta = i->second;
|
const Meta &meta = i->second;
|
||||||
|
|
|
@ -279,6 +279,32 @@ void GUIFormSpecMenu::parseSize(parserData* data,std::string element)
|
||||||
errorstream<< "Invalid size element (" << parts.size() << "): '" << element << "'" << std::endl;
|
errorstream<< "Invalid size element (" << parts.size() << "): '" << element << "'" << std::endl;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void GUIFormSpecMenu::parseContainer(parserData* data, std::string element)
|
||||||
|
{
|
||||||
|
std::vector<std::string> parts = split(element, ',');
|
||||||
|
|
||||||
|
if (parts.size() >= 2) {
|
||||||
|
if (parts[1].find(';') != std::string::npos)
|
||||||
|
parts[1] = parts[1].substr(0, parts[1].find(';'));
|
||||||
|
|
||||||
|
container_stack.push(pos_offset);
|
||||||
|
pos_offset.X += MYMAX(0, stof(parts[0]));
|
||||||
|
pos_offset.Y += MYMAX(0, stof(parts[1]));
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
errorstream<< "Invalid container start element (" << parts.size() << "): '" << element << "'" << std::endl;
|
||||||
|
}
|
||||||
|
|
||||||
|
void GUIFormSpecMenu::parseContainerEnd(parserData* data)
|
||||||
|
{
|
||||||
|
if (container_stack.empty()) {
|
||||||
|
errorstream<< "Invalid container end element, no matching container start element" << std::endl;
|
||||||
|
} else {
|
||||||
|
pos_offset = container_stack.top();
|
||||||
|
container_stack.pop();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
void GUIFormSpecMenu::parseList(parserData* data,std::string element)
|
void GUIFormSpecMenu::parseList(parserData* data,std::string element)
|
||||||
{
|
{
|
||||||
if (m_gamedef == 0) {
|
if (m_gamedef == 0) {
|
||||||
|
@ -309,7 +335,7 @@ void GUIFormSpecMenu::parseList(parserData* data,std::string element)
|
||||||
else
|
else
|
||||||
loc.deSerialize(location);
|
loc.deSerialize(location);
|
||||||
|
|
||||||
v2s32 pos = padding + AbsoluteRect.UpperLeftCorner;
|
v2s32 pos = padding + AbsoluteRect.UpperLeftCorner + pos_offset * spacing;
|
||||||
pos.X += stof(v_pos[0]) * (float)spacing.X;
|
pos.X += stof(v_pos[0]) * (float)spacing.X;
|
||||||
pos.Y += stof(v_pos[1]) * (float)spacing.Y;
|
pos.Y += stof(v_pos[1]) * (float)spacing.Y;
|
||||||
|
|
||||||
|
@ -386,7 +412,7 @@ void GUIFormSpecMenu::parseCheckbox(parserData* data,std::string element)
|
||||||
|
|
||||||
MY_CHECKPOS("checkbox",0);
|
MY_CHECKPOS("checkbox",0);
|
||||||
|
|
||||||
v2s32 pos = padding;
|
v2s32 pos = padding + pos_offset * spacing;
|
||||||
pos.X += stof(v_pos[0]) * (float) spacing.X;
|
pos.X += stof(v_pos[0]) * (float) spacing.X;
|
||||||
pos.Y += stof(v_pos[1]) * (float) spacing.Y;
|
pos.Y += stof(v_pos[1]) * (float) spacing.Y;
|
||||||
|
|
||||||
|
@ -437,7 +463,7 @@ void GUIFormSpecMenu::parseScrollBar(parserData* data, std::string element)
|
||||||
|
|
||||||
MY_CHECKPOS("scrollbar",0);
|
MY_CHECKPOS("scrollbar",0);
|
||||||
|
|
||||||
v2s32 pos = padding;
|
v2s32 pos = padding + pos_offset * spacing;
|
||||||
pos.X += stof(v_pos[0]) * (float) spacing.X;
|
pos.X += stof(v_pos[0]) * (float) spacing.X;
|
||||||
pos.Y += stof(v_pos[1]) * (float) spacing.Y;
|
pos.Y += stof(v_pos[1]) * (float) spacing.Y;
|
||||||
|
|
||||||
|
@ -495,10 +521,10 @@ void GUIFormSpecMenu::parseImage(parserData* data,std::string element)
|
||||||
std::vector<std::string> v_geom = split(parts[1],',');
|
std::vector<std::string> v_geom = split(parts[1],',');
|
||||||
std::string name = unescape_string(parts[2]);
|
std::string name = unescape_string(parts[2]);
|
||||||
|
|
||||||
MY_CHECKPOS("image",0);
|
MY_CHECKPOS("image", 0);
|
||||||
MY_CHECKGEOM("image",1);
|
MY_CHECKGEOM("image", 1);
|
||||||
|
|
||||||
v2s32 pos = padding + AbsoluteRect.UpperLeftCorner;
|
v2s32 pos = padding + AbsoluteRect.UpperLeftCorner + pos_offset * spacing;
|
||||||
pos.X += stof(v_pos[0]) * (float) spacing.X;
|
pos.X += stof(v_pos[0]) * (float) spacing.X;
|
||||||
pos.Y += stof(v_pos[1]) * (float) spacing.Y;
|
pos.Y += stof(v_pos[1]) * (float) spacing.Y;
|
||||||
|
|
||||||
|
@ -506,23 +532,21 @@ void GUIFormSpecMenu::parseImage(parserData* data,std::string element)
|
||||||
geom.X = stof(v_geom[0]) * (float)imgsize.X;
|
geom.X = stof(v_geom[0]) * (float)imgsize.X;
|
||||||
geom.Y = stof(v_geom[1]) * (float)imgsize.Y;
|
geom.Y = stof(v_geom[1]) * (float)imgsize.Y;
|
||||||
|
|
||||||
if(!data->explicit_size)
|
if (!data->explicit_size)
|
||||||
warningstream<<"invalid use of image without a size[] element"<<std::endl;
|
warningstream<<"invalid use of image without a size[] element"<<std::endl;
|
||||||
m_images.push_back(ImageDrawSpec(name, pos, geom));
|
m_images.push_back(ImageDrawSpec(name, pos, geom));
|
||||||
return;
|
return;
|
||||||
}
|
} else if (parts.size() == 2) {
|
||||||
|
|
||||||
if (parts.size() == 2) {
|
|
||||||
std::vector<std::string> v_pos = split(parts[0],',');
|
std::vector<std::string> v_pos = split(parts[0],',');
|
||||||
std::string name = unescape_string(parts[1]);
|
std::string name = unescape_string(parts[1]);
|
||||||
|
|
||||||
MY_CHECKPOS("image",0);
|
MY_CHECKPOS("image", 0);
|
||||||
|
|
||||||
v2s32 pos = padding + AbsoluteRect.UpperLeftCorner;
|
v2s32 pos = padding + AbsoluteRect.UpperLeftCorner + pos_offset * spacing;
|
||||||
pos.X += stof(v_pos[0]) * (float) spacing.X;
|
pos.X += stof(v_pos[0]) * (float) spacing.X;
|
||||||
pos.Y += stof(v_pos[1]) * (float) spacing.Y;
|
pos.Y += stof(v_pos[1]) * (float) spacing.Y;
|
||||||
|
|
||||||
if(!data->explicit_size)
|
if (!data->explicit_size)
|
||||||
warningstream<<"invalid use of image without a size[] element"<<std::endl;
|
warningstream<<"invalid use of image without a size[] element"<<std::endl;
|
||||||
m_images.push_back(ImageDrawSpec(name, pos));
|
m_images.push_back(ImageDrawSpec(name, pos));
|
||||||
return;
|
return;
|
||||||
|
@ -544,7 +568,7 @@ void GUIFormSpecMenu::parseItemImage(parserData* data,std::string element)
|
||||||
MY_CHECKPOS("itemimage",0);
|
MY_CHECKPOS("itemimage",0);
|
||||||
MY_CHECKGEOM("itemimage",1);
|
MY_CHECKGEOM("itemimage",1);
|
||||||
|
|
||||||
v2s32 pos = padding + AbsoluteRect.UpperLeftCorner;
|
v2s32 pos = padding + AbsoluteRect.UpperLeftCorner + pos_offset * spacing;
|
||||||
pos.X += stof(v_pos[0]) * (float) spacing.X;
|
pos.X += stof(v_pos[0]) * (float) spacing.X;
|
||||||
pos.Y += stof(v_pos[1]) * (float) spacing.Y;
|
pos.Y += stof(v_pos[1]) * (float) spacing.Y;
|
||||||
|
|
||||||
|
@ -576,7 +600,7 @@ void GUIFormSpecMenu::parseButton(parserData* data,std::string element,
|
||||||
MY_CHECKPOS("button",0);
|
MY_CHECKPOS("button",0);
|
||||||
MY_CHECKGEOM("button",1);
|
MY_CHECKGEOM("button",1);
|
||||||
|
|
||||||
v2s32 pos = padding;
|
v2s32 pos = padding + pos_offset * spacing;
|
||||||
pos.X += stof(v_pos[0]) * (float)spacing.X;
|
pos.X += stof(v_pos[0]) * (float)spacing.X;
|
||||||
pos.Y += stof(v_pos[1]) * (float)spacing.Y;
|
pos.Y += stof(v_pos[1]) * (float)spacing.Y;
|
||||||
|
|
||||||
|
@ -629,9 +653,9 @@ void GUIFormSpecMenu::parseBackground(parserData* data,std::string element)
|
||||||
MY_CHECKPOS("background",0);
|
MY_CHECKPOS("background",0);
|
||||||
MY_CHECKGEOM("background",1);
|
MY_CHECKGEOM("background",1);
|
||||||
|
|
||||||
v2s32 pos = padding + AbsoluteRect.UpperLeftCorner;
|
v2s32 pos = padding + AbsoluteRect.UpperLeftCorner + pos_offset * spacing;
|
||||||
pos.X += stof(v_pos[0]) * (float)spacing.X - ((float)spacing.X-(float)imgsize.X)/2;
|
pos.X += stof(v_pos[0]) * (float)spacing.X - ((float)spacing.X - (float)imgsize.X)/2;
|
||||||
pos.Y += stof(v_pos[1]) * (float)spacing.Y - ((float)spacing.Y-(float)imgsize.Y)/2;
|
pos.Y += stof(v_pos[1]) * (float)spacing.Y - ((float)spacing.Y - (float)imgsize.Y)/2;
|
||||||
|
|
||||||
v2s32 geom;
|
v2s32 geom;
|
||||||
geom.X = stof(v_geom[0]) * (float)spacing.X;
|
geom.X = stof(v_geom[0]) * (float)spacing.X;
|
||||||
|
@ -705,7 +729,7 @@ void GUIFormSpecMenu::parseTable(parserData* data,std::string element)
|
||||||
MY_CHECKPOS("table",0);
|
MY_CHECKPOS("table",0);
|
||||||
MY_CHECKGEOM("table",1);
|
MY_CHECKGEOM("table",1);
|
||||||
|
|
||||||
v2s32 pos = padding;
|
v2s32 pos = padding + pos_offset * spacing;
|
||||||
pos.X += stof(v_pos[0]) * (float)spacing.X;
|
pos.X += stof(v_pos[0]) * (float)spacing.X;
|
||||||
pos.Y += stof(v_pos[1]) * (float)spacing.Y;
|
pos.Y += stof(v_pos[1]) * (float)spacing.Y;
|
||||||
|
|
||||||
|
@ -776,7 +800,7 @@ void GUIFormSpecMenu::parseTextList(parserData* data,std::string element)
|
||||||
MY_CHECKPOS("textlist",0);
|
MY_CHECKPOS("textlist",0);
|
||||||
MY_CHECKGEOM("textlist",1);
|
MY_CHECKGEOM("textlist",1);
|
||||||
|
|
||||||
v2s32 pos = padding;
|
v2s32 pos = padding + pos_offset * spacing;
|
||||||
pos.X += stof(v_pos[0]) * (float)spacing.X;
|
pos.X += stof(v_pos[0]) * (float)spacing.X;
|
||||||
pos.Y += stof(v_pos[1]) * (float)spacing.Y;
|
pos.Y += stof(v_pos[1]) * (float)spacing.Y;
|
||||||
|
|
||||||
|
@ -841,7 +865,7 @@ void GUIFormSpecMenu::parseDropDown(parserData* data,std::string element)
|
||||||
|
|
||||||
MY_CHECKPOS("dropdown",0);
|
MY_CHECKPOS("dropdown",0);
|
||||||
|
|
||||||
v2s32 pos = padding;
|
v2s32 pos = padding + pos_offset * spacing;
|
||||||
pos.X += stof(v_pos[0]) * (float)spacing.X;
|
pos.X += stof(v_pos[0]) * (float)spacing.X;
|
||||||
pos.Y += stof(v_pos[1]) * (float)spacing.Y;
|
pos.Y += stof(v_pos[1]) * (float)spacing.Y;
|
||||||
|
|
||||||
|
@ -905,7 +929,7 @@ void GUIFormSpecMenu::parsePwdField(parserData* data,std::string element)
|
||||||
MY_CHECKPOS("pwdfield",0);
|
MY_CHECKPOS("pwdfield",0);
|
||||||
MY_CHECKGEOM("pwdfield",1);
|
MY_CHECKGEOM("pwdfield",1);
|
||||||
|
|
||||||
v2s32 pos;
|
v2s32 pos = pos_offset * spacing;
|
||||||
pos.X += stof(v_pos[0]) * (float)spacing.X;
|
pos.X += stof(v_pos[0]) * (float)spacing.X;
|
||||||
pos.Y += stof(v_pos[1]) * (float)spacing.Y;
|
pos.Y += stof(v_pos[1]) * (float)spacing.Y;
|
||||||
|
|
||||||
|
@ -975,7 +999,7 @@ void GUIFormSpecMenu::parseSimpleField(parserData* data,
|
||||||
if(data->explicit_size)
|
if(data->explicit_size)
|
||||||
warningstream<<"invalid use of unpositioned \"field\" in inventory"<<std::endl;
|
warningstream<<"invalid use of unpositioned \"field\" in inventory"<<std::endl;
|
||||||
|
|
||||||
v2s32 pos = padding + AbsoluteRect.UpperLeftCorner;
|
v2s32 pos = padding + AbsoluteRect.UpperLeftCorner + pos_offset * spacing;
|
||||||
pos.Y = ((m_fields.size()+2)*60);
|
pos.Y = ((m_fields.size()+2)*60);
|
||||||
v2s32 size = DesiredRect.getSize();
|
v2s32 size = DesiredRect.getSize();
|
||||||
|
|
||||||
|
@ -1058,9 +1082,9 @@ void GUIFormSpecMenu::parseTextArea(parserData* data,
|
||||||
MY_CHECKPOS(type,0);
|
MY_CHECKPOS(type,0);
|
||||||
MY_CHECKGEOM(type,1);
|
MY_CHECKGEOM(type,1);
|
||||||
|
|
||||||
v2s32 pos;
|
v2s32 pos = pos_offset * spacing;
|
||||||
pos.X = stof(v_pos[0]) * (float) spacing.X;
|
pos.X += stof(v_pos[0]) * (float) spacing.X;
|
||||||
pos.Y = stof(v_pos[1]) * (float) spacing.Y;
|
pos.Y += stof(v_pos[1]) * (float) spacing.Y;
|
||||||
|
|
||||||
v2s32 geom;
|
v2s32 geom;
|
||||||
|
|
||||||
|
@ -1185,7 +1209,7 @@ void GUIFormSpecMenu::parseLabel(parserData* data,std::string element)
|
||||||
|
|
||||||
MY_CHECKPOS("label",0);
|
MY_CHECKPOS("label",0);
|
||||||
|
|
||||||
v2s32 pos = padding;
|
v2s32 pos = padding + pos_offset * spacing;
|
||||||
pos.X += stof(v_pos[0]) * (float)spacing.X;
|
pos.X += stof(v_pos[0]) * (float)spacing.X;
|
||||||
pos.Y += (stof(v_pos[1]) + 7.0/30.0) * (float)spacing.Y;
|
pos.Y += (stof(v_pos[1]) + 7.0/30.0) * (float)spacing.Y;
|
||||||
|
|
||||||
|
@ -1242,7 +1266,7 @@ void GUIFormSpecMenu::parseVertLabel(parserData* data,std::string element)
|
||||||
|
|
||||||
MY_CHECKPOS("vertlabel",1);
|
MY_CHECKPOS("vertlabel",1);
|
||||||
|
|
||||||
v2s32 pos = padding;
|
v2s32 pos = padding + pos_offset * spacing;
|
||||||
pos.X += stof(v_pos[0]) * (float)spacing.X;
|
pos.X += stof(v_pos[0]) * (float)spacing.X;
|
||||||
pos.Y += stof(v_pos[1]) * (float)spacing.Y;
|
pos.Y += stof(v_pos[1]) * (float)spacing.Y;
|
||||||
|
|
||||||
|
@ -1296,7 +1320,7 @@ void GUIFormSpecMenu::parseImageButton(parserData* data,std::string element,
|
||||||
MY_CHECKPOS("imagebutton",0);
|
MY_CHECKPOS("imagebutton",0);
|
||||||
MY_CHECKGEOM("imagebutton",1);
|
MY_CHECKGEOM("imagebutton",1);
|
||||||
|
|
||||||
v2s32 pos = padding;
|
v2s32 pos = padding + pos_offset * spacing;
|
||||||
pos.X += stof(v_pos[0]) * (float)spacing.X;
|
pos.X += stof(v_pos[0]) * (float)spacing.X;
|
||||||
pos.Y += stof(v_pos[1]) * (float)spacing.Y;
|
pos.Y += stof(v_pos[1]) * (float)spacing.Y;
|
||||||
v2s32 geom;
|
v2s32 geom;
|
||||||
|
@ -1401,7 +1425,7 @@ void GUIFormSpecMenu::parseTabHeader(parserData* data,std::string element)
|
||||||
|
|
||||||
spec.ftype = f_TabHeader;
|
spec.ftype = f_TabHeader;
|
||||||
|
|
||||||
v2s32 pos(0,0);
|
v2s32 pos = pos_offset * spacing;
|
||||||
pos.X += stof(v_pos[0]) * (float)spacing.X;
|
pos.X += stof(v_pos[0]) * (float)spacing.X;
|
||||||
pos.Y += stof(v_pos[1]) * (float)spacing.Y - m_btn_height * 2;
|
pos.Y += stof(v_pos[1]) * (float)spacing.Y - m_btn_height * 2;
|
||||||
v2s32 geom;
|
v2s32 geom;
|
||||||
|
@ -1466,7 +1490,7 @@ void GUIFormSpecMenu::parseItemImageButton(parserData* data,std::string element)
|
||||||
MY_CHECKPOS("itemimagebutton",0);
|
MY_CHECKPOS("itemimagebutton",0);
|
||||||
MY_CHECKGEOM("itemimagebutton",1);
|
MY_CHECKGEOM("itemimagebutton",1);
|
||||||
|
|
||||||
v2s32 pos = padding;
|
v2s32 pos = padding + pos_offset * spacing;
|
||||||
pos.X += stof(v_pos[0]) * (float)spacing.X;
|
pos.X += stof(v_pos[0]) * (float)spacing.X;
|
||||||
pos.Y += stof(v_pos[1]) * (float)spacing.Y;
|
pos.Y += stof(v_pos[1]) * (float)spacing.Y;
|
||||||
v2s32 geom;
|
v2s32 geom;
|
||||||
|
@ -1504,7 +1528,7 @@ void GUIFormSpecMenu::parseItemImageButton(parserData* data,std::string element)
|
||||||
rect+=data->basepos-padding;
|
rect+=data->basepos-padding;
|
||||||
spec.rect=rect;
|
spec.rect=rect;
|
||||||
m_fields.push_back(spec);
|
m_fields.push_back(spec);
|
||||||
pos = padding + AbsoluteRect.UpperLeftCorner;
|
pos = padding + AbsoluteRect.UpperLeftCorner + pos_offset * spacing;
|
||||||
pos.X += stof(v_pos[0]) * (float) spacing.X;
|
pos.X += stof(v_pos[0]) * (float) spacing.X;
|
||||||
pos.Y += stof(v_pos[1]) * (float) spacing.Y;
|
pos.Y += stof(v_pos[1]) * (float) spacing.Y;
|
||||||
m_itemimages.push_back(ImageDrawSpec("", item_name, e, pos, geom));
|
m_itemimages.push_back(ImageDrawSpec("", item_name, e, pos, geom));
|
||||||
|
@ -1527,7 +1551,7 @@ void GUIFormSpecMenu::parseBox(parserData* data,std::string element)
|
||||||
MY_CHECKPOS("box",0);
|
MY_CHECKPOS("box",0);
|
||||||
MY_CHECKGEOM("box",1);
|
MY_CHECKGEOM("box",1);
|
||||||
|
|
||||||
v2s32 pos = padding + AbsoluteRect.UpperLeftCorner;
|
v2s32 pos = padding + AbsoluteRect.UpperLeftCorner + pos_offset * spacing;
|
||||||
pos.X += stof(v_pos[0]) * (float) spacing.X;
|
pos.X += stof(v_pos[0]) * (float) spacing.X;
|
||||||
pos.Y += stof(v_pos[1]) * (float) spacing.Y;
|
pos.Y += stof(v_pos[1]) * (float) spacing.Y;
|
||||||
|
|
||||||
|
@ -1689,8 +1713,18 @@ void GUIFormSpecMenu::parseElement(parserData* data, std::string element)
|
||||||
std::string type = trim(parts[0]);
|
std::string type = trim(parts[0]);
|
||||||
std::string description = trim(parts[1]);
|
std::string description = trim(parts[1]);
|
||||||
|
|
||||||
|
if (type == "container") {
|
||||||
|
parseContainer(data, description);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (type == "container_end") {
|
||||||
|
parseContainerEnd(data);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
if (type == "list") {
|
if (type == "list") {
|
||||||
parseList(data,description);
|
parseList(data, description);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1700,22 +1734,22 @@ void GUIFormSpecMenu::parseElement(parserData* data, std::string element)
|
||||||
}
|
}
|
||||||
|
|
||||||
if (type == "checkbox") {
|
if (type == "checkbox") {
|
||||||
parseCheckbox(data,description);
|
parseCheckbox(data, description);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (type == "image") {
|
if (type == "image") {
|
||||||
parseImage(data,description);
|
parseImage(data, description);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (type == "item_image") {
|
if (type == "item_image") {
|
||||||
parseItemImage(data,description);
|
parseItemImage(data, description);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
if ((type == "button") || (type == "button_exit")) {
|
if (type == "button" || type == "button_exit") {
|
||||||
parseButton(data,description,type);
|
parseButton(data, description, type);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -2036,10 +2070,16 @@ void GUIFormSpecMenu::regenerateGui(v2u32 screensize)
|
||||||
gui::IGUIFont *old_font = skin->getFont();
|
gui::IGUIFont *old_font = skin->getFont();
|
||||||
skin->setFont(m_font);
|
skin->setFont(m_font);
|
||||||
|
|
||||||
|
pos_offset = v2s32();
|
||||||
for (; i< elements.size(); i++) {
|
for (; i< elements.size(); i++) {
|
||||||
parseElement(&mydata, elements[i]);
|
parseElement(&mydata, elements[i]);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (!container_stack.empty()) {
|
||||||
|
errorstream << "Invalid formspec string: container was never closed!"
|
||||||
|
<< std::endl;
|
||||||
|
}
|
||||||
|
|
||||||
// If there are fields without explicit size[], add a "Proceed"
|
// If there are fields without explicit size[], add a "Proceed"
|
||||||
// button and adjust size to fit all the fields.
|
// button and adjust size to fit all the fields.
|
||||||
if (m_fields.size() && !mydata.explicit_size) {
|
if (m_fields.size() && !mydata.explicit_size) {
|
||||||
|
|
|
@ -22,6 +22,7 @@ with this program; if not, write to the Free Software Foundation, Inc.,
|
||||||
#define GUIINVENTORYMENU_HEADER
|
#define GUIINVENTORYMENU_HEADER
|
||||||
|
|
||||||
#include <utility>
|
#include <utility>
|
||||||
|
#include <stack>
|
||||||
|
|
||||||
#include "irrlichttypes_extrabloated.h"
|
#include "irrlichttypes_extrabloated.h"
|
||||||
#include "inventory.h"
|
#include "inventory.h"
|
||||||
|
@ -380,6 +381,8 @@ protected:
|
||||||
v2s32 spacing;
|
v2s32 spacing;
|
||||||
v2s32 imgsize;
|
v2s32 imgsize;
|
||||||
v2s32 offset;
|
v2s32 offset;
|
||||||
|
v2s32 pos_offset;
|
||||||
|
std::stack<v2s32> container_stack;
|
||||||
|
|
||||||
irr::IrrlichtDevice* m_device;
|
irr::IrrlichtDevice* m_device;
|
||||||
InventoryManager *m_invmgr;
|
InventoryManager *m_invmgr;
|
||||||
|
@ -472,13 +475,15 @@ private:
|
||||||
fs_key_pendig current_keys_pending;
|
fs_key_pendig current_keys_pending;
|
||||||
std::string current_field_enter_pending;
|
std::string current_field_enter_pending;
|
||||||
|
|
||||||
void parseElement(parserData* data,std::string element);
|
void parseElement(parserData* data, std::string element);
|
||||||
|
|
||||||
void parseSize(parserData* data,std::string element);
|
void parseSize(parserData* data, std::string element);
|
||||||
void parseList(parserData* data,std::string element);
|
void parseContainer(parserData* data, std::string element);
|
||||||
void parseListRing(parserData* data,std::string element);
|
void parseContainerEnd(parserData* data);
|
||||||
void parseCheckbox(parserData* data,std::string element);
|
void parseList(parserData* data, std::string element);
|
||||||
void parseImage(parserData* data,std::string element);
|
void parseListRing(parserData* data, std::string element);
|
||||||
|
void parseCheckbox(parserData* data, std::string element);
|
||||||
|
void parseImage(parserData* data, std::string element);
|
||||||
void parseItemImage(parserData* data,std::string element);
|
void parseItemImage(parserData* data,std::string element);
|
||||||
void parseButton(parserData* data,std::string element,std::string typ);
|
void parseButton(parserData* data,std::string element,std::string typ);
|
||||||
void parseBackground(parserData* data,std::string element);
|
void parseBackground(parserData* data,std::string element);
|
||||||
|
|
|
@ -565,10 +565,8 @@ void GUITable::setSelected(s32 index)
|
||||||
--index; // Switch from 1-based indexing to 0-based indexing
|
--index; // Switch from 1-based indexing to 0-based indexing
|
||||||
|
|
||||||
s32 rowcount = m_rows.size();
|
s32 rowcount = m_rows.size();
|
||||||
if (rowcount == 0) {
|
if (rowcount == 0 || index < 0) {
|
||||||
return;
|
return;
|
||||||
} else if (index < 0) {
|
|
||||||
index = 0;
|
|
||||||
} else if (index >= rowcount) {
|
} else if (index >= rowcount) {
|
||||||
index = rowcount - 1;
|
index = rowcount - 1;
|
||||||
}
|
}
|
||||||
|
|
|
@ -146,9 +146,9 @@ void ItemDefinition::serialize(std::ostream &os, u16 protocol_version) const
|
||||||
}
|
}
|
||||||
os<<serializeString(tool_capabilities_s);
|
os<<serializeString(tool_capabilities_s);
|
||||||
writeU16(os, groups.size());
|
writeU16(os, groups.size());
|
||||||
for(std::map<std::string, int>::const_iterator
|
for (ItemGroupList::const_iterator
|
||||||
i = groups.begin(); i != groups.end(); ++i){
|
i = groups.begin(); i != groups.end(); ++i){
|
||||||
os<<serializeString(i->first);
|
os << serializeString(i->first);
|
||||||
writeS16(os, i->second);
|
writeS16(os, i->second);
|
||||||
}
|
}
|
||||||
os<<serializeString(node_placement_prediction);
|
os<<serializeString(node_placement_prediction);
|
||||||
|
|
|
@ -21,14 +21,14 @@ with this program; if not, write to the Free Software Foundation, Inc.,
|
||||||
#define ITEMGROUP_HEADER
|
#define ITEMGROUP_HEADER
|
||||||
|
|
||||||
#include <string>
|
#include <string>
|
||||||
#include <map>
|
#include "util/cpp11_container.h"
|
||||||
|
|
||||||
typedef std::map<std::string, int> ItemGroupList;
|
typedef UNORDERED_MAP<std::string, int> ItemGroupList;
|
||||||
|
|
||||||
static inline int itemgroup_get(const ItemGroupList &groups,
|
static inline int itemgroup_get(const ItemGroupList &groups,
|
||||||
const std::string &name)
|
const std::string &name)
|
||||||
{
|
{
|
||||||
std::map<std::string, int>::const_iterator i = groups.find(name);
|
ItemGroupList::const_iterator i = groups.find(name);
|
||||||
if(i == groups.end())
|
if(i == groups.end())
|
||||||
return 0;
|
return 0;
|
||||||
return i->second;
|
return i->second;
|
||||||
|
|
555
src/keycode.cpp
555
src/keycode.cpp
|
@ -23,6 +23,7 @@ with this program; if not, write to the Free Software Foundation, Inc.,
|
||||||
#include "log.h"
|
#include "log.h"
|
||||||
#include "debug.h"
|
#include "debug.h"
|
||||||
#include "util/hex.h"
|
#include "util/hex.h"
|
||||||
|
#include "util/string.h"
|
||||||
|
|
||||||
class UnknownKeycode : public BaseException
|
class UnknownKeycode : public BaseException
|
||||||
{
|
{
|
||||||
|
@ -31,321 +32,335 @@ public:
|
||||||
BaseException(s) {};
|
BaseException(s) {};
|
||||||
};
|
};
|
||||||
|
|
||||||
#define CHECKKEY(x){if(strcmp(name, #x)==0) return irr::x;}
|
struct table_key {
|
||||||
|
const char *Name;
|
||||||
|
irr::EKEY_CODE Key;
|
||||||
|
wchar_t Char; // L'\0' means no character assigned
|
||||||
|
const char *LangName; // NULL means it doesn't have a human description
|
||||||
|
};
|
||||||
|
|
||||||
irr::EKEY_CODE keyname_to_keycode(const char *name)
|
#define DEFINEKEY1(x, lang) /* Irrlicht key without character */ \
|
||||||
|
{ #x, irr::x, L'\0', lang },
|
||||||
|
#define DEFINEKEY2(x, ch, lang) /* Irrlicht key with character */ \
|
||||||
|
{ #x, irr::x, ch, lang },
|
||||||
|
#define DEFINEKEY3(ch) /* single Irrlicht key (e.g. KEY_KEY_X) */ \
|
||||||
|
{ "KEY_KEY_" TOSTRING(ch), irr::KEY_KEY_ ## ch, (wchar_t) *TOSTRING(ch), TOSTRING(ch) },
|
||||||
|
#define DEFINEKEY4(ch) /* single Irrlicht function key (e.g. KEY_F3) */ \
|
||||||
|
{ "KEY_F" TOSTRING(ch), irr::KEY_F ## ch, L'\0', "F" TOSTRING(ch) },
|
||||||
|
#define DEFINEKEY5(ch) /* key without Irrlicht keycode */ \
|
||||||
|
{ ch, irr::KEY_KEY_CODES_COUNT, (wchar_t) *ch, ch },
|
||||||
|
|
||||||
|
#define N_(text) text
|
||||||
|
|
||||||
|
static const struct table_key table[] = {
|
||||||
|
// Keys that can be reliably mapped between Char and Key
|
||||||
|
DEFINEKEY3(0)
|
||||||
|
DEFINEKEY3(1)
|
||||||
|
DEFINEKEY3(2)
|
||||||
|
DEFINEKEY3(3)
|
||||||
|
DEFINEKEY3(4)
|
||||||
|
DEFINEKEY3(5)
|
||||||
|
DEFINEKEY3(6)
|
||||||
|
DEFINEKEY3(7)
|
||||||
|
DEFINEKEY3(8)
|
||||||
|
DEFINEKEY3(9)
|
||||||
|
DEFINEKEY3(A)
|
||||||
|
DEFINEKEY3(B)
|
||||||
|
DEFINEKEY3(C)
|
||||||
|
DEFINEKEY3(D)
|
||||||
|
DEFINEKEY3(E)
|
||||||
|
DEFINEKEY3(F)
|
||||||
|
DEFINEKEY3(G)
|
||||||
|
DEFINEKEY3(H)
|
||||||
|
DEFINEKEY3(I)
|
||||||
|
DEFINEKEY3(J)
|
||||||
|
DEFINEKEY3(K)
|
||||||
|
DEFINEKEY3(L)
|
||||||
|
DEFINEKEY3(M)
|
||||||
|
DEFINEKEY3(N)
|
||||||
|
DEFINEKEY3(O)
|
||||||
|
DEFINEKEY3(P)
|
||||||
|
DEFINEKEY3(Q)
|
||||||
|
DEFINEKEY3(R)
|
||||||
|
DEFINEKEY3(S)
|
||||||
|
DEFINEKEY3(T)
|
||||||
|
DEFINEKEY3(U)
|
||||||
|
DEFINEKEY3(V)
|
||||||
|
DEFINEKEY3(W)
|
||||||
|
DEFINEKEY3(X)
|
||||||
|
DEFINEKEY3(Y)
|
||||||
|
DEFINEKEY3(Z)
|
||||||
|
DEFINEKEY2(KEY_PLUS, L'+', "+")
|
||||||
|
DEFINEKEY2(KEY_COMMA, L',', ",")
|
||||||
|
DEFINEKEY2(KEY_MINUS, L'-', "-")
|
||||||
|
DEFINEKEY2(KEY_PERIOD, L'.', ".")
|
||||||
|
|
||||||
|
// Keys without a Char
|
||||||
|
DEFINEKEY1(KEY_LBUTTON, N_("Left Button"))
|
||||||
|
DEFINEKEY1(KEY_RBUTTON, N_("Right Button"))
|
||||||
|
DEFINEKEY1(KEY_CANCEL, N_("Cancel"))
|
||||||
|
DEFINEKEY1(KEY_MBUTTON, N_("Middle Button"))
|
||||||
|
DEFINEKEY1(KEY_XBUTTON1, N_("X Button 1"))
|
||||||
|
DEFINEKEY1(KEY_XBUTTON2, N_("X Button 2"))
|
||||||
|
DEFINEKEY1(KEY_BACK, N_("Back"))
|
||||||
|
DEFINEKEY1(KEY_TAB, N_("Tab"))
|
||||||
|
DEFINEKEY1(KEY_CLEAR, N_("Clear"))
|
||||||
|
DEFINEKEY1(KEY_RETURN, N_("Return"))
|
||||||
|
DEFINEKEY1(KEY_SHIFT, N_("Shift"))
|
||||||
|
DEFINEKEY1(KEY_CONTROL, N_("Control"))
|
||||||
|
DEFINEKEY1(KEY_MENU, N_("Menu"))
|
||||||
|
DEFINEKEY1(KEY_PAUSE, N_("Pause"))
|
||||||
|
DEFINEKEY1(KEY_CAPITAL, N_("Caps Lock"))
|
||||||
|
DEFINEKEY1(KEY_SPACE, N_("Space"))
|
||||||
|
DEFINEKEY1(KEY_PRIOR, N_("Prior"))
|
||||||
|
DEFINEKEY1(KEY_NEXT, N_("Next"))
|
||||||
|
DEFINEKEY1(KEY_END, N_("End"))
|
||||||
|
DEFINEKEY1(KEY_HOME, N_("Home"))
|
||||||
|
DEFINEKEY1(KEY_LEFT, N_("Left"))
|
||||||
|
DEFINEKEY1(KEY_UP, N_("Up"))
|
||||||
|
DEFINEKEY1(KEY_RIGHT, N_("Right"))
|
||||||
|
DEFINEKEY1(KEY_DOWN, N_("Down"))
|
||||||
|
DEFINEKEY1(KEY_SELECT, N_("Select"))
|
||||||
|
DEFINEKEY1(KEY_PRINT, N_("Print"))
|
||||||
|
DEFINEKEY1(KEY_EXECUT, N_("Execute"))
|
||||||
|
DEFINEKEY1(KEY_SNAPSHOT, N_("Snapshot"))
|
||||||
|
DEFINEKEY1(KEY_INSERT, N_("Insert"))
|
||||||
|
DEFINEKEY1(KEY_DELETE, N_("Delete"))
|
||||||
|
DEFINEKEY1(KEY_HELP, N_("Help"))
|
||||||
|
DEFINEKEY1(KEY_LWIN, N_("Left Windows"))
|
||||||
|
DEFINEKEY1(KEY_RWIN, N_("Right Windows"))
|
||||||
|
DEFINEKEY1(KEY_NUMPAD0, N_("Numpad 0")) // These are not assigned to a char
|
||||||
|
DEFINEKEY1(KEY_NUMPAD1, N_("Numpad 1")) // to prevent interference with KEY_KEY_[0-9].
|
||||||
|
DEFINEKEY1(KEY_NUMPAD2, N_("Numpad 2"))
|
||||||
|
DEFINEKEY1(KEY_NUMPAD3, N_("Numpad 3"))
|
||||||
|
DEFINEKEY1(KEY_NUMPAD4, N_("Numpad 4"))
|
||||||
|
DEFINEKEY1(KEY_NUMPAD5, N_("Numpad 5"))
|
||||||
|
DEFINEKEY1(KEY_NUMPAD6, N_("Numpad 6"))
|
||||||
|
DEFINEKEY1(KEY_NUMPAD7, N_("Numpad 7"))
|
||||||
|
DEFINEKEY1(KEY_NUMPAD8, N_("Numpad 8"))
|
||||||
|
DEFINEKEY1(KEY_NUMPAD9, N_("Numpad 9"))
|
||||||
|
DEFINEKEY1(KEY_MULTIPLY, N_("Numpad *"))
|
||||||
|
DEFINEKEY1(KEY_ADD, N_("Numpad +"))
|
||||||
|
DEFINEKEY1(KEY_SEPARATOR, N_("Numpad ."))
|
||||||
|
DEFINEKEY1(KEY_SUBTRACT, N_("Numpad -"))
|
||||||
|
DEFINEKEY1(KEY_DECIMAL, NULL)
|
||||||
|
DEFINEKEY1(KEY_DIVIDE, N_("Numpad /"))
|
||||||
|
DEFINEKEY4(1)
|
||||||
|
DEFINEKEY4(2)
|
||||||
|
DEFINEKEY4(3)
|
||||||
|
DEFINEKEY4(4)
|
||||||
|
DEFINEKEY4(5)
|
||||||
|
DEFINEKEY4(6)
|
||||||
|
DEFINEKEY4(7)
|
||||||
|
DEFINEKEY4(8)
|
||||||
|
DEFINEKEY4(9)
|
||||||
|
DEFINEKEY4(10)
|
||||||
|
DEFINEKEY4(11)
|
||||||
|
DEFINEKEY4(12)
|
||||||
|
DEFINEKEY4(13)
|
||||||
|
DEFINEKEY4(14)
|
||||||
|
DEFINEKEY4(15)
|
||||||
|
DEFINEKEY4(16)
|
||||||
|
DEFINEKEY4(17)
|
||||||
|
DEFINEKEY4(18)
|
||||||
|
DEFINEKEY4(19)
|
||||||
|
DEFINEKEY4(20)
|
||||||
|
DEFINEKEY4(21)
|
||||||
|
DEFINEKEY4(22)
|
||||||
|
DEFINEKEY4(23)
|
||||||
|
DEFINEKEY4(24)
|
||||||
|
DEFINEKEY1(KEY_NUMLOCK, N_("Num Lock"))
|
||||||
|
DEFINEKEY1(KEY_SCROLL, N_("Scroll Lock"))
|
||||||
|
DEFINEKEY1(KEY_LSHIFT, N_("Left Shift"))
|
||||||
|
DEFINEKEY1(KEY_RSHIFT, N_("Right Shift"))
|
||||||
|
DEFINEKEY1(KEY_LCONTROL, N_("Left Control"))
|
||||||
|
DEFINEKEY1(KEY_RCONTROL, N_("Right Control"))
|
||||||
|
DEFINEKEY1(KEY_LMENU, N_("Left Menu"))
|
||||||
|
DEFINEKEY1(KEY_RMENU, N_("Right Menu"))
|
||||||
|
|
||||||
|
// Rare/weird keys
|
||||||
|
DEFINEKEY1(KEY_KANA, "Kana")
|
||||||
|
DEFINEKEY1(KEY_HANGUEL, "Hangul")
|
||||||
|
DEFINEKEY1(KEY_HANGUL, "Hangul")
|
||||||
|
DEFINEKEY1(KEY_JUNJA, "Junja")
|
||||||
|
DEFINEKEY1(KEY_FINAL, "Final")
|
||||||
|
DEFINEKEY1(KEY_KANJI, "Kanji")
|
||||||
|
DEFINEKEY1(KEY_HANJA, "Hanja")
|
||||||
|
DEFINEKEY1(KEY_ESCAPE, N_("IME Escape"))
|
||||||
|
DEFINEKEY1(KEY_CONVERT, N_("IME Convert"))
|
||||||
|
DEFINEKEY1(KEY_NONCONVERT, N_("IME Nonconvert"))
|
||||||
|
DEFINEKEY1(KEY_ACCEPT, N_("IME Accept"))
|
||||||
|
DEFINEKEY1(KEY_MODECHANGE, N_("IME Mode Change"))
|
||||||
|
DEFINEKEY1(KEY_APPS, N_("Apps"))
|
||||||
|
DEFINEKEY1(KEY_SLEEP, N_("Sleep"))
|
||||||
|
#if !(IRRLICHT_VERSION_MAJOR <= 1 && IRRLICHT_VERSION_MINOR <= 7 && IRRLICHT_VERSION_REVISION < 3)
|
||||||
|
DEFINEKEY1(KEY_OEM_1, "OEM 1") // KEY_OEM_[0-9] and KEY_OEM_102 are assigned to multiple
|
||||||
|
DEFINEKEY1(KEY_OEM_2, "OEM 2") // different chars (on different platforms too) and thus w/o char
|
||||||
|
DEFINEKEY1(KEY_OEM_3, "OEM 3")
|
||||||
|
DEFINEKEY1(KEY_OEM_4, "OEM 4")
|
||||||
|
DEFINEKEY1(KEY_OEM_5, "OEM 5")
|
||||||
|
DEFINEKEY1(KEY_OEM_6, "OEM 6")
|
||||||
|
DEFINEKEY1(KEY_OEM_7, "OEM 7")
|
||||||
|
DEFINEKEY1(KEY_OEM_8, "OEM 8")
|
||||||
|
DEFINEKEY1(KEY_OEM_AX, "OEM AX")
|
||||||
|
DEFINEKEY1(KEY_OEM_102, "OEM 102")
|
||||||
|
#endif
|
||||||
|
DEFINEKEY1(KEY_ATTN, "Attn")
|
||||||
|
DEFINEKEY1(KEY_CRSEL, "CrSel")
|
||||||
|
DEFINEKEY1(KEY_EXSEL, "ExSel")
|
||||||
|
DEFINEKEY1(KEY_EREOF, N_("Erase EOF"))
|
||||||
|
DEFINEKEY1(KEY_PLAY, N_("Play"))
|
||||||
|
DEFINEKEY1(KEY_ZOOM, N_("Zoom"))
|
||||||
|
DEFINEKEY1(KEY_PA1, "PA1")
|
||||||
|
DEFINEKEY1(KEY_OEM_CLEAR, N_("OEM Clear"))
|
||||||
|
|
||||||
|
// Keys without Irrlicht keycode
|
||||||
|
DEFINEKEY5("!")
|
||||||
|
DEFINEKEY5("\"")
|
||||||
|
DEFINEKEY5("#")
|
||||||
|
DEFINEKEY5("$")
|
||||||
|
DEFINEKEY5("%")
|
||||||
|
DEFINEKEY5("&")
|
||||||
|
DEFINEKEY5("'")
|
||||||
|
DEFINEKEY5("(")
|
||||||
|
DEFINEKEY5(")")
|
||||||
|
DEFINEKEY5("*")
|
||||||
|
DEFINEKEY5("/")
|
||||||
|
DEFINEKEY5(":")
|
||||||
|
DEFINEKEY5(";")
|
||||||
|
DEFINEKEY5("<")
|
||||||
|
DEFINEKEY5("=")
|
||||||
|
DEFINEKEY5(">")
|
||||||
|
DEFINEKEY5("?")
|
||||||
|
DEFINEKEY5("@")
|
||||||
|
DEFINEKEY5("[")
|
||||||
|
DEFINEKEY5("\\")
|
||||||
|
DEFINEKEY5("]")
|
||||||
|
DEFINEKEY5("^")
|
||||||
|
DEFINEKEY5("_")
|
||||||
|
};
|
||||||
|
|
||||||
|
#undef N_
|
||||||
|
|
||||||
|
#define ARRAYSIZE(a) (sizeof(a) / sizeof((a)[0]))
|
||||||
|
|
||||||
|
struct table_key lookup_keyname(const char *name)
|
||||||
{
|
{
|
||||||
CHECKKEY(KEY_LBUTTON)
|
for (u16 i = 0; i < ARRAYSIZE(table); i++) {
|
||||||
CHECKKEY(KEY_RBUTTON)
|
if (strcmp(table[i].Name, name) == 0)
|
||||||
CHECKKEY(KEY_CANCEL)
|
return table[i];
|
||||||
CHECKKEY(KEY_MBUTTON)
|
}
|
||||||
CHECKKEY(KEY_XBUTTON1)
|
|
||||||
CHECKKEY(KEY_XBUTTON2)
|
|
||||||
CHECKKEY(KEY_BACK)
|
|
||||||
CHECKKEY(KEY_TAB)
|
|
||||||
CHECKKEY(KEY_CLEAR)
|
|
||||||
CHECKKEY(KEY_RETURN)
|
|
||||||
CHECKKEY(KEY_SHIFT)
|
|
||||||
CHECKKEY(KEY_CONTROL)
|
|
||||||
CHECKKEY(KEY_MENU)
|
|
||||||
CHECKKEY(KEY_PAUSE)
|
|
||||||
CHECKKEY(KEY_CAPITAL)
|
|
||||||
CHECKKEY(KEY_KANA)
|
|
||||||
CHECKKEY(KEY_HANGUEL)
|
|
||||||
CHECKKEY(KEY_HANGUL)
|
|
||||||
CHECKKEY(KEY_JUNJA)
|
|
||||||
CHECKKEY(KEY_FINAL)
|
|
||||||
CHECKKEY(KEY_HANJA)
|
|
||||||
CHECKKEY(KEY_KANJI)
|
|
||||||
CHECKKEY(KEY_ESCAPE)
|
|
||||||
CHECKKEY(KEY_CONVERT)
|
|
||||||
CHECKKEY(KEY_NONCONVERT)
|
|
||||||
CHECKKEY(KEY_ACCEPT)
|
|
||||||
CHECKKEY(KEY_MODECHANGE)
|
|
||||||
CHECKKEY(KEY_SPACE)
|
|
||||||
CHECKKEY(KEY_PRIOR)
|
|
||||||
CHECKKEY(KEY_NEXT)
|
|
||||||
CHECKKEY(KEY_END)
|
|
||||||
CHECKKEY(KEY_HOME)
|
|
||||||
CHECKKEY(KEY_LEFT)
|
|
||||||
CHECKKEY(KEY_UP)
|
|
||||||
CHECKKEY(KEY_RIGHT)
|
|
||||||
CHECKKEY(KEY_DOWN)
|
|
||||||
CHECKKEY(KEY_SELECT)
|
|
||||||
CHECKKEY(KEY_PRINT)
|
|
||||||
CHECKKEY(KEY_EXECUT)
|
|
||||||
CHECKKEY(KEY_SNAPSHOT)
|
|
||||||
CHECKKEY(KEY_INSERT)
|
|
||||||
CHECKKEY(KEY_DELETE)
|
|
||||||
CHECKKEY(KEY_HELP)
|
|
||||||
CHECKKEY(KEY_KEY_0)
|
|
||||||
CHECKKEY(KEY_KEY_1)
|
|
||||||
CHECKKEY(KEY_KEY_2)
|
|
||||||
CHECKKEY(KEY_KEY_3)
|
|
||||||
CHECKKEY(KEY_KEY_4)
|
|
||||||
CHECKKEY(KEY_KEY_5)
|
|
||||||
CHECKKEY(KEY_KEY_6)
|
|
||||||
CHECKKEY(KEY_KEY_7)
|
|
||||||
CHECKKEY(KEY_KEY_8)
|
|
||||||
CHECKKEY(KEY_KEY_9)
|
|
||||||
CHECKKEY(KEY_KEY_A)
|
|
||||||
CHECKKEY(KEY_KEY_B)
|
|
||||||
CHECKKEY(KEY_KEY_C)
|
|
||||||
CHECKKEY(KEY_KEY_D)
|
|
||||||
CHECKKEY(KEY_KEY_E)
|
|
||||||
CHECKKEY(KEY_KEY_F)
|
|
||||||
CHECKKEY(KEY_KEY_G)
|
|
||||||
CHECKKEY(KEY_KEY_H)
|
|
||||||
CHECKKEY(KEY_KEY_I)
|
|
||||||
CHECKKEY(KEY_KEY_J)
|
|
||||||
CHECKKEY(KEY_KEY_K)
|
|
||||||
CHECKKEY(KEY_KEY_L)
|
|
||||||
CHECKKEY(KEY_KEY_M)
|
|
||||||
CHECKKEY(KEY_KEY_N)
|
|
||||||
CHECKKEY(KEY_KEY_O)
|
|
||||||
CHECKKEY(KEY_KEY_P)
|
|
||||||
CHECKKEY(KEY_KEY_Q)
|
|
||||||
CHECKKEY(KEY_KEY_R)
|
|
||||||
CHECKKEY(KEY_KEY_S)
|
|
||||||
CHECKKEY(KEY_KEY_T)
|
|
||||||
CHECKKEY(KEY_KEY_U)
|
|
||||||
CHECKKEY(KEY_KEY_V)
|
|
||||||
CHECKKEY(KEY_KEY_W)
|
|
||||||
CHECKKEY(KEY_KEY_X)
|
|
||||||
CHECKKEY(KEY_KEY_Y)
|
|
||||||
CHECKKEY(KEY_KEY_Z)
|
|
||||||
CHECKKEY(KEY_LWIN)
|
|
||||||
CHECKKEY(KEY_RWIN)
|
|
||||||
CHECKKEY(KEY_APPS)
|
|
||||||
CHECKKEY(KEY_SLEEP)
|
|
||||||
CHECKKEY(KEY_NUMPAD0)
|
|
||||||
CHECKKEY(KEY_NUMPAD1)
|
|
||||||
CHECKKEY(KEY_NUMPAD2)
|
|
||||||
CHECKKEY(KEY_NUMPAD3)
|
|
||||||
CHECKKEY(KEY_NUMPAD4)
|
|
||||||
CHECKKEY(KEY_NUMPAD5)
|
|
||||||
CHECKKEY(KEY_NUMPAD6)
|
|
||||||
CHECKKEY(KEY_NUMPAD7)
|
|
||||||
CHECKKEY(KEY_NUMPAD8)
|
|
||||||
CHECKKEY(KEY_NUMPAD9)
|
|
||||||
CHECKKEY(KEY_MULTIPLY)
|
|
||||||
CHECKKEY(KEY_ADD)
|
|
||||||
CHECKKEY(KEY_SEPARATOR)
|
|
||||||
CHECKKEY(KEY_SUBTRACT)
|
|
||||||
CHECKKEY(KEY_DECIMAL)
|
|
||||||
CHECKKEY(KEY_DIVIDE)
|
|
||||||
CHECKKEY(KEY_F1)
|
|
||||||
CHECKKEY(KEY_F2)
|
|
||||||
CHECKKEY(KEY_F3)
|
|
||||||
CHECKKEY(KEY_F4)
|
|
||||||
CHECKKEY(KEY_F5)
|
|
||||||
CHECKKEY(KEY_F6)
|
|
||||||
CHECKKEY(KEY_F7)
|
|
||||||
CHECKKEY(KEY_F8)
|
|
||||||
CHECKKEY(KEY_F9)
|
|
||||||
CHECKKEY(KEY_F10)
|
|
||||||
CHECKKEY(KEY_F11)
|
|
||||||
CHECKKEY(KEY_F12)
|
|
||||||
CHECKKEY(KEY_F13)
|
|
||||||
CHECKKEY(KEY_F14)
|
|
||||||
CHECKKEY(KEY_F15)
|
|
||||||
CHECKKEY(KEY_F16)
|
|
||||||
CHECKKEY(KEY_F17)
|
|
||||||
CHECKKEY(KEY_F18)
|
|
||||||
CHECKKEY(KEY_F19)
|
|
||||||
CHECKKEY(KEY_F20)
|
|
||||||
CHECKKEY(KEY_F21)
|
|
||||||
CHECKKEY(KEY_F22)
|
|
||||||
CHECKKEY(KEY_F23)
|
|
||||||
CHECKKEY(KEY_F24)
|
|
||||||
CHECKKEY(KEY_NUMLOCK)
|
|
||||||
CHECKKEY(KEY_SCROLL)
|
|
||||||
CHECKKEY(KEY_LSHIFT)
|
|
||||||
CHECKKEY(KEY_RSHIFT)
|
|
||||||
CHECKKEY(KEY_LCONTROL)
|
|
||||||
CHECKKEY(KEY_RCONTROL)
|
|
||||||
CHECKKEY(KEY_LMENU)
|
|
||||||
CHECKKEY(KEY_RMENU)
|
|
||||||
CHECKKEY(KEY_PLUS)
|
|
||||||
CHECKKEY(KEY_COMMA)
|
|
||||||
CHECKKEY(KEY_MINUS)
|
|
||||||
CHECKKEY(KEY_PERIOD)
|
|
||||||
CHECKKEY(KEY_ATTN)
|
|
||||||
CHECKKEY(KEY_CRSEL)
|
|
||||||
CHECKKEY(KEY_EXSEL)
|
|
||||||
CHECKKEY(KEY_EREOF)
|
|
||||||
CHECKKEY(KEY_PLAY)
|
|
||||||
CHECKKEY(KEY_ZOOM)
|
|
||||||
CHECKKEY(KEY_PA1)
|
|
||||||
CHECKKEY(KEY_OEM_CLEAR)
|
|
||||||
|
|
||||||
throw UnknownKeycode(name);
|
throw UnknownKeycode(name);
|
||||||
}
|
}
|
||||||
|
|
||||||
static const char *KeyNames[] =
|
struct table_key lookup_keykey(irr::EKEY_CODE key)
|
||||||
{ "-", "KEY_LBUTTON", "KEY_RBUTTON", "KEY_CANCEL", "KEY_MBUTTON", "KEY_XBUTTON1",
|
{
|
||||||
"KEY_XBUTTON2", "-", "KEY_BACK", "KEY_TAB", "-", "-", "KEY_CLEAR", "KEY_RETURN", "-",
|
for (u16 i = 0; i < ARRAYSIZE(table); i++) {
|
||||||
"-", "KEY_SHIFT", "KEY_CONTROL", "KEY_MENU", "KEY_PAUSE", "KEY_CAPITAL", "KEY_KANA", "-",
|
if (table[i].Key == key)
|
||||||
"KEY_JUNJA", "KEY_FINAL", "KEY_KANJI", "-", "KEY_ESCAPE", "KEY_CONVERT", "KEY_NONCONVERT",
|
return table[i];
|
||||||
"KEY_ACCEPT", "KEY_MODECHANGE", "KEY_SPACE", "KEY_PRIOR", "KEY_NEXT", "KEY_END",
|
}
|
||||||
"KEY_HOME", "KEY_LEFT", "KEY_UP", "KEY_RIGHT", "KEY_DOWN", "KEY_SELECT", "KEY_PRINT",
|
|
||||||
"KEY_EXECUTE", "KEY_SNAPSHOT", "KEY_INSERT", "KEY_DELETE", "KEY_HELP", "KEY_KEY_0",
|
|
||||||
"KEY_KEY_1", "KEY_KEY_2", "KEY_KEY_3", "KEY_KEY_4", "KEY_KEY_5",
|
|
||||||
"KEY_KEY_6", "KEY_KEY_7", "KEY_KEY_8", "KEY_KEY_9", "-", "-", "-", "-",
|
|
||||||
"-", "-", "-", "KEY_KEY_A", "KEY_KEY_B", "KEY_KEY_C", "KEY_KEY_D",
|
|
||||||
"KEY_KEY_E", "KEY_KEY_F", "KEY_KEY_G", "KEY_KEY_H", "KEY_KEY_I",
|
|
||||||
"KEY_KEY_J", "KEY_KEY_K", "KEY_KEY_L", "KEY_KEY_M", "KEY_KEY_N",
|
|
||||||
"KEY_KEY_O", "KEY_KEY_P", "KEY_KEY_Q", "KEY_KEY_R", "KEY_KEY_S",
|
|
||||||
"KEY_KEY_T", "KEY_KEY_U", "KEY_KEY_V", "KEY_KEY_W", "KEY_KEY_X",
|
|
||||||
"KEY_KEY_Y", "KEY_KEY_Z", "KEY_LWIN", "KEY_RWIN", "KEY_APPS", "-",
|
|
||||||
"KEY_SLEEP", "KEY_NUMPAD0", "KEY_NUMPAD1", "KEY_NUMPAD2", "KEY_NUMPAD3",
|
|
||||||
"KEY_NUMPAD4", "KEY_NUMPAD5", "KEY_NUMPAD6", "KEY_NUMPAD7",
|
|
||||||
"KEY_NUMPAD8", "KEY_NUMPAD9", "KEY_MULTIPLY", "KEY_ADD", "KEY_SEPERATOR",
|
|
||||||
"KEY_SUBTRACT", "KEY_DECIMAL", "KEY_DIVIDE", "KEY_F1", "KEY_F2", "KEY_F3",
|
|
||||||
"KEY_F4", "KEY_F5", "KEY_F6", "KEY_F7", "KEY_F8", "KEY_F9", "KEY_F10",
|
|
||||||
"KEY_F11", "KEY_F12", "KEY_F13", "KEY_F14", "KEY_F15", "KEY_F16",
|
|
||||||
"KEY_F17", "KEY_F18", "KEY_F19", "KEY_F20", "KEY_F21", "KEY_F22",
|
|
||||||
"KEY_F23", "KEY_F24", "-", "-", "-", "-", "-", "-", "-", "-",
|
|
||||||
"KEY_NUMLOCK", "KEY_SCROLL", "-", "-", "-", "-", "-", "-", "-", "-", "-",
|
|
||||||
"-", "-", "-", "-", "-", "KEY_LSHIFT", "KEY_RSHIFT", "KEY_LCONTROL",
|
|
||||||
"KEY_RCONTROL", "KEY_LMENU", "KEY_RMENU", "-", "-", "-", "-", "-",
|
|
||||||
"-", "-", "-", "-", "-", "-", "-", "-", "-", "-", "-", "-", "-", "-",
|
|
||||||
"-", "-", "KEY_PLUS", "KEY_COMMA", "KEY_MINUS", "KEY_PERIOD", "-", "-", "-", "-", "-",
|
|
||||||
"-", "-", "-", "-", "-", "-", "-", "-", "-", "-", "-", "-", "-", "-",
|
|
||||||
"-", "-", "-", "-", "-", "-", "-", "-", "-", "-", "-", "-", "-", "-",
|
|
||||||
"-", "-", "-", "-", "-", "-", "-", "-", "-", "-", "-", "-", "-", "-",
|
|
||||||
"-", "-", "-", "-", "-", "-", "-", "-", "KEY_ATTN", "KEY_CRSEL", "KEY_EXSEL",
|
|
||||||
"KEY_EREOF", "KEY_PLAY", "KEY_ZOOM", "KEY_PA1", "KEY_OEM_CLEAR", "-" };
|
|
||||||
|
|
||||||
#define N_(text) text
|
std::ostringstream os;
|
||||||
|
os << "<Keycode " << (int) key << ">";
|
||||||
|
throw UnknownKeycode(os.str().c_str());
|
||||||
|
}
|
||||||
|
|
||||||
static const char *KeyNamesLang[] =
|
struct table_key lookup_keychar(wchar_t Char)
|
||||||
{ "-", N_("Left Button"), N_("Right Button"), N_("Cancel"), N_("Middle Button"), N_("X Button 1"),
|
{
|
||||||
N_("X Button 2"), "-", N_("Back"), N_("Tab"), "-", "-", N_("Clear"), N_("Return"), "-",
|
for (u16 i = 0; i < ARRAYSIZE(table); i++) {
|
||||||
"-", N_("Shift"), N_("Control"), N_("Menu"), N_("Pause"), N_("Capital"), N_("Kana"), "-",
|
if (table[i].Char == Char)
|
||||||
N_("Junja"), N_("Final"), N_("Kanji"), "-", N_("Escape"), N_("Convert"), N_("Nonconvert"),
|
return table[i];
|
||||||
N_("Accept"), N_("Mode Change"), N_("Space"), N_("Prior"), N_("Next"), N_("End"), N_("Home"),
|
}
|
||||||
N_("Left"), N_("Up"), N_("Right"), N_("Down"), N_("Select"), N_("Print"), N_("Execute"),
|
|
||||||
N_("Snapshot"), N_("Insert"), N_("Delete"), N_("Help"), "0", "1", "2", "3", "4", "5",
|
|
||||||
"6", "7", "8", "9", "-", "-", "-", "-", "-", "-", "-", "A", "B", "C",
|
|
||||||
"D", "E", "F", "G", "H", "I", "J", "K", "L", "M", "N", "O", "P", "Q",
|
|
||||||
"R", "S", "T", "U", "V", "W", "X", "Y", "Z", N_("Left Windows"),
|
|
||||||
N_("Right Windows"), N_("Apps"), "-", N_("Sleep"), N_("Numpad 0"), N_("Numpad 1"),
|
|
||||||
N_("Numpad 2"), N_("Numpad 3"), N_("Numpad 4"), N_("Numpad 5"), N_("Numpad 6"), N_("Numpad 7"),
|
|
||||||
N_("Numpad 8"), N_("Numpad 9"), N_("Numpad *"), N_("Numpad +"), N_("Numpad /"), N_("Numpad -"),
|
|
||||||
"Numpad .", "Numpad /", "F1", "F2", "F3", "F4", "F5", "F6", "F7", "F8",
|
|
||||||
"F9", "F10", "F11", "F12", "F13", "F14", "F15", "F16", "F17", "F18",
|
|
||||||
"F19", "F20", "F21", "F22", "F23", "F24", "-", "-", "-", "-", "-", "-",
|
|
||||||
"-", "-", N_("Num Lock"), N_("Scroll Lock"), "-", "-", "-", "-", "-", "-", "-",
|
|
||||||
"-", "-", "-", "-", "-", "-", "-", N_("Left Shift"), N_("Right Shift"),
|
|
||||||
N_("Left Control"), N_("Right Control"), N_("Left Menu"), N_("Right Menu"), "-", "-",
|
|
||||||
"-", "-", "-", "-", "-", "-", "-", "-", "-", "-", "-", "-", "-", "-",
|
|
||||||
"-", "-", "-", "-", "-", N_("Plus"), N_("Comma"), N_("Minus"), N_("Period"), "-", "-",
|
|
||||||
"-", "-", "-", "-", "-", "-", "-", "-", "-", "-", "-", "-", "-", "-",
|
|
||||||
"-", "-", "-", "-", "-", "-", "-", "-", "-", "-", "-", "-", "-", "-",
|
|
||||||
"-", "-", "-", "-", "-", "-", "-", "-", "-", "-", "-", "-", "-", "-",
|
|
||||||
"-", "-", "-", "-", "-", "-", "-", "-", "-", "-", "-", N_("Attn"), N_("CrSel"),
|
|
||||||
N_("ExSel"), N_("Erase OEF"), N_("Play"), N_("Zoom"), N_("PA1"), N_("OEM Clear"), "-" };
|
|
||||||
|
|
||||||
#undef N_
|
std::ostringstream os;
|
||||||
|
os << "<Char " << hex_encode((char*) &Char, sizeof(wchar_t)) << ">";
|
||||||
|
throw UnknownKeycode(os.str().c_str());
|
||||||
|
}
|
||||||
|
|
||||||
KeyPress::KeyPress() :
|
KeyPress::KeyPress() :
|
||||||
Key(irr::KEY_KEY_CODES_COUNT),
|
Key(irr::KEY_KEY_CODES_COUNT),
|
||||||
Char(L'\0')
|
Char(L'\0'),
|
||||||
|
m_name("")
|
||||||
{}
|
{}
|
||||||
|
|
||||||
KeyPress::KeyPress(const char *name)
|
KeyPress::KeyPress(const char *name)
|
||||||
{
|
{
|
||||||
if (name[0] == 0) {
|
if (strlen(name) == 0) {
|
||||||
Key = irr::KEY_KEY_CODES_COUNT;
|
Key = irr::KEY_KEY_CODES_COUNT;
|
||||||
Char = L'\0';
|
Char = L'\0';
|
||||||
|
m_name = "";
|
||||||
return;
|
return;
|
||||||
} else if (strlen(name) > 4) {
|
} else if (strlen(name) <= 4) {
|
||||||
|
// Lookup by resulting character
|
||||||
|
int chars_read = mbtowc(&Char, name, 1);
|
||||||
|
FATAL_ERROR_IF(chars_read != 1, "Unexpected multibyte character");
|
||||||
try {
|
try {
|
||||||
Key = keyname_to_keycode(name);
|
struct table_key k = lookup_keychar(Char);
|
||||||
m_name = name;
|
m_name = k.Name;
|
||||||
if (strlen(name) > 8 && strncmp(name, "KEY_KEY_", 8) == 0) {
|
Key = k.Key;
|
||||||
int chars_read = mbtowc(&Char, name + 8, 1);
|
|
||||||
|
|
||||||
FATAL_ERROR_IF(chars_read != 1, "Unexpected multibyte character");
|
|
||||||
} else
|
|
||||||
Char = L'\0';
|
|
||||||
return;
|
return;
|
||||||
} catch (UnknownKeycode &e) {};
|
} catch (UnknownKeycode &e) {};
|
||||||
} else {
|
} else {
|
||||||
// see if we can set it up as a KEY_KEY_something
|
// Lookup by name
|
||||||
m_name = "KEY_KEY_";
|
m_name = name;
|
||||||
m_name += name;
|
|
||||||
try {
|
try {
|
||||||
Key = keyname_to_keycode(m_name.c_str());
|
struct table_key k = lookup_keyname(name);
|
||||||
int chars_read = mbtowc(&Char, name, 1);
|
Key = k.Key;
|
||||||
|
Char = k.Char;
|
||||||
FATAL_ERROR_IF(chars_read != 1, "Unexpected multibyte character");
|
|
||||||
return;
|
return;
|
||||||
} catch (UnknownKeycode &e) {};
|
} catch (UnknownKeycode &e) {};
|
||||||
}
|
}
|
||||||
|
|
||||||
// it's not a (known) key, just take the first char and use that
|
// It's not a known key, complain and try to do something
|
||||||
|
|
||||||
Key = irr::KEY_KEY_CODES_COUNT;
|
Key = irr::KEY_KEY_CODES_COUNT;
|
||||||
|
int chars_read = mbtowc(&Char, name, 1);
|
||||||
int mbtowc_ret = mbtowc(&Char, name, 1);
|
FATAL_ERROR_IF(chars_read != 1, "Unexpected multibyte character");
|
||||||
FATAL_ERROR_IF(mbtowc_ret != 1, "Unexpected multibyte character");
|
m_name = "";
|
||||||
m_name = name[0];
|
warningstream << "KeyPress: Unknown key '" << name << "', falling back to first char.";
|
||||||
}
|
}
|
||||||
|
|
||||||
KeyPress::KeyPress(const irr::SEvent::SKeyInput &in, bool prefer_character)
|
KeyPress::KeyPress(const irr::SEvent::SKeyInput &in, bool prefer_character)
|
||||||
{
|
{
|
||||||
Key = in.Key;
|
if (prefer_character)
|
||||||
|
Key = irr::KEY_KEY_CODES_COUNT;
|
||||||
|
else
|
||||||
|
Key = in.Key;
|
||||||
Char = in.Char;
|
Char = in.Char;
|
||||||
|
|
||||||
if(prefer_character){
|
try {
|
||||||
m_name.resize(MB_CUR_MAX+1, '\0');
|
if (valid_kcode(Key))
|
||||||
int written = wctomb(&m_name[0], Char);
|
m_name = lookup_keykey(Key).Name;
|
||||||
if(written > 0){
|
else
|
||||||
infostream<<"KeyPress: Preferring character for "<<m_name<<std::endl;
|
m_name = lookup_keychar(Char).Name;
|
||||||
Key = irr::KEY_KEY_CODES_COUNT;
|
} catch (UnknownKeycode &e) {
|
||||||
return;
|
m_name = "";
|
||||||
}
|
};
|
||||||
}
|
|
||||||
|
|
||||||
if (valid_kcode(Key)) {
|
|
||||||
m_name = KeyNames[Key];
|
|
||||||
} else {
|
|
||||||
m_name.resize(MB_CUR_MAX+1, '\0');
|
|
||||||
int written = wctomb(&m_name[0], Char);
|
|
||||||
if(written < 0){
|
|
||||||
std::string hexstr = hex_encode((const char*)&Char, sizeof(Char));
|
|
||||||
errorstream<<"KeyPress: Unexpected multibyte character "<<hexstr<<std::endl;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
const char *KeyPress::sym() const
|
const char *KeyPress::sym() const
|
||||||
{
|
{
|
||||||
if (Key && Key < irr::KEY_KEY_CODES_COUNT)
|
return m_name.c_str();
|
||||||
return KeyNames[Key];
|
|
||||||
else {
|
|
||||||
return m_name.c_str();
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
const char *KeyPress::name() const
|
const char *KeyPress::name() const
|
||||||
{
|
{
|
||||||
if (Key && Key < irr::KEY_KEY_CODES_COUNT)
|
if (m_name == "")
|
||||||
return KeyNamesLang[Key];
|
return "";
|
||||||
else {
|
const char *ret;
|
||||||
return m_name.c_str();
|
if (valid_kcode(Key))
|
||||||
}
|
ret = lookup_keykey(Key).LangName;
|
||||||
|
else
|
||||||
|
ret = lookup_keychar(Char).LangName;
|
||||||
|
return ret ? ret : "<Unnamed key>";
|
||||||
}
|
}
|
||||||
|
|
||||||
const KeyPress EscapeKey("KEY_ESCAPE");
|
const KeyPress EscapeKey("KEY_ESCAPE");
|
||||||
const KeyPress CancelKey("KEY_CANCEL");
|
const KeyPress CancelKey("KEY_CANCEL");
|
||||||
const KeyPress NumberKey[] = {
|
const KeyPress NumberKey[] = {
|
||||||
KeyPress("KEY_KEY_0"), KeyPress("KEY_KEY_1"), KeyPress("KEY_KEY_2"),
|
KeyPress("0"), KeyPress("1"), KeyPress("2"), KeyPress("3"), KeyPress("4"),
|
||||||
KeyPress("KEY_KEY_3"), KeyPress("KEY_KEY_4"), KeyPress("KEY_KEY_5"),
|
KeyPress("5"), KeyPress("6"), KeyPress("7"), KeyPress("8"), KeyPress("9")
|
||||||
KeyPress("KEY_KEY_6"), KeyPress("KEY_KEY_7"), KeyPress("KEY_KEY_8"),
|
};
|
||||||
KeyPress("KEY_KEY_9")};
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
Key config
|
Key config
|
||||||
|
@ -360,8 +375,10 @@ KeyPress getKeySetting(const char *settingname)
|
||||||
n = g_key_setting_cache.find(settingname);
|
n = g_key_setting_cache.find(settingname);
|
||||||
if(n != g_key_setting_cache.end())
|
if(n != g_key_setting_cache.end())
|
||||||
return n->second;
|
return n->second;
|
||||||
g_key_setting_cache[settingname] = g_settings->get(settingname).c_str();
|
|
||||||
return g_key_setting_cache.find(settingname)->second;
|
KeyPress k(g_settings->get(settingname).c_str());
|
||||||
|
g_key_setting_cache[settingname] = k;
|
||||||
|
return k;
|
||||||
}
|
}
|
||||||
|
|
||||||
void clearKeyCache()
|
void clearKeyCache()
|
||||||
|
|
|
@ -44,8 +44,6 @@ public:
|
||||||
|
|
||||||
const char *sym() const;
|
const char *sym() const;
|
||||||
const char *name() const;
|
const char *name() const;
|
||||||
|
|
||||||
std::string debug() const;
|
|
||||||
protected:
|
protected:
|
||||||
static bool valid_kcode(irr::EKEY_CODE k)
|
static bool valid_kcode(irr::EKEY_CODE k)
|
||||||
{
|
{
|
||||||
|
|
|
@ -27,8 +27,10 @@ with this program; if not, write to the Free Software Foundation, Inc.,
|
||||||
*/
|
*/
|
||||||
|
|
||||||
// This directly sets the range of light.
|
// This directly sets the range of light.
|
||||||
// Actually this is not the real maximum, and this is not the
|
// Actually this is not the real maximum, and this is not the brightest, the
|
||||||
// brightest. The brightest is LIGHT_SUN.
|
// brightest is LIGHT_SUN.
|
||||||
|
// If changed, this constant as defined in builtin/game/constants.lua must
|
||||||
|
// also be changed.
|
||||||
#define LIGHT_MAX 14
|
#define LIGHT_MAX 14
|
||||||
// Light is stored as 4 bits, thus 15 is the maximum.
|
// Light is stored as 4 bits, thus 15 is the maximum.
|
||||||
// This brightness is reserved for sunlight
|
// This brightness is reserved for sunlight
|
||||||
|
|
|
@ -154,17 +154,27 @@ int MapgenV7::getSpawnLevelAtPoint(v2s16 p)
|
||||||
// Base terrain calculation
|
// Base terrain calculation
|
||||||
s16 y = baseTerrainLevelAtPoint(p.X, p.Y);
|
s16 y = baseTerrainLevelAtPoint(p.X, p.Y);
|
||||||
|
|
||||||
// Ridge/river terrain calculation
|
// If enabled, check if inside a river
|
||||||
float width = 0.2;
|
if (spflags & MGV7_RIDGES) {
|
||||||
float uwatern = NoisePerlin2D(&noise_ridge_uwater->np, p.X, p.Y, seed) * 2;
|
float width = 0.2;
|
||||||
// if inside a river this is an unsuitable spawn point
|
float uwatern = NoisePerlin2D(&noise_ridge_uwater->np, p.X, p.Y, seed) * 2;
|
||||||
if (fabs(uwatern) <= width)
|
if (fabs(uwatern) <= width)
|
||||||
return MAX_MAP_GENERATION_LIMIT;
|
return MAX_MAP_GENERATION_LIMIT; // Unsuitable spawn point
|
||||||
|
}
|
||||||
|
|
||||||
|
// If mountains are disabled, terrain level is base terrain level
|
||||||
|
// Avoids spawn on non-existant mountain terrain
|
||||||
|
if (!(spflags & MGV7_MOUNTAINS)) {
|
||||||
|
if (y <= water_level || y > water_level + 16)
|
||||||
|
return MAX_MAP_GENERATION_LIMIT; // Unsuitable spawn point
|
||||||
|
else
|
||||||
|
return y;
|
||||||
|
}
|
||||||
|
|
||||||
// Mountain terrain calculation
|
// Mountain terrain calculation
|
||||||
int iters = 128;
|
int iters = 128;
|
||||||
while (iters--) {
|
while (iters--) {
|
||||||
if (!getMountainTerrainAtPoint(p.X, y + 1, p.Y)) { // Air, y is ground level
|
if (!getMountainTerrainAtPoint(p.X, y + 1, p.Y)) { // If air above
|
||||||
if (y <= water_level || y > water_level + 16)
|
if (y <= water_level || y > water_level + 16)
|
||||||
return MAX_MAP_GENERATION_LIMIT; // Unsuitable spawn point
|
return MAX_MAP_GENERATION_LIMIT; // Unsuitable spawn point
|
||||||
else
|
else
|
||||||
|
@ -173,7 +183,7 @@ int MapgenV7::getSpawnLevelAtPoint(v2s16 p)
|
||||||
y++;
|
y++;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Unsuitable spawn point, no ground surface found
|
// Unsuitable spawn point, no mountain surface found
|
||||||
return MAX_MAP_GENERATION_LIMIT;
|
return MAX_MAP_GENERATION_LIMIT;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -42,9 +42,8 @@ void MapSector::deleteBlocks()
|
||||||
m_block_cache = NULL;
|
m_block_cache = NULL;
|
||||||
|
|
||||||
// Delete all
|
// Delete all
|
||||||
for(std::map<s16, MapBlock*>::iterator i = m_blocks.begin();
|
for (UNORDERED_MAP<s16, MapBlock*>::iterator i = m_blocks.begin();
|
||||||
i != m_blocks.end(); ++i)
|
i != m_blocks.end(); ++i) {
|
||||||
{
|
|
||||||
delete i->second;
|
delete i->second;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -56,20 +55,13 @@ MapBlock * MapSector::getBlockBuffered(s16 y)
|
||||||
{
|
{
|
||||||
MapBlock *block;
|
MapBlock *block;
|
||||||
|
|
||||||
if(m_block_cache != NULL && y == m_block_cache_y){
|
if (m_block_cache != NULL && y == m_block_cache_y) {
|
||||||
return m_block_cache;
|
return m_block_cache;
|
||||||
}
|
}
|
||||||
|
|
||||||
// If block doesn't exist, return NULL
|
// If block doesn't exist, return NULL
|
||||||
std::map<s16, MapBlock*>::iterator n = m_blocks.find(y);
|
UNORDERED_MAP<s16, MapBlock*>::iterator n = m_blocks.find(y);
|
||||||
if(n == m_blocks.end())
|
block = (n != m_blocks.end() ? n->second : NULL);
|
||||||
{
|
|
||||||
block = NULL;
|
|
||||||
}
|
|
||||||
// If block exists, return it
|
|
||||||
else{
|
|
||||||
block = n->second;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Cache the last result
|
// Cache the last result
|
||||||
m_block_cache_y = y;
|
m_block_cache_y = y;
|
||||||
|
@ -135,18 +127,12 @@ void MapSector::deleteBlock(MapBlock *block)
|
||||||
|
|
||||||
void MapSector::getBlocks(MapBlockVect &dest)
|
void MapSector::getBlocks(MapBlockVect &dest)
|
||||||
{
|
{
|
||||||
for(std::map<s16, MapBlock*>::iterator bi = m_blocks.begin();
|
for (UNORDERED_MAP<s16, MapBlock*>::iterator bi = m_blocks.begin();
|
||||||
bi != m_blocks.end(); ++bi)
|
bi != m_blocks.end(); ++bi) {
|
||||||
{
|
|
||||||
dest.push_back(bi->second);
|
dest.push_back(bi->second);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
bool MapSector::empty()
|
|
||||||
{
|
|
||||||
return m_blocks.empty();
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
ServerMapSector
|
ServerMapSector
|
||||||
*/
|
*/
|
||||||
|
|
|
@ -63,7 +63,7 @@ public:
|
||||||
|
|
||||||
void getBlocks(MapBlockVect &dest);
|
void getBlocks(MapBlockVect &dest);
|
||||||
|
|
||||||
bool empty();
|
bool empty() const { return m_blocks.empty(); }
|
||||||
|
|
||||||
// Always false at the moment, because sector contains no metadata.
|
// Always false at the moment, because sector contains no metadata.
|
||||||
bool differs_from_disk;
|
bool differs_from_disk;
|
||||||
|
@ -71,7 +71,7 @@ public:
|
||||||
protected:
|
protected:
|
||||||
|
|
||||||
// The pile of MapBlocks
|
// The pile of MapBlocks
|
||||||
std::map<s16, MapBlock*> m_blocks;
|
UNORDERED_MAP<s16, MapBlock*> m_blocks;
|
||||||
|
|
||||||
Map *m_parent;
|
Map *m_parent;
|
||||||
// Position on parent (in MapBlock widths)
|
// Position on parent (in MapBlock widths)
|
||||||
|
|
|
@ -26,12 +26,12 @@ with this program; if not, write to the Free Software Foundation, Inc.,
|
||||||
#include "util/numeric.h"
|
#include "util/numeric.h"
|
||||||
|
|
||||||
FlagDesc flagdesc_deco[] = {
|
FlagDesc flagdesc_deco[] = {
|
||||||
{"place_center_x", DECO_PLACE_CENTER_X},
|
{"place_center_x", DECO_PLACE_CENTER_X},
|
||||||
{"place_center_y", DECO_PLACE_CENTER_Y},
|
{"place_center_y", DECO_PLACE_CENTER_Y},
|
||||||
{"place_center_z", DECO_PLACE_CENTER_Z},
|
{"place_center_z", DECO_PLACE_CENTER_Z},
|
||||||
{"force_placement", DECO_FORCE_PLACEMENT},
|
{"force_placement", DECO_FORCE_PLACEMENT},
|
||||||
{"liquid_surface", DECO_LIQUID_SURFACE},
|
{"liquid_surface", DECO_LIQUID_SURFACE},
|
||||||
{NULL, 0}
|
{NULL, 0}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
|
@ -82,6 +82,56 @@ Decoration::~Decoration()
|
||||||
void Decoration::resolveNodeNames()
|
void Decoration::resolveNodeNames()
|
||||||
{
|
{
|
||||||
getIdsFromNrBacklog(&c_place_on);
|
getIdsFromNrBacklog(&c_place_on);
|
||||||
|
getIdsFromNrBacklog(&c_spawnby);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
bool Decoration::canPlaceDecoration(MMVManip *vm, v3s16 p)
|
||||||
|
{
|
||||||
|
// Check if the decoration can be placed on this node
|
||||||
|
u32 vi = vm->m_area.index(p);
|
||||||
|
if (!CONTAINS(c_place_on, vm->m_data[vi].getContent()))
|
||||||
|
return false;
|
||||||
|
|
||||||
|
// Don't continue if there are no spawnby constraints
|
||||||
|
if (nspawnby == -1)
|
||||||
|
return true;
|
||||||
|
|
||||||
|
int nneighs = 0;
|
||||||
|
static const v3s16 dirs[16] = {
|
||||||
|
v3s16( 0, 0, 1),
|
||||||
|
v3s16( 0, 0, -1),
|
||||||
|
v3s16( 1, 0, 0),
|
||||||
|
v3s16(-1, 0, 0),
|
||||||
|
v3s16( 1, 0, 1),
|
||||||
|
v3s16(-1, 0, 1),
|
||||||
|
v3s16(-1, 0, -1),
|
||||||
|
v3s16( 1, 0, -1),
|
||||||
|
|
||||||
|
v3s16( 0, 1, 1),
|
||||||
|
v3s16( 0, 1, -1),
|
||||||
|
v3s16( 1, 1, 0),
|
||||||
|
v3s16(-1, 1, 0),
|
||||||
|
v3s16( 1, 1, 1),
|
||||||
|
v3s16(-1, 1, 1),
|
||||||
|
v3s16(-1, 1, -1),
|
||||||
|
v3s16( 1, 1, -1)
|
||||||
|
};
|
||||||
|
|
||||||
|
// Check these 16 neighbouring nodes for enough spawnby nodes
|
||||||
|
for (size_t i = 0; i != ARRLEN(dirs); i++) {
|
||||||
|
u32 index = vm->m_area.index(p + dirs[i]);
|
||||||
|
if (!vm->m_area.contains(index))
|
||||||
|
continue;
|
||||||
|
|
||||||
|
if (CONTAINS(c_spawnby, vm->m_data[index].getContent()))
|
||||||
|
nneighs++;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (nneighs < nspawnby)
|
||||||
|
return false;
|
||||||
|
|
||||||
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -236,66 +286,15 @@ void DecoSimple::resolveNodeNames()
|
||||||
{
|
{
|
||||||
Decoration::resolveNodeNames();
|
Decoration::resolveNodeNames();
|
||||||
getIdsFromNrBacklog(&c_decos);
|
getIdsFromNrBacklog(&c_decos);
|
||||||
getIdsFromNrBacklog(&c_spawnby);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
bool DecoSimple::canPlaceDecoration(MMVManip *vm, v3s16 p)
|
|
||||||
{
|
|
||||||
// Don't bother if there aren't any decorations to place
|
|
||||||
if (c_decos.size() == 0)
|
|
||||||
return false;
|
|
||||||
|
|
||||||
u32 vi = vm->m_area.index(p);
|
|
||||||
|
|
||||||
// Check if the decoration can be placed on this node
|
|
||||||
if (!CONTAINS(c_place_on, vm->m_data[vi].getContent()))
|
|
||||||
return false;
|
|
||||||
|
|
||||||
// Don't continue if there are no spawnby constraints
|
|
||||||
if (nspawnby == -1)
|
|
||||||
return true;
|
|
||||||
|
|
||||||
int nneighs = 0;
|
|
||||||
v3s16 dirs[16] = {
|
|
||||||
v3s16( 0, 0, 1),
|
|
||||||
v3s16( 0, 0, -1),
|
|
||||||
v3s16( 1, 0, 0),
|
|
||||||
v3s16(-1, 0, 0),
|
|
||||||
v3s16( 1, 0, 1),
|
|
||||||
v3s16(-1, 0, 1),
|
|
||||||
v3s16(-1, 0, -1),
|
|
||||||
v3s16( 1, 0, -1),
|
|
||||||
|
|
||||||
v3s16( 0, 1, 1),
|
|
||||||
v3s16( 0, 1, -1),
|
|
||||||
v3s16( 1, 1, 0),
|
|
||||||
v3s16(-1, 1, 0),
|
|
||||||
v3s16( 1, 1, 1),
|
|
||||||
v3s16(-1, 1, 1),
|
|
||||||
v3s16(-1, 1, -1),
|
|
||||||
v3s16( 1, 1, -1)
|
|
||||||
};
|
|
||||||
|
|
||||||
// Check a Moore neighborhood if there are enough spawnby nodes
|
|
||||||
for (size_t i = 0; i != ARRLEN(dirs); i++) {
|
|
||||||
u32 index = vm->m_area.index(p + dirs[i]);
|
|
||||||
if (!vm->m_area.contains(index))
|
|
||||||
continue;
|
|
||||||
|
|
||||||
if (CONTAINS(c_spawnby, vm->m_data[index].getContent()))
|
|
||||||
nneighs++;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (nneighs < nspawnby)
|
|
||||||
return false;
|
|
||||||
|
|
||||||
return true;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
size_t DecoSimple::generate(MMVManip *vm, PcgRandom *pr, v3s16 p)
|
size_t DecoSimple::generate(MMVManip *vm, PcgRandom *pr, v3s16 p)
|
||||||
{
|
{
|
||||||
|
// Don't bother if there aren't any decorations to place
|
||||||
|
if (c_decos.size() == 0)
|
||||||
|
return 0;
|
||||||
|
|
||||||
if (!canPlaceDecoration(vm, p))
|
if (!canPlaceDecoration(vm, p))
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
|
@ -345,9 +344,7 @@ size_t DecoSchematic::generate(MMVManip *vm, PcgRandom *pr, v3s16 p)
|
||||||
if (schematic == NULL)
|
if (schematic == NULL)
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
u32 vi = vm->m_area.index(p);
|
if (!canPlaceDecoration(vm, p))
|
||||||
content_t c = vm->m_data[vi].getContent();
|
|
||||||
if (!CONTAINS(c_place_on, c))
|
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
if (flags & DECO_PLACE_CENTER_X)
|
if (flags & DECO_PLACE_CENTER_X)
|
||||||
|
|
|
@ -68,6 +68,7 @@ public:
|
||||||
|
|
||||||
virtual void resolveNodeNames();
|
virtual void resolveNodeNames();
|
||||||
|
|
||||||
|
bool canPlaceDecoration(MMVManip *vm, v3s16 p);
|
||||||
size_t placeDeco(Mapgen *mg, u32 blockseed, v3s16 nmin, v3s16 nmax);
|
size_t placeDeco(Mapgen *mg, u32 blockseed, v3s16 nmin, v3s16 nmax);
|
||||||
//size_t placeCutoffs(Mapgen *mg, u32 blockseed, v3s16 nmin, v3s16 nmax);
|
//size_t placeCutoffs(Mapgen *mg, u32 blockseed, v3s16 nmin, v3s16 nmax);
|
||||||
|
|
||||||
|
@ -82,6 +83,8 @@ public:
|
||||||
s16 y_max;
|
s16 y_max;
|
||||||
float fill_ratio;
|
float fill_ratio;
|
||||||
NoiseParams np;
|
NoiseParams np;
|
||||||
|
std::vector<content_t> c_spawnby;
|
||||||
|
s16 nspawnby;
|
||||||
|
|
||||||
UNORDERED_SET<u8> biomes;
|
UNORDERED_SET<u8> biomes;
|
||||||
//std::list<CutoffData> cutoffs;
|
//std::list<CutoffData> cutoffs;
|
||||||
|
@ -90,17 +93,13 @@ public:
|
||||||
|
|
||||||
class DecoSimple : public Decoration {
|
class DecoSimple : public Decoration {
|
||||||
public:
|
public:
|
||||||
|
virtual void resolveNodeNames();
|
||||||
virtual size_t generate(MMVManip *vm, PcgRandom *pr, v3s16 p);
|
virtual size_t generate(MMVManip *vm, PcgRandom *pr, v3s16 p);
|
||||||
bool canPlaceDecoration(MMVManip *vm, v3s16 p);
|
|
||||||
virtual int getHeight();
|
virtual int getHeight();
|
||||||
|
|
||||||
virtual void resolveNodeNames();
|
|
||||||
|
|
||||||
std::vector<content_t> c_decos;
|
std::vector<content_t> c_decos;
|
||||||
std::vector<content_t> c_spawnby;
|
|
||||||
s16 deco_height;
|
s16 deco_height;
|
||||||
s16 deco_height_max;
|
s16 deco_height_max;
|
||||||
s16 nspawnby;
|
|
||||||
};
|
};
|
||||||
|
|
||||||
class DecoSchematic : public Decoration {
|
class DecoSchematic : public Decoration {
|
||||||
|
|
|
@ -564,14 +564,14 @@ void Schematic::applyProbabilities(v3s16 p0,
|
||||||
void generate_nodelist_and_update_ids(MapNode *nodes, size_t nodecount,
|
void generate_nodelist_and_update_ids(MapNode *nodes, size_t nodecount,
|
||||||
std::vector<std::string> *usednodes, INodeDefManager *ndef)
|
std::vector<std::string> *usednodes, INodeDefManager *ndef)
|
||||||
{
|
{
|
||||||
std::map<content_t, content_t> nodeidmap;
|
UNORDERED_MAP<content_t, content_t> nodeidmap;
|
||||||
content_t numids = 0;
|
content_t numids = 0;
|
||||||
|
|
||||||
for (size_t i = 0; i != nodecount; i++) {
|
for (size_t i = 0; i != nodecount; i++) {
|
||||||
content_t id;
|
content_t id;
|
||||||
content_t c = nodes[i].getContent();
|
content_t c = nodes[i].getContent();
|
||||||
|
|
||||||
std::map<content_t, content_t>::const_iterator it = nodeidmap.find(c);
|
UNORDERED_MAP<content_t, content_t>::const_iterator it = nodeidmap.find(c);
|
||||||
if (it == nodeidmap.end()) {
|
if (it == nodeidmap.end()) {
|
||||||
id = numids;
|
id = numids;
|
||||||
numids++;
|
numids++;
|
||||||
|
|
|
@ -1065,7 +1065,7 @@ void Server::handleCommand_ChatMessage(NetworkPacket* pkt)
|
||||||
std::wstring wname = narrow_to_wide(name);
|
std::wstring wname = narrow_to_wide(name);
|
||||||
|
|
||||||
std::wstring answer_to_sender = handleChat(name, wname, message,
|
std::wstring answer_to_sender = handleChat(name, wname, message,
|
||||||
true, pkt->getPeerId());
|
true, dynamic_cast<RemotePlayer *>(player));
|
||||||
if (!answer_to_sender.empty()) {
|
if (!answer_to_sender.empty()) {
|
||||||
// Send the answer to sender
|
// Send the answer to sender
|
||||||
SendChatMessage(pkt->getPeerId(), answer_to_sender);
|
SendChatMessage(pkt->getPeerId(), answer_to_sender);
|
||||||
|
@ -1656,16 +1656,16 @@ void Server::handleCommand_Interact(NetworkPacket* pkt)
|
||||||
}
|
}
|
||||||
|
|
||||||
} // action == 4
|
} // action == 4
|
||||||
|
|
||||||
/*
|
/*
|
||||||
5: rightclick air
|
5: rightclick air
|
||||||
*/
|
*/
|
||||||
else if (action == 5) {
|
else if (action == 5) {
|
||||||
ItemStack item = playersao->getWieldedItem();
|
ItemStack item = playersao->getWieldedItem();
|
||||||
|
|
||||||
actionstream << player->getName() << " activates "
|
actionstream << player->getName() << " activates "
|
||||||
<< item.name << std::endl;
|
<< item.name << std::endl;
|
||||||
|
|
||||||
if (m_script->item_OnSecondaryUse(
|
if (m_script->item_OnSecondaryUse(
|
||||||
item, playersao)) {
|
item, playersao)) {
|
||||||
if( playersao->setWieldedItem(item)) {
|
if( playersao->setWieldedItem(item)) {
|
||||||
|
|
|
@ -74,6 +74,11 @@ void NodeMetadata::clear()
|
||||||
m_inventory->clear();
|
m_inventory->clear();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool NodeMetadata::empty() const
|
||||||
|
{
|
||||||
|
return m_stringvars.size() == 0 && m_inventory->getLists().size() == 0;
|
||||||
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
NodeMetadataList
|
NodeMetadataList
|
||||||
*/
|
*/
|
||||||
|
@ -84,14 +89,13 @@ void NodeMetadataList::serialize(std::ostream &os) const
|
||||||
Version 0 is a placeholder for "nothing to see here; go away."
|
Version 0 is a placeholder for "nothing to see here; go away."
|
||||||
*/
|
*/
|
||||||
|
|
||||||
if(m_data.empty()){
|
u16 count = countNonEmpty();
|
||||||
|
if (count == 0) {
|
||||||
writeU8(os, 0); // version
|
writeU8(os, 0); // version
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
writeU8(os, 1); // version
|
writeU8(os, 1); // version
|
||||||
|
|
||||||
u16 count = m_data.size();
|
|
||||||
writeU16(os, count);
|
writeU16(os, count);
|
||||||
|
|
||||||
for(std::map<v3s16, NodeMetadata*>::const_iterator
|
for(std::map<v3s16, NodeMetadata*>::const_iterator
|
||||||
|
@ -100,6 +104,8 @@ void NodeMetadataList::serialize(std::ostream &os) const
|
||||||
{
|
{
|
||||||
v3s16 p = i->first;
|
v3s16 p = i->first;
|
||||||
NodeMetadata *data = i->second;
|
NodeMetadata *data = i->second;
|
||||||
|
if (data->empty())
|
||||||
|
continue;
|
||||||
|
|
||||||
u16 p16 = p.Z * MAP_BLOCKSIZE * MAP_BLOCKSIZE + p.Y * MAP_BLOCKSIZE + p.X;
|
u16 p16 = p.Z * MAP_BLOCKSIZE * MAP_BLOCKSIZE + p.Y * MAP_BLOCKSIZE + p.X;
|
||||||
writeU16(os, p16);
|
writeU16(os, p16);
|
||||||
|
@ -200,6 +206,17 @@ void NodeMetadataList::clear()
|
||||||
m_data.clear();
|
m_data.clear();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
int NodeMetadataList::countNonEmpty() const
|
||||||
|
{
|
||||||
|
int n = 0;
|
||||||
|
std::map<v3s16, NodeMetadata*>::const_iterator it;
|
||||||
|
for (it = m_data.begin(); it != m_data.end(); ++it) {
|
||||||
|
if (!it->second->empty())
|
||||||
|
n++;
|
||||||
|
}
|
||||||
|
return n;
|
||||||
|
}
|
||||||
|
|
||||||
std::string NodeMetadata::getString(const std::string &name,
|
std::string NodeMetadata::getString(const std::string &name,
|
||||||
unsigned short recursion) const
|
unsigned short recursion) const
|
||||||
{
|
{
|
||||||
|
|
|
@ -47,6 +47,7 @@ public:
|
||||||
void deSerialize(std::istream &is);
|
void deSerialize(std::istream &is);
|
||||||
|
|
||||||
void clear();
|
void clear();
|
||||||
|
bool empty() const;
|
||||||
|
|
||||||
// Generic key/value store
|
// Generic key/value store
|
||||||
std::string getString(const std::string &name, unsigned short recursion = 0) const;
|
std::string getString(const std::string &name, unsigned short recursion = 0) const;
|
||||||
|
@ -94,6 +95,8 @@ public:
|
||||||
void clear();
|
void clear();
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
int countNonEmpty() const;
|
||||||
|
|
||||||
std::map<v3s16, NodeMetadata *> m_data;
|
std::map<v3s16, NodeMetadata *> m_data;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
@ -227,10 +227,25 @@ void Player::clearHud()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// static config cache for remoteplayer
|
||||||
|
bool RemotePlayer::m_setting_cache_loaded = false;
|
||||||
|
float RemotePlayer::m_setting_chat_message_limit_per_10sec = 0.0f;
|
||||||
|
u16 RemotePlayer::m_setting_chat_message_limit_trigger_kick = 0;
|
||||||
|
|
||||||
RemotePlayer::RemotePlayer(IGameDef *gamedef, const char *name):
|
RemotePlayer::RemotePlayer(IGameDef *gamedef, const char *name):
|
||||||
Player(gamedef, name),
|
Player(gamedef, name),
|
||||||
m_sao(NULL)
|
m_sao(NULL),
|
||||||
|
m_last_chat_message_sent(time(NULL)),
|
||||||
|
m_chat_message_allowance(5.0f),
|
||||||
|
m_message_rate_overhead(0)
|
||||||
{
|
{
|
||||||
|
if (!RemotePlayer::m_setting_cache_loaded) {
|
||||||
|
RemotePlayer::m_setting_chat_message_limit_per_10sec =
|
||||||
|
g_settings->getFloat("chat_message_limit_per_10sec");
|
||||||
|
RemotePlayer::m_setting_chat_message_limit_trigger_kick =
|
||||||
|
g_settings->getU16("chat_message_limit_trigger_kick");
|
||||||
|
RemotePlayer::m_setting_cache_loaded = true;
|
||||||
|
}
|
||||||
movement_acceleration_default = g_settings->getFloat("movement_acceleration_default") * BS;
|
movement_acceleration_default = g_settings->getFloat("movement_acceleration_default") * BS;
|
||||||
movement_acceleration_air = g_settings->getFloat("movement_acceleration_air") * BS;
|
movement_acceleration_air = g_settings->getFloat("movement_acceleration_air") * BS;
|
||||||
movement_acceleration_fast = g_settings->getFloat("movement_acceleration_fast") * BS;
|
movement_acceleration_fast = g_settings->getFloat("movement_acceleration_fast") * BS;
|
||||||
|
@ -304,3 +319,42 @@ void RemotePlayer::setPosition(const v3f &position)
|
||||||
m_sao->setBasePosition(position);
|
m_sao->setBasePosition(position);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const RemotePlayerChatResult RemotePlayer::canSendChatMessage()
|
||||||
|
{
|
||||||
|
// Rate limit messages
|
||||||
|
u32 now = time(NULL);
|
||||||
|
float time_passed = now - m_last_chat_message_sent;
|
||||||
|
m_last_chat_message_sent = now;
|
||||||
|
|
||||||
|
// If this feature is disabled
|
||||||
|
if (m_setting_chat_message_limit_per_10sec <= 0.0) {
|
||||||
|
return RPLAYER_CHATRESULT_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
m_chat_message_allowance += time_passed * (m_setting_chat_message_limit_per_10sec / 8.0f);
|
||||||
|
if (m_chat_message_allowance > m_setting_chat_message_limit_per_10sec) {
|
||||||
|
m_chat_message_allowance = m_setting_chat_message_limit_per_10sec;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (m_chat_message_allowance < 1.0f) {
|
||||||
|
infostream << "Player " << m_name
|
||||||
|
<< " chat limited due to excessive message amount." << std::endl;
|
||||||
|
|
||||||
|
// Kick player if flooding is too intensive
|
||||||
|
m_message_rate_overhead++;
|
||||||
|
if (m_message_rate_overhead > RemotePlayer::m_setting_chat_message_limit_trigger_kick) {
|
||||||
|
return RPLAYER_CHATRESULT_KICK;
|
||||||
|
}
|
||||||
|
|
||||||
|
return RPLAYER_CHATRESULT_FLOODING;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Reinit message overhead
|
||||||
|
if (m_message_rate_overhead > 0) {
|
||||||
|
m_message_rate_overhead = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
m_chat_message_allowance -= 1.0f;
|
||||||
|
return RPLAYER_CHATRESULT_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
16
src/player.h
16
src/player.h
|
@ -439,7 +439,11 @@ private:
|
||||||
Mutex m_mutex;
|
Mutex m_mutex;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
enum RemotePlayerChatResult {
|
||||||
|
RPLAYER_CHATRESULT_OK,
|
||||||
|
RPLAYER_CHATRESULT_FLOODING,
|
||||||
|
RPLAYER_CHATRESULT_KICK,
|
||||||
|
};
|
||||||
/*
|
/*
|
||||||
Player on the server
|
Player on the server
|
||||||
*/
|
*/
|
||||||
|
@ -457,8 +461,18 @@ public:
|
||||||
{ m_sao = sao; }
|
{ m_sao = sao; }
|
||||||
void setPosition(const v3f &position);
|
void setPosition(const v3f &position);
|
||||||
|
|
||||||
|
const RemotePlayerChatResult canSendChatMessage();
|
||||||
|
|
||||||
private:
|
private:
|
||||||
PlayerSAO *m_sao;
|
PlayerSAO *m_sao;
|
||||||
|
|
||||||
|
static bool m_setting_cache_loaded;
|
||||||
|
static float m_setting_chat_message_limit_per_10sec;
|
||||||
|
static u16 m_setting_chat_message_limit_trigger_kick;
|
||||||
|
|
||||||
|
u32 m_last_chat_message_sent;
|
||||||
|
float m_chat_message_allowance;
|
||||||
|
u16 m_message_rate_overhead;
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
|
@ -613,10 +613,11 @@ void setXorgClassHint(const video::SExposedVideoData &video_data,
|
||||||
|
|
||||||
bool setXorgWindowIcon(IrrlichtDevice *device)
|
bool setXorgWindowIcon(IrrlichtDevice *device)
|
||||||
{
|
{
|
||||||
#if RUN_IN_PLACE
|
#ifdef XORG_USED
|
||||||
|
# if RUN_IN_PLACE
|
||||||
return setXorgWindowIconFromPath(device,
|
return setXorgWindowIconFromPath(device,
|
||||||
path_share + "/misc/" PROJECT_NAME "-xorg-icon-128.png");
|
path_share + "/misc/" PROJECT_NAME "-xorg-icon-128.png");
|
||||||
#else
|
# else
|
||||||
// We have semi-support for reading in-place data if we are
|
// We have semi-support for reading in-place data if we are
|
||||||
// compiled with RUN_IN_PLACE. Don't break with this and
|
// compiled with RUN_IN_PLACE. Don't break with this and
|
||||||
// also try the path_share location.
|
// also try the path_share location.
|
||||||
|
@ -625,6 +626,9 @@ bool setXorgWindowIcon(IrrlichtDevice *device)
|
||||||
ICON_DIR "/hicolor/128x128/apps/" PROJECT_NAME ".png") ||
|
ICON_DIR "/hicolor/128x128/apps/" PROJECT_NAME ".png") ||
|
||||||
setXorgWindowIconFromPath(device,
|
setXorgWindowIconFromPath(device,
|
||||||
path_share + "/misc/" PROJECT_NAME "-xorg-icon-128.png");
|
path_share + "/misc/" PROJECT_NAME "-xorg-icon-128.png");
|
||||||
|
# endif
|
||||||
|
#else
|
||||||
|
return false;
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -829,20 +829,18 @@ void push_tool_capabilities(lua_State *L,
|
||||||
// Create groupcaps table
|
// Create groupcaps table
|
||||||
lua_newtable(L);
|
lua_newtable(L);
|
||||||
// For each groupcap
|
// For each groupcap
|
||||||
for(std::map<std::string, ToolGroupCap>::const_iterator
|
for (ToolGCMap::const_iterator i = toolcap.groupcaps.begin();
|
||||||
i = toolcap.groupcaps.begin(); i != toolcap.groupcaps.end(); i++){
|
i != toolcap.groupcaps.end(); i++) {
|
||||||
// Create groupcap table
|
// Create groupcap table
|
||||||
lua_newtable(L);
|
lua_newtable(L);
|
||||||
const std::string &name = i->first;
|
const std::string &name = i->first;
|
||||||
const ToolGroupCap &groupcap = i->second;
|
const ToolGroupCap &groupcap = i->second;
|
||||||
// Create subtable "times"
|
// Create subtable "times"
|
||||||
lua_newtable(L);
|
lua_newtable(L);
|
||||||
for(std::map<int, float>::const_iterator
|
for (UNORDERED_MAP<int, float>::const_iterator
|
||||||
i = groupcap.times.begin(); i != groupcap.times.end(); i++){
|
i = groupcap.times.begin(); i != groupcap.times.end(); i++) {
|
||||||
int rating = i->first;
|
lua_pushinteger(L, i->first);
|
||||||
float time = i->second;
|
lua_pushnumber(L, i->second);
|
||||||
lua_pushinteger(L, rating);
|
|
||||||
lua_pushnumber(L, time);
|
|
||||||
lua_settable(L, -3);
|
lua_settable(L, -3);
|
||||||
}
|
}
|
||||||
// Set subtable "times"
|
// Set subtable "times"
|
||||||
|
@ -858,8 +856,8 @@ void push_tool_capabilities(lua_State *L,
|
||||||
//Create damage_groups table
|
//Create damage_groups table
|
||||||
lua_newtable(L);
|
lua_newtable(L);
|
||||||
// For each damage group
|
// For each damage group
|
||||||
for(std::map<std::string, s16>::const_iterator
|
for (DamageGroup::const_iterator i = toolcap.damageGroups.begin();
|
||||||
i = toolcap.damageGroups.begin(); i != toolcap.damageGroups.end(); i++){
|
i != toolcap.damageGroups.end(); i++) {
|
||||||
// Create damage group table
|
// Create damage group table
|
||||||
lua_pushinteger(L, i->second);
|
lua_pushinteger(L, i->second);
|
||||||
lua_setfield(L, -2, i->first.c_str());
|
lua_setfield(L, -2, i->first.c_str());
|
||||||
|
@ -1065,8 +1063,7 @@ void push_flags_string(lua_State *L, FlagDesc *flagdesc, u32 flags, u32 flagmask
|
||||||
/******************************************************************************/
|
/******************************************************************************/
|
||||||
|
|
||||||
/******************************************************************************/
|
/******************************************************************************/
|
||||||
void read_groups(lua_State *L, int index,
|
void read_groups(lua_State *L, int index, ItemGroupList &result)
|
||||||
std::map<std::string, int> &result)
|
|
||||||
{
|
{
|
||||||
if (!lua_istable(L,index))
|
if (!lua_istable(L,index))
|
||||||
return;
|
return;
|
||||||
|
@ -1085,11 +1082,10 @@ void read_groups(lua_State *L, int index,
|
||||||
}
|
}
|
||||||
|
|
||||||
/******************************************************************************/
|
/******************************************************************************/
|
||||||
void push_groups(lua_State *L, const std::map<std::string, int> &groups)
|
void push_groups(lua_State *L, const ItemGroupList &groups)
|
||||||
{
|
{
|
||||||
lua_newtable(L);
|
lua_newtable(L);
|
||||||
std::map<std::string, int>::const_iterator it;
|
for (ItemGroupList::const_iterator it = groups.begin(); it != groups.end(); ++it) {
|
||||||
for (it = groups.begin(); it != groups.end(); ++it) {
|
|
||||||
lua_pushnumber(L, it->second);
|
lua_pushnumber(L, it->second);
|
||||||
lua_setfield(L, -2, it->first.c_str());
|
lua_setfield(L, -2, it->first.c_str());
|
||||||
}
|
}
|
||||||
|
|
|
@ -33,11 +33,11 @@ extern "C" {
|
||||||
}
|
}
|
||||||
|
|
||||||
#include <iostream>
|
#include <iostream>
|
||||||
#include <map>
|
|
||||||
#include <vector>
|
#include <vector>
|
||||||
|
|
||||||
#include "irrlichttypes_bloated.h"
|
#include "irrlichttypes_bloated.h"
|
||||||
#include "util/string.h"
|
#include "util/string.h"
|
||||||
|
#include "itemgroup.h"
|
||||||
|
|
||||||
namespace Json { class Value; }
|
namespace Json { class Value; }
|
||||||
|
|
||||||
|
@ -106,10 +106,10 @@ void pushnode (lua_State *L, const MapNode &n,
|
||||||
NodeBox read_nodebox (lua_State *L, int index);
|
NodeBox read_nodebox (lua_State *L, int index);
|
||||||
|
|
||||||
void read_groups (lua_State *L, int index,
|
void read_groups (lua_State *L, int index,
|
||||||
std::map<std::string, int> &result);
|
ItemGroupList &result);
|
||||||
|
|
||||||
void push_groups (lua_State *L,
|
void push_groups (lua_State *L,
|
||||||
const std::map<std::string, int> &groups);
|
const ItemGroupList &groups);
|
||||||
|
|
||||||
//TODO rename to "read_enum_field"
|
//TODO rename to "read_enum_field"
|
||||||
int getenumfield (lua_State *L, int table,
|
int getenumfield (lua_State *L, int table,
|
||||||
|
|
|
@ -28,7 +28,7 @@ with this program; if not, write to the Free Software Foundation, Inc.,
|
||||||
#define C_CONVERTER_H_
|
#define C_CONVERTER_H_
|
||||||
|
|
||||||
#include <vector>
|
#include <vector>
|
||||||
#include <map>
|
#include "util/cpp11_container.h"
|
||||||
|
|
||||||
#include "irrlichttypes_bloated.h"
|
#include "irrlichttypes_bloated.h"
|
||||||
#include "common/c_types.h"
|
#include "common/c_types.h"
|
||||||
|
@ -60,7 +60,7 @@ bool getintfield(lua_State *L, int table,
|
||||||
bool getintfield(lua_State *L, int table,
|
bool getintfield(lua_State *L, int table,
|
||||||
const char *fieldname, u32 &result);
|
const char *fieldname, u32 &result);
|
||||||
void read_groups(lua_State *L, int index,
|
void read_groups(lua_State *L, int index,
|
||||||
std::map<std::string, int> &result);
|
UNORDERED_MAP<std::string, int> &result);
|
||||||
bool getboolfield(lua_State *L, int table,
|
bool getboolfield(lua_State *L, int table,
|
||||||
const char *fieldname, bool &result);
|
const char *fieldname, bool &result);
|
||||||
bool getfloatfield(lua_State *L, int table,
|
bool getfloatfield(lua_State *L, int table,
|
||||||
|
|
|
@ -111,6 +111,9 @@ int LuaAreaStore::l_get_area(lua_State *L)
|
||||||
const Area *res;
|
const Area *res;
|
||||||
|
|
||||||
res = ast->getArea(id);
|
res = ast->getArea(id);
|
||||||
|
if (!res)
|
||||||
|
return 0;
|
||||||
|
|
||||||
push_area(L, res, include_borders, include_data);
|
push_area(L, res, include_borders, include_data);
|
||||||
|
|
||||||
return 1;
|
return 1;
|
||||||
|
|
|
@ -902,6 +902,7 @@ int ModApiMapgen::l_register_decoration(lua_State *L)
|
||||||
deco->fill_ratio = getfloatfield_default(L, index, "fill_ratio", 0.02);
|
deco->fill_ratio = getfloatfield_default(L, index, "fill_ratio", 0.02);
|
||||||
deco->y_min = getintfield_default(L, index, "y_min", -31000);
|
deco->y_min = getintfield_default(L, index, "y_min", -31000);
|
||||||
deco->y_max = getintfield_default(L, index, "y_max", 31000);
|
deco->y_max = getintfield_default(L, index, "y_max", 31000);
|
||||||
|
deco->nspawnby = getintfield_default(L, index, "num_spawn_by", -1);
|
||||||
deco->sidelen = getintfield_default(L, index, "sidelen", 8);
|
deco->sidelen = getintfield_default(L, index, "sidelen", 8);
|
||||||
if (deco->sidelen <= 0) {
|
if (deco->sidelen <= 0) {
|
||||||
errorstream << "register_decoration: sidelen must be "
|
errorstream << "register_decoration: sidelen must be "
|
||||||
|
@ -929,6 +930,14 @@ int ModApiMapgen::l_register_decoration(lua_State *L)
|
||||||
errorstream << "register_decoration: couldn't get all biomes " << std::endl;
|
errorstream << "register_decoration: couldn't get all biomes " << std::endl;
|
||||||
lua_pop(L, 1);
|
lua_pop(L, 1);
|
||||||
|
|
||||||
|
//// Get node name(s) to 'spawn by'
|
||||||
|
size_t nnames = getstringlistfield(L, index, "spawn_by", &deco->m_nodenames);
|
||||||
|
deco->m_nnlistsizes.push_back(nnames);
|
||||||
|
if (nnames == 0 && deco->nspawnby != -1) {
|
||||||
|
errorstream << "register_decoration: no spawn_by nodes defined,"
|
||||||
|
" but num_spawn_by specified" << std::endl;
|
||||||
|
}
|
||||||
|
|
||||||
//// Handle decoration type-specific parameters
|
//// Handle decoration type-specific parameters
|
||||||
bool success = false;
|
bool success = false;
|
||||||
switch (decotype) {
|
switch (decotype) {
|
||||||
|
@ -962,12 +971,10 @@ int ModApiMapgen::l_register_decoration(lua_State *L)
|
||||||
|
|
||||||
bool read_deco_simple(lua_State *L, DecoSimple *deco)
|
bool read_deco_simple(lua_State *L, DecoSimple *deco)
|
||||||
{
|
{
|
||||||
size_t nnames;
|
|
||||||
int index = 1;
|
int index = 1;
|
||||||
|
|
||||||
deco->deco_height = getintfield_default(L, index, "height", 1);
|
deco->deco_height = getintfield_default(L, index, "height", 1);
|
||||||
deco->deco_height_max = getintfield_default(L, index, "height_max", 0);
|
deco->deco_height_max = getintfield_default(L, index, "height_max", 0);
|
||||||
deco->nspawnby = getintfield_default(L, index, "num_spawn_by", -1);
|
|
||||||
|
|
||||||
if (deco->deco_height <= 0) {
|
if (deco->deco_height <= 0) {
|
||||||
errorstream << "register_decoration: simple decoration height"
|
errorstream << "register_decoration: simple decoration height"
|
||||||
|
@ -975,7 +982,7 @@ bool read_deco_simple(lua_State *L, DecoSimple *deco)
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
nnames = getstringlistfield(L, index, "decoration", &deco->m_nodenames);
|
size_t nnames = getstringlistfield(L, index, "decoration", &deco->m_nodenames);
|
||||||
deco->m_nnlistsizes.push_back(nnames);
|
deco->m_nnlistsizes.push_back(nnames);
|
||||||
if (nnames == 0) {
|
if (nnames == 0) {
|
||||||
errorstream << "register_decoration: no decoration nodes "
|
errorstream << "register_decoration: no decoration nodes "
|
||||||
|
@ -983,14 +990,6 @@ bool read_deco_simple(lua_State *L, DecoSimple *deco)
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
nnames = getstringlistfield(L, index, "spawn_by", &deco->m_nodenames);
|
|
||||||
deco->m_nnlistsizes.push_back(nnames);
|
|
||||||
if (nnames == 0 && deco->nspawnby != -1) {
|
|
||||||
errorstream << "register_decoration: no spawn_by nodes defined,"
|
|
||||||
" but num_spawn_by specified" << std::endl;
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -220,7 +220,7 @@ int ModApiUtil::l_write_json(lua_State *L)
|
||||||
int ModApiUtil::l_get_dig_params(lua_State *L)
|
int ModApiUtil::l_get_dig_params(lua_State *L)
|
||||||
{
|
{
|
||||||
NO_MAP_LOCK_REQUIRED;
|
NO_MAP_LOCK_REQUIRED;
|
||||||
std::map<std::string, int> groups;
|
ItemGroupList groups;
|
||||||
read_groups(L, 1, groups);
|
read_groups(L, 1, groups);
|
||||||
ToolCapabilities tp = read_tool_capabilities(L, 2);
|
ToolCapabilities tp = read_tool_capabilities(L, 2);
|
||||||
if(lua_isnoneornil(L, 3))
|
if(lua_isnoneornil(L, 3))
|
||||||
|
@ -235,7 +235,7 @@ int ModApiUtil::l_get_dig_params(lua_State *L)
|
||||||
int ModApiUtil::l_get_hit_params(lua_State *L)
|
int ModApiUtil::l_get_hit_params(lua_State *L)
|
||||||
{
|
{
|
||||||
NO_MAP_LOCK_REQUIRED;
|
NO_MAP_LOCK_REQUIRED;
|
||||||
std::map<std::string, int> groups;
|
UNORDERED_MAP<std::string, int> groups;
|
||||||
read_groups(L, 1, groups);
|
read_groups(L, 1, groups);
|
||||||
ToolCapabilities tp = read_tool_capabilities(L, 2);
|
ToolCapabilities tp = read_tool_capabilities(L, 2);
|
||||||
if(lua_isnoneornil(L, 3))
|
if(lua_isnoneornil(L, 3))
|
||||||
|
|
|
@ -20,7 +20,7 @@ with this program; if not, write to the Free Software Foundation, Inc.,
|
||||||
#include "serialization.h"
|
#include "serialization.h"
|
||||||
|
|
||||||
#include "util/serialize.h"
|
#include "util/serialize.h"
|
||||||
#ifdef _WIN32
|
#if defined(_WIN32) && !defined(WIN32_NO_ZLIB_WINAPI)
|
||||||
#define ZLIB_WINAPI
|
#define ZLIB_WINAPI
|
||||||
#endif
|
#endif
|
||||||
#include "zlib.h"
|
#include "zlib.h"
|
||||||
|
|
|
@ -358,6 +358,7 @@ Server::Server(
|
||||||
add_legacy_abms(m_env, m_nodedef);
|
add_legacy_abms(m_env, m_nodedef);
|
||||||
|
|
||||||
m_liquid_transform_every = g_settings->getFloat("liquid_update");
|
m_liquid_transform_every = g_settings->getFloat("liquid_update");
|
||||||
|
m_max_chatmessage_length = g_settings->getU16("chat_message_max_size");
|
||||||
}
|
}
|
||||||
|
|
||||||
Server::~Server()
|
Server::~Server()
|
||||||
|
@ -668,7 +669,7 @@ void Server::AsyncRunStep(bool initial_step)
|
||||||
MutexAutoLock envlock(m_env_mutex);
|
MutexAutoLock envlock(m_env_mutex);
|
||||||
|
|
||||||
m_clients.lock();
|
m_clients.lock();
|
||||||
std::map<u16, RemoteClient*> clients = m_clients.getClientList();
|
UNORDERED_MAP<u16, RemoteClient*> clients = m_clients.getClientList();
|
||||||
ScopeProfiler sp(g_profiler, "Server: checking added and deleted objs");
|
ScopeProfiler sp(g_profiler, "Server: checking added and deleted objs");
|
||||||
|
|
||||||
// Radius inside which objects are active
|
// Radius inside which objects are active
|
||||||
|
@ -684,8 +685,7 @@ void Server::AsyncRunStep(bool initial_step)
|
||||||
if (player_radius == 0 && is_transfer_limited)
|
if (player_radius == 0 && is_transfer_limited)
|
||||||
player_radius = radius;
|
player_radius = radius;
|
||||||
|
|
||||||
for (std::map<u16, RemoteClient*>::iterator
|
for (UNORDERED_MAP<u16, RemoteClient*>::iterator i = clients.begin();
|
||||||
i = clients.begin();
|
|
||||||
i != clients.end(); ++i) {
|
i != clients.end(); ++i) {
|
||||||
RemoteClient *client = i->second;
|
RemoteClient *client = i->second;
|
||||||
|
|
||||||
|
@ -695,7 +695,7 @@ void Server::AsyncRunStep(bool initial_step)
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
Player *player = m_env->getPlayer(client->peer_id);
|
Player *player = m_env->getPlayer(client->peer_id);
|
||||||
if(player == NULL) {
|
if (player == NULL) {
|
||||||
// This can happen if the client timeouts somehow
|
// This can happen if the client timeouts somehow
|
||||||
/*warningstream<<FUNCTION_NAME<<": Client "
|
/*warningstream<<FUNCTION_NAME<<": Client "
|
||||||
<<client->peer_id
|
<<client->peer_id
|
||||||
|
@ -816,10 +816,9 @@ void Server::AsyncRunStep(bool initial_step)
|
||||||
}
|
}
|
||||||
|
|
||||||
m_clients.lock();
|
m_clients.lock();
|
||||||
std::map<u16, RemoteClient*> clients = m_clients.getClientList();
|
UNORDERED_MAP<u16, RemoteClient*> clients = m_clients.getClientList();
|
||||||
// Route data to every client
|
// Route data to every client
|
||||||
for (std::map<u16, RemoteClient*>::iterator
|
for (UNORDERED_MAP<u16, RemoteClient*>::iterator i = clients.begin();
|
||||||
i = clients.begin();
|
|
||||||
i != clients.end(); ++i) {
|
i != clients.end(); ++i) {
|
||||||
RemoteClient *client = i->second;
|
RemoteClient *client = i->second;
|
||||||
std::string reliable_data;
|
std::string reliable_data;
|
||||||
|
@ -2734,8 +2733,7 @@ void Server::handleChatInterfaceEvent(ChatEvent *evt)
|
||||||
}
|
}
|
||||||
|
|
||||||
std::wstring Server::handleChat(const std::string &name, const std::wstring &wname,
|
std::wstring Server::handleChat(const std::string &name, const std::wstring &wname,
|
||||||
const std::wstring &wmessage, bool check_shout_priv,
|
const std::wstring &wmessage, bool check_shout_priv, RemotePlayer *player)
|
||||||
u16 peer_id_to_avoid_sending)
|
|
||||||
{
|
{
|
||||||
// If something goes wrong, this player is to blame
|
// If something goes wrong, this player is to blame
|
||||||
RollbackScopeActor rollback_scope(m_rollback,
|
RollbackScopeActor rollback_scope(m_rollback,
|
||||||
|
@ -2753,6 +2751,28 @@ std::wstring Server::handleChat(const std::string &name, const std::wstring &wna
|
||||||
if (ate)
|
if (ate)
|
||||||
return L"";
|
return L"";
|
||||||
|
|
||||||
|
if (player) {
|
||||||
|
switch (player->canSendChatMessage()) {
|
||||||
|
case RPLAYER_CHATRESULT_FLOODING: {
|
||||||
|
std::wstringstream ws;
|
||||||
|
ws << L"You cannot send more messages. You are limited to "
|
||||||
|
<< g_settings->getFloat("chat_message_limit_per_10sec")
|
||||||
|
<< " messages per 10 seconds.";
|
||||||
|
return ws.str();
|
||||||
|
}
|
||||||
|
case RPLAYER_CHATRESULT_KICK:
|
||||||
|
DenyAccess_Legacy(player->peer_id, L"You have been kicked due to message flooding.");
|
||||||
|
return L"";
|
||||||
|
case RPLAYER_CHATRESULT_OK: break;
|
||||||
|
default: FATAL_ERROR("Unhandled chat filtering result found.");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (m_max_chatmessage_length > 0 && wmessage.length() > m_max_chatmessage_length) {
|
||||||
|
return L"Your message exceed the maximum chat message limit set on the server. "
|
||||||
|
"It was refused. Send a shorter message";
|
||||||
|
}
|
||||||
|
|
||||||
// Commands are implemented in Lua, so only catch invalid
|
// Commands are implemented in Lua, so only catch invalid
|
||||||
// commands that were not "eaten" and send an error back
|
// commands that were not "eaten" and send an error back
|
||||||
if (wmessage[0] == L'/') {
|
if (wmessage[0] == L'/') {
|
||||||
|
@ -2787,6 +2807,7 @@ std::wstring Server::handleChat(const std::string &name, const std::wstring &wna
|
||||||
|
|
||||||
std::vector<u16> clients = m_clients.getClientIDs();
|
std::vector<u16> clients = m_clients.getClientIDs();
|
||||||
|
|
||||||
|
u16 peer_id_to_avoid_sending = (player ? player->peer_id : PEER_ID_INEXISTENT);
|
||||||
for (u16 i = 0; i < clients.size(); i++) {
|
for (u16 i = 0; i < clients.size(); i++) {
|
||||||
u16 cid = clients[i];
|
u16 cid = clients[i];
|
||||||
if (cid != peer_id_to_avoid_sending)
|
if (cid != peer_id_to_avoid_sending)
|
||||||
|
|
|
@ -487,7 +487,7 @@ private:
|
||||||
std::wstring handleChat(const std::string &name, const std::wstring &wname,
|
std::wstring handleChat(const std::string &name, const std::wstring &wname,
|
||||||
const std::wstring &wmessage,
|
const std::wstring &wmessage,
|
||||||
bool check_shout_priv = false,
|
bool check_shout_priv = false,
|
||||||
u16 peer_id_to_avoid_sending = PEER_ID_INEXISTENT);
|
RemotePlayer *player = NULL);
|
||||||
void handleAdminChat(const ChatEventChat *evt);
|
void handleAdminChat(const ChatEventChat *evt);
|
||||||
|
|
||||||
v3f findSpawnPos();
|
v3f findSpawnPos();
|
||||||
|
@ -522,6 +522,7 @@ private:
|
||||||
// If true, do not allow multiple players and hide some multiplayer
|
// If true, do not allow multiple players and hide some multiplayer
|
||||||
// functionality
|
// functionality
|
||||||
bool m_simple_singleplayer_mode;
|
bool m_simple_singleplayer_mode;
|
||||||
|
u16 m_max_chatmessage_length;
|
||||||
|
|
||||||
// Thread can set; step() will throw as ServerError
|
// Thread can set; step() will throw as ServerError
|
||||||
MutexedVariable<std::string> m_async_fatal_error;
|
MutexedVariable<std::string> m_async_fatal_error;
|
||||||
|
|
|
@ -196,9 +196,8 @@ void Settings::writeLines(std::ostream &os, u32 tab_depth) const
|
||||||
{
|
{
|
||||||
MutexAutoLock lock(m_mutex);
|
MutexAutoLock lock(m_mutex);
|
||||||
|
|
||||||
for (std::map<std::string, SettingsEntry>::const_iterator
|
for (SettingEntries::const_iterator it = m_settings.begin();
|
||||||
it = m_settings.begin();
|
it != m_settings.end(); ++it)
|
||||||
it != m_settings.end(); ++it)
|
|
||||||
printEntry(os, it->first, it->second, tab_depth);
|
printEntry(os, it->first, it->second, tab_depth);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -231,7 +230,7 @@ void Settings::printEntry(std::ostream &os, const std::string &name,
|
||||||
bool Settings::updateConfigObject(std::istream &is, std::ostream &os,
|
bool Settings::updateConfigObject(std::istream &is, std::ostream &os,
|
||||||
const std::string &end, u32 tab_depth)
|
const std::string &end, u32 tab_depth)
|
||||||
{
|
{
|
||||||
std::map<std::string, SettingsEntry>::const_iterator it;
|
SettingEntries::const_iterator it;
|
||||||
std::set<std::string> present_entries;
|
std::set<std::string> present_entries;
|
||||||
std::string line, name, value;
|
std::string line, name, value;
|
||||||
bool was_modified = false;
|
bool was_modified = false;
|
||||||
|
@ -381,7 +380,7 @@ const SettingsEntry &Settings::getEntry(const std::string &name) const
|
||||||
{
|
{
|
||||||
MutexAutoLock lock(m_mutex);
|
MutexAutoLock lock(m_mutex);
|
||||||
|
|
||||||
std::map<std::string, SettingsEntry>::const_iterator n;
|
SettingEntries::const_iterator n;
|
||||||
if ((n = m_settings.find(name)) == m_settings.end()) {
|
if ((n = m_settings.find(name)) == m_settings.end()) {
|
||||||
if ((n = m_defaults.find(name)) == m_defaults.end())
|
if ((n = m_defaults.find(name)) == m_defaults.end())
|
||||||
throw SettingNotFoundException("Setting [" + name + "] not found.");
|
throw SettingNotFoundException("Setting [" + name + "] not found.");
|
||||||
|
@ -572,9 +571,8 @@ bool Settings::exists(const std::string &name) const
|
||||||
std::vector<std::string> Settings::getNames() const
|
std::vector<std::string> Settings::getNames() const
|
||||||
{
|
{
|
||||||
std::vector<std::string> names;
|
std::vector<std::string> names;
|
||||||
for (std::map<std::string, SettingsEntry>::const_iterator
|
for (SettingEntries::const_iterator i = m_settings.begin();
|
||||||
i = m_settings.begin();
|
i != m_settings.end(); ++i) {
|
||||||
i != m_settings.end(); ++i) {
|
|
||||||
names.push_back(i->first);
|
names.push_back(i->first);
|
||||||
}
|
}
|
||||||
return names;
|
return names;
|
||||||
|
@ -880,7 +878,7 @@ bool Settings::remove(const std::string &name)
|
||||||
{
|
{
|
||||||
MutexAutoLock lock(m_mutex);
|
MutexAutoLock lock(m_mutex);
|
||||||
|
|
||||||
std::map<std::string, SettingsEntry>::iterator it = m_settings.find(name);
|
SettingEntries::iterator it = m_settings.find(name);
|
||||||
if (it != m_settings.end()) {
|
if (it != m_settings.end()) {
|
||||||
delete it->second.group;
|
delete it->second.group;
|
||||||
m_settings.erase(it);
|
m_settings.erase(it);
|
||||||
|
@ -912,7 +910,6 @@ void Settings::updateValue(const Settings &other, const std::string &name)
|
||||||
|
|
||||||
try {
|
try {
|
||||||
std::string val = other.get(name);
|
std::string val = other.get(name);
|
||||||
|
|
||||||
m_settings[name] = val;
|
m_settings[name] = val;
|
||||||
} catch (SettingNotFoundException &e) {
|
} catch (SettingNotFoundException &e) {
|
||||||
}
|
}
|
||||||
|
@ -968,8 +965,9 @@ void Settings::updateNoLock(const Settings &other)
|
||||||
|
|
||||||
void Settings::clearNoLock()
|
void Settings::clearNoLock()
|
||||||
{
|
{
|
||||||
std::map<std::string, SettingsEntry>::const_iterator it;
|
|
||||||
for (it = m_settings.begin(); it != m_settings.end(); ++it)
|
for (SettingEntries::const_iterator it = m_settings.begin();
|
||||||
|
it != m_settings.end(); ++it)
|
||||||
delete it->second.group;
|
delete it->second.group;
|
||||||
m_settings.clear();
|
m_settings.clear();
|
||||||
|
|
||||||
|
@ -978,8 +976,8 @@ void Settings::clearNoLock()
|
||||||
|
|
||||||
void Settings::clearDefaultsNoLock()
|
void Settings::clearDefaultsNoLock()
|
||||||
{
|
{
|
||||||
std::map<std::string, SettingsEntry>::const_iterator it;
|
for (SettingEntries::const_iterator it = m_defaults.begin();
|
||||||
for (it = m_defaults.begin(); it != m_defaults.end(); ++it)
|
it != m_defaults.end(); ++it)
|
||||||
delete it->second.group;
|
delete it->second.group;
|
||||||
m_defaults.clear();
|
m_defaults.clear();
|
||||||
}
|
}
|
||||||
|
|
|
@ -24,7 +24,7 @@ with this program; if not, write to the Free Software Foundation, Inc.,
|
||||||
#include "util/string.h"
|
#include "util/string.h"
|
||||||
#include "threading/mutex.h"
|
#include "threading/mutex.h"
|
||||||
#include <string>
|
#include <string>
|
||||||
#include <map>
|
#include "util/cpp11_container.h"
|
||||||
#include <list>
|
#include <list>
|
||||||
#include <set>
|
#include <set>
|
||||||
|
|
||||||
|
@ -45,7 +45,7 @@ typedef std::vector<
|
||||||
>
|
>
|
||||||
> SettingsCallbackList;
|
> SettingsCallbackList;
|
||||||
|
|
||||||
typedef std::map<std::string, SettingsCallbackList> SettingsCallbackMap;
|
typedef UNORDERED_MAP<std::string, SettingsCallbackList> SettingsCallbackMap;
|
||||||
|
|
||||||
enum ValueType {
|
enum ValueType {
|
||||||
VALUETYPE_STRING,
|
VALUETYPE_STRING,
|
||||||
|
@ -98,6 +98,8 @@ struct SettingsEntry {
|
||||||
bool is_group;
|
bool is_group;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
typedef UNORDERED_MAP<std::string, SettingsEntry> SettingEntries;
|
||||||
|
|
||||||
class Settings {
|
class Settings {
|
||||||
public:
|
public:
|
||||||
Settings() {}
|
Settings() {}
|
||||||
|
@ -231,8 +233,8 @@ private:
|
||||||
|
|
||||||
void doCallbacks(const std::string &name) const;
|
void doCallbacks(const std::string &name) const;
|
||||||
|
|
||||||
std::map<std::string, SettingsEntry> m_settings;
|
SettingEntries m_settings;
|
||||||
std::map<std::string, SettingsEntry> m_defaults;
|
SettingEntries m_defaults;
|
||||||
|
|
||||||
SettingsCallbackMap m_callbacks;
|
SettingsCallbackMap m_callbacks;
|
||||||
|
|
||||||
|
|
|
@ -41,9 +41,9 @@ with this program; ifnot, write to the Free Software Foundation, Inc.,
|
||||||
#include "log.h"
|
#include "log.h"
|
||||||
#include "util/numeric.h" // myrand()
|
#include "util/numeric.h" // myrand()
|
||||||
#include "porting.h"
|
#include "porting.h"
|
||||||
#include <map>
|
|
||||||
#include <vector>
|
#include <vector>
|
||||||
#include <fstream>
|
#include <fstream>
|
||||||
|
#include "util/cpp11_container.h"
|
||||||
|
|
||||||
#define BUFFER_SIZE 30000
|
#define BUFFER_SIZE 30000
|
||||||
|
|
||||||
|
@ -271,8 +271,8 @@ private:
|
||||||
ALCdevice *m_device;
|
ALCdevice *m_device;
|
||||||
ALCcontext *m_context;
|
ALCcontext *m_context;
|
||||||
int m_next_id;
|
int m_next_id;
|
||||||
std::map<std::string, std::vector<SoundBuffer*> > m_buffers;
|
UNORDERED_MAP<std::string, std::vector<SoundBuffer*> > m_buffers;
|
||||||
std::map<int, PlayingSound*> m_sounds_playing;
|
UNORDERED_MAP<int, PlayingSound*> m_sounds_playing;
|
||||||
v3f m_listener_pos;
|
v3f m_listener_pos;
|
||||||
public:
|
public:
|
||||||
bool m_is_initialized;
|
bool m_is_initialized;
|
||||||
|
@ -337,7 +337,7 @@ public:
|
||||||
alcCloseDevice(m_device);
|
alcCloseDevice(m_device);
|
||||||
m_device = NULL;
|
m_device = NULL;
|
||||||
|
|
||||||
for (std::map<std::string, std::vector<SoundBuffer*> >::iterator i = m_buffers.begin();
|
for (UNORDERED_MAP<std::string, std::vector<SoundBuffer*> >::iterator i = m_buffers.begin();
|
||||||
i != m_buffers.end(); ++i) {
|
i != m_buffers.end(); ++i) {
|
||||||
for (std::vector<SoundBuffer*>::iterator iter = (*i).second.begin();
|
for (std::vector<SoundBuffer*>::iterator iter = (*i).second.begin();
|
||||||
iter != (*i).second.end(); ++iter) {
|
iter != (*i).second.end(); ++iter) {
|
||||||
|
@ -351,7 +351,7 @@ public:
|
||||||
|
|
||||||
void addBuffer(const std::string &name, SoundBuffer *buf)
|
void addBuffer(const std::string &name, SoundBuffer *buf)
|
||||||
{
|
{
|
||||||
std::map<std::string, std::vector<SoundBuffer*> >::iterator i =
|
UNORDERED_MAP<std::string, std::vector<SoundBuffer*> >::iterator i =
|
||||||
m_buffers.find(name);
|
m_buffers.find(name);
|
||||||
if(i != m_buffers.end()){
|
if(i != m_buffers.end()){
|
||||||
i->second.push_back(buf);
|
i->second.push_back(buf);
|
||||||
|
@ -365,7 +365,7 @@ public:
|
||||||
|
|
||||||
SoundBuffer* getBuffer(const std::string &name)
|
SoundBuffer* getBuffer(const std::string &name)
|
||||||
{
|
{
|
||||||
std::map<std::string, std::vector<SoundBuffer*> >::iterator i =
|
UNORDERED_MAP<std::string, std::vector<SoundBuffer*> >::iterator i =
|
||||||
m_buffers.find(name);
|
m_buffers.find(name);
|
||||||
if(i == m_buffers.end())
|
if(i == m_buffers.end())
|
||||||
return NULL;
|
return NULL;
|
||||||
|
@ -443,8 +443,7 @@ public:
|
||||||
|
|
||||||
void deleteSound(int id)
|
void deleteSound(int id)
|
||||||
{
|
{
|
||||||
std::map<int, PlayingSound*>::iterator i =
|
UNORDERED_MAP<int, PlayingSound*>::iterator i = m_sounds_playing.find(id);
|
||||||
m_sounds_playing.find(id);
|
|
||||||
if(i == m_sounds_playing.end())
|
if(i == m_sounds_playing.end())
|
||||||
return;
|
return;
|
||||||
PlayingSound *sound = i->second;
|
PlayingSound *sound = i->second;
|
||||||
|
@ -484,10 +483,8 @@ public:
|
||||||
<<m_sounds_playing.size()<<" playing sounds, "
|
<<m_sounds_playing.size()<<" playing sounds, "
|
||||||
<<m_buffers.size()<<" sound names loaded"<<std::endl;
|
<<m_buffers.size()<<" sound names loaded"<<std::endl;
|
||||||
std::set<int> del_list;
|
std::set<int> del_list;
|
||||||
for(std::map<int, PlayingSound*>::iterator
|
for(UNORDERED_MAP<int, PlayingSound*>::iterator i = m_sounds_playing.begin();
|
||||||
i = m_sounds_playing.begin();
|
i != m_sounds_playing.end(); ++i) {
|
||||||
i != m_sounds_playing.end(); ++i)
|
|
||||||
{
|
|
||||||
int id = i->first;
|
int id = i->first;
|
||||||
PlayingSound *sound = i->second;
|
PlayingSound *sound = i->second;
|
||||||
// If not playing, remove it
|
// If not playing, remove it
|
||||||
|
@ -583,9 +580,8 @@ public:
|
||||||
}
|
}
|
||||||
void updateSoundPosition(int id, v3f pos)
|
void updateSoundPosition(int id, v3f pos)
|
||||||
{
|
{
|
||||||
std::map<int, PlayingSound*>::iterator i =
|
UNORDERED_MAP<int, PlayingSound*>::iterator i = m_sounds_playing.find(id);
|
||||||
m_sounds_playing.find(id);
|
if (i == m_sounds_playing.end())
|
||||||
if(i == m_sounds_playing.end())
|
|
||||||
return;
|
return;
|
||||||
PlayingSound *sound = i->second;
|
PlayingSound *sound = i->second;
|
||||||
|
|
||||||
|
|
23
src/tool.cpp
23
src/tool.cpp
|
@ -34,24 +34,23 @@ void ToolCapabilities::serialize(std::ostream &os, u16 protocol_version) const
|
||||||
writeF1000(os, full_punch_interval);
|
writeF1000(os, full_punch_interval);
|
||||||
writeS16(os, max_drop_level);
|
writeS16(os, max_drop_level);
|
||||||
writeU32(os, groupcaps.size());
|
writeU32(os, groupcaps.size());
|
||||||
for(std::map<std::string, ToolGroupCap>::const_iterator
|
for (ToolGCMap::const_iterator i = groupcaps.begin(); i != groupcaps.end(); ++i) {
|
||||||
i = groupcaps.begin(); i != groupcaps.end(); ++i){
|
|
||||||
const std::string *name = &i->first;
|
const std::string *name = &i->first;
|
||||||
const ToolGroupCap *cap = &i->second;
|
const ToolGroupCap *cap = &i->second;
|
||||||
os<<serializeString(*name);
|
os<<serializeString(*name);
|
||||||
writeS16(os, cap->uses);
|
writeS16(os, cap->uses);
|
||||||
writeS16(os, cap->maxlevel);
|
writeS16(os, cap->maxlevel);
|
||||||
writeU32(os, cap->times.size());
|
writeU32(os, cap->times.size());
|
||||||
for(std::map<int, float>::const_iterator
|
for (UNORDERED_MAP<int, float>::const_iterator
|
||||||
i = cap->times.begin(); i != cap->times.end(); ++i){
|
i = cap->times.begin(); i != cap->times.end(); ++i) {
|
||||||
writeS16(os, i->first);
|
writeS16(os, i->first);
|
||||||
writeF1000(os, i->second);
|
writeF1000(os, i->second);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if(protocol_version > 17){
|
if(protocol_version > 17){
|
||||||
writeU32(os, damageGroups.size());
|
writeU32(os, damageGroups.size());
|
||||||
for(std::map<std::string, s16>::const_iterator
|
for (DamageGroup::const_iterator i = damageGroups.begin();
|
||||||
i = damageGroups.begin(); i != damageGroups.end(); ++i){
|
i != damageGroups.end(); ++i) {
|
||||||
os<<serializeString(i->first);
|
os<<serializeString(i->first);
|
||||||
writeS16(os, i->second);
|
writeS16(os, i->second);
|
||||||
}
|
}
|
||||||
|
@ -106,7 +105,7 @@ DigParams getDigParams(const ItemGroupList &groups,
|
||||||
default:
|
default:
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Values to be returned (with a bit of conversion)
|
// Values to be returned (with a bit of conversion)
|
||||||
bool result_diggable = false;
|
bool result_diggable = false;
|
||||||
float result_time = 0.0;
|
float result_time = 0.0;
|
||||||
|
@ -115,8 +114,8 @@ DigParams getDigParams(const ItemGroupList &groups,
|
||||||
|
|
||||||
int level = itemgroup_get(groups, "level");
|
int level = itemgroup_get(groups, "level");
|
||||||
//infostream<<"level="<<level<<std::endl;
|
//infostream<<"level="<<level<<std::endl;
|
||||||
for(std::map<std::string, ToolGroupCap>::const_iterator
|
for (ToolGCMap::const_iterator i = tp->groupcaps.begin();
|
||||||
i = tp->groupcaps.begin(); i != tp->groupcaps.end(); ++i){
|
i != tp->groupcaps.end(); ++i) {
|
||||||
const std::string &name = i->first;
|
const std::string &name = i->first;
|
||||||
//infostream<<"group="<<name<<std::endl;
|
//infostream<<"group="<<name<<std::endl;
|
||||||
const ToolGroupCap &cap = i->second;
|
const ToolGroupCap &cap = i->second;
|
||||||
|
@ -163,8 +162,8 @@ HitParams getHitParams(const ItemGroupList &armor_groups,
|
||||||
s16 damage = 0;
|
s16 damage = 0;
|
||||||
float full_punch_interval = tp->full_punch_interval;
|
float full_punch_interval = tp->full_punch_interval;
|
||||||
|
|
||||||
for(std::map<std::string, s16>::const_iterator
|
for (DamageGroup::const_iterator i = tp->damageGroups.begin();
|
||||||
i = tp->damageGroups.begin(); i != tp->damageGroups.end(); ++i){
|
i != tp->damageGroups.end(); ++i) {
|
||||||
s16 armor = itemgroup_get(armor_groups, i->first);
|
s16 armor = itemgroup_get(armor_groups, i->first);
|
||||||
damage += i->second * rangelim(time_from_last_punch / full_punch_interval, 0.0, 1.0)
|
damage += i->second * rangelim(time_from_last_punch / full_punch_interval, 0.0, 1.0)
|
||||||
* armor / 100.0;
|
* armor / 100.0;
|
||||||
|
@ -197,7 +196,7 @@ PunchDamageResult getPunchDamage(
|
||||||
do_hit = false;
|
do_hit = false;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
PunchDamageResult result;
|
PunchDamageResult result;
|
||||||
if(do_hit)
|
if(do_hit)
|
||||||
{
|
{
|
||||||
|
|
15
src/tool.h
15
src/tool.h
|
@ -23,12 +23,12 @@ with this program; if not, write to the Free Software Foundation, Inc.,
|
||||||
#include "irrlichttypes.h"
|
#include "irrlichttypes.h"
|
||||||
#include <string>
|
#include <string>
|
||||||
#include <iostream>
|
#include <iostream>
|
||||||
#include <map>
|
#include "util/cpp11_container.h"
|
||||||
#include "itemgroup.h"
|
#include "itemgroup.h"
|
||||||
|
|
||||||
struct ToolGroupCap
|
struct ToolGroupCap
|
||||||
{
|
{
|
||||||
std::map<int, float> times;
|
UNORDERED_MAP<int, float> times;
|
||||||
int maxlevel;
|
int maxlevel;
|
||||||
int uses;
|
int uses;
|
||||||
|
|
||||||
|
@ -39,8 +39,8 @@ struct ToolGroupCap
|
||||||
|
|
||||||
bool getTime(int rating, float *time) const
|
bool getTime(int rating, float *time) const
|
||||||
{
|
{
|
||||||
std::map<int, float>::const_iterator i = times.find(rating);
|
UNORDERED_MAP<int, float>::const_iterator i = times.find(rating);
|
||||||
if(i == times.end()){
|
if (i == times.end()) {
|
||||||
*time = 0;
|
*time = 0;
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
@ -50,22 +50,19 @@ struct ToolGroupCap
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
// CLANG SUCKS DONKEY BALLS
|
typedef UNORDERED_MAP<std::string, struct ToolGroupCap> ToolGCMap;
|
||||||
typedef std::map<std::string, struct ToolGroupCap> ToolGCMap;
|
typedef UNORDERED_MAP<std::string, s16> DamageGroup;
|
||||||
typedef std::map<std::string, s16> DamageGroup;
|
|
||||||
|
|
||||||
struct ToolCapabilities
|
struct ToolCapabilities
|
||||||
{
|
{
|
||||||
float full_punch_interval;
|
float full_punch_interval;
|
||||||
int max_drop_level;
|
int max_drop_level;
|
||||||
// CLANG SUCKS DONKEY BALLS
|
|
||||||
ToolGCMap groupcaps;
|
ToolGCMap groupcaps;
|
||||||
DamageGroup damageGroups;
|
DamageGroup damageGroups;
|
||||||
|
|
||||||
ToolCapabilities(
|
ToolCapabilities(
|
||||||
float full_punch_interval_=1.4,
|
float full_punch_interval_=1.4,
|
||||||
int max_drop_level_=1,
|
int max_drop_level_=1,
|
||||||
// CLANG SUCKS DONKEY BALLS
|
|
||||||
ToolGCMap groupcaps_=ToolGCMap(),
|
ToolGCMap groupcaps_=ToolGCMap(),
|
||||||
DamageGroup damageGroups_=DamageGroup()
|
DamageGroup damageGroups_=DamageGroup()
|
||||||
):
|
):
|
||||||
|
|
|
@ -23,3 +23,7 @@ set (UNITTEST_SRCS
|
||||||
${CMAKE_CURRENT_SOURCE_DIR}/test_voxelalgorithms.cpp
|
${CMAKE_CURRENT_SOURCE_DIR}/test_voxelalgorithms.cpp
|
||||||
${CMAKE_CURRENT_SOURCE_DIR}/test_voxelmanipulator.cpp
|
${CMAKE_CURRENT_SOURCE_DIR}/test_voxelmanipulator.cpp
|
||||||
PARENT_SCOPE)
|
PARENT_SCOPE)
|
||||||
|
|
||||||
|
set (UNITTEST_CLIENT_SRCS
|
||||||
|
${CMAKE_CURRENT_SOURCE_DIR}/test_keycode.cpp
|
||||||
|
PARENT_SCOPE)
|
||||||
|
|
|
@ -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));
|
||||||
|
}
|
|
@ -32,7 +32,7 @@ public:
|
||||||
void testAllSettings();
|
void testAllSettings();
|
||||||
|
|
||||||
static const char *config_text_before;
|
static const char *config_text_before;
|
||||||
static const char *config_text_after;
|
static const std::string config_text_after;
|
||||||
};
|
};
|
||||||
|
|
||||||
static TestSettings g_test_instance;
|
static TestSettings g_test_instance;
|
||||||
|
@ -69,7 +69,7 @@ const char *TestSettings::config_text_before =
|
||||||
"np_terrain = 5, 40, (250, 250, 250), 12341, 5, 0.7, 2.4\n"
|
"np_terrain = 5, 40, (250, 250, 250), 12341, 5, 0.7, 2.4\n"
|
||||||
"zoop = true";
|
"zoop = true";
|
||||||
|
|
||||||
const char *TestSettings::config_text_after =
|
const std::string TestSettings::config_text_after =
|
||||||
"leet = 1337\n"
|
"leet = 1337\n"
|
||||||
"leetleet = 13371337\n"
|
"leetleet = 13371337\n"
|
||||||
"leetleet_neg = -13371337\n"
|
"leetleet_neg = -13371337\n"
|
||||||
|
@ -197,7 +197,10 @@ void TestSettings::testAllSettings()
|
||||||
UASSERT(s.updateConfigObject(is, os, "", 0) == true);
|
UASSERT(s.updateConfigObject(is, os, "", 0) == true);
|
||||||
//printf(">>>> expected config:\n%s\n", TEST_CONFIG_TEXT_AFTER);
|
//printf(">>>> expected config:\n%s\n", TEST_CONFIG_TEXT_AFTER);
|
||||||
//printf(">>>> actual config:\n%s\n", os.str().c_str());
|
//printf(">>>> actual config:\n%s\n", os.str().c_str());
|
||||||
|
#if __cplusplus < 201103L
|
||||||
|
// This test only works in older C++ versions than C++11 because we use unordered_map
|
||||||
UASSERT(os.str() == config_text_after);
|
UASSERT(os.str() == config_text_after);
|
||||||
|
#endif
|
||||||
} catch (SettingNotFoundException &e) {
|
} catch (SettingNotFoundException &e) {
|
||||||
UASSERT(!"Setting not found!");
|
UASSERT(!"Setting not found!");
|
||||||
}
|
}
|
||||||
|
|
|
@ -163,6 +163,7 @@ private:
|
||||||
void TestThreading::testAtomicSemaphoreThread()
|
void TestThreading::testAtomicSemaphoreThread()
|
||||||
{
|
{
|
||||||
Atomic<u32> val;
|
Atomic<u32> val;
|
||||||
|
val = 0;
|
||||||
Semaphore trigger;
|
Semaphore trigger;
|
||||||
static const u8 num_threads = 4;
|
static const u8 num_threads = 4;
|
||||||
|
|
||||||
|
|
Binary file not shown.
Before Width: | Height: | Size: 1.2 KiB After Width: | Height: | Size: 202 B |
|
@ -13,15 +13,15 @@ packagedir=$builddir/packages
|
||||||
libdir=$builddir/libs
|
libdir=$builddir/libs
|
||||||
|
|
||||||
toolchain_file=$dir/toolchain_mingw.cmake
|
toolchain_file=$dir/toolchain_mingw.cmake
|
||||||
irrlicht_version=1.8.1
|
irrlicht_version=1.8.4
|
||||||
ogg_version=1.2.1
|
ogg_version=1.3.2
|
||||||
vorbis_version=1.3.3
|
vorbis_version=1.3.5
|
||||||
curl_version=7.38.0
|
curl_version=7.50.3
|
||||||
gettext_version=0.14.4
|
gettext_version=0.14.4
|
||||||
freetype_version=2.3.5
|
freetype_version=2.7
|
||||||
sqlite3_version=3.8.7.4
|
sqlite3_version=3.14.2
|
||||||
luajit_version=2.0.1
|
luajit_version=2.0.1
|
||||||
leveldb_version=1.15
|
leveldb_version=1.18
|
||||||
zlib_version=1.2.8
|
zlib_version=1.2.8
|
||||||
|
|
||||||
mkdir -p $packagedir
|
mkdir -p $packagedir
|
||||||
|
@ -34,44 +34,38 @@ cd $builddir
|
||||||
-c -O $packagedir/irrlicht-$irrlicht_version.zip
|
-c -O $packagedir/irrlicht-$irrlicht_version.zip
|
||||||
[ -e $packagedir/zlib-$zlib_version.zip ] || wget http://minetest.kitsunemimi.pw/zlib-$zlib_version-win32.zip \
|
[ -e $packagedir/zlib-$zlib_version.zip ] || wget http://minetest.kitsunemimi.pw/zlib-$zlib_version-win32.zip \
|
||||||
-c -O $packagedir/zlib-$zlib_version.zip
|
-c -O $packagedir/zlib-$zlib_version.zip
|
||||||
[ -e $packagedir/libogg-$ogg_version-dev.7z ] || wget http://minetest.kitsunemimi.pw/libogg-$ogg_version-dev.7z \
|
[ -e $packagedir/libogg-$ogg_version.zip ] || wget http://minetest.kitsunemimi.pw/libogg-$ogg_version-win32.zip \
|
||||||
-c -O $packagedir/libogg-$ogg_version-dev.7z
|
-c -O $packagedir/libogg-$ogg_version.zip
|
||||||
[ -e $packagedir/libogg-$ogg_version-dll.7z ] || wget http://minetest.kitsunemimi.pw/libogg-$ogg_version-dll.7z \
|
[ -e $packagedir/libvorbis-$vorbis_version.zip ] || wget http://minetest.kitsunemimi.pw/libvorbis-$vorbis_version-win32.zip \
|
||||||
-c -O $packagedir/libogg-$ogg_version-dll.7z
|
-c -O $packagedir/libvorbis-$vorbis_version.zip
|
||||||
[ -e $packagedir/libvorbis-$vorbis_version-dev.7z ] || wget http://minetest.kitsunemimi.pw/libvorbis-$vorbis_version-dev.7z \
|
[ -e $packagedir/curl-$curl_version.zip ] || wget http://minetest.kitsunemimi.pw/curl-$curl_version-win32.zip \
|
||||||
-c -O $packagedir/libvorbis-$vorbis_version-dev.7z
|
-c -O $packagedir/curl-$curl_version.zip
|
||||||
[ -e $packagedir/libvorbis-$vorbis_version-dll.7z ] || wget http://minetest.kitsunemimi.pw/libvorbis-$vorbis_version-dll.7z \
|
|
||||||
-c -O $packagedir/libvorbis-$vorbis_version-dll.7z
|
|
||||||
[ -e $packagedir/libcurl-$curl_version.zip ] || wget http://minetest.kitsunemimi.pw/libcurl-$curl_version-win32.zip \
|
|
||||||
-c -O $packagedir/libcurl-$curl_version.zip
|
|
||||||
[ -e $packagedir/gettext-$gettext_version.zip ] || wget http://minetest.kitsunemimi.pw/gettext-$gettext_version.zip \
|
[ -e $packagedir/gettext-$gettext_version.zip ] || wget http://minetest.kitsunemimi.pw/gettext-$gettext_version.zip \
|
||||||
-c -O $packagedir/gettext-$gettext_version.zip
|
-c -O $packagedir/gettext-$gettext_version.zip
|
||||||
[ -e $packagedir/libfreetype-$freetype_version.zip ] || wget http://minetest.kitsunemimi.pw/libfreetype-$freetype_version-win32.zip \
|
[ -e $packagedir/freetype2-$freetype_version.zip ] || wget http://minetest.kitsunemimi.pw/freetype2-$freetype_version-win32.zip \
|
||||||
-c -O $packagedir/libfreetype-$freetype_version.zip
|
-c -O $packagedir/freetype2-$freetype_version.zip
|
||||||
[ -e $packagedir/sqlite3-$sqlite3_version.zip ] || wget http://minetest.kitsunemimi.pw/sqlite3-$sqlite3_version-win32.zip \
|
[ -e $packagedir/sqlite3-$sqlite3_version.zip ] || wget http://minetest.kitsunemimi.pw/sqlite3-$sqlite3_version-win32.zip \
|
||||||
-c -O $packagedir/sqlite3-$sqlite3_version.zip
|
-c -O $packagedir/sqlite3-$sqlite3_version.zip
|
||||||
[ -e $packagedir/luajit-$luajit_version-static-win32.zip ] || wget http://minetest.kitsunemimi.pw/luajit-$luajit_version-static-win32.zip \
|
[ -e $packagedir/luajit-$luajit_version-static-win32.zip ] || wget http://minetest.kitsunemimi.pw/luajit-$luajit_version-static-win32.zip \
|
||||||
-c -O $packagedir/luajit-$luajit_version-static-win32.zip
|
-c -O $packagedir/luajit-$luajit_version-static-win32.zip
|
||||||
[ -e $packagedir/libleveldb-$leveldb_version-win32.zip ] || wget http://minetest.kitsunemimi.pw/libleveldb-$leveldb_version-win32.zip \
|
[ -e $packagedir/libleveldb-$leveldb_version.zip ] || wget http://minetest.kitsunemimi.pw/libleveldb-$leveldb_version-win32.zip \
|
||||||
-c -O $packagedir/libleveldb-$leveldb_version-win32.zip
|
-c -O $packagedir/libleveldb-$leveldb_version.zip
|
||||||
[ -e $packagedir/openal_stripped.zip ] || wget http://minetest.kitsunemimi.pw/openal_stripped.zip \
|
[ -e $packagedir/openal_stripped.zip ] || wget http://minetest.kitsunemimi.pw/openal_stripped.zip \
|
||||||
-c -O $packagedir/openal_stripped.zip
|
-c -O $packagedir/openal_stripped.zip
|
||||||
|
|
||||||
# Extract stuff
|
# Extract stuff
|
||||||
cd $libdir
|
cd $libdir
|
||||||
[ -d irrlicht-$irrlicht_version ] || unzip -o $packagedir/irrlicht-$irrlicht_version.zip
|
[ -d irrlicht ] || unzip -o $packagedir/irrlicht-$irrlicht_version.zip -d irrlicht
|
||||||
[ -d zlib ] || unzip -o $packagedir/zlib-$zlib_version.zip -d zlib
|
[ -d zlib ] || unzip -o $packagedir/zlib-$zlib_version.zip -d zlib
|
||||||
[ -d libogg/include ] || 7z x -y -olibogg $packagedir/libogg-$ogg_version-dev.7z
|
[ -d libogg ] || unzip -o $packagedir/libogg-$ogg_version.zip -d libogg
|
||||||
[ -d libogg/bin ] || 7z x -y -olibogg $packagedir/libogg-$ogg_version-dll.7z
|
[ -d libvorbis ] || unzip -o $packagedir/libvorbis-$vorbis_version.zip -d libvorbis
|
||||||
[ -d libvorbis/include ] || 7z x -y -olibvorbis $packagedir/libvorbis-$vorbis_version-dev.7z
|
[ -d libcurl ] || unzip -o $packagedir/curl-$curl_version.zip -d libcurl
|
||||||
[ -d libvorbis/bin ] || 7z x -y -olibvorbis $packagedir/libvorbis-$vorbis_version-dll.7z
|
|
||||||
[ -d libcurl ] || unzip -o $packagedir/libcurl-$curl_version.zip -d libcurl
|
|
||||||
[ -d gettext ] || unzip -o $packagedir/gettext-$gettext_version.zip -d gettext
|
[ -d gettext ] || unzip -o $packagedir/gettext-$gettext_version.zip -d gettext
|
||||||
[ -d freetype ] || unzip -o $packagedir/libfreetype-$freetype_version.zip -d freetype
|
[ -d freetype ] || unzip -o $packagedir/freetype2-$freetype_version.zip -d freetype
|
||||||
[ -d sqlite3 ] || unzip -o $packagedir/sqlite3-$sqlite3_version.zip -d sqlite3
|
[ -d sqlite3 ] || unzip -o $packagedir/sqlite3-$sqlite3_version.zip -d sqlite3
|
||||||
[ -d openal_stripped ] || unzip -o $packagedir/openal_stripped.zip
|
[ -d openal_stripped ] || unzip -o $packagedir/openal_stripped.zip
|
||||||
[ -d luajit ] || unzip -o $packagedir/luajit-$luajit_version-static-win32.zip -d luajit
|
[ -d luajit ] || unzip -o $packagedir/luajit-$luajit_version-static-win32.zip -d luajit
|
||||||
[ -d leveldb ] || unzip -o $packagedir/libleveldb-$leveldb_version-win32.zip -d leveldb
|
[ -d leveldb ] || unzip -o $packagedir/libleveldb-$leveldb_version.zip -d leveldb
|
||||||
|
|
||||||
# Get minetest
|
# Get minetest
|
||||||
cd $builddir
|
cd $builddir
|
||||||
|
@ -107,14 +101,13 @@ cmake .. \
|
||||||
-DENABLE_FREETYPE=1 \
|
-DENABLE_FREETYPE=1 \
|
||||||
-DENABLE_LEVELDB=1 \
|
-DENABLE_LEVELDB=1 \
|
||||||
\
|
\
|
||||||
-DIRRLICHT_INCLUDE_DIR=$libdir/irrlicht-$irrlicht_version/include \
|
-DIRRLICHT_INCLUDE_DIR=$libdir/irrlicht/include \
|
||||||
-DIRRLICHT_LIBRARY=$libdir/irrlicht-$irrlicht_version/lib/Win32-gcc/libIrrlicht.dll.a \
|
-DIRRLICHT_LIBRARY=$libdir/irrlicht/lib/Win32-gcc/libIrrlicht.dll.a \
|
||||||
-DIRRLICHT_DLL=$libdir/irrlicht-$irrlicht_version/bin/Win32-gcc/Irrlicht.dll \
|
-DIRRLICHT_DLL=$libdir/irrlicht/bin/Win32-gcc/Irrlicht.dll \
|
||||||
\
|
\
|
||||||
-DZLIB_INCLUDE_DIR=$libdir/zlib/include \
|
-DZLIB_INCLUDE_DIR=$libdir/zlib/include \
|
||||||
-DZLIB_LIBRARIES=$libdir/zlib/lib/zlibwapi.dll.a \
|
-DZLIB_LIBRARIES=$libdir/zlib/lib/libz.dll.a \
|
||||||
-DZLIB_DLL=$libdir/zlib/bin/zlib1.dll \
|
-DZLIB_DLL=$libdir/zlib/bin/zlib1.dll \
|
||||||
-DZLIBWAPI_DLL=$libdir/zlib/bin/zlibwapi.dll \
|
|
||||||
\
|
\
|
||||||
-DLUA_INCLUDE_DIR=$libdir/luajit/include \
|
-DLUA_INCLUDE_DIR=$libdir/luajit/include \
|
||||||
-DLUA_LIBRARY=$libdir/luajit/libluajit.a \
|
-DLUA_LIBRARY=$libdir/luajit/libluajit.a \
|
||||||
|
@ -145,9 +138,9 @@ cmake .. \
|
||||||
-DGETTEXT_LIBRARY=$libdir/gettext/lib/libintl.dll.a \
|
-DGETTEXT_LIBRARY=$libdir/gettext/lib/libintl.dll.a \
|
||||||
\
|
\
|
||||||
-DFREETYPE_INCLUDE_DIR_freetype2=$libdir/freetype/include/freetype2 \
|
-DFREETYPE_INCLUDE_DIR_freetype2=$libdir/freetype/include/freetype2 \
|
||||||
-DFREETYPE_INCLUDE_DIR_ft2build=$libdir/freetype/include \
|
-DFREETYPE_INCLUDE_DIR_ft2build=$libdir/freetype/include/freetype2 \
|
||||||
-DFREETYPE_LIBRARY=$libdir/freetype/lib/libfreetype.dll.a \
|
-DFREETYPE_LIBRARY=$libdir/freetype/lib/libfreetype.dll.a \
|
||||||
-DFREETYPE_DLL=$libdir/freetype/bin/freetype6.dll \
|
-DFREETYPE_DLL=$libdir/freetype/bin/libfreetype-6.dll \
|
||||||
\
|
\
|
||||||
-DSQLITE3_INCLUDE_DIR=$libdir/sqlite3/include \
|
-DSQLITE3_INCLUDE_DIR=$libdir/sqlite3/include \
|
||||||
-DSQLITE3_LIBRARY=$libdir/sqlite3/lib/libsqlite3.dll.a \
|
-DSQLITE3_LIBRARY=$libdir/sqlite3/lib/libsqlite3.dll.a \
|
||||||
|
|
|
@ -13,15 +13,15 @@ packagedir=$builddir/packages
|
||||||
libdir=$builddir/libs
|
libdir=$builddir/libs
|
||||||
|
|
||||||
toolchain_file=$dir/toolchain_mingw64.cmake
|
toolchain_file=$dir/toolchain_mingw64.cmake
|
||||||
irrlicht_version=1.8.1
|
irrlicht_version=1.8.4
|
||||||
ogg_version=1.3.1
|
ogg_version=1.3.2
|
||||||
vorbis_version=1.3.4
|
vorbis_version=1.3.5
|
||||||
curl_version=7.38.0
|
curl_version=7.50.3
|
||||||
gettext_version=0.18.2
|
gettext_version=0.18.2
|
||||||
freetype_version=2.5.3
|
freetype_version=2.7
|
||||||
sqlite3_version=3.8.7.4
|
sqlite3_version=3.14.2
|
||||||
luajit_version=2.0.3
|
luajit_version=2.0.3
|
||||||
leveldb_version=1.15
|
leveldb_version=1.18
|
||||||
zlib_version=1.2.8
|
zlib_version=1.2.8
|
||||||
|
|
||||||
mkdir -p $packagedir
|
mkdir -p $packagedir
|
||||||
|
@ -38,12 +38,12 @@ cd $builddir
|
||||||
-c -O $packagedir/libogg-$ogg_version.zip
|
-c -O $packagedir/libogg-$ogg_version.zip
|
||||||
[ -e $packagedir/libvorbis-$vorbis_version.zip ] || wget http://minetest.kitsunemimi.pw/libvorbis-$vorbis_version-win64.zip \
|
[ -e $packagedir/libvorbis-$vorbis_version.zip ] || wget http://minetest.kitsunemimi.pw/libvorbis-$vorbis_version-win64.zip \
|
||||||
-c -O $packagedir/libvorbis-$vorbis_version.zip
|
-c -O $packagedir/libvorbis-$vorbis_version.zip
|
||||||
[ -e $packagedir/libcurl-$curl_version.zip ] || wget http://minetest.kitsunemimi.pw/libcurl-$curl_version-win64.zip \
|
[ -e $packagedir/curl-$curl_version.zip ] || wget http://minetest.kitsunemimi.pw/curl-$curl_version-win64.zip \
|
||||||
-c -O $packagedir/libcurl-$curl_version.zip
|
-c -O $packagedir/curl-$curl_version.zip
|
||||||
[ -e $packagedir/gettext-$gettext_version.zip ] || wget http://minetest.kitsunemimi.pw/gettext-$gettext_version-win64.zip \
|
[ -e $packagedir/gettext-$gettext_version.zip ] || wget http://minetest.kitsunemimi.pw/gettext-$gettext_version-win64.zip \
|
||||||
-c -O $packagedir/gettext-$gettext_version.zip
|
-c -O $packagedir/gettext-$gettext_version.zip
|
||||||
[ -e $packagedir/freetype-$freetype_version.zip ] || wget http://minetest.kitsunemimi.pw/libfreetype-$freetype_version-win64.zip \
|
[ -e $packagedir/freetype2-$freetype_version.zip ] || wget http://minetest.kitsunemimi.pw/freetype2-$freetype_version-win64.zip \
|
||||||
-c -O $packagedir/freetype-$freetype_version.zip
|
-c -O $packagedir/freetype2-$freetype_version.zip
|
||||||
[ -e $packagedir/sqlite3-$sqlite3_version.zip ] || wget http://minetest.kitsunemimi.pw/sqlite3-$sqlite3_version-win64.zip \
|
[ -e $packagedir/sqlite3-$sqlite3_version.zip ] || wget http://minetest.kitsunemimi.pw/sqlite3-$sqlite3_version-win64.zip \
|
||||||
-c -O $packagedir/sqlite3-$sqlite3_version.zip
|
-c -O $packagedir/sqlite3-$sqlite3_version.zip
|
||||||
[ -e $packagedir/luajit-$luajit_version.zip ] || wget http://minetest.kitsunemimi.pw/luajit-$luajit_version-static-win64.zip \
|
[ -e $packagedir/luajit-$luajit_version.zip ] || wget http://minetest.kitsunemimi.pw/luajit-$luajit_version-static-win64.zip \
|
||||||
|
@ -56,13 +56,13 @@ cd $builddir
|
||||||
|
|
||||||
# Extract stuff
|
# Extract stuff
|
||||||
cd $libdir
|
cd $libdir
|
||||||
[ -d irrlicht-$irrlicht_version ] || unzip -o $packagedir/irrlicht-$irrlicht_version.zip
|
[ -d irrlicht ] || unzip -o $packagedir/irrlicht-$irrlicht_version.zip -d irrlicht
|
||||||
[ -d zlib ] || unzip -o $packagedir/zlib-$zlib_version.zip -d zlib
|
[ -d zlib ] || unzip -o $packagedir/zlib-$zlib_version.zip -d zlib
|
||||||
[ -d libogg ] || unzip -o $packagedir/libogg-$ogg_version.zip -d libogg
|
[ -d libogg ] || unzip -o $packagedir/libogg-$ogg_version.zip -d libogg
|
||||||
[ -d libvorbis ] || unzip -o $packagedir/libvorbis-$vorbis_version.zip -d libvorbis
|
[ -d libvorbis ] || unzip -o $packagedir/libvorbis-$vorbis_version.zip -d libvorbis
|
||||||
[ -d libcurl ] || unzip -o $packagedir/libcurl-$curl_version.zip -d libcurl
|
[ -d libcurl ] || unzip -o $packagedir/curl-$curl_version.zip -d libcurl
|
||||||
[ -d gettext ] || unzip -o $packagedir/gettext-$gettext_version.zip -d gettext
|
[ -d gettext ] || unzip -o $packagedir/gettext-$gettext_version.zip -d gettext
|
||||||
[ -d freetype ] || unzip -o $packagedir/freetype-$freetype_version.zip -d freetype
|
[ -d freetype ] || unzip -o $packagedir/freetype2-$freetype_version.zip -d freetype
|
||||||
[ -d sqlite3 ] || unzip -o $packagedir/sqlite3-$sqlite3_version.zip -d sqlite3
|
[ -d sqlite3 ] || unzip -o $packagedir/sqlite3-$sqlite3_version.zip -d sqlite3
|
||||||
[ -d openal_stripped ] || unzip -o $packagedir/openal_stripped.zip
|
[ -d openal_stripped ] || unzip -o $packagedir/openal_stripped.zip
|
||||||
[ -d luajit ] || unzip -o $packagedir/luajit-$luajit_version.zip -d luajit
|
[ -d luajit ] || unzip -o $packagedir/luajit-$luajit_version.zip -d luajit
|
||||||
|
@ -102,9 +102,9 @@ cmake .. \
|
||||||
-DENABLE_FREETYPE=1 \
|
-DENABLE_FREETYPE=1 \
|
||||||
-DENABLE_LEVELDB=1 \
|
-DENABLE_LEVELDB=1 \
|
||||||
\
|
\
|
||||||
-DIRRLICHT_INCLUDE_DIR=$libdir/irrlicht-$irrlicht_version/include \
|
-DIRRLICHT_INCLUDE_DIR=$libdir/irrlicht/include \
|
||||||
-DIRRLICHT_LIBRARY=$libdir/irrlicht-$irrlicht_version/lib/Win64-gcc/libIrrlicht.dll.a \
|
-DIRRLICHT_LIBRARY=$libdir/irrlicht/lib/Win64-gcc/libIrrlicht.dll.a \
|
||||||
-DIRRLICHT_DLL=$libdir/irrlicht-$irrlicht_version/bin/Win64-gcc/Irrlicht.dll \
|
-DIRRLICHT_DLL=$libdir/irrlicht/bin/Win64-gcc/Irrlicht.dll \
|
||||||
\
|
\
|
||||||
-DZLIB_INCLUDE_DIR=$libdir/zlib/include \
|
-DZLIB_INCLUDE_DIR=$libdir/zlib/include \
|
||||||
-DZLIB_LIBRARIES=$libdir/zlib/lib/libz.dll.a \
|
-DZLIB_LIBRARIES=$libdir/zlib/lib/libz.dll.a \
|
||||||
|
@ -131,6 +131,13 @@ cmake .. \
|
||||||
-DCURL_INCLUDE_DIR=$libdir/libcurl/include \
|
-DCURL_INCLUDE_DIR=$libdir/libcurl/include \
|
||||||
-DCURL_LIBRARY=$libdir/libcurl/lib/libcurl.dll.a \
|
-DCURL_LIBRARY=$libdir/libcurl/lib/libcurl.dll.a \
|
||||||
\
|
\
|
||||||
|
-DCUSTOM_GETTEXT_PATH=$libdir/gettext \
|
||||||
|
-DGETTEXT_MSGFMT=`which msgfmt` \
|
||||||
|
-DGETTEXT_DLL=$libdir/gettext/bin/libintl-8.dll \
|
||||||
|
-DGETTEXT_ICONV_DLL=$libdir/gettext/bin/libiconv-2.dll \
|
||||||
|
-DGETTEXT_INCLUDE_DIR=$libdir/gettext/include \
|
||||||
|
-DGETTEXT_LIBRARY=$libdir/gettext/lib/libintl.dll.a \
|
||||||
|
\
|
||||||
-DFREETYPE_INCLUDE_DIR_freetype2=$libdir/freetype/include/freetype2 \
|
-DFREETYPE_INCLUDE_DIR_freetype2=$libdir/freetype/include/freetype2 \
|
||||||
-DFREETYPE_INCLUDE_DIR_ft2build=$libdir/freetype/include/freetype2 \
|
-DFREETYPE_INCLUDE_DIR_ft2build=$libdir/freetype/include/freetype2 \
|
||||||
-DFREETYPE_LIBRARY=$libdir/freetype/lib/libfreetype.dll.a \
|
-DFREETYPE_LIBRARY=$libdir/freetype/lib/libfreetype.dll.a \
|
||||||
|
@ -142,14 +149,7 @@ cmake .. \
|
||||||
\
|
\
|
||||||
-DLEVELDB_INCLUDE_DIR=$libdir/leveldb/include \
|
-DLEVELDB_INCLUDE_DIR=$libdir/leveldb/include \
|
||||||
-DLEVELDB_LIBRARY=$libdir/leveldb/lib/libleveldb.dll.a \
|
-DLEVELDB_LIBRARY=$libdir/leveldb/lib/libleveldb.dll.a \
|
||||||
-DLEVELDB_DLL=$libdir/leveldb/bin/libleveldb.dll \
|
-DLEVELDB_DLL=$libdir/leveldb/bin/libleveldb.dll
|
||||||
\
|
|
||||||
-DCUSTOM_GETTEXT_PATH=$libdir/gettext \
|
|
||||||
-DGETTEXT_MSGFMT=`which msgfmt` \
|
|
||||||
-DGETTEXT_DLL=$libdir/gettext/bin/libintl-8.dll \
|
|
||||||
-DGETTEXT_ICONV_DLL=$libdir/gettext/bin/libiconv-2.dll \
|
|
||||||
-DGETTEXT_INCLUDE_DIR=$libdir/gettext/include \
|
|
||||||
-DGETTEXT_LIBRARY=$libdir/gettext/lib/libintl.dll.a
|
|
||||||
|
|
||||||
make package -j2
|
make package -j2
|
||||||
|
|
||||||
|
|
|
@ -1,16 +1,8 @@
|
||||||
#!/bin/bash -e
|
#!/bin/bash -e
|
||||||
|
|
||||||
if [[ $TRAVIS_OS_NAME == "linux" ]]; then
|
if [[ $TRAVIS_OS_NAME == "linux" ]]; then
|
||||||
if [[ $CC == "clang" ]]; then
|
|
||||||
export PATH="/usr/bin/:$PATH"
|
|
||||||
sudo sh -c 'echo "deb http://ppa.launchpad.net/eudoxos/llvm-3.1/ubuntu precise main" >> /etc/apt/sources.list'
|
|
||||||
sudo apt-key adv --keyserver pool.sks-keyservers.net --recv-keys 92DE8183
|
|
||||||
sudo apt-get update
|
|
||||||
sudo apt-get install llvm-3.1
|
|
||||||
sudo apt-get install clang
|
|
||||||
fi
|
|
||||||
sudo apt-get update
|
sudo apt-get update
|
||||||
sudo apt-get install p7zip-full
|
sudo apt-get install p7zip-full $COMPILER
|
||||||
fi
|
fi
|
||||||
|
|
||||||
if [[ $PLATFORM == "Unix" ]]; then
|
if [[ $PLATFORM == "Unix" ]]; then
|
||||||
|
@ -25,7 +17,7 @@ if [[ $PLATFORM == "Unix" ]]; then
|
||||||
else
|
else
|
||||||
brew update
|
brew update
|
||||||
brew install freetype gettext hiredis irrlicht jpeg leveldb libogg libvorbis luajit
|
brew install freetype gettext hiredis irrlicht jpeg leveldb libogg libvorbis luajit
|
||||||
brew upgrade postgresql
|
#brew upgrade postgresql
|
||||||
fi
|
fi
|
||||||
elif [[ $PLATFORM == "Win32" ]]; then
|
elif [[ $PLATFORM == "Win32" ]]; then
|
||||||
wget http://minetest.kitsunemimi.pw/mingw_w64_i686_ubuntu12.04_4.9.1.7z -O mingw.7z
|
wget http://minetest.kitsunemimi.pw/mingw_w64_i686_ubuntu12.04_4.9.1.7z -O mingw.7z
|
||||||
|
|
|
@ -4,6 +4,10 @@ if [[ $PLATFORM == "Unix" ]]; then
|
||||||
mkdir -p travisbuild
|
mkdir -p travisbuild
|
||||||
cd travisbuild || exit 1
|
cd travisbuild || exit 1
|
||||||
CMAKE_FLAGS=''
|
CMAKE_FLAGS=''
|
||||||
|
if [[ $COMPILER == "g++-6" ]]; then
|
||||||
|
export CC=gcc-6
|
||||||
|
export CXX=g++-6
|
||||||
|
fi
|
||||||
# Clang builds with FreeType fail on Travis
|
# Clang builds with FreeType fail on Travis
|
||||||
if [[ $CC == "clang" ]]; then
|
if [[ $CC == "clang" ]]; then
|
||||||
CMAKE_FLAGS+=' -DENABLE_FREETYPE=FALSE'
|
CMAKE_FLAGS+=' -DENABLE_FREETYPE=FALSE'
|
||||||
|
|
Loading…
Reference in New Issue