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,57 +1076,64 @@ methods:
^ clear all objects in the environments
- spawn_tree (pos, {treedef})
^ spawns L-System tree at given pos with definition in treedef table
treedef={
axiom, - string initial tree axiom
rules_a, - string rules set A
rules_b, - string rules set B
rules_c, - string rules set C
rules_d, - string rules set D
trunk, - string trunk node name
leaves, - string leaves node name
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
treedef={
axiom, - string initial tree axiom
rules_a, - string rules set A
rules_b, - string rules set B
rules_c, - string rules set C
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
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
A - replace with rules set A
B - replace with rules set B
C - replace with rules set C
D - replace with rules set D
a - replace with rules set A, chance 90%
b - replace with rules set B, chance 80%
c - replace with rules set C, chance 70%
d - replace with rules set D, chance 60%
+ - yaw the turtle right by angle parameter
- - yaw the turtle left by angle parameter
& - pitch the turtle down by angle parameter
^ - pitch the turtle up by angle parameter
/ - roll the turtle to the right by angle parameter
* - roll the turtle to the left by angle parameter
[ - save in stack current state info
] - recover from stack state info
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
D - replace with rules set D
a - replace with rules set A, chance 90%
b - replace with rules set B, chance 80%
c - replace with rules set C, chance 70%
d - replace with rules set D, chance 60%
+ - yaw the turtle right by angle parameter
- - yaw the turtle left by angle parameter
& - pitch the turtle down by angle parameter
^ - pitch the turtle up by angle parameter
/ - roll the turtle to the right by angle parameter
* - roll the turtle to the left by angle parameter
[ - save in stack current state info
] - recover from stack state info
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]",
trunk="default:tree",
leaves="default:leaves",
angle=30,
iterations=2,
random_level=0,
thin_trunks=true,
fruit_tree=true,
fruit="default:apple"
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]",
trunk="default:tree",
leaves="default:leaves",
angle=30,
iterations=2,
random_level=0,
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
@ -283,6 +284,10 @@ public:
Other stuff
-------------------------------------------
*/
// 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;
@ -2587,6 +2719,12 @@ void the_game(
farmesh->update(v2f(player_position.X, player_position.Z),
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,20 +356,32 @@ 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);
pos.Y += (stof(flabel.substr(flabel.find(",")+1)) * (float)imgsize.Y)/2;
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;
}
std::string odefault = f.next("]");
std::string fdefault;
// fdefault may contain a variable reference, which
// needs to be resolved from the node metadata
if(m_form_src)
@ -380,41 +395,40 @@ void GUIFormSpecMenu::regenerateGui(v2u32 screensize)
narrow_to_wide(fdefault.c_str()),
258+m_fields.size()
);
// three cases: field and no label, label and no field, label and field
if (flabel == "")
{
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 == "")
// three cases: field name and no label, label and field, label name and no field
gui::IGUIEditBox *e;
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);
irr::SEvent evt;
evt.EventType = EET_KEY_INPUT_EVENT;
evt.KeyInput.Key = KEY_END;
evt.KeyInput.PressedDown = true;
e->OnEvent(evt);
if (type == "textarea")
{
e->setMultiLine(true);
e->setTextAlignment(gui::EGUIA_UPPERLEFT, gui::EGUIA_UPPERLEFT);
} else {
irr::SEvent evt;
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")
@ -807,7 +821,29 @@ void GUIFormSpecMenu::drawMenu()
core::dimension2di(texture->getOriginalSize())),
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"));
menu->drop();
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)
{}
};
@ -109,12 +119,15 @@ private:
gui::IGUIElement* parent;
s32 id;
IMenuManager *menumgr;
bool m_is_regenerating;
v2s32 m_topleft_client;
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

@ -1,253 +1,253 @@
/*
Minetest-c55
Copyright (C) 2010 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 "guiPauseMenu.h"
#include "debug.h"
#include "serialization.h"
#include "porting.h"
#include "config.h"
#include "main.h"
#include <IGUICheckBox.h>
#include <IGUIEditBox.h>
#include <IGUIButton.h>
#include <IGUIStaticText.h>
#include <IGUIFont.h>
#include "gettext.h"
#include "util/string.h"
GUIPauseMenu::GUIPauseMenu(gui::IGUIEnvironment* env,
gui::IGUIElement* parent, s32 id,
IGameCallback *gamecallback,
IMenuManager *menumgr,
bool simple_singleplayer_mode):
GUIModalMenu(env, parent, id, menumgr),
m_gamecallback(gamecallback),
m_simple_singleplayer_mode(simple_singleplayer_mode)
{
}
GUIPauseMenu::~GUIPauseMenu()
{
removeChildren();
}
void GUIPauseMenu::removeChildren()
{
{
gui::IGUIElement *e = getElementFromId(256);
if(e != NULL)
e->remove();
}
{
gui::IGUIElement *e = getElementFromId(257);
if(e != NULL)
e->remove();
}
{
gui::IGUIElement *e = getElementFromId(258);
if(e != NULL)
e->remove();
}
{
gui::IGUIElement *e = getElementFromId(259);
if(e != NULL)
e->remove();
}
{
gui::IGUIElement *e = getElementFromId(260);
if(e != NULL)
e->remove();
}
{
gui::IGUIElement *e = getElementFromId(261);
if(e != NULL)
e->remove();
}
}
void GUIPauseMenu::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();
/*
Add stuff
*/
const s32 btn_height = 30;
const s32 btn_gap = 20;
const s32 btn_num = m_simple_singleplayer_mode ? 3 : 4;
s32 btn_y = size.Y/2-((btn_num*btn_height+(btn_num-1)*btn_gap))/2;
changeCtype("");
{
core::rect<s32> rect(0, 0, 140, btn_height);
rect = rect + v2s32(size.X/2-140/2, btn_y);
Environment->addButton(rect, this, 256,
wgettext("Continue"));
}
btn_y += btn_height + btn_gap;
if(!m_simple_singleplayer_mode)
{
{
core::rect<s32> rect(0, 0, 140, btn_height);
rect = rect + v2s32(size.X/2-140/2, btn_y);
Environment->addButton(rect, this, 261,
wgettext("Change Password"));
}
btn_y += btn_height + btn_gap;
}
{
core::rect<s32> rect(0, 0, 140, btn_height);
rect = rect + v2s32(size.X/2-140/2, btn_y);
Environment->addButton(rect, this, 260,
wgettext("Exit to Menu"));
}
btn_y += btn_height + btn_gap;
{
core::rect<s32> rect(0, 0, 140, btn_height);
rect = rect + v2s32(size.X/2-140/2, btn_y);
Environment->addButton(rect, this, 257,
wgettext("Exit to OS"));
}
{
core::rect<s32> rect(0, 0, 180, 240);
rect = rect + v2s32(size.X/2 + 90, size.Y/2-rect.getHeight()/2);
Environment->addStaticText(chartowchar_t(gettext(
"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"
)), rect, false, true, this, 258);
}
{
core::rect<s32> rect(0, 0, 180, 220);
rect = rect + v2s32(size.X/2 - 90 - rect.getWidth(), size.Y/2-rect.getHeight()/2);
v2u32 max_texture_size;
{
video::IVideoDriver* driver = Environment->getVideoDriver();
max_texture_size = driver->getMaxTextureSize();
}
std::ostringstream os;
os<<"Minetest\n";
os<<BUILD_INFO<<"\n";
os<<"path_user = "<<wrap_rows(porting::path_user, 20)<<"\n";
Environment->addStaticText(narrow_to_wide(os.str()).c_str(), rect, false, true, this, 259);
}
changeCtype("C");
}
void GUIPauseMenu::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();
}
bool GUIPauseMenu::OnEvent(const SEvent& event)
{
if(event.EventType==EET_KEY_INPUT_EVENT)
{
if(event.KeyInput.PressedDown)
{
if(event.KeyInput.Key==KEY_ESCAPE)
{
quitMenu();
return true;
}
else if(event.KeyInput.Key==KEY_RETURN)
{
quitMenu();
return true;
}
}
}
if(event.EventType==EET_GUI_EVENT)
{
if(event.GUIEvent.EventType==gui::EGET_ELEMENT_FOCUS_LOST
&& isVisible())
{
if(!canTakeFocus(event.GUIEvent.Element))
{
dstream<<"GUIPauseMenu: 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 256: // continue
quitMenu();
// ALWAYS return immediately after quitMenu()
return true;
case 261:
quitMenu();
m_gamecallback->changePassword();
return true;
case 260: // disconnect
m_gamecallback->disconnect();
quitMenu();
return true;
case 257: // exit
m_gamecallback->exitToOS();
quitMenu();
return true;
}
}
}
return Parent ? Parent->OnEvent(event) : false;
}
/*
Minetest-c55
Copyright (C) 2010 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 "guiPauseMenu.h"
#include "debug.h"
#include "serialization.h"
#include "porting.h"
#include "config.h"
#include "main.h"
#include <IGUICheckBox.h>
#include <IGUIEditBox.h>
#include <IGUIButton.h>
#include <IGUIStaticText.h>
#include <IGUIFont.h>
#include "gettext.h"
#include "util/string.h"
GUIPauseMenu::GUIPauseMenu(gui::IGUIEnvironment* env,
gui::IGUIElement* parent, s32 id,
IGameCallback *gamecallback,
IMenuManager *menumgr,
bool simple_singleplayer_mode):
GUIModalMenu(env, parent, id, menumgr),
m_gamecallback(gamecallback),
m_simple_singleplayer_mode(simple_singleplayer_mode)
{
}
GUIPauseMenu::~GUIPauseMenu()
{
removeChildren();
}
void GUIPauseMenu::removeChildren()
{
{
gui::IGUIElement *e = getElementFromId(256);
if(e != NULL)
e->remove();
}
{
gui::IGUIElement *e = getElementFromId(257);
if(e != NULL)
e->remove();
}
{
gui::IGUIElement *e = getElementFromId(258);
if(e != NULL)
e->remove();
}
{
gui::IGUIElement *e = getElementFromId(259);
if(e != NULL)
e->remove();
}
{
gui::IGUIElement *e = getElementFromId(260);
if(e != NULL)
e->remove();
}
{
gui::IGUIElement *e = getElementFromId(261);
if(e != NULL)
e->remove();
}
}
void GUIPauseMenu::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();
/*
Add stuff
*/
const s32 btn_height = 30;
const s32 btn_gap = 20;
const s32 btn_num = m_simple_singleplayer_mode ? 3 : 4;
s32 btn_y = size.Y/2-((btn_num*btn_height+(btn_num-1)*btn_gap))/2;
changeCtype("");
{
core::rect<s32> rect(0, 0, 140, btn_height);
rect = rect + v2s32(size.X/2-140/2, btn_y);
Environment->addButton(rect, this, 256,
wgettext("Continue"));
}
btn_y += btn_height + btn_gap;
if(!m_simple_singleplayer_mode)
{
{
core::rect<s32> rect(0, 0, 140, btn_height);
rect = rect + v2s32(size.X/2-140/2, btn_y);
Environment->addButton(rect, this, 261,
wgettext("Change Password"));
}
btn_y += btn_height + btn_gap;
}
{
core::rect<s32> rect(0, 0, 140, btn_height);
rect = rect + v2s32(size.X/2-140/2, btn_y);
Environment->addButton(rect, this, 260,
wgettext("Exit to Menu"));
}
btn_y += btn_height + btn_gap;
{
core::rect<s32> rect(0, 0, 140, btn_height);
rect = rect + v2s32(size.X/2-140/2, btn_y);
Environment->addButton(rect, this, 257,
wgettext("Exit to OS"));
}
{
core::rect<s32> rect(0, 0, 180, 240);
rect = rect + v2s32(size.X/2 + 90, size.Y/2-rect.getHeight()/2);
Environment->addStaticText(chartowchar_t(gettext(
"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"
)), rect, false, true, this, 258);
}
{
core::rect<s32> rect(0, 0, 180, 220);
rect = rect + v2s32(size.X/2 - 90 - rect.getWidth(), size.Y/2-rect.getHeight()/2);
v2u32 max_texture_size;
{
video::IVideoDriver* driver = Environment->getVideoDriver();
max_texture_size = driver->getMaxTextureSize();
}
std::ostringstream os;
os<<"Minetest\n";
os<<BUILD_INFO<<"\n";
os<<"path_user = "<<wrap_rows(porting::path_user, 20)<<"\n";
Environment->addStaticText(narrow_to_wide(os.str()).c_str(), rect, false, true, this, 259);
}
changeCtype("C");
}
void GUIPauseMenu::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();
}
bool GUIPauseMenu::OnEvent(const SEvent& event)
{
if(event.EventType==EET_KEY_INPUT_EVENT)
{
if(event.KeyInput.PressedDown)
{
if(event.KeyInput.Key==KEY_ESCAPE)
{
quitMenu();
return true;
}
else if(event.KeyInput.Key==KEY_RETURN)
{
quitMenu();
return true;
}
}
}
if(event.EventType==EET_GUI_EVENT)
{
if(event.GUIEvent.EventType==gui::EGET_ELEMENT_FOCUS_LOST
&& isVisible())
{
if(!canTakeFocus(event.GUIEvent.Element))
{
dstream<<"GUIPauseMenu: 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 256: // continue
quitMenu();
// ALWAYS return immediately after quitMenu()
return true;
case 261:
quitMenu();
m_gamecallback->changePassword();
return true;
case 260: // disconnect
m_gamecallback->disconnect();
quitMenu();
return true;
case 257: // exit
m_gamecallback->exitToOS();
quitMenu();
return true;
}
}
}
return Parent ? Parent->OnEvent(event) : false;
}

