Merge remote-tracking branch 'upstream/master'

This commit is contained in:
Stefan 2013-02-02 17:54:58 +01:00
commit 35b9d68700
74 changed files with 12526 additions and 3615 deletions

10
.travis.yml Normal file
View File

@ -0,0 +1,10 @@
language: cpp
compiler:
- gcc
- clang
before_install:
- 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 keyserver.ubuntu.com --recv-keys 92DE8183; sudo apt-get update; sudo apt-get install llvm-3.1; sudo apt-get install clang; fi
- sudo apt-get install libirrlicht-dev cmake libbz2-dev libpng12-dev libjpeg8-dev libxxf86vm-dev libgl1-mesa-dev libsqlite3-dev libogg-dev libvorbis-dev libopenal-dev
script: cmake . && make
notifications:
email: false

View File

@ -12,7 +12,7 @@ set(VERSION_EXTRA "" CACHE STRING "Stuff to append to version string")
# Also remember to set PROTOCOL_VERSION in clientserver.h when releasing
set(VERSION_MAJOR 0)
set(VERSION_MINOR 4)
set(VERSION_PATCH 4)
set(VERSION_PATCH 4-d1)
if(VERSION_EXTRA)
set(VERSION_PATCH ${VERSION_PATCH}-${VERSION_EXTRA})
endif()

View File

@ -96,9 +96,9 @@ function drop_attached_node(p)
minetest.env:remove_node(p)
for _,item in ipairs(minetest.get_node_drops(nn, "")) do
local pos = {
x = p.x + math.random(60)/60-0.3,
y = p.y + math.random(60)/60-0.3,
z = p.z + math.random(60)/60-0.3,
x = p.x + math.random()/2 - 0.25,
y = p.y + math.random()/2 - 0.25,
z = p.z + math.random()/2 - 0.25,
}
minetest.env:add_item(pos, item)
end

View File

@ -231,9 +231,20 @@ function minetest.item_place_object(itemstack, placer, pointed_thing)
end
function minetest.item_place(itemstack, placer, pointed_thing)
-- Call on_rightclick if the pointed node defines it
if pointed_thing.type == "node" and placer and
not placer:get_player_control().sneak then
local n = minetest.env:get_node(pointed_thing.under)
local nn = n.name
if minetest.registered_nodes[nn] and minetest.registered_nodes[nn].on_rightclick then
minetest.registered_nodes[nn].on_rightclick(pointed_thing.under, n, placer)
return
end
end
if itemstack:get_definition().type == "node" then
return minetest.item_place_node(itemstack, placer, pointed_thing)
else
elseif itemstack:get_definition().type ~= "none" then
return minetest.item_place_object(itemstack, placer, pointed_thing)
end
end
@ -375,6 +386,7 @@ minetest.nodedef_default = {
can_dig = nil,
on_punch = redef_wrapper(minetest, 'node_punch'), -- minetest.node_punch
on_rightclick = nil,
on_dig = redef_wrapper(minetest, 'node_dig'), -- minetest.node_dig
on_receive_fields = nil,
@ -464,7 +476,7 @@ minetest.noneitemdef_default = { -- This is used for the hand and unknown items
tool_capabilities = nil,
-- Interaction callbacks
on_place = nil,
on_place = redef_wrapper(minetest, 'item_place'),
on_drop = nil,
on_use = nil,
}

2
client/serverlist/.gitignore vendored Normal file
View File

@ -0,0 +1,2 @@
*
!.gitignore

View File

@ -725,6 +725,9 @@ field[<name>;<label>;<default>]
^ must be used without a size[] element
^ a 'Proceed' button will be added automatically
textarea[<X>,<Y>;<W>,<H>;<name>;<label>;<default>]
^ same as fields above, but with multi-line input
label[<X>,<Y>;<label>]
^ x and y work as per field
^ label is the text on the label
@ -857,6 +860,7 @@ minetest.setting_set(name, value)
minetest.setting_get(name) -> string or nil
minetest.setting_getbool(name) -> boolean value or nil
minetest.setting_get_pos(name) -> position or nil
minetest.setting_save() -> nil, save all settings to config file
minetest.add_to_creative_inventory(itemstring)
Authentication:
@ -888,6 +892,11 @@ minetest.get_inventory(location) -> InvRef
minetest.create_detached_inventory(name, callbacks) -> InvRef
^ callbacks: See "Detached inventory callbacks"
^ Creates a detached inventory. If it already exists, it is cleared.
minetest.show_formspec(playername, formname, formspec)
^ playername: name of player to show formspec
^ formname: name passed to on_player_receive_fields callbacks
^ should follow "modname:<whatever>" naming convention
^ formspec: formspec to display
Item handling:
minetest.inventorycube(img1, img2, img3)
@ -939,6 +948,8 @@ minetest.item_place_object(itemstack, placer, pointed_thing)
^ Place item as-is
minetest.item_place(itemstack, placer, pointed_thing)
^ Use one of the above based on what the item is.
^ Calls on_rightclick of pointed_thing.under if defined instead
^ Note: is not called when wielded item overrides on_place
minetest.item_drop(itemstack, dropper, pos)
^ Drop the item
minetest.item_eat(hp_change, replace_with_item)
@ -1065,7 +1076,7 @@ methods:
^ clear all objects in the environments
- spawn_tree (pos, {treedef})
^ spawns L-System tree at given pos with definition in treedef table
treedef={
treedef={
axiom, - string initial tree axiom
rules_a, - string rules set A
rules_b, - string rules set B
@ -1073,17 +1084,23 @@ methods:
rules_d, - string rules set D
trunk, - string trunk node name
leaves, - string leaves node name
leaves2, - string secondary leaves node name
leaves2_chance,- num chance (0-100) to replace leaves with leaves2
angle, - num angle in deg
iterations, - num max # of iterations, usually 2 -5
random_level, - num factor to lower nr of iterations, usually 0 - 3
thin_trunks, - boolean true -> use thin trunks
fruit_tree, - boolean true -> is a fruit tree
fruit - string fruit node name
trunk_type, - string single/double/crossed) type of trunk: 1 node, 2x2 nodes or 3x3 in cross shape
thin_branches, - boolean true -> use thin (1 node) branches
fruit, - string fruit node name
fruit_chance, - num chance (0-100) to replace leaves with fruit node
}
Key for Special L-System Symbols used in Axioms
G - move forward one unit with the pin down
F - move forward one unit with the pin up
Key for Special L-System Symbols used in Axioms
G - move forward one unit with the pen up
F - move forward one unit with the pen down drawing trunks and branches
f - move forward one unit with the pen down drawing leaves (100% chance)
T - move forward one unit with the pen down drawing trunks only
R - move forward one unit with the pen down placing fruit
A - replace with rules set A
B - replace with rules set B
C - replace with rules set C
@ -1101,8 +1118,8 @@ methods:
[ - save in stack current state info
] - recover from stack state info
Example usage: spawn small apple tree
apple_tree={
Example usage: spawn small apple tree
apple_tree={
axiom="FFFFFAFFBF",
rules_a="[&&&FFFFF&&FFFF][&&&++++FFFFF&&FFFF][&&&----FFFFF&&FFFF]",
rules_b="[&&&++FFFFF&&FFFF][&&&--FFFFF&&FFFF][&&&------FFFFF&&FFFF]",
@ -1111,11 +1128,12 @@ methods:
angle=30,
iterations=2,
random_level=0,
thin_trunks=true,
fruit_tree=true,
trunk_type="single",
thin_branches=true,
fruit_chance=10,
fruit="default:apple"
}
minetest.env:spawn_tree(pos,apple_tree)
minetest.env:spawn_tree(pos,apple_tree)
Deprecated:
- add_rat(pos): Add C++ rat object (no-op)
@ -1228,6 +1246,8 @@ methods:
can be fully taken from the list
remove_item(listname, stack): take as many items as specified from the list,
returns the items that were actually removed (as an ItemStack)
- get_location() -> location compatible to minetest.get_inventory(location)
-> {type="undefined"} in case location is not known
ItemStack: A stack of items.
- Can be created via ItemStack(itemstack or itemstring or table or nil)
@ -1477,6 +1497,8 @@ Node definition (register_node)
on_punch = func(pos, node, puncher),
^ default: minetest.node_punch
^ By default: does nothing
on_rightclick = func(pos, node, clicker),
^ default: nil
on_dig = func(pos, node, digger),
^ default: minetest.node_dig
^ By default: checks privileges, wears out tool and removes node

View File

@ -1586,6 +1586,99 @@ minetest.register_alias("mapgen_stone_with_coal", "default:stone_with_coal")
minetest.register_alias("mapgen_stone_with_iron", "default:stone_with_iron")
minetest.register_alias("mapgen_mese", "default:mese")
minetest.register_biome_groups({
0.35, 0.10, 0.30
})
--
-- Register the biomes for the map generator
--
minetest.register_biome({
group_id = 0,
name = "Ocean",
terrain_type = "liquid",
node_top = "default:gravel",
node_filler = "default:stone",
num_top_nodes = 4,
height_min = -3000,
height_max = 3000,
heat_min = -20.0,
heat_max = 100.0,
humidity_min = 0.0,
humidity_max = 100.0,
scale = 10.0,
offset = -10.0,
})
minetest.register_biome({
group_id = 1,
name = "Beach",
terrain_type = "normal",
node_top = "default:sand",
node_filler = "default:stone",
num_top_nodes = 5,
height_min = -3000,
height_max = 3000,
heat_min = 5.0,
heat_max = 100.0,
humidity_min = 0.0,
humidity_max = 100.0,
scale = 5.0,
offset = 5.0,
})
minetest.register_biome({
group_id = 1,
name = "Gravel Beach",
terrain_type = "normal",
node_top = "default:gravel",
node_filler = "default:cobble",
num_top_nodes = 5,
height_min = -3000,
height_max = 3000,
heat_min = -50.0,
heat_max = 5.0,
humidity_min = 0.0,
humidity_max = 100.0,
scale = 5.0,
offset = 5.0,
})
minetest.register_biome({
group_id = 2,
name = "Land",
terrain_type = "normal",
node_top = "default:dirt_with_grass",
node_filler = "default:stone",
num_top_nodes = 5,
height_min = -3000,
height_max = 3000,
heat_min = -50.0,
heat_max = 100.0,
humidity_min = 0.0,
humidity_max = 100.0,
scale = 12.0,
offset = 20.0,
})
minetest.register_biome({
group_id = 3,
name = "Hills",
terrain_type = "normal",
node_top = "default:dirt",
node_filler = "default:stone",
num_top_nodes = 3,
height_min = -3000,
height_max = 3000,
heat_min = -50.0,
heat_max = 100.0,
humidity_min = 0.0,
humidity_max = 100.0,
scale = 60.0,
offset = 20.0,
})
-- Support old code
function default.spawn_falling_node(p, nodename)
spawn_falling_node(p, nodename)

View File

@ -51,6 +51,10 @@
#keymap_screenshot = KEY_F12
# If true, keymap_special1 instead of keymap_sneak is used for climbing down and descending
#aux1_descends = false
# Doubletaping the jump key toogles fly mode
#doubletap_jump = false
# If false aux1 is used to fly fast
#always_fly_fast = true
# Some (temporary) keys for debugging
#keymap_print_debug_stacks = KEY_KEY_P
#keymap_quicktune_prev = KEY_HOME
@ -146,11 +150,19 @@
# (1: low level shaders; not implemented)
# 2: enable high level shaders
#enable_shaders = 2
# The time in seconds it takes between repeated
# right clicks when holding the right mouse button
#repeat_rightclick_time = 0.25
# will only work for servers which use remote_media setting
# and only for clients compiled with cURL
#media_fetch_threads = 8
# Url to the server list displayed in the Multiplayer Tab
#serverlist_url = servers.minetest.ru/server.list
# File in client/serverlist/ that contains your favorite servers displayed in the Multiplayer Tab
#serverlist_file = favoriteservers.txt
#
# Server stuff
#
@ -228,3 +240,25 @@
#congestion_control_max_rate = 400
#congestion_control_min_rate = 10
#remote_media =
# Mapgen stuff
#mg_name = v6
#water_level = 1
#chunksize = 5
#mg_flags = 19
#mgv6_freq_desert = 0.45
#mgv6_freq_beach = 0.15
#mgv6_np_terrain_base = -4, 20, (250.0, 250, 250), 82341, 5, 0.6
#mgv6_np_terrain_higher = 20, 16, (500, 500, 500), 85039, 5, 0.6
#mgv6_np_steepness = 0.85, 0.5, (125, 125, 125), -932, 5, 0.7
#mgv6_np_height_select = 0.5, 1, (250, 250, 250), 4213, 5, 0.69
#mgv6_np_trees = 0, 1, (125, 125, 125), 2, 4, 0.66
#mgv6_np_mud = 4, 2, (200, 200, 200), 91013, 3, 0.55
#mgv6_np_beach = 0, 1, (250, 250, 250), 59420, 3, 0.50
#mgv6_np_biome = 0, 1, (250, 250, 250), 9130, 3, 0.50
#mgv6_np_cave = 6, 6, (250, 250, 250), 34329, 3, 0.50
#mgv7_np_terrain = 10, 12, (350, 350, 350), 82341, 5, 0.6
#mgv7_np_bgroup = 0.5, 0.3125, (350, 350, 350), 5923, 2, 0.6
#mgv7_np_heat = 25, 50, (500, 500, 500), 35293, 1, 0
#mgv7_np_humidity = 50, 31.25, (750, 750, 750), 12094, 2, 0.6

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

669
po/es/minetest.po Normal file
View File

@ -0,0 +1,669 @@
# SOME DESCRIPTIVE TITLE.
# Copyright (C) YEAR THE PACKAGE'S COPYRIGHT HOLDER
# This file is distributed under the same license as the PACKAGE package.
# FIRST AUTHOR <EMAIL@ADDRESS>, YEAR.
#
#, fuzzy
msgid ""
msgstr ""
"Project-Id-Version: minetest\n"
"Report-Msgid-Bugs-To: \n"
"POT-Creation-Date: 2013-01-23 18:24+0200\n"
"PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n"
"Last-Translator: FULL NAME <EMAIL@ADDRESS>\n"
"Language-Team: LANGUAGE <LL@li.org>\n"
"Language: \n"
"MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=CHARSET\n"
"Content-Transfer-Encoding: 8bit\n"
#: src/guiConfigureWorld.cpp:127
msgid ""
"Warning: Some mods are not configured yet.\n"
"They will be enabled by default when you save the configuration. "
msgstr ""
#: src/guiConfigureWorld.cpp:146
msgid ""
"Warning: Some configured mods are missing.\n"
"Their setting will be removed when you save the configuration. "
msgstr ""
#: src/guiConfigureWorld.cpp:210
msgid "enabled"
msgstr ""
#: src/guiConfigureWorld.cpp:217
msgid "Enable All"
msgstr ""
#: src/guiConfigureWorld.cpp:224
msgid "Disable All"
msgstr ""
#: src/guiConfigureWorld.cpp:230
msgid "depends on:"
msgstr ""
#: src/guiConfigureWorld.cpp:242
msgid "is required by:"
msgstr ""
#: src/guiConfigureWorld.cpp:262 src/guiCreateWorld.cpp:165
#: src/guiKeyChangeMenu.cpp:179 src/keycode.cpp:223
msgid "Cancel"
msgstr ""
#: src/guiConfigureWorld.cpp:268 src/guiKeyChangeMenu.cpp:173
msgid "Save"
msgstr ""
#: src/guiConfigureWorld.cpp:394
msgid "Configuration saved. "
msgstr ""
#: src/guiConfigureWorld.cpp:402
msgid "Warning: Configuration not consistent. "
msgstr ""
#: src/guiConfirmMenu.cpp:120
msgid "Yes"
msgstr ""
#: src/guiConfirmMenu.cpp:126
msgid "No"
msgstr ""
#: src/guiCreateWorld.cpp:116
msgid "World name"
msgstr ""
#: src/guiCreateWorld.cpp:135
msgid "Game"
msgstr ""
#: src/guiCreateWorld.cpp:159
msgid "Create"
msgstr ""
#: src/guiDeathScreen.cpp:96
msgid "You died."
msgstr ""
#: src/guiDeathScreen.cpp:104
msgid "Respawn"
msgstr ""
#: src/guiFormSpecMenu.cpp:572
msgid "Left click: Move all items, Right click: Move single item"
msgstr ""
#: src/guiFormSpecMenu.cpp:597 src/guiMessageMenu.cpp:109
#: src/guiTextInputMenu.cpp:123
msgid "Proceed"
msgstr ""
#: src/guiKeyChangeMenu.cpp:114
msgid "Keybindings. (If this menu screws up, remove stuff from minetest.conf)"
msgstr ""
#: src/guiKeyChangeMenu.cpp:151
msgid "\"Use\" = climb down"
msgstr ""
#: src/guiKeyChangeMenu.cpp:164
msgid "Double tap \"jump\" to toggle fly"
msgstr ""
#: src/guiKeyChangeMenu.cpp:269
msgid "Key already in use"
msgstr ""
#: src/guiKeyChangeMenu.cpp:347
msgid "press key"
msgstr ""
#: src/guiMainMenu.cpp:55
msgid "Cannot create world: Name contains invalid characters"
msgstr ""
#: src/guiMainMenu.cpp:64
msgid "Cannot create world: A world by this name already exists"
msgstr ""
#: src/guiMainMenu.cpp:245
msgid "Singleplayer"
msgstr ""
#: src/guiMainMenu.cpp:246
msgid "Multiplayer"
msgstr ""
#: src/guiMainMenu.cpp:247
msgid "Advanced"
msgstr ""
#: src/guiMainMenu.cpp:248
msgid "Settings"
msgstr ""
#: src/guiMainMenu.cpp:249
msgid "Credits"
msgstr ""
#: src/guiMainMenu.cpp:280
msgid "Select World:"
msgstr ""
#: src/guiMainMenu.cpp:302 src/guiMainMenu.cpp:449 src/keycode.cpp:229
msgid "Delete"
msgstr ""
#: src/guiMainMenu.cpp:309
msgid "New"
msgstr ""
#: src/guiMainMenu.cpp:317
msgid "Configure"
msgstr ""
#: src/guiMainMenu.cpp:332 src/keycode.cpp:248
msgid "Play"
msgstr ""
#: src/guiMainMenu.cpp:343 src/guiMainMenu.cpp:557
msgid "Creative Mode"
msgstr ""
#: src/guiMainMenu.cpp:349 src/guiMainMenu.cpp:563
msgid "Enable Damage"
msgstr ""
#: src/guiMainMenu.cpp:369 src/guiMainMenu.cpp:479
msgid "Name/Password"
msgstr ""
#: src/guiMainMenu.cpp:408 src/guiMainMenu.cpp:506
msgid "Address/Port"
msgstr ""
#: src/guiMainMenu.cpp:435 src/guiMainMenu.cpp:1075
msgid "Show Public"
msgstr ""
#: src/guiMainMenu.cpp:439 src/guiMainMenu.cpp:1083
msgid "Show Favorites"
msgstr ""
#: src/guiMainMenu.cpp:459
msgid "Connect"
msgstr ""
#: src/guiMainMenu.cpp:529
msgid "Leave address blank to start a local server."
msgstr ""
#: src/guiMainMenu.cpp:538
msgid "Start Game / Connect"
msgstr ""
#: src/guiMainMenu.cpp:570 src/guiMainMenu.cpp:1006
msgid "Delete world"
msgstr ""
#: src/guiMainMenu.cpp:577
msgid "Create world"
msgstr ""
#: src/guiMainMenu.cpp:611
msgid "Fancy trees"
msgstr ""
#: src/guiMainMenu.cpp:617
msgid "Smooth Lighting"
msgstr ""
#: src/guiMainMenu.cpp:623
msgid "3D Clouds"
msgstr ""
#: src/guiMainMenu.cpp:629
msgid "Opaque water"
msgstr ""
#: src/guiMainMenu.cpp:639
msgid "Mip-Mapping"
msgstr ""
#: src/guiMainMenu.cpp:646
msgid "Anisotropic Filtering"
msgstr ""
#: src/guiMainMenu.cpp:653
msgid "Bi-Linear Filtering"
msgstr ""
#: src/guiMainMenu.cpp:660
msgid "Tri-Linear Filtering"
msgstr ""
#: src/guiMainMenu.cpp:668
msgid "Shaders"
msgstr ""
#: src/guiMainMenu.cpp:675
msgid "Preload item visuals"
msgstr ""
#: src/guiMainMenu.cpp:682
msgid "Enable Particles"
msgstr ""
#: src/guiMainMenu.cpp:692
msgid "Change keys"
msgstr ""
#: src/guiMainMenu.cpp:977
msgid "Address required."
msgstr ""
#: src/guiMainMenu.cpp:995
msgid "Cannot delete world: Nothing selected"
msgstr ""
#: src/guiMainMenu.cpp:1010
msgid "Files to be deleted"
msgstr ""
#: src/guiMainMenu.cpp:1026
msgid "Cannot create world: No games found"
msgstr ""
#: src/guiMainMenu.cpp:1042
msgid "Cannot configure world: Nothing selected"
msgstr ""
#: src/guiMainMenu.cpp:1146
msgid "Failed to delete all world files"
msgstr ""
#: src/guiPasswordChange.cpp:108
msgid "Old Password"
msgstr ""
#: src/guiPasswordChange.cpp:125
msgid "New Password"
msgstr ""
#: src/guiPasswordChange.cpp:141
msgid "Confirm Password"
msgstr ""
#: src/guiPasswordChange.cpp:158
msgid "Change"
msgstr ""
#: src/guiPasswordChange.cpp:167
msgid "Passwords do not match!"
msgstr ""
#: src/guiPauseMenu.cpp:118
msgid "Continue"
msgstr ""
#: src/guiPauseMenu.cpp:127
msgid "Change Password"
msgstr ""
#: src/guiPauseMenu.cpp:135
msgid "Exit to Menu"
msgstr ""
#: src/guiPauseMenu.cpp:142
msgid "Exit to OS"
msgstr ""
#: src/guiPauseMenu.cpp:149
msgid ""
"Default Controls:\n"
"- WASD: Walk\n"
"- Mouse left: dig/hit\n"
"- Mouse right: place/use\n"
"- Mouse wheel: select item\n"
"- 0...9: select item\n"
"- Shift: sneak\n"
"- R: Toggle viewing all loaded chunks\n"
"- I: Inventory menu\n"
"- ESC: This menu\n"
"- T: Chat\n"
msgstr ""
#: src/keycode.cpp:223
msgid "Left Button"
msgstr ""
#: src/keycode.cpp:223
msgid "Middle Button"
msgstr ""
#: src/keycode.cpp:223
msgid "Right Button"
msgstr ""
#: src/keycode.cpp:223
msgid "X Button 1"
msgstr ""
#: src/keycode.cpp:224
msgid "Back"
msgstr ""
#: src/keycode.cpp:224
msgid "Clear"
msgstr ""
#: src/keycode.cpp:224
msgid "Return"
msgstr ""
#: src/keycode.cpp:224
msgid "Tab"
msgstr ""
#: src/keycode.cpp:224
msgid "X Button 2"
msgstr ""
#: src/keycode.cpp:225
msgid "Capital"
msgstr ""
#: src/keycode.cpp:225
msgid "Control"
msgstr ""
#: src/keycode.cpp:225
msgid "Kana"
msgstr ""
#: src/keycode.cpp:225
msgid "Menu"
msgstr ""
#: src/keycode.cpp:225
msgid "Pause"
msgstr ""
#: src/keycode.cpp:225
msgid "Shift"
msgstr ""
#: src/keycode.cpp:226
msgid "Convert"
msgstr ""
#: src/keycode.cpp:226
msgid "Escape"
msgstr ""
#: src/keycode.cpp:226
msgid "Final"
msgstr ""
#: src/keycode.cpp:226
msgid "Junja"
msgstr ""
#: src/keycode.cpp:226
msgid "Kanji"
msgstr ""
#: src/keycode.cpp:226
msgid "Nonconvert"
msgstr ""
#: src/keycode.cpp:227
msgid "Accept"
msgstr ""
#: src/keycode.cpp:227
msgid "End"
msgstr ""
#: src/keycode.cpp:227
msgid "Home"
msgstr ""
#: src/keycode.cpp:227
msgid "Mode Change"
msgstr ""
#: src/keycode.cpp:227
msgid "Next"
msgstr ""
#: src/keycode.cpp:227
msgid "Prior"
msgstr ""
#: src/keycode.cpp:227
msgid "Space"
msgstr ""
#: src/keycode.cpp:228
msgid "Down"
msgstr ""
#: src/keycode.cpp:228
msgid "Execute"
msgstr ""
#: src/keycode.cpp:228
msgid "Left"
msgstr ""
#: src/keycode.cpp:228
msgid "Print"
msgstr ""
#: src/keycode.cpp:228
msgid "Right"
msgstr ""
#: src/keycode.cpp:228
msgid "Select"
msgstr ""
#: src/keycode.cpp:228
msgid "Up"
msgstr ""
#: src/keycode.cpp:229
msgid "Help"
msgstr ""
#: src/keycode.cpp:229
msgid "Insert"
msgstr ""
#: src/keycode.cpp:229
msgid "Snapshot"
msgstr ""
#: src/keycode.cpp:232
msgid "Left Windows"
msgstr ""
#: src/keycode.cpp:233
msgid "Apps"
msgstr ""
#: src/keycode.cpp:233
msgid "Numpad 0"
msgstr ""
#: src/keycode.cpp:233
msgid "Numpad 1"
msgstr ""
#: src/keycode.cpp:233
msgid "Right Windows"
msgstr ""
#: src/keycode.cpp:233
msgid "Sleep"
msgstr ""
#: src/keycode.cpp:234
msgid "Numpad 2"
msgstr ""
#: src/keycode.cpp:234
msgid "Numpad 3"
msgstr ""
#: src/keycode.cpp:234
msgid "Numpad 4"
msgstr ""
#: src/keycode.cpp:234
msgid "Numpad 5"
msgstr ""
#: src/keycode.cpp:234
msgid "Numpad 6"
msgstr ""
#: src/keycode.cpp:234
msgid "Numpad 7"
msgstr ""
#: src/keycode.cpp:235
msgid "Numpad *"
msgstr ""
#: src/keycode.cpp:235
msgid "Numpad +"
msgstr ""
#: src/keycode.cpp:235
msgid "Numpad -"
msgstr ""
#: src/keycode.cpp:235
msgid "Numpad /"
msgstr ""
#: src/keycode.cpp:235
msgid "Numpad 8"
msgstr ""
#: src/keycode.cpp:235
msgid "Numpad 9"
msgstr ""
#: src/keycode.cpp:239
msgid "Num Lock"
msgstr ""
#: src/keycode.cpp:239
msgid "Scroll Lock"
msgstr ""
#: src/keycode.cpp:240
msgid "Left Shift"
msgstr ""
#: src/keycode.cpp:240
msgid "Right Shift"
msgstr ""
#: src/keycode.cpp:241
msgid "Left Control"
msgstr ""
#: src/keycode.cpp:241
msgid "Left Menu"
msgstr ""
#: src/keycode.cpp:241
msgid "Right Control"
msgstr ""
#: src/keycode.cpp:241
msgid "Right Menu"
msgstr ""
#: src/keycode.cpp:243
msgid "Comma"
msgstr ""
#: src/keycode.cpp:243
msgid "Minus"
msgstr ""
#: src/keycode.cpp:243
msgid "Period"
msgstr ""
#: src/keycode.cpp:243
msgid "Plus"
msgstr ""
#: src/keycode.cpp:247
msgid "Attn"
msgstr ""
#: src/keycode.cpp:247
msgid "CrSel"
msgstr ""
#: src/keycode.cpp:248
msgid "Erase OEF"
msgstr ""
#: src/keycode.cpp:248
msgid "ExSel"
msgstr ""
#: src/keycode.cpp:248
msgid "OEM Clear"
msgstr ""
#: src/keycode.cpp:248
msgid "PA1"
msgstr ""
#: src/keycode.cpp:248
msgid "Zoom"
msgstr ""
#: src/main.cpp:1384
msgid "Main Menu"
msgstr ""
#: src/main.cpp:1633
msgid "Failed to initialize world"
msgstr ""
#: src/main.cpp:1645
msgid "No world selected and no address provided. Nothing to do."
msgstr ""
#: src/main.cpp:1653
msgid "Could not find or load game \""
msgstr ""
#: src/main.cpp:1667
msgid "Invalid gamespec."
msgstr ""
#: src/main.cpp:1707
msgid "Connection error (timed out?)"
msgstr ""
#: src/main.cpp:1718
msgid ""
"\n"
"Check debug.txt for details."
msgstr ""

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

View File

@ -8,7 +8,7 @@ msgid ""
msgstr ""
"Project-Id-Version: minetest\n"
"Report-Msgid-Bugs-To: \n"
"POT-Creation-Date: 2012-06-04 23:25+0300\n"
"POT-Creation-Date: 2013-01-23 18:24+0200\n"
"PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n"
"Last-Translator: FULL NAME <EMAIL@ADDRESS>\n"
"Language-Team: LANGUAGE <LL@li.org>\n"
@ -17,6 +17,55 @@ msgstr ""
"Content-Type: text/plain; charset=CHARSET\n"
"Content-Transfer-Encoding: 8bit\n"
#: src/guiConfigureWorld.cpp:127
msgid ""
"Warning: Some mods are not configured yet.\n"
"They will be enabled by default when you save the configuration. "
msgstr ""
#: src/guiConfigureWorld.cpp:146
msgid ""
"Warning: Some configured mods are missing.\n"
"Their setting will be removed when you save the configuration. "
msgstr ""
#: src/guiConfigureWorld.cpp:210
msgid "enabled"
msgstr ""
#: src/guiConfigureWorld.cpp:217
msgid "Enable All"
msgstr ""
#: src/guiConfigureWorld.cpp:224
msgid "Disable All"
msgstr ""
#: src/guiConfigureWorld.cpp:230
msgid "depends on:"
msgstr ""
#: src/guiConfigureWorld.cpp:242
msgid "is required by:"
msgstr ""
#: src/guiConfigureWorld.cpp:262 src/guiCreateWorld.cpp:165
#: src/guiKeyChangeMenu.cpp:179 src/keycode.cpp:223
msgid "Cancel"
msgstr ""
#: src/guiConfigureWorld.cpp:268 src/guiKeyChangeMenu.cpp:173
msgid "Save"
msgstr ""
#: src/guiConfigureWorld.cpp:394
msgid "Configuration saved. "
msgstr ""
#: src/guiConfigureWorld.cpp:402
msgid "Warning: Configuration not consistent. "
msgstr ""
#: src/guiConfirmMenu.cpp:120
msgid "Yes"
msgstr ""
@ -37,10 +86,6 @@ msgstr ""
msgid "Create"
msgstr ""
#: src/guiCreateWorld.cpp:165 src/guiKeyChangeMenu.cpp:374 src/keycode.cpp:221
msgid "Cancel"
msgstr ""
#: src/guiDeathScreen.cpp:96
msgid "You died."
msgstr ""
@ -49,209 +94,199 @@ msgstr ""
msgid "Respawn"
msgstr ""
#: src/guiKeyChangeMenu.cpp:111
#: src/guiFormSpecMenu.cpp:572
msgid "Left click: Move all items, Right click: Move single item"
msgstr ""
#: src/guiFormSpecMenu.cpp:597 src/guiMessageMenu.cpp:109
#: src/guiTextInputMenu.cpp:123
msgid "Proceed"
msgstr ""
#: src/guiKeyChangeMenu.cpp:114
msgid "Keybindings. (If this menu screws up, remove stuff from minetest.conf)"
msgstr ""
#: src/guiKeyChangeMenu.cpp:121
msgid "Forward"
#: src/guiKeyChangeMenu.cpp:151
msgid "\"Use\" = climb down"
msgstr ""
#: src/guiKeyChangeMenu.cpp:138
msgid "Backward"
#: src/guiKeyChangeMenu.cpp:164
msgid "Double tap \"jump\" to toggle fly"
msgstr ""
#: src/guiKeyChangeMenu.cpp:154 src/keycode.cpp:226
msgid "Left"
#: src/guiKeyChangeMenu.cpp:269
msgid "Key already in use"
msgstr ""
#: src/guiKeyChangeMenu.cpp:169 src/keycode.cpp:226
msgid "Right"
#: src/guiKeyChangeMenu.cpp:347
msgid "press key"
msgstr ""
#: src/guiKeyChangeMenu.cpp:185
msgid "Use"
#: src/guiMainMenu.cpp:55
msgid "Cannot create world: Name contains invalid characters"
msgstr ""
#: src/guiKeyChangeMenu.cpp:200
msgid "Sneak"
#: src/guiMainMenu.cpp:64
msgid "Cannot create world: A world by this name already exists"
msgstr ""
#: src/guiKeyChangeMenu.cpp:216
msgid "Jump"
msgstr ""
#: src/guiKeyChangeMenu.cpp:231
msgid "Drop"
msgstr ""
#: src/guiKeyChangeMenu.cpp:246
msgid "Inventory"
msgstr ""
#: src/guiKeyChangeMenu.cpp:262
msgid "Chat"
msgstr ""
#: src/guiKeyChangeMenu.cpp:276
msgid "Command"
msgstr ""
#: src/guiKeyChangeMenu.cpp:290
msgid "Console"
msgstr ""
#: src/guiKeyChangeMenu.cpp:306
msgid "Toggle fly"
msgstr ""
#: src/guiKeyChangeMenu.cpp:321
msgid "Toggle fast"
msgstr ""
#: src/guiKeyChangeMenu.cpp:336
msgid "Range select"
msgstr ""
#: src/guiKeyChangeMenu.cpp:353
msgid "Print stacks"
msgstr ""
#: src/guiKeyChangeMenu.cpp:368
msgid "Save"
msgstr ""
#: src/guiKeyChangeMenu.cpp:626 src/guiKeyChangeMenu.cpp:631
#: src/guiKeyChangeMenu.cpp:636 src/guiKeyChangeMenu.cpp:641
#: src/guiKeyChangeMenu.cpp:646 src/guiKeyChangeMenu.cpp:651
#: src/guiKeyChangeMenu.cpp:656 src/guiKeyChangeMenu.cpp:661
#: src/guiKeyChangeMenu.cpp:666 src/guiKeyChangeMenu.cpp:671
#: src/guiKeyChangeMenu.cpp:676 src/guiKeyChangeMenu.cpp:681
#: src/guiKeyChangeMenu.cpp:686 src/guiKeyChangeMenu.cpp:691
#: src/guiKeyChangeMenu.cpp:696 src/guiKeyChangeMenu.cpp:701
msgid "press Key"
msgstr ""
#: src/guiMainMenu.cpp:217
#: src/guiMainMenu.cpp:245
msgid "Singleplayer"
msgstr ""
#: src/guiMainMenu.cpp:218
#: src/guiMainMenu.cpp:246
msgid "Multiplayer"
msgstr ""
#: src/guiMainMenu.cpp:219
#: src/guiMainMenu.cpp:247
msgid "Advanced"
msgstr ""
#: src/guiMainMenu.cpp:220
#: src/guiMainMenu.cpp:248
msgid "Settings"
msgstr ""
#: src/guiMainMenu.cpp:221
#: src/guiMainMenu.cpp:249
msgid "Credits"
msgstr ""
#: src/guiMainMenu.cpp:252
#: src/guiMainMenu.cpp:280
msgid "Select World:"
msgstr ""
#: src/guiMainMenu.cpp:274 src/keycode.cpp:227
#: src/guiMainMenu.cpp:302 src/guiMainMenu.cpp:449 src/keycode.cpp:229
msgid "Delete"
msgstr ""
#: src/guiMainMenu.cpp:281
#: src/guiMainMenu.cpp:309
msgid "New"
msgstr ""
#: src/guiMainMenu.cpp:289
#: src/guiMainMenu.cpp:317
msgid "Configure"
msgstr ""
#: src/guiMainMenu.cpp:304 src/keycode.cpp:246
#: src/guiMainMenu.cpp:332 src/keycode.cpp:248
msgid "Play"
msgstr ""
#: src/guiMainMenu.cpp:315 src/guiMainMenu.cpp:492
#: src/guiMainMenu.cpp:343 src/guiMainMenu.cpp:557
msgid "Creative Mode"
msgstr ""
#: src/guiMainMenu.cpp:321 src/guiMainMenu.cpp:498
#: src/guiMainMenu.cpp:349 src/guiMainMenu.cpp:563
msgid "Enable Damage"
msgstr ""
#: src/guiMainMenu.cpp:341 src/guiMainMenu.cpp:414
#: src/guiMainMenu.cpp:369 src/guiMainMenu.cpp:479
msgid "Name/Password"
msgstr ""
#: src/guiMainMenu.cpp:368 src/guiMainMenu.cpp:441
#: src/guiMainMenu.cpp:408 src/guiMainMenu.cpp:506
msgid "Address/Port"
msgstr ""
#: src/guiMainMenu.cpp:394 src/guiMainMenu.cpp:473
msgid "Start Game / Connect"
#: src/guiMainMenu.cpp:435 src/guiMainMenu.cpp:1075
msgid "Show Public"
msgstr ""
#: src/guiMainMenu.cpp:464
#: src/guiMainMenu.cpp:439 src/guiMainMenu.cpp:1083
msgid "Show Favorites"
msgstr ""
#: src/guiMainMenu.cpp:459
msgid "Connect"
msgstr ""
#: src/guiMainMenu.cpp:529
msgid "Leave address blank to start a local server."
msgstr ""
#: src/guiMainMenu.cpp:505 src/guiMainMenu.cpp:833
#: src/guiMainMenu.cpp:538
msgid "Start Game / Connect"
msgstr ""
#: src/guiMainMenu.cpp:570 src/guiMainMenu.cpp:1006
msgid "Delete world"
msgstr ""
#: src/guiMainMenu.cpp:512
#: src/guiMainMenu.cpp:577
msgid "Create world"
msgstr ""
#: src/guiMainMenu.cpp:546
#: src/guiMainMenu.cpp:611
msgid "Fancy trees"
msgstr ""
#: src/guiMainMenu.cpp:552
#: src/guiMainMenu.cpp:617
msgid "Smooth Lighting"
msgstr ""
#: src/guiMainMenu.cpp:558
#: src/guiMainMenu.cpp:623
msgid "3D Clouds"
msgstr ""
#: src/guiMainMenu.cpp:564
#: src/guiMainMenu.cpp:629
msgid "Opaque water"
msgstr ""
#: src/guiMainMenu.cpp:573
#: src/guiMainMenu.cpp:639
msgid "Mip-Mapping"
msgstr ""
#: src/guiMainMenu.cpp:646
msgid "Anisotropic Filtering"
msgstr ""
#: src/guiMainMenu.cpp:653
msgid "Bi-Linear Filtering"
msgstr ""
#: src/guiMainMenu.cpp:660
msgid "Tri-Linear Filtering"
msgstr ""
#: src/guiMainMenu.cpp:668
msgid "Shaders"
msgstr ""
#: src/guiMainMenu.cpp:675
msgid "Preload item visuals"
msgstr ""
#: src/guiMainMenu.cpp:682
msgid "Enable Particles"
msgstr ""
#: src/guiMainMenu.cpp:692
msgid "Change keys"
msgstr ""
#: src/guiMainMenu.cpp:804
#: src/guiMainMenu.cpp:977
msgid "Address required."
msgstr ""
#: src/guiMainMenu.cpp:822
#: src/guiMainMenu.cpp:995
msgid "Cannot delete world: Nothing selected"
msgstr ""
#: src/guiMainMenu.cpp:837
#: src/guiMainMenu.cpp:1010
msgid "Files to be deleted"
msgstr ""
#: src/guiMainMenu.cpp:853
#: src/guiMainMenu.cpp:1026
msgid "Cannot create world: No games found"
msgstr ""
#: src/guiMainMenu.cpp:866
msgid "Nothing here"
#: src/guiMainMenu.cpp:1042
msgid "Cannot configure world: Nothing selected"
msgstr ""
#: src/guiMainMenu.cpp:915
#: src/guiMainMenu.cpp:1146
msgid "Failed to delete all world files"
msgstr ""
#: src/guiMessageMenu.cpp:109 src/guiTextInputMenu.cpp:123
msgid "Proceed"
msgstr ""
#: src/guiPasswordChange.cpp:108
msgid "Old Password"
msgstr ""
@ -303,323 +338,331 @@ msgid ""
"- T: Chat\n"
msgstr ""
#: src/keycode.cpp:221
#: src/keycode.cpp:223
msgid "Left Button"
msgstr ""
#: src/keycode.cpp:221
#: src/keycode.cpp:223
msgid "Middle Button"
msgstr ""
#: src/keycode.cpp:221
#: src/keycode.cpp:223
msgid "Right Button"
msgstr ""
#: src/keycode.cpp:221
#: src/keycode.cpp:223
msgid "X Button 1"
msgstr ""
#: src/keycode.cpp:222
#: src/keycode.cpp:224
msgid "Back"
msgstr ""
#: src/keycode.cpp:222
#: src/keycode.cpp:224
msgid "Clear"
msgstr ""
#: src/keycode.cpp:222
#: src/keycode.cpp:224
msgid "Return"
msgstr ""
#: src/keycode.cpp:222
#: src/keycode.cpp:224
msgid "Tab"
msgstr ""
#: src/keycode.cpp:222
#: src/keycode.cpp:224
msgid "X Button 2"
msgstr ""
#: src/keycode.cpp:223
#: src/keycode.cpp:225
msgid "Capital"
msgstr ""
#: src/keycode.cpp:223
#: src/keycode.cpp:225
msgid "Control"
msgstr ""
#: src/keycode.cpp:223
#: src/keycode.cpp:225
msgid "Kana"
msgstr ""
#: src/keycode.cpp:223
#: src/keycode.cpp:225
msgid "Menu"
msgstr ""
#: src/keycode.cpp:223
#: src/keycode.cpp:225
msgid "Pause"
msgstr ""
#: src/keycode.cpp:223
#: src/keycode.cpp:225
msgid "Shift"
msgstr ""
#: src/keycode.cpp:224
#: src/keycode.cpp:226
msgid "Convert"
msgstr ""
#: src/keycode.cpp:224
#: src/keycode.cpp:226
msgid "Escape"
msgstr ""
#: src/keycode.cpp:224
#: src/keycode.cpp:226
msgid "Final"
msgstr ""
#: src/keycode.cpp:224
#: src/keycode.cpp:226
msgid "Junja"
msgstr ""
#: src/keycode.cpp:224
#: src/keycode.cpp:226
msgid "Kanji"
msgstr ""
#: src/keycode.cpp:224
#: src/keycode.cpp:226
msgid "Nonconvert"
msgstr ""
#: src/keycode.cpp:225
#: src/keycode.cpp:227
msgid "Accept"
msgstr ""
#: src/keycode.cpp:225
#: src/keycode.cpp:227
msgid "End"
msgstr ""
#: src/keycode.cpp:225
#: src/keycode.cpp:227
msgid "Home"
msgstr ""
#: src/keycode.cpp:225
#: src/keycode.cpp:227
msgid "Mode Change"
msgstr ""
#: src/keycode.cpp:225
#: src/keycode.cpp:227
msgid "Next"
msgstr ""
#: src/keycode.cpp:225
#: src/keycode.cpp:227
msgid "Prior"
msgstr ""
#: src/keycode.cpp:225
#: src/keycode.cpp:227
msgid "Space"
msgstr ""
#: src/keycode.cpp:226
#: src/keycode.cpp:228
msgid "Down"
msgstr ""
#: src/keycode.cpp:226
#: src/keycode.cpp:228
msgid "Execute"
msgstr ""
#: src/keycode.cpp:226
#: src/keycode.cpp:228
msgid "Left"
msgstr ""
#: src/keycode.cpp:228
msgid "Print"
msgstr ""
#: src/keycode.cpp:226
#: src/keycode.cpp:228
msgid "Right"
msgstr ""
#: src/keycode.cpp:228
msgid "Select"
msgstr ""
#: src/keycode.cpp:226
#: src/keycode.cpp:228
msgid "Up"
msgstr ""
#: src/keycode.cpp:227
#: src/keycode.cpp:229
msgid "Help"
msgstr ""
#: src/keycode.cpp:227
#: src/keycode.cpp:229
msgid "Insert"
msgstr ""
#: src/keycode.cpp:227
#: src/keycode.cpp:229
msgid "Snapshot"
msgstr ""
#: src/keycode.cpp:230
#: src/keycode.cpp:232
msgid "Left Windows"
msgstr ""
#: src/keycode.cpp:231
#: src/keycode.cpp:233
msgid "Apps"
msgstr ""
#: src/keycode.cpp:231
#: src/keycode.cpp:233
msgid "Numpad 0"
msgstr ""
#: src/keycode.cpp:231
#: src/keycode.cpp:233
msgid "Numpad 1"
msgstr ""
#: src/keycode.cpp:231
#: src/keycode.cpp:233
msgid "Right Windows"
msgstr ""
#: src/keycode.cpp:231
#: src/keycode.cpp:233
msgid "Sleep"
msgstr ""
#: src/keycode.cpp:232
#: src/keycode.cpp:234
msgid "Numpad 2"
msgstr ""
#: src/keycode.cpp:232
#: src/keycode.cpp:234
msgid "Numpad 3"
msgstr ""
#: src/keycode.cpp:232
#: src/keycode.cpp:234
msgid "Numpad 4"
msgstr ""
#: src/keycode.cpp:232
#: src/keycode.cpp:234
msgid "Numpad 5"
msgstr ""
#: src/keycode.cpp:232
#: src/keycode.cpp:234
msgid "Numpad 6"
msgstr ""
#: src/keycode.cpp:232
#: src/keycode.cpp:234
msgid "Numpad 7"
msgstr ""
#: src/keycode.cpp:233
#: src/keycode.cpp:235
msgid "Numpad *"
msgstr ""
#: src/keycode.cpp:233
#: src/keycode.cpp:235
msgid "Numpad +"
msgstr ""
#: src/keycode.cpp:233
#: src/keycode.cpp:235
msgid "Numpad -"
msgstr ""
#: src/keycode.cpp:233
#: src/keycode.cpp:235
msgid "Numpad /"
msgstr ""
#: src/keycode.cpp:233
#: src/keycode.cpp:235
msgid "Numpad 8"
msgstr ""
#: src/keycode.cpp:233
#: src/keycode.cpp:235
msgid "Numpad 9"
msgstr ""
#: src/keycode.cpp:237
#: src/keycode.cpp:239
msgid "Num Lock"
msgstr ""
#: src/keycode.cpp:237
#: src/keycode.cpp:239
msgid "Scroll Lock"
msgstr ""
#: src/keycode.cpp:238
#: src/keycode.cpp:240
msgid "Left Shift"
msgstr ""
#: src/keycode.cpp:238
#: src/keycode.cpp:240
msgid "Right Shift"
msgstr ""
#: src/keycode.cpp:239
#: src/keycode.cpp:241
msgid "Left Control"
msgstr ""
#: src/keycode.cpp:239
#: src/keycode.cpp:241
msgid "Left Menu"
msgstr ""
#: src/keycode.cpp:239
#: src/keycode.cpp:241
msgid "Right Control"
msgstr ""
#: src/keycode.cpp:239
#: src/keycode.cpp:241
msgid "Right Menu"
msgstr ""
#: src/keycode.cpp:241
#: src/keycode.cpp:243
msgid "Comma"
msgstr ""
#: src/keycode.cpp:241
#: src/keycode.cpp:243
msgid "Minus"
msgstr ""
#: src/keycode.cpp:241
#: src/keycode.cpp:243
msgid "Period"
msgstr ""
#: src/keycode.cpp:241
#: src/keycode.cpp:243
msgid "Plus"
msgstr ""
#: src/keycode.cpp:245
#: src/keycode.cpp:247
msgid "Attn"
msgstr ""
#: src/keycode.cpp:245
#: src/keycode.cpp:247
msgid "CrSel"
msgstr ""
#: src/keycode.cpp:246
#: src/keycode.cpp:248
msgid "Erase OEF"
msgstr ""
#: src/keycode.cpp:246
#: src/keycode.cpp:248
msgid "ExSel"
msgstr ""
#: src/keycode.cpp:246
#: src/keycode.cpp:248
msgid "OEM Clear"
msgstr ""
#: src/keycode.cpp:246
#: src/keycode.cpp:248
msgid "PA1"
msgstr ""
#: src/keycode.cpp:246
#: src/keycode.cpp:248
msgid "Zoom"
msgstr ""
#: src/main.cpp:1379
#: src/main.cpp:1384
msgid "Main Menu"
msgstr ""
#: src/main.cpp:1601
#: src/main.cpp:1633
msgid "Failed to initialize world"
msgstr ""
#: src/main.cpp:1613
#: src/main.cpp:1645
msgid "No world selected and no address provided. Nothing to do."
msgstr ""
#: src/main.cpp:1621
#: src/main.cpp:1653
msgid "Could not find or load game \""
msgstr ""
#: src/main.cpp:1635
#: src/main.cpp:1667
msgid "Invalid gamespec."
msgstr ""
#: src/main.cpp:1675
#: src/main.cpp:1707
msgid "Connection error (timed out?)"
msgstr ""
#: src/main.cpp:1686
#: src/main.cpp:1718
msgid ""
"\n"
"Check debug.txt for details."

669
po/pl/minetest.po Normal file
View File

@ -0,0 +1,669 @@
# SOME DESCRIPTIVE TITLE.
# Copyright (C) YEAR THE PACKAGE'S COPYRIGHT HOLDER
# This file is distributed under the same license as the PACKAGE package.
# FIRST AUTHOR <EMAIL@ADDRESS>, YEAR.
#
#, fuzzy
msgid ""
msgstr ""
"Project-Id-Version: minetest\n"
"Report-Msgid-Bugs-To: \n"
"POT-Creation-Date: 2013-01-23 18:24+0200\n"
"PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n"
"Last-Translator: FULL NAME <EMAIL@ADDRESS>\n"
"Language-Team: LANGUAGE <LL@li.org>\n"
"Language: \n"
"MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=CHARSET\n"
"Content-Transfer-Encoding: 8bit\n"
#: src/guiConfigureWorld.cpp:127
msgid ""
"Warning: Some mods are not configured yet.\n"
"They will be enabled by default when you save the configuration. "
msgstr ""
#: src/guiConfigureWorld.cpp:146
msgid ""
"Warning: Some configured mods are missing.\n"
"Their setting will be removed when you save the configuration. "
msgstr ""
#: src/guiConfigureWorld.cpp:210
msgid "enabled"
msgstr ""
#: src/guiConfigureWorld.cpp:217
msgid "Enable All"
msgstr ""
#: src/guiConfigureWorld.cpp:224
msgid "Disable All"
msgstr ""
#: src/guiConfigureWorld.cpp:230
msgid "depends on:"
msgstr ""
#: src/guiConfigureWorld.cpp:242
msgid "is required by:"
msgstr ""
#: src/guiConfigureWorld.cpp:262 src/guiCreateWorld.cpp:165
#: src/guiKeyChangeMenu.cpp:179 src/keycode.cpp:223
msgid "Cancel"
msgstr ""
#: src/guiConfigureWorld.cpp:268 src/guiKeyChangeMenu.cpp:173
msgid "Save"
msgstr ""
#: src/guiConfigureWorld.cpp:394
msgid "Configuration saved. "
msgstr ""
#: src/guiConfigureWorld.cpp:402
msgid "Warning: Configuration not consistent. "
msgstr ""
#: src/guiConfirmMenu.cpp:120
msgid "Yes"
msgstr ""
#: src/guiConfirmMenu.cpp:126
msgid "No"
msgstr ""
#: src/guiCreateWorld.cpp:116
msgid "World name"
msgstr ""
#: src/guiCreateWorld.cpp:135
msgid "Game"
msgstr ""
#: src/guiCreateWorld.cpp:159
msgid "Create"
msgstr ""
#: src/guiDeathScreen.cpp:96
msgid "You died."
msgstr ""
#: src/guiDeathScreen.cpp:104
msgid "Respawn"
msgstr ""
#: src/guiFormSpecMenu.cpp:572
msgid "Left click: Move all items, Right click: Move single item"
msgstr ""
#: src/guiFormSpecMenu.cpp:597 src/guiMessageMenu.cpp:109
#: src/guiTextInputMenu.cpp:123
msgid "Proceed"
msgstr ""
#: src/guiKeyChangeMenu.cpp:114
msgid "Keybindings. (If this menu screws up, remove stuff from minetest.conf)"
msgstr ""
#: src/guiKeyChangeMenu.cpp:151
msgid "\"Use\" = climb down"
msgstr ""
#: src/guiKeyChangeMenu.cpp:164
msgid "Double tap \"jump\" to toggle fly"
msgstr ""
#: src/guiKeyChangeMenu.cpp:269
msgid "Key already in use"
msgstr ""
#: src/guiKeyChangeMenu.cpp:347
msgid "press key"
msgstr ""
#: src/guiMainMenu.cpp:55
msgid "Cannot create world: Name contains invalid characters"
msgstr ""
#: src/guiMainMenu.cpp:64
msgid "Cannot create world: A world by this name already exists"
msgstr ""
#: src/guiMainMenu.cpp:245
msgid "Singleplayer"
msgstr ""
#: src/guiMainMenu.cpp:246
msgid "Multiplayer"
msgstr ""
#: src/guiMainMenu.cpp:247
msgid "Advanced"
msgstr ""
#: src/guiMainMenu.cpp:248
msgid "Settings"
msgstr ""
#: src/guiMainMenu.cpp:249
msgid "Credits"
msgstr ""
#: src/guiMainMenu.cpp:280
msgid "Select World:"
msgstr ""
#: src/guiMainMenu.cpp:302 src/guiMainMenu.cpp:449 src/keycode.cpp:229
msgid "Delete"
msgstr ""
#: src/guiMainMenu.cpp:309
msgid "New"
msgstr ""
#: src/guiMainMenu.cpp:317
msgid "Configure"
msgstr ""
#: src/guiMainMenu.cpp:332 src/keycode.cpp:248
msgid "Play"
msgstr ""
#: src/guiMainMenu.cpp:343 src/guiMainMenu.cpp:557
msgid "Creative Mode"
msgstr ""
#: src/guiMainMenu.cpp:349 src/guiMainMenu.cpp:563
msgid "Enable Damage"
msgstr ""
#: src/guiMainMenu.cpp:369 src/guiMainMenu.cpp:479
msgid "Name/Password"
msgstr ""
#: src/guiMainMenu.cpp:408 src/guiMainMenu.cpp:506
msgid "Address/Port"
msgstr ""
#: src/guiMainMenu.cpp:435 src/guiMainMenu.cpp:1075
msgid "Show Public"
msgstr ""
#: src/guiMainMenu.cpp:439 src/guiMainMenu.cpp:1083
msgid "Show Favorites"
msgstr ""
#: src/guiMainMenu.cpp:459
msgid "Connect"
msgstr ""
#: src/guiMainMenu.cpp:529
msgid "Leave address blank to start a local server."
msgstr ""
#: src/guiMainMenu.cpp:538
msgid "Start Game / Connect"
msgstr ""
#: src/guiMainMenu.cpp:570 src/guiMainMenu.cpp:1006
msgid "Delete world"
msgstr ""
#: src/guiMainMenu.cpp:577
msgid "Create world"
msgstr ""
#: src/guiMainMenu.cpp:611
msgid "Fancy trees"
msgstr ""
#: src/guiMainMenu.cpp:617
msgid "Smooth Lighting"
msgstr ""
#: src/guiMainMenu.cpp:623
msgid "3D Clouds"
msgstr ""
#: src/guiMainMenu.cpp:629
msgid "Opaque water"
msgstr ""
#: src/guiMainMenu.cpp:639
msgid "Mip-Mapping"
msgstr ""
#: src/guiMainMenu.cpp:646
msgid "Anisotropic Filtering"
msgstr ""
#: src/guiMainMenu.cpp:653
msgid "Bi-Linear Filtering"
msgstr ""
#: src/guiMainMenu.cpp:660
msgid "Tri-Linear Filtering"
msgstr ""
#: src/guiMainMenu.cpp:668
msgid "Shaders"
msgstr ""
#: src/guiMainMenu.cpp:675
msgid "Preload item visuals"
msgstr ""
#: src/guiMainMenu.cpp:682
msgid "Enable Particles"
msgstr ""
#: src/guiMainMenu.cpp:692
msgid "Change keys"
msgstr ""
#: src/guiMainMenu.cpp:977
msgid "Address required."
msgstr ""
#: src/guiMainMenu.cpp:995
msgid "Cannot delete world: Nothing selected"
msgstr ""
#: src/guiMainMenu.cpp:1010
msgid "Files to be deleted"
msgstr ""
#: src/guiMainMenu.cpp:1026
msgid "Cannot create world: No games found"
msgstr ""
#: src/guiMainMenu.cpp:1042
msgid "Cannot configure world: Nothing selected"
msgstr ""
#: src/guiMainMenu.cpp:1146
msgid "Failed to delete all world files"
msgstr ""
#: src/guiPasswordChange.cpp:108
msgid "Old Password"
msgstr ""
#: src/guiPasswordChange.cpp:125
msgid "New Password"
msgstr ""
#: src/guiPasswordChange.cpp:141
msgid "Confirm Password"
msgstr ""
#: src/guiPasswordChange.cpp:158
msgid "Change"
msgstr ""
#: src/guiPasswordChange.cpp:167
msgid "Passwords do not match!"
msgstr ""
#: src/guiPauseMenu.cpp:118
msgid "Continue"
msgstr ""
#: src/guiPauseMenu.cpp:127
msgid "Change Password"
msgstr ""
#: src/guiPauseMenu.cpp:135
msgid "Exit to Menu"
msgstr ""
#: src/guiPauseMenu.cpp:142
msgid "Exit to OS"
msgstr ""
#: src/guiPauseMenu.cpp:149
msgid ""
"Default Controls:\n"
"- WASD: Walk\n"
"- Mouse left: dig/hit\n"
"- Mouse right: place/use\n"
"- Mouse wheel: select item\n"
"- 0...9: select item\n"
"- Shift: sneak\n"
"- R: Toggle viewing all loaded chunks\n"
"- I: Inventory menu\n"
"- ESC: This menu\n"
"- T: Chat\n"
msgstr ""
#: src/keycode.cpp:223
msgid "Left Button"
msgstr ""
#: src/keycode.cpp:223
msgid "Middle Button"
msgstr ""
#: src/keycode.cpp:223
msgid "Right Button"
msgstr ""
#: src/keycode.cpp:223
msgid "X Button 1"
msgstr ""
#: src/keycode.cpp:224
msgid "Back"
msgstr ""
#: src/keycode.cpp:224
msgid "Clear"
msgstr ""
#: src/keycode.cpp:224
msgid "Return"
msgstr ""
#: src/keycode.cpp:224
msgid "Tab"
msgstr ""
#: src/keycode.cpp:224
msgid "X Button 2"
msgstr ""
#: src/keycode.cpp:225
msgid "Capital"
msgstr ""
#: src/keycode.cpp:225
msgid "Control"
msgstr ""
#: src/keycode.cpp:225
msgid "Kana"
msgstr ""
#: src/keycode.cpp:225
msgid "Menu"
msgstr ""
#: src/keycode.cpp:225
msgid "Pause"
msgstr ""
#: src/keycode.cpp:225
msgid "Shift"
msgstr ""
#: src/keycode.cpp:226
msgid "Convert"
msgstr ""
#: src/keycode.cpp:226
msgid "Escape"
msgstr ""
#: src/keycode.cpp:226
msgid "Final"
msgstr ""
#: src/keycode.cpp:226
msgid "Junja"
msgstr ""
#: src/keycode.cpp:226
msgid "Kanji"
msgstr ""
#: src/keycode.cpp:226
msgid "Nonconvert"
msgstr ""
#: src/keycode.cpp:227
msgid "Accept"
msgstr ""
#: src/keycode.cpp:227
msgid "End"
msgstr ""
#: src/keycode.cpp:227
msgid "Home"
msgstr ""
#: src/keycode.cpp:227
msgid "Mode Change"
msgstr ""
#: src/keycode.cpp:227
msgid "Next"
msgstr ""
#: src/keycode.cpp:227
msgid "Prior"
msgstr ""
#: src/keycode.cpp:227
msgid "Space"
msgstr ""
#: src/keycode.cpp:228
msgid "Down"
msgstr ""
#: src/keycode.cpp:228
msgid "Execute"
msgstr ""
#: src/keycode.cpp:228
msgid "Left"
msgstr ""
#: src/keycode.cpp:228
msgid "Print"
msgstr ""
#: src/keycode.cpp:228
msgid "Right"
msgstr ""
#: src/keycode.cpp:228
msgid "Select"
msgstr ""
#: src/keycode.cpp:228
msgid "Up"
msgstr ""
#: src/keycode.cpp:229
msgid "Help"
msgstr ""
#: src/keycode.cpp:229
msgid "Insert"
msgstr ""
#: src/keycode.cpp:229
msgid "Snapshot"
msgstr ""
#: src/keycode.cpp:232
msgid "Left Windows"
msgstr ""
#: src/keycode.cpp:233
msgid "Apps"
msgstr ""
#: src/keycode.cpp:233
msgid "Numpad 0"
msgstr ""
#: src/keycode.cpp:233
msgid "Numpad 1"
msgstr ""
#: src/keycode.cpp:233
msgid "Right Windows"
msgstr ""
#: src/keycode.cpp:233
msgid "Sleep"
msgstr ""
#: src/keycode.cpp:234
msgid "Numpad 2"
msgstr ""
#: src/keycode.cpp:234
msgid "Numpad 3"
msgstr ""
#: src/keycode.cpp:234
msgid "Numpad 4"
msgstr ""
#: src/keycode.cpp:234
msgid "Numpad 5"
msgstr ""
#: src/keycode.cpp:234
msgid "Numpad 6"
msgstr ""
#: src/keycode.cpp:234
msgid "Numpad 7"
msgstr ""
#: src/keycode.cpp:235
msgid "Numpad *"
msgstr ""
#: src/keycode.cpp:235
msgid "Numpad +"
msgstr ""
#: src/keycode.cpp:235
msgid "Numpad -"
msgstr ""
#: src/keycode.cpp:235
msgid "Numpad /"
msgstr ""
#: src/keycode.cpp:235
msgid "Numpad 8"
msgstr ""
#: src/keycode.cpp:235
msgid "Numpad 9"
msgstr ""
#: src/keycode.cpp:239
msgid "Num Lock"
msgstr ""
#: src/keycode.cpp:239
msgid "Scroll Lock"
msgstr ""
#: src/keycode.cpp:240
msgid "Left Shift"
msgstr ""
#: src/keycode.cpp:240
msgid "Right Shift"
msgstr ""
#: src/keycode.cpp:241
msgid "Left Control"
msgstr ""
#: src/keycode.cpp:241
msgid "Left Menu"
msgstr ""
#: src/keycode.cpp:241
msgid "Right Control"
msgstr ""
#: src/keycode.cpp:241
msgid "Right Menu"
msgstr ""
#: src/keycode.cpp:243
msgid "Comma"
msgstr ""
#: src/keycode.cpp:243
msgid "Minus"
msgstr ""
#: src/keycode.cpp:243
msgid "Period"
msgstr ""
#: src/keycode.cpp:243
msgid "Plus"
msgstr ""
#: src/keycode.cpp:247
msgid "Attn"
msgstr ""
#: src/keycode.cpp:247
msgid "CrSel"
msgstr ""
#: src/keycode.cpp:248
msgid "Erase OEF"
msgstr ""
#: src/keycode.cpp:248
msgid "ExSel"
msgstr ""
#: src/keycode.cpp:248
msgid "OEM Clear"
msgstr ""
#: src/keycode.cpp:248
msgid "PA1"
msgstr ""
#: src/keycode.cpp:248
msgid "Zoom"
msgstr ""
#: src/main.cpp:1384
msgid "Main Menu"
msgstr ""
#: src/main.cpp:1633
msgid "Failed to initialize world"
msgstr ""
#: src/main.cpp:1645
msgid "No world selected and no address provided. Nothing to do."
msgstr ""
#: src/main.cpp:1653
msgid "Could not find or load game \""
msgstr ""
#: src/main.cpp:1667
msgid "Invalid gamespec."
msgstr ""
#: src/main.cpp:1707
msgid "Connection error (timed out?)"
msgstr ""
#: src/main.cpp:1718
msgid ""
"\n"
"Check debug.txt for details."
msgstr ""

669
po/ro/minetest.po Normal file
View File

@ -0,0 +1,669 @@
# SOME DESCRIPTIVE TITLE.
# Copyright (C) YEAR THE PACKAGE'S COPYRIGHT HOLDER
# This file is distributed under the same license as the PACKAGE package.
# FIRST AUTHOR <EMAIL@ADDRESS>, YEAR.
#
#, fuzzy
msgid ""
msgstr ""
"Project-Id-Version: minetest\n"
"Report-Msgid-Bugs-To: \n"
"POT-Creation-Date: 2013-01-23 18:24+0200\n"
"PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n"
"Last-Translator: FULL NAME <EMAIL@ADDRESS>\n"
"Language-Team: LANGUAGE <LL@li.org>\n"
"Language: \n"
"MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=CHARSET\n"
"Content-Transfer-Encoding: 8bit\n"
#: src/guiConfigureWorld.cpp:127
msgid ""
"Warning: Some mods are not configured yet.\n"
"They will be enabled by default when you save the configuration. "
msgstr ""
#: src/guiConfigureWorld.cpp:146
msgid ""
"Warning: Some configured mods are missing.\n"
"Their setting will be removed when you save the configuration. "
msgstr ""
#: src/guiConfigureWorld.cpp:210
msgid "enabled"
msgstr ""
#: src/guiConfigureWorld.cpp:217
msgid "Enable All"
msgstr ""
#: src/guiConfigureWorld.cpp:224
msgid "Disable All"
msgstr ""
#: src/guiConfigureWorld.cpp:230
msgid "depends on:"
msgstr ""
#: src/guiConfigureWorld.cpp:242
msgid "is required by:"
msgstr ""
#: src/guiConfigureWorld.cpp:262 src/guiCreateWorld.cpp:165
#: src/guiKeyChangeMenu.cpp:179 src/keycode.cpp:223
msgid "Cancel"
msgstr ""
#: src/guiConfigureWorld.cpp:268 src/guiKeyChangeMenu.cpp:173
msgid "Save"
msgstr ""
#: src/guiConfigureWorld.cpp:394
msgid "Configuration saved. "
msgstr ""
#: src/guiConfigureWorld.cpp:402
msgid "Warning: Configuration not consistent. "
msgstr ""
#: src/guiConfirmMenu.cpp:120
msgid "Yes"
msgstr ""
#: src/guiConfirmMenu.cpp:126
msgid "No"
msgstr ""
#: src/guiCreateWorld.cpp:116
msgid "World name"
msgstr ""
#: src/guiCreateWorld.cpp:135
msgid "Game"
msgstr ""
#: src/guiCreateWorld.cpp:159
msgid "Create"
msgstr ""
#: src/guiDeathScreen.cpp:96
msgid "You died."
msgstr ""
#: src/guiDeathScreen.cpp:104
msgid "Respawn"
msgstr ""
#: src/guiFormSpecMenu.cpp:572
msgid "Left click: Move all items, Right click: Move single item"
msgstr ""
#: src/guiFormSpecMenu.cpp:597 src/guiMessageMenu.cpp:109
#: src/guiTextInputMenu.cpp:123
msgid "Proceed"
msgstr ""
#: src/guiKeyChangeMenu.cpp:114
msgid "Keybindings. (If this menu screws up, remove stuff from minetest.conf)"
msgstr ""
#: src/guiKeyChangeMenu.cpp:151
msgid "\"Use\" = climb down"
msgstr ""
#: src/guiKeyChangeMenu.cpp:164
msgid "Double tap \"jump\" to toggle fly"
msgstr ""
#: src/guiKeyChangeMenu.cpp:269
msgid "Key already in use"
msgstr ""
#: src/guiKeyChangeMenu.cpp:347
msgid "press key"
msgstr ""
#: src/guiMainMenu.cpp:55
msgid "Cannot create world: Name contains invalid characters"
msgstr ""
#: src/guiMainMenu.cpp:64
msgid "Cannot create world: A world by this name already exists"
msgstr ""
#: src/guiMainMenu.cpp:245
msgid "Singleplayer"
msgstr ""
#: src/guiMainMenu.cpp:246
msgid "Multiplayer"
msgstr ""
#: src/guiMainMenu.cpp:247
msgid "Advanced"
msgstr ""
#: src/guiMainMenu.cpp:248
msgid "Settings"
msgstr ""
#: src/guiMainMenu.cpp:249
msgid "Credits"
msgstr ""
#: src/guiMainMenu.cpp:280
msgid "Select World:"
msgstr ""
#: src/guiMainMenu.cpp:302 src/guiMainMenu.cpp:449 src/keycode.cpp:229
msgid "Delete"
msgstr ""
#: src/guiMainMenu.cpp:309
msgid "New"
msgstr ""
#: src/guiMainMenu.cpp:317
msgid "Configure"
msgstr ""
#: src/guiMainMenu.cpp:332 src/keycode.cpp:248
msgid "Play"
msgstr ""
#: src/guiMainMenu.cpp:343 src/guiMainMenu.cpp:557
msgid "Creative Mode"
msgstr ""
#: src/guiMainMenu.cpp:349 src/guiMainMenu.cpp:563
msgid "Enable Damage"
msgstr ""
#: src/guiMainMenu.cpp:369 src/guiMainMenu.cpp:479
msgid "Name/Password"
msgstr ""
#: src/guiMainMenu.cpp:408 src/guiMainMenu.cpp:506
msgid "Address/Port"
msgstr ""
#: src/guiMainMenu.cpp:435 src/guiMainMenu.cpp:1075
msgid "Show Public"
msgstr ""
#: src/guiMainMenu.cpp:439 src/guiMainMenu.cpp:1083
msgid "Show Favorites"
msgstr ""
#: src/guiMainMenu.cpp:459
msgid "Connect"
msgstr ""
#: src/guiMainMenu.cpp:529
msgid "Leave address blank to start a local server."
msgstr ""
#: src/guiMainMenu.cpp:538
msgid "Start Game / Connect"
msgstr ""
#: src/guiMainMenu.cpp:570 src/guiMainMenu.cpp:1006
msgid "Delete world"
msgstr ""
#: src/guiMainMenu.cpp:577
msgid "Create world"
msgstr ""
#: src/guiMainMenu.cpp:611
msgid "Fancy trees"
msgstr ""
#: src/guiMainMenu.cpp:617
msgid "Smooth Lighting"
msgstr ""
#: src/guiMainMenu.cpp:623
msgid "3D Clouds"
msgstr ""
#: src/guiMainMenu.cpp:629
msgid "Opaque water"
msgstr ""
#: src/guiMainMenu.cpp:639
msgid "Mip-Mapping"
msgstr ""
#: src/guiMainMenu.cpp:646
msgid "Anisotropic Filtering"
msgstr ""
#: src/guiMainMenu.cpp:653
msgid "Bi-Linear Filtering"
msgstr ""
#: src/guiMainMenu.cpp:660
msgid "Tri-Linear Filtering"
msgstr ""
#: src/guiMainMenu.cpp:668
msgid "Shaders"
msgstr ""
#: src/guiMainMenu.cpp:675
msgid "Preload item visuals"
msgstr ""
#: src/guiMainMenu.cpp:682
msgid "Enable Particles"
msgstr ""
#: src/guiMainMenu.cpp:692
msgid "Change keys"
msgstr ""
#: src/guiMainMenu.cpp:977
msgid "Address required."
msgstr ""
#: src/guiMainMenu.cpp:995
msgid "Cannot delete world: Nothing selected"
msgstr ""
#: src/guiMainMenu.cpp:1010
msgid "Files to be deleted"
msgstr ""
#: src/guiMainMenu.cpp:1026
msgid "Cannot create world: No games found"
msgstr ""
#: src/guiMainMenu.cpp:1042
msgid "Cannot configure world: Nothing selected"
msgstr ""
#: src/guiMainMenu.cpp:1146
msgid "Failed to delete all world files"
msgstr ""
#: src/guiPasswordChange.cpp:108
msgid "Old Password"
msgstr ""
#: src/guiPasswordChange.cpp:125
msgid "New Password"
msgstr ""
#: src/guiPasswordChange.cpp:141
msgid "Confirm Password"
msgstr ""
#: src/guiPasswordChange.cpp:158
msgid "Change"
msgstr ""
#: src/guiPasswordChange.cpp:167
msgid "Passwords do not match!"
msgstr ""
#: src/guiPauseMenu.cpp:118
msgid "Continue"
msgstr ""
#: src/guiPauseMenu.cpp:127
msgid "Change Password"
msgstr ""
#: src/guiPauseMenu.cpp:135
msgid "Exit to Menu"
msgstr ""
#: src/guiPauseMenu.cpp:142
msgid "Exit to OS"
msgstr ""
#: src/guiPauseMenu.cpp:149
msgid ""
"Default Controls:\n"
"- WASD: Walk\n"
"- Mouse left: dig/hit\n"
"- Mouse right: place/use\n"
"- Mouse wheel: select item\n"
"- 0...9: select item\n"
"- Shift: sneak\n"
"- R: Toggle viewing all loaded chunks\n"
"- I: Inventory menu\n"
"- ESC: This menu\n"
"- T: Chat\n"
msgstr ""
#: src/keycode.cpp:223
msgid "Left Button"
msgstr ""
#: src/keycode.cpp:223
msgid "Middle Button"
msgstr ""
#: src/keycode.cpp:223
msgid "Right Button"
msgstr ""
#: src/keycode.cpp:223
msgid "X Button 1"
msgstr ""
#: src/keycode.cpp:224
msgid "Back"
msgstr ""
#: src/keycode.cpp:224
msgid "Clear"
msgstr ""
#: src/keycode.cpp:224
msgid "Return"
msgstr ""
#: src/keycode.cpp:224
msgid "Tab"
msgstr ""
#: src/keycode.cpp:224
msgid "X Button 2"
msgstr ""
#: src/keycode.cpp:225
msgid "Capital"
msgstr ""
#: src/keycode.cpp:225
msgid "Control"
msgstr ""
#: src/keycode.cpp:225
msgid "Kana"
msgstr ""
#: src/keycode.cpp:225
msgid "Menu"
msgstr ""
#: src/keycode.cpp:225
msgid "Pause"
msgstr ""
#: src/keycode.cpp:225
msgid "Shift"
msgstr ""
#: src/keycode.cpp:226
msgid "Convert"
msgstr ""
#: src/keycode.cpp:226
msgid "Escape"
msgstr ""
#: src/keycode.cpp:226
msgid "Final"
msgstr ""
#: src/keycode.cpp:226
msgid "Junja"
msgstr ""
#: src/keycode.cpp:226
msgid "Kanji"
msgstr ""
#: src/keycode.cpp:226
msgid "Nonconvert"
msgstr ""
#: src/keycode.cpp:227
msgid "Accept"
msgstr ""
#: src/keycode.cpp:227
msgid "End"
msgstr ""
#: src/keycode.cpp:227
msgid "Home"
msgstr ""
#: src/keycode.cpp:227
msgid "Mode Change"
msgstr ""
#: src/keycode.cpp:227
msgid "Next"
msgstr ""
#: src/keycode.cpp:227
msgid "Prior"
msgstr ""
#: src/keycode.cpp:227
msgid "Space"
msgstr ""
#: src/keycode.cpp:228
msgid "Down"
msgstr ""
#: src/keycode.cpp:228
msgid "Execute"
msgstr ""
#: src/keycode.cpp:228
msgid "Left"
msgstr ""
#: src/keycode.cpp:228
msgid "Print"
msgstr ""
#: src/keycode.cpp:228
msgid "Right"
msgstr ""
#: src/keycode.cpp:228
msgid "Select"
msgstr ""
#: src/keycode.cpp:228
msgid "Up"
msgstr ""
#: src/keycode.cpp:229
msgid "Help"
msgstr ""
#: src/keycode.cpp:229
msgid "Insert"
msgstr ""
#: src/keycode.cpp:229
msgid "Snapshot"
msgstr ""
#: src/keycode.cpp:232
msgid "Left Windows"
msgstr ""
#: src/keycode.cpp:233
msgid "Apps"
msgstr ""
#: src/keycode.cpp:233
msgid "Numpad 0"
msgstr ""
#: src/keycode.cpp:233
msgid "Numpad 1"
msgstr ""
#: src/keycode.cpp:233
msgid "Right Windows"
msgstr ""
#: src/keycode.cpp:233
msgid "Sleep"
msgstr ""
#: src/keycode.cpp:234
msgid "Numpad 2"
msgstr ""
#: src/keycode.cpp:234
msgid "Numpad 3"
msgstr ""
#: src/keycode.cpp:234
msgid "Numpad 4"
msgstr ""
#: src/keycode.cpp:234
msgid "Numpad 5"
msgstr ""
#: src/keycode.cpp:234
msgid "Numpad 6"
msgstr ""
#: src/keycode.cpp:234
msgid "Numpad 7"
msgstr ""
#: src/keycode.cpp:235
msgid "Numpad *"
msgstr ""
#: src/keycode.cpp:235
msgid "Numpad +"
msgstr ""
#: src/keycode.cpp:235
msgid "Numpad -"
msgstr ""
#: src/keycode.cpp:235
msgid "Numpad /"
msgstr ""
#: src/keycode.cpp:235
msgid "Numpad 8"
msgstr ""
#: src/keycode.cpp:235
msgid "Numpad 9"
msgstr ""
#: src/keycode.cpp:239
msgid "Num Lock"
msgstr ""
#: src/keycode.cpp:239
msgid "Scroll Lock"
msgstr ""
#: src/keycode.cpp:240
msgid "Left Shift"
msgstr ""
#: src/keycode.cpp:240
msgid "Right Shift"
msgstr ""
#: src/keycode.cpp:241
msgid "Left Control"
msgstr ""
#: src/keycode.cpp:241
msgid "Left Menu"
msgstr ""
#: src/keycode.cpp:241
msgid "Right Control"
msgstr ""
#: src/keycode.cpp:241
msgid "Right Menu"
msgstr ""
#: src/keycode.cpp:243
msgid "Comma"
msgstr ""
#: src/keycode.cpp:243
msgid "Minus"
msgstr ""
#: src/keycode.cpp:243
msgid "Period"
msgstr ""
#: src/keycode.cpp:243
msgid "Plus"
msgstr ""
#: src/keycode.cpp:247
msgid "Attn"
msgstr ""
#: src/keycode.cpp:247
msgid "CrSel"
msgstr ""
#: src/keycode.cpp:248
msgid "Erase OEF"
msgstr ""
#: src/keycode.cpp:248
msgid "ExSel"
msgstr ""
#: src/keycode.cpp:248
msgid "OEM Clear"
msgstr ""
#: src/keycode.cpp:248
msgid "PA1"
msgstr ""
#: src/keycode.cpp:248
msgid "Zoom"
msgstr ""
#: src/main.cpp:1384
msgid "Main Menu"
msgstr ""
#: src/main.cpp:1633
msgid "Failed to initialize world"
msgstr ""
#: src/main.cpp:1645
msgid "No world selected and no address provided. Nothing to do."
msgstr ""
#: src/main.cpp:1653
msgid "Could not find or load game \""
msgstr ""
#: src/main.cpp:1667
msgid "Invalid gamespec."
msgstr ""
#: src/main.cpp:1707
msgid "Connection error (timed out?)"
msgstr ""
#: src/main.cpp:1718
msgid ""
"\n"
"Check debug.txt for details."
msgstr ""

669
po/ru/minetest.po Normal file
View File

@ -0,0 +1,669 @@
# SOME DESCRIPTIVE TITLE.
# Copyright (C) YEAR THE PACKAGE'S COPYRIGHT HOLDER
# This file is distributed under the same license as the PACKAGE package.
# FIRST AUTHOR <EMAIL@ADDRESS>, YEAR.
#
#, fuzzy
msgid ""
msgstr ""
"Project-Id-Version: minetest\n"
"Report-Msgid-Bugs-To: \n"
"POT-Creation-Date: 2013-01-23 18:24+0200\n"
"PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n"
"Last-Translator: FULL NAME <EMAIL@ADDRESS>\n"
"Language-Team: LANGUAGE <LL@li.org>\n"
"Language: \n"
"MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=CHARSET\n"
"Content-Transfer-Encoding: 8bit\n"
#: src/guiConfigureWorld.cpp:127
msgid ""
"Warning: Some mods are not configured yet.\n"
"They will be enabled by default when you save the configuration. "
msgstr ""
#: src/guiConfigureWorld.cpp:146
msgid ""
"Warning: Some configured mods are missing.\n"
"Their setting will be removed when you save the configuration. "
msgstr ""
#: src/guiConfigureWorld.cpp:210
msgid "enabled"
msgstr ""
#: src/guiConfigureWorld.cpp:217
msgid "Enable All"
msgstr ""
#: src/guiConfigureWorld.cpp:224
msgid "Disable All"
msgstr ""
#: src/guiConfigureWorld.cpp:230
msgid "depends on:"
msgstr ""
#: src/guiConfigureWorld.cpp:242
msgid "is required by:"
msgstr ""
#: src/guiConfigureWorld.cpp:262 src/guiCreateWorld.cpp:165
#: src/guiKeyChangeMenu.cpp:179 src/keycode.cpp:223
msgid "Cancel"
msgstr ""
#: src/guiConfigureWorld.cpp:268 src/guiKeyChangeMenu.cpp:173
msgid "Save"
msgstr ""
#: src/guiConfigureWorld.cpp:394
msgid "Configuration saved. "
msgstr ""
#: src/guiConfigureWorld.cpp:402
msgid "Warning: Configuration not consistent. "
msgstr ""
#: src/guiConfirmMenu.cpp:120
msgid "Yes"
msgstr ""
#: src/guiConfirmMenu.cpp:126
msgid "No"
msgstr ""
#: src/guiCreateWorld.cpp:116
msgid "World name"
msgstr ""
#: src/guiCreateWorld.cpp:135
msgid "Game"
msgstr ""
#: src/guiCreateWorld.cpp:159
msgid "Create"
msgstr ""
#: src/guiDeathScreen.cpp:96
msgid "You died."
msgstr ""
#: src/guiDeathScreen.cpp:104
msgid "Respawn"
msgstr ""
#: src/guiFormSpecMenu.cpp:572
msgid "Left click: Move all items, Right click: Move single item"
msgstr ""
#: src/guiFormSpecMenu.cpp:597 src/guiMessageMenu.cpp:109
#: src/guiTextInputMenu.cpp:123
msgid "Proceed"
msgstr ""
#: src/guiKeyChangeMenu.cpp:114
msgid "Keybindings. (If this menu screws up, remove stuff from minetest.conf)"
msgstr ""
#: src/guiKeyChangeMenu.cpp:151
msgid "\"Use\" = climb down"
msgstr ""
#: src/guiKeyChangeMenu.cpp:164
msgid "Double tap \"jump\" to toggle fly"
msgstr ""
#: src/guiKeyChangeMenu.cpp:269
msgid "Key already in use"
msgstr ""
#: src/guiKeyChangeMenu.cpp:347
msgid "press key"
msgstr ""
#: src/guiMainMenu.cpp:55
msgid "Cannot create world: Name contains invalid characters"
msgstr ""
#: src/guiMainMenu.cpp:64
msgid "Cannot create world: A world by this name already exists"
msgstr ""
#: src/guiMainMenu.cpp:245
msgid "Singleplayer"
msgstr ""
#: src/guiMainMenu.cpp:246
msgid "Multiplayer"
msgstr ""
#: src/guiMainMenu.cpp:247
msgid "Advanced"
msgstr ""
#: src/guiMainMenu.cpp:248
msgid "Settings"
msgstr ""
#: src/guiMainMenu.cpp:249
msgid "Credits"
msgstr ""
#: src/guiMainMenu.cpp:280
msgid "Select World:"
msgstr ""
#: src/guiMainMenu.cpp:302 src/guiMainMenu.cpp:449 src/keycode.cpp:229
msgid "Delete"
msgstr ""
#: src/guiMainMenu.cpp:309
msgid "New"
msgstr ""
#: src/guiMainMenu.cpp:317
msgid "Configure"
msgstr ""
#: src/guiMainMenu.cpp:332 src/keycode.cpp:248
msgid "Play"
msgstr ""
#: src/guiMainMenu.cpp:343 src/guiMainMenu.cpp:557
msgid "Creative Mode"
msgstr ""
#: src/guiMainMenu.cpp:349 src/guiMainMenu.cpp:563
msgid "Enable Damage"
msgstr ""
#: src/guiMainMenu.cpp:369 src/guiMainMenu.cpp:479
msgid "Name/Password"
msgstr ""
#: src/guiMainMenu.cpp:408 src/guiMainMenu.cpp:506
msgid "Address/Port"
msgstr ""
#: src/guiMainMenu.cpp:435 src/guiMainMenu.cpp:1075
msgid "Show Public"
msgstr ""
#: src/guiMainMenu.cpp:439 src/guiMainMenu.cpp:1083
msgid "Show Favorites"
msgstr ""
#: src/guiMainMenu.cpp:459
msgid "Connect"
msgstr ""
#: src/guiMainMenu.cpp:529
msgid "Leave address blank to start a local server."
msgstr ""
#: src/guiMainMenu.cpp:538
msgid "Start Game / Connect"
msgstr ""
#: src/guiMainMenu.cpp:570 src/guiMainMenu.cpp:1006
msgid "Delete world"
msgstr ""
#: src/guiMainMenu.cpp:577
msgid "Create world"
msgstr ""
#: src/guiMainMenu.cpp:611
msgid "Fancy trees"
msgstr ""
#: src/guiMainMenu.cpp:617
msgid "Smooth Lighting"
msgstr ""
#: src/guiMainMenu.cpp:623
msgid "3D Clouds"
msgstr ""
#: src/guiMainMenu.cpp:629
msgid "Opaque water"
msgstr ""
#: src/guiMainMenu.cpp:639
msgid "Mip-Mapping"
msgstr ""
#: src/guiMainMenu.cpp:646
msgid "Anisotropic Filtering"
msgstr ""
#: src/guiMainMenu.cpp:653
msgid "Bi-Linear Filtering"
msgstr ""
#: src/guiMainMenu.cpp:660
msgid "Tri-Linear Filtering"
msgstr ""
#: src/guiMainMenu.cpp:668
msgid "Shaders"
msgstr ""
#: src/guiMainMenu.cpp:675
msgid "Preload item visuals"
msgstr ""
#: src/guiMainMenu.cpp:682
msgid "Enable Particles"
msgstr ""
#: src/guiMainMenu.cpp:692
msgid "Change keys"
msgstr ""
#: src/guiMainMenu.cpp:977
msgid "Address required."
msgstr ""
#: src/guiMainMenu.cpp:995
msgid "Cannot delete world: Nothing selected"
msgstr ""
#: src/guiMainMenu.cpp:1010
msgid "Files to be deleted"
msgstr ""
#: src/guiMainMenu.cpp:1026
msgid "Cannot create world: No games found"
msgstr ""
#: src/guiMainMenu.cpp:1042
msgid "Cannot configure world: Nothing selected"
msgstr ""
#: src/guiMainMenu.cpp:1146
msgid "Failed to delete all world files"
msgstr ""
#: src/guiPasswordChange.cpp:108
msgid "Old Password"
msgstr ""
#: src/guiPasswordChange.cpp:125
msgid "New Password"
msgstr ""
#: src/guiPasswordChange.cpp:141
msgid "Confirm Password"
msgstr ""
#: src/guiPasswordChange.cpp:158
msgid "Change"
msgstr ""
#: src/guiPasswordChange.cpp:167
msgid "Passwords do not match!"
msgstr ""
#: src/guiPauseMenu.cpp:118
msgid "Continue"
msgstr ""
#: src/guiPauseMenu.cpp:127
msgid "Change Password"
msgstr ""
#: src/guiPauseMenu.cpp:135
msgid "Exit to Menu"
msgstr ""
#: src/guiPauseMenu.cpp:142
msgid "Exit to OS"
msgstr ""
#: src/guiPauseMenu.cpp:149
msgid ""
"Default Controls:\n"
"- WASD: Walk\n"
"- Mouse left: dig/hit\n"
"- Mouse right: place/use\n"
"- Mouse wheel: select item\n"
"- 0...9: select item\n"
"- Shift: sneak\n"
"- R: Toggle viewing all loaded chunks\n"
"- I: Inventory menu\n"
"- ESC: This menu\n"
"- T: Chat\n"
msgstr ""
#: src/keycode.cpp:223
msgid "Left Button"
msgstr ""
#: src/keycode.cpp:223
msgid "Middle Button"
msgstr ""
#: src/keycode.cpp:223
msgid "Right Button"
msgstr ""
#: src/keycode.cpp:223
msgid "X Button 1"
msgstr ""
#: src/keycode.cpp:224
msgid "Back"
msgstr ""
#: src/keycode.cpp:224
msgid "Clear"
msgstr ""
#: src/keycode.cpp:224
msgid "Return"
msgstr ""
#: src/keycode.cpp:224
msgid "Tab"
msgstr ""
#: src/keycode.cpp:224
msgid "X Button 2"
msgstr ""
#: src/keycode.cpp:225
msgid "Capital"
msgstr ""
#: src/keycode.cpp:225
msgid "Control"
msgstr ""
#: src/keycode.cpp:225
msgid "Kana"
msgstr ""
#: src/keycode.cpp:225
msgid "Menu"
msgstr ""
#: src/keycode.cpp:225
msgid "Pause"
msgstr ""
#: src/keycode.cpp:225
msgid "Shift"
msgstr ""
#: src/keycode.cpp:226
msgid "Convert"
msgstr ""
#: src/keycode.cpp:226
msgid "Escape"
msgstr ""
#: src/keycode.cpp:226
msgid "Final"
msgstr ""
#: src/keycode.cpp:226
msgid "Junja"
msgstr ""
#: src/keycode.cpp:226
msgid "Kanji"
msgstr ""
#: src/keycode.cpp:226
msgid "Nonconvert"
msgstr ""
#: src/keycode.cpp:227
msgid "Accept"
msgstr ""
#: src/keycode.cpp:227
msgid "End"
msgstr ""
#: src/keycode.cpp:227
msgid "Home"
msgstr ""
#: src/keycode.cpp:227
msgid "Mode Change"
msgstr ""
#: src/keycode.cpp:227
msgid "Next"
msgstr ""
#: src/keycode.cpp:227
msgid "Prior"
msgstr ""
#: src/keycode.cpp:227
msgid "Space"
msgstr ""
#: src/keycode.cpp:228
msgid "Down"
msgstr ""
#: src/keycode.cpp:228
msgid "Execute"
msgstr ""
#: src/keycode.cpp:228
msgid "Left"
msgstr ""
#: src/keycode.cpp:228
msgid "Print"
msgstr ""
#: src/keycode.cpp:228
msgid "Right"
msgstr ""
#: src/keycode.cpp:228
msgid "Select"
msgstr ""
#: src/keycode.cpp:228
msgid "Up"
msgstr ""
#: src/keycode.cpp:229
msgid "Help"
msgstr ""
#: src/keycode.cpp:229
msgid "Insert"
msgstr ""
#: src/keycode.cpp:229
msgid "Snapshot"
msgstr ""
#: src/keycode.cpp:232
msgid "Left Windows"
msgstr ""
#: src/keycode.cpp:233
msgid "Apps"
msgstr ""
#: src/keycode.cpp:233
msgid "Numpad 0"
msgstr ""
#: src/keycode.cpp:233
msgid "Numpad 1"
msgstr ""
#: src/keycode.cpp:233
msgid "Right Windows"
msgstr ""
#: src/keycode.cpp:233
msgid "Sleep"
msgstr ""
#: src/keycode.cpp:234
msgid "Numpad 2"
msgstr ""
#: src/keycode.cpp:234
msgid "Numpad 3"
msgstr ""
#: src/keycode.cpp:234
msgid "Numpad 4"
msgstr ""
#: src/keycode.cpp:234
msgid "Numpad 5"
msgstr ""
#: src/keycode.cpp:234
msgid "Numpad 6"
msgstr ""
#: src/keycode.cpp:234
msgid "Numpad 7"
msgstr ""
#: src/keycode.cpp:235
msgid "Numpad *"
msgstr ""
#: src/keycode.cpp:235
msgid "Numpad +"
msgstr ""
#: src/keycode.cpp:235
msgid "Numpad -"
msgstr ""
#: src/keycode.cpp:235
msgid "Numpad /"
msgstr ""
#: src/keycode.cpp:235
msgid "Numpad 8"
msgstr ""
#: src/keycode.cpp:235
msgid "Numpad 9"
msgstr ""
#: src/keycode.cpp:239
msgid "Num Lock"
msgstr ""
#: src/keycode.cpp:239
msgid "Scroll Lock"
msgstr ""
#: src/keycode.cpp:240
msgid "Left Shift"
msgstr ""
#: src/keycode.cpp:240
msgid "Right Shift"
msgstr ""
#: src/keycode.cpp:241
msgid "Left Control"
msgstr ""
#: src/keycode.cpp:241
msgid "Left Menu"
msgstr ""
#: src/keycode.cpp:241
msgid "Right Control"
msgstr ""
#: src/keycode.cpp:241
msgid "Right Menu"
msgstr ""
#: src/keycode.cpp:243
msgid "Comma"
msgstr ""
#: src/keycode.cpp:243
msgid "Minus"
msgstr ""
#: src/keycode.cpp:243
msgid "Period"
msgstr ""
#: src/keycode.cpp:243
msgid "Plus"
msgstr ""
#: src/keycode.cpp:247
msgid "Attn"
msgstr ""
#: src/keycode.cpp:247
msgid "CrSel"
msgstr ""
#: src/keycode.cpp:248
msgid "Erase OEF"
msgstr ""
#: src/keycode.cpp:248
msgid "ExSel"
msgstr ""
#: src/keycode.cpp:248
msgid "OEM Clear"
msgstr ""
#: src/keycode.cpp:248
msgid "PA1"
msgstr ""
#: src/keycode.cpp:248
msgid "Zoom"
msgstr ""
#: src/main.cpp:1384
msgid "Main Menu"
msgstr ""
#: src/main.cpp:1633
msgid "Failed to initialize world"
msgstr ""
#: src/main.cpp:1645
msgid "No world selected and no address provided. Nothing to do."
msgstr ""
#: src/main.cpp:1653
msgid "Could not find or load game \""
msgstr ""
#: src/main.cpp:1667
msgid "Invalid gamespec."
msgstr ""
#: src/main.cpp:1707
msgid "Connection error (timed out?)"
msgstr ""
#: src/main.cpp:1718
msgid ""
"\n"
"Check debug.txt for details."
msgstr ""

View File

@ -188,6 +188,7 @@ set(common_SRCS
log.cpp
content_sao.cpp
mapgen.cpp
mapgen_v6.cpp
treegen.cpp
content_nodemeta.cpp
content_mapnode.cpp
@ -218,6 +219,7 @@ set(common_SRCS
sha1.cpp
base64.cpp
ban.cpp
biome.cpp
clientserver.cpp
staticobject.cpp
util/serialize.cpp
@ -262,6 +264,7 @@ set(minetest_SRCS
keycode.cpp
camera.cpp
clouds.cpp
particles.cpp
clientobject.cpp
chat.cpp
guiMainMenu.cpp
@ -274,11 +277,13 @@ set(minetest_SRCS
guiDeathScreen.cpp
guiChatConsole.cpp
guiCreateWorld.cpp
guiConfigureWorld.cpp
guiConfirmMenu.cpp
client.cpp
filecache.cpp
tile.cpp
shader.cpp
serverlist.cpp
game.cpp
main.cpp
)

233
src/biome.cpp Normal file
View File

@ -0,0 +1,233 @@
/*
Minetest-c55
Copyright (C) 2010-2011 kwolekr, Ryan Kwolek <kwolekr2@cs.scranton.edu>
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 "biome.h"
#include "nodedef.h"
#include "map.h" //for ManualMapVoxelManipulator
#include "log.h"
#include "main.h"
#define BT_NONE 0
#define BT_OCEAN 1
#define BT_LAKE 2
#define BT_SBEACH 3
#define BT_GBEACH 4
#define BT_PLAINS 5
#define BT_HILLS 6
#define BT_EXTREMEHILLS 7
#define BT_MOUNTAINS 8
#define BT_DESERT 9
#define BT_DESERTHILLS 10
#define BT_HELL 11
#define BT_AETHER 12
#define BT_BTMASK 0x3F
#define BTF_SNOW 0x40
#define BTF_FOREST 0x80
#define BGFREQ_1 ( 0.40)
#define BGFREQ_2 (BGFREQ_1 + 0.05)
#define BGFREQ_3 (BGFREQ_2 + 0.08)
#define BGFREQ_4 (BGFREQ_3 + 0.35)
#define BGFREQ_5 (BGFREQ_4 + 0.18)
//BGFREQ_5 is not checked as an upper bound; it ought to sum up to 1.00, but it's okay if it doesn't.
/*float bg1_temps[] = {0.0};
int bg1_biomes[] = {BT_OCEAN};
float bg2_temps[] = {10.0};
int bg2_biomes[] = {BT_GBEACH, BT_SBEACH};
float bg3_temps[] = {30.0, 40.0};
int bg3_biomes[] = {BT_HILLS, BT_EXTREMEHILLS, BT_MOUNTAINS};
float bg4_temps[] = {25.0, 30.0, 35.0, 40.0};
int bg4_biomes[] = {BT_HILLS, BT_EXTREMEHILLS, BT_MOUNTAINS, BT_DESERT, BT_DESERTHILLS};
float bg5_temps[] = {5.0, 40.0};
int bg5_biomes[] = {BT_LAKE, BT_PLAINS, BT_DESERT};*/
NoiseParams np_default = {20.0, 15.0, v3f(250., 250., 250.), 82341, 5, 0.6};
BiomeDefManager::BiomeDefManager(IGameDef *gamedef) {
this->m_gamedef = gamedef;
this->ndef = gamedef->ndef();
//the initial biome group
bgroups.push_back(new std::vector<Biome *>);
}
BiomeDefManager::~BiomeDefManager() {
for (unsigned int i = 0; i != bgroups.size(); i++)
delete bgroups[i];
}
Biome *BiomeDefManager::createBiome(BiomeTerrainType btt) {
switch (btt) {
case BIOME_TERRAIN_NORMAL:
return new Biome;
case BIOME_TERRAIN_LIQUID:
return new BiomeLiquid;
case BIOME_TERRAIN_NETHER:
return new BiomeHell;
case BIOME_TERRAIN_AETHER:
return new BiomeAether;
case BIOME_TERRAIN_FLAT:
return new BiomeSuperflat;
}
return NULL;
}
void BiomeDefManager::addBiomeGroup(float freq) {
int size = bgroup_freqs.size();
float newfreq = freq;
if (size)
newfreq += bgroup_freqs[size - 1];
bgroup_freqs.push_back(newfreq);
bgroups.push_back(new std::vector<Biome *>);
verbosestream << "BiomeDefManager: added biome group with frequency " <<
newfreq << std::endl;
}
void BiomeDefManager::addBiome(Biome *b) {
std::vector<Biome *> *bgroup;
if ((unsigned int)b->groupid >= bgroups.size()) {
errorstream << "BiomeDefManager: attempted to add biome '" << b->name
<< "' to nonexistent biome group " << b->groupid << std::endl;
return;
}
bgroup = bgroups[b->groupid];
bgroup->push_back(b);
verbosestream << "BiomeDefManager: added biome '" << b->name <<
"' to biome group " << b->groupid << std::endl;
}
void BiomeDefManager::addDefaultBiomes() {
Biome *b;
b = new Biome;
b->name = "Default";
b->n_top = MapNode(ndef->getId("mapgen_stone"));
b->n_filler = b->n_top;
b->ntopnodes = 0;
b->height_min = -MAP_GENERATION_LIMIT;
b->height_max = MAP_GENERATION_LIMIT;
b->heat_min = FLT_MIN;
b->heat_max = FLT_MAX;
b->humidity_min = FLT_MIN;
b->humidity_max = FLT_MAX;
b->np = &np_default;
biome_default = b;
}
Biome *BiomeDefManager::getBiome(float bgfreq, float heat, float humidity) {
std::vector<Biome *> *bgroup;
Biome *b;
int i;
int ngroups = bgroup_freqs.size();
if (!ngroups)
return biome_default;
for (i = 0; (i != ngroups) && (bgfreq > bgroup_freqs[i]); i++);
bgroup = bgroups[i];
int nbiomes = bgroup->size();
for (i = 0; i != nbiomes; i++) {
b = bgroup->operator[](i);
if (heat >= b->heat_min && heat <= b->heat_max &&
humidity >= b->humidity_min && humidity <= b->humidity_max)
return b;
}
return biome_default;
}
//////////////////////////// [ Generic biome ] ////////////////////////////////
int Biome::getSurfaceHeight(float noise_terrain) {
return np->offset + np->scale * noise_terrain;
}
void Biome::genColumn(Mapgen *mapgen, int x, int z, int y1, int y2) {
}
///////////////////////////// [ Ocean biome ] /////////////////////////////////
void BiomeLiquid::genColumn(Mapgen *mapgen, int x, int z, int y1, int y2) {
}
///////////////////////////// [ Nether biome ] /////////////////////////////////
int BiomeHell::getSurfaceHeight(float noise_terrain) {
return np->offset + np->scale * noise_terrain;
}
void BiomeHell::genColumn(Mapgen *mapgen, int x, int z, int y1, int y2) {
}
///////////////////////////// [ Aether biome ] ////////////////////////////////
int BiomeAether::getSurfaceHeight(float noise_terrain) {
return np->offset + np->scale * noise_terrain;
}
void BiomeAether::genColumn(Mapgen *mapgen, int x, int z, int y1, int y2) {
}
/////////////////////////// [ Superflat biome ] ///////////////////////////////
int BiomeSuperflat::getSurfaceHeight(float noise_terrain) {
return ntopnodes;
}
void BiomeSuperflat::genColumn(Mapgen *mapgen, int x, int z, int y1, int y2) {
}

98
src/biome.h Normal file
View File

@ -0,0 +1,98 @@
/*
Minetest-c55
Copyright (C) 2010-2011 kwolekr, Ryan Kwolek <kwolekr2@cs.scranton.edu>
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU Lesser General Public License as published by
the Free Software Foundation; either version 2.1 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU Lesser General Public License for more details.
You should have received a copy of the GNU Lesser General Public License along
with this program; if not, write to the Free Software Foundation, Inc.,
51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
*/
#ifndef BIOME_HEADER
#define BIOME_HEADER
#include <string>
#include "nodedef.h"
#include "gamedef.h"
#include "mapnode.h"
#include "noise.h"
#include "mapgen.h"
enum BiomeTerrainType
{
BIOME_TERRAIN_NORMAL,
BIOME_TERRAIN_LIQUID,
BIOME_TERRAIN_NETHER,
BIOME_TERRAIN_AETHER,
BIOME_TERRAIN_FLAT
};
class Biome {
public:
MapNode n_top;
MapNode n_filler;
s16 ntopnodes;
s8 groupid;
s8 flags;
s16 height_min;
s16 height_max;
float heat_min;
float heat_max;
float humidity_min;
float humidity_max;
std::string name;
NoiseParams *np;
virtual void genColumn(Mapgen *mg, int x, int z, int y1, int y2);
virtual int getSurfaceHeight(float noise_terrain);
};
class BiomeLiquid : public Biome {
virtual void genColumn(Mapgen *mg, int x, int z, int y1, int y2);
};
class BiomeHell : public Biome {
virtual void genColumn(Mapgen *mg, int x, int z, int y1, int y2);
virtual int getSurfaceHeight(float noise_terrain);
};
class BiomeAether : public Biome {
virtual void genColumn(Mapgen *mg, int x, int z, int y1, int y2);
virtual int getSurfaceHeight(float noise_terrain);
};
class BiomeSuperflat : public Biome {
virtual void genColumn(Mapgen *mg, int x, int z, int y1, int y2);
virtual int getSurfaceHeight(float noise_terrain);
};
class BiomeDefManager {
public:
std::vector<float> bgroup_freqs;
std::vector<std::vector<Biome *> *> bgroups;
Biome *biome_default;
IGameDef *m_gamedef;
INodeDefManager *ndef;
BiomeDefManager(IGameDef *gamedef);
~BiomeDefManager();
Biome *createBiome(BiomeTerrainType btt);
Biome *getBiome(float bgfreq, float heat, float humidity);
void addBiomeGroup(float freq);
void addBiome(Biome *b);
void addDefaultBiomes();
};
#endif

View File

@ -233,9 +233,12 @@ void Camera::update(LocalPlayer* player, f32 frametime, v2u32 screensize,
m_playernode->setRotation(v3f(0, -1 * player->getYaw(), 0));
m_playernode->updateAbsolutePosition();
//Get camera tilt timer (hurt animation)
float cameratilt = fabs(fabs(player->hurt_tilt_timer-0.75)-0.75);
// Set head node transformation
m_headnode->setPosition(player->getEyeOffset());
m_headnode->setRotation(v3f(player->getPitch(), 0, 0));
m_headnode->setPosition(player->getEyeOffset()+v3f(0,cameratilt*-player->hurt_tilt_strength,0));
m_headnode->setRotation(v3f(player->getPitch(), 0, cameratilt*player->hurt_tilt_strength));
m_headnode->updateAbsolutePosition();
// Compute relative camera position and target

View File

@ -1900,6 +1900,22 @@ void Client::ProcessData(u8 *data, u32 datasize, u16 sender_peer_id)
}
inv->deSerialize(is);
}
else if(command == TOCLIENT_SHOW_FORMSPEC)
{
std::string datastring((char*)&data[2], datasize-2);
std::istringstream is(datastring, std::ios_base::binary);
std::string formspec = deSerializeLongString(is);
std::string formname = deSerializeString(is);
ClientEvent event;
event.type = CE_SHOW_FORMSPEC;
// pointer is required as event is a struct only!
// adding a std:string to a struct isn't possible
event.show_formspec.formspec = new std::string(formspec);
event.show_formspec.formname = new std::string(formname);
m_client_event_queue.push_back(event);
}
else
{
infostream<<"Client: Ignoring unknown command "

View File

@ -34,6 +34,7 @@ with this program; if not, write to the Free Software Foundation, Inc.,
#include "filecache.h"
#include "localplayer.h"
#include "server.h"
#include "particles.h"
#include "util/pointedthing.h"
struct MeshMakeData;
@ -154,7 +155,8 @@ enum ClientEventType
CE_PLAYER_DAMAGE,
CE_PLAYER_FORCE_MOVE,
CE_DEATHSCREEN,
CE_TEXTURES_UPDATED
CE_TEXTURES_UPDATED,
CE_SHOW_FORMSPEC
};
struct ClientEvent
@ -176,6 +178,10 @@ struct ClientEvent
f32 camera_point_target_y;
f32 camera_point_target_z;
} deathscreen;
struct{
std::string* formspec;
std::string* formname;
} show_formspec;
struct{
} textures_updated;
};

View File

@ -77,9 +77,11 @@ SharedBuffer<u8> makePacket_TOCLIENT_TIME_OF_DAY(u16 time, float time_speed);
GENERIC_CMD_SET_ATTACHMENT
PROTOCOL_VERSION 15:
Serialization format changes
PROTOCOL_VERSION 16:
TOCLIENT_SHOW_FORMSPEC
*/
#define LATEST_PROTOCOL_VERSION 15
#define LATEST_PROTOCOL_VERSION 16
// Server's supported network protocol range
#define SERVER_PROTOCOL_VERSION_MIN 13
@ -354,6 +356,14 @@ enum ToClientCommand
u8[len] name
[2] serialized inventory
*/
TOCLIENT_SHOW_FORMSPEC = 0x44,
/*
[0] u16 command
u32 len
u8[len] formspec
u16 len
u8[len] formname
*/
};
enum ToServerCommand

View File

@ -45,8 +45,7 @@ Clouds::Clouds(
//m_material.MaterialType = video::EMT_TRANSPARENT_VERTEX_ALPHA;
m_material.MaterialType = video::EMT_TRANSPARENT_ALPHA_CHANNEL;
m_cloud_y = BS*100;
//m_cloud_y = BS*50;
m_cloud_y = BS * g_settings->getS16("cloud_height");
m_box = core::aabbox3d<f32>(-BS*1000000,m_cloud_y-BS,-BS*1000000,
BS*1000000,m_cloud_y+BS,BS*1000000);

View File

@ -37,7 +37,7 @@ public:
virtual std::set<std::string> getTriggerContents()
{
std::set<std::string> s;
s.insert("dirt");
s.insert("mapgen_dirt");
return s;
}
virtual float getTriggerInterval()
@ -54,7 +54,7 @@ public:
!ndef->get(n_top).isLiquid() &&
n_top.getLightBlend(env->getDayNightRatio(), ndef) >= 13)
{
n.setContent(ndef->getId("dirt_with_grass"));
n.setContent(ndef->getId("mapgen_dirt_with_grass"));
map->addNodeWithEvent(p, n);
}
}
@ -67,7 +67,7 @@ public:
virtual std::set<std::string> getTriggerContents()
{
std::set<std::string> s;
s.insert("dirt_with_grass");
s.insert("mapgen_dirt_with_grass");
return s;
}
virtual float getTriggerInterval()
@ -83,7 +83,7 @@ public:
if(!ndef->get(n_top).light_propagates ||
ndef->get(n_top).isLiquid())
{
n.setContent(ndef->getId("dirt"));
n.setContent(ndef->getId("mapgen_dirt"));
map->addNodeWithEvent(p, n);
}
}

View File

@ -56,6 +56,8 @@ void set_default_settings(Settings *settings)
settings->setDefault("anaglyph", "false");
settings->setDefault("anaglyph_strength", "0.1");
settings->setDefault("aux1_descends", "false");
settings->setDefault("doubletap_jump", "false");
settings->setDefault("always_fly_fast", "true");
// Some (temporary) keys for debugging
settings->setDefault("keymap_print_debug_stacks", "KEY_KEY_P");
@ -105,6 +107,7 @@ void set_default_settings(Settings *settings)
settings->setDefault("screenshot_path", ".");
settings->setDefault("view_bobbing_amount", "1.0");
settings->setDefault("enable_3d_clouds", "true");
settings->setDefault("cloud_height", "120");
settings->setDefault("opaque_water", "false");
settings->setDefault("console_color", "(0,0,0)");
settings->setDefault("console_alpha", "200");
@ -121,9 +124,14 @@ void set_default_settings(Settings *settings)
settings->setDefault("trilinear_filter", "false");
settings->setDefault("preload_item_visuals", "true");
settings->setDefault("enable_shaders", "2");
settings->setDefault("repeat_rightclick_time", "0.25");
settings->setDefault("enable_particles", "true");
settings->setDefault("media_fetch_threads", "8");
settings->setDefault("serverlist_url", "servers.minetest.ru/server.list");
settings->setDefault("serverlist_file", "favoriteservers.txt");
// Server stuff
// "map-dir" doesn't exist by default.
settings->setDefault("default_game", "minetest");
@ -164,5 +172,28 @@ void set_default_settings(Settings *settings)
settings->setDefault("congestion_control_max_rate", "400");
settings->setDefault("congestion_control_min_rate", "10");
settings->setDefault("remote_media", "");
//mapgen related things
settings->setDefault("mg_name", "v6");
settings->setDefault("water_level", "1");
settings->setDefault("chunksize", "5");
settings->setDefault("mg_flags", "19");
settings->setDefault("mgv6_freq_desert", "0.45");
settings->setDefault("mgv6_freq_beach", "0.15");
settings->setDefault("mgv6_np_terrain_base", "-4, 20, (250.0, 250, 250), 82341, 5, 0.6");
settings->setDefault("mgv6_np_terrain_higher", "20, 16, (500, 500, 500), 85039, 5, 0.6");
settings->setDefault("mgv6_np_steepness", "0.85, 0.5, (125, 125, 125), -932, 5, 0.7");
settings->setDefault("mgv6_np_height_select", "0.5, 1, (250, 250, 250), 4213, 5, 0.69");
settings->setDefault("mgv6_np_trees", "0, 1, (125, 125, 125), 2, 4, 0.66");
settings->setDefault("mgv6_np_mud", "4, 2, (200, 200, 200), 91013, 3, 0.55");
settings->setDefault("mgv6_np_beach", "0, 1, (250, 250, 250), 59420, 3, 0.50");
settings->setDefault("mgv6_np_biome", "0, 1, (250, 250, 250), 9130, 3, 0.50");
settings->setDefault("mgv6_np_cave", "6, 6, (250, 250, 250), 34329, 3, 0.50");
settings->setDefault("mgv7_np_terrain", "10, 12, (350, 350, 350), 82341, 5, 0.6");
settings->setDefault("mgv7_np_bgroup", "0.5, 0.3125, (350, 350, 350), 5923, 2, 0.6");
settings->setDefault("mgv7_np_heat", "25, 50, (500, 500, 500), 35293, 1, 0");
settings->setDefault("mgv7_np_humidity", "50, 31.25, (750, 750, 750), 12094, 2, 0.6");
}

View File

@ -804,7 +804,8 @@ void ServerEnvironment::activateBlock(MapBlock *block, u32 additional_dtime)
i = elapsed_timers.begin();
i != elapsed_timers.end(); i++){
n = block->getNodeNoEx(i->first);
if(scriptapi_node_on_timer(m_lua,i->first,n,i->second.elapsed))
v3s16 p = i->first + block->getPosRelative();
if(scriptapi_node_on_timer(m_lua,p,n,i->second.elapsed))
block->setNodeTimer(i->first,NodeTimer(i->second.timeout,0));
}
}
@ -819,6 +820,45 @@ void ServerEnvironment::addActiveBlockModifier(ActiveBlockModifier *abm)
m_abms.push_back(ABMWithState(abm));
}
bool ServerEnvironment::setNode(v3s16 p, const MapNode &n)
{
INodeDefManager *ndef = m_gamedef->ndef();
MapNode n_old = m_map->getNodeNoEx(p);
// Call destructor
if(ndef->get(n_old).has_on_destruct)
scriptapi_node_on_destruct(m_lua, p, n_old);
// Replace node
bool succeeded = m_map->addNodeWithEvent(p, n);
if(!succeeded)
return false;
// Call post-destructor
if(ndef->get(n_old).has_after_destruct)
scriptapi_node_after_destruct(m_lua, p, n_old);
// Call constructor
if(ndef->get(n).has_on_construct)
scriptapi_node_on_construct(m_lua, p, n);
return true;
}
bool ServerEnvironment::removeNode(v3s16 p)
{
INodeDefManager *ndef = m_gamedef->ndef();
MapNode n_old = m_map->getNodeNoEx(p);
// Call destructor
if(ndef->get(n_old).has_on_destruct)
scriptapi_node_on_destruct(m_lua, p, n_old);
// Replace with air
// This is slightly optimized compared to addNodeWithEvent(air)
bool succeeded = m_map->removeNodeWithEvent(p);
if(!succeeded)
return false;
// Call post-destructor
if(ndef->get(n_old).has_after_destruct)
scriptapi_node_after_destruct(m_lua, p, n_old);
// Air doesn't require constructor
return true;
}
std::set<u16> ServerEnvironment::getObjectsInsideRadius(v3f pos, float radius)
{
std::set<u16> objects;
@ -1261,6 +1301,7 @@ u16 ServerEnvironment::addActiveObject(ServerActiveObject *object)
return id;
}
#if 0
bool ServerEnvironment::addActiveObjectAsStatic(ServerActiveObject *obj)
{
assert(obj);
@ -1303,6 +1344,7 @@ bool ServerEnvironment::addActiveObjectAsStatic(ServerActiveObject *obj)
return succeeded;
}
#endif
/*
Finds out what new objects have been added to
@ -1523,13 +1565,15 @@ void ServerEnvironment::removeRemovedObjects()
*/
if(obj->m_static_exists && obj->m_removed)
{
MapBlock *block = m_map->emergeBlock(obj->m_static_block);
if(block)
{
MapBlock *block = m_map->emergeBlock(obj->m_static_block, false);
if (block) {
block->m_static_objects.remove(id);
block->raiseModified(MOD_STATE_WRITE_NEEDED,
"removeRemovedObjects");
obj->m_static_exists = false;
} else {
infostream << "failed to emerge block from which "
"an object to be removed was loaded from. id="<<id<<std::endl;
}
}
@ -1677,6 +1721,8 @@ void ServerEnvironment::activateObjects(MapBlock *block, u32 dtime_s)
If force_delete is set, active object is deleted nevertheless. It
shall only be set so in the destructor of the environment.
If block wasn't generated (not in memory or on disk),
*/
void ServerEnvironment::deactivateFarObjects(bool force_delete)
{

View File

@ -241,8 +241,9 @@ public:
MapBlock.
Caller allocates memory, ServerEnvironment frees memory.
Return value: true if succeeded, false if failed.
(note: not used, pending removal from engine)
*/
bool addActiveObjectAsStatic(ServerActiveObject *object);
//bool addActiveObjectAsStatic(ServerActiveObject *object);
/*
Find out what new objects have been added to
@ -284,6 +285,10 @@ public:
-------------------------------------------
*/
// Script-aware node setters
bool setNode(v3s16 p, const MapNode &n);
bool removeNode(v3s16 p);
// Find all active objects inside a radius around a point
std::set<u16> getObjectsInsideRadius(v3f pos, float radius);

View File

@ -120,14 +120,14 @@ HeightPoint ground_height(u64 seed, v2s16 p2d)
if(n)
return n->getValue();
HeightPoint hp;
s16 level = mapgen::find_ground_level_from_noise(seed, p2d, 3);
s16 level = Mapgen::find_ground_level_from_noise(seed, p2d, 3);
hp.gh = (level-4)*BS;
hp.ma = (4)*BS;
/*hp.gh = BS*base_rock_level_2d(seed, p2d);
hp.ma = BS*get_mud_add_amount(seed, p2d);*/
hp.have_sand = mapgen::get_have_beach(seed, p2d);
hp.have_sand = Mapgen::get_have_beach(seed, p2d);
if(hp.gh > BS*WATER_LEVEL)
hp.tree_amount = mapgen::tree_amount_2d(seed, p2d);
hp.tree_amount = Mapgen::tree_amount_2d(seed, p2d);
else
hp.tree_amount = 0;
// No mud has been added if mud amount is less than 1

View File

@ -36,6 +36,7 @@ with this program; if not, write to the Free Software Foundation, Inc.,
#include "guiChatConsole.h"
#include "config.h"
#include "clouds.h"
#include "particles.h"
#include "camera.h"
#include "farmesh.h"
#include "mapblock.h"
@ -118,13 +119,20 @@ struct TextDestPlayerInventory : public TextDest
TextDestPlayerInventory(Client *client)
{
m_client = client;
m_formname = "";
}
TextDestPlayerInventory(Client *client, std::string formname)
{
m_client = client;
m_formname = formname;
}
void gotText(std::map<std::string, std::string> fields)
{
m_client->sendInventoryFields("", fields);
m_client->sendInventoryFields(m_formname, fields);
}
Client *m_client;
std::string m_formname;
};
/* Respawn menu callback */
@ -192,6 +200,32 @@ public:
Client *m_client;
};
class FormspecFormSource: public IFormSource
{
public:
FormspecFormSource(std::string formspec,FormspecFormSource** game_formspec)
{
m_formspec = formspec;
m_game_formspec = game_formspec;
}
~FormspecFormSource()
{
*m_game_formspec = 0;
}
void setForm(std::string formspec) {
m_formspec = formspec;
}
std::string getForm()
{
return m_formspec;
}
std::string m_formspec;
FormspecFormSource** m_game_formspec;
};
/*
Hotbar draw routine
*/
@ -901,6 +935,7 @@ void the_game(
bool simple_singleplayer_mode
)
{
FormspecFormSource* current_formspec = 0;
video::IVideoDriver* driver = device->getVideoDriver();
scene::ISceneManager* smgr = device->getSceneManager();
@ -1280,9 +1315,12 @@ void the_game(
bool digging = false;
bool ldown_for_dig = false;
float damage_flash_timer = 0;
float damage_flash = 0;
s16 farmesh_range = 20*MAP_BLOCKSIZE;
float jump_timer = 0;
bool reset_jump_timer = false;
const float object_hit_delay = 0.2;
float object_hit_delay_timer = 0.0;
float time_from_last_punch = 10;
@ -1308,6 +1346,8 @@ void the_game(
float time_of_day = 0;
float time_of_day_smooth = 0;
float repeat_rightclick_timer = 0;
/*
Shader constants
*/
@ -1329,6 +1369,10 @@ void the_game(
// NOTE: So we have to use getTime() and call run()s between them
u32 lasttime = device->getTimer()->getTime();
LocalPlayer* player = client.getEnv().getLocalPlayer();
player->hurt_tilt_timer = 0;
player->hurt_tilt_strength = 0;
for(;;)
{
if(device->run() == false || kill == true)
@ -1559,6 +1603,10 @@ void the_game(
// Input handler step() (used by the random input generator)
input->step(dtime);
// Increase timer for doubleclick of "jump"
if(g_settings->getBool("doubletap_jump") && jump_timer <= 0.2)
jump_timer += dtime;
/*
Launch menus and trigger stuff according to keys
*/
@ -1648,6 +1696,27 @@ void the_game(
statustext += L" (note: no 'fly' privilege)";
}
}
else if(input->wasKeyDown(getKeySetting("keymap_jump")))
{
if(g_settings->getBool("doubletap_jump") && jump_timer < 0.2)
{
if(g_settings->getBool("free_move"))
{
g_settings->set("free_move","false");
statustext = L"free_move disabled";
statustext_time = 0;
}
else
{
g_settings->set("free_move","true");
statustext = L"free_move enabled";
statustext_time = 0;
if(!client.checkPrivilege("fly"))
statustext += L" (note: no 'fly' privilege)";
}
}
reset_jump_timer = true;
}
else if(input->wasKeyDown(getKeySetting("keymap_fastmove")))
{
if(g_settings->getBool("fast_move"))
@ -1810,6 +1879,13 @@ void the_game(
statustext_time = 0;
}
// Reset jump_timer
if(!input->isKeyDown(getKeySetting("keymap_jump")) && reset_jump_timer)
{
reset_jump_timer = false;
jump_timer = 0.0;
}
// Handle QuicktuneShortcutter
if(input->wasKeyDown(getKeySetting("keymap_quicktune_next")))
quicktune.next();
@ -2024,14 +2100,18 @@ void the_game(
{
break;
}
else if(event.type == CE_PLAYER_DAMAGE)
else if(event.type == CE_PLAYER_DAMAGE &&
client.getHP() != 0)
{
//u16 damage = event.player_damage.amount;
//infostream<<"Player damage: "<<damage<<std::endl;
damage_flash_timer = 0.05;
if(event.player_damage.amount >= 2){
damage_flash_timer += 0.05 * event.player_damage.amount;
}
damage_flash += 100.0;
damage_flash += 8.0 * event.player_damage.amount;
player->hurt_tilt_timer = 1.5;
player->hurt_tilt_strength = event.player_damage.amount/2;
player->hurt_tilt_strength = rangelim(player->hurt_tilt_strength, 2.0, 10.0);
}
else if(event.type == CE_PLAYER_FORCE_MOVE)
{
@ -2061,12 +2141,39 @@ void the_game(
/* Handle visualization */
damage_flash_timer = 0;
damage_flash = 0;
LocalPlayer* player = client.getEnv().getLocalPlayer();
player->hurt_tilt_timer = 0;
player->hurt_tilt_strength = 0;
/*LocalPlayer* player = client.getLocalPlayer();
player->setPosition(player->getPosition() + v3f(0,-BS,0));
camera.update(player, busytime, screensize);*/
}
else if (event.type == CE_SHOW_FORMSPEC)
{
if (current_formspec == 0)
{
/* Create menu */
current_formspec = new FormspecFormSource(*(event.show_formspec.formspec),&current_formspec);
GUIFormSpecMenu *menu =
new GUIFormSpecMenu(device, guiroot, -1,
&g_menumgr,
&client, gamedef);
menu->setFormSource(current_formspec);
menu->setTextDest(new TextDestPlayerInventory(&client,*(event.show_formspec.formname)));
menu->drop();
}
else
{
/* update menu */
current_formspec->setForm(*(event.show_formspec.formspec));
}
delete(event.show_formspec.formspec);
delete(event.show_formspec.formname);
}
else if(event.type == CE_TEXTURES_UPDATED)
{
update_wielded_item_trigger = true;
@ -2207,6 +2314,11 @@ void the_game(
bool left_punch = false;
soundmaker.m_player_leftpunch_sound.name = "";
if(input->getRightState())
repeat_rightclick_timer += dtime;
else
repeat_rightclick_timer = 0;
if(playeritem_usable && input->getLeftState())
{
if(input->getLeftClicked())
@ -2290,6 +2402,13 @@ void the_game(
else
{
dig_time_complete = params.time;
if (g_settings->getBool("enable_particles"))
{
const ContentFeatures &features =
client.getNodeDefManager()->get(n);
addPunchingParticles
(gamedef, smgr, player, nodepos, features.tiles);
}
}
if(dig_time_complete >= 0.001)
@ -2321,6 +2440,14 @@ void the_game(
MapNode wasnode = map.getNode(nodepos);
client.removeNode(nodepos);
if (g_settings->getBool("enable_particles"))
{
const ContentFeatures &features =
client.getNodeDefManager()->get(wasnode);
addDiggingParticles
(gamedef, smgr, player, nodepos, features.tiles);
}
dig_time = 0;
digging = false;
@ -2347,13 +2474,17 @@ void the_game(
camera.setDigging(0); // left click animation
}
if(input->getRightClicked())
if(input->getRightClicked() ||
repeat_rightclick_timer >= g_settings->getFloat("repeat_rightclick_time"))
{
repeat_rightclick_timer = 0;
infostream<<"Ground right-clicked"<<std::endl;
// Sign special case, at least until formspec is properly implemented.
// Deprecated?
if(meta && meta->getString("formspec") == "hack:sign_text_input" && !random_input)
if(meta && meta->getString("formspec") == "hack:sign_text_input"
&& !random_input
&& !input->isKeyDown(getKeySetting("keymap_sneak")))
{
infostream<<"Launching metadata text input"<<std::endl;
@ -2368,7 +2499,8 @@ void the_game(
wtext))->drop();
}
// If metadata provides an inventory view, activate it
else if(meta && meta->getString("formspec") != "" && !random_input)
else if(meta && meta->getString("formspec") != "" && !random_input
&& !input->isKeyDown(getKeySetting("keymap_sneak")))
{
infostream<<"Launching custom inventory view"<<std::endl;
@ -2588,6 +2720,12 @@ void the_game(
brightness, farmesh_range);
}
/*
Update particles
*/
allparticles_step(dtime, client.getEnv());
/*
Fog
*/
@ -3001,14 +3139,24 @@ void the_game(
/*
Damage flash
*/
if(damage_flash_timer > 0.0)
if(damage_flash > 0.0)
{
damage_flash_timer -= dtime;
video::SColor color(128,255,0,0);
video::SColor color(std::min(damage_flash, 180.0f),180,0,0);
driver->draw2DRectangle(color,
core::rect<s32>(0,0,screensize.X,screensize.Y),
NULL);
damage_flash -= 100.0*dtime;
}
/*
Damage camera tilt
*/
if(player->hurt_tilt_timer > 0.0)
{
player->hurt_tilt_timer -= dtime*5;
if(player->hurt_tilt_timer < 0)
player->hurt_tilt_strength = 0;
}
/*

686
src/guiConfigureWorld.cpp Normal file
View File

@ -0,0 +1,686 @@
/*
Minetest-c55
Copyright (C) 2012 celeron55, Perttu Ahola <celeron55@gmail.com>
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 <iostream>
#include <string>
#include <map>
#include "guiConfigureWorld.h"
#include "guiMessageMenu.h"
#include <IGUIButton.h>
#include <IGUICheckBox.h>
#include <IGUIListBox.h>
#include <IGUIStaticText.h>
#include <IGUITreeView.h>
#include "gettext.h"
#include "util/string.h"
#include "settings.h"
#include "filesys.h"
enum
{
GUI_ID_MOD_TREEVIEW = 101,
GUI_ID_ENABLED_CHECKBOX,
GUI_ID_ENABLEALL,
GUI_ID_DISABLEALL,
GUI_ID_DEPENDS_LISTBOX,
GUI_ID_RDEPENDS_LISTBOX,
GUI_ID_CANCEL,
GUI_ID_SAVE
};
#define QUESTIONMARK_STR L"?"
#define CHECKMARK_STR L"\411"
#define CROSS_STR L"\403"
GUIConfigureWorld::GUIConfigureWorld(gui::IGUIEnvironment* env,
gui::IGUIElement* parent, s32 id,
IMenuManager *menumgr, WorldSpec wspec):
GUIModalMenu(env, parent, id, menumgr),
m_wspec(wspec),
m_gspec(findWorldSubgame(m_wspec.path)),
m_menumgr(menumgr)
{
//will be initialized in regenerateGUI()
m_treeview=NULL;
// game mods
m_gamemods = flattenModTree(getModsInPath(m_gspec.gamemods_path));
// world mods
std::string worldmods_path = wspec.path + DIR_DELIM + "worldmods";
m_worldmods = flattenModTree(getModsInPath(worldmods_path));
// fill m_addontree with add-on mods
std::set<std::string> paths = m_gspec.addon_mods_paths;
for(std::set<std::string>::iterator it=paths.begin();
it != paths.end(); ++it)
{
std::map<std::string,ModSpec> mods = getModsInPath(*it);
m_addontree.insert(mods.begin(), mods.end());
}
// expand modpacks
m_addonmods = flattenModTree(m_addontree);
// collect reverse dependencies
for(std::map<std::string, ModSpec>::iterator it = m_addonmods.begin();
it != m_addonmods.end(); ++it)
{
std::string modname = (*it).first;
ModSpec mod = (*it).second;
for(std::set<std::string>::iterator dep_it = mod.depends.begin();
dep_it != mod.depends.end(); ++dep_it)
{
m_reverse_depends.insert(std::make_pair((*dep_it),modname));
}
}
m_settings.readConfigFile((m_wspec.path + DIR_DELIM + "world.mt").c_str());
std::vector<std::string> names = m_settings.getNames();
// mod_names contains the names of mods mentioned in the world.mt file
std::set<std::string> mod_names;
for(std::vector<std::string>::iterator it = names.begin();
it != names.end(); ++it)
{
std::string name = *it;
if (name.compare(0,9,"load_mod_")==0)
mod_names.insert(name.substr(9));
}
// find new mods (installed but not mentioned in world.mt)
for(std::map<std::string, ModSpec>::iterator it = m_addonmods.begin();
it != m_addonmods.end(); ++it)
{
std::string modname = (*it).first;
ModSpec mod = (*it).second;
// a mod is new if it is not a modpack, and does not occur in
// mod_names
if(!mod.is_modpack &&
mod_names.count(modname) == 0)
m_new_mod_names.insert(modname);
}
if(!m_new_mod_names.empty())
{
GUIMessageMenu *menu =
new GUIMessageMenu(Environment, Parent, -1, m_menumgr,
wgettext("Warning: Some mods are not configured yet.\n"
"They will be enabled by default when you save the configuration. "));
menu->drop();
}
// find missing mods (mentioned in world.mt, but not installed)
std::set<std::string> missing_mods;
for(std::set<std::string>::iterator it = mod_names.begin();
it != mod_names.end(); ++it)
{
std::string modname = *it;
if(m_addonmods.count(modname) == 0)
missing_mods.insert(modname);
}
if(!missing_mods.empty())
{
GUIMessageMenu *menu =
new GUIMessageMenu(Environment, Parent, -1, m_menumgr,
wgettext("Warning: Some configured mods are missing.\n"
"Their setting will be removed when you save the configuration. "));
for(std::set<std::string>::iterator it = missing_mods.begin();
it != missing_mods.end(); ++it)
m_settings.remove("load_mod_"+(*it));
menu->drop();
}
}
void GUIConfigureWorld::drawMenu()
{
gui::IGUISkin* skin = Environment->getSkin();
if (!skin)
return;
video::IVideoDriver* driver = Environment->getVideoDriver();
video::SColor bgcolor(140,0,0,0);
driver->draw2DRectangle(bgcolor, AbsoluteRect, &AbsoluteClippingRect);
gui::IGUIElement::draw();
}
void GUIConfigureWorld::regenerateGui(v2u32 screensize)
{
/*
Remove stuff
*/
removeChildren();
/*
Calculate new sizes and positions
*/
core::rect<s32> rect(
screensize.X/2 - 580/2,
screensize.Y/2 - 300/2,
screensize.X/2 + 580/2,
screensize.Y/2 + 300/2
);
DesiredRect = rect;
recalculateAbsolutePosition(false);
v2s32 size = rect.getSize();
v2s32 topleft = v2s32(10, 10);
/*
Add stuff
*/
changeCtype("");
{
core::rect<s32> rect(0, 0, 200, 20);
rect += topleft;
//proper text is set below, when a mod is selected
m_modname_text = Environment->addStaticText(L"Mod: N/A", rect, false,
false, this, -1);
}
{
core::rect<s32> rect(0, 0, 200, 20);
rect += v2s32(0, 25) + topleft;
m_enabled_checkbox =
Environment->addCheckBox(false, rect, this, GUI_ID_ENABLED_CHECKBOX,
wgettext("enabled"));
m_enabled_checkbox->setVisible(false);
}
{
core::rect<s32> rect(0, 0, 85, 30);
rect = rect + v2s32(0, 25) + topleft;
m_enableall = Environment->addButton(rect, this, GUI_ID_ENABLEALL,
wgettext("Enable All"));
m_enableall->setVisible(false);
}
{
core::rect<s32> rect(0, 0, 85, 30);
rect = rect + v2s32(115, 25) + topleft;
m_disableall = Environment->addButton(rect, this, GUI_ID_DISABLEALL,
wgettext("Disable All"));
m_disableall->setVisible(false);
}
{
core::rect<s32> rect(0, 0, 200, 20);
rect += v2s32(0, 60) + topleft;
Environment->addStaticText(wgettext("depends on:"),
rect, false, false, this, -1);
}
{
core::rect<s32> rect(0, 0, 200, 85);
rect += v2s32(0, 80) + topleft;
m_dependencies_listbox =
Environment->addListBox(rect, this, GUI_ID_DEPENDS_LISTBOX, true);
}
{
core::rect<s32> rect(0, 0, 200, 20);
rect += v2s32(0, 175) + topleft;
Environment->addStaticText(wgettext("is required by:"),
rect, false, false, this, -1);
}
{
core::rect<s32> rect(0, 0, 200, 85);
rect += v2s32(0, 195) + topleft;
m_rdependencies_listbox =
Environment->addListBox(rect,this, GUI_ID_RDEPENDS_LISTBOX,true);
}
{
core::rect<s32> rect(0, 0, 340, 250);
rect += v2s32(220, 0) + topleft;
m_treeview = Environment->addTreeView(rect, this,
GUI_ID_MOD_TREEVIEW,true);
gui::IGUITreeViewNode* node
= m_treeview->getRoot()->addChildBack(L"Add-Ons");
buildTreeView(m_addontree, node);
}
{
core::rect<s32> rect(0, 0, 120, 30);
rect = rect + v2s32(330, 270) - topleft;
Environment->addButton(rect, this, GUI_ID_CANCEL,
wgettext("Cancel"));
}
{
core::rect<s32> rect(0, 0, 120, 30);
rect = rect + v2s32(460, 270) - topleft;
Environment->addButton(rect, this, GUI_ID_SAVE,
wgettext("Save"));
}
changeCtype("C");
// at start, none of the treeview nodes is selected, so we select
// the first element in the treeview of mods manually here.
if(m_treeview->getRoot()->hasChilds())
{
m_treeview->getRoot()->getFirstChild()->setExpanded(true);
m_treeview->getRoot()->getFirstChild()->setSelected(true);
// Because a manual ->setSelected() doesn't cause an event, we
// have to do this here:
adjustSidebar();
}
}
bool GUIConfigureWorld::OnEvent(const SEvent& event)
{
gui::IGUITreeViewNode* selected_node = NULL;
if(m_treeview != NULL)
selected_node = m_treeview->getSelected();
if(event.EventType==EET_KEY_INPUT_EVENT && event.KeyInput.PressedDown)
{
switch (event.KeyInput.Key) {
case KEY_ESCAPE: {
quitMenu();
return true;
}
// irrlicht's built-in TreeView gui has no keyboard control,
// so we do it here: up/down to select prev/next node,
// left/right to collapse/expand nodes, space to toggle
// enabled/disabled.
case KEY_DOWN: {
if(selected_node != NULL)
{
gui::IGUITreeViewNode* node = selected_node->getNextVisible();
if(node != NULL)
{
node->setSelected(true);
adjustSidebar();
}
}
return true;
}
case KEY_UP: {
if(selected_node != NULL)
{
gui::IGUITreeViewNode* node = selected_node->getPrevSibling();
if(node!=NULL)
{
node->setSelected(true);
adjustSidebar();
}
else
{
gui::IGUITreeViewNode* parent = selected_node->getParent();
if(selected_node == parent->getFirstChild() &&
parent != m_treeview->getRoot())
{
parent->setSelected(true);
adjustSidebar();
}
}
}
return true;
}
case KEY_RIGHT: {
if(selected_node != NULL && selected_node->hasChilds())
selected_node->setExpanded(true);
return true;
}
case KEY_LEFT: {
if(selected_node != NULL && selected_node->hasChilds())
selected_node->setExpanded(false);
return true;
}
case KEY_SPACE: {
if(selected_node != NULL && !selected_node->hasChilds() &&
selected_node->getText() != NULL)
{
std::string modname = wide_to_narrow(selected_node->getText());
bool checked = m_enabled_checkbox->isChecked();
m_enabled_checkbox->setChecked(!checked);
setEnabled(modname,!checked);
}
return true;
}
default: {}
}
}
if(event.EventType==EET_GUI_EVENT)
{
if(event.GUIEvent.EventType==gui::EGET_ELEMENT_FOCUS_LOST
&& isVisible())
{
if(!canTakeFocus(event.GUIEvent.Element))
{
dstream<<"GUIConfigureWorld: Not allowing focus change."
<<std::endl;
// Returning true disables focus change
return true;
}
}
if(event.GUIEvent.EventType==gui::EGET_BUTTON_CLICKED){
switch(event.GUIEvent.Caller->getID()){
case GUI_ID_CANCEL: {
quitMenu();
return true;
}
case GUI_ID_SAVE: {
for(std::set<std::string>::iterator it = m_new_mod_names.begin();
it!= m_new_mod_names.end(); ++it)
{
m_settings.setBool("load_mod_"+(*it),true);
}
std::string worldmtfile = m_wspec.path+DIR_DELIM+"world.mt";
m_settings.updateConfigFile(worldmtfile.c_str());
// The trailing spaces are because there seems to be a
// bug in the text-size calculation. if the trailing
// spaces are removed from the message text, the
// message gets wrapped and parts of it are cut off:
GUIMessageMenu *menu =
new GUIMessageMenu(Environment, Parent, -1, m_menumgr,
wgettext("Configuration saved. "));
menu->drop();
ModConfiguration modconf(m_wspec.path);
if(!modconf.isConsistent())
{
GUIMessageMenu *menu =
new GUIMessageMenu(Environment, Parent, -1, m_menumgr,
wgettext("Warning: Configuration not consistent. "));
menu->drop();
}
quitMenu();
return true;
}
case GUI_ID_ENABLEALL: {
if(selected_node != NULL && selected_node->getParent() == m_treeview->getRoot())
{
enableAllMods(m_addonmods,true);
}
else if(selected_node != NULL && selected_node->getText() != NULL)
{
std::string modname = wide_to_narrow(selected_node->getText());
ModSpec mod = m_addonmods[modname];
enableAllMods(mod.modpack_content,true);
}
return true;
}
case GUI_ID_DISABLEALL: {
if(selected_node != NULL && selected_node->getParent() == m_treeview->getRoot())
{
enableAllMods(m_addonmods,false);
}
if(selected_node != NULL && selected_node->getText() != NULL)
{
std::string modname = wide_to_narrow(selected_node->getText());
ModSpec mod = m_addonmods[modname];
enableAllMods(mod.modpack_content,false);
}
return true;
}
}
}
if(event.GUIEvent.EventType==gui::EGET_CHECKBOX_CHANGED &&
event.GUIEvent.Caller->getID() == GUI_ID_ENABLED_CHECKBOX)
{
if(selected_node != NULL && !selected_node->hasChilds() &&
selected_node->getText() != NULL)
{
std::string modname = wide_to_narrow(selected_node->getText());
setEnabled(modname, m_enabled_checkbox->isChecked());
}
return true;
}
if(event.GUIEvent.EventType==gui::EGET_TREEVIEW_NODE_SELECT &&
event.GUIEvent.Caller->getID() == GUI_ID_MOD_TREEVIEW)
{
selecting_dep = -1;
selecting_rdep = -1;
adjustSidebar();
return true;
}
if(event.GUIEvent.EventType==gui::EGET_LISTBOX_CHANGED &&
event.GUIEvent.Caller->getID() == GUI_ID_DEPENDS_LISTBOX)
{
selecting_dep = m_dependencies_listbox->getSelected();
selecting_rdep = -1;
return true;
}
if(event.GUIEvent.EventType==gui::EGET_LISTBOX_CHANGED &&
event.GUIEvent.Caller->getID() == GUI_ID_RDEPENDS_LISTBOX)
{
selecting_dep = -1;
selecting_rdep = m_rdependencies_listbox->getSelected();
return true;
}
//double click in a dependency listbox: find corresponding
//treeviewnode and select it:
if(event.GUIEvent.EventType==gui::EGET_LISTBOX_SELECTED_AGAIN)
{
gui::IGUIListBox* box = NULL;
if(event.GUIEvent.Caller->getID() == GUI_ID_DEPENDS_LISTBOX)
{
box = m_dependencies_listbox;
if(box->getSelected() != selecting_dep)
return true;
}
if(event.GUIEvent.Caller->getID() == GUI_ID_RDEPENDS_LISTBOX)
{
box = m_rdependencies_listbox;
if(box->getSelected() != selecting_rdep)
return true;
}
if(box != NULL && box->getSelected() != -1 &&
box->getListItem(box->getSelected()) != NULL)
{
std::string modname =
wide_to_narrow(box->getListItem(box->getSelected()));
std::map<std::string, gui::IGUITreeViewNode*>::iterator it =
m_nodes.find(modname);
if(it != m_nodes.end())
{
// select node and make sure node is visible by
// expanding all parents
gui::IGUITreeViewNode* node = (*it).second;
node->setSelected(true);
while(!node->isVisible() &&
node->getParent() != m_treeview->getRoot())
{
node = node->getParent();
node->setExpanded(true);
}
adjustSidebar();
}
}
return true;
}
}
return Parent ? Parent->OnEvent(event) : false;
}
void GUIConfigureWorld::buildTreeView(std::map<std::string, ModSpec> mods,
gui::IGUITreeViewNode* node)
{
for(std::map<std::string,ModSpec>::iterator it = mods.begin();
it != mods.end(); ++it)
{
std::string modname = (*it).first;
ModSpec mod = (*it).second;
gui::IGUITreeViewNode* new_node =
node->addChildBack(narrow_to_wide(modname).c_str());
m_nodes.insert(std::make_pair(modname, new_node));
if(mod.is_modpack)
buildTreeView(mod.modpack_content, new_node);
else
{
// set icon for node: ? for new mods, x for disabled mods,
// checkmark for enabled mods
if(m_new_mod_names.count(modname) > 0)
{
new_node->setIcon(QUESTIONMARK_STR);
}
else
{
bool mod_enabled = true;
if(m_settings.exists("load_mod_"+modname))
mod_enabled = m_settings.getBool("load_mod_"+modname);
if(mod_enabled)
new_node->setIcon(CHECKMARK_STR);
else
new_node->setIcon(CROSS_STR);
}
}
}
}
void GUIConfigureWorld::adjustSidebar()
{
gui::IGUITreeViewNode* node = m_treeview->getSelected();
std::wstring modname_w;
if(node->getText() != NULL)
modname_w = node->getText();
else
modname_w = L"N/A";
std::string modname = wide_to_narrow(modname_w);
// if no mods installed, don't show buttons or checkbox on the sidebar
if(node->getParent() == m_treeview->getRoot() && !node->hasChilds())
{
m_disableall->setVisible(false);
m_enableall->setVisible(false);
m_enabled_checkbox->setVisible(false);
}
else
{
// if modpack, show enable/disable all buttons. otherwise, show
// enabled checkbox
if(node->getParent() == m_treeview->getRoot() ||
m_addonmods[modname].is_modpack)
{
m_enabled_checkbox->setVisible(false);
m_disableall->setVisible(true);
m_enableall->setVisible(true);
m_modname_text->setText((L"Modpack: "+modname_w).c_str());
}
else
{
m_disableall->setVisible(false);
m_enableall->setVisible(false);
m_enabled_checkbox->setVisible(true);
m_modname_text->setText((L"Mod: "+modname_w).c_str());
}
}
// the mod is enabled unless it is disabled in the world.mt settings.
bool mod_enabled = true;
if(m_settings.exists("load_mod_"+modname))
mod_enabled = m_settings.getBool("load_mod_"+modname);
m_enabled_checkbox->setChecked(mod_enabled);
// dependencies of this mod:
m_dependencies_listbox->clear();
ModSpec mspec = m_addonmods[modname];
for(std::set<std::string>::iterator it=mspec.depends.begin();
it != mspec.depends.end(); ++it)
{
// check if it is an add-on mod or a game/world mod. We only
// want to show add-ons
std::string dependency = (*it);
if(m_gamemods.count(dependency) > 0)
dependency += " (" + m_gspec.id + ")";
else if(m_worldmods.count(dependency) > 0)
dependency += " (" + m_wspec.name + ")";
else if(m_addonmods.count(dependency) == 0)
dependency += " (missing)";
m_dependencies_listbox->addItem(narrow_to_wide(dependency).c_str());
}
// reverse dependencies of this mod:
m_rdependencies_listbox->clear();
std::pair< std::multimap<std::string, std::string>::iterator,
std::multimap<std::string, std::string>::iterator > rdep =
m_reverse_depends.equal_range(modname);
for(std::multimap<std::string,std::string>::iterator it = rdep.first;
it != rdep.second; ++it)
{
// check if it is an add-on mod or a game/world mod. We only
// want to show add-ons
std::string rdependency = (*it).second;
if(m_addonmods.count(rdependency) > 0)
m_rdependencies_listbox->addItem(narrow_to_wide(rdependency).c_str());
}
}
void GUIConfigureWorld::enableAllMods(std::map<std::string, ModSpec> mods,bool enable)
{
for(std::map<std::string, ModSpec>::iterator it = mods.begin();
it != mods.end(); ++it)
{
ModSpec mod = (*it).second;
if(mod.is_modpack)
// a modpack, recursively enable all mods in it
enableAllMods(mod.modpack_content,enable);
else // not a modpack
setEnabled(mod.name, enable);
}
}
void GUIConfigureWorld::enableMod(std::string modname)
{
m_settings.setBool("load_mod_"+modname,true);
std::map<std::string,gui::IGUITreeViewNode*>::iterator it =
m_nodes.find(modname);
if(it != m_nodes.end())
(*it).second->setIcon(CHECKMARK_STR);
m_new_mod_names.erase(modname);
//also enable all dependencies
ModSpec mspec = m_addonmods[modname];
for(std::set<std::string>::iterator it=mspec.depends.begin();
it != mspec.depends.end(); ++it)
{
std::string dependency = *it;
// only enable it if it is an add-on mod
if(m_addonmods.count(dependency) > 0)
enableMod(dependency);
}
}
void GUIConfigureWorld::disableMod(std::string modname)
{
m_settings.setBool("load_mod_"+modname,false);
std::map<std::string,gui::IGUITreeViewNode*>::iterator it =
m_nodes.find(modname);
if(it != m_nodes.end())
(*it).second->setIcon(CROSS_STR);
m_new_mod_names.erase(modname);
//also disable all mods that depend on this one
std::pair<std::multimap<std::string, std::string>::iterator,
std::multimap<std::string, std::string>::iterator > rdep =
m_reverse_depends.equal_range(modname);
for(std::multimap<std::string,std::string>::iterator it = rdep.first;
it != rdep.second; ++it)
{
std::string rdependency = (*it).second;
// only disable it if it is an add-on mod
if(m_addonmods.count(rdependency) > 0)
disableMod(rdependency);
}
}

110
src/guiConfigureWorld.h Normal file
View File

@ -0,0 +1,110 @@
/*
Minetest-c55
Copyright (C) 2012 celeron55, Perttu Ahola <celeron55@gmail.com>
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU Lesser General Public License as published by
the Free Software Foundation; either version 2.1 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU Lesser General Public License for more details.
You should have received a copy of the GNU Lesser General Public License along
with this program; if not, write to the Free Software Foundation, Inc.,
51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
*/
#ifndef GUICONFIGUREWORLD_HEADER
#define GUICONFIGUREWORLD_HEADER
#include "irrlichttypes_extrabloated.h"
#include "modalMenu.h"
#include "mods.h"
#include "subgame.h"
#include "settings.h"
namespace irr{
namespace gui{
class IGUITreeViewNode;
}
}
class GUIConfigureWorld : public GUIModalMenu
{
public:
GUIConfigureWorld(gui::IGUIEnvironment* env,
gui::IGUIElement* parent, s32 id,
IMenuManager *menumgr, WorldSpec wspec);
void regenerateGui(v2u32 screensize);
void drawMenu();
bool OnEvent(const SEvent& event);
private:
WorldSpec m_wspec;
SubgameSpec m_gspec;
// tree of installed add-on mods. key is the mod name, modpacks
// are not expanded.
std::map<std::string, ModSpec> m_addontree;
// like m_addontree, but modpacks are expanded.
std::map<std::string, ModSpec> m_addonmods;
// list of game mods (flattened)
std::map<std::string, ModSpec> m_gamemods;
// list of world mods (flattened)
std::map<std::string, ModSpec> m_worldmods;
// for each mod, the set of mods depending on it
std::multimap<std::string, std::string> m_reverse_depends;
// the settings in the world.mt file
Settings m_settings;
// mods that are installed but not mentioned in world.mt file
std::set<std::string> m_new_mod_names;
// maps modnames to nodes in m_treeview
std::map<std::string,gui::IGUITreeViewNode*> m_nodes;
gui::IGUIStaticText* m_modname_text;
gui::IGUITreeView* m_treeview;
gui::IGUIButton* m_enableall;
gui::IGUIButton* m_disableall;
gui::IGUICheckBox* m_enabled_checkbox;
gui::IGUIListBox* m_dependencies_listbox;
gui::IGUIListBox* m_rdependencies_listbox;
void buildTreeView(std::map<std::string,ModSpec> mods,
gui::IGUITreeViewNode* node);
void adjustSidebar();
void enableAllMods(std::map<std::string,ModSpec> mods, bool enable);
void setEnabled(std::string modname, bool enable)
{
if(enable)
enableMod(modname);
else
disableMod(modname);
};
void enableMod(std::string modname);
void disableMod(std::string modname);
// hack to work around wonky handling of double-click in
// irrlicht. store selected index of listbox items here so event
// handling can check whether it was a real double click on the
// same item. (irrlicht also reports a double click if you rapidly
// select two different items.)
int selecting_dep;
int selecting_rdep;
IMenuManager* m_menumgr;
};
#endif

View File

@ -293,7 +293,7 @@ void GUIFormSpecMenu::regenerateGui(v2u32 screensize)
geom.X = stof(f.next(",")) * (float)imgsize.X;
geom.Y = stof(f.next(";")) * (float)imgsize.Y;
std::string name = f.next("]");
errorstream<<"item name="<<name
infostream<<"item name="<<name
<<", pos=("<<pos.X<<","<<pos.Y<<")"
<<", geom=("<<geom.X<<","<<geom.Y<<")"
<<std::endl;
@ -318,13 +318,16 @@ void GUIFormSpecMenu::regenerateGui(v2u32 screensize)
errorstream<<"WARNING: invalid use of background without a size[] element"<<std::endl;
m_backgrounds.push_back(ImageDrawSpec(name, pos, geom));
}
else if(type == "field")
else if(type == "field" || type == "textarea")
{
std::string fname = f.next(";");
std::string flabel = f.next(";");
if(fname.find(",") == std::string::npos && flabel.find(",") == std::string::npos)
{
if (type == "textarea")
errorstream<<"WARNING: Textarea connot be unpositioned"<<std::endl;
if(!bp_set)
{
rect = core::rect<s32>(
@ -339,7 +342,7 @@ void GUIFormSpecMenu::regenerateGui(v2u32 screensize)
bp_set = 1;
}
else if(bp_set == 2)
errorstream<<"WARNING: invalid use of unpositioned field in inventory"<<std::endl;
errorstream<<"WARNING: invalid use of unpositioned "<<type<<" in inventory"<<std::endl;
v2s32 pos = basepos;
pos.Y = ((m_fields.size()+2)*60);
@ -353,14 +356,26 @@ void GUIFormSpecMenu::regenerateGui(v2u32 screensize)
pos.Y = stof(fname.substr(fname.find(",")+1)) * (float)spacing.Y;
v2s32 geom;
geom.X = (stof(flabel.substr(0,flabel.find(","))) * (float)spacing.X)-(spacing.X-imgsize.X);
if (type == "textarea")
{
geom.Y = (stof(flabel.substr(flabel.find(",")+1)) * (float)imgsize.Y) - (spacing.Y-imgsize.Y);
pos.Y += 15;
}
else
{
pos.Y += (stof(flabel.substr(flabel.find(",")+1)) * (float)imgsize.Y)/2;
pos.Y -= 15;
geom.Y = 30;
}
rect = core::rect<s32>(pos.X, pos.Y, pos.X+geom.X, pos.Y+geom.Y);
rect = core::rect<s32>(pos.X, pos.Y-15, pos.X+geom.X, pos.Y+15);
fname = f.next(";");
flabel = f.next(";");
if(bp_set != 2)
errorstream<<"WARNING: invalid use of positioned field without a size[] element"<<std::endl;
errorstream<<"WARNING: invalid use of positioned "<<type<<" without a size[] element"<<std::endl;
}
@ -381,40 +396,39 @@ void GUIFormSpecMenu::regenerateGui(v2u32 screensize)
258+m_fields.size()
);
// three cases: field and no label, label and no field, label and field
if (flabel == "")
// three cases: field name and no label, label and field, label name and no field
gui::IGUIEditBox *e;
if (fname == "")
{
spec.send = true;
gui::IGUIElement *e = Environment->addEditBox(spec.fdefault.c_str(), rect, true, this, spec.fid);
Environment->setFocus(e);
irr::SEvent evt;
evt.EventType = EET_KEY_INPUT_EVENT;
evt.KeyInput.Key = KEY_END;
evt.KeyInput.PressedDown = true;
e->OnEvent(evt);
}
else if (fname == "")
{
// set spec field id to 0, this stops submit searching for a value that isn't there
// spec field id to 0, this stops submit searching for a value that isn't there
Environment->addStaticText(spec.flabel.c_str(), rect, false, true, this, spec.fid);
}
else
{
spec.send = true;
gui::IGUIElement *e = Environment->addEditBox(spec.fdefault.c_str(), rect, true, this, spec.fid);
e = Environment->addEditBox(spec.fdefault.c_str(), rect, true, this, spec.fid);
Environment->setFocus(e);
rect.UpperLeftCorner.Y -= 15;
rect.LowerRightCorner.Y -= 15;
Environment->addStaticText(spec.flabel.c_str(), rect, false, true, this, 0);
if (type == "textarea")
{
e->setMultiLine(true);
e->setTextAlignment(gui::EGUIA_UPPERLEFT, gui::EGUIA_UPPERLEFT);
} else {
irr::SEvent evt;
evt.EventType = EET_KEY_INPUT_EVENT;
evt.KeyInput.Key = KEY_END;
evt.EventType = EET_KEY_INPUT_EVENT;
evt.KeyInput.PressedDown = true;
e->OnEvent(evt);
}
if (flabel != "")
{
rect.UpperLeftCorner.Y -= 15;
rect.LowerRightCorner.Y = rect.UpperLeftCorner.Y + 15;
Environment->addStaticText(spec.flabel.c_str(), rect, false, true, this, 0);
}
}
m_fields.push_back(spec);
}
else if(type == "label")
@ -808,6 +822,28 @@ void GUIFormSpecMenu::drawMenu()
NULL/*&AbsoluteClippingRect*/, colors, true);
}
/*
Draw item images
*/
for(u32 i=0; i<m_itemimages.size(); i++)
{
const ImageDrawSpec &spec = m_itemimages[i];
IItemDefManager *idef = m_gamedef->idef();
ItemStack item;
item.deSerialize(spec.name, idef);
video::ITexture *texture = idef->getInventoryTexture(item.getDefinition(idef).name, m_gamedef);
// Image size on screen
core::rect<s32> imgrect(0, 0, spec.geom.X, spec.geom.Y);
// Image rectangle on screen
core::rect<s32> rect = imgrect + spec.pos;
const video::SColor color(255,255,255,255);
const video::SColor colors[] = {color,color,color,color};
driver->draw2DImage(texture, rect,
core::rect<s32>(core::position2d<s32>(0,0),
core::dimension2di(texture->getOriginalSize())),
NULL/*&AbsoluteClippingRect*/, colors, true);
}
/*
Draw items
Phase 0: Item slot rectangles

View File

@ -57,6 +57,7 @@ enum
GUI_ID_KEY_RANGE_BUTTON,
// other
GUI_ID_CB_AUX1_DESCENDS,
GUI_ID_CB_DOUBLETAP_JUMP,
};
GUIKeyChangeMenu::GUIKeyChangeMenu(gui::IGUIEnvironment* env,
@ -149,6 +150,20 @@ void GUIKeyChangeMenu::regenerateGui(v2u32 screensize)
Environment->addCheckBox(g_settings->getBool("aux1_descends"), rect, this,
GUI_ID_CB_AUX1_DESCENDS, wgettext("\"Use\" = climb down"));
}
offset += v2s32(0, 25);
}
{
s32 option_x = offset.X + 10;
s32 option_y = offset.Y;
u32 option_w = 220;
{
core::rect<s32> rect(0, 0, option_w, 30);
rect += topleft + v2s32(option_x, option_y);
Environment->addCheckBox(g_settings->getBool("doubletap_jump"), rect, this,
GUI_ID_CB_DOUBLETAP_JUMP, wgettext("Double tap \"jump\" to toggle fly"));
}
offset += v2s32(0, 25);
}
{
@ -197,6 +212,11 @@ bool GUIKeyChangeMenu::acceptInput()
if(e != NULL && e->getType() == gui::EGUIET_CHECK_BOX)
g_settings->setBool("aux1_descends", ((gui::IGUICheckBox*)e)->isChecked());
}
{
gui::IGUIElement *e = getElementFromId(GUI_ID_CB_DOUBLETAP_JUMP);
if(e != NULL && e->getType() == gui::EGUIET_CHECK_BOX)
g_settings->setBool("doubletap_jump", ((gui::IGUICheckBox*)e)->isChecked());
}
clearKeyCache();
return true;
}

View File

@ -20,6 +20,7 @@ with this program; if not, write to the Free Software Foundation, Inc.,
#include "guiMainMenu.h"
#include "guiKeyChangeMenu.h"
#include "guiCreateWorld.h"
#include "guiConfigureWorld.h"
#include "guiMessageMenu.h"
#include "guiConfirmMenu.h"
#include "debug.h"
@ -104,6 +105,7 @@ enum
GUI_ID_TRILINEAR_CB,
GUI_ID_SHADERS_CB,
GUI_ID_PRELOAD_ITEM_VISUALS_CB,
GUI_ID_ENABLE_PARTICLES_CB,
GUI_ID_DAMAGE_CB,
GUI_ID_CREATIVE_CB,
GUI_ID_JOIN_GAME_BUTTON,
@ -113,6 +115,9 @@ enum
GUI_ID_CONFIGURE_WORLD_BUTTON,
GUI_ID_WORLD_LISTBOX,
GUI_ID_TAB_CONTROL,
GUI_ID_SERVERLIST,
GUI_ID_SERVERLIST_TOGGLE,
GUI_ID_SERVERLIST_DELETE,
};
enum
@ -360,14 +365,14 @@ void GUIMainMenu::regenerateGui(v2u32 screensize)
// Nickname + password
{
core::rect<s32> rect(0, 0, 110, 20);
rect += m_topleft_client + v2s32(35+30, 50+6);
rect += m_topleft_client + v2s32(m_size_client.X-60-100, 10+6);
Environment->addStaticText(wgettext("Name/Password"),
rect, false, true, this, -1);
}
changeCtype("C");
{
core::rect<s32> rect(0, 0, 230, 30);
rect += m_topleft_client + v2s32(160+30, 50);
core::rect<s32> rect(0, 0, 120, 30);
rect += m_topleft_client + v2s32(m_size_client.X-60-100, 50);
gui::IGUIElement *e =
Environment->addEditBox(m_data->name.c_str(), rect, true, this, GUI_ID_NAME_INPUT);
if(m_data->name == L"")
@ -375,7 +380,7 @@ void GUIMainMenu::regenerateGui(v2u32 screensize)
}
{
core::rect<s32> rect(0, 0, 120, 30);
rect += m_topleft_client + v2s32(m_size_client.X-60-100, 50);
rect += m_topleft_client + v2s32(m_size_client.X-60-100, 90);
gui::IGUIEditBox *e =
Environment->addEditBox(L"", rect, true, this, 264);
e->setPasswordBox(true);
@ -384,17 +389,29 @@ void GUIMainMenu::regenerateGui(v2u32 screensize)
}
changeCtype("");
// Server List
{
core::rect<s32> rect(0, 0, 390, 160);
rect += m_topleft_client + v2s32(50, 10);
gui::IGUIListBox *e = Environment->addListBox(rect, this,
GUI_ID_SERVERLIST);
e->setDrawBackground(true);
if (m_data->serverlist_show_available == false)
m_data->servers = ServerList::getLocal();
updateGuiServerList();
e->setSelected(0);
}
// Address + port
{
core::rect<s32> rect(0, 0, 110, 20);
rect += m_topleft_client + v2s32(35+30, 100+6);
rect += m_topleft_client + v2s32(50, m_size_client.Y-50-15+6);
Environment->addStaticText(wgettext("Address/Port"),
rect, false, true, this, -1);
}
changeCtype("C");
{
core::rect<s32> rect(0, 0, 230, 30);
rect += m_topleft_client + v2s32(160+30, 100);
core::rect<s32> rect(0, 0, 260, 30);
rect += m_topleft_client + v2s32(50, m_size_client.Y-25-15);
gui::IGUIElement *e =
Environment->addEditBox(m_data->address.c_str(), rect, true,
this, GUI_ID_ADDRESS_INPUT);
@ -403,18 +420,43 @@ void GUIMainMenu::regenerateGui(v2u32 screensize)
}
{
core::rect<s32> rect(0, 0, 120, 30);
rect += m_topleft_client + v2s32(m_size_client.X-60-100, 100);
rect += m_topleft_client + v2s32(50+260+10, m_size_client.Y-25-15);
Environment->addEditBox(m_data->port.c_str(), rect, true,
this, GUI_ID_PORT_INPUT);
}
changeCtype("");
#if USE_CURL
// Toggle Serverlist (Favorites/Online)
{
core::rect<s32> rect(0, 0, 260, 30);
rect += m_topleft_client + v2s32(50,
180);
gui::IGUIButton *e = Environment->addButton(rect, this, GUI_ID_SERVERLIST_TOGGLE,
wgettext("Show Public"));
e->setIsPushButton(true);
if (m_data->serverlist_show_available)
{
e->setText(wgettext("Show Favorites"));
e->setPressed();
}
}
#endif
// Delete Local Favorite
{
core::rect<s32> rect(0, 0, 120, 30);
rect += m_topleft_client + v2s32(50+260+10, 180);
gui::IGUIButton *e = Environment->addButton(rect, this, GUI_ID_SERVERLIST_DELETE,
wgettext("Delete"));
if (m_data->serverlist_show_available) // Hidden on Show-Online mode
e->setVisible(false);
}
// Start game button
{
core::rect<s32> rect(0, 0, 180, 30);
rect += m_topleft_client + v2s32(m_size_client.X-180-30,
m_size_client.Y-30-15);
core::rect<s32> rect(0, 0, 120, 30);
rect += m_topleft_client + v2s32(m_size_client.X-130-30,
m_size_client.Y-25-15);
Environment->addButton(rect, this, GUI_ID_JOIN_GAME_BUTTON,
wgettext("Start Game / Connect"));
wgettext("Connect"));
}
changeCtype("C");
}
@ -618,7 +660,7 @@ void GUIMainMenu::regenerateGui(v2u32 screensize)
GUI_ID_TRILINEAR_CB, wgettext("Tri-Linear Filtering"));
}
// shader/on demand image loading settings
// shader/on demand image loading/particles settings
{
core::rect<s32> rect(0, 0, option_w+20, 30);
rect += m_topleft_client + v2s32(option_x+175*2, option_y);
@ -633,6 +675,13 @@ void GUIMainMenu::regenerateGui(v2u32 screensize)
GUI_ID_PRELOAD_ITEM_VISUALS_CB, wgettext("Preload item visuals"));
}
{
core::rect<s32> rect(0, 0, option_w+20+20, 30);
rect += m_topleft_client + v2s32(option_x+175*2, option_y+20*2);
Environment->addCheckBox(m_data->enable_particles, rect, this,
GUI_ID_ENABLE_PARTICLES_CB, wgettext("Enable Particles"));
}
// Key change button
{
core::rect<s32> rect(0, 0, 120, 30);
@ -849,11 +898,23 @@ void GUIMainMenu::readInput(MainMenuData *dst)
dst->preload_item_visuals = ((gui::IGUICheckBox*)e)->isChecked();
}
{
gui::IGUIElement *e = getElementFromId(GUI_ID_ENABLE_PARTICLES_CB);
if(e != NULL && e->getType() == gui::EGUIET_CHECK_BOX)
dst->enable_particles = ((gui::IGUICheckBox*)e)->isChecked();
}
{
gui::IGUIElement *e = getElementFromId(GUI_ID_WORLD_LISTBOX);
if(e != NULL && e->getType() == gui::EGUIET_LIST_BOX)
dst->selected_world = ((gui::IGUIListBox*)e)->getSelected();
}
{
ServerListSpec server =
getServerListSpec(wide_to_narrow(dst->address), wide_to_narrow(dst->port));
dst->servername = server.name;
dst->serverdescription = server.description;
}
}
void GUIMainMenu::acceptInput()
@ -898,6 +959,11 @@ bool GUIMainMenu::OnEvent(const SEvent& event)
regenerateGui(m_screensize_old);
return true;
}
if(event.GUIEvent.EventType==gui::EGET_LISTBOX_CHANGED && event.GUIEvent.Caller->getID() == GUI_ID_SERVERLIST)
{
serverListOnSelected();
return true;
}
if(event.GUIEvent.EventType==gui::EGET_BUTTON_CLICKED)
{
switch(event.GUIEvent.Caller->getID())
@ -905,7 +971,8 @@ bool GUIMainMenu::OnEvent(const SEvent& event)
case GUI_ID_JOIN_GAME_BUTTON: {
MainMenuData cur;
readInput(&cur);
if(cur.address == L"" && getTab() == TAB_MULTIPLAYER){
if (getTab() == TAB_MULTIPLAYER && cur.address == L"")
{
(new GUIMessageMenu(env, parent, -1, menumgr,
wgettext("Address required."))
)->drop();
@ -967,12 +1034,62 @@ bool GUIMainMenu::OnEvent(const SEvent& event)
return true;
}
case GUI_ID_CONFIGURE_WORLD_BUTTON: {
GUIMessageMenu *menu = new GUIMessageMenu(env, parent,
-1, menumgr,
wgettext("Nothing here"));
MainMenuData cur;
readInput(&cur);
if(cur.selected_world == -1)
{
(new GUIMessageMenu(env, parent, -1, menumgr,
wgettext("Cannot configure world: Nothing selected"))
)->drop();
}
else
{
WorldSpec wspec = m_data->worlds[cur.selected_world];
GUIConfigureWorld *menu = new GUIConfigureWorld(env, parent,
-1, menumgr, wspec);
menu->drop();
}
return true;
}
case GUI_ID_SERVERLIST_DELETE: {
gui::IGUIListBox *serverlist = (gui::IGUIListBox*)getElementFromId(GUI_ID_SERVERLIST);
s32 selected = ((gui::IGUIListBox*)serverlist)->getSelected();
if (selected == -1) return true;
ServerList::deleteEntry(m_data->servers[selected]);
m_data->servers = ServerList::getLocal();
updateGuiServerList();
if (selected > 0)
selected -= 1;
serverlist->setSelected(selected);
serverListOnSelected();
return true;
}
#if USE_CURL
case GUI_ID_SERVERLIST_TOGGLE: {
gui::IGUIElement *togglebutton = getElementFromId(GUI_ID_SERVERLIST_TOGGLE);
gui::IGUIElement *deletebutton = getElementFromId(GUI_ID_SERVERLIST_DELETE);
gui::IGUIListBox *serverlist = (gui::IGUIListBox*)getElementFromId(GUI_ID_SERVERLIST);
if (m_data->serverlist_show_available) // switch to favorite list
{
m_data->servers = ServerList::getLocal();
togglebutton->setText(wgettext("Show Public"));
deletebutton->setVisible(true);
updateGuiServerList();
serverlist->setSelected(0);
}
else // switch to online list
{
m_data->servers = ServerList::getOnline();
togglebutton->setText(wgettext("Show Favorites"));
deletebutton->setVisible(false);
updateGuiServerList();
serverlist->setSelected(0);
}
serverListOnSelected();
m_data->serverlist_show_available = !m_data->serverlist_show_available;
}
#endif
}
}
if(event.GUIEvent.EventType==gui::EGET_EDITBOX_ENTER)
@ -995,6 +1112,14 @@ bool GUIMainMenu::OnEvent(const SEvent& event)
m_data->address = L""; // Force local game
quitMenu();
return true;
case GUI_ID_SERVERLIST:
gui::IGUIListBox *serverlist = (gui::IGUIListBox*)getElementFromId(GUI_ID_SERVERLIST);
if (serverlist->getSelected() > -1)
{
acceptInput();
quitMenu();
return true;
}
}
}
}
@ -1039,3 +1164,55 @@ void GUIMainMenu::displayMessageMenu(std::wstring msg)
{
(new GUIMessageMenu(env, parent, -1, menumgr, msg))->drop();
}
void GUIMainMenu::updateGuiServerList()
{
gui::IGUIListBox *serverlist = (gui::IGUIListBox *)getElementFromId(GUI_ID_SERVERLIST);
serverlist->clear();
for(std::vector<ServerListSpec>::iterator i = m_data->servers.begin();
i != m_data->servers.end(); i++)
{
std::string text;
if (i->name != "" && i->description != "")
text = i->name + " (" + i->description + ")";
else if (i->name !="")
text = i->name;
else
text = i->address + ":" + i->port;
serverlist->addItem(narrow_to_wide(text).c_str());
}
}
void GUIMainMenu::serverListOnSelected()
{
if (!m_data->servers.empty())
{
gui::IGUIListBox *serverlist = (gui::IGUIListBox*)getElementFromId(GUI_ID_SERVERLIST);
u16 id = serverlist->getSelected();
if (id < 0) return;
((gui::IGUIEditBox*)getElementFromId(GUI_ID_ADDRESS_INPUT))
->setText(narrow_to_wide(m_data->servers[id].address).c_str());
((gui::IGUIEditBox*)getElementFromId(GUI_ID_PORT_INPUT))
->setText(narrow_to_wide(m_data->servers[id].port).c_str());
}
}
ServerListSpec GUIMainMenu::getServerListSpec(std::string address, std::string port)
{
ServerListSpec server;
server.address = address;
server.port = port;
for(std::vector<ServerListSpec>::iterator i = m_data->servers.begin();
i != m_data->servers.end(); i++)
{
if (i->address == address && i->port == port)
{
server.description = i->description;
server.name = i->name;
break;
}
}
return server;
}

View File

@ -25,6 +25,8 @@ with this program; if not, write to the Free Software Foundation, Inc.,
#include <string>
#include <list>
#include "subgame.h"
#include "serverlist.h"
class IGameCallback;
struct MainMenuData
@ -33,6 +35,8 @@ struct MainMenuData
// Generic
int selected_tab;
// Client options
std::string servername;
std::string serverdescription;
std::wstring address;
std::wstring port;
std::wstring name;
@ -47,6 +51,7 @@ struct MainMenuData
bool trilinear_filter;
int enable_shaders;
bool preload_item_visuals;
bool enable_particles;
// Server options
bool creative_mode;
bool enable_damage;
@ -57,8 +62,11 @@ struct MainMenuData
std::string create_world_gameid;
bool only_refresh;
bool serverlist_show_available; // if false show local favorites only
std::vector<WorldSpec> worlds;
std::vector<SubgameSpec> games;
std::vector<ServerListSpec> servers;
MainMenuData():
// Generic
@ -72,7 +80,9 @@ struct MainMenuData
selected_world(0),
simple_singleplayer_mode(false),
// Actions
only_refresh(false)
only_refresh(false),
serverlist_show_available(false)
{}
};
@ -115,6 +125,9 @@ private:
v2s32 m_size_client;
v2s32 m_topleft_server;
v2s32 m_size_server;
void updateGuiServerList();
void serverListOnSelected();
ServerListSpec getServerListSpec(std::string address, std::string port);
};
#endif

View File

@ -28,12 +28,13 @@ using namespace irr;
#if (IRRLICHT_VERSION_MAJOR == 1 && IRRLICHT_VERSION_MINOR < 8)
#ifdef _MSC_VER
// Windows
typedef long long s64;
typedef unsigned long long u64;
#else
// Posix
#include <stdint.h>
typedef int64_t s64;
typedef uint64_t u64;
//typedef unsigned long long u64;
#endif
#endif

View File

@ -399,6 +399,9 @@ void LocalPlayer::applyControl(float dtime)
// Whether superspeed mode is used or not
bool superspeed = false;
if(g_settings->getBool("always_fly_fast") && free_move && fast_move)
superspeed = true;
// Old descend control
if(g_settings->getBool("aux1_descends"))
{
@ -454,7 +457,8 @@ void LocalPlayer::applyControl(float dtime)
{
// In free movement mode, sneak descends
v3f speed = getSpeed();
if(fast_move && control.aux1)
if(fast_move && (control.aux1 ||
g_settings->getBool("always_fly_fast")))
speed.Y = -20*BS;
else
speed.Y = -walkspeed_max;
@ -497,7 +501,8 @@ void LocalPlayer::applyControl(float dtime)
{
v3f speed = getSpeed();
if(g_settings->getBool("aux1_descends"))
if(g_settings->getBool("aux1_descends") ||
g_settings->getBool("always_fly_fast"))
{
if(fast_move)
speed.Y = 20*BS;

View File

@ -71,6 +71,7 @@ with this program; if not, write to the Free Software Foundation, Inc.,
#include "util/string.h"
#include "subgame.h"
#include "quicktune.h"
#include "serverlist.h"
/*
Settings.
@ -1448,6 +1449,7 @@ int main(int argc, char *argv[])
menudata.trilinear_filter = g_settings->getBool("trilinear_filter");
menudata.enable_shaders = g_settings->getS32("enable_shaders");
menudata.preload_item_visuals = g_settings->getBool("preload_item_visuals");
menudata.enable_particles = g_settings->getBool("enable_particles");
driver->setTextureCreationFlag(video::ETCF_CREATE_MIP_MAPS, menudata.mip_map);
menudata.creative_mode = g_settings->getBool("creative_mode");
menudata.enable_damage = g_settings->getBool("enable_damage");
@ -1570,6 +1572,7 @@ int main(int argc, char *argv[])
g_settings->setS32("enable_shaders", menudata.enable_shaders);
g_settings->set("preload_item_visuals", itos(menudata.preload_item_visuals));
g_settings->set("enable_particles", itos(menudata.enable_particles));
g_settings->set("creative_mode", itos(menudata.creative_mode));
g_settings->set("enable_damage", itos(menudata.enable_damage));
@ -1596,6 +1599,15 @@ int main(int argc, char *argv[])
current_address = "";
current_port = 30011;
}
else if (address != "")
{
ServerListSpec server;
server.name = menudata.servername;
server.address = wide_to_narrow(menudata.address);
server.port = wide_to_narrow(menudata.port);
server.description = menudata.serverdescription;
ServerList::insert(server);
}
// Set world path to selected one
if(menudata.selected_world != -1){

View File

@ -33,6 +33,7 @@ with this program; if not, write to the Free Software Foundation, Inc.,
#include "gamedef.h"
#include "util/directiontables.h"
#include "rollback_interface.h"
#include "mapgen_v6.h"
#define PP(x) "("<<(x).X<<","<<(x).Y<<","<<(x).Z<<")"
@ -1651,7 +1652,7 @@ void Map::transformLiquids(core::map<v3s16, MapBlock*> & modified_blocks)
Collect information about current node
*/
s8 liquid_level = -1;
u8 liquid_kind = CONTENT_IGNORE;
content_t liquid_kind = CONTENT_IGNORE;
LiquidType liquid_type = nodemgr->get(n0).liquid_type;
switch (liquid_type) {
case LIQUID_SOURCE:
@ -1993,8 +1994,7 @@ void Map::removeNodeTimer(v3s16 p)
/*
ServerMap
*/
ServerMap::ServerMap(std::string savedir, IGameDef *gamedef):
ServerMap::ServerMap(std::string savedir, IGameDef *gamedef, EmergeManager *emerge):
Map(dout_server, gamedef),
m_seed(0),
m_map_metadata_changed(true),
@ -2004,18 +2004,20 @@ ServerMap::ServerMap(std::string savedir, IGameDef *gamedef):
{
verbosestream<<__FUNCTION_NAME<<std::endl;
//m_chunksize = 8; // Takes a few seconds
m_emerge = emerge;
m_mgparams = m_emerge->getParamsFromSettings(g_settings);
if (!m_mgparams)
m_mgparams = new MapgenV6Params();
m_seed = m_mgparams->seed;
if (g_settings->get("fixed_map_seed").empty())
{
m_seed = (((u64)(myrand()%0xffff)<<0)
+ ((u64)(myrand()%0xffff)<<16)
+ ((u64)(myrand()%0xffff)<<32)
+ ((u64)(myrand()%0xffff)<<48));
}
else
{
m_seed = g_settings->getU64("fixed_map_seed");
+ ((u64)(myrand()&0xffff)<<48));
m_mgparams->seed = m_seed;
}
/*
@ -2050,6 +2052,10 @@ ServerMap::ServerMap(std::string savedir, IGameDef *gamedef):
// Load map metadata (seed, chunksize)
loadMapMeta();
}
catch(SettingNotFoundException &e){
infostream<<"ServerMap: Some metadata not found."
<<" Using default settings."<<std::endl;
}
catch(FileNotGoodException &e){
infostream<<"WARNING: Could not load map metadata"
//<<" Disabling chunk-based generator."
@ -2136,7 +2142,7 @@ ServerMap::~ServerMap()
#endif
}
void ServerMap::initBlockMake(mapgen::BlockMakeData *data, v3s16 blockpos)
void ServerMap::initBlockMake(BlockMakeData *data, v3s16 blockpos)
{
bool enable_mapgen_debug_info = g_settings->getBool("enable_mapgen_debug_info");
if(enable_mapgen_debug_info)
@ -2208,7 +2214,7 @@ void ServerMap::initBlockMake(mapgen::BlockMakeData *data, v3s16 blockpos)
Refer to the map generator heuristics.
*/
bool ug = mapgen::block_is_underground(data->seed, p);
bool ug = m_emerge->isBlockUnderground(p);
block->setIsUnderground(ug);
}
@ -2243,7 +2249,7 @@ void ServerMap::initBlockMake(mapgen::BlockMakeData *data, v3s16 blockpos)
// Data is ready now.
}
MapBlock* ServerMap::finishBlockMake(mapgen::BlockMakeData *data,
MapBlock* ServerMap::finishBlockMake(BlockMakeData *data,
core::map<v3s16, MapBlock*> &changed_blocks)
{
v3s16 blockpos_min = data->blockpos_min;
@ -2483,6 +2489,7 @@ ServerMapSector * ServerMap::createSector(v2s16 p2d)
return sector;
}
#if 0
/*
This is a quick-hand function for calling makeBlock().
*/
@ -2518,7 +2525,7 @@ MapBlock * ServerMap::generateBlock(
/*
Create block make data
*/
mapgen::BlockMakeData data;
BlockMakeData data;
initBlockMake(&data, p);
/*
@ -2526,7 +2533,8 @@ MapBlock * ServerMap::generateBlock(
*/
{
TimeTaker t("mapgen::make_block()");
mapgen::make_block(&data);
mapgen->makeChunk(&data);
//mapgen::make_block(&data);
if(enable_mapgen_debug_info == false)
t.stop(true); // Hide output
@ -2595,6 +2603,7 @@ MapBlock * ServerMap::generateBlock(
return block;
}
#endif
MapBlock * ServerMap::createBlock(v3s16 p)
{
@ -2656,14 +2665,15 @@ MapBlock * ServerMap::createBlock(v3s16 p)
}
// Create blank
block = sector->createBlankBlock(block_y);
return block;
}
MapBlock * ServerMap::emergeBlock(v3s16 p, bool allow_generate)
MapBlock * ServerMap::emergeBlock(v3s16 p, bool create_blank)
{
DSTACKF("%s: p=(%d,%d,%d), allow_generate=%d",
DSTACKF("%s: p=(%d,%d,%d), create_blank=%d",
__FUNCTION_NAME,
p.X, p.Y, p.Z, allow_generate);
p.X, p.Y, p.Z, create_blank);
{
MapBlock *block = getBlockNoCreateNoEx(p);
@ -2677,7 +2687,13 @@ MapBlock * ServerMap::emergeBlock(v3s16 p, bool allow_generate)
return block;
}
if(allow_generate)
if (create_blank) {
ServerMapSector *sector = createSector(v2s16(p.X, p.Z));
MapBlock *block = sector->createBlankBlock(p.Y);
return block;
}
/*if(allow_generate)
{
core::map<v3s16, MapBlock*> modified_blocks;
MapBlock *block = generateBlock(p, modified_blocks);
@ -2700,7 +2716,7 @@ MapBlock * ServerMap::emergeBlock(v3s16 p, bool allow_generate)
return block;
}
}
}*/
return NULL;
}
@ -2742,7 +2758,7 @@ plan_b:
Determine from map generator noise functions
*/
s16 level = mapgen::find_ground_level_from_noise(m_seed, p2d, 1);
s16 level = m_emerge->getGroundLevelAtPoint(p2d);
return level;
//double level = base_rock_level_2d(m_seed, p2d) + AVERAGE_MUD_AMOUNT;
@ -3061,7 +3077,14 @@ void ServerMap::saveMapMeta()
}
Settings params;
params.setU64("seed", m_seed);
params.set("mg_name", m_emerge->params->mg_name);
params.setU64("seed", m_emerge->params->seed);
params.setS16("water_level", m_emerge->params->water_level);
params.setS16("chunksize", m_emerge->params->chunksize);
params.setS32("mg_flags", m_emerge->params->flags);
m_emerge->params->writeParams(&params);
params.writeLines(os);
@ -3101,7 +3124,18 @@ void ServerMap::loadMapMeta()
params.parseConfigLine(line);
}
MapgenParams *mgparams = m_emerge->getParamsFromSettings(&params);
if (mgparams) {
if (m_mgparams)
delete m_mgparams;
m_mgparams = mgparams;
m_seed = mgparams->seed;
} else {
if (params.exists("seed")) {
m_seed = params.getU64("seed");
m_mgparams->seed = m_seed;
}
}
verbosestream<<"ServerMap::loadMapMeta(): "<<"seed="<<m_seed<<std::endl;
}
@ -3344,18 +3378,26 @@ void ServerMap::saveBlock(MapBlock *block)
std::string tmp = o.str();
const char *bytes = tmp.c_str();
if(sqlite3_bind_int64(m_database_write, 1, getBlockAsInteger(p3d)) != SQLITE_OK)
bool success = true;
if(sqlite3_bind_int64(m_database_write, 1, getBlockAsInteger(p3d)) != SQLITE_OK) {
infostream<<"WARNING: Block position failed to bind: "<<sqlite3_errmsg(m_database)<<std::endl;
if(sqlite3_bind_blob(m_database_write, 2, (void *)bytes, o.tellp(), NULL) != SQLITE_OK) // TODO this mught not be the right length
success = false;
}
if(sqlite3_bind_blob(m_database_write, 2, (void *)bytes, o.tellp(), NULL) != SQLITE_OK) { // TODO this mught not be the right length
infostream<<"WARNING: Block data failed to bind: "<<sqlite3_errmsg(m_database)<<std::endl;
success = false;
}
int written = sqlite3_step(m_database_write);
if(written != SQLITE_DONE)
infostream<<"WARNING: Block failed to save ("<<p3d.X<<", "<<p3d.Y<<", "<<p3d.Z<<") "
if(written != SQLITE_DONE) {
errorstream<<"WARNING: Block failed to save ("<<p3d.X<<", "<<p3d.Y<<", "<<p3d.Z<<") "
<<sqlite3_errmsg(m_database)<<std::endl;
success = false;
}
// Make ready for later reuse
sqlite3_reset(m_database_write);
// We just wrote it to the disk so clear modified flag
if (success)
block->resetModified();
}

View File

@ -30,6 +30,7 @@ with this program; if not, write to the Free Software Foundation, Inc.,
#include "mapnode.h"
#include "constants.h"
#include "voxel.h"
#include "mapgen.h" //for BlockMakeData and EmergeManager
#include "modifiedstate.h"
#include "util/container.h"
#include "nodetimer.h"
@ -46,9 +47,6 @@ class NodeMetadata;
class IGameDef;
class IRollbackReportSink;
namespace mapgen{
struct BlockMakeData;
};
/*
MapEditEvent
@ -360,7 +358,7 @@ public:
/*
savedir: directory to which map data should be saved
*/
ServerMap(std::string savedir, IGameDef *gamedef);
ServerMap(std::string savedir, IGameDef *gamedef, EmergeManager *emerge);
~ServerMap();
s32 mapType() const
@ -379,15 +377,15 @@ public:
/*
Blocks are generated by using these and makeBlock().
*/
void initBlockMake(mapgen::BlockMakeData *data, v3s16 blockpos);
MapBlock* finishBlockMake(mapgen::BlockMakeData *data,
void initBlockMake(BlockMakeData *data, v3s16 blockpos);
MapBlock* finishBlockMake(BlockMakeData *data,
core::map<v3s16, MapBlock*> &changed_blocks);
// A non-threaded wrapper to the above
MapBlock * generateBlock(
// A non-threaded wrapper to the above - DEFUNCT
/* MapBlock * generateBlock(
v3s16 p,
core::map<v3s16, MapBlock*> &modified_blocks
);
);*/
/*
Get a block from somewhere.
@ -400,9 +398,10 @@ public:
Forcefully get a block from somewhere.
- Memory
- Load from disk
- Generate
- Create blank filled with CONTENT_IGNORE
*/
MapBlock * emergeBlock(v3s16 p, bool allow_generate=true);
MapBlock * emergeBlock(v3s16 p, bool create_blank=true);
// Helper for placing objects on ground level
s16 findGroundLevel(v2s16 p2d);
@ -479,10 +478,17 @@ public:
u64 getSeed(){ return m_seed; }
MapgenParams *getMapgenParams(){ return m_mgparams; }
// Parameters fed to the Mapgen
MapgenParams *m_mgparams;
private:
// Seed used for all kinds of randomness in generation
u64 m_seed;
// Emerge manager
EmergeManager *m_emerge;
std::string m_savedir;
bool m_map_saving_enabled;

View File

@ -20,7 +20,9 @@ with this program; if not, write to the Free Software Foundation, Inc.,
#include "mapgen.h"
#include "voxel.h"
#include "noise.h"
#include "biome.h"
#include "mapblock.h"
#include "mapnode.h"
#include "map.h"
//#include "serverobject.h"
#include "content_sao.h"
@ -28,9 +30,213 @@ with this program; if not, write to the Free Software Foundation, Inc.,
#include "content_mapnode.h" // For content_mapnode_get_new_name
#include "voxelalgorithms.h"
#include "profiler.h"
#include "settings.h" // For g_settings
#include "main.h" // For g_profiler
#include "treegen.h"
#include "mapgen_v6.h"
///////////////////////////////////////////////////////////////////////////////
/////////////////////////////// Emerge Manager ////////////////////////////////
EmergeManager::EmergeManager(IGameDef *gamedef, BiomeDefManager *bdef) {
//register built-in mapgens
registerMapgen("v6", new MapgenFactoryV6());
//the order of these assignments is pretty important
this->biomedef = bdef ? bdef : new BiomeDefManager(gamedef);
this->params = NULL;
this->mapgen = NULL;
}
EmergeManager::~EmergeManager() {
delete biomedef;
delete mapgen;
delete params;
}
void EmergeManager::initMapgens(MapgenParams *mgparams) {
if (mapgen)
return;
this->params = mgparams;
this->mapgen = getMapgen(); //only one mapgen for now!
}
Mapgen *EmergeManager::getMapgen() {
if (!mapgen) {
mapgen = createMapgen(params->mg_name, 0, params, this);
if (!mapgen) {
infostream << "EmergeManager: falling back to mapgen v6" << std::endl;
delete params;
params = createMapgenParams("v6");
mapgen = createMapgen("v6", 0, params, this);
}
}
return mapgen;
}
void EmergeManager::addBlockToQueue() {
//STUB
}
int EmergeManager::getGroundLevelAtPoint(v2s16 p) {
if (!mapgen)
return 0;
return mapgen->getGroundLevelAtPoint(p);
}
bool EmergeManager::isBlockUnderground(v3s16 blockpos) {
/*
v2s16 p = v2s16((blockpos.X * MAP_BLOCKSIZE) + MAP_BLOCKSIZE / 2,
(blockpos.Y * MAP_BLOCKSIZE) + MAP_BLOCKSIZE / 2);
int ground_level = getGroundLevelAtPoint(p);
return blockpos.Y * (MAP_BLOCKSIZE + 1) <= min(water_level, ground_level);
*/
//yuck, but then again, should i bother being accurate?
//the height of the nodes in a single block is quite variable
return blockpos.Y * (MAP_BLOCKSIZE + 1) <= params->water_level;
}
u32 EmergeManager::getBlockSeed(v3s16 p) {
return (u32)(params->seed & 0xFFFFFFFF) +
p.Z * 38134234 +
p.Y * 42123 +
p.Y * 23;
}
Mapgen *EmergeManager::createMapgen(std::string mgname, int mgid,
MapgenParams *mgparams, EmergeManager *emerge) {
std::map<std::string, MapgenFactory *>::const_iterator iter = mglist.find(mgname);
if (iter == mglist.end()) {
errorstream << "EmergeManager; mapgen " << mgname <<
" not registered" << std::endl;
return NULL;
}
MapgenFactory *mgfactory = iter->second;
return mgfactory->createMapgen(mgid, mgparams, emerge);
}
MapgenParams *EmergeManager::createMapgenParams(std::string mgname) {
std::map<std::string, MapgenFactory *>::const_iterator iter = mglist.find(mgname);
if (iter == mglist.end()) {
errorstream << "EmergeManager: mapgen " << mgname <<
" not registered" << std::endl;
return NULL;
}
MapgenFactory *mgfactory = iter->second;
return mgfactory->createMapgenParams();
}
MapgenParams *EmergeManager::getParamsFromSettings(Settings *settings) {
std::string mg_name = settings->get("mg_name");
MapgenParams *mgparams = createMapgenParams(mg_name);
mgparams->mg_name = mg_name;
mgparams->seed = settings->getU64(settings == g_settings ? "fixed_map_seed" : "seed");
mgparams->water_level = settings->getS16("water_level");
mgparams->chunksize = settings->getS16("chunksize");
mgparams->flags = settings->getS32("mg_flags");
if (!mgparams->readParams(settings)) {
delete mgparams;
return NULL;
}
return mgparams;
}
bool EmergeManager::registerMapgen(std::string mgname, MapgenFactory *mgfactory) {
mglist.insert(std::make_pair(mgname, mgfactory));
infostream << "EmergeManager: registered mapgen " << mgname << std::endl;
}
/////////////////////
bool MapgenV6Params::readParams(Settings *settings) {
freq_desert = settings->getFloat("mgv6_freq_desert");
freq_beach = settings->getFloat("mgv6_freq_beach");
np_terrain_base = settings->getNoiseParams("mgv6_np_terrain_base");
np_terrain_higher = settings->getNoiseParams("mgv6_np_terrain_higher");
np_steepness = settings->getNoiseParams("mgv6_np_steepness");
np_height_select = settings->getNoiseParams("mgv6_np_height_select");
np_trees = settings->getNoiseParams("mgv6_np_trees");
np_mud = settings->getNoiseParams("mgv6_np_mud");
np_beach = settings->getNoiseParams("mgv6_np_beach");
np_biome = settings->getNoiseParams("mgv6_np_biome");
np_cave = settings->getNoiseParams("mgv6_np_cave");
bool success =
np_terrain_base && np_terrain_higher && np_steepness &&
np_height_select && np_trees && np_mud &&
np_beach && np_biome && np_cave;
return success;
}
void MapgenV6Params::writeParams(Settings *settings) {
settings->setFloat("mgv6_freq_desert", freq_desert);
settings->setFloat("mgv6_freq_beach", freq_beach);
settings->setNoiseParams("mgv6_np_terrain_base", np_terrain_base);
settings->setNoiseParams("mgv6_np_terrain_higher", np_terrain_higher);
settings->setNoiseParams("mgv6_np_steepness", np_steepness);
settings->setNoiseParams("mgv6_np_height_select", np_height_select);
settings->setNoiseParams("mgv6_np_trees", np_trees);
settings->setNoiseParams("mgv6_np_mud", np_mud);
settings->setNoiseParams("mgv6_np_beach", np_beach);
settings->setNoiseParams("mgv6_np_biome", np_biome);
settings->setNoiseParams("mgv6_np_cave", np_cave);
}
/////////////////////////////////// legacy static functions for farmesh
s16 Mapgen::find_ground_level_from_noise(u64 seed, v2s16 p2d, s16 precision) {
//just need to return something
s16 level = 5;
return level;
}
bool Mapgen::get_have_beach(u64 seed, v2s16 p2d) {
double sandnoise = noise2d_perlin(
0.2+(float)p2d.X/250, 0.7+(float)p2d.Y/250,
seed+59420, 3, 0.50);
return (sandnoise > 0.15);
}
double Mapgen::tree_amount_2d(u64 seed, v2s16 p) {
double noise = noise2d_perlin(
0.5+(float)p.X/125, 0.5+(float)p.Y/125,
seed+2, 4, 0.66);
double zeroval = -0.39;
if(noise < zeroval)
return 0;
else
return 0.04 * (noise-zeroval) / (1.0-zeroval);
}
#if 0 /// BIG COMMENT
namespace mapgen
{
@ -121,6 +327,7 @@ static s16 find_stone_level(VoxelManipulator &vmanip, v2s16 p2d,
}
#endif
#if 0
static void make_papyrus(VoxelManipulator &vmanip, v3s16 p0,
@ -2756,6 +2963,8 @@ void make_block(BlockMakeData *data)
}
}
#endif ///BIG COMMENT
BlockMakeData::BlockMakeData():
no_op(false),
vmanip(NULL),
@ -2768,6 +2977,6 @@ BlockMakeData::~BlockMakeData()
delete vmanip;
}
}; // namespace mapgen
//}; // namespace mapgen

View File

@ -22,36 +22,30 @@ with this program; if not, write to the Free Software Foundation, Inc.,
#include "irrlichttypes_extrabloated.h"
#include "util/container.h" // UniqueQueue
#include "gamedef.h"
#include "mapnode.h"
#include "noise.h"
#include "settings.h"
#include <map>
struct BlockMakeData;
/////////////////// Mapgen flags
#define MG_TREES 0x01
#define MG_CAVES 0x02
#define MG_DUNGEONS 0x04
#define MGV6_FORESTS 0x08
#define MGV6_BIOME_BLEND 0x10
class BiomeDefManager;
class Biome;
class EmergeManager;
class MapBlock;
class ManualMapVoxelManipulator;
class VoxelManipulator;
class INodeDefManager;
namespace mapgen
{
// Finds precise ground level at any position
s16 find_ground_level_from_noise(u64 seed, v2s16 p2d, s16 precision);
// Find out if block is completely underground
bool block_is_underground(u64 seed, v3s16 blockpos);
// Get a pseudorandom seed for a position on the map
u32 get_blockseed(u64 seed, v3s16 p);
// Main map generation routine
void make_block(BlockMakeData *data);
/*
These are used by FarMesh
*/
bool get_have_beach(u64 seed, v2s16 p2d);
double tree_amount_2d(u64 seed, v2s16 p);
struct BlockMakeData
{
struct BlockMakeData {
bool no_op;
ManualMapVoxelManipulator *vmanip; // Destructor deletes
ManualMapVoxelManipulator *vmanip;
u64 seed;
v3s16 blockpos_min;
v3s16 blockpos_max;
@ -61,9 +55,81 @@ namespace mapgen
BlockMakeData();
~BlockMakeData();
};
};
}; // namespace mapgen
struct MapgenParams {
std::string mg_name;
int chunksize;
u64 seed;
int water_level;
u32 flags;
MapgenParams() {
mg_name = "v6";
seed = 0;
water_level = 1;
chunksize = 5;
flags = MG_TREES | MG_CAVES | MGV6_BIOME_BLEND;
}
virtual bool readParams(Settings *settings) = 0;
virtual void writeParams(Settings *settings) {};
};
class Mapgen {
public:
int seed;
int water_level;
bool generating;
int id;
virtual void makeChunk(BlockMakeData *data) {};
virtual int getGroundLevelAtPoint(v2s16 p) = 0;
//Legacy functions for Farmesh (pending removal)
static bool get_have_beach(u64 seed, v2s16 p2d);
static double tree_amount_2d(u64 seed, v2s16 p);
static s16 find_ground_level_from_noise(u64 seed, v2s16 p2d, s16 precision);
};
struct MapgenFactory {
virtual Mapgen *createMapgen(int mgid, MapgenParams *params,
EmergeManager *emerge) = 0;
virtual MapgenParams *createMapgenParams() = 0;
};
class EmergeManager {
public:
std::map<std::string, MapgenFactory *> mglist;
//settings
MapgenParams *params;
//mapgen objects here
Mapgen *mapgen;
//biome manager
BiomeDefManager *biomedef;
EmergeManager(IGameDef *gamedef, BiomeDefManager *bdef);
~EmergeManager();
void initMapgens(MapgenParams *mgparams);
Mapgen *createMapgen(std::string mgname, int mgid,
MapgenParams *mgparams, EmergeManager *emerge);
MapgenParams *createMapgenParams(std::string mgname);
Mapgen *getMapgen();
void addBlockToQueue();
bool registerMapgen(std::string name, MapgenFactory *mgfactory);
MapgenParams *getParamsFromSettings(Settings *settings);
//mapgen helper methods
Biome *getBiomeAtPoint(v3s16 p);
int getGroundLevelAtPoint(v2s16 p);
bool isBlockUnderground(v3s16 blockpos);
u32 getBlockSeed(v3s16 p);
};
#endif

1426
src/mapgen_v6.cpp Normal file

File diff suppressed because it is too large Load Diff

141
src/mapgen_v6.h Normal file
View File

@ -0,0 +1,141 @@
/*
Minetest-c55
Copyright (C) 2010-2011 celeron55, Perttu Ahola <celeron55@gmail.com>
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU Lesser General Public License as published by
the Free Software Foundation; either version 2.1 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU Lesser General Public License for more details.
You should have received a copy of the GNU Lesser General Public License along
with this program; if not, write to the Free Software Foundation, Inc.,
51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
*/
#ifndef MAPGENV6_HEADER
#define MAPGENV6_HEADER
#include "mapgen.h"
#define AVERAGE_MUD_AMOUNT 4
enum BiomeType
{
BT_NORMAL,
BT_DESERT
};
extern NoiseParams nparams_v6_def_terrain_base;
extern NoiseParams nparams_v6_def_terrain_higher;
extern NoiseParams nparams_v6_def_steepness;
extern NoiseParams nparams_v6_def_height_select;
extern NoiseParams nparams_v6_def_trees;
extern NoiseParams nparams_v6_def_mud;
extern NoiseParams nparams_v6_def_beach;
extern NoiseParams nparams_v6_def_biome;
extern NoiseParams nparams_v6_def_cave;
struct MapgenV6Params : public MapgenParams {
float freq_desert;
float freq_beach;
NoiseParams *np_terrain_base;
NoiseParams *np_terrain_higher;
NoiseParams *np_steepness;
NoiseParams *np_height_select;
NoiseParams *np_trees;
NoiseParams *np_mud;
NoiseParams *np_beach;
NoiseParams *np_biome;
NoiseParams *np_cave;
MapgenV6Params() {
freq_desert = 0.45;
freq_beach = 0.15;
np_terrain_base = &nparams_v6_def_terrain_base;
np_terrain_higher = &nparams_v6_def_terrain_higher;
np_steepness = &nparams_v6_def_steepness;
np_height_select = &nparams_v6_def_height_select;
np_trees = &nparams_v6_def_trees;
np_mud = &nparams_v6_def_mud;
np_beach = &nparams_v6_def_beach;
np_biome = &nparams_v6_def_biome;
np_cave = &nparams_v6_def_cave;
}
bool readParams(Settings *settings);
void writeParams(Settings *settings);
};
class MapgenV6 : public Mapgen {
public:
//ManualMapVoxelManipulator &vmanip;
int ystride;
v3s16 csize;
v3s16 node_min;
v3s16 node_max;
Noise *noise_terrain_base;
Noise *noise_terrain_higher;
Noise *noise_steepness;
Noise *noise_height_select;
Noise *noise_trees;
Noise *noise_mud;
Noise *noise_beach;
Noise *noise_biome;
float *map_terrain_base;
float *map_terrain_higher;
float *map_steepness;
float *map_height_select;
float *map_trees;
float *map_mud;
float *map_beach;
float *map_biome;
NoiseParams *np_cave;
u32 flags;
float freq_desert;
float freq_beach;
MapgenV6(int mapgenid, MapgenV6Params *params);
~MapgenV6();
void makeChunk(BlockMakeData *data);
int getGroundLevelAtPoint(v2s16 p);
double baseRockLevelFromNoise(v2s16 p);
static s16 find_ground_level(VoxelManipulator &vmanip,
v2s16 p2d, INodeDefManager *ndef);
static s16 find_stone_level(VoxelManipulator &vmanip,
v2s16 p2d, INodeDefManager *ndef);
void make_tree(ManualMapVoxelManipulator &vmanip, v3s16 p0,
bool is_apple_tree, INodeDefManager *ndef);
double tree_amount_2d(u64 seed, v2s16 p);
bool block_is_underground(u64 seed, v3s16 blockpos);
double base_rock_level_2d(u64 seed, v2s16 p);
s16 find_ground_level_from_noise(u64 seed, v2s16 p2d, s16 precision);
double get_mud_add_amount(u64 seed, v2s16 p);
bool get_have_beach(u64 seed, v2s16 p2d);
BiomeType get_biome(u64 seed, v2s16 p2d);
u32 get_blockseed(u64 seed, v3s16 p);
};
struct MapgenFactoryV6 : public MapgenFactory {
Mapgen *createMapgen(int mgid, MapgenParams *params, EmergeManager *emerge) {
return new MapgenV6(mgid, (MapgenV6Params *)params);
};
MapgenParams *createMapgenParams() {
return new MapgenV6Params();
};
};
#endif

View File

@ -18,23 +18,16 @@ with this program; if not, write to the Free Software Foundation, Inc.,
*/
#include "mods.h"
#include <queue>
#include <fstream>
#include <sstream>
#include <map>
#include "filesys.h"
#include "strfnd.h"
#include "log.h"
#include "subgame.h"
#include "settings.h"
static void collectMods(const std::string &modspath,
std::queue<ModSpec> &mods_satisfied,
core::list<ModSpec> &mods_unsorted,
std::map<std::string, std::string> &mod_names,
std::string indentation)
std::map<std::string, ModSpec> getModsInPath(std::string path)
{
TRACESTREAM(<<indentation<<"collectMods(\""<<modspath<<"\")"<<std::endl);
TRACEDO(indentation += " ");
std::vector<fs::DirListNode> dirlist = fs::GetDirListing(modspath);
std::map<std::string, ModSpec> result;
std::vector<fs::DirListNode> dirlist = fs::GetDirListing(path);
for(u32 j=0; j<dirlist.size(); j++){
if(!dirlist[j].dir)
continue;
@ -43,119 +36,187 @@ static void collectMods(const std::string &modspath,
// VCS directories like ".git" or ".svn"
if(modname[0] == '.')
continue;
std::string modpath = modspath + DIR_DELIM + modname;
TRACESTREAM(<<indentation<<"collectMods: "<<modname<<" at \""<<modpath<<"\""<<std::endl);
std::string modpath = path + DIR_DELIM + modname;
// Handle modpacks (defined by containing modpack.txt)
{
std::ifstream is((modpath+DIR_DELIM+"modpack.txt").c_str(),
std::ifstream modpack_is((modpath+DIR_DELIM+"modpack.txt").c_str(),
std::ios_base::binary);
if(is.good()){
// Is a modpack
is.close(); // We don't actually need the file
// Recurse into it
collectMods(modpath, mods_satisfied, mods_unsorted, mod_names, indentation);
continue;
}
}
// Detect mod name conflicts
if(modpack_is.good()) //a modpack, recursively get the mods in it
{
std::map<std::string, std::string>::const_iterator i;
i = mod_names.find(modname);
if(i != mod_names.end()){
std::string s;
infostream<<indentation<<"WARNING: Mod name conflict detected: "
<<std::endl
<<"Already loaded: "<<i->second<<std::endl
<<"Will not load: "<<modpath<<std::endl;
continue;
}
modpack_is.close(); // We don't actually need the file
ModSpec spec(modname,modpath);
spec.modpack_content = getModsInPath(modpath);
spec.is_modpack = true;
result.insert(std::make_pair(modname,spec));
}
else // not a modpack, add the modspec
{
std::set<std::string> depends;
std::ifstream is((modpath+DIR_DELIM+"depends.txt").c_str(),
std::ios_base::binary);
while(is.good()){
while(is.good())
{
std::string dep;
std::getline(is, dep);
dep = trim(dep);
if(dep != "")
depends.insert(dep);
}
ModSpec spec(modname, modpath, depends);
mods_unsorted.push_back(spec);
if(depends.empty())
mods_satisfied.push(spec);
mod_names[modname] = modpath;
result.insert(std::make_pair(modname,spec));
}
}
return result;
}
// Get a dependency-sorted list of ModSpecs
core::list<ModSpec> getMods(core::list<std::string> &modspaths)
throw(ModError)
std::map<std::string, ModSpec> flattenModTree(std::map<std::string, ModSpec> mods)
{
std::queue<ModSpec> mods_satisfied;
core::list<ModSpec> mods_unsorted;
core::list<ModSpec> mods_sorted;
// name, path: For detecting name conflicts
std::map<std::string, std::string> mod_names;
for(core::list<std::string>::Iterator i = modspaths.begin();
i != modspaths.end(); i++){
std::string modspath = *i;
collectMods(modspath, mods_satisfied, mods_unsorted, mod_names, "");
std::map<std::string, ModSpec> result;
for(std::map<std::string,ModSpec>::iterator it = mods.begin();
it != mods.end(); ++it)
{
ModSpec mod = (*it).second;
if(mod.is_modpack)
{
std::map<std::string, ModSpec> content =
flattenModTree(mod.modpack_content);
result.insert(content.begin(),content.end());
result.insert(std::make_pair(mod.name,mod));
}
// Sort by depencencies
while(!mods_satisfied.empty()){
ModSpec mod = mods_satisfied.front();
mods_satisfied.pop();
mods_sorted.push_back(mod);
for(core::list<ModSpec>::Iterator i = mods_unsorted.begin();
i != mods_unsorted.end(); i++){
ModSpec &mod2 = *i;
if(mod2.unsatisfied_depends.empty())
continue;
mod2.unsatisfied_depends.erase(mod.name);
if(!mod2.unsatisfied_depends.empty())
continue;
mods_satisfied.push(mod2);
else //not a modpack
{
result.insert(std::make_pair(mod.name,mod));
}
}
std::ostringstream errs(std::ios::binary);
// Check unsatisfied dependencies
for(core::list<ModSpec>::Iterator i = mods_unsorted.begin();
i != mods_unsorted.end(); i++){
ModSpec &mod = *i;
if(mod.unsatisfied_depends.empty())
continue;
errs<<"mod \""<<mod.name
<<"\" has unsatisfied dependencies:";
for(std::set<std::string>::iterator
i = mod.unsatisfied_depends.begin();
i != mod.unsatisfied_depends.end(); i++){
errs<<" \""<<(*i)<<"\"";
return result;
}
std::vector<ModSpec> flattenMods(std::map<std::string, ModSpec> mods)
{
std::vector<ModSpec> result;
for(std::map<std::string,ModSpec>::iterator it = mods.begin();
it != mods.end(); ++it)
{
ModSpec mod = (*it).second;
if(mod.is_modpack)
{
std::vector<ModSpec> content = flattenMods(mod.modpack_content);
result.reserve(result.size() + content.size());
result.insert(result.end(),content.begin(),content.end());
}
errs<<"."<<std::endl;
mods_sorted.push_back(mod);
else //not a modpack
{
// infostream << "inserting mod " << mod.name << std::endl;
result.push_back(mod);
}
// If an error occurred, throw an exception
if(errs.str().size() != 0){
throw ModError(errs.str());
}
// Print out some debug info
TRACESTREAM(<<"Detected mods in load order:"<<std::endl);
for(core::list<ModSpec>::Iterator i = mods_sorted.begin();
i != mods_sorted.end(); i++){
ModSpec &mod = *i;
TRACESTREAM(<<"name=\""<<mod.name<<"\" path=\""<<mod.path<<"\"");
TRACESTREAM(<<" depends=[");
for(std::set<std::string>::iterator i = mod.depends.begin();
i != mod.depends.end(); i++)
TRACESTREAM(<<" "<<(*i));
TRACESTREAM(<<" ] unsatisfied_depends=[");
for(std::set<std::string>::iterator i = mod.unsatisfied_depends.begin();
i != mod.unsatisfied_depends.end(); i++)
TRACESTREAM(<<" "<<(*i));
TRACESTREAM(<<" ]"<<std::endl);
return result;
}
std::vector<ModSpec> filterMods(std::vector<ModSpec> mods,
std::set<std::string> exclude_mod_names)
{
std::vector<ModSpec> result;
for(std::vector<ModSpec>::iterator it = mods.begin();
it != mods.end(); ++it)
{
ModSpec& mod = *it;
if(exclude_mod_names.count(mod.name) == 0)
result.push_back(mod);
}
return mods_sorted;
return result;
}
void ModConfiguration::addModsInPathFiltered(std::string path, std::set<std::string> exclude_mods)
{
addMods(filterMods(flattenMods(getModsInPath(path)),exclude_mods));
}
void ModConfiguration::addMods(std::vector<ModSpec> new_mods)
{
// Step 1: remove mods in sorted_mods from unmet dependencies
// of new_mods. new mods without unmet dependencies are
// temporarily stored in satisfied_mods
std::vector<ModSpec> satisfied_mods;
for(std::vector<ModSpec>::iterator it = m_sorted_mods.begin();
it != m_sorted_mods.end(); ++it)
{
ModSpec mod = *it;
for(std::vector<ModSpec>::iterator it_new = new_mods.begin();
it_new != new_mods.end(); ++it_new)
{
ModSpec& mod_new = *it_new;
//infostream << "erasing dependency " << mod.name << " from " << mod_new.name << std::endl;
mod_new.unsatisfied_depends.erase(mod.name);
}
}
// split new mods into satisfied and unsatisfied
for(std::vector<ModSpec>::iterator it = new_mods.begin();
it != new_mods.end(); ++it)
{
ModSpec mod_new = *it;
if(mod_new.unsatisfied_depends.empty())
satisfied_mods.push_back(mod_new);
else
m_unsatisfied_mods.push_back(mod_new);
}
// Step 2: mods without unmet dependencies can be appended to
// the sorted list.
while(!satisfied_mods.empty())
{
ModSpec mod = satisfied_mods.back();
m_sorted_mods.push_back(mod);
satisfied_mods.pop_back();
for(std::list<ModSpec>::iterator it = m_unsatisfied_mods.begin();
it != m_unsatisfied_mods.end(); )
{
ModSpec& mod2 = *it;
mod2.unsatisfied_depends.erase(mod.name);
if(mod2.unsatisfied_depends.empty())
{
satisfied_mods.push_back(mod2);
it = m_unsatisfied_mods.erase(it);
}
else
++it;
}
}
}
ModConfiguration::ModConfiguration(std::string worldpath)
{
// Add all world mods and all game mods
addModsInPath(worldpath + DIR_DELIM + "worldmods");
SubgameSpec gamespec = findWorldSubgame(worldpath);
addModsInPath(gamespec.gamemods_path);
// check world.mt file for mods explicitely declared to be
// loaded or not by a load_mod_<modname> = ... line.
std::string worldmt = worldpath+DIR_DELIM+"world.mt";
Settings worldmt_settings;
worldmt_settings.readConfigFile(worldmt.c_str());
std::vector<std::string> names = worldmt_settings.getNames();
std::set<std::string> exclude_mod_names;
for(std::vector<std::string>::iterator it = names.begin();
it != names.end(); ++it)
{
std::string name = *it;
// for backwards compatibility: exclude only mods which are
// explicitely excluded. if mod is not mentioned at all, it is
// enabled. So by default, all installed mods are enabled.
if (name.compare(0,9,"load_mod_") == 0 &&
!worldmt_settings.getBool(name))
{
exclude_mod_names.insert(name.substr(9));
}
}
for(std::set<std::string>::const_iterator i = gamespec.addon_mods_paths.begin();
i != gamespec.addon_mods_paths.end(); ++i)
addModsInPathFiltered((*i),exclude_mod_names);
}

View File

@ -22,8 +22,11 @@ with this program; if not, write to the Free Software Foundation, Inc.,
#include "irrlichttypes.h"
#include <irrList.h>
#include <list>
#include <set>
#include <vector>
#include <string>
#include <map>
#include <exception>
class ModError : public std::exception
@ -47,21 +50,96 @@ struct ModSpec
{
std::string name;
std::string path;
//if normal mod:
std::set<std::string> depends;
std::set<std::string> unsatisfied_depends;
ModSpec(const std::string &name_="", const std::string path_="",
const std::set<std::string> &depends_=std::set<std::string>()):
bool is_modpack;
// if modpack:
std::map<std::string,ModSpec> modpack_content;
ModSpec(const std::string name_="", const std::string path_="",
const std::set<std::string> depends_=std::set<std::string>()):
name(name_),
path(path_),
depends(depends_),
unsatisfied_depends(depends_)
unsatisfied_depends(depends_),
is_modpack(false),
modpack_content()
{}
};
// Get a dependency-sorted list of ModSpecs
core::list<ModSpec> getMods(core::list<std::string> &modspaths)
throw(ModError);
std::map<std::string,ModSpec> getModsInPath(std::string path);
// expands modpack contents, but does not replace them.
std::map<std::string, ModSpec> flattenModTree(std::map<std::string, ModSpec> mods);
// replaces modpack Modspecs with their content
std::vector<ModSpec> flattenMods(std::map<std::string,ModSpec> mods);
// removes Mods mentioned in exclude_mod_names
std::vector<ModSpec> filterMods(std::vector<ModSpec> mods,
std::set<std::string> exclude_mod_names);
// a ModConfiguration is a subset of installed mods, expected to have
// all dependencies fullfilled, so it can be used as a list of mods to
// load when the game starts.
class ModConfiguration
{
public:
ModConfiguration():
m_unsatisfied_mods(),
m_sorted_mods()
{}
ModConfiguration(std::string worldpath);
// adds all mods in the given path. used for games, modpacks
// and world-specific mods (worldmods-folders)
void addModsInPath(std::string path)
{
addMods(flattenMods(getModsInPath(path)));
}
// adds all mods in the given path whose name does not appear
// in the exclude_mods set.
void addModsInPathFiltered(std::string path, std::set<std::string> exclude_mods);
// adds all mods in the set.
void addMods(std::vector<ModSpec> mods);
// checks if all dependencies are fullfilled.
bool isConsistent()
{
return m_unsatisfied_mods.empty();
}
std::vector<ModSpec> getMods()
{
return m_sorted_mods;
}
std::list<ModSpec> getUnsatisfiedMods()
{
return m_unsatisfied_mods;
}
private:
// mods with unmet dependencies. This is a list and not a
// vector because we want easy removal of elements at every
// position.
std::list<ModSpec> m_unsatisfied_mods;
// list of mods sorted such that they can be loaded in the
// given order with all dependencies being fullfilled. I.e.,
// every mod in this list has only dependencies on mods which
// appear earlier in the vector.
std::vector<ModSpec> m_sorted_mods;
};
#endif

View File

@ -21,89 +21,116 @@ with this program; if not, write to the Free Software Foundation, Inc.,
#include "noise.h"
#include <iostream>
#include "debug.h"
#include "util/numeric.h"
#define NOISE_MAGIC_X 1619
#define NOISE_MAGIC_Y 31337
#define NOISE_MAGIC_Z 52591
#define NOISE_MAGIC_SEED 1013
double cos_lookup[16] = {
1.0,0.9238,0.7071,0.3826,0,-0.3826,-0.7071,-0.9238,
1.0,-0.9238,-0.7071,-0.3826,0,0.3826,0.7071,0.9238
float cos_lookup[16] = {
1.0, 0.9238, 0.7071, 0.3826, 0, -0.3826, -0.7071, -0.9238,
1.0, -0.9238, -0.7071, -0.3826, 0, 0.3826, 0.7071, 0.9238
};
double dotProduct(double vx, double vy, double wx, double wy){
return vx*wx+vy*wy;
}
double easeCurve(double t){
return t * t * t * (6. * t * t - 15. * t + 10.);
}
///////////////////////////////////////////////////////////////////////////////
double linearInterpolation(double x0, double x1, double t){
return x0+(x1-x0)*t;
}
double biLinearInterpolation(double x0y0, double x1y0, double x0y1, double x1y1, double x, double y){
double tx = easeCurve(x);
double ty = easeCurve(y);
/*double tx = x;
double ty = y;*/
double u = linearInterpolation(x0y0,x1y0,tx);
double v = linearInterpolation(x0y1,x1y1,tx);
return linearInterpolation(u,v,ty);
}
double triLinearInterpolation(
double v000, double v100, double v010, double v110,
double v001, double v101, double v011, double v111,
double x, double y, double z)
{
/*double tx = easeCurve(x);
double ty = easeCurve(y);
double tz = easeCurve(z);*/
double tx = x;
double ty = y;
double tz = z;
return(
v000*(1-tx)*(1-ty)*(1-tz) +
v100*tx*(1-ty)*(1-tz) +
v010*(1-tx)*ty*(1-tz) +
v110*tx*ty*(1-tz) +
v001*(1-tx)*(1-ty)*tz +
v101*tx*(1-ty)*tz +
v011*(1-tx)*ty*tz +
v111*tx*ty*tz
);
}
double noise2d(int x, int y, int seed)
{
//noise poly: p(n) = 60493n^3 + 19990303n + 137612589
float noise2d(int x, int y, int seed) {
int n = (NOISE_MAGIC_X * x + NOISE_MAGIC_Y * y
+ NOISE_MAGIC_SEED * seed) & 0x7fffffff;
n = (n>>13)^n;
n = (n * (n*n*60493+19990303) + 1376312589) & 0x7fffffff;
return 1.0 - (double)n/1073741824;
n = (n >> 13) ^ n;
n = (n * (n * n * 60493 + 19990303) + 1376312589) & 0x7fffffff;
return 1.f - (float)n / 0x40000000;
}
double noise3d(int x, int y, int z, int seed)
{
float noise3d(int x, int y, int z, int seed) {
int n = (NOISE_MAGIC_X * x + NOISE_MAGIC_Y * y + NOISE_MAGIC_Z * z
+ NOISE_MAGIC_SEED * seed) & 0x7fffffff;
n = (n>>13)^n;
n = (n * (n*n*60493+19990303) + 1376312589) & 0x7fffffff;
return 1.0 - (double)n/1073741824;
n = (n >> 13) ^ n;
n = (n * (n * n * 60493 + 19990303) + 1376312589) & 0x7fffffff;
return 1.f - (float)n / 0x40000000;
}
float dotProduct(float vx, float vy, float wx, float wy) {
return vx * wx + vy * wy;
}
inline float linearInterpolation(float v0, float v1, float t) {
return v0 + (v1 - v0) * t;
}
float biLinearInterpolation(float v00, float v10,
float v01, float v11,
float x, float y) {
float tx = easeCurve(x);
float ty = easeCurve(y);
float u = linearInterpolation(v00, v10, tx);
float v = linearInterpolation(v01, v11, tx);
return linearInterpolation(u, v, ty);
}
float biLinearInterpolationNoEase(float x0y0, float x1y0,
float x0y1, float x1y1,
float x, float y) {
float u = linearInterpolation(x0y0, x1y0, x);
float v = linearInterpolation(x0y1, x1y1, x);
return linearInterpolation(u, v, y);
}
float triLinearInterpolation(
float v000, float v100, float v010, float v110,
float v001, float v101, float v011, float v111,
float x, float y, float z) {
float u = biLinearInterpolationNoEase(v000, v100, v010, v110, x, y);
float v = biLinearInterpolationNoEase(v001, v101, v011, v111, x, y);
return linearInterpolation(u, v, z);
}
#if 0
double noise2d_gradient(double x, double y, int seed)
float triLinearInterpolation(
float v000, float v100, float v010, float v110,
float v001, float v101, float v011, float v111,
float x, float y, float z)
{
/*float tx = easeCurve(x);
float ty = easeCurve(y);
float tz = easeCurve(z);*/
float tx = x;
float ty = y;
float tz = z;
return(
v000 * (1 - tx) * (1 - ty) * (1 - tz) +
v100 * tx * (1 - ty) * (1 - tz) +
v010 * (1 - tx) * ty * (1 - tz) +
v110 * tx * ty * (1 - tz) +
v001 * (1 - tx) * (1 - ty) * tz +
v101 * tx * (1 - ty) * tz +
v011 * (1 - tx) * ty * tz +
v111 * tx * ty * tz
);
}
#endif
#if 0
float noise2d_gradient(float x, float y, int seed)
{
// Calculate the integer coordinates
int x0 = (x > 0.0 ? (int)x : (int)x - 1);
int y0 = (y > 0.0 ? (int)y : (int)y - 1);
// Calculate the remaining part of the coordinates
double xl = x - (double)x0;
double yl = y - (double)y0;
float xl = x - (float)x0;
float yl = y - (float)y0;
// Calculate random cosine lookup table indices for the integer corners.
// They are looked up as unit vector gradients from the lookup table.
int n00 = (int)((noise2d(x0, y0, seed)+1)*8);
@ -111,119 +138,126 @@ double noise2d_gradient(double x, double y, int seed)
int n01 = (int)((noise2d(x0, y0+1, seed)+1)*8);
int n11 = (int)((noise2d(x0+1, y0+1, seed)+1)*8);
// Make a dot product for the gradients and the positions, to get the values
double s = dotProduct(cos_lookup[n00], cos_lookup[(n00+12)%16], xl, yl);
double u = dotProduct(-cos_lookup[n10], cos_lookup[(n10+12)%16], 1.-xl, yl);
double v = dotProduct(cos_lookup[n01], -cos_lookup[(n01+12)%16], xl, 1.-yl);
double w = dotProduct(-cos_lookup[n11], -cos_lookup[(n11+12)%16], 1.-xl, 1.-yl);
float s = dotProduct(cos_lookup[n00], cos_lookup[(n00+12)%16], xl, yl);
float u = dotProduct(-cos_lookup[n10], cos_lookup[(n10+12)%16], 1.-xl, yl);
float v = dotProduct(cos_lookup[n01], -cos_lookup[(n01+12)%16], xl, 1.-yl);
float w = dotProduct(-cos_lookup[n11], -cos_lookup[(n11+12)%16], 1.-xl, 1.-yl);
// Interpolate between the values
return biLinearInterpolation(s,u,v,w,xl,yl);
}
#endif
#if 1
double noise2d_gradient(double x, double y, int seed)
float noise2d_gradient(float x, float y, int seed)
{
// Calculate the integer coordinates
int x0 = (x > 0.0 ? (int)x : (int)x - 1);
int y0 = (y > 0.0 ? (int)y : (int)y - 1);
int x0 = myfloor(x);
int y0 = myfloor(y);
// Calculate the remaining part of the coordinates
double xl = x - (double)x0;
double yl = y - (double)y0;
// Get values for corners of cube
double v00 = noise2d(x0, y0, seed);
double v10 = noise2d(x0+1, y0, seed);
double v01 = noise2d(x0, y0+1, seed);
double v11 = noise2d(x0+1, y0+1, seed);
float xl = x - (float)x0;
float yl = y - (float)y0;
// Get values for corners of square
float v00 = noise2d(x0, y0, seed);
float v10 = noise2d(x0+1, y0, seed);
float v01 = noise2d(x0, y0+1, seed);
float v11 = noise2d(x0+1, y0+1, seed);
// Interpolate
return biLinearInterpolation(v00,v10,v01,v11,xl,yl);
}
#endif
double noise3d_gradient(double x, double y, double z, int seed)
float noise3d_gradient(float x, float y, float z, int seed)
{
// Calculate the integer coordinates
int x0 = (x > 0.0 ? (int)x : (int)x - 1);
int y0 = (y > 0.0 ? (int)y : (int)y - 1);
int z0 = (z > 0.0 ? (int)z : (int)z - 1);
int x0 = myfloor(x);
int y0 = myfloor(y);
int z0 = myfloor(z);
// Calculate the remaining part of the coordinates
double xl = x - (double)x0;
double yl = y - (double)y0;
double zl = z - (double)z0;
float xl = x - (float)x0;
float yl = y - (float)y0;
float zl = z - (float)z0;
// Get values for corners of cube
double v000 = noise3d(x0, y0, z0, seed);
double v100 = noise3d(x0+1, y0, z0, seed);
double v010 = noise3d(x0, y0+1, z0, seed);
double v110 = noise3d(x0+1, y0+1, z0, seed);
double v001 = noise3d(x0, y0, z0+1, seed);
double v101 = noise3d(x0+1, y0, z0+1, seed);
double v011 = noise3d(x0, y0+1, z0+1, seed);
double v111 = noise3d(x0+1, y0+1, z0+1, seed);
float v000 = noise3d(x0, y0, z0, seed);
float v100 = noise3d(x0 + 1, y0, z0, seed);
float v010 = noise3d(x0, y0 + 1, z0, seed);
float v110 = noise3d(x0 + 1, y0 + 1, z0, seed);
float v001 = noise3d(x0, y0, z0 + 1, seed);
float v101 = noise3d(x0 + 1, y0, z0 + 1, seed);
float v011 = noise3d(x0, y0 + 1, z0 + 1, seed);
float v111 = noise3d(x0 + 1, y0 + 1, z0 + 1, seed);
// Interpolate
return triLinearInterpolation(v000,v100,v010,v110,v001,v101,v011,v111,xl,yl,zl);
return triLinearInterpolation(v000, v100, v010, v110,
v001, v101, v011, v111,
xl, yl, zl);
}
double noise2d_perlin(double x, double y, int seed,
int octaves, double persistence)
float noise2d_perlin(float x, float y, int seed,
int octaves, float persistence)
{
double a = 0;
double f = 1.0;
double g = 1.0;
for(int i=0; i<octaves; i++)
float a = 0;
float f = 1.0;
float g = 1.0;
for (int i = 0; i < octaves; i++)
{
a += g * noise2d_gradient(x*f, y*f, seed+i);
a += g * noise2d_gradient(x * f, y * f, seed + i);
f *= 2.0;
g *= persistence;
}
return a;
}
double noise2d_perlin_abs(double x, double y, int seed,
int octaves, double persistence)
float noise2d_perlin_abs(float x, float y, int seed,
int octaves, float persistence)
{
double a = 0;
double f = 1.0;
double g = 1.0;
for(int i=0; i<octaves; i++)
float a = 0;
float f = 1.0;
float g = 1.0;
for (int i = 0; i < octaves; i++)
{
a += g * fabs(noise2d_gradient(x*f, y*f, seed+i));
a += g * fabs(noise2d_gradient(x * f, y * f, seed + i));
f *= 2.0;
g *= persistence;
}
return a;
}
double noise3d_perlin(double x, double y, double z, int seed,
int octaves, double persistence)
float noise3d_perlin(float x, float y, float z, int seed,
int octaves, float persistence)
{
double a = 0;
double f = 1.0;
double g = 1.0;
for(int i=0; i<octaves; i++)
float a = 0;
float f = 1.0;
float g = 1.0;
for (int i = 0; i < octaves; i++)
{
a += g * noise3d_gradient(x*f, y*f, z*f, seed+i);
a += g * noise3d_gradient(x * f, y * f, z * f, seed + i);
f *= 2.0;
g *= persistence;
}
return a;
}
double noise3d_perlin_abs(double x, double y, double z, int seed,
int octaves, double persistence)
float noise3d_perlin_abs(float x, float y, float z, int seed,
int octaves, float persistence)
{
double a = 0;
double f = 1.0;
double g = 1.0;
for(int i=0; i<octaves; i++)
float a = 0;
float f = 1.0;
float g = 1.0;
for (int i = 0; i < octaves; i++)
{
a += g * fabs(noise3d_gradient(x*f, y*f, z*f, seed+i));
a += g * fabs(noise3d_gradient(x * f, y * f, z * f, seed + i));
f *= 2.0;
g *= persistence;
}
return a;
}
// -1->0, 0->1, 1->0
double contour(double v)
float contour(float v)
{
v = fabs(v);
if(v >= 1.0)
@ -231,195 +265,323 @@ double contour(double v)
return (1.0-v);
}
double noise3d_param(const NoiseParams &param, double x, double y, double z)
{
double s = param.pos_scale;
x /= s;
y /= s;
z /= s;
if(param.type == NOISE_CONSTANT_ONE)
{
return 1.0;
}
else if(param.type == NOISE_PERLIN)
{
return param.noise_scale*noise3d_perlin(x,y,z, param.seed,
param.octaves,
param.persistence);
}
else if(param.type == NOISE_PERLIN_ABS)
{
return param.noise_scale*noise3d_perlin_abs(x,y,z, param.seed,
param.octaves,
param.persistence);
}
else if(param.type == NOISE_PERLIN_CONTOUR)
{
return contour(param.noise_scale*noise3d_perlin(x,y,z,
param.seed, param.octaves,
param.persistence));
}
else if(param.type == NOISE_PERLIN_CONTOUR_FLIP_YZ)
{
return contour(param.noise_scale*noise3d_perlin(x,z,y,
param.seed, param.octaves,
param.persistence));
}
else assert(0);
///////////////////////// [ New perlin stuff ] ////////////////////////////
Noise::Noise(NoiseParams *np, int seed, int sx, int sy) {
init(np, seed, sx, sy, 1);
}
Noise::Noise(NoiseParams *np, int seed, int sx, int sy, int sz) {
init(np, seed, sx, sy, sz);
}
void Noise::init(NoiseParams *np, int seed, int sx, int sy, int sz) {
this->np = np;
this->seed = seed;
this->sx = sx;
this->sy = sy;
this->sz = sz;
this->noisebuf = NULL;
resizeNoiseBuf(sz > 1);
this->buf = new float[sx * sy * sz];
this->result = new float[sx * sy * sz];
}
Noise::~Noise() {
delete[] buf;
delete[] result;
delete[] noisebuf;
}
void Noise::setSize(int sx, int sy) {
setSize(sx, sy, 1);
}
void Noise::setSize(int sx, int sy, int sz) {
this->sx = sx;
this->sy = sy;
this->sz = sz;
this->noisebuf = NULL;
resizeNoiseBuf(sz > 1);
delete[] buf;
delete[] result;
this->buf = new float[sx * sy * sz];
this->result = new float[sx * sy * sz];
}
void Noise::setSpreadFactor(v3f spread) {
this->np->spread = spread;
resizeNoiseBuf(sz > 1);
}
void Noise::setOctaves(int octaves) {
this->np->octaves = octaves;
resizeNoiseBuf(sz > 1);
}
void Noise::resizeNoiseBuf(bool is3d) {
int nlx, nly, nlz;
float ofactor;
//maximum possible spread value factor
ofactor = (float)(1 << (np->octaves - 1));
//noise lattice point count
//(int)(sz * spread * ofactor) is # of lattice points crossed due to length
// + 2 for the two initial endpoints
// + 1 for potentially crossing a boundary due to offset
nlx = (int)(sx * ofactor / np->spread.X) + 3;
nly = (int)(sy * ofactor / np->spread.Y) + 3;
nlz = is3d ? (int)(sz * ofactor / np->spread.Z) + 3 : 1;
if (noisebuf)
delete[] noisebuf;
noisebuf = new float[nlx * nly * nlz];
}
/*
NoiseBuffer
*/
* NB: This algorithm is not optimal in terms of space complexity. The entire
* integer lattice of noise points could be done as 2 lines instead, and for 3D,
* 2 lines + 2 planes.
* However, this would require the noise calls to be interposed with the
* interpolation loops, which may trash the icache, leading to lower overall
* performance.
* Another optimization that could save half as many noise calls is to carry over
* values from the previous noise lattice as midpoints in the new lattice for the
* next octave.
*/
void Noise::gradientMap2D(float x, float y, float step_x, float step_y, int seed) {
float v00, v01, v10, v11, u, v, orig_u;
int index, i, j, x0, y0, noisex, noisey;
int nlx, nly;
NoiseBuffer::NoiseBuffer():
m_data(NULL)
{
}
x0 = floor(x);
y0 = floor(y);
u = x - (float)x0;
v = y - (float)y0;
orig_u = u;
NoiseBuffer::~NoiseBuffer()
{
clear();
}
//calculate noise point lattice
nlx = (int)(u + sx * step_x) + 2;
nly = (int)(v + sy * step_y) + 2;
index = 0;
for (j = 0; j != nly; j++)
for (i = 0; i != nlx; i++)
noisebuf[index++] = noise2d(x0 + i, y0 + j, seed);
void NoiseBuffer::clear()
{
if(m_data)
delete[] m_data;
m_data = NULL;
m_size_x = 0;
m_size_y = 0;
m_size_z = 0;
}
//calculate interpolations
noisey = 0;
for (j = 0; j != sy; j++) {
v00 = noisebuf[noisey * nlx];
v10 = noisebuf[noisey * nlx + 1];
v01 = noisebuf[(noisey + 1) * nlx];
v11 = noisebuf[(noisey + 1) * nlx + 1];
void NoiseBuffer::create(const NoiseParams &param,
double first_x, double first_y, double first_z,
double last_x, double last_y, double last_z,
double samplelength_x, double samplelength_y, double samplelength_z)
{
clear();
u = orig_u;
noisex = 0;
for (i = 0; i != sx; i++) {
buf[j * sx + i] = biLinearInterpolation(v00, v10, v01, v11, u, v);
u += step_x;
if (u >= 1.0) {
u -= 1.0;
noisex++;
v00 = v10;
v01 = v11;
v10 = noisebuf[noisey * nlx + noisex + 1];
v11 = noisebuf[(noisey + 1) * nlx + noisex + 1];
}
}
m_start_x = first_x - samplelength_x;
m_start_y = first_y - samplelength_y;
m_start_z = first_z - samplelength_z;
m_samplelength_x = samplelength_x;
m_samplelength_y = samplelength_y;
m_samplelength_z = samplelength_z;
m_size_x = (last_x - m_start_x)/samplelength_x + 2;
m_size_y = (last_y - m_start_y)/samplelength_y + 2;
m_size_z = (last_z - m_start_z)/samplelength_z + 2;
m_data = new double[m_size_x*m_size_y*m_size_z];
for(int x=0; x<m_size_x; x++)
for(int y=0; y<m_size_y; y++)
for(int z=0; z<m_size_z; z++)
{
double xd = (m_start_x + (double)x*m_samplelength_x);
double yd = (m_start_y + (double)y*m_samplelength_y);
double zd = (m_start_z + (double)z*m_samplelength_z);
double a = noise3d_param(param, xd,yd,zd);
intSet(x,y,z, a);
v += step_y;
if (v >= 1.0) {
v -= 1.0;
noisey++;
}
}
}
void NoiseBuffer::multiply(const NoiseParams &param)
{
assert(m_data != NULL);
for(int x=0; x<m_size_x; x++)
for(int y=0; y<m_size_y; y++)
for(int z=0; z<m_size_z; z++)
{
double xd = (m_start_x + (double)x*m_samplelength_x);
double yd = (m_start_y + (double)y*m_samplelength_y);
double zd = (m_start_z + (double)z*m_samplelength_z);
double a = noise3d_param(param, xd,yd,zd);
intMultiply(x,y,z, a);
void Noise::gradientMap3D(float x, float y, float z,
float step_x, float step_y, float step_z,
int seed) {
float v000, v010, v100, v110;
float v001, v011, v101, v111;
float u, v, w, orig_u, orig_w;
int index, i, j, k, x0, y0, z0, noisex, noisey, noisez;
int nlx, nly, nlz;
x0 = floor(x);
y0 = floor(y);
z0 = floor(z);
u = x - (float)x0;
v = y - (float)y0;
w = z - (float)z0;
orig_u = u;
orig_w = w;
//calculate noise point lattice
nlx = (int)(u + sx * step_x) + 2;
nly = (int)(v + sy * step_y) + 2;
nlz = (int)(v + sy * step_z) + 2;
index = 0;
for (k = 0; k != nlz; k++)
for (j = 0; j != nly; j++)
for (i = 0; i != nlx; i++)
noisebuf[index++] = noise3d(x0 + i, y0 + j, z0 + k, seed);
#define index(x, y, z) ((z) * nly * nlx + (y) * nlx + (x))
//calculate interpolations
noisey = 0;
noisez = 0;
for (k = 0; k != sz; k++) {
v000 = noisebuf[index(0, noisey, noisez)];
v100 = noisebuf[index(1, noisey, noisez)];
v010 = noisebuf[index(0, noisey + 1, noisez)];
v110 = noisebuf[index(1, noisey + 1, noisez)];
v001 = noisebuf[index(0, noisey, noisez + 1)];
v101 = noisebuf[index(1, noisey, noisez + 1)];
v011 = noisebuf[index(0, noisey + 1, noisez + 1)];
v111 = noisebuf[index(1, noisey + 1, noisez + 1)];
w = orig_w;
noisey = 0;
for (j = 0; j != sy; j++) {
v000 = noisebuf[index(0, noisey, noisez)];
v100 = noisebuf[index(1, noisey, noisez)];
v010 = noisebuf[index(0, noisey + 1, noisez)];
v110 = noisebuf[index(1, noisey + 1, noisez)];
v001 = noisebuf[index(0, noisey, noisez + 1)];
v101 = noisebuf[index(1, noisey, noisez + 1)];
v011 = noisebuf[index(0, noisey + 1, noisez + 1)];
v111 = noisebuf[index(1, noisey + 1, noisez + 1)];
u = orig_u;
noisex = 0;
for (i = 0; i != sx; i++) {
buf[j * sx + i] = triLinearInterpolation(
v000, v100, v010, v110,
v001, v101, v011, v111,
u, v, w);
u += step_x;
if (u >= 1.0) {
u -= 1.0;
noisex++;
v000 = v100;
v010 = v110;
v100 = noisebuf[index(noisex + 1, noisey, noisez)];
v110 = noisebuf[index(noisex + 1, noisey + 1, noisez)];
v001 = v101;
v011 = v111;
v101 = noisebuf[index(noisex + 1, noisey, noisez + 1)];
v111 = noisebuf[index(noisex + 1, noisey + 1, noisez + 1)];
}
}
v += step_y;
if (v >= 1.0) {
v -= 1.0;
noisey++;
}
}
w += step_z;
if (w >= 1.0) {
w -= 1.0;
noisez++;
}
}
}
// Deprecated
void NoiseBuffer::create(int seed, int octaves, double persistence,
bool abs,
double first_x, double first_y, double first_z,
double last_x, double last_y, double last_z,
double samplelength_x, double samplelength_y, double samplelength_z)
{
NoiseParams param;
param.type = abs ? NOISE_PERLIN_ABS : NOISE_PERLIN;
param.seed = seed;
param.octaves = octaves;
param.persistence = persistence;
create(param, first_x, first_y, first_z,
last_x, last_y, last_z,
samplelength_x, samplelength_y, samplelength_z);
float *Noise::perlinMap2D(float x, float y) {
float a = 0.0, f = 1.0, g = 1.0;
int i, j, index, oct;
x /= np->spread.X;
y /= np->spread.Y;
memset(result, 0, sizeof(float) * sx * sy);
for (oct = 0; oct < np->octaves; oct++) {
gradientMap2D(x * f, y * f,
f / np->spread.X, f / np->spread.Y,
seed + np->seed + oct);
index = 0;
for (j = 0; j != sy; j++) {
for (i = 0; i != sx; i++) {
result[index] += g * buf[index];
index++;
}
}
f *= 2.0;
g *= np->persist;
}
return result;
}
void NoiseBuffer::intSet(int x, int y, int z, double d)
{
int i = m_size_x*m_size_y*z + m_size_x*y + x;
assert(i >= 0);
assert(i < m_size_x*m_size_y*m_size_z);
m_data[i] = d;
float *Noise::perlinMap3D(float x, float y, float z) {
float a = 0.0, f = 1.0, g = 1.0;
int i, j, k, index, oct;
x /= np->spread.X;
y /= np->spread.Y;
z /= np->spread.Z;
memset(result, 0, sizeof(float) * sx * sy * sz);
for (oct = 0; oct < np->octaves; oct++) {
gradientMap3D(x * f, y * f, z * f,
f / np->spread.X, f / np->spread.Y, f / np->spread.Z,
seed + np->seed + oct);
index = 0;
for (k = 0; k != sz; k++) {
for (j = 0; j != sy; j++) {
for (i = 0; i != sx; i++) {
result[index] += g * buf[index];
index++;
}
}
}
f *= 2.0;
g *= np->persist;
}
return result;
}
void NoiseBuffer::intMultiply(int x, int y, int z, double d)
{
int i = m_size_x*m_size_y*z + m_size_x*y + x;
assert(i >= 0);
assert(i < m_size_x*m_size_y*m_size_z);
m_data[i] = m_data[i] * d;
void Noise::transformNoiseMap() {
int i = 0;
for (int z = 0; z != sz; z++) {
for (int y = 0; y != sy; y++) {
for (int x = 0; x != sx; x++) {
result[i] = result[i] * np->scale + np->offset;
i++;
}
}
}
}
double NoiseBuffer::intGet(int x, int y, int z)
{
int i = m_size_x*m_size_y*z + m_size_x*y + x;
assert(i >= 0);
assert(i < m_size_x*m_size_y*m_size_z);
return m_data[i];
}
double NoiseBuffer::get(double x, double y, double z)
{
x -= m_start_x;
y -= m_start_y;
z -= m_start_z;
x /= m_samplelength_x;
y /= m_samplelength_y;
z /= m_samplelength_z;
// Calculate the integer coordinates
int x0 = (x > 0.0 ? (int)x : (int)x - 1);
int y0 = (y > 0.0 ? (int)y : (int)y - 1);
int z0 = (z > 0.0 ? (int)z : (int)z - 1);
// Calculate the remaining part of the coordinates
double xl = x - (double)x0;
double yl = y - (double)y0;
double zl = z - (double)z0;
// Get values for corners of cube
double v000 = intGet(x0, y0, z0);
double v100 = intGet(x0+1, y0, z0);
double v010 = intGet(x0, y0+1, z0);
double v110 = intGet(x0+1, y0+1, z0);
double v001 = intGet(x0, y0, z0+1);
double v101 = intGet(x0+1, y0, z0+1);
double v011 = intGet(x0, y0+1, z0+1);
double v111 = intGet(x0+1, y0+1, z0+1);
// Interpolate
return triLinearInterpolation(v000,v100,v010,v110,v001,v101,v011,v111,xl,yl,zl);
}
/*bool NoiseBuffer::contains(double x, double y, double z)
{
x -= m_start_x;
y -= m_start_y;
z -= m_start_z;
x /= m_samplelength_x;
y /= m_samplelength_y;
z /= m_samplelength_z;
if(x <= 0.0 || x >= m_size_x)
}*/

View File

@ -21,6 +21,7 @@ with this program; if not, write to the Free Software Foundation, Inc.,
#define NOISE_HEADER
#include "debug.h"
#include "irr_v3d.h"
class PseudoRandom
{
@ -59,91 +60,105 @@ private:
int m_next;
};
double easeCurve(double t);
// Return value: -1 ... 1
double noise2d(int x, int y, int seed);
double noise3d(int x, int y, int z, int seed);
double noise2d_gradient(double x, double y, int seed);
double noise3d_gradient(double x, double y, double z, int seed);
double noise2d_perlin(double x, double y, int seed,
int octaves, double persistence);
double noise2d_perlin_abs(double x, double y, int seed,
int octaves, double persistence);
double noise3d_perlin(double x, double y, double z, int seed,
int octaves, double persistence);
double noise3d_perlin_abs(double x, double y, double z, int seed,
int octaves, double persistence);
enum NoiseType
{
NOISE_CONSTANT_ONE,
NOISE_PERLIN,
NOISE_PERLIN_ABS,
NOISE_PERLIN_CONTOUR,
NOISE_PERLIN_CONTOUR_FLIP_YZ,
};
struct NoiseParams
{
NoiseType type;
struct NoiseParams {
float offset;
float scale;
v3f spread;
int seed;
int octaves;
double persistence;
double pos_scale;
double noise_scale; // Useful for contour noises
NoiseParams(NoiseType type_=NOISE_PERLIN, int seed_=0,
int octaves_=3, double persistence_=0.5,
double pos_scale_=100.0, double noise_scale_=1.0):
type(type_),
seed(seed_),
octaves(octaves_),
persistence(persistence_),
pos_scale(pos_scale_),
noise_scale(noise_scale_)
{
}
float persist;
};
double noise3d_param(const NoiseParams &param, double x, double y, double z);
class NoiseBuffer
{
// Convenience macros for getting/setting NoiseParams in Settings
#define getNoiseParams(x) getStruct<NoiseParams>((x), "f,f,v3,s32,s32,f")
#define setNoiseParams(x, y) setStruct((x), "f,f,v3,s32,s32,f", (y))
class Noise {
public:
NoiseBuffer();
~NoiseBuffer();
NoiseParams *np;
int seed;
int sx;
int sy;
int sz;
float *noisebuf;
float *buf;
float *result;
void clear();
void create(const NoiseParams &param,
double first_x, double first_y, double first_z,
double last_x, double last_y, double last_z,
double samplelength_x, double samplelength_y, double samplelength_z);
void multiply(const NoiseParams &param);
// Deprecated
void create(int seed, int octaves, double persistence,
bool abs,
double first_x, double first_y, double first_z,
double last_x, double last_y, double last_z,
double samplelength_x, double samplelength_y, double samplelength_z);
Noise(NoiseParams *np, int seed, int sx, int sy);
Noise(NoiseParams *np, int seed, int sx, int sy, int sz);
~Noise();
void intSet(int x, int y, int z, double d);
void intMultiply(int x, int y, int z, double d);
double intGet(int x, int y, int z);
double get(double x, double y, double z);
//bool contains(double x, double y, double z);
void init(NoiseParams *np, int seed, int sx, int sy, int sz);
void setSize(int sx, int sy);
void setSize(int sx, int sy, int sz);
void setSpreadFactor(v3f spread);
void setOctaves(int octaves);
void resizeNoiseBuf(bool is3d);
private:
double *m_data;
double m_start_x, m_start_y, m_start_z;
double m_samplelength_x, m_samplelength_y, m_samplelength_z;
int m_size_x, m_size_y, m_size_z;
void gradientMap2D(
float x, float y,
float step_x, float step_y,
int seed);
void gradientMap3D(
float x, float y, float z,
float step_x, float step_y, float step_z,
int seed);
float *perlinMap2D(float x, float y);
float *perlinMap3D(float x, float y, float z);
void transformNoiseMap();
};
// Return value: -1 ... 1
float noise2d(int x, int y, int seed);
float noise3d(int x, int y, int z, int seed);
float noise2d_gradient(float x, float y, int seed);
float noise3d_gradient(float x, float y, float z, int seed);
float noise2d_perlin(float x, float y, int seed,
int octaves, float persistence);
float noise2d_perlin_abs(float x, float y, int seed,
int octaves, float persistence);
float noise3d_perlin(float x, float y, float z, int seed,
int octaves, float persistence);
float noise3d_perlin_abs(float x, float y, float z, int seed,
int octaves, float persistence);
inline float easeCurve(float t) {
return t * t * t * (t * (6.f * t - 15.f) + 10.f);
}
#define NoisePerlin2D(np, x, y, s) \
((np)->offset + (np)->scale * noise2d_perlin( \
(float)(x) / (np)->spread.X, \
(float)(y) / (np)->spread.Y, \
(s) + (np)->seed, (np)->octaves, (np)->persist))
#define NoisePerlin2DNoTxfm(np, x, y, s) \
(noise2d_perlin( \
(float)(x) / (np)->spread.X, \
(float)(y) / (np)->spread.Y, \
(s) + (np)->seed, (np)->octaves, (np)->persist))
#define NoisePerlin2DPosOffset(np, x, xoff, y, yoff, s) \
((np)->offset + (np)->scale * noise2d_perlin( \
(float)(xoff) + (float)(x) / (np)->spread.X, \
(float)(yoff) + (float)(y) / (np)->spread.Y, \
(s) + (np)->seed, (np)->octaves, (np)->persist))
#define NoisePerlin2DNoTxfmPosOffset(np, x, xoff, y, yoff, s) \
(noise2d_perlin( \
(float)(xoff) + (float)(x) / (np)->spread.X, \
(float)(yoff) + (float)(y) / (np)->spread.Y, \
(s) + (np)->seed, (np)->octaves, (np)->persist))
#define NoisePerlin3D(np, x, y, z, s) ((np)->offset + (np)->scale * \
noise2d_perlin((float)(x) / (np)->spread.X, (float)(y) / (np)->spread.Y, \
(float)(z) / (np)->spread.Z, (s) + (np)->seed, (np)->octaves, (np)->persist))
#endif

229
src/particles.cpp Normal file
View File

@ -0,0 +1,229 @@
/*
Minetest-c55
Copyright (C) 2012 celeron55, Perttu Ahola <celeron55@gmail.com>
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 "particles.h"
#include "constants.h"
#include "debug.h"
#include "main.h" // For g_profiler and g_settings
#include "settings.h"
#include "tile.h"
#include "gamedef.h"
#include "collision.h"
#include <stdlib.h>
#include "util/numeric.h"
#include "light.h"
#include "environment.h"
#include "clientmap.h"
#include "mapnode.h"
Particle::Particle(
IGameDef *gamedef,
scene::ISceneManager* smgr,
LocalPlayer *player,
s32 id,
v3f pos,
v3f velocity,
v3f acceleration,
float expirationtime,
float size,
AtlasPointer ap
):
scene::ISceneNode(smgr->getRootSceneNode(), smgr, id)
{
// Misc
m_gamedef = gamedef;
// Texture
m_material.setFlag(video::EMF_LIGHTING, false);
m_material.setFlag(video::EMF_BACK_FACE_CULLING, false);
m_material.setFlag(video::EMF_BILINEAR_FILTER, false);
m_material.setFlag(video::EMF_FOG_ENABLE, true);
m_material.MaterialType = video::EMT_TRANSPARENT_ALPHA_CHANNEL;
m_material.setTexture(0, ap.atlas);
m_ap = ap;
m_light = 0;
// Particle related
m_pos = pos;
m_velocity = velocity;
m_acceleration = acceleration;
m_expiration = expirationtime;
m_time = 0;
m_player = player;
m_size = size;
// Irrlicht stuff (TODO)
m_collisionbox = core::aabbox3d<f32>(-size/2,-size/2,-size/2,size/2,size/2,size/2);
this->setAutomaticCulling(scene::EAC_OFF);
}
Particle::~Particle()
{
}
void Particle::OnRegisterSceneNode()
{
if (IsVisible)
{
SceneManager->registerNodeForRendering(this, scene::ESNRP_TRANSPARENT);
SceneManager->registerNodeForRendering(this, scene::ESNRP_SOLID);
}
ISceneNode::OnRegisterSceneNode();
}
void Particle::render()
{
// TODO: Render particles in front of water and the selectionbox
video::IVideoDriver* driver = SceneManager->getVideoDriver();
driver->setMaterial(m_material);
driver->setTransform(video::ETS_WORLD, AbsoluteTransformation);
video::SColor c(255, m_light, m_light, m_light);
video::S3DVertex vertices[4] =
{
video::S3DVertex(-m_size/2,-m_size/2,0, 0,0,0, c, m_ap.x0(), m_ap.y1()),
video::S3DVertex(m_size/2,-m_size/2,0, 0,0,0, c, m_ap.x1(), m_ap.y1()),
video::S3DVertex(m_size/2,m_size/2,0, 0,0,0, c, m_ap.x1(), m_ap.y0()),
video::S3DVertex(-m_size/2,m_size/2,0, 0,0,0, c ,m_ap.x0(), m_ap.y0()),
};
for(u16 i=0; i<4; i++)
{
vertices[i].Pos.rotateYZBy(m_player->getPitch());
vertices[i].Pos.rotateXZBy(m_player->getYaw());
m_box.addInternalPoint(vertices[i].Pos);
vertices[i].Pos += m_pos*BS;
}
u16 indices[] = {0,1,2, 2,3,0};
driver->drawVertexPrimitiveList(vertices, 4, indices, 2,
video::EVT_STANDARD, scene::EPT_TRIANGLES, video::EIT_16BIT);
}
void Particle::step(float dtime, ClientEnvironment &env)
{
core::aabbox3d<f32> box = m_collisionbox;
v3f p_pos = m_pos*BS;
v3f p_velocity = m_velocity*BS;
v3f p_acceleration = m_acceleration*BS;
collisionMoveSimple(&env.getClientMap(), m_gamedef,
BS*0.5, box,
0, dtime,
p_pos, p_velocity, p_acceleration);
m_pos = p_pos/BS;
m_velocity = p_velocity/BS;
m_acceleration = p_acceleration/BS;
m_time += dtime;
// Update lighting
u8 light = 0;
try{
v3s16 p = v3s16(
floor(m_pos.X+0.5),
floor(m_pos.Y+0.5),
floor(m_pos.Z+0.5)
);
MapNode n = env.getClientMap().getNode(p);
light = n.getLightBlend(env.getDayNightRatio(), m_gamedef->ndef());
}
catch(InvalidPositionException &e){
light = blend_light(env.getDayNightRatio(), LIGHT_SUN, 0);
}
m_light = decode_light(light);
}
std::vector<Particle*> all_particles;
void allparticles_step (float dtime, ClientEnvironment &env)
{
for(std::vector<Particle*>::iterator i = all_particles.begin(); i != all_particles.end();)
{
if ((*i)->get_expired())
{
(*i)->remove();
delete *i;
all_particles.erase(i);
}
else
{
(*i)->step(dtime, env);
i++;
}
}
}
void addDiggingParticles(IGameDef* gamedef, scene::ISceneManager* smgr, LocalPlayer *player, v3s16 pos, const TileSpec tiles[])
{
for (u16 j = 0; j < 32; j++) // set the amount of particles here
{
addNodeParticle(gamedef, smgr, player, pos, tiles);
}
}
void addPunchingParticles(IGameDef* gamedef, scene::ISceneManager* smgr, LocalPlayer *player, v3s16 pos, const TileSpec tiles[])
{
addNodeParticle(gamedef, smgr, player, pos, tiles);
}
// add a particle of a node
// used by digging and punching particles
void addNodeParticle(IGameDef* gamedef, scene::ISceneManager* smgr, LocalPlayer *player, v3s16 pos, const TileSpec tiles[])
{
// Texture
u8 texid = myrand_range(0,5);
AtlasPointer ap = tiles[texid].texture;
float size = rand()%64/512.;
float visual_size = BS*size;
float texsize = size*2;
float x1 = ap.x1();
float y1 = ap.y1();
ap.size.X = (ap.x1() - ap.x0()) * texsize;
ap.size.Y = (ap.x1() - ap.x0()) * texsize;
ap.pos.X = ap.x0() + (x1 - ap.x0()) * ((rand()%64)/64.-texsize);
ap.pos.Y = ap.y0() + (y1 - ap.y0()) * ((rand()%64)/64.-texsize);
// Physics
v3f velocity((rand()%100/50.-1)/1.5, rand()%100/35., (rand()%100/50.-1)/1.5);
v3f acceleration(0,-9,0);
v3f particlepos = v3f(
(f32)pos.X+rand()%100/200.-0.25,
(f32)pos.Y+rand()%100/200.-0.25,
(f32)pos.Z+rand()%100/200.-0.25
);
Particle *particle = new Particle(
gamedef,
smgr,
player,
0,
particlepos,
velocity,
acceleration,
rand()%100/100., // expiration time
visual_size,
ap);
all_particles.push_back(particle);
}

98
src/particles.h Normal file
View File

@ -0,0 +1,98 @@
/*
Minetest-c55
Copyright (C) 2012 celeron55, Perttu Ahola <celeron55@gmail.com>
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU Lesser General Public License as published by
the Free Software Foundation; either version 2.1 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU Lesser General Public License for more details.
You should have received a copy of the GNU Lesser General Public License along
with this program; if not, write to the Free Software Foundation, Inc.,
51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
*/
#ifndef PARTICLES_HEADER
#define PARTICLES_HEADER
#define DIGGING_PARTICLES_AMOUNT 10
#include <iostream>
#include "irrlichttypes_extrabloated.h"
#include "tile.h"
#include "localplayer.h"
#include "environment.h"
class Particle : public scene::ISceneNode
{
public:
Particle(
IGameDef* gamedef,
scene::ISceneManager* mgr,
LocalPlayer *player,
s32 id,
v3f pos,
v3f velocity,
v3f acceleration,
float expirationtime,
float size,
AtlasPointer texture
);
~Particle();
virtual const core::aabbox3d<f32>& getBoundingBox() const
{
return m_box;
}
virtual u32 getMaterialCount() const
{
return 1;
}
virtual video::SMaterial& getMaterial(u32 i)
{
return m_material;
}
virtual void OnRegisterSceneNode();
virtual void render();
void step(float dtime, ClientEnvironment &env);
bool get_expired ()
{ return m_expiration < m_time; }
private:
float m_time;
float m_expiration;
IGameDef *m_gamedef;
core::aabbox3d<f32> m_box;
core::aabbox3d<f32> m_collisionbox;
video::SMaterial m_material;
v3f m_pos;
v3f m_velocity;
v3f m_acceleration;
float tex_x0;
float tex_x1;
float tex_y0;
float tex_y1;
LocalPlayer *m_player;
float m_size;
AtlasPointer m_ap;
u8 m_light;
};
void allparticles_step (float dtime, ClientEnvironment &env);
void addDiggingParticles(IGameDef* gamedef, scene::ISceneManager* smgr, LocalPlayer *player, v3s16 pos, const TileSpec tiles[]);
void addPunchingParticles(IGameDef* gamedef, scene::ISceneManager* smgr, LocalPlayer *player, v3s16 pos, const TileSpec tiles[]);
void addNodeParticle(IGameDef* gamedef, scene::ISceneManager* smgr, LocalPlayer *player, v3s16 pos, const TileSpec tiles[]);
#endif

View File

@ -209,6 +209,9 @@ public:
u16 hp;
float hurt_tilt_timer;
float hurt_tilt_strength;
u16 peer_id;
std::string inventory_formspec;

View File

@ -23,6 +23,17 @@ with this program; if not, write to the Free Software Foundation, Inc.,
See comments in porting.h
*/
#if defined(linux)
#include <unistd.h>
#elif defined(__APPLE__)
#include <unistd.h>
#include <mach-o/dyld.h>
#elif defined(__FreeBSD__)
#include <unistd.h>
#include <sys/types.h>
#include <sys/sysctl.h>
#endif
#include "porting.h"
#include "config.h"
#include "debug.h"
@ -79,7 +90,6 @@ void signal_handler_init(void)
#else // _WIN32
#include <signal.h>
#include <windows.h>
BOOL WINAPI event_handler(DWORD sig)
{
@ -166,7 +176,6 @@ void initializePaths()
Windows
*/
#if defined(_WIN32)
#include <windows.h>
const DWORD buflen = 1000;
char buf[buflen];
@ -191,7 +200,6 @@ void initializePaths()
Linux
*/
#elif defined(linux)
#include <unistd.h>
char buf[BUFSIZ];
memset(buf, 0, BUFSIZ);
@ -206,10 +214,43 @@ void initializePaths()
/*
OS X
*/
#elif defined(__APPLE__) || defined(__FreeBSD__)
#elif defined(__APPLE__)
//https://developer.apple.com/library/mac/#documentation/Darwin/Reference/ManPages/man3/dyld.3.html
//TODO: Test this code
char buf[BUFSIZ];
uint32_t len = sizeof(buf);
assert(_NSGetExecutablePath(buf, &len) != 0);
pathRemoveFile(buf, '/');
path_share = std::string(buf) + "/..";
path_user = std::string(buf) + "/..";
/*
FreeBSD
*/
#elif defined(__FreeBSD__)
int mib[4];
char buf[BUFSIZ];
size_t len = sizeof(buf);
mib[0] = CTL_KERN;
mib[1] = KERN_PROC;
mib[2] = KERN_PROC_PATHNAME;
mib[3] = -1;
assert(sysctl(mib, 4, buf, &len, NULL, 0) != -1);
pathRemoveFile(buf, '/');
path_share = std::string(buf) + "/..";
path_user = std::string(buf) + "/..";
#else
//TODO: Get path of executable. This assumes working directory is bin/
dstream<<"WARNING: Relative path not properly supported on OS X and FreeBSD"
dstream<<"WARNING: Relative path not properly supported on this platform"
<<std::endl;
path_share = std::string("..");
path_user = std::string("..");
@ -228,7 +269,6 @@ void initializePaths()
Windows
*/
#if defined(_WIN32)
#include <windows.h>
const DWORD buflen = 1000;
char buf[buflen];
@ -251,7 +291,6 @@ void initializePaths()
Linux
*/
#elif defined(linux)
#include <unistd.h>
// Get path to executable
std::string bindir = "";
@ -296,7 +335,6 @@ void initializePaths()
OS X
*/
#elif defined(__APPLE__)
#include <unistd.h>
// Code based on
// http://stackoverflow.com/questions/516200/relative-paths-not-working-in-xcode-c

View File

@ -35,14 +35,37 @@ with this program; if not, write to the Free Software Foundation, Inc.,
#define SWPRINTF_CHARSTRING L"%s"
#endif
//currently not needed
//template<typename T> struct alignment_trick { char c; T member; };
//#define ALIGNOF(type) offsetof (alignment_trick<type>, member)
#ifdef _WIN32
#include <windows.h>
#define sleep_ms(x) Sleep(x)
#else
#include <unistd.h>
#include <stdint.h> //for uintptr_t
#define sleep_ms(x) usleep(x*1000)
#endif
#ifdef _MSC_VER
#define ALIGNOF(x) __alignof(x)
#define strtok_r(x, y, z) strtok_s(x, y, z)
#define strtof(x, y) (float)strtod(x, y)
#define strtoll(x, y, z) _strtoi64(x, y, z)
#define strtoull(x, y, z) _strtoui64(x, y, z)
#else
#define ALIGNOF(x) __alignof__(x)
#endif
#ifdef __MINGW32__
#define strtok_r(x, y, z) mystrtok_r(x, y, z)
#endif
#define PADDING(x, y) ((ALIGNOF(y) - ((uintptr_t)(x) & (ALIGNOF(y) - 1))) & (ALIGNOF(y) - 1))
namespace porting
{

View File

@ -37,6 +37,7 @@ extern "C" {
#include "content_sao.h" // For LuaEntitySAO and PlayerSAO
#include "itemdef.h"
#include "nodedef.h"
#include "biome.h"
#include "craftdef.h"
#include "main.h" // For g_settings
#include "settings.h" // For accessing g_settings
@ -436,6 +437,16 @@ struct EnumString es_TileAnimationType[] =
{0, NULL},
};
struct EnumString es_BiomeTerrainType[] =
{
{BIOME_TERRAIN_NORMAL, "normal"},
{BIOME_TERRAIN_LIQUID, "liquid"},
{BIOME_TERRAIN_NETHER, "nether"},
{BIOME_TERRAIN_AETHER, "aether"},
{BIOME_TERRAIN_FLAT, "flat"},
{0, NULL},
};
/*
C struct <-> Lua table converter functions
*/
@ -2049,6 +2060,43 @@ private:
return 1;
}
// get_location() -> location (like minetest.get_inventory(location))
static int l_get_location(lua_State *L)
{
InvRef *ref = checkobject(L, 1);
const InventoryLocation &loc = ref->m_loc;
switch(loc.type){
case InventoryLocation::PLAYER:
lua_newtable(L);
lua_pushstring(L, "player");
lua_setfield(L, -2, "type");
lua_pushstring(L, loc.name.c_str());
lua_setfield(L, -2, "name");
return 1;
case InventoryLocation::NODEMETA:
lua_newtable(L);
lua_pushstring(L, "nodemeta");
lua_setfield(L, -2, "type");
push_v3s16(L, loc.p);
lua_setfield(L, -2, "name");
return 1;
case InventoryLocation::DETACHED:
lua_newtable(L);
lua_pushstring(L, "detached");
lua_setfield(L, -2, "type");
lua_pushstring(L, loc.name.c_str());
lua_setfield(L, -2, "name");
return 1;
case InventoryLocation::UNDEFINED:
case InventoryLocation::CURRENT_PLAYER:
break;
}
lua_newtable(L);
lua_pushstring(L, "undefined");
lua_setfield(L, -2, "type");
return 1;
}
public:
InvRef(const InventoryLocation &loc):
m_loc(loc)
@ -2124,6 +2172,7 @@ const luaL_reg InvRef::methods[] = {
method(InvRef, room_for_item),
method(InvRef, contains_item),
method(InvRef, remove_item),
method(InvRef, get_location),
{0,0}
};
@ -3202,8 +3251,8 @@ class LuaPerlinNoise
private:
int seed;
int octaves;
double persistence;
double scale;
float persistence;
float scale;
static const char className[];
static const luaL_reg methods[];
@ -3235,8 +3284,8 @@ private:
}
public:
LuaPerlinNoise(int a_seed, int a_octaves, double a_persistence,
double a_scale):
LuaPerlinNoise(int a_seed, int a_octaves, float a_persistence,
float a_scale):
seed(a_seed),
octaves(a_octaves),
persistence(a_persistence),
@ -3254,8 +3303,8 @@ public:
{
int seed = luaL_checkint(L, 1);
int octaves = luaL_checkint(L, 2);
double persistence = luaL_checknumber(L, 3);
double scale = luaL_checknumber(L, 4);
float persistence = luaL_checknumber(L, 3);
float scale = luaL_checknumber(L, 4);
LuaPerlinNoise *o = new LuaPerlinNoise(seed, octaves, persistence, scale);
*(void **)(lua_newuserdata(L, sizeof(void *))) = o;
luaL_getmetatable(L, className);
@ -3502,20 +3551,7 @@ private:
v3s16 pos = read_v3s16(L, 2);
MapNode n = readnode(L, 3, ndef);
// Do it
MapNode n_old = env->getMap().getNodeNoEx(pos);
// Call destructor
if(ndef->get(n_old).has_on_destruct)
scriptapi_node_on_destruct(L, pos, n_old);
// Replace node
bool succeeded = env->getMap().addNodeWithEvent(pos, n);
if(succeeded){
// Call post-destructor
if(ndef->get(n_old).has_after_destruct)
scriptapi_node_after_destruct(L, pos, n_old);
// Call constructor
if(ndef->get(n).has_on_construct)
scriptapi_node_on_construct(L, pos, n);
}
bool succeeded = env->setNode(pos, n);
lua_pushboolean(L, succeeded);
return 1;
}
@ -3536,20 +3572,8 @@ private:
// parameters
v3s16 pos = read_v3s16(L, 2);
// Do it
MapNode n_old = env->getMap().getNodeNoEx(pos);
// Call destructor
if(ndef->get(n_old).has_on_destruct)
scriptapi_node_on_destruct(L, pos, n_old);
// Replace with air
// This is slightly optimized compared to addNodeWithEvent(air)
bool succeeded = env->getMap().removeNodeWithEvent(pos);
if(succeeded){
// Call post-destructor
if(ndef->get(n_old).has_after_destruct)
scriptapi_node_after_destruct(L, pos, n_old);
}
bool succeeded = env->removeNode(pos);
lua_pushboolean(L, succeeded);
// Air doesn't require constructor
return 1;
}
@ -3986,8 +4010,8 @@ private:
int seeddiff = luaL_checkint(L, 2);
int octaves = luaL_checkint(L, 3);
double persistence = luaL_checknumber(L, 4);
double scale = luaL_checknumber(L, 5);
float persistence = luaL_checknumber(L, 4);
float scale = luaL_checknumber(L, 5);
LuaPerlinNoise *n = new LuaPerlinNoise(seeddiff + int(env->getServerMap().getSeed()), octaves, persistence, scale);
*(void **)(lua_newuserdata(L, sizeof(void *))) = n;
@ -4021,21 +4045,30 @@ private:
getstringfield(L, 3, "axiom", tree_def.initial_axiom);
getstringfield(L, 3, "rules_a", tree_def.rules_a);
getstringfield(L, 3, "rules_b", tree_def.rules_b);
getstringfield(L, 3, "rules_c", tree_def.rules_a);
getstringfield(L, 3, "rules_d", tree_def.rules_b);
getstringfield(L, 3, "rules_c", tree_def.rules_c);
getstringfield(L, 3, "rules_d", tree_def.rules_d);
getstringfield(L, 3, "trunk", trunk);
tree_def.trunknode=ndef->getId(trunk);
getstringfield(L, 3, "leaves", leaves);
tree_def.leavesnode=ndef->getId(leaves);
tree_def.leaves2_chance=0;
getstringfield(L, 3, "leaves2", leaves);
if (leaves !="")
{
tree_def.leaves2node=ndef->getId(leaves);
getintfield(L, 3, "leaves2_chance", tree_def.leaves2_chance);
}
getintfield(L, 3, "angle", tree_def.angle);
getintfield(L, 3, "iterations", tree_def.iterations);
getintfield(L, 3, "random_level", tree_def.iterations_random_level);
getboolfield(L, 3, "thin_trunks", tree_def.thin_trunks);
getboolfield(L, 3, "fruit_tree", tree_def.fruit_tree);
if (tree_def.fruit_tree)
{
getstringfield(L, 3, "trunk_type", tree_def.trunk_type);
getboolfield(L, 3, "thin_branches", tree_def.thin_branches);
tree_def.fruit_chance=0;
getstringfield(L, 3, "fruit", fruit);
if (fruit != "")
{
tree_def.fruitnode=ndef->getId(fruit);
getintfield(L, 3, "fruit_chance",tree_def.fruit_chance);
}
}
else
@ -4125,6 +4158,8 @@ const luaL_reg EnvRef::methods[] = {
method(EnvRef, find_node_near),
method(EnvRef, find_nodes_in_area),
method(EnvRef, get_perlin),
//method{EnvRef, get_perlin_map_2d},
//method{EnvRef, get_perlin_map_3d},
method(EnvRef, clear_objects),
method(EnvRef, spawn_tree),
{0,0}
@ -4393,8 +4428,8 @@ static int l_log(lua_State *L)
}
else
{
std::string levelname = lua_tostring(L, 1);
text = lua_tostring(L, 2);
std::string levelname = luaL_checkstring(L, 1);
text = luaL_checkstring(L, 2);
if(levelname == "error")
level = LMT_ERROR;
else if(levelname == "action")
@ -4420,6 +4455,84 @@ static int l_get_server_status(lua_State *L)
return 1;
}
// register_biome_groups({frequencies})
static int l_register_biome_groups(lua_State *L)
{
luaL_checktype(L, 1, LUA_TTABLE);
int index = 1;
if (!lua_istable(L, index))
throw LuaError(L, "register_biome_groups: parameter is not a table");
BiomeDefManager *bmgr = get_server(L)->getBiomeDef();
if (!bmgr) {
verbosestream << "register_biome_groups: BiomeDefManager not active" << std::endl;
return 0;
}
lua_pushnil(L);
for (int i = 1; lua_next(L, index) != 0; i++) {
bmgr->addBiomeGroup(lua_tonumber(L, -1));
lua_pop(L, 1);
}
lua_pop(L, 1);
return 0;
}
// register_biome({lots of stuff})
static int l_register_biome(lua_State *L)
{
luaL_checktype(L, 1, LUA_TTABLE);
int index = 1, groupid;
std::string nodename;
IWritableNodeDefManager *ndef = get_server(L)->getWritableNodeDefManager();
BiomeDefManager *bmgr = get_server(L)->getBiomeDef();
if (!bmgr) {
verbosestream << "register_biome: BiomeDefManager not active" << std::endl;
return 0;
}
groupid = getintfield_default(L, index, "group_id", 0);
enum BiomeTerrainType terrain = (BiomeTerrainType)getenumfield(L, index,
"terrain_type", es_BiomeTerrainType, BIOME_TERRAIN_NORMAL);
Biome *b = bmgr->createBiome(terrain);
b->name = getstringfield_default(L, index, "name", "");
if (getstringfield(L, index, "node_top", nodename))
b->n_top = MapNode(ndef->getId(nodename));
else
b->n_top = MapNode(CONTENT_IGNORE);
if (getstringfield(L, index, "node_filler", nodename))
b->n_filler = MapNode(ndef->getId(nodename));
else
b->n_filler = b->n_top;
b->ntopnodes = getintfield_default(L, index, "num_top_nodes", 0);
b->height_min = getintfield_default(L, index, "height_min", 0);
b->height_max = getintfield_default(L, index, "height_max", 0);
b->heat_min = getfloatfield_default(L, index, "heat_min", 0.);
b->heat_max = getfloatfield_default(L, index, "heat_max", 0.);
b->humidity_min = getfloatfield_default(L, index, "humidity_min", 0.);
b->humidity_max = getfloatfield_default(L, index, "humidity_max", 0.);
b->np = new NoiseParams; // should read an entire NoiseParams later on...
getfloatfield(L, index, "scale", b->np->scale);
getfloatfield(L, index, "offset", b->np->offset);
b->groupid = (s8)groupid;
b->flags = 0; //reserved
bmgr->addBiome(b);
verbosestream << "register_biome: " << b->name << std::endl;
return 0;
}
// register_item_raw({lots of stuff})
static int l_register_item_raw(lua_State *L)
{
@ -4768,6 +4881,13 @@ static int l_setting_getbool(lua_State *L)
return 1;
}
// setting_save()
static int l_setting_save(lua_State *L)
{
get_server(L)->saveConfig();
return 0;
}
// chat_send_all(text)
static int l_chat_send_all(lua_State *L)
{
@ -4899,6 +5019,22 @@ static int l_create_detached_inventory_raw(lua_State *L)
return 1;
}
// show_formspec(playername,formname,formspec)
static int l_show_formspec(lua_State *L)
{
const char *playername = luaL_checkstring(L, 1);
const char *formname = luaL_checkstring(L, 2);
const char *formspec = luaL_checkstring(L, 3);
if(get_server(L)->showFormspec(playername,formspec,formname))
{
lua_pushboolean(L, true);
}else{
lua_pushboolean(L, false);
}
return 1;
}
// get_dig_params(groups, tool_capabilities[, time_from_last_punch])
static int l_get_dig_params(lua_State *L)
{
@ -5216,9 +5352,12 @@ static const struct luaL_Reg minetest_f [] = {
{"register_item_raw", l_register_item_raw},
{"register_alias_raw", l_register_alias_raw},
{"register_craft", l_register_craft},
{"register_biome", l_register_biome},
{"register_biome_groups", l_register_biome_groups},
{"setting_set", l_setting_set},
{"setting_get", l_setting_get},
{"setting_getbool", l_setting_getbool},
{"setting_save",l_setting_save},
{"chat_send_all", l_chat_send_all},
{"chat_send_player", l_chat_send_player},
{"get_player_privs", l_get_player_privs},
@ -5228,6 +5367,7 @@ static const struct luaL_Reg minetest_f [] = {
{"unban_player_or_ip", l_unban_player_of_ip},
{"get_inventory", l_get_inventory},
{"create_detached_inventory_raw", l_create_detached_inventory_raw},
{"show_formspec", l_show_formspec},
{"get_dig_params", l_get_dig_params},
{"get_hit_params", l_get_hit_params},
{"get_current_modname", l_get_current_modname},
@ -5552,16 +5692,16 @@ static void scriptapi_run_callbacks(lua_State *L, int nargs,
lua_replace(L, rv);
else if(mode == RUN_CALLBACKS_MODE_AND ||
mode == RUN_CALLBACKS_MODE_AND_SC){
if(lua_toboolean(L, rv) == true &&
lua_toboolean(L, -1) == false)
if((bool)lua_toboolean(L, rv) == true &&
(bool)lua_toboolean(L, -1) == false)
lua_replace(L, rv);
else
lua_pop(L, 1);
}
else if(mode == RUN_CALLBACKS_MODE_OR ||
mode == RUN_CALLBACKS_MODE_OR_SC){
if(lua_toboolean(L, rv) == false &&
lua_toboolean(L, -1) == true)
if((bool)lua_toboolean(L, rv) == false &&
(bool)lua_toboolean(L, -1) == true)
lua_replace(L, rv);
else
lua_pop(L, 1);
@ -5572,10 +5712,10 @@ static void scriptapi_run_callbacks(lua_State *L, int nargs,
// Handle short circuit modes
if(mode == RUN_CALLBACKS_MODE_AND_SC &&
lua_toboolean(L, rv) == false)
(bool)lua_toboolean(L, rv) == false)
break;
else if(mode == RUN_CALLBACKS_MODE_OR_SC &&
lua_toboolean(L, rv) == true)
(bool)lua_toboolean(L, rv) == true)
break;
// value removed, keep key for next iteration
@ -6056,7 +6196,7 @@ bool scriptapi_node_on_timer(lua_State *L, v3s16 p, MapNode node, f32 dtime)
lua_pushnumber(L,dtime);
if(lua_pcall(L, 2, 1, 0))
script_error(L, "error: %s", lua_tostring(L, -1));
if(lua_isboolean(L,-1) && lua_toboolean(L,-1) == true)
if((bool)lua_isboolean(L,-1) && (bool)lua_toboolean(L,-1) == true)
return true;
return false;

View File

@ -39,6 +39,7 @@ with this program; if not, write to the Free Software Foundation, Inc.,
#include "itemdef.h"
#include "craftdef.h"
#include "mapgen.h"
#include "biome.h"
#include "content_mapnode.h"
#include "content_nodemeta.h"
#include "content_abm.h"
@ -169,6 +170,10 @@ void * EmergeThread::Thread()
v3s16 last_tried_pos(-32768,-32768,-32768); // For error output
ServerMap &map = ((ServerMap&)m_server->m_env->getMap());
EmergeManager *emerge = m_server->m_emerge;
Mapgen *mapgen = emerge->getMapgen();
/*
Get block info from queue, emerge them and send them
to clients.
@ -233,7 +238,7 @@ void * EmergeThread::Thread()
<<"("<<p.X<<","<<p.Y<<","<<p.Z<<") "
<<"only_from_disk="<<only_from_disk<<std::endl;
ServerMap &map = ((ServerMap&)m_server->m_env->getMap());
MapBlock *block = NULL;
bool got_block = true;
@ -245,7 +250,7 @@ void * EmergeThread::Thread()
*/
bool started_generate = false;
mapgen::BlockMakeData data;
BlockMakeData data;
{
JMutexAutoLock envlock(m_server->m_env_mutex);
@ -287,7 +292,8 @@ void * EmergeThread::Thread()
SPT_AVG);
TimeTaker t("mapgen::make_block()");
mapgen::make_block(&data);
mapgen->makeChunk(&data);
//mapgen::make_block(&data);
if(enable_mapgen_debug_info == false)
t.stop(true); // Hide output
@ -332,7 +338,7 @@ void * EmergeThread::Thread()
{
TimeTaker timer("on_generated");
scriptapi_environment_on_generated(m_server->m_lua,
minp, maxp, mapgen::get_blockseed(data.seed, minp));
minp, maxp, emerge->getBlockSeed(minp));
/*int t = timer.stop(true);
dstream<<"on_generated took "<<t<<"ms"<<std::endl;*/
}
@ -790,6 +796,7 @@ void RemoteClient::GetNextBlocks(Server *server, float dtime,
} else {
if(nearest_emergefull_d == -1)
nearest_emergefull_d = d;
goto queue_full_break;
}
// get next one.
@ -937,6 +944,8 @@ Server::Server(
m_rollback(NULL),
m_rollback_sink_enabled(true),
m_enable_rollback_recording(false),
m_emerge(NULL),
m_biomedef(NULL),
m_lua(NULL),
m_itemdef(createItemDefManager()),
m_nodedef(createNodeDefManager()),
@ -976,31 +985,66 @@ Server::Server(
infostream<<"- config: "<<m_path_config<<std::endl;
infostream<<"- game: "<<m_gamespec.path<<std::endl;
// Create biome definition manager
m_biomedef = new BiomeDefManager(this);
// Create rollback manager
std::string rollback_path = m_path_world+DIR_DELIM+"rollback.txt";
m_rollback = createRollbackManager(rollback_path, this);
// Add world mod search path
m_modspaths.push_front(m_path_world + DIR_DELIM + "worldmods");
// Add addon mod search path
for(std::set<std::string>::const_iterator i = m_gamespec.mods_paths.begin();
i != m_gamespec.mods_paths.end(); i++)
m_modspaths.push_front((*i));
// Create world if it doesn't exist
if(!initializeWorld(m_path_world, m_gamespec.id))
throw ServerError("Failed to initialize world");
// Print out mod search paths
for(core::list<std::string>::Iterator i = m_modspaths.begin();
i != m_modspaths.end(); i++){
std::string modspath = *i;
infostream<<"- mods: "<<modspath<<std::endl;
ModConfiguration modconf(m_path_world);
m_mods = modconf.getMods();
// complain about mods with unsatisfied dependencies
if(!modconf.isConsistent())
{
errorstream << "The following mods have unsatisfied dependencies: ";
std::list<ModSpec> modlist = modconf.getUnsatisfiedMods();
for(std::list<ModSpec>::iterator it = modlist.begin();
it != modlist.end(); ++it)
{
errorstream << (*it).name << " ";
}
errorstream << std::endl;
}
Settings worldmt_settings;
std::string worldmt = m_path_world + DIR_DELIM + "world.mt";
worldmt_settings.readConfigFile(worldmt.c_str());
std::vector<std::string> names = worldmt_settings.getNames();
std::set<std::string> exclude_mod_names;
std::set<std::string> load_mod_names;
for(std::vector<std::string>::iterator it = names.begin();
it != names.end(); ++it)
{
std::string name = *it;
if (name.compare(0,9,"load_mod_")==0)
{
if(worldmt_settings.getBool(name))
load_mod_names.insert(name.substr(9));
else
exclude_mod_names.insert(name.substr(9));
}
}
// complain about mods declared to be loaded, but not found
for(std::vector<ModSpec>::iterator it = m_mods.begin();
it != m_mods.end(); ++it)
load_mod_names.erase((*it).name);
if(!load_mod_names.empty())
{
errorstream << "The following mods could not be found: ";
for(std::set<std::string>::iterator it = load_mod_names.begin();
it != load_mod_names.end(); ++it)
errorstream << (*it) << " ";
errorstream << std::endl;
}
// Path to builtin.lua
std::string builtinpath = getBuiltinLuaPath() + DIR_DELIM + "builtin.lua";
// Create world if it doesn't exist
if(!initializeWorld(m_path_world, m_gamespec.id))
throw ServerError("Failed to initialize world");
// Lock environment
JMutexAutoLock envlock(m_env_mutex);
JMutexAutoLock conlock(m_con_mutex);
@ -1021,18 +1065,16 @@ Server::Server(
<<builtinpath<<std::endl;
throw ModError("Failed to load and run "+builtinpath);
}
// Find mods in mod search paths
m_mods = getMods(m_modspaths);
// Print 'em
infostream<<"Server: Loading mods: ";
for(core::list<ModSpec>::Iterator i = m_mods.begin();
for(std::vector<ModSpec>::iterator i = m_mods.begin();
i != m_mods.end(); i++){
const ModSpec &mod = *i;
infostream<<mod.name<<" ";
}
infostream<<std::endl;
// Load and run "mod" scripts
for(core::list<ModSpec>::Iterator i = m_mods.begin();
for(std::vector<ModSpec>::iterator i = m_mods.begin();
i != m_mods.end(); i++){
const ModSpec &mod = *i;
std::string scriptpath = mod.path + DIR_DELIM + "init.lua";
@ -1052,16 +1094,23 @@ Server::Server(
// Apply item aliases in the node definition manager
m_nodedef->updateAliases(m_itemdef);
// Initialize Environment
// Add default biomes after nodedef had its aliases added
m_biomedef->addDefaultBiomes();
m_env = new ServerEnvironment(new ServerMap(path_world, this), m_lua,
this, this);
// Create emerge manager
m_emerge = new EmergeManager(this, m_biomedef);
// Initialize Environment
ServerMap *servermap = new ServerMap(path_world, this, m_emerge);
m_env = new ServerEnvironment(servermap, m_lua, this, this);
m_emerge->initMapgens(servermap->getMapgenParams());
// Give environment reference to scripting api
scriptapi_add_environment(m_lua, m_env);
// Register us to receive map edit events
m_env->getMap().addEventReceiver(this);
servermap->addEventReceiver(this);
// If file exists, load environment metadata
if(fs::PathExists(m_path_world+DIR_DELIM+"env_meta.txt"))
@ -1154,6 +1203,7 @@ Server::~Server()
i = m_clients.getIterator();
i.atEnd() == false; i++)
{
// Delete client
delete i.getNode()->getValue();
}
@ -1162,6 +1212,7 @@ Server::~Server()
// Delete things in the reverse order of creation
delete m_env;
delete m_rollback;
delete m_emerge;
delete m_event;
delete m_itemdef;
delete m_nodedef;
@ -1368,11 +1419,16 @@ void Server::AsyncRunStep()
/*
Handle player HPs (die if hp=0)
*/
if(playersao->getHP() == 0 && playersao->m_hp_not_sent)
if(playersao->m_hp_not_sent && g_settings->getBool("enable_damage"))
{
if(playersao->getHP() == 0)
DiePlayer(client->peer_id);
else
SendPlayerHP(client->peer_id);
}
/*
Send player inventories and HPs if necessary
Send player inventories if necessary
*/
if(playersao->m_moved){
SendMovePlayer(client->peer_id);
@ -1382,9 +1438,6 @@ void Server::AsyncRunStep()
UpdateCrafting(client->peer_id);
SendInventory(client->peer_id);
}
if(playersao->m_hp_not_sent){
SendPlayerHP(client->peer_id);
}
}
}
@ -2311,6 +2364,7 @@ void Server::ProcessData(u8 *data, u32 datasize, u16 peer_id)
SendInventory(peer_id);
// Send HP
if(g_settings->getBool("enable_damage"))
SendPlayerHP(peer_id);
// Send detached inventories
@ -2764,6 +2818,8 @@ void Server::ProcessData(u8 *data, u32 datasize, u16 peer_id)
std::istringstream is(datastring, std::ios_base::binary);
u8 damage = readU8(is);
if(g_settings->getBool("enable_damage"))
{
actionstream<<player->getName()<<" damaged by "
<<(int)damage<<" hp at "<<PP(player->getPosition()/BS)
<<std::endl;
@ -2776,6 +2832,7 @@ void Server::ProcessData(u8 *data, u32 datasize, u16 peer_id)
if(playersao->m_hp_not_sent)
SendPlayerHP(peer_id);
}
}
else if(command == TOSERVER_PASSWORD)
{
/*
@ -2850,7 +2907,7 @@ void Server::ProcessData(u8 *data, u32 datasize, u16 peer_id)
}
else if(command == TOSERVER_RESPAWN)
{
if(player->hp != 0)
if(player->hp != 0 || !g_settings->getBool("enable_damage"))
return;
RespawnPlayer(peer_id);
@ -3638,6 +3695,25 @@ void Server::SendChatMessage(u16 peer_id, const std::wstring &message)
// Send as reliable
m_con.Send(peer_id, 0, data, true);
}
void Server::SendShowFormspecMessage(u16 peer_id, const std::string formspec, const std::string formname)
{
DSTACK(__FUNCTION_NAME);
std::ostringstream os(std::ios_base::binary);
u8 buf[12];
// Write command
writeU16(buf, TOCLIENT_SHOW_FORMSPEC);
os.write((char*)buf, 2);
os<<serializeLongString(formspec);
os<<serializeString(formname);
// Make data buffer
std::string s = os.str();
SharedBuffer<u8> data((u8*)s.c_str(), s.size());
// Send as reliable
m_con.Send(peer_id, 0, data, true);
}
void Server::BroadcastChatMessage(const std::wstring &message)
{
@ -4080,7 +4156,7 @@ void Server::fillMediaCache()
// Collect all media file paths
std::list<std::string> paths;
for(core::list<ModSpec>::Iterator i = m_mods.begin();
for(std::vector<ModSpec>::iterator i = m_mods.begin();
i != m_mods.end(); i++){
const ModSpec &mod = *i;
paths.push_back(mod.path + DIR_DELIM + "textures");
@ -4578,6 +4654,20 @@ void Server::notifyPlayer(const char *name, const std::wstring msg)
SendChatMessage(player->peer_id, std::wstring(L"Server: -!- ")+msg);
}
bool Server::showFormspec(const char *playername, const std::string &formspec, const std::string &formname)
{
Player *player = m_env->getPlayer(playername);
if(!player)
{
infostream<<"showFormspec: couldn't find player:"<<playername<<std::endl;
return false;
}
SendShowFormspecMessage(player->peer_id, formspec, formname);
return true;
}
void Server::notifyPlayers(const std::wstring msg)
{
BroadcastChatMessage(msg);
@ -4731,7 +4821,7 @@ IWritableCraftDefManager* Server::getWritableCraftDefManager()
const ModSpec* Server::getModSpec(const std::string &modname)
{
for(core::list<ModSpec>::Iterator i = m_mods.begin();
for(std::vector<ModSpec>::iterator i = m_mods.begin();
i != m_mods.end(); i++){
const ModSpec &mod = *i;
if(mod.name == modname)
@ -4741,7 +4831,7 @@ const ModSpec* Server::getModSpec(const std::string &modname)
}
void Server::getModNames(core::list<std::string> &modlist)
{
for(core::list<ModSpec>::Iterator i = m_mods.begin(); i != m_mods.end(); i++)
for(std::vector<ModSpec>::iterator i = m_mods.begin(); i != m_mods.end(); i++)
{
modlist.push_back((*i).name);
}
@ -4763,6 +4853,8 @@ v3f findSpawnPos(ServerMap &map)
#endif
#if 1
s16 water_level = map.m_mgparams->water_level;
// Try to find a good place a few times
for(s32 i=0; i<1000; i++)
{
@ -4774,13 +4866,13 @@ v3f findSpawnPos(ServerMap &map)
// Get ground height at point (fallbacks to heightmap function)
s16 groundheight = map.findGroundLevel(nodepos2d);
// Don't go underwater
if(groundheight < WATER_LEVEL)
if(groundheight <= water_level)
{
//infostream<<"-> Underwater"<<std::endl;
continue;
}
// Don't go to high places
if(groundheight > WATER_LEVEL + 4)
if(groundheight > water_level + 6)
{
//infostream<<"-> Underwater"<<std::endl;
continue;

View File

@ -549,6 +549,12 @@ public:
// Envlock should be locked when using the rollback manager
IRollbackManager *getRollbackManager(){ return m_rollback; }
//TODO: determine what should be locked when accessing the emerge manager
EmergeManager *getEmergeManager(){ return m_emerge; }
BiomeDefManager *getBiomeDef(){ return m_biomedef; }
// actions: time-reversed list
// Return value: success/failure
bool rollbackRevertActions(const std::list<RollbackAction> &actions,
@ -583,6 +589,7 @@ public:
m_async_fatal_error.set(error);
}
bool showFormspec(const char *name, const std::string &formspec, const std::string &formname);
private:
// con::PeerHandler implementation.
@ -620,6 +627,7 @@ private:
void SendMovePlayer(u16 peer_id);
void SendPlayerPrivileges(u16 peer_id);
void SendPlayerInventoryFormspec(u16 peer_id);
void SendShowFormspecMessage(u16 peer_id, const std::string formspec, const std::string formname);
/*
Send a node removal/addition event to all clients except ignore_id.
Additionally, if far_players!=NULL, players further away than
@ -737,6 +745,12 @@ private:
bool m_rollback_sink_enabled;
bool m_enable_rollback_recording; // Updated once in a while
// Emerge manager
EmergeManager *m_emerge;
// Biome Definition Manager
BiomeDefManager *m_biomedef;
// Scripting
// Envlock and conlock should be locked when using Lua
lua_State *m_lua;
@ -754,7 +768,7 @@ private:
EventManager *m_event;
// Mods
core::list<ModSpec> m_mods;
std::vector<ModSpec> m_mods;
/*
Threads

185
src/serverlist.cpp Normal file
View File

@ -0,0 +1,185 @@
/*
Minetest-c55
Copyright (C) 2011 celeron55, Perttu Ahola <celeron55@gmail.com>
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 <iostream>
#include <sstream>
#include <algorithm>
#include "main.h" // for g_settings
#include "settings.h"
#include "serverlist.h"
#include "filesys.h"
#include "porting.h"
#include "log.h"
#if USE_CURL
#include <curl/curl.h>
#endif
namespace ServerList
{
std::string getFilePath()
{
std::string serverlist_file = g_settings->get("serverlist_file");
std::string rel_path = std::string("client") + DIR_DELIM
+ "serverlist" + DIR_DELIM
+ serverlist_file;
std::string path = porting::path_share + DIR_DELIM + rel_path;
return path;
}
std::vector<ServerListSpec> getLocal()
{
std::string path = ServerList::getFilePath();
std::string liststring;
if(fs::PathExists(path))
{
std::ifstream istream(path.c_str(), std::ios::binary);
if(istream.is_open())
{
std::ostringstream ostream;
ostream << istream.rdbuf();
liststring = ostream.str();
istream.close();
}
}
return ServerList::deSerialize(liststring);
}
#if USE_CURL
static size_t WriteCallback(void *contents, size_t size, size_t nmemb, void *userp)
{
((std::string*)userp)->append((char*)contents, size * nmemb);
return size * nmemb;
}
std::vector<ServerListSpec> getOnline()
{
std::string liststring;
CURL *curl;
curl = curl_easy_init();
if (curl)
{
CURLcode res;
curl_easy_setopt(curl, CURLOPT_URL, g_settings->get("serverlist_url").c_str());
curl_easy_setopt(curl, CURLOPT_WRITEFUNCTION, ServerList::WriteCallback);
curl_easy_setopt(curl, CURLOPT_WRITEDATA, &liststring);
res = curl_easy_perform(curl);
if (res != CURLE_OK)
errorstream<<"Serverlist at url "<<g_settings->get("serverlist_url")<<" not found (internet connection?)"<<std::endl;
curl_easy_cleanup(curl);
}
return ServerList::deSerialize(liststring);
}
#endif
/*
Delete a server fromt he local favorites list
*/
bool deleteEntry (ServerListSpec server)
{
std::vector<ServerListSpec> serverlist = ServerList::getLocal();
for(unsigned i = 0; i < serverlist.size(); i++)
{
if (serverlist[i].address == server.address
&& serverlist[i].port == server.port)
{
serverlist.erase(serverlist.begin() + i);
}
}
std::string path = ServerList::getFilePath();
std::ofstream stream (path.c_str());
if (stream.is_open())
{
stream<<ServerList::serialize(serverlist);
return true;
}
return false;
}
/*
Insert a server to the local favorites list
*/
bool insert (ServerListSpec server)
{
// Remove duplicates
ServerList::deleteEntry(server);
std::vector<ServerListSpec> serverlist = ServerList::getLocal();
// Insert new server at the top of the list
serverlist.insert(serverlist.begin(), server);
std::string path = ServerList::getFilePath();
std::ofstream stream (path.c_str());
if (stream.is_open())
{
stream<<ServerList::serialize(serverlist);
}
return false;
}
std::vector<ServerListSpec> deSerialize(std::string liststring)
{
std::vector<ServerListSpec> serverlist;
std::istringstream stream(liststring);
std::string line;
while (std::getline(stream, line))
{
std::transform(line.begin(), line.end(),line.begin(), ::toupper);
if (line == "[SERVER]")
{
ServerListSpec thisserver;
std::getline(stream, thisserver.name);
std::getline(stream, thisserver.address);
std::getline(stream, thisserver.port);
std::getline(stream, thisserver.description);
serverlist.push_back(thisserver);
}
}
return serverlist;
}
std::string serialize(std::vector<ServerListSpec> serverlist)
{
std::string liststring;
for(std::vector<ServerListSpec>::iterator i = serverlist.begin(); i != serverlist.end(); i++)
{
liststring += "[server]\n";
liststring += i->name + "\n";
liststring += i->address + "\n";
liststring += i->port + "\n";
liststring += i->description + "\n";
liststring += "\n";
}
return liststring;
}
} //namespace ServerList

46
src/serverlist.h Normal file
View File

@ -0,0 +1,46 @@
/*
Minetest-c55
Copyright (C) 2011 celeron55, Perttu Ahola <celeron55@gmail.com>
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 <iostream>
#include "config.h"
#ifndef SERVERLIST_HEADER
#define SERVERLIST_HEADER
struct ServerListSpec
{
std::string name;
std::string address;
std::string port;
std::string description;
};
namespace ServerList
{
std::vector<ServerListSpec> getLocal();
#if USE_CURL
std::vector<ServerListSpec> getOnline();
#endif
bool deleteEntry(ServerListSpec server);
bool insert(ServerListSpec server);
std::vector<ServerListSpec> deSerialize(std::string liststring);
std::string serialize(std::vector<ServerListSpec>);
} //ServerList namespace
#endif

View File

@ -32,6 +32,7 @@ with this program; if not, write to the Free Software Foundation, Inc.,
#include "debug.h"
#include "log.h"
#include "util/string.h"
#include "porting.h"
enum ValueType
{
@ -72,6 +73,26 @@ public:
}
}
// return all keys used
std::vector<std::string> getNames(){
std::vector<std::string> names;
for(core::map<std::string, std::string>::Iterator
i = m_settings.getIterator();
i.atEnd() == false; i++)
{
std::string name = i.getNode()->getKey();
names.push_back(name);
}
return names;
}
// remove a setting
bool remove(const std::string& name)
{
return m_settings.remove(name);
}
bool parseConfigLine(const std::string &line)
{
JMutexAutoLock lock(m_mutex);
@ -223,6 +244,8 @@ public:
updated[name] = true;
}
else //file contains a setting which is not in m_settings
value_changed=true;
return true;
}
@ -546,6 +569,269 @@ public:
return value;
}
template <class T> T *getStruct(std::string name, std::string format)
{
size_t len = sizeof(T);
std::vector<std::string *> strs_alloced;
std::string *str;
std::string valstr = get(name);
char *s = &valstr[0];
T *buf = new T;
char *bufpos = (char *)buf;
char *f, *snext;
size_t pos;
char *fmtpos, *fmt = &format[0];
while ((f = strtok_r(fmt, ",", &fmtpos)) && s) {
fmt = NULL;
bool is_unsigned = false;
int width = 0;
char valtype = *f;
width = (int)strtol(f + 1, &f, 10);
if (width && valtype == 's')
valtype = 'i';
switch (valtype) {
case 'u':
is_unsigned = true;
/* FALLTHROUGH */
case 'i':
if (width == 16) {
bufpos += PADDING(bufpos, u16);
if ((bufpos - (char *)buf) + sizeof(u16) <= len) {
if (is_unsigned)
*(u16 *)bufpos = (u16)strtoul(s, &s, 10);
else
*(s16 *)bufpos = (s16)strtol(s, &s, 10);
}
bufpos += sizeof(u16);
} else if (width == 32) {
bufpos += PADDING(bufpos, u32);
if ((bufpos - (char *)buf) + sizeof(u32) <= len) {
if (is_unsigned)
*(u32 *)bufpos = (u32)strtoul(s, &s, 10);
else
*(s32 *)bufpos = (s32)strtol(s, &s, 10);
}
bufpos += sizeof(u32);
} else if (width == 64) {
bufpos += PADDING(bufpos, u64);
if ((bufpos - (char *)buf) + sizeof(u64) <= len) {
if (is_unsigned)
*(u64 *)bufpos = (u64)strtoull(s, &s, 10);
else
*(s64 *)bufpos = (s64)strtoll(s, &s, 10);
}
bufpos += sizeof(u64);
}
s = strchr(s, ',');
break;
case 'b':
snext = strchr(s, ',');
if (snext)
*snext++ = 0;
bufpos += PADDING(bufpos, bool);
if ((bufpos - (char *)buf) + sizeof(bool) <= len)
*(bool *)bufpos = is_yes(std::string(s));
bufpos += sizeof(bool);
s = snext;
break;
case 'f':
bufpos += PADDING(bufpos, float);
if ((bufpos - (char *)buf) + sizeof(float) <= len)
*(float *)bufpos = strtof(s, &s);
bufpos += sizeof(float);
s = strchr(s, ',');
break;
case 's':
while (*s == ' ' || *s == '\t')
s++;
if (*s++ != '"') //error, expected string
goto fail;
snext = s;
while (snext[0] && !(snext[-1] != '\\' && snext[0] == '"'))
snext++;
*snext++ = 0;
bufpos += PADDING(bufpos, std::string *);
str = new std::string(s);
pos = 0;
while ((pos = str->find("\\\"", pos)) != std::string::npos)
str->erase(pos, 1);
if ((bufpos - (char *)buf) + sizeof(std::string *) <= len)
*(std::string **)bufpos = str;
bufpos += sizeof(std::string *);
strs_alloced.push_back(str);
s = *snext ? snext + 1 : NULL;
break;
case 'v':
while (*s == ' ' || *s == '\t')
s++;
if (*s++ != '(') //error, expected vector
goto fail;
if (width == 2) {
bufpos += PADDING(bufpos, v2f);
if ((bufpos - (char *)buf) + sizeof(v2f) <= len) {
v2f *v = (v2f *)bufpos;
v->X = strtof(s, &s);
s++;
v->Y = strtof(s, &s);
}
bufpos += sizeof(v2f);
} else if (width == 3) {
bufpos += PADDING(bufpos, v3f);
if ((bufpos - (char *)buf) + sizeof(v3f) <= len) {
v3f *v = (v3f *)bufpos;
v->X = strtof(s, &s);
s++;
v->Y = strtof(s, &s);
s++;
v->Z = strtof(s, &s);
}
bufpos += sizeof(v3f);
}
s = strchr(s, ',');
break;
default: //error, invalid format specifier
goto fail;
}
if (s && *s == ',')
s++;
if ((size_t)(bufpos - (char *)buf) > len) //error, buffer too small
goto fail;
}
if (f && *f) { //error, mismatched number of fields and values
fail:
for (unsigned int i = 0; i != strs_alloced.size(); i++)
delete strs_alloced[i];
delete buf;
//delete[] buf;
buf = NULL;
}
return buf;
}
bool setStruct(std::string name, std::string format, void *value)
{
char sbuf[2048];
int sbuflen = sizeof(sbuf) - 1;
sbuf[sbuflen] = 0;
std::string str;
int pos = 0;
size_t fpos;
char *f;
char *bufpos = (char *)value;
char *fmtpos, *fmt = &format[0];
while ((f = strtok_r(fmt, ",", &fmtpos))) {
fmt = NULL;
bool is_unsigned = false;
int width = 0, nprinted = 0;
char valtype = *f;
width = (int)strtol(f + 1, &f, 10);
if (width && valtype == 's')
valtype = 'i';
switch (valtype) {
case 'u':
is_unsigned = true;
/* FALLTHROUGH */
case 'i':
if (width == 16) {
bufpos += PADDING(bufpos, u16);
nprinted = snprintf(sbuf + pos, sbuflen,
is_unsigned ? "%u, " : "%d, ",
*((u16 *)bufpos));
bufpos += sizeof(u16);
} else if (width == 32) {
bufpos += PADDING(bufpos, u32);
nprinted = snprintf(sbuf + pos, sbuflen,
is_unsigned ? "%u, " : "%d, ",
*((u32 *)bufpos));
bufpos += sizeof(u32);
} else if (width == 64) {
bufpos += PADDING(bufpos, u64);
nprinted = snprintf(sbuf + pos, sbuflen,
is_unsigned ? "%llu, " : "%lli, ",
(unsigned long long)*((u64 *)bufpos));
bufpos += sizeof(u64);
}
break;
case 'b':
bufpos += PADDING(bufpos, bool);
nprinted = snprintf(sbuf + pos, sbuflen, "%s, ",
*((bool *)bufpos) ? "true" : "false");
bufpos += sizeof(bool);
break;
case 'f':
bufpos += PADDING(bufpos, float);
nprinted = snprintf(sbuf + pos, sbuflen, "%f, ",
*((float *)bufpos));
bufpos += sizeof(float);
break;
case 's':
bufpos += PADDING(bufpos, std::string *);
str = **((std::string **)bufpos);
fpos = 0;
while ((fpos = str.find('"', fpos)) != std::string::npos) {
str.insert(fpos, 1, '\\');
fpos += 2;
}
nprinted = snprintf(sbuf + pos, sbuflen, "\"%s\", ",
(*((std::string **)bufpos))->c_str());
bufpos += sizeof(std::string *);
break;
case 'v':
if (width == 2) {
bufpos += PADDING(bufpos, v2f);
v2f *v = (v2f *)bufpos;
nprinted = snprintf(sbuf + pos, sbuflen,
"(%f, %f), ", v->X, v->Y);
bufpos += sizeof(v2f);
} else {
bufpos += PADDING(bufpos, v3f);
v3f *v = (v3f *)bufpos;
nprinted = snprintf(sbuf + pos, sbuflen,
"(%f, %f, %f), ", v->X, v->Y, v->Z);
bufpos += sizeof(v3f);
}
break;
default:
return false;
}
if (nprinted < 0) //error, buffer too small
return false;
pos += nprinted;
sbuflen -= nprinted;
}
if (pos >= 2)
sbuf[pos - 2] = 0;
set(name, std::string(sbuf));
return true;
}
void setBool(std::string name, bool value)
{
if(value)
@ -554,11 +840,6 @@ public:
set(name, "false");
}
void setS32(std::string name, s32 value)
{
set(name, itos(value));
}
void setFloat(std::string name, float value)
{
set(name, ftos(value));
@ -578,6 +859,16 @@ public:
set(name, os.str());
}
void setS16(std::string name, s16 value)
{
set(name, itos(value));
}
void setS32(std::string name, s32 value)
{
set(name, itos(value));
}
void setU64(std::string name, u64 value)
{
std::ostringstream os;

View File

@ -74,9 +74,9 @@ SubgameSpec findSubgame(const std::string &id)
}
if(game_path == "")
return SubgameSpec();
std::string gamemod_path = game_path + DIR_DELIM + "mods";
// Find mod directories
std::set<std::string> mods_paths;
mods_paths.insert(game_path + DIR_DELIM + "mods");
if(!user_game)
mods_paths.insert(share + DIR_DELIM + "mods" + DIR_DELIM + id);
if(user != share || user_game)
@ -84,7 +84,7 @@ SubgameSpec findSubgame(const std::string &id)
std::string game_name = getGameName(game_path);
if(game_name == "")
game_name = id;
return SubgameSpec(id, game_path, mods_paths, game_name);
return SubgameSpec(id, game_path, gamemod_path, mods_paths, game_name);
}
SubgameSpec findWorldSubgame(const std::string &world_path)
@ -96,7 +96,7 @@ SubgameSpec findWorldSubgame(const std::string &world_path)
SubgameSpec gamespec;
gamespec.id = world_gameid;
gamespec.path = world_gamepath;
gamespec.mods_paths.insert(world_gamepath + DIR_DELIM + "mods");
gamespec.gamemods_path= world_gamepath + DIR_DELIM + "mods";
gamespec.name = getGameName(world_gamepath);
if(gamespec.name == "")
gamespec.name = "unknown";

View File

@ -29,17 +29,20 @@ with this program; if not, write to the Free Software Foundation, Inc.,
struct SubgameSpec
{
std::string id; // "" = game does not exist
std::string path;
std::set<std::string> mods_paths;
std::string path; // path to game
std::string gamemods_path; //path to mods of the game
std::set<std::string> addon_mods_paths; //paths to addon mods for this game
std::string name;
SubgameSpec(const std::string &id_="",
const std::string &path_="",
const std::set<std::string> &mods_paths_=std::set<std::string>(),
const std::string &gamemods_path_="",
const std::set<std::string> &addon_mods_paths_=std::set<std::string>(),
const std::string &name_=""):
id(id_),
path(path_),
mods_paths(mods_paths_),
gamemods_path(gamemods_path_),
addon_mods_paths(addon_mods_paths_),
name(name_)
{}

View File

@ -1,7 +1,7 @@
/*
Minetest-c55
Copyright (C) 2010-2012 celeron55, Perttu Ahola <celeron55@gmail.com>,
2012 RealBadAngel, Maciej Kasatkin <mk@realbadangel.pl>
2012-2013 RealBadAngel, Maciej Kasatkin <mk@realbadangel.pl>
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
@ -118,7 +118,7 @@ void spawn_ltree (ServerEnvironment *env, v3s16 p0, INodeDefManager *ndef, TreeD
core::map<v3s16, MapBlock*> modified_blocks;
ManualMapVoxelManipulator vmanip(map);
v3s16 tree_blockp = getNodeBlockPos(p0);
vmanip.initialEmerge(tree_blockp - v3s16(1,1,1), tree_blockp + v3s16(1,1,1));
vmanip.initialEmerge(tree_blockp - v3s16(1,1,1), tree_blockp + v3s16(1,3,1));
make_ltree (vmanip, p0, ndef, tree_definition);
vmanip.blitBackAll(&modified_blocks);
@ -169,8 +169,11 @@ void make_ltree(ManualMapVoxelManipulator &vmanip, v3s16 p0, INodeDefManager *nd
//initialize rotation matrix, position and stacks for branches
core::matrix4 rotation;
rotation=setRotationAxisRadians(rotation, M_PI/2,v3f(0,0,1));
v3f position = v3f(0,0,0);
rotation = setRotationAxisRadians(rotation, M_PI/2,v3f(0,0,1));
v3f position;
position.X = p0.X;
position.Y = p0.Y;
position.Z = p0.Z;
std::stack <core::matrix4> stack_orientation;
std::stack <v3f> stack_position;
@ -221,20 +224,29 @@ void make_ltree(ManualMapVoxelManipulator &vmanip, v3s16 p0, INodeDefManager *nd
}
//make sure tree is not floating in the air
if (tree_definition.thin_trunks == false)
if (tree_definition.trunk_type == "double")
{
make_tree_node_placement(vmanip,v3f(p0.X+position.X+1,p0.Y+position.Y-1,p0.Z+position.Z),dirtnode);
make_tree_node_placement(vmanip,v3f(p0.X+position.X-1,p0.Y+position.Y-1,p0.Z+position.Z),dirtnode);
make_tree_node_placement(vmanip,v3f(p0.X+position.X,p0.Y+position.Y-1,p0.Z+position.Z+1),dirtnode);
make_tree_node_placement(vmanip,v3f(p0.X+position.X,p0.Y+position.Y-1,p0.Z+position.Z-1),dirtnode);
tree_node_placement(vmanip,v3f(position.X+1,position.Y-1,position.Z),dirtnode);
tree_node_placement(vmanip,v3f(position.X,position.Y-1,position.Z+1),dirtnode);
tree_node_placement(vmanip,v3f(position.X+1,position.Y-1,position.Z+1),dirtnode);
}
if (tree_definition.trunk_type == "crossed")
{
tree_node_placement(vmanip,v3f(position.X+1,position.Y-1,position.Z),dirtnode);
tree_node_placement(vmanip,v3f(position.X-1,position.Y-1,position.Z),dirtnode);
tree_node_placement(vmanip,v3f(position.X,position.Y-1,position.Z+1),dirtnode);
tree_node_placement(vmanip,v3f(position.X,position.Y-1,position.Z-1),dirtnode);
}
/* build tree out of generated axiom
Key for Special L-System Symbols used in Axioms
G - move forward one unit with the pin down
F - move forward one unit with the pin up
G - move forward one unit with the pen up
F - move forward one unit with the pen down drawing trunks and branches
f - move forward one unit with the pen down drawing leaves (100% chance)
T - move forward one unit with the pen down drawing trunks only
R - move forward one unit with the pen down placing fruit
A - replace with rules set A
B - replace with rules set B
C - replace with rules set C
@ -264,38 +276,78 @@ void make_ltree(ManualMapVoxelManipulator &vmanip, v3s16 p0, INodeDefManager *nd
switch (axiom_char)
{
case 'G':
dir = v3f(-1,0,0);
dir = v3f(1,0,0);
dir = transposeMatrix(rotation,dir);
position+=dir;
break;
case 'T':
tree_trunk_placement(vmanip,v3f(position.X,position.Y,position.Z),tree_definition);
if (tree_definition.trunk_type == "double" && !tree_definition.thin_branches)
{
tree_trunk_placement(vmanip,v3f(position.X+1,position.Y,position.Z),tree_definition);
tree_trunk_placement(vmanip,v3f(position.X,position.Y,position.Z+1),tree_definition);
tree_trunk_placement(vmanip,v3f(position.X+1,position.Y,position.Z+1),tree_definition);
}
if (tree_definition.trunk_type == "crossed" && !tree_definition.thin_branches)
{
tree_trunk_placement(vmanip,v3f(position.X+1,position.Y,position.Z),tree_definition);
tree_trunk_placement(vmanip,v3f(position.X-1,position.Y,position.Z),tree_definition);
tree_trunk_placement(vmanip,v3f(position.X,position.Y,position.Z+1),tree_definition);
tree_trunk_placement(vmanip,v3f(position.X,position.Y,position.Z-1),tree_definition);
}
dir = v3f(1,0,0);
dir = transposeMatrix(rotation,dir);
position+=dir;
break;
case 'F':
make_tree_trunk_placement(vmanip,v3f(p0.X+position.X,p0.Y+position.Y,p0.Z+position.Z),tree_definition);
if (tree_definition.thin_trunks == false)
tree_trunk_placement(vmanip,v3f(position.X,position.Y,position.Z),tree_definition);
if ((stack_orientation.empty() && tree_definition.trunk_type == "double") ||
(!stack_orientation.empty() && tree_definition.trunk_type == "double" && !tree_definition.thin_branches))
{
make_tree_trunk_placement(vmanip,v3f(p0.X+position.X+1,p0.Y+position.Y,p0.Z+position.Z),tree_definition);
make_tree_trunk_placement(vmanip,v3f(p0.X+position.X-1,p0.Y+position.Y,p0.Z+position.Z),tree_definition);
make_tree_trunk_placement(vmanip,v3f(p0.X+position.X,p0.Y+position.Y,p0.Z+position.Z+1),tree_definition);
make_tree_trunk_placement(vmanip,v3f(p0.X+position.X,p0.Y+position.Y,p0.Z+position.Z-1),tree_definition);
tree_trunk_placement(vmanip,v3f(position.X+1,position.Y,position.Z),tree_definition);
tree_trunk_placement(vmanip,v3f(position.X,position.Y,position.Z+1),tree_definition);
tree_trunk_placement(vmanip,v3f(position.X+1,position.Y,position.Z+1),tree_definition);
}
if ((stack_orientation.empty() && tree_definition.trunk_type == "crossed") ||
(!stack_orientation.empty() && tree_definition.trunk_type == "crossed" && !tree_definition.thin_branches))
{
tree_trunk_placement(vmanip,v3f(position.X+1,position.Y,position.Z),tree_definition);
tree_trunk_placement(vmanip,v3f(position.X-1,position.Y,position.Z),tree_definition);
tree_trunk_placement(vmanip,v3f(position.X,position.Y,position.Z+1),tree_definition);
tree_trunk_placement(vmanip,v3f(position.X,position.Y,position.Z-1),tree_definition);
}
if (stack_orientation.empty() == false)
{
s16 size = 1;
for(x=-size; x<size+1; x++)
for(y=-size; y<size+1; y++)
for(z=-size; z<size+1; z++)
for(x=-size; x<=size; x++)
for(y=-size; y<=size; y++)
for(z=-size; z<=size; z++)
if (abs(x) == size && abs(y) == size && abs(z) == size)
{
make_tree_leaves_placement(vmanip,v3f(p0.X+position.X+x+1,p0.Y+position.Y+y,p0.Z+position.Z+z),tree_definition);
make_tree_leaves_placement(vmanip,v3f(p0.X+position.X+x-1,p0.Y+position.Y+y,p0.Z+position.Z+z),tree_definition);
make_tree_leaves_placement(vmanip,v3f(p0.X+position.X+x,p0.Y+position.Y+y,p0.Z+position.Z+z+1),tree_definition);
make_tree_leaves_placement(vmanip,v3f(p0.X+position.X+x,p0.Y+position.Y+y,p0.Z+position.Z+z-1),tree_definition);
tree_leaves_placement(vmanip,v3f(position.X+x+1,position.Y+y,position.Z+z),tree_definition);
tree_leaves_placement(vmanip,v3f(position.X+x-1,position.Y+y,position.Z+z),tree_definition);
tree_leaves_placement(vmanip,v3f(position.X+x,position.Y+y,position.Z+z+1),tree_definition);
tree_leaves_placement(vmanip,v3f(position.X+x,position.Y+y,position.Z+z-1),tree_definition);
}
}
dir = v3f(1,0,0);
dir = transposeMatrix(rotation,dir);
position+=dir;
break;
// turtle commands
case 'f':
tree_single_leaves_placement(vmanip,v3f(position.X,position.Y,position.Z),tree_definition);
dir = v3f(1,0,0);
dir = transposeMatrix(rotation,dir);
position+=dir;
break;
case 'R':
tree_fruit_placement(vmanip,v3f(position.X,position.Y,position.Z),tree_definition);
dir = v3f(1,0,0);
dir = transposeMatrix(rotation,dir);
position+=dir;
break;
// turtle orientation commands
case '[':
stack_orientation.push(rotation);
stack_position.push(position);
@ -342,7 +394,7 @@ void make_ltree(ManualMapVoxelManipulator &vmanip, v3s16 p0, INodeDefManager *nd
}
}
void make_tree_node_placement(ManualMapVoxelManipulator &vmanip, v3f p0,
void tree_node_placement(ManualMapVoxelManipulator &vmanip, v3f p0,
MapNode node)
{
v3s16 p1 = v3s16(myround(p0.X),myround(p0.Y),myround(p0.Z));
@ -355,7 +407,7 @@ void make_tree_node_placement(ManualMapVoxelManipulator &vmanip, v3f p0,
vmanip.m_data[vmanip.m_area.index(p1)] = node;
}
void make_tree_trunk_placement(ManualMapVoxelManipulator &vmanip, v3f p0,
void tree_trunk_placement(ManualMapVoxelManipulator &vmanip, v3f p0,
TreeDef &tree_definition)
{
v3s16 p1 = v3s16(myround(p0.X),myround(p0.Y),myround(p0.Z));
@ -368,7 +420,47 @@ void make_tree_trunk_placement(ManualMapVoxelManipulator &vmanip, v3f p0,
vmanip.m_data[vmanip.m_area.index(p1)] = tree_definition.trunknode;
}
void make_tree_leaves_placement(ManualMapVoxelManipulator &vmanip, v3f p0,
void tree_leaves_placement(ManualMapVoxelManipulator &vmanip, v3f p0,
TreeDef &tree_definition)
{
MapNode leavesnode=tree_definition.leavesnode;
if (myrand_range(1,100) > 100-tree_definition.leaves2_chance)
leavesnode=tree_definition.leaves2node;
v3s16 p1 = v3s16(myround(p0.X),myround(p0.Y),myround(p0.Z));
if(vmanip.m_area.contains(p1) == false)
return;
u32 vi = vmanip.m_area.index(p1);
if(vmanip.m_data[vi].getContent() != CONTENT_AIR
&& vmanip.m_data[vi].getContent() != CONTENT_IGNORE)
return;
if (tree_definition.fruit_chance>0)
{
if (myrand_range(1,100) > 100-tree_definition.fruit_chance)
vmanip.m_data[vmanip.m_area.index(p1)] = tree_definition.fruitnode;
else
vmanip.m_data[vmanip.m_area.index(p1)] = leavesnode;
}
else if (myrand_range(1,100) > 20)
vmanip.m_data[vmanip.m_area.index(p1)] = leavesnode;
}
void tree_single_leaves_placement(ManualMapVoxelManipulator &vmanip, v3f p0,
TreeDef &tree_definition)
{
MapNode leavesnode=tree_definition.leavesnode;
if (myrand_range(1,100) > 100-tree_definition.leaves2_chance)
leavesnode=tree_definition.leaves2node;
v3s16 p1 = v3s16(myround(p0.X),myround(p0.Y),myround(p0.Z));
if(vmanip.m_area.contains(p1) == false)
return;
u32 vi = vmanip.m_area.index(p1);
if(vmanip.m_data[vi].getContent() != CONTENT_AIR
&& vmanip.m_data[vi].getContent() != CONTENT_IGNORE)
return;
vmanip.m_data[vmanip.m_area.index(p1)] = leavesnode;
}
void tree_fruit_placement(ManualMapVoxelManipulator &vmanip, v3f p0,
TreeDef &tree_definition)
{
v3s16 p1 = v3s16(myround(p0.X),myround(p0.Y),myround(p0.Z));
@ -378,15 +470,7 @@ void make_tree_leaves_placement(ManualMapVoxelManipulator &vmanip, v3f p0,
if(vmanip.m_data[vi].getContent() != CONTENT_AIR
&& vmanip.m_data[vi].getContent() != CONTENT_IGNORE)
return;
if (tree_definition.fruit_tree)
{
if (myrand_range(1,100) > 90+tree_definition.iterations)
vmanip.m_data[vmanip.m_area.index(p1)] = tree_definition.fruitnode;
else
vmanip.m_data[vmanip.m_area.index(p1)] = tree_definition.leavesnode;
}
else if (myrand_range(1,100) > 20)
vmanip.m_data[vmanip.m_area.index(p1)] = tree_definition.leavesnode;
}
irr::core::matrix4 setRotationAxisRadians(irr::core::matrix4 M, double angle, v3f axis)

View File

@ -1,7 +1,7 @@
/*
Minetest-c55
Copyright (C) 2010-2012 celeron55, Perttu Ahola <celeron55@gmail.com>,
2012 RealBadAngel, Maciej Kasatkin <mk@realbadangel.pl>
2012-2013 RealBadAngel, Maciej Kasatkin <mk@realbadangel.pl>
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
@ -38,12 +38,15 @@ std::string rules_c;
std::string rules_d;
MapNode trunknode;
MapNode leavesnode;
MapNode leaves2node;
int leaves2_chance;
int angle;
int iterations;
int iterations_random_level;
bool thin_trunks;
bool fruit_tree;
std::string trunk_type;
bool thin_branches;
MapNode fruitnode;
int fruit_chance;
};
// Add default tree
@ -54,14 +57,19 @@ MapNode fruitnode;
void make_ltree(ManualMapVoxelManipulator &vmanip, v3s16 p0, INodeDefManager *ndef,
TreeDef tree_definition);
// Spawn L-systems tree from LUA
void spawn_ltree (ServerEnvironment *env, v3s16 p0, INodeDefManager *ndef, TreeDef tree_definition);
void spawn_ltree (ServerEnvironment *env, v3s16 p0, INodeDefManager *ndef,
TreeDef tree_definition);
// L-System tree gen helper functions
void make_tree_node_placement(ManualMapVoxelManipulator &vmanip, v3f p0,
void tree_node_placement(ManualMapVoxelManipulator &vmanip, v3f p0,
MapNode node);
void make_tree_trunk_placement(ManualMapVoxelManipulator &vmanip, v3f p0,
void tree_trunk_placement(ManualMapVoxelManipulator &vmanip, v3f p0,
TreeDef &tree_definition);
void make_tree_leaves_placement(ManualMapVoxelManipulator &vmanip, v3f p0,
void tree_leaves_placement(ManualMapVoxelManipulator &vmanip, v3f p0,
TreeDef &tree_definition);
void tree_single_leaves_placement(ManualMapVoxelManipulator &vmanip, v3f p0,
TreeDef &tree_definition);
void tree_fruit_placement(ManualMapVoxelManipulator &vmanip, v3f p0,
TreeDef &tree_definition);
irr::core::matrix4 setRotationAxisRadians(irr::core::matrix4 M, double angle,v3f axis);

View File

@ -120,6 +120,7 @@ inline s16 rangelim(s16 i, s16 max)
}
#define rangelim(d, min, max) ((d) < (min) ? (min) : ((d)>(max)?(max):(d)))
#define myfloor(x) ((x) > 0.0 ? (int)(x) : (int)(x) - 1)
inline v3s16 arealim(v3s16 p, s16 d)
{

View File

@ -47,3 +47,28 @@ size_t curl_write_data(char *ptr, size_t size, size_t nmemb, void *userdata) {
stream->write(ptr, count);
return count;
}
char *mystrtok_r(char *s, const char *sep, char **lasts) {
char *t;
if (!s)
s = *lasts;
while (*s && strchr(sep, *s))
s++;
if (!*s)
return NULL;
t = s;
while (*t) {
if (strchr(sep, *t)) {
*t++ = '\0';
break;
}
t++;
}
*lasts = t;
return s;
}

View File

@ -283,6 +283,7 @@ inline std::string wrap_rows(const std::string &from, u32 rowlen)
std::string translatePassword(std::string playername, std::wstring password);
size_t curl_write_data(char *ptr, size_t size, size_t nmemb, void *userdata);
char *mystrtok_r(char *s, const char *sep, char **lasts);
#endif

View File

@ -15,7 +15,8 @@ openal_stripped_file=$dir/openal_stripped.zip
mingwm10_dll_file=$dir/mingwm10.dll
irrlicht_version=1.7.2
ogg_version=1.2.1
vorbis_version=1.3.2
vorbis_version=1.3.3
curl_version=7.18.0
# unzip -l $openal_stripped_file:
# 0 2012-04-03 00:25 openal_stripped/
@ -33,26 +34,33 @@ mkdir -p $libdir
cd $builddir
# Get stuff
wget http://downloads.sourceforge.net/irrlicht/irrlicht-$irrlicht_version.zip \
[ -e $packagedir/irrlicht-$irrlicht_version.zip ] || wget http://downloads.sourceforge.net/irrlicht/irrlicht-$irrlicht_version.zip \
-c -O $packagedir/irrlicht-$irrlicht_version.zip || exit 1
wget http://www.winimage.com/zLibDll/zlib125.zip \
[ -e $packagedir/zlib125.zip ] || wget http://www.winimage.com/zLibDll/zlib125.zip \
-c -O $packagedir/zlib125.zip || exit 1
wget http://www.winimage.com/zLibDll/zlib125dll.zip \
[ -e $packagedir/zlib125dll.zip ] || wget http://www.winimage.com/zLibDll/zlib125dll.zip \
-c -O $packagedir/zlib125dll.zip || exit 1
wget http://switch.dl.sourceforge.net/project/winlibs/libogg/libogg-$ogg_version-dev.7z \
[ -e $packagedir/libogg-$ogg_version-dev.7z ] || wget http://mirror.transact.net.au/sourceforge/w/project/wi/winlibs/libogg/libogg-$ogg_version-dev.7z \
-c -O $packagedir/libogg-$ogg_version-dev.7z || exit 1
wget http://switch.dl.sourceforge.net/project/winlibs/libogg/libogg-$ogg_version-dll.7z \
[ -e $packagedir/libogg-$ogg_version-dll.7z ] || wget http://mirror.transact.net.au/sourceforge/w/project/wi/winlibs/libogg/libogg-$ogg_version-dll.7z \
-c -O $packagedir/libogg-$ogg_version-dll.7z || exit 1
wget http://switch.dl.sourceforge.net/project/winlibs/libvorbis/libvorbis-$vorbis_version-dev.7z \
[ -e $packagedir/libvorbis-$vorbis_version-dev.7z ] || wget http://minetest.ru/bin/libvorbis-$vorbis_version-dev.7z \
-c -O $packagedir/libvorbis-$vorbis_version-dev.7z || exit 1
wget http://switch.dl.sourceforge.net/project/winlibs/libvorbis/libvorbis-$vorbis_version-dll.7z \
[ -e $packagedir/libvorbis-$vorbis_version-dll.7z ] || wget http://minetest.ru/bin/libvorbis-$vorbis_version-dll.7z \
-c -O $packagedir/libvorbis-$vorbis_version-dll.7z || exit 1
[ -e $packagedir/libcurl-$curl_version-win32-msvc.zip ] || wget http://curl.haxx.se/download/libcurl-$curl_version-win32-msvc.zip \
-c -O $packagedir/libcurl-$curl_version-win32-msvc.zip || exit 1
wget http://github.com/celeron55/minetest/zipball/master \
-c -O $packagedir/minetest.zip || exit 1
cp $openal_stripped_file $packagedir/openal_stripped.zip || exit 1
cp $mingwm10_dll_file $packagedir/mingwm10.dll || exit 1
-c -O $packagedir/minetest.zip --tries=3 || (echo "Please download http://github.com/celeron55/minetest/zipball/master manually and save it as $packagedir/minetest.zip"; read -s)
[ -e $packagedir/minetest.zip ] || (echo "minetest.zip not found"; exit 1)
wget http://github.com/celeron55/minetest_game/zipball/master \
-c -O $packagedir/minetest_game.zip || exit 1
-c -O $packagedir/minetest_game.zip --tries=3 || (echo "Please download http://github.com/celeron55/minetest_game/zipball/master manually and save it as $packagedir/minetest_game.zip"; read -s)
[ -e $packagedir/minetest_game.zip ] || (echo "minetest_game.zip not found"; exit 1)
[ -e $packagedir/openal_stripped.zip ] || wget http://minetest.ru/bin/openal_stripped.zip \
-c -O $packagedir/openal_stripped.zip || exit 1
[ -e $packagedir/mingwm10.dll ] || wget http://minetest.ru/bin/mingwm10.dll \
-c -O $packagedir/mingwm10.dll || exit 1
# Figure out some path names from the packages
minetestdirname=`unzip -l $packagedir/minetest.zip | head -n 7 | tail -n 1 | sed -e 's/^[^c]*//' -e 's/\/.*$//'`
@ -69,6 +77,7 @@ unzip -o $packagedir/zlib125dll.zip -d zlib125dll || exit 1
7z x -y -olibogg $packagedir/libogg-$ogg_version-dll.7z || exit 1
7z x -y -olibvorbis $packagedir/libvorbis-$vorbis_version-dev.7z || exit 1
7z x -y -olibvorbis $packagedir/libvorbis-$vorbis_version-dll.7z || exit 1
unzip -o $packagedir/libcurl-$curl_version-win32-msvc.zip -d libcurl || exit 1
unzip -o $packagedir/openal_stripped.zip || exit 1
cd $builddir || exit 1
unzip -o $packagedir/minetest.zip || exit 1
@ -106,6 +115,10 @@ cmake $minetestdir -DCMAKE_TOOLCHAIN_FILE=$toolchain_file -DENABLE_SOUND=1 \
-DOPENAL_INCLUDE_DIR=$libdir/openal_stripped/include \
-DOPENAL_LIBRARY=$libdir/openal_stripped/lib/OpenAL32.lib \
-DOPENAL_DLL=$libdir/openal_stripped/bin/OpenAL32.dll \
-DENABLE_CURL=1 \
-DCURL_DLL=$libdir/libcurl/libcurl.dll \
-DCURL_INCLUDE_DIR=$libdir/libcurl/include \
-DCURL_LIBRARY=$libdir/libcurl/libcurl.lib \
-DMINGWM10_DLL=$packagedir/mingwm10.dll \
-DCMAKE_INSTALL_PREFIX=/tmp \
-DVERSION_EXTRA=$git_hash \