View File

@ -1,60 +1,60 @@
/*
Minetest-c55
Copyright (C) 2010 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 GUIPAUSEMENU_HEADER
#define GUIPAUSEMENU_HEADER
#include "irrlichttypes_extrabloated.h"
#include "modalMenu.h"
class IGameCallback
{
public:
virtual void exitToOS() = 0;
virtual void disconnect() = 0;
virtual void changePassword() = 0;
};
class GUIPauseMenu : public GUIModalMenu
{
public:
GUIPauseMenu(gui::IGUIEnvironment* env,
gui::IGUIElement* parent, s32 id,
IGameCallback *gamecallback,
IMenuManager *menumgr,
bool simple_singleplayer_mode);
~GUIPauseMenu();
void removeChildren();
/*
Remove and re-add (or reposition) stuff
*/
void regenerateGui(v2u32 screensize);
void drawMenu();
bool OnEvent(const SEvent& event);
private:
IGameCallback *m_gamecallback;
bool m_simple_singleplayer_mode;
};
#endif
/*
Minetest-c55
Copyright (C) 2010 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 GUIPAUSEMENU_HEADER
#define GUIPAUSEMENU_HEADER
#include "irrlichttypes_extrabloated.h"
#include "modalMenu.h"
class IGameCallback
{
public:
virtual void exitToOS() = 0;
virtual void disconnect() = 0;
virtual void changePassword() = 0;
};
class GUIPauseMenu : public GUIModalMenu
{
public:
GUIPauseMenu(gui::IGUIEnvironment* env,
gui::IGUIElement* parent, s32 id,
IGameCallback *gamecallback,
IMenuManager *menumgr,
bool simple_singleplayer_mode);
~GUIPauseMenu();
void removeChildren();
/*
Remove and re-add (or reposition) stuff
*/
void regenerateGui(v2u32 screensize);
void drawMenu();
bool OnEvent(const SEvent& event);
private:
IGameCallback *m_gamecallback;
bool m_simple_singleplayer_mode;
};
#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));
@ -1579,7 +1582,7 @@ int main(int argc, char *argv[])
if(menudata.selected_world != -1)
g_settings->set("selected_world_path",
worldspecs[menudata.selected_world].path);
// Break out of menu-game loop to shut down cleanly
if(device->run() == false || kill == true)
break;
@ -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,19 +33,20 @@ 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<<")"
/*
SQLite format specification:
- Initially only replaces sectors/ and sectors2/
If map.sqlite does not exist in the save dir
or the block was not found in the database
the map will try to load from sectors folder.
In either case, map.sqlite will be created
and all future saves will save there.
Structure of map.sqlite:
Tables:
blocks
@ -108,14 +109,14 @@ MapSector * Map::getSectorNoGenerateNoExNoLock(v2s16 p)
MapSector * sector = m_sector_cache;
return sector;
}
core::map<v2s16, MapSector*>::Node *n = m_sectors.find(p);
if(n == NULL)
return NULL;
MapSector *sector = n->getValue();
// Cache the last result
m_sector_cache_p = p;
m_sector_cache = sector;
@ -133,7 +134,7 @@ MapSector * Map::getSectorNoGenerate(v2s16 p)
MapSector *sector = getSectorNoGenerateNoEx(p);
if(sector == NULL)
throw InvalidPositionException();
return sector;
}
@ -148,7 +149,7 @@ MapBlock * Map::getBlockNoCreateNoEx(v3s16 p3d)
}
MapBlock * Map::getBlockNoCreate(v3s16 p3d)
{
{
MapBlock *block = getBlockNoCreateNoEx(p3d);
if(block == NULL)
throw InvalidPositionException();
@ -248,10 +249,10 @@ void Map::unspreadLight(enum LightBank bank,
v3s16(0,-1,0), // bottom
v3s16(-1,0,0), // left
};
if(from_nodes.size() == 0)
return;
u32 blockchangecount = 0;
core::map<v3s16, u8> unlighted_nodes;
@ -265,12 +266,12 @@ void Map::unspreadLight(enum LightBank bank,
MapBlock *block = NULL;
// Cache this a bit, too
bool block_checked_in_modified = false;
for(; j.atEnd() == false; j++)
{
v3s16 pos = j.getNode()->getKey();
v3s16 blockpos = getNodeBlockPos(pos);
// Only fetch a new block if the block position has changed
try{
if(block == NULL || blockpos != blockpos_last){
@ -693,7 +694,7 @@ void Map::updateLighting(enum LightBank bank,
core::map<v3s16, u8> unlight_from;
int num_bottom_invalid = 0;
{
//TimeTaker t("first stuff");
@ -847,7 +848,7 @@ void Map::updateLighting(enum LightBank bank,
#if 0
{
//MapVoxelManipulator vmanip(this);
// Make a manual voxel manipulator and load all the blocks
// that touch the requested blocks
ManualMapVoxelManipulator vmanip(this);
@ -938,7 +939,7 @@ void Map::addNodeAndUpdate(v3s16 p, MapNode n,
/*PrintInfo(m_dout);
m_dout<<DTIME<<"Map::addNodeAndUpdate(): p=("
<<p.X<<","<<p.Y<<","<<p.Z<<")"<<std::endl;*/
/*
From this node to nodes underneath:
If lighting is sunlight (1.0), unlight neighbours and
@ -951,7 +952,7 @@ void Map::addNodeAndUpdate(v3s16 p, MapNode n,
bool node_under_sunlight = true;
core::map<v3s16, bool> light_sources;
/*
Collect old node for rollback
*/
@ -1440,10 +1441,10 @@ void Map::timerUpdate(float dtime, float unload_timeout,
core::list<v3s16> *unloaded_blocks)
{
bool save_before_unloading = (mapType() == MAPTYPE_SERVER);
// Profile modified reasons
Profiler modprofiler;
core::list<v2s16> sector_deletion_queue;
u32 deleted_blocks_count = 0;
u32 saved_blocks_count = 0;
@ -1461,12 +1462,12 @@ void Map::timerUpdate(float dtime, float unload_timeout,
core::list<MapBlock*> blocks;
sector->getBlocks(blocks);
for(core::list<MapBlock*>::Iterator i = blocks.begin();
i != blocks.end(); i++)
{
MapBlock *block = (*i);
block->incrementUsageTimer(dtime);
if(block->refGet() == 0 && block->getUsageTimer() > unload_timeout)
@ -1503,10 +1504,10 @@ void Map::timerUpdate(float dtime, float unload_timeout,
}
}
endSave();
// Finally delete the empty sectors
deleteSectors(sector_deletion_queue);
if(deleted_blocks_count != 0)
{
PrintInfo(infostream); // ServerMap/ClientMap:
@ -1560,7 +1561,7 @@ void Map::unloadUnusedData(float timeout,
i != blocks.end(); i++)
{
MapBlock *block = (*i);
if(block->getUsageTimer() > timeout)
{
// Save if modified
@ -1629,7 +1630,7 @@ void Map::transformLiquids(core::map<v3s16, MapBlock*> & modified_blocks)
// list of nodes that due to viscosity have not reached their max level height
UniqueQueue<v3s16> must_reflow;
// List of MapBlocks that will require a lighting update (due to lava)
core::map<v3s16, MapBlock*> lighting_modified_blocks;
@ -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:
@ -1714,7 +1715,7 @@ void Map::transformLiquids(core::map<v3s16, MapBlock*> & modified_blocks)
}
break;
case LIQUID_SOURCE:
// if this node is not (yet) of a liquid type, choose the first liquid type we encounter
// if this node is not (yet) of a liquid type, choose the first liquid type we encounter
if (liquid_kind == CONTENT_AIR)
liquid_kind = nodemgr->getId(nodemgr->get(nb.n).liquid_alternative_flowing);
if (nodemgr->getId(nodemgr->get(nb.n).liquid_alternative_flowing) != liquid_kind) {
@ -1824,7 +1825,7 @@ void Map::transformLiquids(core::map<v3s16, MapBlock*> & modified_blocks)
n0.param2 = ~(LIQUID_LEVEL_MASK | LIQUID_FLOW_DOWN_MASK);
}
n0.setContent(new_node_content);
// Find out whether there is a suspect for this action
std::string suspect;
if(m_gamedef->rollback()){
@ -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)
@ -2144,7 +2150,7 @@ void ServerMap::initBlockMake(mapgen::BlockMakeData *data, v3s16 blockpos)
<<"("<<blockpos.X<<","<<blockpos.Y<<","<<blockpos.Z<<") - "
<<"("<<blockpos.X<<","<<blockpos.Y<<","<<blockpos.Z<<")"
<<std::endl;
//s16 chunksize = 3;
//v3s16 chunk_offset(-1,-1,-1);
//s16 chunksize = 4;
@ -2167,7 +2173,7 @@ void ServerMap::initBlockMake(mapgen::BlockMakeData *data, v3s16 blockpos)
data->no_op = true;
return;
}
data->no_op = false;
data->seed = m_seed;
data->blockpos_min = blockpos_min;
@ -2180,7 +2186,7 @@ void ServerMap::initBlockMake(mapgen::BlockMakeData *data, v3s16 blockpos)
*/
{
//TimeTaker timer("initBlockMake() create area");
for(s16 x=blockpos_min.X-extra_borders.X;
x<=blockpos_max.X+extra_borders.X; x++)
for(s16 z=blockpos_min.Z-extra_borders.Z;
@ -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);
}
@ -2219,18 +2225,18 @@ void ServerMap::initBlockMake(mapgen::BlockMakeData *data, v3s16 blockpos)
}
}
}
/*
Now we have a big empty area.
Make a ManualMapVoxelManipulator that contains this and the
neighboring blocks
*/
// The area that contains this block and it's neighbors
v3s16 bigarea_blocks_min = blockpos_min - extra_borders;
v3s16 bigarea_blocks_max = blockpos_max + extra_borders;
data->vmanip = new ManualMapVoxelManipulator(this);
//data->vmanip->setMap(this);
@ -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;
@ -2314,7 +2320,7 @@ MapBlock* ServerMap::finishBlockMake(mapgen::BlockMakeData *data,
TimeTaker t("finishBlockMake lighting update");
core::map<v3s16, MapBlock*> lighting_update_blocks;
// Center blocks
for(s16 x=blockpos_min.X-extra_borders.X;
x<=blockpos_max.X+extra_borders.X; x++)
@ -2331,7 +2337,7 @@ MapBlock* ServerMap::finishBlockMake(mapgen::BlockMakeData *data,
updateLighting(lighting_update_blocks, changed_blocks);
#endif
/*
Set lighting to non-expired state in all of them.
This is cheating, but it is not fast enough if all of them
@ -2385,7 +2391,7 @@ MapBlock* ServerMap::finishBlockMake(mapgen::BlockMakeData *data,
assert(block);
block->setGenerated(true);
}
/*
Save changed parts of map
NOTE: Will be saved later.
@ -2429,14 +2435,14 @@ ServerMapSector * ServerMap::createSector(v2s16 p2d)
DSTACKF("%s: p2d=(%d,%d)",
__FUNCTION_NAME,
p2d.X, p2d.Y);
/*
Check if it exists already in memory
*/
ServerMapSector *sector = (ServerMapSector*)getSectorNoGenerateNoEx(p2d);
if(sector != NULL)
return sector;
/*
Try to load it from disk (with blocks)
*/
@ -2469,9 +2475,9 @@ ServerMapSector * ServerMap::createSector(v2s16 p2d)
/*
Generate blank sector
*/
sector = new ServerMapSector(this, p2d, m_gamedef);
// Sector position on map in nodes
v2s16 nodepos2d = p2d * MAP_BLOCKSIZE;
@ -2479,10 +2485,11 @@ ServerMapSector * ServerMap::createSector(v2s16 p2d)
Insert to container
*/
m_sectors.insert(p2d, sector);
return sector;
}
#if 0
/*
This is a quick-hand function for calling makeBlock().
*/
@ -2492,20 +2499,20 @@ MapBlock * ServerMap::generateBlock(
)
{
DSTACKF("%s: p=(%d,%d,%d)", __FUNCTION_NAME, p.X, p.Y, p.Z);
/*infostream<<"generateBlock(): "
<<"("<<p.X<<","<<p.Y<<","<<p.Z<<")"
<<std::endl;*/
bool enable_mapgen_debug_info = g_settings->getBool("enable_mapgen_debug_info");
TimeTaker timer("generateBlock");
//MapBlock *block = original_dummy;
v2s16 p2d(p.X, p.Z);
v2s16 p2d_nodes = p2d * MAP_BLOCKSIZE;
/*
Do not generate over-limit
*/
@ -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,12 +2603,13 @@ MapBlock * ServerMap::generateBlock(
return block;
}
#endif
MapBlock * ServerMap::createBlock(v3s16 p)
{
DSTACKF("%s: p=(%d,%d,%d)",
__FUNCTION_NAME, p.X, p.Y, p.Z);
/*
Do not create over-limit
*/
@ -2611,7 +2620,7 @@ MapBlock * ServerMap::createBlock(v3s16 p)
|| p.Z < -MAP_GENERATION_LIMIT / MAP_BLOCKSIZE
|| p.Z > MAP_GENERATION_LIMIT / MAP_BLOCKSIZE)
throw InvalidPositionException("createBlock(): pos. over limit");
v2s16 p2d(p.X, p.Z);
s16 block_y = p.Y;
/*
@ -2656,15 +2665,16 @@ 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);
if(block && block->isDummy() == false)
@ -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);
@ -2697,10 +2713,10 @@ MapBlock * ServerMap::emergeBlock(v3s16 p, bool allow_generate)
// Queue event
dispatchEvent(&event);
return block;
}
}
}*/
return NULL;
}
@ -2741,8 +2757,8 @@ 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;
@ -2767,48 +2783,48 @@ void ServerMap::createDatabase() {
void ServerMap::verifyDatabase() {
if(m_database)
return;
{
std::string dbp = m_savedir + DIR_DELIM + "map.sqlite";
bool needs_create = false;
int d;
/*
Open the database connection
*/
createDirs(m_savedir);
if(!fs::PathExists(dbp))
needs_create = true;
d = sqlite3_open_v2(dbp.c_str(), &m_database, SQLITE_OPEN_READWRITE | SQLITE_OPEN_CREATE, NULL);
if(d != SQLITE_OK) {
infostream<<"WARNING: Database failed to open: "<<sqlite3_errmsg(m_database)<<std::endl;
throw FileNotGoodException("Cannot open database file");
}
if(needs_create)
createDatabase();
d = sqlite3_prepare(m_database, "SELECT `data` FROM `blocks` WHERE `pos`=? LIMIT 1", -1, &m_database_read, NULL);
if(d != SQLITE_OK) {
infostream<<"WARNING: Database read statment failed to prepare: "<<sqlite3_errmsg(m_database)<<std::endl;
throw FileNotGoodException("Cannot prepare read statement");
}
d = sqlite3_prepare(m_database, "REPLACE INTO `blocks` VALUES(?, ?)", -1, &m_database_write, NULL);
if(d != SQLITE_OK) {
infostream<<"WARNING: Database write statment failed to prepare: "<<sqlite3_errmsg(m_database)<<std::endl;
throw FileNotGoodException("Cannot prepare write statement");
}
d = sqlite3_prepare(m_database, "SELECT `pos` FROM `blocks`", -1, &m_database_list, NULL);
if(d != SQLITE_OK) {
infostream<<"WARNING: Database list statment failed to prepare: "<<sqlite3_errmsg(m_database)<<std::endl;
throw FileNotGoodException("Cannot prepare read statement");
}
infostream<<"ServerMap: Database opened"<<std::endl;
}
}
@ -2913,11 +2929,11 @@ void ServerMap::save(ModifiedState save_level)
infostream<<"WARNING: Not saving map, saving disabled."<<std::endl;
return;
}
if(save_level == MOD_STATE_CLEAN)
infostream<<"ServerMap: Saving whole map, this can take time."
<<std::endl;
if(m_map_metadata_changed || save_level == MOD_STATE_CLEAN)
{
saveMapMeta();
@ -2925,11 +2941,11 @@ void ServerMap::save(ModifiedState save_level)
// Profile modified reasons
Profiler modprofiler;
u32 sector_meta_count = 0;
u32 block_count = 0;
u32 block_count_all = 0; // Number of blocks in memory
// Don't do anything with sqlite unless something is really saved
bool save_started = false;
@ -2938,7 +2954,7 @@ void ServerMap::save(ModifiedState save_level)
{
ServerMapSector *sector = (ServerMapSector*)i.getNode()->getValue();
assert(sector->getId() == MAPSECTOR_SERVER);
if(sector->differs_from_disk || save_level == MOD_STATE_CLEAN)
{
saveSectorMeta(sector);
@ -2947,11 +2963,11 @@ void ServerMap::save(ModifiedState save_level)
core::list<MapBlock*> blocks;
sector->getBlocks(blocks);
core::list<MapBlock*>::Iterator j;
for(j=blocks.begin(); j!=blocks.end(); j++)
{
MapBlock *block = *j;
block_count_all++;
if(block->getModified() >= save_level)
@ -3027,10 +3043,10 @@ void ServerMap::listAllLoadableBlocks(core::list<v3s16> &dst)
errorstream<<"Map::listAllLoadableBlocks(): Result will be missing "
<<"all blocks that are stored in flat files"<<std::endl;
}
{
verifyDatabase();
while(sqlite3_step(m_database_list) == SQLITE_ROW)
{
sqlite3_int64 block_i = sqlite3_column_int64(m_database_list, 0);
@ -3044,13 +3060,13 @@ void ServerMap::listAllLoadableBlocks(core::list<v3s16> &dst)
void ServerMap::saveMapMeta()
{
DSTACK(__FUNCTION_NAME);
/*infostream<<"ServerMap::saveMapMeta(): "
<<"seed="<<m_seed
<<std::endl;*/
createDirs(m_savedir);
std::string fullpath = m_savedir + DIR_DELIM + "map_meta.txt";
std::ofstream os(fullpath.c_str(), std::ios_base::binary);
if(os.good() == false)
@ -3059,21 +3075,28 @@ void ServerMap::saveMapMeta()
<<"could not open"<<fullpath<<std::endl;
throw FileNotGoodException("Cannot open chunk metadata");
}
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);
os<<"[end_of_params]\n";
m_map_metadata_changed = false;
}
void ServerMap::loadMapMeta()
{
DSTACK(__FUNCTION_NAME);
/*infostream<<"ServerMap::loadMapMeta(): Loading map metadata"
<<std::endl;*/
@ -3101,7 +3124,18 @@ void ServerMap::loadMapMeta()
params.parseConfigLine(line);
}
m_seed = params.getU64("seed");
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;
}
@ -3115,14 +3149,14 @@ void ServerMap::saveSectorMeta(ServerMapSector *sector)
v2s16 pos = sector->getPos();
std::string dir = getSectorDir(pos);
createDirs(dir);
std::string fullpath = dir + DIR_DELIM + "meta";
std::ofstream o(fullpath.c_str(), std::ios_base::binary);
if(o.good() == false)
throw FileNotGoodException("Cannot open sector metafile");
sector->serialize(o, version);
sector->differs_from_disk = false;
}
@ -3161,7 +3195,7 @@ MapSector* ServerMap::loadSectorMeta(std::string sectordir, bool save_after_load
if(save_after_load)
saveSectorMeta(sector);
}
sector->differs_from_disk = false;
return sector;
@ -3206,7 +3240,7 @@ bool ServerMap::loadSectorMeta(v2s16 p2d)
{
return false;
}
return true;
}
@ -3250,7 +3284,7 @@ bool ServerMap::loadSectorFull(v2s16 p2d)
{
return false;
}
/*
Load blocks
*/
@ -3312,8 +3346,8 @@ void ServerMap::saveBlock(MapBlock *block)
u8 version = SER_FMT_VER_HIGHEST;
// Get destination
v3s16 p3d = block->getPos();
#if 0
v2s16 p2d(p3d.X, p3d.Z);
std::string sectordir = getSectorDir(p2d);
@ -3329,34 +3363,42 @@ void ServerMap::saveBlock(MapBlock *block)
[0] u8 serialization version
[1] data
*/
verifyDatabase();
std::ostringstream o(std::ios_base::binary);
o.write((char*)&version, 1);
// Write basic data
block->serialize(o, version, true);
// Write block to database
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<<") "
<<sqlite3_errmsg(m_database)<<std::endl;
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
block->resetModified();
if (success)
block->resetModified();
}
void ServerMap::loadBlock(std::string sectordir, std::string blockfile, MapSector *sector, bool save_after_load)
@ -3369,12 +3411,12 @@ void ServerMap::loadBlock(std::string sectordir, std::string blockfile, MapSecto
std::ifstream is(fullpath.c_str(), std::ios_base::binary);
if(is.good() == false)
throw FileNotGoodException("Cannot open block file");
v3s16 p3d = getBlockPos(sectordir, blockfile);
v2s16 p2d(p3d.X, p3d.Z);
assert(sector->getPos() == p2d);
u8 version = SER_FMT_VER_INVALID;
is.read((char*)&version, 1);
@ -3397,14 +3439,14 @@ void ServerMap::loadBlock(std::string sectordir, std::string blockfile, MapSecto
block = sector->createBlankBlockNoInsert(p3d.Y);
created_new = true;
}
// Read basic data
block->deSerialize(is, version, true);
// If it's a new block, insert it to the map
if(created_new)
sector->insertBlock(block);
/*
Save blocks loaded in old format in new format
*/
@ -3412,11 +3454,11 @@ void ServerMap::loadBlock(std::string sectordir, std::string blockfile, MapSecto
if(version < SER_FMT_VER_HIGHEST || save_after_load)
{
saveBlock(block);
// Should be in database now, so delete the old file
fs::RecursiveDelete(fullpath);
}
// We just loaded it from the disk, so it's up-to-date.
block->resetModified();
@ -3441,7 +3483,7 @@ void ServerMap::loadBlock(std::string *blob, v3s16 p3d, MapSector *sector, bool
try {
std::istringstream is(*blob, std::ios_base::binary);
u8 version = SER_FMT_VER_INVALID;
is.read((char*)&version, 1);
@ -3464,14 +3506,14 @@ void ServerMap::loadBlock(std::string *blob, v3s16 p3d, MapSector *sector, bool
block = sector->createBlankBlockNoInsert(p3d.Y);
created_new = true;
}
// Read basic data
block->deSerialize(is, version, true);
// If it's a new block, insert it to the map
if(created_new)
sector->insertBlock(block);
/*
Save blocks loaded in old format in new format
*/
@ -3480,7 +3522,7 @@ void ServerMap::loadBlock(std::string *blob, v3s16 p3d, MapSector *sector, bool
// Only save if asked to; no need to update version
if(save_after_load)
saveBlock(block);
// We just loaded it from, so it's up-to-date.
block->resetModified();
@ -3490,7 +3532,7 @@ void ServerMap::loadBlock(std::string *blob, v3s16 p3d, MapSector *sector, bool
errorstream<<"Invalid block data in database"
<<" ("<<p3d.X<<","<<p3d.Y<<","<<p3d.Z<<")"
<<" (SerializationError): "<<e.what()<<std::endl;
// TODO: Block should be marked as invalid in memory so that it is
// not touched but the game can run
@ -3512,7 +3554,7 @@ MapBlock* ServerMap::loadBlock(v3s16 blockpos)
if(!loadFromFolders()) {
verifyDatabase();
if(sqlite3_bind_int64(m_database_read, 1, getBlockAsInteger(blockpos)) != SQLITE_OK)
infostream<<"WARNING: Could not bind block position for load: "
<<sqlite3_errmsg(m_database)<<std::endl;
@ -3521,15 +3563,15 @@ MapBlock* ServerMap::loadBlock(v3s16 blockpos)
Make sure sector is loaded
*/
MapSector *sector = createSector(p2d);
/*
Load block
*/
const char * data = (const char *)sqlite3_column_blob(m_database_read, 0);
size_t len = sqlite3_column_bytes(m_database_read, 0);
std::string datastr(data, len);
loadBlock(&datastr, blockpos, sector, false);
sqlite3_step(m_database_read);
@ -3539,7 +3581,7 @@ MapBlock* ServerMap::loadBlock(v3s16 blockpos)
return getBlockNoCreateNoEx(blockpos);
}
sqlite3_reset(m_database_read);
// Not found in database, try the files
}
@ -3560,7 +3602,7 @@ MapBlock* ServerMap::loadBlock(v3s16 blockpos)
loadlayout = 2;
sectordir = getSectorDir(p2d, 2);
}
/*
Make sure sector is loaded
*/
@ -3583,7 +3625,7 @@ MapBlock* ServerMap::loadBlock(v3s16 blockpos)
return NULL;
}
}
/*
Make sure file exists
*/
@ -3641,7 +3683,7 @@ void MapVoxelManipulator::emerge(VoxelArea a, s32 caller_id)
n = m_loaded_blocks.find(p);
if(n != NULL)
continue;
bool block_data_inexistent = false;
try
{
@ -3652,7 +3694,7 @@ void MapVoxelManipulator::emerge(VoxelArea a, s32 caller_id)
<<" wanted area: ";
a.print(infostream);
infostream<<std::endl;*/
MapBlock *block = m_map->getBlockNoCreate(p);
if(block->isDummy())
block_data_inexistent = true;
@ -3692,12 +3734,12 @@ void MapVoxelManipulator::blitBack
{
if(m_area.getExtent() == v3s16(0,0,0))
return;
//TimeTaker timer1("blitBack");
/*infostream<<"blitBack(): m_loaded_blocks.size()="
<<m_loaded_blocks.size()<<std::endl;*/
/*
Initialize block cache
*/
@ -3716,9 +3758,9 @@ void MapVoxelManipulator::blitBack
continue;
MapNode &n = m_data[m_area.index(p)];
v3s16 blockpos = getNodeBlockPos(p);
try
{
// Get block
@ -3727,7 +3769,7 @@ void MapVoxelManipulator::blitBack
blockpos_last = blockpos;
block_checked_in_modified = false;
}
// Calculate relative position in block
v3s16 relpos = p - blockpos * MAP_BLOCKSIZE;
@ -3737,7 +3779,7 @@ void MapVoxelManipulator::blitBack
//m_map->setNode(m_area.MinEdge + p, n);
block->setNode(relpos, n);
/*
Make sure block is in modified_blocks
*/
@ -3780,7 +3822,7 @@ void ManualMapVoxelManipulator::initialEmerge(
VoxelArea block_area_nodes
(p_min*MAP_BLOCKSIZE, (p_max+1)*MAP_BLOCKSIZE-v3s16(1,1,1));
u32 size_MB = block_area_nodes.getVolume()*4/1000000;
if(size_MB >= 1)
{
@ -3801,7 +3843,7 @@ void ManualMapVoxelManipulator::initialEmerge(
n = m_loaded_blocks.find(p);
if(n != NULL)
continue;
bool block_data_inexistent = false;
try
{
@ -3842,7 +3884,7 @@ void ManualMapVoxelManipulator::blitBackAll(
{
if(m_area.getExtent() == v3s16(0,0,0))
return;
/*
Copy data of all blocks
*/

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
@ -83,7 +81,7 @@ struct MapEditEvent
already_known_by_peer(0)
{
}
MapEditEvent * clone()
{
MapEditEvent *event = new MapEditEvent();
@ -157,7 +155,7 @@ public:
{
return MAPTYPE_BASE;
}
/*
Drop (client) or delete (server) the map.
*/
@ -170,7 +168,7 @@ public:
void removeEventReceiver(MapEventReceiver *event_receiver);
// event shall be deleted by caller after the call.
void dispatchEvent(MapEditEvent *event);
// On failure returns NULL
MapSector * getSectorNoGenerateNoExNoLock(v2s16 p2d);
// Same as the above (there exists no lock anymore)
@ -192,22 +190,22 @@ public:
MapBlock * getBlockNoCreate(v3s16 p);
// Returns NULL if not found
MapBlock * getBlockNoCreateNoEx(v3s16 p);
/* Server overrides */
virtual MapBlock * emergeBlock(v3s16 p, bool allow_generate=true)
{ return getBlockNoCreateNoEx(p); }
// Returns InvalidPositionException if not found
bool isNodeUnderground(v3s16 p);
bool isValidPosition(v3s16 p);
// throws InvalidPositionException if not found
MapNode getNode(v3s16 p);
// throws InvalidPositionException if not found
void setNode(v3s16 p, MapNode & n);
// Returns a CONTENT_IGNORE node if not found
MapNode getNodeNoEx(v3s16 p);
@ -220,11 +218,11 @@ public:
v3s16 pos, u8 lightwas,
core::map<v3s16, bool> & light_sources,
core::map<v3s16, MapBlock*> & modified_blocks);
void spreadLight(enum LightBank bank,
core::map<v3s16, bool> & from_nodes,
core::map<v3s16, MapBlock*> & modified_blocks);
void lightNeighbors(enum LightBank bank,
v3s16 pos,
core::map<v3s16, MapBlock*> & modified_blocks);
@ -233,14 +231,14 @@ public:
s16 propagateSunlight(v3s16 start,
core::map<v3s16, MapBlock*> & modified_blocks);
void updateLighting(enum LightBank bank,
core::map<v3s16, MapBlock*> & a_blocks,
core::map<v3s16, MapBlock*> & modified_blocks);
void updateLighting(core::map<v3s16, MapBlock*> & a_blocks,
core::map<v3s16, MapBlock*> & modified_blocks);
/*
These handle lighting but not faces.
*/
@ -256,7 +254,7 @@ public:
*/
bool addNodeWithEvent(v3s16 p, MapNode n);
bool removeNodeWithEvent(v3s16 p);
/*
Takes the blocks at the edges into account
*/
@ -269,9 +267,9 @@ public:
// Call these before and after saving of many blocks
virtual void beginSave() {return;};
virtual void endSave() {return;};
virtual void save(ModifiedState save_level){assert(0);};
// Server implements this.
// Client leaves it as no-op.
virtual void saveBlock(MapBlock *block){};
@ -282,7 +280,7 @@ public:
*/
void timerUpdate(float dtime, float unload_timeout,
core::list<v3s16> *unloaded_blocks=NULL);
// Deletes sectors and their blocks from memory
// Takes cache into account
// If deleted sector is in sector cache, clears cache
@ -300,14 +298,14 @@ public:
// For debug printing. Prints "Map: ", "ServerMap: " or "ClientMap: "
virtual void PrintInfo(std::ostream &out);
void transformLiquids(core::map<v3s16, MapBlock*> & modified_blocks);
/*
Node metadata
These are basically coordinate wrappers to MapBlock
*/
NodeMetadata* getNodeMetadata(v3s16 p);
void setNodeMetadata(v3s16 p, NodeMetadata *meta);
void removeNodeMetadata(v3s16 p);
@ -316,7 +314,7 @@ public:
Node Timers
These are basically coordinate wrappers to MapBlock
*/
NodeTimer getNodeTimer(v3s16 p);
void setNodeTimer(v3s16 p, NodeTimer t);
void removeNodeTimer(v3s16 p);
@ -329,7 +327,7 @@ public:
/*
Variables
*/
protected:
std::ostream &m_dout; // A bit deprecated, could be removed
@ -340,7 +338,7 @@ protected:
core::map<v2s16, MapSector*> m_sectors;
// Be sure to set this to NULL when the cached sector is deleted
// Be sure to set this to NULL when the cached sector is deleted
MapSector *m_sector_cache;
v2s16 m_sector_cache_p;
@ -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,16 +377,16 @@ 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.
- Memory
@ -400,10 +398,11 @@ 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);
@ -439,32 +438,32 @@ public:
void save(ModifiedState save_level);
//void loadAll();
void listAllLoadableBlocks(core::list<v3s16> &dst);
// Saves map seed and possibly other stuff
void saveMapMeta();
void loadMapMeta();
/*void saveChunkMeta();
void loadChunkMeta();*/
// The sector mutex should be locked when calling most of these
// This only saves sector-specific data such as the heightmap
// (no MapBlocks)
// DEPRECATED? Sectors have no metadata anymore.
void saveSectorMeta(ServerMapSector *sector);
MapSector* loadSectorMeta(std::string dirname, bool save_after_load);
bool loadSectorMeta(v2s16 p2d);
// Full load of a sector including all blocks.
// returns true on success, false on failure.
bool loadSectorFull(v2s16 p2d);
// If sector is not found in memory, try to load it from disk.
// Returns true if sector now resides in memory
//bool deFlushSector(v2s16 p2d);
void saveBlock(MapBlock *block);
// This will generate a sector with getSector if not found.
void loadBlock(std::string sectordir, std::string blockfile, MapSector *sector, bool save_after_load=false);
@ -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;
@ -499,7 +505,7 @@ private:
This is reset to false when written on disk.
*/
bool m_map_metadata_changed;
/*
SQLite database and statements
*/
@ -514,7 +520,7 @@ class MapVoxelManipulator : public VoxelManipulator
public:
MapVoxelManipulator(Map *map);
virtual ~MapVoxelManipulator();
virtual void clear()
{
VoxelManipulator::clear();
@ -542,11 +548,11 @@ public:
void setMap(Map *map)
{m_map = map;}
virtual void emerge(VoxelArea a, s32 caller_id=-1);
void initialEmerge(v3s16 blockpos_min, v3s16 blockpos_max);
// This is much faster with big chunks of generated data
void blitBackAll(core::map<v3s16, MapBlock*> * modified_blocks);

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,
@ -190,7 +397,7 @@ static void make_room1(VoxelManipulator &vmanip, v3s16 roomsize, v3s16 roomplace
vmanip.m_data[vi] = MapNode(ndef->getId("mapgen_cobble"));
}
}
// Make +-Z walls
for(s16 x=0; x<roomsize.X; x++)
for(s16 y=0; y<roomsize.Y; y++)
@ -214,7 +421,7 @@ static void make_room1(VoxelManipulator &vmanip, v3s16 roomsize, v3s16 roomplace
vmanip.m_data[vi] = MapNode(ndef->getId("mapgen_cobble"));
}
}
// Make +-Y walls (floor and ceiling)
for(s16 z=0; z<roomsize.Z; z++)
for(s16 x=0; x<roomsize.X; x++)
@ -238,7 +445,7 @@ static void make_room1(VoxelManipulator &vmanip, v3s16 roomsize, v3s16 roomplace
vmanip.m_data[vi] = MapNode(ndef->getId("mapgen_cobble"));
}
}
// Fill with air
for(s16 z=1; z<roomsize.Z-1; z++)
for(s16 y=1; y<roomsize.Y-1; y++)
@ -401,9 +608,9 @@ static void make_corridor(VoxelManipulator &vmanip, v3s16 doorplace,
if(partcount >= partlength)
{
partcount = 0;
dir = random_turn(random, dir);
partlength = random.range(1,length);
make_stairs = 0;
@ -443,7 +650,7 @@ public:
{
m_dir = dir;
}
bool findPlaceForDoor(v3s16 &result_place, v3s16 &result_dir)
{
for(u32 i=0; i<100; i++)
@ -540,7 +747,7 @@ public:
if(doordir == v3s16(0,0,-1)) // Z-
roomplace = doorplace + v3s16(-roomsize.X/2,-1,-roomsize.Z+1);
#endif
// Check fit
bool fits = true;
for(s16 z=1; z<roomsize.Z-1; z++)
@ -587,7 +794,7 @@ static void make_dungeon1(VoxelManipulator &vmanip, PseudoRandom &random,
v3s16 areasize = vmanip.m_area.getExtent();
v3s16 roomsize;
v3s16 roomplace;
/*
Find place for first room
*/
@ -627,20 +834,20 @@ static void make_dungeon1(VoxelManipulator &vmanip, PseudoRandom &random,
// No place found
if(fits == false)
return;
/*
Stores the center position of the last room made, so that
a new corridor can be started from the last room instead of
the new room, if chosen so.
*/
v3s16 last_room_center = roomplace+v3s16(roomsize.X/2,1,roomsize.Z/2);
u32 room_count = random.range(2,7);
for(u32 i=0; i<room_count; i++)
{
// Make a room to the determined place
make_room1(vmanip, roomsize, roomplace, ndef);
v3s16 room_center = roomplace + v3s16(roomsize.X/2,1,roomsize.Z/2);
// Place torch at room center (for testing)
@ -649,7 +856,7 @@ static void make_dungeon1(VoxelManipulator &vmanip, PseudoRandom &random,
// Quit if last room
if(i == room_count-1)
break;
// Determine walker start position
bool start_in_last_room = (random.range(0,2)!=0);
@ -667,7 +874,7 @@ static void make_dungeon1(VoxelManipulator &vmanip, PseudoRandom &random,
// Store center of current room as the last one
last_room_center = room_center;
}
// Create walker and find a place for a door
RoomWalker walker(vmanip, walker_start_place, random, ndef);
v3s16 doorplace;
@ -675,20 +882,20 @@ static void make_dungeon1(VoxelManipulator &vmanip, PseudoRandom &random,
bool r = walker.findPlaceForDoor(doorplace, doordir);
if(r == false)
return;
if(random.range(0,1)==0)
// Make the door
make_door1(vmanip, doorplace, doordir, ndef);
else
// Don't actually make a door
doorplace -= doordir;
// Make a random corridor starting from the door
v3s16 corridor_end;
v3s16 corridor_end_dir;
make_corridor(vmanip, doorplace, doordir, corridor_end,
corridor_end_dir, random, ndef);
// Find a place for a random sized room
roomsize = v3s16(random.range(4,8),random.range(4,6),random.range(4,8));
walker.setPos(corridor_end);
@ -703,7 +910,7 @@ static void make_dungeon1(VoxelManipulator &vmanip, PseudoRandom &random,
else
// Don't actually make a door
roomplace -= doordir;
}
}
#endif
@ -926,7 +1133,7 @@ s16 find_ground_level_from_noise(u64 seed, v2s16 p2d, s16 precision)
}
}
}
// This is more like the actual ground level
level += dec[i-1]/2;
@ -1024,7 +1231,7 @@ bool block_is_underground(u64 seed, v3s16 blockpos)
seed, v2s16(blockpos.X, blockpos.Z));*/
// Nah, this is just a heuristic, just return something
s16 minimum_groundlevel = WATER_LEVEL;
if(blockpos.Y*MAP_BLOCKSIZE + MAP_BLOCKSIZE <= minimum_groundlevel)
return true;
else
@ -1132,9 +1339,9 @@ BiomeType get_biome(u64 seed, v2s16 p2d)
double d = noise2d_perlin(
0.6+(float)p2d.X/250, 0.2+(float)p2d.Y/250,
seed+9130, 3, 0.50);
if(d > 0.45)
if(d > 0.45)
return BT_DESERT;
if(d > 0.35 && (noise2d( p2d.X, p2d.Y, int(seed) ) + 1.0) > ( 0.45 - d ) * 20.0 )
if(d > 0.35 && (noise2d( p2d.X, p2d.Y, int(seed) ) + 1.0) > ( 0.45 - d ) * 20.0 )
return BT_DESERT;
return BT_NORMAL;
};
@ -1169,7 +1376,7 @@ void make_block(BlockMakeData *data)
// Hack: use minimum block coordinates for old code that assumes
// a single block
v3s16 blockpos = data->blockpos_requested;
/*dstream<<"makeBlock(): ("<<blockpos.X<<","<<blockpos.Y<<","
<<blockpos.Z<<")"<<std::endl;*/
@ -1177,7 +1384,7 @@ void make_block(BlockMakeData *data)
v3s16 blockpos_max = data->blockpos_max;
v3s16 blockpos_full_min = blockpos_min - v3s16(1,1,1);
v3s16 blockpos_full_max = blockpos_max + v3s16(1,1,1);
ManualMapVoxelManipulator &vmanip = *(data->vmanip);
// Area of central chunk
v3s16 node_min = blockpos_min*MAP_BLOCKSIZE;
@ -1193,10 +1400,10 @@ void make_block(BlockMakeData *data)
int volume_blocks = (blockpos_max.X - blockpos_min.X + 1)
* (blockpos_max.Y - blockpos_min.Y + 1)
* (blockpos_max.Z - blockpos_max.Z + 1);
int volume_nodes = volume_blocks *
MAP_BLOCKSIZE*MAP_BLOCKSIZE*MAP_BLOCKSIZE;
// Generated surface area
//double gen_area_nodes = MAP_BLOCKSIZE*MAP_BLOCKSIZE * rel_volume;
@ -1207,7 +1414,7 @@ void make_block(BlockMakeData *data)
Create a block-specific seed
*/
u32 blockseed = get_blockseed(data->seed, full_node_min);
/*
Cache some ground type values for speed
*/
@ -1253,13 +1460,13 @@ void make_block(BlockMakeData *data)
{
#if 1
TimeTaker timer1("Generating ground level");
for(s16 x=node_min.X; x<=node_max.X; x++)
for(s16 z=node_min.Z; z<=node_max.Z; z++)
{
// Node position
v2s16 p2d = v2s16(x,z);
/*
Skip of already generated
*/
@ -1274,7 +1481,7 @@ void make_block(BlockMakeData *data)
// Use perlin noise for ground height
surface_y_f = base_rock_level_2d(data->seed, p2d);
/*// Experimental stuff
{
float a = highlands_level_2d(data->seed, p2d);
@ -1284,7 +1491,7 @@ void make_block(BlockMakeData *data)
// Convert to integer
s16 surface_y = (s16)surface_y_f;
// Log it
if(surface_y > stone_surface_max_y)
stone_surface_max_y = surface_y;
@ -1316,9 +1523,9 @@ void make_block(BlockMakeData *data)
}
}
#endif
}//timer1
// Limit dirt flow area by 1 because mud is flown into neighbors.
assert(central_area_size.X == central_area_size.Z);
s16 mudflow_minpos = 0-max_spread_amount+1;
@ -1375,7 +1582,7 @@ void make_block(BlockMakeData *data)
tunnel_routepoints = ps.range(10, ps.range(15,30));
}
bool large_cave_is_flat = (ps.range(0,1) == 0);
v3f main_direction(0,0,0);
// Allowed route area size in nodes
@ -1391,7 +1598,7 @@ void make_block(BlockMakeData *data)
s16 more = max_spread_amount - max_tunnel_diameter/2 - insure;
ar += v3s16(1,0,1) * more * 2;
of -= v3s16(1,0,1) * more;
s16 route_y_min = 0;
// Allow half a diameter + 7 over stone surface
s16 route_y_max = -of.Y + stone_surface_max_y + max_tunnel_diameter/2 + 7;
@ -1434,7 +1641,7 @@ void make_block(BlockMakeData *data)
if(coming_from_surface)
route_start_y_min = -of.Y + stone_surface_max_y + 10;
}*/
route_start_y_min = rangelim(route_start_y_min, 0, ar.Y-1);
route_start_y_max = rangelim(route_start_y_max, route_start_y_min, ar.Y-1);
@ -1451,11 +1658,11 @@ void make_block(BlockMakeData *data)
MapNode airnode(CONTENT_AIR);
MapNode waternode(c_water_source);
MapNode lavanode(c_lava_source);
/*
Generate some tunnel starting from orp
*/
for(u16 j=0; j<tunnel_routepoints; j++)
{
if(j%dswitchint==0 && large_cave == false)
@ -1467,12 +1674,12 @@ void make_block(BlockMakeData *data)
);
main_direction *= (float)ps.range(0, 10)/10;
}
// Randomize size
s16 min_d = min_tunnel_diameter;
s16 max_d = max_tunnel_diameter;
s16 rs = ps.range(min_d, max_d);
// Every second section is rough
bool randomize_xz = (ps2.range(1,2) == 1);
@ -1495,13 +1702,13 @@ void make_block(BlockMakeData *data)
}
v3f vec;
vec = v3f(
(float)(ps.next()%(maxlen.X*1))-(float)maxlen.X/2,
(float)(ps.next()%(maxlen.Y*1))-(float)maxlen.Y/2,
(float)(ps.next()%(maxlen.Z*1))-(float)maxlen.Z/2
);
// Jump downward sometimes
if(!large_cave && ps.range(0,12) == 0)
{
@ -1511,7 +1718,7 @@ void make_block(BlockMakeData *data)
(float)(ps.next()%(maxlen.Z*1))-(float)maxlen.Z/2
);
}
/*if(large_cave){
v3f p = orp + vec;
s16 h = find_ground_level_clever(vmanip,
@ -1573,12 +1780,12 @@ void make_block(BlockMakeData *data)
s16 x = cp.X + x0;
v3s16 p(x,y,z);
p += of;
if(vmanip.m_area.contains(p) == false)
continue;
u32 i = vmanip.m_area.index(p);
if(large_cave)
{
if(full_node_min.Y < WATER_LEVEL &&
@ -1602,7 +1809,7 @@ void make_block(BlockMakeData *data)
vmanip.m_data[i].getContent() == c_water_source ||
vmanip.m_data[i].getContent() == c_lava_source)
continue;
vmanip.m_data[i] = airnode;
// Set tunnel flag
@ -1615,12 +1822,12 @@ void make_block(BlockMakeData *data)
orp = rp;
}
}
}//timer1
#endif
#if 1
{
// 15ms @cs=8
@ -1629,13 +1836,13 @@ void make_block(BlockMakeData *data)
/*
Add mud to the central chunk
*/
for(s16 x=node_min.X; x<=node_max.X; x++)
for(s16 z=node_min.Z; z<=node_max.Z; z++)
{
// Node position in 2d
v2s16 p2d = v2s16(x,z);
// Randomize mud amount
s16 mud_add_amount = get_mud_add_amount(data->seed, p2d) / 2.0 + 0.5;
@ -1660,7 +1867,7 @@ void make_block(BlockMakeData *data)
surface_y + mud_add_amount <= WATER_LEVEL+2){
addnode = MapNode(c_sand);
}
if(bt == BT_DESERT){
if(surface_y > 20){
mud_add_amount = MYMAX(0, mud_add_amount - (surface_y - 20)/5);
@ -1691,7 +1898,7 @@ void make_block(BlockMakeData *data)
{
if(mudcount >= mud_add_amount)
break;
MapNode &n = vmanip.m_data[i];
n = addnode;
mudcount++;
@ -1756,7 +1963,7 @@ void make_block(BlockMakeData *data)
/*
Flow mud away from steep edges
*/
// Iterate a few times
for(s16 k=0; k<3; k++)
{
@ -1773,7 +1980,7 @@ void make_block(BlockMakeData *data)
// Node position in 2d
v2s16 p2d = v2s16(node_min.X, node_min.Z) + v2s16(x,z);
v3s16 em = vmanip.m_area.getExtent();
u32 i = vmanip.m_area.index(v3s16(p2d.X, node_max.Y, p2d.Y));
s16 y=node_max.Y;
@ -1794,7 +2001,7 @@ void make_block(BlockMakeData *data)
n->getContent() == c_dirt_with_grass ||
n->getContent() == c_gravel)
break;
vmanip.m_area.add_y(em, i, -1);
}
@ -1813,7 +2020,7 @@ void make_block(BlockMakeData *data)
{
// Make it exactly mud
n->setContent(c_dirt);
/*
Don't flow it if the stuff under it is not mud
*/
@ -1851,7 +2058,7 @@ void make_block(BlockMakeData *data)
}
// Drop mud on side
for(u32 di=0; di<4; di++)
{
v3s16 dirp = dirs4[di];
@ -1894,7 +2101,7 @@ void make_block(BlockMakeData *data)
// Loop one up so that we're in air
vmanip.m_area.add_y(em, i2, 1);
n2 = &vmanip.m_data[i2];
bool old_is_water = (n->getContent() == c_water_source);
// Move mud to new place
if(!dropped_to_unknown) {
@ -1912,7 +2119,7 @@ void make_block(BlockMakeData *data)
}
}
}
}
}//timer1
@ -1940,7 +2147,7 @@ void make_block(BlockMakeData *data)
for(s16 y=full_node_max.Y; y>=full_node_min.Y; y--)
{
if(y == full_node_max.Y){
water_found =
water_found =
(vmanip.m_data[i].getContent() == c_water_source ||
vmanip.m_data[i].getContent() == c_lava_source);
}
@ -1982,7 +2189,7 @@ void make_block(BlockMakeData *data)
{
// Node position in 2d
v2s16 p2d = v2s16(x,z);
/*
Find the lowest surface to which enough light ends up
to make grass grow.
@ -2008,7 +2215,7 @@ void make_block(BlockMakeData *data)
else
surface_y = full_node_min.Y;
}
u32 i = vmanip.m_area.index(p2d.X, surface_y, p2d.Y);
MapNode *n = &vmanip.m_data[i];
if(n->getContent() == c_dirt){
@ -2113,7 +2320,7 @@ void make_block(BlockMakeData *data)
else
vmanip.m_data[i] = n_stone;
}
vmanip->m_area.add_y(em, i, 1);
}
}
@ -2168,7 +2375,7 @@ void make_block(BlockMakeData *data)
/*
Add dungeons
*/
//if(node_min.Y < approx_groundlevel)
//if(myrand() % 3 == 0)
//if(myrand() % 3 == 0 && node_min.Y < approx_groundlevel)
@ -2182,7 +2389,7 @@ void make_block(BlockMakeData *data)
// Dungeon generator doesn't modify places which have this set
vmanip->clearFlag(VMANIP_FLAG_DUNGEON_INSIDE
| VMANIP_FLAG_DUNGEON_PRESERVE);
// Set all air and water to be untouchable to make dungeons open
// to caves and open air
for(s16 x=full_node_min.X; x<=full_node_max.X; x++)
@ -2204,12 +2411,12 @@ void make_block(BlockMakeData *data)
}
}
}
PseudoRandom random(blockseed+2);
// Add it
make_dungeon1(vmanip, random, ndef);
// Convert some cobble to mossy cobble
for(s16 x=full_node_min.X; x<=full_node_max.X; x++)
for(s16 z=full_node_min.Z; z<=full_node_max.Z; z++)
@ -2257,7 +2464,7 @@ void make_block(BlockMakeData *data)
make_nc(vmanip, ncrandom, ndef);
}
}
/*
Add top and bottom side of water to transforming_liquid queue
*/
@ -2346,7 +2553,7 @@ void make_block(BlockMakeData *data)
if(current_depth == 0 && y <= WATER_LEVEL+2
&& possibly_have_sand)
have_sand = true;
if(current_depth < 4)
{
if(have_sand)
@ -2384,7 +2591,7 @@ void make_block(BlockMakeData *data)
/*
Calculate some stuff
*/
float surface_humidity = surface_humidity_2d(data->seed, p2d_center);
bool is_jungle = surface_humidity > 0.75;
// Amount of trees
@ -2521,7 +2728,7 @@ void make_block(BlockMakeData *data)
/*
Add some kind of random stones
*/
u32 random_stone_count = gen_area_nodes *
randomstone_amount_2d(data->seed, p2d_center);
// Put in random places on part of division
@ -2555,7 +2762,7 @@ void make_block(BlockMakeData *data)
/*
Add larger stones
*/
u32 large_stone_count = gen_area_nodes *
largestone_amount_2d(data->seed, p2d_center);
//u32 large_stone_count = 1;
@ -2612,7 +2819,7 @@ void make_block(BlockMakeData *data)
if(mineralrandom.next()%8 == 0)
vmanip.m_data[vi] = MapNode(c_mese);
}
}
}
/*
@ -2742,7 +2949,7 @@ void make_block(BlockMakeData *data)
voxalgo::clearLightAndCollectSources(vmanip, a, bank, ndef,
light_sources, unlight_from);
bool inexistent_top_provides_sunlight = !block_is_underground;
voxalgo::SunlightPropagateResult res = voxalgo::propagateSunlight(
vmanip, a, inexistent_top_provides_sunlight,
@ -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,48 +22,114 @@ 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);
struct BlockMakeData {
bool no_op;
ManualMapVoxelManipulator *vmanip;
u64 seed;
v3s16 blockpos_min;
v3s16 blockpos_max;
v3s16 blockpos_requested;
UniqueQueue<v3s16> transforming_liquid;
INodeDefManager *nodedef;
// Find out if block is completely underground
bool block_is_underground(u64 seed, v3s16 blockpos);
BlockMakeData();
~BlockMakeData();
};
// Get a pseudorandom seed for a position on the map
u32 get_blockseed(u64 seed, v3s16 p);
struct MapgenParams {
std::string mg_name;
int chunksize;
u64 seed;
int water_level;
u32 flags;
// Main map generation routine
void make_block(BlockMakeData *data);
MapgenParams() {
mg_name = "v6";
seed = 0;
water_level = 1;
chunksize = 5;
flags = MG_TREES | MG_CAVES | MGV6_BIOME_BLEND;
}
/*
These are used by FarMesh
*/
bool get_have_beach(u64 seed, v2s16 p2d);
double tree_amount_2d(u64 seed, v2s16 p);
virtual bool readParams(Settings *settings) = 0;
virtual void writeParams(Settings *settings) {};
};
struct BlockMakeData
{
bool no_op;
ManualMapVoxelManipulator *vmanip; // Destructor deletes
u64 seed;
v3s16 blockpos_min;
v3s16 blockpos_max;
v3s16 blockpos_requested;
UniqueQueue<v3s16> transforming_liquid;
INodeDefManager *nodedef;
class Mapgen {
public:
int seed;
int water_level;
bool generating;
int id;
BlockMakeData();
~BlockMakeData();
};
virtual void makeChunk(BlockMakeData *data) {};
virtual int getGroundLevelAtPoint(v2s16 p) = 0;
}; // namespace mapgen
//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));
}
std::set<std::string> depends;
std::ifstream is((modpath+DIR_DELIM+"depends.txt").c_str(),
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()){
std::string dep;
std::getline(is, dep);
dep = trim(dep);
if(dep != "")
depends.insert(dep);
while(is.good())
{
std::string dep;
std::getline(is, dep);
dep = trim(dep);
if(dep != "")
depends.insert(dep);
}
ModSpec spec(modname, modpath, depends);
result.insert(std::make_pair(modname,spec));
}
ModSpec spec(modname, modpath, depends);
mods_unsorted.push_back(spec);
if(depends.empty())
mods_satisfied.push(spec);
mod_names[modname] = modpath;
}
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, "");
}
// 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);
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));
}
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());
}
else //not a modpack
{
// infostream << "inserting mod " << mod.name << std::endl;
result.push_back(mod);
}
errs<<"."<<std::endl;
mods_sorted.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 mods_sorted;
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 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

@ -106,7 +106,7 @@ void NodeBox::deSerialize(std::istream &is)
/*
TileDef
*/
void TileDef::serialize(std::ostream &os) const
{
writeU8(os, 0); // version
@ -173,7 +173,7 @@ void ContentFeatures::reset()
has_after_destruct = false;
/*
Actual data
NOTE: Most of this is always overridden by the default values given
in builtin.lua
*/
@ -354,7 +354,7 @@ public:
ContentFeatures &f = m_content_features[i];
f.reset(); // Reset to defaults
}
// Set CONTENT_AIR
{
ContentFeatures f;
@ -541,11 +541,11 @@ public:
bool new_style_water = g_settings->getBool("new_style_water");
bool new_style_leaves = g_settings->getBool("new_style_leaves");
bool opaque_water = g_settings->getBool("opaque_water");
for(u16 i=0; i<=MAX_CONTENT; i++)
{
ContentFeatures *f = &m_content_features[i];
// Figure out the actual tiles to use
TileDef tiledef[6];
for(u32 j=0; j<6; j++)

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_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();
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;
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_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();
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);
NoiseParams *np;
int seed;
int sx;
int sy;
int sz;
float *noisebuf;
float *buf;
float *result;
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);
Noise(NoiseParams *np, int seed, int sx, int sy);
Noise(NoiseParams *np, int seed, int sx, int sy, int sz);
~Noise();
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 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);
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"
@ -58,7 +69,7 @@ void sigint_handler(int sig)
{
dstream<<DTIME<<"INFO: sigint_handler(): "
<<"Ctrl-C pressed, shutting down."<<std::endl;
// Comment out for less clutter when testing scripts
/*dstream<<DTIME<<"INFO: sigint_handler(): "
<<"Printing debug stacks"<<std::endl;
@ -79,8 +90,7 @@ void signal_handler_init(void)
#else // _WIN32
#include <signal.h>
#include <windows.h>
BOOL WINAPI event_handler(DWORD sig)
{
switch(sig)
@ -110,10 +120,10 @@ void signal_handler_init(void)
case CTRL_BREAK_EVENT:
break;
}
return TRUE;
}
void signal_handler_init(void)
{
SetConsoleCtrlHandler( (PHANDLER_ROUTINE)event_handler,TRUE);
@ -166,17 +176,16 @@ void initializePaths()
Windows
*/
#if defined(_WIN32)
#include <windows.h>
const DWORD buflen = 1000;
char buf[buflen];
DWORD len;
// Find path of executable and set path_share relative to it
len = GetModuleFileName(GetModuleHandle(NULL), buf, buflen);
assert(len < buflen);
pathRemoveFile(buf, '\\');
if(detectMSVCBuildDir(buf)){
infostream<<"MSVC build directory detected"<<std::endl;
path_share = std::string(buf) + "\\..\\..";
@ -191,25 +200,57 @@ void initializePaths()
Linux
*/
#elif defined(linux)
#include <unistd.h>
char buf[BUFSIZ];
memset(buf, 0, BUFSIZ);
// Get path to executable
assert(readlink("/proc/self/exe", buf, BUFSIZ-1) != -1);
pathRemoveFile(buf, '/');
path_share = std::string(buf) + "/..";
path_user = std::string(buf) + "/..";
/*
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,20 +269,19 @@ void initializePaths()
Windows
*/
#if defined(_WIN32)
#include <windows.h>
const DWORD buflen = 1000;
char buf[buflen];
DWORD len;
// Find path of executable and set path_share relative to it
len = GetModuleFileName(GetModuleHandle(NULL), buf, buflen);
assert(len < buflen);
pathRemoveFile(buf, '\\');
// Use ".\bin\.."
path_share = std::string(buf) + "\\..";
// Use "C:\Documents and Settings\user\Application Data\<PROJECT_NAME>"
len = GetEnvironmentVariable("APPDATA", buf, buflen);
assert(len < buflen);
@ -251,8 +291,7 @@ void initializePaths()
Linux
*/
#elif defined(linux)
#include <unistd.h>
// Get path to executable
std::string bindir = "";
{
@ -271,7 +310,7 @@ void initializePaths()
trylist.push_back(static_sharedir);
trylist.push_back(bindir + "/../share/" + PROJECT_NAME);
trylist.push_back(bindir + "/..");
for(std::list<std::string>::const_iterator i = trylist.begin();
i != trylist.end(); i++)
{
@ -289,14 +328,13 @@ void initializePaths()
path_share = trypath;
break;
}
path_user = std::string(getenv("HOME")) + "/." + PROJECT_NAME;
/*
OS X
*/
#elif defined(__APPLE__)
#include <unistd.h>
// Code based on
// http://stackoverflow.com/questions/516200/relative-paths-not-working-in-xcode-c
@ -315,14 +353,14 @@ void initializePaths()
dstream<<"WARNING: Could not determine bundle resource path"<<std::endl;
}
CFRelease(resources_url);
path_user = std::string(getenv("HOME")) + "/Library/Application Support/" + PROJECT_NAME;
#elif defined(__FreeBSD__)
path_share = STATIC_SHAREDIR;
path_user = std::string(getenv("HOME")) + "/." + PROJECT_NAME;
#endif
#endif // RUN_IN_PLACE

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
{

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

View File

@ -103,14 +103,14 @@ public:
delete q;
}
}
/*
peer_id=0 adds with nobody to send to
*/
void addBlock(u16 peer_id, v3s16 pos, u8 flags)
{
DSTACK(__FUNCTION_NAME);
JMutexAutoLock lock(m_mutex);
if(peer_id != 0)
@ -130,7 +130,7 @@ public:
}
}
}
/*
Add the block
*/
@ -160,7 +160,7 @@ public:
JMutexAutoLock lock(m_mutex);
return m_queue.size();
}
u32 peerItemCount(u16 peer_id)
{
JMutexAutoLock lock(m_mutex);
@ -238,7 +238,7 @@ struct PlayerInfo
/*
Used for queueing and sorting block transfers in containers
Lower priority number means higher priority.
*/
struct PrioritySortedBlockTransfer
@ -303,7 +303,7 @@ struct ServerSoundParams
max_hear_distance(32*BS),
loop(false)
{}
v3f getPos(ServerEnvironment *env, bool *pos_exists) const;
};
@ -347,7 +347,7 @@ public:
~RemoteClient()
{
}
/*
Finds block that should be sent next to the client.
Environment should be locked when this is called.
@ -367,7 +367,7 @@ public:
{
return m_blocks_sending.size();
}
// Increments timeouts and removes timed-out blocks from list
// NOTE: This doesn't fix the server-not-sending-block bug
// because it is related to emerging, not sending.
@ -386,13 +386,13 @@ public:
// Time from last placing or removing blocks
float m_time_from_building;
/*JMutex m_dig_mutex;
float m_dig_time_remaining;
// -1 = not digging
s16 m_dig_tool_item;
v3s16 m_dig_position;*/
/*
List of active objects that the client knows of.
Value is dummy.
@ -405,7 +405,7 @@ private:
- These don't have to be sent again.
- A block is cleared from here when client says it has
deleted it from it's memory
Key is position, value is dummy.
No MapBlock* is stored here because the blocks can get deleted.
*/
@ -413,7 +413,7 @@ private:
s16 m_nearest_unsent_d;
v3s16 m_last_center;
float m_nearest_unsent_reset_timer;
/*
Blocks that are currently on the line.
This is used for throttling the sending of blocks.
@ -432,7 +432,7 @@ private:
This is resetted by PrintInfo()
*/
u32 m_excess_gotblocks;
// CPU usage optimization
u32 m_nothing_to_send_counter;
float m_nothing_to_send_pause_timer;
@ -446,7 +446,7 @@ public:
/*
NOTE: Every public method should be thread-safe
*/
Server(
const std::string &path_world,
const std::string &path_config,
@ -477,7 +477,7 @@ public:
{
return m_shutdown_requested;
}
/*
Shall be called with the environment locked.
This is accessed by the map, which is inside the environment,
@ -503,7 +503,7 @@ public:
// Envlock + conlock
s32 playSound(const SimpleSoundSpec &spec, const ServerSoundParams &params);
void stopSound(s32 handle);
// Envlock + conlock
std::set<std::string> getPlayerEffectivePrivs(const std::string &name);
bool checkPriv(const std::string &name, const std::string &priv);
@ -534,26 +534,32 @@ public:
{
return m_con.GetPeerAddress(peer_id);
}
// Envlock and conlock should be locked when calling this
void notifyPlayer(const char *name, const std::wstring msg);
void notifyPlayers(const std::wstring msg);
void queueBlockEmerge(v3s16 blockpos, bool allow_generate);
// Creates or resets inventory
Inventory* createDetachedInventory(const std::string &name);
// Envlock and conlock should be locked when using Lua
lua_State *getLua(){ return m_lua; }
// 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,
std::list<std::string> *log);
// IGameDef interface
// Under envlock
virtual IItemDefManager* getItemDefManager();
@ -565,7 +571,7 @@ public:
virtual ISoundManager* getSoundManager();
virtual MtEventManager* getEventManager();
virtual IRollbackReportSink* getRollbackReportSink();
IWritableItemDefManager* getWritableItemDefManager();
IWritableNodeDefManager* getWritableNodeDefManager();
IWritableCraftDefManager* getWritableCraftDefManager();
@ -573,7 +579,7 @@ public:
const ModSpec* getModSpec(const std::string &modname);
void getModNames(core::list<std::string> &modlist);
std::string getBuiltinLuaPath();
std::string getWorldPath(){ return m_path_world; }
bool isSingleplayer(){ return m_simple_singleplayer_mode; }
@ -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.
@ -590,11 +597,11 @@ private:
// As of now, these create and remove clients and players.
void peerAdded(con::Peer *peer);
void deletingPeer(con::Peer *peer, bool timeout);
/*
Static send methods
*/
static void SendHP(con::Connection &con, u16 peer_id, u8 hp);
static void SendAccessDenied(con::Connection &con, u16 peer_id,
const std::wstring &reason);
@ -604,7 +611,7 @@ private:
IItemDefManager *itemdef);
static void SendNodeDef(con::Connection &con, u16 peer_id,
INodeDefManager *nodedef, u16 protocol_version);
/*
Non-static send methods.
Conlock should be always used.
@ -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
@ -631,18 +639,18 @@ private:
void sendAddNode(v3s16 p, MapNode n, u16 ignore_id=0,
core::list<u16> *far_players=NULL, float far_d_nodes=100);
void setBlockNotSent(v3s16 p);
// Environment and Connection must be locked when called
void SendBlockNoLock(u16 peer_id, MapBlock *block, u8 ver);
// Sends blocks to clients (locks env and con on its own)
void SendBlocks(float dtime);
void fillMediaCache();
void sendMediaAnnouncement(u16 peer_id);
void sendRequestedMedia(u16 peer_id,
const core::list<MediaRequest> &tosend);
void sendDetachedInventory(const std::string &name, u16 peer_id);
void sendDetachedInventoryToAll(const std::string &name);
void sendDetachedInventories(u16 peer_id);
@ -650,15 +658,15 @@ private:
/*
Something random
*/
void DiePlayer(u16 peer_id);
void RespawnPlayer(u16 peer_id);
void UpdateCrafting(u16 peer_id);
// When called, connection mutex should be locked
RemoteClient* getClient(u16 peer_id);
// When called, environment mutex should be locked
std::string getPlayerName(u16 peer_id)
{
@ -685,7 +693,7 @@ private:
Call with env and con locked.
*/
PlayerSAO *emergePlayer(const char *name, u16 peer_id);
// Locks environment and connection by its own
struct PeerChange;
void handlePeerChange(PeerChange &c);
@ -694,7 +702,7 @@ private:
/*
Variables
*/
// World directory
std::string m_path_world;
// Path to user's configuration file ("" = no configuration file)
@ -707,7 +715,7 @@ private:
// Thread can set; step() will throw as ServerError
MutexedVariable<std::string> m_async_fatal_error;
// Some timers
float m_liquid_transform_timer;
float m_print_info_timer;
@ -715,14 +723,14 @@ private:
float m_emergethread_trigger_timer;
float m_savemap_timer;
IntervalLimiter m_map_timer_and_unload_interval;
// NOTE: If connection and environment are both to be locked,
// environment shall be locked first.
// Environment
ServerEnvironment *m_env;
JMutex m_env_mutex;
// Connection
con::Connection m_con;
JMutex m_con_mutex;
@ -737,29 +745,35 @@ 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;
// Item definition manager
IWritableItemDefManager *m_itemdef;
// Node definition manager
IWritableNodeDefManager *m_nodedef;
// Craft definition manager
IWritableCraftDefManager *m_craftdef;
// Event manager
EventManager *m_event;
// Mods
core::list<ModSpec> m_mods;
std::vector<ModSpec> m_mods;
/*
Threads
*/
// A buffer for time steps
// step() increments and AsyncRunStep() run by m_thread reads it.
float m_step_dtime;
@ -771,7 +785,7 @@ private:
EmergeThread m_emergethread;
// Queue of block coordinates to be processed by the emerge thread
BlockEmergeQueue m_emerge_queue;
/*
Time related stuff
*/
@ -780,7 +794,7 @@ private:
float m_time_of_day_send_timer;
// Uptime of server in seconds
MutexedVariable<double> m_uptime;
/*
Peer change queue.
Queues stuff from peerAdded() and deletingPeer() to
@ -802,7 +816,7 @@ private:
/*
Random stuff
*/
// Mod parent directory paths
core::list<std::string> m_modspaths;

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
{
@ -61,7 +62,7 @@ public:
void writeLines(std::ostream &os)
{
JMutexAutoLock lock(m_mutex);
for(core::map<std::string, std::string>::Iterator
i = m_settings.getIterator();
i.atEnd() == false; i++)
@ -71,13 +72,33 @@ public:
os<<name<<" = "<<value<<"\n";
}
}
// 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);
std::string trimmedline = trim(line);
// Ignore empty lines and comments
if(trimmedline.size() == 0 || trimmedline[0] == '#')
return true;
@ -91,15 +112,15 @@ public:
if(name == "")
return true;
std::string value = sf.next("\n");
value = trim(value);
/*infostream<<"Config name=\""<<name<<"\" value=\""
<<value<<"\""<<std::endl;*/
m_settings[name] = value;
return true;
}
@ -124,7 +145,7 @@ public:
{
if(is.eof())
return false;
/*
NOTE: This function might be expanded to allow multi-line
settings.
@ -149,16 +170,16 @@ public:
/*infostream<<"Parsing configuration file: \""
<<filename<<"\""<<std::endl;*/
while(parseConfigObject(is));
return true;
}
/*
Reads a configuration object from stream (usually a single line)
and adds it to dst.
Preserves comments and empty lines.
Settings that were added to dst are also added to updated.
@ -172,10 +193,10 @@ public:
bool &value_changed)
{
JMutexAutoLock lock(m_mutex);
if(is.eof())
return false;
// NOTE: This function will be expanded to allow multi-line settings
std::string line;
std::getline(is, line);
@ -185,7 +206,7 @@ public:
std::string line_end = "";
if(is.eof() == false)
line_end = "\n";
// Ignore empty lines and comments
if(trimmedline.size() == 0 || trimmedline[0] == '#')
{
@ -203,14 +224,14 @@ public:
dst.push_back(line+line_end);
return true;
}
std::string value = sf.next("\n");
value = trim(value);
if(m_settings.find(name))
{
std::string newvalue = m_settings[name];
if(newvalue != value)
{
infostream<<"Changing value of \""<<name<<"\" = \""
@ -223,7 +244,9 @@ public:
updated[name] = true;
}
else //file contains a setting which is not in m_settings
value_changed=true;
return true;
}
@ -236,11 +259,11 @@ public:
{
infostream<<"Updating configuration file: \""
<<filename<<"\""<<std::endl;
core::list<std::string> objects;
core::map<std::string, bool> updated;
bool something_actually_changed = false;
// Read and modify stuff
{
std::ifstream is(filename);
@ -257,9 +280,9 @@ public:
something_actually_changed));
}
}
JMutexAutoLock lock(m_mutex);
// If something not yet determined to have been changed, check if
// any new stuff was added
if(!something_actually_changed){
@ -273,14 +296,14 @@ public:
break;
}
}
// If nothing was actually changed, skip writing the file
if(!something_actually_changed){
infostream<<"Skipping writing of "<<filename
<<" because content wouldn't be modified"<<std::endl;
return true;
}
// Write stuff back
{
std::ofstream os(filename);
@ -291,7 +314,7 @@ public:
<<filename<<"\""<<std::endl;
return false;
}
/*
Write updated stuff
*/
@ -318,7 +341,7 @@ public:
os<<name<<" = "<<value<<"\n";
}
}
return true;
}
@ -368,7 +391,7 @@ public:
ValueType type = n->getValue().type;
std::string value = "";
if(type == VALUETYPE_FLAG)
{
value = "true";
@ -384,7 +407,7 @@ public:
value = argv[i];
i++;
}
infostream<<"Valid command-line parameter: \""
<<name<<"\" = \""<<value<<"\""
@ -398,7 +421,7 @@ public:
void set(std::string name, std::string value)
{
JMutexAutoLock lock(m_mutex);
m_settings[name] = value;
}
@ -413,21 +436,21 @@ public:
void setDefault(std::string name, std::string value)
{
JMutexAutoLock lock(m_mutex);
m_defaults[name] = value;
}
bool exists(std::string name)
{
JMutexAutoLock lock(m_mutex);
return (m_settings.find(name) || m_defaults.find(name));
}
std::string get(std::string name)
{
JMutexAutoLock lock(m_mutex);
core::map<std::string, std::string>::Node *n;
n = m_settings.find(name);
if(n == NULL)
@ -446,7 +469,7 @@ public:
{
return is_yes(get(name));
}
bool getFlag(std::string name)
{
try
@ -465,7 +488,7 @@ public:
// If it is in settings
if(exists(name))
return getBool(name);
std::string s;
char templine[10];
std::cout<<question<<" [y/N]: ";
@ -493,7 +516,7 @@ public:
// If it is in settings
if(exists(name))
return getU16(name);
std::string s;
char templine[10];
std::cout<<question<<" ["<<def<<"]: ";
@ -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;
@ -588,7 +879,7 @@ public:
void clear()
{
JMutexAutoLock lock(m_mutex);
m_settings.clear();
m_defaults.clear();
}
@ -596,7 +887,7 @@ public:
void updateValue(Settings &other, const std::string &name)
{
JMutexAutoLock lock(m_mutex);
if(&other == this)
return;
@ -613,7 +904,7 @@ public:
{
JMutexAutoLock lock(m_mutex);
JMutexAutoLock lock2(other.m_mutex);
if(&other == this)
return;
@ -623,7 +914,7 @@ public:
{
m_settings[i.getNode()->getKey()] = i.getNode()->getValue();
}
for(core::map<std::string, std::string>::Iterator
i = other.m_defaults.getIterator();
i.atEnd() == false; i++)
@ -638,7 +929,7 @@ public:
{
JMutexAutoLock lock(m_mutex);
JMutexAutoLock lock2(other.m_mutex);
if(&other == this)
return *this;
@ -649,7 +940,7 @@ public:
m_settings.insert(i.getNode()->getKey(),
i.getNode()->getValue());
}
for(core::map<std::string, std::string>::Iterator
i = other.m_defaults.getIterator();
i.atEnd() == false; i++)
@ -666,13 +957,13 @@ public:
{
JMutexAutoLock lock(m_mutex);
JMutexAutoLock lock2(other.m_mutex);
if(&other == this)
return *this;
clear();
(*this) += other;
return *this;
}

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 &path_="",
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));
@ -376,17 +468,9 @@ void make_tree_leaves_placement(ManualMapVoxelManipulator &vmanip, v3f p0,
return;
u32 vi = vmanip.m_area.index(p1);
if(vmanip.m_data[vi].getContent() != CONTENT_AIR
&& vmanip.m_data[vi].getContent() != CONTENT_IGNORE)
&& 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;
vmanip.m_data[vmanip.m_area.index(p1)] = tree_definition.fruitnode;
}
irr::core::matrix4 setRotationAxisRadians(irr::core::matrix4 M, double angle, v3f axis)
@ -517,4 +601,4 @@ static void make_jungletree(VoxelManipulator &vmanip, v3s16 p0,
}
#endif
}; // namespace treegen
}; // namespace treegen

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,34 +38,42 @@ 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
void make_tree(ManualMapVoxelManipulator &vmanip, v3s16 p0,
bool is_apple_tree, INodeDefManager *ndef);
bool is_apple_tree, INodeDefManager *ndef);
// Add L-Systems tree (used by engine)
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 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);
void make_tree_leaves_placement(ManualMapVoxelManipulator &vmanip, v3f p0,
TreeDef &tree_definition);
irr::core::matrix4 setRotationAxisRadians(irr::core::matrix4 M, double angle,v3f axis);
v3f transposeMatrix(irr::core::matrix4 M ,v3f v);
}; // namespace treegen
#endif

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

@ -72,7 +72,7 @@ public:
MaxEdge(p)
{
}
/*
Modifying methods
*/
@ -106,14 +106,14 @@ public:
if(p.Y > MaxEdge.Y) MaxEdge.Y = p.Y;
if(p.Z > MaxEdge.Z) MaxEdge.Z = p.Z;
}
// Pad with d nodes
void pad(v3s16 d)
{
MinEdge -= d;
MaxEdge += d;
}
/*void operator+=(v3s16 off)
{
MinEdge += off;
@ -202,7 +202,7 @@ public:
}
assert(contains(a));
// Take back area, XY inclusive
{
v3s16 min(MinEdge.X, MinEdge.Y, a.MaxEdge.Z+1);
@ -258,7 +258,7 @@ public:
}
}
/*
Translates position from virtual coordinates to array index
*/
@ -274,7 +274,7 @@ public:
{
return index(p.X, p.Y, p.Z);
}
// Translate index in the X coordinate
void add_x(const v3s16 &extent, u32 &i, s16 a)
{
@ -343,7 +343,7 @@ class VoxelManipulator /*: public NodeContainer*/
public:
VoxelManipulator();
virtual ~VoxelManipulator();
/*
Virtuals from NodeContainer
*/
@ -430,7 +430,7 @@ public:
void setNode(v3s16 p, const MapNode &n)
{
emerge(p);
m_data[m_area.index(p)] = n;
m_flags[m_area.index(p)] &= ~VOXELFLAG_INEXISTENT;
m_flags[m_area.index(p)] &= ~VOXELFLAG_NOT_LOADED;
@ -457,10 +457,10 @@ public:
//dstream<<"operator[] p=("<<p.X<<","<<p.Y<<","<<p.Z<<")"<<std::endl;
if(isValidPosition(p) == false)
emerge(VoxelArea(p));
return m_data[m_area.index(p)];
}*/
/*
Set stuff if available without an emerge.
Return false if failed.
@ -496,7 +496,7 @@ public:
void print(std::ostream &o, INodeDefManager *nodemgr,
VoxelPrintMode mode=VOXELPRINT_MATERIAL);
void addArea(VoxelArea area);
/*
@ -505,7 +505,7 @@ public:
*/
void copyFrom(MapNode *src, VoxelArea src_area,
v3s16 from_pos, v3s16 to_pos, v3s16 size);
// Copy data
void copyTo(MapNode *dst, VoxelArea dst_area,
v3s16 dst_pos, v3s16 from_pos, v3s16 size);
@ -523,15 +523,15 @@ public:
void unspreadLight(enum LightBank bank,
core::map<v3s16, u8> & from_nodes,
core::map<v3s16, bool> & light_sources, INodeDefManager *nodemgr);
void spreadLight(enum LightBank bank, v3s16 p, INodeDefManager *nodemgr);
void spreadLight(enum LightBank bank,
core::map<v3s16, bool> & from_nodes, INodeDefManager *nodemgr);
/*
Virtual functions
*/
/*
Get the contents of the requested area from somewhere.
Shall touch only nodes that have VOXELFLAG_NOT_LOADED
@ -565,7 +565,7 @@ public:
MaxEdge is 1 higher than maximum allowed position
*/
VoxelArea m_area;
/*
NULL if data size is 0 (extent (0,0,0))
Data is stored as [z*h*w + y*h + x]
@ -576,7 +576,7 @@ public:
Flags of all nodes
*/
u8 *m_flags;
//TODO: Use these or remove them
//TODO: Would these make any speed improvement?
//bool m_pressure_route_valid;

View File

@ -86,10 +86,10 @@ SunlightPropagateResult propagateSunlight(VoxelManipulator &v, VoxelArea a,
required_a.pad(v3s16(0,1,0));
// Make sure we have access to it
v.emerge(a);
s16 max_y = a.MaxEdge.Y;
s16 min_y = a.MinEdge.Y;
for(s32 x=a.MinEdge.X; x<=a.MaxEdge.X; x++)
for(s32 z=a.MinEdge.Z; z<=a.MaxEdge.Z; z++)
{
@ -125,11 +125,11 @@ SunlightPropagateResult propagateSunlight(VoxelManipulator &v, VoxelArea a,
if(incoming_light > old_light)
n.setLight(LIGHTBANK_DAY, incoming_light, ndef);
if(diminish_light(incoming_light) != 0)
light_sources.insert(p, true);
}
// Check validity of sunlight at top of block below if it
// hasn't already been proven invalid
if(bottom_sunlight_valid)

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 \