1
0
mirror of https://github.com/moparisthebest/minetest synced 2024-08-13 16:53:49 -04:00

Merge remote branch 'origin/master'

This commit is contained in:
Weblate 2013-04-22 22:37:16 +02:00
commit 418c2e7a44
16 changed files with 1351 additions and 411 deletions

View File

@ -407,6 +407,8 @@ The position field is used for all element types.
To account for differing resolutions, the position coordinates are the percentage of the screen, To account for differing resolutions, the position coordinates are the percentage of the screen,
ranging in value from 0 to 1. ranging in value from 0 to 1.
The name field is not yet used, but should contain a description of what the HUD element represents. The name field is not yet used, but should contain a description of what the HUD element represents.
The direction field is the direction in which something is drawn.
0 draws from left to right, 1 draws from right to left, 2 draws from top to bottom, and 3 draws from bottom to top.
Below are the specific uses for fields in each type; fields not listed for that type are ignored. Below are the specific uses for fields in each type; fields not listed for that type are ignored.
Note: Future revisions to the HUD API may be incompatible; the HUD API is still in the experimental stages. Note: Future revisions to the HUD API may be incompatible; the HUD API is still in the experimental stages.
@ -428,15 +430,12 @@ Note: Future revisions to the HUD API may be incompatible; the HUD API is still
- text: The name of the texture that is used. - text: The name of the texture that is used.
- number: The number of half-textures that are displayed. - number: The number of half-textures that are displayed.
If odd, will end with a vertically center-split texture. If odd, will end with a vertically center-split texture.
- direction
- inventory - inventory
- text: The name of the inventory list to be displayed. - text: The name of the inventory list to be displayed.
- number: Number of items in the inventory to be displayed. - number: Number of items in the inventory to be displayed.
- item: Position of item that is selected. - item: Position of item that is selected.
- direction: Direction in which the inventory list is drawn. - direction
0 draws from left to right,
1 draws from right to left,
2 draws from top to bottom, and
3 draws from bottom to top.
Representations of simple things Representations of simple things
-------------------------------- --------------------------------
@ -1846,7 +1845,7 @@ Detached inventory callbacks
HUD Definition (hud_add, hud_get) HUD Definition (hud_add, hud_get)
{ {
type = "image", hud_elem_type = "image", -- see HUD element types
^ type of HUD element, can be either of "image", "text", "statbar", or "inventory" ^ type of HUD element, can be either of "image", "text", "statbar", or "inventory"
position = {x=0.5, y=0.5}, position = {x=0.5, y=0.5},
^ Left corner position of element ^ Left corner position of element
@ -1856,6 +1855,6 @@ HUD Definition (hud_add, hud_get)
number = 2, number = 2,
item = 3, item = 3,
^ Selected item in inventory. 0 for no item selected. ^ Selected item in inventory. 0 for no item selected.
dir = 0, direction = 0,
^ Direction: 0: left-right, 1: right-left, 2: top-bottom, 3: bottom-top ^ Direction: 0: left-right, 1: right-left, 2: top-bottom, 3: bottom-top
} }

776
po/pt_BR/minetest.po Normal file
View File

@ -0,0 +1,776 @@
# 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.
#
msgid ""
msgstr ""
"Project-Id-Version: minetest\n"
"Report-Msgid-Bugs-To: \n"
"POT-Creation-Date: 2013-03-30 19:56+0100\n"
"PO-Revision-Date: 2013-04-22 17:06-0300\n"
"Last-Translator: Eduardo Junio <contato@ejweb.com.br>\n"
"Language-Team: LANGUAGE <contato@ejweb.com.br>\n"
"Language: pt_BR\n"
"MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=UTF-8\n"
"Content-Transfer-Encoding: 8bit\n"
"Plural-Forms: nplurals=2; plural=(n != 1);\n"
"X-Generator: Poedit 1.5.5\n"
#: src/guiConfigureWorld.cpp:125
msgid ""
"Warning: Some mods are not configured yet.\n"
"They will be enabled by default when you save the configuration. "
msgstr ""
"Alerta: Alguns mods ainda não estão configurados.\n"
"Eles vão ser ativos por predefinição quando salvar a configuração. "
#: src/guiConfigureWorld.cpp:144
msgid ""
"Warning: Some configured mods are missing.\n"
"Their setting will be removed when you save the configuration. "
msgstr ""
"Alerta: Alguns mods configurados estão em falta.\n"
"As definições vão ser removidas quando salvar a configuração. "
#: src/guiConfigureWorld.cpp:208
msgid "enabled"
msgstr "ativo"
#: src/guiConfigureWorld.cpp:215
msgid "Enable All"
msgstr "Ativar Tudo"
#: src/guiConfigureWorld.cpp:222
msgid "Disable All"
msgstr "Desativar Tudo"
#: src/guiConfigureWorld.cpp:228
msgid "depends on:"
msgstr "depende de:"
#: src/guiConfigureWorld.cpp:240
msgid "is required by:"
msgstr "é necessário pelo:"
#: src/guiConfigureWorld.cpp:262 src/guiCreateWorld.cpp:165
#: src/guiKeyChangeMenu.cpp:179 src/keycode.cpp:223
msgid "Cancel"
msgstr "Cancelar"
#: src/guiConfigureWorld.cpp:268 src/guiKeyChangeMenu.cpp:173
msgid "Save"
msgstr "Salvar"
#: src/guiConfigureWorld.cpp:394
msgid "Configuration saved. "
msgstr "Configuração salva. "
#: src/guiConfigureWorld.cpp:402
msgid "Warning: Configuration not consistent. "
msgstr "Alerta: Configuração não compativel. "
#: src/guiConfirmMenu.cpp:120
msgid "Yes"
msgstr "Sim"
#: src/guiConfirmMenu.cpp:126
msgid "No"
msgstr "Não"
#: src/guiCreateWorld.cpp:116
msgid "World name"
msgstr "Nome do mundo"
#: src/guiCreateWorld.cpp:135
msgid "Game"
msgstr "Jogo"
#: src/guiCreateWorld.cpp:159
msgid "Create"
msgstr "Criar"
#: src/guiDeathScreen.cpp:96
msgid "You died."
msgstr "Você morreu."
#: src/guiDeathScreen.cpp:104
msgid "Respawn"
msgstr "Renascer"
#: src/guiFormSpecMenu.cpp:582
msgid "Left click: Move all items, Right click: Move single item"
msgstr "Botão esq.: Mover todos os items, Botão dir.: Mover um item"
#: src/guiFormSpecMenu.cpp:607 src/guiMessageMenu.cpp:109
#: src/guiTextInputMenu.cpp:131
msgid "Proceed"
msgstr "Continuar"
#: src/guiKeyChangeMenu.cpp:114
msgid "Keybindings. (If this menu screws up, remove stuff from minetest.conf)"
msgstr "Teclas. (Se este menu estragar-se, remova as linhas do minetest.conf)"
#: src/guiKeyChangeMenu.cpp:151
msgid "\"Use\" = climb down"
msgstr "\"Use\" = ir para baixo"
#: src/guiKeyChangeMenu.cpp:164
msgid "Double tap \"jump\" to toggle fly"
msgstr "\"saltar\" duas vezes para voar"
#: src/guiKeyChangeMenu.cpp:269
msgid "Key already in use"
msgstr "Tecla já em uso"
#: src/guiKeyChangeMenu.cpp:347
msgid "press key"
msgstr "pressione uma tecla"
#: src/guiKeyChangeMenu.cpp:372
msgid "Forward"
msgstr "Avançar"
#: src/guiKeyChangeMenu.cpp:373
msgid "Backward"
msgstr "Voltar"
#: src/guiKeyChangeMenu.cpp:374 src/keycode.cpp:228
msgid "Left"
msgstr "Esquerda"
#: src/guiKeyChangeMenu.cpp:375 src/keycode.cpp:228
msgid "Right"
msgstr "Direita"
#: src/guiKeyChangeMenu.cpp:376
msgid "Use"
msgstr "Usar"
#: src/guiKeyChangeMenu.cpp:377
msgid "Jump"
msgstr "Saltar"
#: src/guiKeyChangeMenu.cpp:378
msgid "Sneak"
msgstr "Agachar"
#: src/guiKeyChangeMenu.cpp:379
msgid "Drop"
msgstr "Dropar"
#: src/guiKeyChangeMenu.cpp:380
msgid "Inventory"
msgstr "Inventário"
#: src/guiKeyChangeMenu.cpp:381
msgid "Chat"
msgstr "Chat"
#: src/guiKeyChangeMenu.cpp:382
msgid "Command"
msgstr "Comando"
#: src/guiKeyChangeMenu.cpp:383
msgid "Console"
msgstr "Console"
#: src/guiKeyChangeMenu.cpp:384
msgid "Toggle fly"
msgstr "Ativar vôo"
#: src/guiKeyChangeMenu.cpp:385
msgid "Toggle fast"
msgstr "Ativar correr"
#: src/guiKeyChangeMenu.cpp:386
msgid "Toggle noclip"
msgstr "Ativar noclip"
#: src/guiKeyChangeMenu.cpp:387
msgid "Range select"
msgstr "Selecionar Distância"
#: src/guiKeyChangeMenu.cpp:388
msgid "Print stacks"
msgstr "Imprimir stacks"
#: src/guiMainMenu.cpp:92
msgid "Cannot create world: Name contains invalid characters"
msgstr "Não foi possível criar o mundo: Nome com caracteres inválidos"
#: src/guiMainMenu.cpp:101
msgid "Cannot create world: A world by this name already exists"
msgstr "Não foi possivel criar o mundo: Esse nome já existe"
#: src/guiMainMenu.cpp:283
msgid "Singleplayer"
msgstr "Um Jogador"
#: src/guiMainMenu.cpp:284
msgid "Multiplayer"
msgstr "Multijogador"
#: src/guiMainMenu.cpp:285
msgid "Advanced"
msgstr "Avançado"
#: src/guiMainMenu.cpp:286
msgid "Settings"
msgstr "Configurações"
#: src/guiMainMenu.cpp:287
msgid "Credits"
msgstr "Créditos"
#: src/guiMainMenu.cpp:317
msgid "Select World:"
msgstr "Selecionar Mundo:"
#: src/guiMainMenu.cpp:339 src/guiMainMenu.cpp:511 src/keycode.cpp:229
msgid "Delete"
msgstr "Excluir"
#: src/guiMainMenu.cpp:346
msgid "New"
msgstr "Novo"
#: src/guiMainMenu.cpp:354
msgid "Configure"
msgstr "Configurar"
#: src/guiMainMenu.cpp:369 src/keycode.cpp:248
msgid "Play"
msgstr "Jogar"
#: src/guiMainMenu.cpp:380 src/guiMainMenu.cpp:619
msgid "Creative Mode"
msgstr "Modo Criativo"
#: src/guiMainMenu.cpp:386 src/guiMainMenu.cpp:625
msgid "Enable Damage"
msgstr "Ativar Dano"
#: src/guiMainMenu.cpp:406 src/guiMainMenu.cpp:541
msgid "Name/Password"
msgstr "Nome/Senha"
#: src/guiMainMenu.cpp:442 src/guiMainMenu.cpp:459 src/guiMainMenu.cpp:1184
msgid "Favorites:"
msgstr "Favoritos:"
#: src/guiMainMenu.cpp:450 src/guiMainMenu.cpp:1194
msgid "Public Server List:"
msgstr "Lista de servidor públicos:"
#: src/guiMainMenu.cpp:470 src/guiMainMenu.cpp:568
msgid "Address/Port"
msgstr "Endereço/Porta"
#: src/guiMainMenu.cpp:497 src/guiMainMenu.cpp:1183
msgid "Show Public"
msgstr "Mostrar Públicos"
#: src/guiMainMenu.cpp:501 src/guiMainMenu.cpp:1193
msgid "Show Favorites"
msgstr "Mostrar Favoritos"
#: src/guiMainMenu.cpp:521
msgid "Connect"
msgstr "Conectar"
#: src/guiMainMenu.cpp:591
msgid "Leave address blank to start a local server."
msgstr "Deixe o endereço em branco para iniciar o servidor local."
#: src/guiMainMenu.cpp:600
msgid "Start Game / Connect"
msgstr "Iniciar Jogo / Conectar"
#: src/guiMainMenu.cpp:632
msgid "Public"
msgstr "Público"
#: src/guiMainMenu.cpp:640 src/guiMainMenu.cpp:1113
msgid "Delete world"
msgstr "Eliminar mundo"
#: src/guiMainMenu.cpp:647
msgid "Create world"
msgstr "Criar mundo"
#: src/guiMainMenu.cpp:681
msgid "Fancy trees"
msgstr "Árvores Melhoradas"
#: src/guiMainMenu.cpp:687
msgid "Smooth Lighting"
msgstr "Iluminação Suave"
#: src/guiMainMenu.cpp:693
msgid "3D Clouds"
msgstr "Nuvens 3D"
#: src/guiMainMenu.cpp:699
msgid "Opaque water"
msgstr "Água Opaca"
#: src/guiMainMenu.cpp:709
msgid "Mip-Mapping"
msgstr "Mip-Mapping"
#: src/guiMainMenu.cpp:716
msgid "Anisotropic Filtering"
msgstr "Filtro Anisotropico"
#: src/guiMainMenu.cpp:723
msgid "Bi-Linear Filtering"
msgstr "Filtro Bi-Linear"
#: src/guiMainMenu.cpp:730
msgid "Tri-Linear Filtering"
msgstr "Filtro Tri-Linear"
#: src/guiMainMenu.cpp:738
msgid "Shaders"
msgstr "Sombras"
#: src/guiMainMenu.cpp:745
msgid "Preload item visuals"
msgstr "Precarregamento dos items"
#: src/guiMainMenu.cpp:752
msgid "Enable Particles"
msgstr "Ativar Particulas"
#: src/guiMainMenu.cpp:759
msgid "Finite liquid"
msgstr "Líquido finito"
#: src/guiMainMenu.cpp:769
msgid "Change keys"
msgstr "Mudar teclas"
#: src/guiMainMenu.cpp:1084
msgid "Address required."
msgstr "Endereço necessário."
#: src/guiMainMenu.cpp:1102
msgid "Cannot delete world: Nothing selected"
msgstr "Não foi possível eliminar mundo: Nada seleccionado"
#: src/guiMainMenu.cpp:1117
msgid "Files to be deleted"
msgstr "Arquivos para excluir"
#: src/guiMainMenu.cpp:1133
msgid "Cannot create world: No games found"
msgstr "Não foi possivel criar mundo: Jogos não detectados"
#: src/guiMainMenu.cpp:1149
msgid "Cannot configure world: Nothing selected"
msgstr "Não foi possivel configurar mundo: Nada selecionado"
#: src/guiMainMenu.cpp:1256
msgid "Failed to delete all world files"
msgstr "Erro ao remover arquivos do mundo"
#: src/guiPasswordChange.cpp:108
msgid "Old Password"
msgstr "Senha antiga"
#: src/guiPasswordChange.cpp:125
msgid "New Password"
msgstr "Senha Nova"
#: src/guiPasswordChange.cpp:141
msgid "Confirm Password"
msgstr "Confirmar Senha"
#: src/guiPasswordChange.cpp:158
msgid "Change"
msgstr "Mudar"
#: src/guiPasswordChange.cpp:167
msgid "Passwords do not match!"
msgstr "Senhas não correspondem!"
#: src/guiPauseMenu.cpp:123
msgid "Continue"
msgstr "Continuar"
#: src/guiPauseMenu.cpp:132
msgid "Change Password"
msgstr "Mudar Senha"
#: src/guiPauseMenu.cpp:140
msgid "Sound Volume"
msgstr "Volume do som"
#: src/guiPauseMenu.cpp:147
msgid "Exit to Menu"
msgstr "Voltar para o Menu"
#: src/guiPauseMenu.cpp:154
msgid "Exit to OS"
msgstr "Sair do Jogo"
#: src/guiPauseMenu.cpp:161
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 ""
"Controles Normais:\n"
"- WASD: Andar\n"
"- Botão esq.: partir/atacar\n"
"- Botão dir.: colocar/usar\n"
"- Scroll do Mouse: seleccionar item\n"
"- 0...9: seleccionar item\n"
"- Shift: agachar\n"
"- R: Mudar visualização de todos os chunks\n"
"- I: Inventário\n"
"- ESC: Este menu\n"
"- T: Chat\n"
#: src/guiVolumeChange.cpp:108
msgid "Sound Volume: "
msgstr "Volume do som: "
#: src/guiVolumeChange.cpp:121
msgid "Exit"
msgstr "Sair"
#: src/keycode.cpp:223
msgid "Left Button"
msgstr "Botão Esquerdo"
#: src/keycode.cpp:223
msgid "Middle Button"
msgstr "Scroll do Mouse"
#: src/keycode.cpp:223
msgid "Right Button"
msgstr "Botão Direito"
#: src/keycode.cpp:223
msgid "X Button 1"
msgstr "Botão X 1"
#: src/keycode.cpp:224
msgid "Back"
msgstr "Voltar"
#: src/keycode.cpp:224
msgid "Clear"
msgstr "Limpar"
#: src/keycode.cpp:224
msgid "Return"
msgstr "Voltar"
#: src/keycode.cpp:224
msgid "Tab"
msgstr "Tabulação"
#: src/keycode.cpp:224
msgid "X Button 2"
msgstr "Botão X 2"
#: src/keycode.cpp:225
msgid "Capital"
msgstr "Capital"
#: src/keycode.cpp:225
msgid "Control"
msgstr "Controle"
#: src/keycode.cpp:225
msgid "Kana"
msgstr "Kana"
#: src/keycode.cpp:225
msgid "Menu"
msgstr "Menu"
#: src/keycode.cpp:225
msgid "Pause"
msgstr "Pausa"
#: src/keycode.cpp:225
msgid "Shift"
msgstr "Shift"
#: src/keycode.cpp:226
msgid "Convert"
msgstr "Converter"
#: src/keycode.cpp:226
msgid "Escape"
msgstr "ESC"
#: src/keycode.cpp:226
msgid "Final"
msgstr "Final"
#: src/keycode.cpp:226
msgid "Junja"
msgstr "Junja"
#: src/keycode.cpp:226
msgid "Kanji"
msgstr "Kanji"
#: src/keycode.cpp:226
msgid "Nonconvert"
msgstr "Nãoconverter"
#: src/keycode.cpp:227
msgid "Accept"
msgstr "Aceitar"
#: src/keycode.cpp:227
msgid "End"
msgstr "Fim"
#: src/keycode.cpp:227
msgid "Home"
msgstr "Início"
#: src/keycode.cpp:227
msgid "Mode Change"
msgstr "Alterar o modo"
#: src/keycode.cpp:227
msgid "Next"
msgstr "Próximo"
#: src/keycode.cpp:227
msgid "Prior"
msgstr "Prévio"
#: src/keycode.cpp:227
msgid "Space"
msgstr "Espaço"
#: src/keycode.cpp:228
msgid "Down"
msgstr "Baixo"
#: src/keycode.cpp:228
msgid "Execute"
msgstr "Executar"
#: src/keycode.cpp:228
msgid "Print"
msgstr "Print"
#: src/keycode.cpp:228
msgid "Select"
msgstr "Selecionar"
#: src/keycode.cpp:228
msgid "Up"
msgstr "Cima"
#: src/keycode.cpp:229
msgid "Help"
msgstr "Ajuda"
#: src/keycode.cpp:229
msgid "Insert"
msgstr "Insert"
#: src/keycode.cpp:229
msgid "Snapshot"
msgstr "Screenshot"
#: src/keycode.cpp:232
msgid "Left Windows"
msgstr "Windows Esq."
#: src/keycode.cpp:233
msgid "Apps"
msgstr "Apps"
#: src/keycode.cpp:233
msgid "Numpad 0"
msgstr "Numpad 0"
#: src/keycode.cpp:233
msgid "Numpad 1"
msgstr "Numpad 1"
#: src/keycode.cpp:233
msgid "Right Windows"
msgstr "Windows Dir."
#: src/keycode.cpp:233
msgid "Sleep"
msgstr "Suspender"
#: src/keycode.cpp:234
msgid "Numpad 2"
msgstr "Numpad 2"
#: src/keycode.cpp:234
msgid "Numpad 3"
msgstr "Numpad 3"
#: src/keycode.cpp:234
msgid "Numpad 4"
msgstr "Numpad 4"
#: src/keycode.cpp:234
msgid "Numpad 5"
msgstr "Numpad 5"
#: src/keycode.cpp:234
msgid "Numpad 6"
msgstr "Numpad 6"
#: src/keycode.cpp:234
msgid "Numpad 7"
msgstr "Numpad 7"
#: src/keycode.cpp:235
msgid "Numpad *"
msgstr "Numpad *"
#: src/keycode.cpp:235
msgid "Numpad +"
msgstr "Numpad +"
#: src/keycode.cpp:235
msgid "Numpad -"
msgstr "Numpad -"
#: src/keycode.cpp:235
msgid "Numpad /"
msgstr "Numpad /"
#: src/keycode.cpp:235
msgid "Numpad 8"
msgstr "Numpad 8"
#: src/keycode.cpp:235
msgid "Numpad 9"
msgstr "Numpad 9"
#: src/keycode.cpp:239
msgid "Num Lock"
msgstr "Num Lock"
#: src/keycode.cpp:239
msgid "Scroll Lock"
msgstr "Scroll Lock"
#: src/keycode.cpp:240
msgid "Left Shift"
msgstr "Shift Esquerdo"
#: src/keycode.cpp:240
msgid "Right Shift"
msgstr "Shift Direito"
#: src/keycode.cpp:241
msgid "Left Control"
msgstr "Controle Esquerdo"
#: src/keycode.cpp:241
msgid "Left Menu"
msgstr "Menu Esquerdo"
#: src/keycode.cpp:241
msgid "Right Control"
msgstr "Controle Direito"
#: src/keycode.cpp:241
msgid "Right Menu"
msgstr "Menu Direito"
#: src/keycode.cpp:243
msgid "Comma"
msgstr "Vírgula"
#: src/keycode.cpp:243
msgid "Minus"
msgstr "Menos"
#: src/keycode.cpp:243
msgid "Period"
msgstr "Período"
#: src/keycode.cpp:243
msgid "Plus"
msgstr "Mais"
#: src/keycode.cpp:247
msgid "Attn"
msgstr "Attn"
#: src/keycode.cpp:247
msgid "CrSel"
msgstr "CrSel"
#: src/keycode.cpp:248
msgid "Erase OEF"
msgstr "Apagar OEF"
#: src/keycode.cpp:248
msgid "ExSel"
msgstr "ExSel"
#: src/keycode.cpp:248
msgid "OEM Clear"
msgstr "Limpar OEM"
#: src/keycode.cpp:248
msgid "PA1"
msgstr "PAL"
#: src/keycode.cpp:248
msgid "Zoom"
msgstr "Zoom"
#: src/main.cpp:1506
msgid "Main Menu"
msgstr "Menu Principal"
#: src/main.cpp:1830
msgid "Failed to initialize world"
msgstr "Falha ao iniciar mundo"
#: src/main.cpp:1842
msgid "No world selected and no address provided. Nothing to do."
msgstr ""
"Nenhum mundo selecionado e nenhum endereço providenciado. Nada para fazer."
#: src/main.cpp:1850
msgid "Could not find or load game \""
msgstr "Não foi possível encontrar ou carregar jogo \""
#: src/main.cpp:1864
msgid "Invalid gamespec."
msgstr "gamespec inválido."
#: src/main.cpp:1904
msgid "Connection error (timed out?)"
msgstr "Erro de conexão (excedeu o tempo?)"
#: src/main.cpp:1915
msgid ""
"\n"
"Check debug.txt for details."
msgstr ""
"\n"
"Verifique debug.txt para mais detalhes."

View File

@ -248,6 +248,7 @@ set(common_SRCS
mapgen_singlenode.cpp mapgen_singlenode.cpp
treegen.cpp treegen.cpp
dungeongen.cpp dungeongen.cpp
cavegen.cpp
content_nodemeta.cpp content_nodemeta.cpp
content_mapnode.cpp content_mapnode.cpp
collision.cpp collision.cpp

266
src/cavegen.cpp Normal file
View File

@ -0,0 +1,266 @@
/*
Minetest
Copyright (C) 2010-2013 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 "util/numeric.h"
#include "map.h"
#include "mapgen.h"
#include "cavegen.h"
CaveV6::CaveV6(Mapgen *mg, PseudoRandom *ps, PseudoRandom *ps2,
bool is_large_cave, content_t c_water, content_t c_lava) {
this->vm = mg->vm;
this->water_level = mg->water_level;
this->large_cave = is_large_cave;
this->ps = ps;
this->ps2 = ps2;
this->c_water_source = c_water;
this->c_lava_source = c_lava;
min_tunnel_diameter = 2;
max_tunnel_diameter = ps->range(2, 6);
dswitchint = ps->range(1, 14);
flooded = true;
if (large_cave) {
part_max_length_rs = ps->range(2,4);
tunnel_routepoints = ps->range(5, ps->range(15,30));
min_tunnel_diameter = 5;
max_tunnel_diameter = ps->range(7, ps->range(8,24));
} else {
part_max_length_rs = ps->range(2,9);
tunnel_routepoints = ps->range(10, ps->range(15,30));
}
large_cave_is_flat = (ps->range(0,1) == 0);
}
void CaveV6::makeCave(v3s16 nmin, v3s16 nmax, int max_stone_height) {
node_min = nmin;
node_max = nmax;
max_stone_y = max_stone_height;
main_direction = v3f(0, 0, 0);
// Allowed route area size in nodes
ar = node_max - node_min + v3s16(1, 1, 1);
// Area starting point in nodes
of = node_min;
// Allow a bit more
//(this should be more than the maximum radius of the tunnel)
const s16 max_spread_amount = MAP_BLOCKSIZE;
s16 insure = 10;
s16 more = max_spread_amount - max_tunnel_diameter / 2 - insure;
ar += v3s16(1,0,1) * more * 2;
of -= v3s16(1,0,1) * more;
route_y_min = 0;
// Allow half a diameter + 7 over stone surface
route_y_max = -of.Y + max_stone_y + max_tunnel_diameter / 2 + 7;
// Limit maximum to area
route_y_max = rangelim(route_y_max, 0, ar.Y - 1);
if (large_cave) {
s16 min = 0;
if (node_min.Y < water_level && node_max.Y > water_level) {
min = water_level - max_tunnel_diameter/3 - of.Y;
route_y_max = water_level + max_tunnel_diameter/3 - of.Y;
}
route_y_min = ps->range(min, min + max_tunnel_diameter);
route_y_min = rangelim(route_y_min, 0, route_y_max);
}
s16 route_start_y_min = route_y_min;
s16 route_start_y_max = route_y_max;
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);
// Randomize starting position
orp = v3f(
(float)(ps->next() % ar.X) + 0.5,
(float)(ps->range(route_start_y_min, route_start_y_max)) + 0.5,
(float)(ps->next() % ar.Z) + 0.5
);
// Generate some tunnel starting from orp
for (u16 j = 0; j < tunnel_routepoints; j++)
makeTunnel(j % dswitchint == 0);
}
void CaveV6::makeTunnel(bool dirswitch) {
if (dirswitch && !large_cave) {
main_direction = v3f(
((float)(ps->next() % 20) - (float)10) / 10,
((float)(ps->next() % 20) - (float)10) / 30,
((float)(ps->next() % 20) - (float)10) / 10
);
main_direction *= (float)ps->range(0, 10) / 10;
}
// Randomize size
s16 min_d = min_tunnel_diameter;
s16 max_d = max_tunnel_diameter;
rs = ps->range(min_d, max_d);
v3s16 maxlen;
if (large_cave) {
maxlen = v3s16(
rs * part_max_length_rs,
rs * part_max_length_rs / 2,
rs * part_max_length_rs
);
} else {
maxlen = v3s16(
rs * part_max_length_rs,
ps->range(1, rs * part_max_length_rs),
rs * part_max_length_rs
);
}
v3f vec(
(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) {
vec = v3f(
(float)(ps->next() % (maxlen.X * 1)) - (float)maxlen.X / 2,
(float)(ps->next() % (maxlen.Y * 2)) - (float)maxlen.Y,
(float)(ps->next() % (maxlen.Z * 1)) - (float)maxlen.Z / 2
);
}
/*if(large_cave){
v3f p = orp + vec;
s16 h = find_ground_level_clever(vmanip, v2s16(p.X, p.Z), ndef);
route_y_min = h - rs/3;
route_y_max = h + rs;
}*/
vec += main_direction;
v3f rp = orp + vec;
if (rp.X < 0)
rp.X = 0;
else if (rp.X >= ar.X)
rp.X = ar.X - 1;
if (rp.Y < route_y_min)
rp.Y = route_y_min;
else if (rp.Y >= route_y_max)
rp.Y = route_y_max - 1;
if (rp.Z < 0)
rp.Z = 0;
else if (rp.Z >= ar.Z)
rp.Z = ar.Z - 1;
vec = rp - orp;
float veclen = vec.getLength();
// As odd as it sounds, veclen is *exactly* 0.0 sometimes, causing a FPE
if (veclen == 0.0)
veclen = 1.0;
// Every second section is rough
bool randomize_xz = (ps2->range(1, 2) == 1);
// Carve routes
for (float f = 0; f < 1.0; f += 1.0 / veclen)
carveRoute(vec, f, randomize_xz);
orp = rp;
}
void CaveV6::carveRoute(v3f vec, float f, bool randomize_xz) {
MapNode airnode(CONTENT_AIR);
MapNode waternode(c_water_source);
MapNode lavanode(c_lava_source);
v3s16 startp(orp.X, orp.Y, orp.Z);
startp += of;
v3f fp = orp + vec * f;
fp.X += 0.1 * ps->range(-10, 10);
fp.Z += 0.1 * ps->range(-10, 10);
v3s16 cp(fp.X, fp.Y, fp.Z);
s16 d0 = -rs/2;
s16 d1 = d0 + rs;
if (randomize_xz) {
d0 += ps->range(-1, 1);
d1 += ps->range(-1, 1);
}
for (s16 z0 = d0; z0 <= d1; z0++) {
s16 si = rs / 2 - MYMAX(0, abs(z0) - rs / 7 - 1);
for (s16 x0 = -si - ps->range(0,1); x0 <= si - 1 + ps->range(0,1); x0++) {
s16 maxabsxz = MYMAX(abs(x0), abs(z0));
s16 si2 = rs / 2 - MYMAX(0, maxabsxz - rs / 7 - 1);
for (s16 y0 = -si2; y0 <= si2; y0++) {
// Make better floors in small caves
//if(y0 <= -rs/2 && rs<=7)
// continue;
if (large_cave_is_flat) {
// Make large caves not so tall
if (rs > 7 && abs(y0) >= rs / 3)
continue;
}
v3s16 p(cp.X + x0, cp.Y + y0, cp.Z + z0);
p += of;
if (vm->m_area.contains(p) == false)
continue;
u32 i = vm->m_area.index(p);
if (large_cave) {
int full_ymin = node_min.Y - MAP_BLOCKSIZE;
int full_ymax = node_max.Y + MAP_BLOCKSIZE;
if (flooded && full_ymin < water_level && full_ymax > water_level) {
vm->m_data[i] = (p.Y <= water_level) ? waternode : airnode;
} else if (flooded && full_ymax < water_level) {
vm->m_data[i] = (p.Y < startp.Y - 2) ? lavanode : airnode;
} else {
vm->m_data[i] = airnode;
}
} else {
// Don't replace air or water or lava or ignore
content_t c = vm->m_data[i].getContent();
if (c == CONTENT_IGNORE || c == CONTENT_AIR ||
c == c_water_source || c == c_lava_source)
continue;
vm->m_data[i] = airnode;
vm->m_flags[i] |= VMANIP_FLAG_CAVE;
}
}
}
}
}

68
src/cavegen.h Normal file
View File

@ -0,0 +1,68 @@
/*
Minetest
Copyright (C) 2010-2013 kwolekr, Ryan Kwolek <kwolekr@minetest.net>
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 CAVEGEN_HEADER
#define CAVEGEN_HEADER
#define VMANIP_FLAG_CAVE VOXELFLAG_CHECKED1
class CaveV6 {
public:
ManualMapVoxelManipulator *vm;
s16 min_tunnel_diameter;
s16 max_tunnel_diameter;
u16 tunnel_routepoints;
int dswitchint;
int part_max_length_rs;
bool large_cave;
bool large_cave_is_flat;
bool flooded;
s16 max_stone_y;
v3s16 node_min;
v3s16 node_max;
v3f orp; //original point
v3s16 of;
v3s16 ar; // allowed route area
s16 rs; // radius size
v3f main_direction;
s16 route_y_min;
s16 route_y_max;
PseudoRandom *ps;
PseudoRandom *ps2;
content_t c_water_source;
content_t c_lava_source;
int water_level;
CaveV6() {}
CaveV6(Mapgen *mg, PseudoRandom *ps, PseudoRandom *ps2, bool large_cave,
content_t c_water, content_t c_lava);
void makeCave(v3s16 nmin, v3s16 nmax, int max_stone_height);
void makeTunnel(bool dirswitch);
void carveRoute(v3f vec, float f, bool randomize_xz);
};
#endif

View File

@ -50,7 +50,7 @@ with this program; if not, write to the Free Software Foundation, Inc.,
EmergeManager::EmergeManager(IGameDef *gamedef) { EmergeManager::EmergeManager(IGameDef *gamedef) {
//register built-in mapgens //register built-in mapgens
registerMapgen("v6", new MapgenFactoryV6()); registerMapgen("v6", new MapgenFactoryV6());
//registerMapgen("v7", new MapgenFactoryV7()); registerMapgen("v7", new MapgenFactoryV7());
registerMapgen("indev", new MapgenFactoryIndev()); registerMapgen("indev", new MapgenFactoryIndev());
registerMapgen("singlenode", new MapgenFactorySinglenode()); registerMapgen("singlenode", new MapgenFactorySinglenode());

View File

@ -198,7 +198,7 @@ void Hud::drawLuaElements() {
font->draw(narrow_to_wide(e->text).c_str(), size + pos, color); font->draw(narrow_to_wide(e->text).c_str(), size + pos, color);
break; } break; }
case HUD_ELEM_STATBAR: case HUD_ELEM_STATBAR:
drawStatbar(pos, e->text, e->number); drawStatbar(pos, HUD_CORNER_UPPER, e->dir, e->text, e->number);
break; break;
case HUD_ELEM_INVENTORY: { case HUD_ELEM_INVENTORY: {
InventoryList *inv = inventory->getList(e->text); InventoryList *inv = inventory->getList(e->text);
@ -212,38 +212,55 @@ void Hud::drawLuaElements() {
} }
void Hud::drawStatbar(v2s32 upperleftpos, std::string texture, s32 count) { void Hud::drawStatbar(v2s32 pos, u16 corner, u16 drawdir, std::string texture, s32 count) {
const video::SColor color(255, 255, 255, 255);
const video::SColor colors[] = {color, color, color, color};
video::ITexture *stat_texture = video::ITexture *stat_texture =
gamedef->getTextureSource()->getTextureRaw(texture); gamedef->getTextureSource()->getTextureRaw(texture);
if (!stat_texture) if (!stat_texture)
return; return;
v2s32 p = upperleftpos; core::dimension2di srcd(stat_texture->getOriginalSize());
v2s32 p = pos;
if (corner & HUD_CORNER_LOWER)
p -= srcd.Height;
v2s32 steppos;
switch (drawdir) {
case HUD_DIR_RIGHT_LEFT:
steppos = v2s32(-1, 0);
break;
case HUD_DIR_TOP_BOTTOM:
steppos = v2s32(0, 1);
break;
case HUD_DIR_BOTTOM_TOP:
steppos = v2s32(0, -1);
break;
default:
steppos = v2s32(1, 0);
}
steppos.X *= srcd.Width;
steppos.Y *= srcd.Height;
for (s32 i = 0; i < count / 2; i++) for (s32 i = 0; i < count / 2; i++)
{ {
core::dimension2di srcd(stat_texture->getOriginalSize()); core::rect<s32> srcrect(0, 0, srcd.Width, srcd.Height);
const video::SColor color(255, 255, 255, 255); core::rect<s32> dstrect(srcrect);
const video::SColor colors[] = {color, color, color, color};
core::rect<s32> rect(0, 0, srcd.Width, srcd.Height); dstrect += p;
rect += p; driver->draw2DImage(stat_texture, dstrect, srcrect, NULL, colors, true);
driver->draw2DImage(stat_texture, rect, p += steppos;
core::rect<s32>(core::position2d<s32>(0, 0), srcd),
NULL, colors, true);
p += v2s32(srcd.Width, 0);
} }
if (count % 2 == 1) if (count % 2 == 1)
{ {
core::dimension2di srcd(stat_texture->getOriginalSize()); core::rect<s32> srcrect(0, 0, srcd.Width / 2, srcd.Height);
const video::SColor color(255, 255, 255, 255); core::rect<s32> dstrect(srcrect);
const video::SColor colors[] = {color, color, color, color};
core::rect<s32> rect(0, 0, srcd.Width / 2, srcd.Height); dstrect += p;
rect += p; driver->draw2DImage(stat_texture, dstrect, srcrect, NULL, colors, true);
srcd.Width /= 2;
driver->draw2DImage(stat_texture, rect,
core::rect<s32>(core::position2d<s32>(0, 0), srcd),
NULL, colors, true);
p += v2s32(srcd.Width * 2, 0);
} }
} }
@ -260,7 +277,8 @@ void Hud::drawHotbar(v2s32 centerlowerpos, s32 halfheartcount, u16 playeritem) {
v2s32 pos = centerlowerpos - v2s32(width / 2, hotbar_imagesize + padding * 2); v2s32 pos = centerlowerpos - v2s32(width / 2, hotbar_imagesize + padding * 2);
drawItem(pos, hotbar_imagesize, hotbar_itemcount, mainlist, playeritem + 1, 0); drawItem(pos, hotbar_imagesize, hotbar_itemcount, mainlist, playeritem + 1, 0);
drawStatbar(pos + v2s32(0, -20), "heart.png", halfheartcount); drawStatbar(pos - v2s32(0, 4), HUD_CORNER_LOWER, HUD_DIR_LEFT_RIGHT,
"heart.png", halfheartcount);
} }

View File

@ -27,6 +27,10 @@ with this program; if not, write to the Free Software Foundation, Inc.,
#define HUD_DIR_TOP_BOTTOM 2 #define HUD_DIR_TOP_BOTTOM 2
#define HUD_DIR_BOTTOM_TOP 3 #define HUD_DIR_BOTTOM_TOP 3
#define HUD_CORNER_UPPER 0
#define HUD_CORNER_LOWER 1
#define HUD_CORNER_CENTER 2
class Player; class Player;
enum HudElementType { enum HudElementType {
@ -102,7 +106,7 @@ public:
void drawItem(v2s32 upperleftpos, s32 imgsize, s32 itemcount, void drawItem(v2s32 upperleftpos, s32 imgsize, s32 itemcount,
InventoryList *mainlist, u16 selectitem, u16 direction); InventoryList *mainlist, u16 selectitem, u16 direction);
void drawLuaElements(); void drawLuaElements();
void drawStatbar(v2s32 upperleftpos, std::string texture, s32 count); void drawStatbar(v2s32 pos, u16 corner, u16 drawdir, std::string texture, s32 count);
void drawHotbar(v2s32 centerlowerpos, s32 halfheartcount, u16 playeritem); void drawHotbar(v2s32 centerlowerpos, s32 halfheartcount, u16 playeritem);
void resizeHotbar(); void resizeHotbar();

View File

@ -21,6 +21,7 @@ with this program; if not, write to the Free Software Foundation, Inc.,
#include "constants.h" #include "constants.h"
#include "map.h" #include "map.h"
#include "main.h" #include "main.h"
#include "util/numeric.h"
#include "log.h" #include "log.h"
/////////////////// Mapgen Indev perlin noise (default values - not used, from config or defaultsettings) /////////////////// Mapgen Indev perlin noise (default values - not used, from config or defaultsettings)
@ -154,9 +155,6 @@ void MapgenIndev::calculateNoise() {
z + 0.5 * noiseindev_float_islands3->npindev->spread.Z * farscale(noiseindev_float_islands3->npindev->farspread, x, z)); z + 0.5 * noiseindev_float_islands3->npindev->spread.Z * farscale(noiseindev_float_islands3->npindev->farspread, x, z));
noiseindev_float_islands3->transformNoiseMapFarScale(x, y, z); noiseindev_float_islands3->transformNoiseMapFarScale(x, y, z);
}
if (!(flags & MG_FLAT)) {
noiseindev_mud->perlinMap2D( noiseindev_mud->perlinMap2D(
x + 0.5 * noiseindev_mud->npindev->spread.X * farscale(noiseindev_mud->npindev->farspread, x, y, z), x + 0.5 * noiseindev_mud->npindev->spread.X * farscale(noiseindev_mud->npindev->farspread, x, y, z),
z + 0.5 * noiseindev_mud->npindev->spread.Z * farscale(noiseindev_mud->npindev->farspread, x, y, z)); z + 0.5 * noiseindev_mud->npindev->spread.Z * farscale(noiseindev_mud->npindev->farspread, x, y, z));
@ -256,28 +254,66 @@ float MapgenIndev::getMudAmount(int index) {
return noiseindev_mud->result[index]; return noiseindev_mud->result[index];
} }
void MapgenIndev::defineCave(Cave & cave, PseudoRandom ps, v3s16 node_min, bool large_cave) { void MapgenIndev::generateCaves(int max_stone_y) {
cave.min_tunnel_diameter = 2; float cave_amount = NoisePerlin2D(np_cave, node_min.X, node_min.Y, seed);
cave.max_tunnel_diameter = ps.range(2,6); int volume_nodes = (node_max.X - node_min.X + 1) *
cave.dswitchint = ps.range(1,14); (node_max.Y - node_min.Y + 1) * MAP_BLOCKSIZE;
cave.flooded = large_cave && ps.range(0,4); cave_amount = MYMAX(0.0, cave_amount);
u32 caves_count = cave_amount * volume_nodes / 50000;
u32 bruises_count = 1;
PseudoRandom ps(blockseed + 21343);
PseudoRandom ps2(blockseed + 1032);
if (ps.range(1, 6) == 1)
bruises_count = ps.range(0, ps.range(0, 2));
if (getBiome(v2s16(node_min.X, node_min.Z)) == BT_DESERT) {
caves_count /= 3;
bruises_count /= 3;
}
for (u32 i = 0; i < caves_count + bruises_count; i++) {
bool large_cave = (i >= caves_count);
CaveIndev cave(this, &ps, &ps2, node_min, large_cave,
c_water_source, c_lava_source);
cave.makeCave(node_min, node_max, max_stone_y);
}
}
CaveIndev::CaveIndev(Mapgen *mg, PseudoRandom *ps, PseudoRandom *ps2,
v3s16 node_min, bool is_large_cave,
content_t c_water, content_t c_lava) {
this->vm = mg->vm;
this->water_level = mg->water_level;
this->large_cave = is_large_cave;
this->ps = ps;
this->ps2 = ps2;
this->c_water_source = c_water;
this->c_lava_source = c_lava;
min_tunnel_diameter = 2;
max_tunnel_diameter = ps->range(2,6);
dswitchint = ps->range(1,14);
flooded = large_cave && ps->range(0,4);
if (large_cave) { if (large_cave) {
cave.part_max_length_rs = ps.range(2,4); part_max_length_rs = ps->range(2,4);
if (node_min.Y < -100 && !ps.range(0, farscale(0.2, node_min.X,node_min.Y,node_min.Z)*30)) { //huge float scale = farscale(0.2, node_min.X, node_min.Y, node_min.Z);
cave.flooded = !ps.range(0, 3); if (node_min.Y < -100 && !ps->range(0, scale * 30)) { //huge
cave.tunnel_routepoints = ps.range(5, 30); flooded = !ps->range(0, 3);
cave.min_tunnel_diameter = 30; tunnel_routepoints = ps->range(5, 30);
cave.max_tunnel_diameter = ps.range(40, ps.range(80,200)); min_tunnel_diameter = 30;
max_tunnel_diameter = ps->range(40, ps->range(80, 200));
} else { } else {
cave.tunnel_routepoints = ps.range(5, ps.range(15,30)); tunnel_routepoints = ps->range(5, ps->range(15,30));
cave.min_tunnel_diameter = 5; min_tunnel_diameter = 5;
cave.max_tunnel_diameter = ps.range(7, ps.range(8,24)); max_tunnel_diameter = ps->range(7, ps->range(8,24));
} }
} else { } else {
cave.part_max_length_rs = ps.range(2,9); part_max_length_rs = ps->range(2,9);
cave.tunnel_routepoints = ps.range(10, ps.range(15,30)); tunnel_routepoints = ps->range(10, ps->range(15,30));
} }
cave.large_cave_is_flat = (ps.range(0,1) == 0); large_cave_is_flat = (ps->range(0,1) == 0);
} }
/* /*
@ -365,7 +401,8 @@ void MapgenIndev::generateFloatIslands(int min_y) {
} }
} }
void MapgenIndev::generateSomething() { void MapgenIndev::generateExperimental() {
int float_islands = g_settings->getS16("mgindev_float_islands"); int float_islands = g_settings->getS16("mgindev_float_islands");
if(float_islands) generateFloatIslands(float_islands); if (float_islands)
generateFloatIslands(float_islands);
} }

View File

@ -22,6 +22,7 @@ with this program; if not, write to the Free Software Foundation, Inc.,
#include "mapgen.h" #include "mapgen.h"
#include "mapgen_v6.h" #include "mapgen_v6.h"
#include "cavegen.h"
float farscale(float scale, float z); float farscale(float scale, float z);
float farscale(float scale, float x, float z); float farscale(float scale, float x, float z);
@ -133,8 +134,9 @@ class MapgenIndev : public MapgenV6 {
float baseTerrainLevelFromNoise(v2s16 p); float baseTerrainLevelFromNoise(v2s16 p);
float baseTerrainLevelFromMap(int index); float baseTerrainLevelFromMap(int index);
float getMudAmount(int index); float getMudAmount(int index);
void defineCave(Cave & cave, PseudoRandom ps, v3s16 node_min, bool large_cave); void generateCaves(int max_stone_y);
void generateSomething(); //void defineCave(Cave & cave, PseudoRandom ps, v3s16 node_min, bool large_cave);
void generateExperimental();
void generateFloatIslands(int min_y); void generateFloatIslands(int min_y);
}; };
@ -149,4 +151,10 @@ struct MapgenFactoryIndev : public MapgenFactoryV6 {
}; };
}; };
class CaveIndev : public CaveV6 {
public:
CaveIndev(Mapgen *mg, PseudoRandom *ps, PseudoRandom *ps2, v3s16 node_min,
bool is_large_cave, content_t c_water, content_t c_lava);
};
#endif #endif

View File

@ -33,6 +33,7 @@ with this program; if not, write to the Free Software Foundation, Inc.,
#include "main.h" // For g_profiler #include "main.h" // For g_profiler
#include "emerge.h" #include "emerge.h"
#include "dungeongen.h" #include "dungeongen.h"
#include "cavegen.h"
#include "treegen.h" #include "treegen.h"
#include "mapgen_v6.h" #include "mapgen_v6.h"
@ -423,7 +424,7 @@ void MapgenV6::makeChunk(BlockMakeData *data) {
// Generate general ground level to full area // Generate general ground level to full area
stone_surface_max_y = generateGround(); stone_surface_max_y = generateGround();
generateSomething(); generateExperimental();
const s16 max_spread_amount = MAP_BLOCKSIZE; const s16 max_spread_amount = MAP_BLOCKSIZE;
// Limit dirt flow area by 1 because mud is flown into neighbors. // Limit dirt flow area by 1 because mud is flown into neighbors.
@ -927,35 +928,10 @@ void MapgenV6::growGrass() {
} }
void MapgenV6::defineCave(Cave &cave, PseudoRandom ps,
v3s16 node_min, bool large_cave) {
cave.min_tunnel_diameter = 2;
cave.max_tunnel_diameter = ps.range(2,6);
cave.dswitchint = ps.range(1,14);
cave.flooded = true; //large_cave && ps.range(0,4);
if (large_cave){
cave.part_max_length_rs = ps.range(2,4);
cave.tunnel_routepoints = ps.range(5, ps.range(15,30));
cave.min_tunnel_diameter = 5;
cave.max_tunnel_diameter = ps.range(7, ps.range(8,24));
} else {
cave.part_max_length_rs = ps.range(2,9);
cave.tunnel_routepoints = ps.range(10, ps.range(15,30));
}
cave.large_cave_is_flat = (ps.range(0,1) == 0);
}
void MapgenV6::generateCaves(int max_stone_y) { void MapgenV6::generateCaves(int max_stone_y) {
// 24ms @cs=8
//TimeTaker timer1("caves");
/*double cave_amount = 6.0 + 6.0 * noise2d_perlin(
0.5+(double)node_min.X/250, 0.5+(double)node_min.Y/250,
data->seed+34329, 3, 0.50);*/
const s16 max_spread_amount = MAP_BLOCKSIZE;
float cave_amount = NoisePerlin2D(np_cave, node_min.X, node_min.Y, seed); float cave_amount = NoisePerlin2D(np_cave, node_min.X, node_min.Y, seed);
int volume_nodes = (node_max.X - node_min.X + 1) *
(node_max.Y - node_min.Y + 1) * MAP_BLOCKSIZE;
cave_amount = MYMAX(0.0, cave_amount); cave_amount = MYMAX(0.0, cave_amount);
u32 caves_count = cave_amount * volume_nodes / 50000; u32 caves_count = cave_amount * volume_nodes / 50000;
u32 bruises_count = 1; u32 bruises_count = 1;
@ -970,238 +946,10 @@ void MapgenV6::generateCaves(int max_stone_y) {
bruises_count /= 3; bruises_count /= 3;
} }
for(u32 jj = 0; jj < caves_count + bruises_count; jj++) { for (u32 i = 0; i < caves_count + bruises_count; i++) {
/*int avg_height = (int) bool large_cave = (i >= caves_count);
((base_rock_level_2d(data->seed, v2s16(node_min.X, node_min.Z)) + CaveV6 cave(this, &ps, &ps2, large_cave, c_water_source, c_lava_source);
base_rock_level_2d(data->seed, v2s16(node_max.X, node_max.Z))) / 2);
if ((node_max.Y + node_min.Y) / 2 > avg_height)
break;*/
bool large_cave = (jj >= caves_count); cave.makeCave(node_min, node_max, max_stone_y);
Cave cave;
defineCave(cave, ps, node_min, large_cave);
v3f main_direction(0,0,0);
// Allowed route area size in nodes
v3s16 ar = central_area_size;
// Area starting point in nodes
v3s16 of = node_min;
// Allow a bit more
//(this should be more than the maximum radius of the tunnel)
s16 insure = 10;
s16 more = max_spread_amount - cave.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 + max_stone_y + cave.max_tunnel_diameter/2 + 7;
// Limit maximum to area
route_y_max = rangelim(route_y_max, 0, ar.Y-1);
if(large_cave)
{
s16 min = 0;
if(node_min.Y < water_level && node_max.Y > water_level)
{
min = water_level - cave.max_tunnel_diameter/3 - of.Y;
route_y_max = water_level + cave.max_tunnel_diameter/3 - of.Y;
}
route_y_min = ps.range(min, min + cave.max_tunnel_diameter);
route_y_min = rangelim(route_y_min, 0, route_y_max);
}
s16 route_start_y_min = route_y_min;
s16 route_start_y_max = route_y_max;
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);
// Randomize starting position
v3f orp(
(float)(ps.next()%ar.X)+0.5,
(float)(ps.range(route_start_y_min, route_start_y_max))+0.5,
(float)(ps.next()%ar.Z)+0.5
);
v3s16 startp(orp.X, orp.Y, orp.Z);
startp += of;
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<cave.tunnel_routepoints; j++)
{
if(j%cave.dswitchint==0 && large_cave == false)
{
main_direction = v3f(
((float)(ps.next()%20)-(float)10)/10,
((float)(ps.next()%20)-(float)10)/30,
((float)(ps.next()%20)-(float)10)/10
);
main_direction *= (float)ps.range(0, 10)/10;
}
// Randomize size
s16 min_d = cave.min_tunnel_diameter;
s16 max_d = cave.max_tunnel_diameter;
s16 rs = ps.range(min_d, max_d);
// Every second section is rough
bool randomize_xz = (ps2.range(1,2) == 1);
v3s16 maxlen;
if(large_cave)
{
maxlen = v3s16(
rs*cave.part_max_length_rs,
rs*cave.part_max_length_rs/2,
rs*cave.part_max_length_rs
);
}
else
{
maxlen = v3s16(
rs*cave.part_max_length_rs,
ps.range(1, rs*cave.part_max_length_rs),
rs*cave.part_max_length_rs
);
}
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)
{
vec = v3f(
(float)(ps.next()%(maxlen.X*1))-(float)maxlen.X/2,
(float)(ps.next()%(maxlen.Y*2))-(float)maxlen.Y*2/2,
(float)(ps.next()%(maxlen.Z*1))-(float)maxlen.Z/2
);
}
/*if(large_cave){
v3f p = orp + vec;
s16 h = find_ground_level_clever(vmanip,
v2s16(p.X, p.Z), ndef);
route_y_min = h - rs/3;
route_y_max = h + rs;
}*/
vec += main_direction;
v3f rp = orp + vec;
if(rp.X < 0)
rp.X = 0;
else if(rp.X >= ar.X)
rp.X = ar.X-1;
if(rp.Y < route_y_min)
rp.Y = route_y_min;
else if(rp.Y >= route_y_max)
rp.Y = route_y_max-1;
if(rp.Z < 0)
rp.Z = 0;
else if(rp.Z >= ar.Z)
rp.Z = ar.Z-1;
vec = rp - orp;
float veclen = vec.getLength();
// As odd as it sounds, veclen is *exactly*
// 0.0 sometimes, causing a FPE
if (veclen == 0.0)
veclen = 1.0;
for(float f=0; f<1.0; f+=1.0/veclen)
{
v3f fp = orp + vec * f;
fp.X += 0.1*ps.range(-10,10);
fp.Z += 0.1*ps.range(-10,10);
v3s16 cp(fp.X, fp.Y, fp.Z);
s16 d0 = -rs/2;
s16 d1 = d0 + rs;
if(randomize_xz){
d0 += ps.range(-1,1);
d1 += ps.range(-1,1);
}
for(s16 z0=d0; z0<=d1; z0++)
{
s16 si = rs/2 - MYMAX(0, abs(z0)-rs/7-1);
for(s16 x0=-si-ps.range(0,1); x0<=si-1+ps.range(0,1); x0++)
{
s16 maxabsxz = MYMAX(abs(x0), abs(z0));
s16 si2 = rs/2 - MYMAX(0, maxabsxz-rs/7-1);
for(s16 y0=-si2; y0<=si2; y0++)
{
/*// Make better floors in small caves
if(y0 <= -rs/2 && rs<=7)
continue;*/
if (cave.large_cave_is_flat) {
// Make large caves not so tall
if (rs > 7 && abs(y0) >= rs/3)
continue;
}
s16 z = cp.Z + z0;
s16 y = cp.Y + y0;
s16 x = cp.X + x0;
v3s16 p(x,y,z);
p += of;
if(vm->m_area.contains(p) == false)
continue;
u32 i = vm->m_area.index(p);
if(large_cave) {
if (cave.flooded && full_node_min.Y < water_level &&
full_node_max.Y > water_level) {
if (p.Y <= water_level)
vm->m_data[i] = waternode;
else
vm->m_data[i] = airnode;
} else if (cave.flooded && full_node_max.Y < water_level) {
if (p.Y < startp.Y - 2)
vm->m_data[i] = lavanode;
else
vm->m_data[i] = airnode;
} else {
vm->m_data[i] = airnode;
}
} else {
// Don't replace air or water or lava or ignore
if (vm->m_data[i].getContent() == CONTENT_IGNORE ||
vm->m_data[i].getContent() == CONTENT_AIR ||
vm->m_data[i].getContent() == c_water_source ||
vm->m_data[i].getContent() == c_lava_source)
continue;
vm->m_data[i] = airnode;
// Set tunnel flag
vm->m_flags[i] |= VMANIP_FLAG_CAVE;
}
}
}
}
}
orp = rp;
}
} }
} }

View File

@ -23,7 +23,6 @@ with this program; if not, write to the Free Software Foundation, Inc.,
#include "mapgen.h" #include "mapgen.h"
#define AVERAGE_MUD_AMOUNT 4 #define AVERAGE_MUD_AMOUNT 4
#define VMANIP_FLAG_CAVE VOXELFLAG_CHECKED1
enum BiomeType enum BiomeType
{ {
@ -43,16 +42,6 @@ extern NoiseParams nparams_v6_def_humidity;
extern NoiseParams nparams_v6_def_trees; extern NoiseParams nparams_v6_def_trees;
extern NoiseParams nparams_v6_def_apple_trees; extern NoiseParams nparams_v6_def_apple_trees;
struct Cave {
s16 min_tunnel_diameter;
s16 max_tunnel_diameter;
int dswitchint;
u16 tunnel_routepoints;
int part_max_length_rs;
bool large_cave_is_flat;
bool flooded;
};
struct MapgenV6Params : public MapgenParams { struct MapgenV6Params : public MapgenParams {
float freq_desert; float freq_desert;
float freq_beach; float freq_beach;
@ -166,10 +155,8 @@ public:
void addDirtGravelBlobs(); void addDirtGravelBlobs();
void growGrass(); void growGrass();
void placeTreesAndJungleGrass(); void placeTreesAndJungleGrass();
virtual void defineCave(Cave &cave, PseudoRandom ps, virtual void generateCaves(int max_stone_y);
v3s16 node_min, bool large_cave); virtual void generateExperimental() {}
void generateCaves(int max_stone_y);
virtual void generateSomething() {}; //for next mapgen
}; };
struct MapgenFactoryV6 : public MapgenFactory { struct MapgenFactoryV6 : public MapgenFactory {

View File

@ -34,6 +34,7 @@ with this program; if not, write to the Free Software Foundation, Inc.,
#include "main.h" // For g_profiler #include "main.h" // For g_profiler
#include "emerge.h" #include "emerge.h"
#include "dungeongen.h" #include "dungeongen.h"
#include "cavegen.h"
#include "treegen.h" #include "treegen.h"
#include "biome.h" #include "biome.h"
#include "mapgen_v7.h" #include "mapgen_v7.h"
@ -114,7 +115,23 @@ MapgenV7::~MapgenV7() {
int MapgenV7::getGroundLevelAtPoint(v2s16 p) { int MapgenV7::getGroundLevelAtPoint(v2s16 p) {
return 20; s16 groundlevel = baseTerrainLevelAtPoint(p.X, p.Y);
float heat = NoisePerlin2D(bmgr->np_heat, p.X, p.Y, seed);
float humidity = NoisePerlin2D(bmgr->np_humidity, p.X, p.Y, seed);
Biome *b = bmgr->getBiome(heat, humidity, groundlevel);
s16 y = groundlevel;
if (y > water_level) {
int iters = 1024; // don't even bother iterating more than 1024 times..
while (iters--) {
float ridgenoise = NoisePerlin3D(noise_ridge->np, p.X, y, p.Y, seed);
if (ridgenoise * (float)(y * y) < 15.0)
break;
y--;
}
}
return y + b->top_depth;
} }
@ -142,7 +159,7 @@ void MapgenV7::makeChunk(BlockMakeData *data) {
full_node_min = (blockpos_min - 1) * MAP_BLOCKSIZE; full_node_min = (blockpos_min - 1) * MAP_BLOCKSIZE;
full_node_max = (blockpos_max + 2) * MAP_BLOCKSIZE - v3s16(1, 1, 1); full_node_max = (blockpos_max + 2) * MAP_BLOCKSIZE - v3s16(1, 1, 1);
//blockseed = emerge->getBlockSeed(full_node_min); blockseed = emerge->getBlockSeed(full_node_min); //////use getBlockSeed2()!
// Make some noise // Make some noise
calculateNoise(); calculateNoise();
@ -163,14 +180,13 @@ void MapgenV7::makeChunk(BlockMakeData *data) {
c_dirt_with_grass = ndef->getId("mapgen_dirt_with_grass"); c_dirt_with_grass = ndef->getId("mapgen_dirt_with_grass");
c_sand = ndef->getId("mapgen_sand"); c_sand = ndef->getId("mapgen_sand");
c_water_source = ndef->getId("mapgen_water_source"); c_water_source = ndef->getId("mapgen_water_source");
c_lava_source = ndef->getId("mapgen_lava_source");
generateTerrain(); generateTerrain();
carveRidges(); carveRidges();
//carveRivers(); generateCaves(stone_surface_max_y);
addTopNodes(); addTopNodes();
growGrass();
//v3s16 central_area_size = node_max - node_min + v3s16(1,1,1); //v3s16 central_area_size = node_max - node_min + v3s16(1,1,1);
if (flags & MG_DUNGEONS) { if (flags & MG_DUNGEONS) {
@ -189,7 +205,8 @@ void MapgenV7::makeChunk(BlockMakeData *data) {
calcLighting(node_min - v3s16(1, 0, 1) * MAP_BLOCKSIZE, calcLighting(node_min - v3s16(1, 0, 1) * MAP_BLOCKSIZE,
node_max + v3s16(1, 0, 1) * MAP_BLOCKSIZE); node_max + v3s16(1, 0, 1) * MAP_BLOCKSIZE);
//setLighting(node_min, node_max, 0xFF); //setLighting(node_min - v3s16(1, 0, 1) * MAP_BLOCKSIZE,
// node_max + v3s16(1, 0, 1) * MAP_BLOCKSIZE, 0xFF);
this->generating = false; this->generating = false;
} }
@ -398,7 +415,9 @@ void MapgenV7::addTopNodes() {
for (s16 z = node_min.Z; z <= node_max.Z; z++) for (s16 z = node_min.Z; z <= node_max.Z; z++)
for (s16 x = node_min.X; x <= node_max.X; x++, index++) { for (s16 x = node_min.X; x <= node_max.X; x++, index++) {
// First, add top nodes below the ridge Biome *biome = bmgr->biomes[biomemap[index]];
//////////////////// First, add top nodes below the ridge
s16 y = ridge_heightmap[index]; s16 y = ridge_heightmap[index];
// This cutoff is good enough, but not perfect. // This cutoff is good enough, but not perfect.
@ -408,7 +427,8 @@ void MapgenV7::addTopNodes() {
if (y > node_max.Y) { if (y > node_max.Y) {
y = node_max.Y; // Let's see if we can still go downward anyway y = node_max.Y; // Let's see if we can still go downward anyway
u32 vi = vm->m_area.index(x, y, z); u32 vi = vm->m_area.index(x, y, z);
if (vm->m_data[vi].getContent() != CONTENT_AIR) content_t c = vm->m_data[vi].getContent();
if (ndef->get(c).walkable)
continue; continue;
} }
@ -417,14 +437,13 @@ void MapgenV7::addTopNodes() {
// where a ridge had been carved // where a ridge had been carved
u32 i = vm->m_area.index(x, y, z); u32 i = vm->m_area.index(x, y, z);
for (; y >= node_min.Y; y--) { for (; y >= node_min.Y; y--) {
if (vm->m_data[i].getContent() != CONTENT_AIR) content_t c = vm->m_data[i].getContent();
if (ndef->get(c).walkable)
break; break;
vm->m_area.add_y(em, i, -1); vm->m_area.add_y(em, i, -1);
} }
Biome *biome = bmgr->biomes[biomemap[index]]; if (y != node_min.Y - 1 && y >= water_level) {
if (y != node_min.Y - 1) {
ridge_heightmap[index] = y; //update ridgeheight ridge_heightmap[index] = y; //update ridgeheight
ntopnodes = biome->top_depth; ntopnodes = biome->top_depth;
for (; y <= node_max.Y && ntopnodes; y++) { for (; y <= node_max.Y && ntopnodes; y++) {
@ -432,15 +451,28 @@ void MapgenV7::addTopNodes() {
vm->m_data[i] = MapNode(biome->c_top); vm->m_data[i] = MapNode(biome->c_top);
vm->m_area.add_y(em, i, 1); vm->m_area.add_y(em, i, 1);
} }
//heightmap[index] = y; // If dirt, grow grass on it.
if (vm->m_data[i].getContent() == CONTENT_AIR) {
vm->m_area.add_y(em, i, -1);
if (vm->m_data[i].getContent() == c_dirt)
vm->m_data[i] = MapNode(c_dirt_with_grass);
}
} }
// Now, add top nodes on top of the ridge //////////////////// Now, add top nodes on top of the ridge
y = heightmap[index]; y = heightmap[index];
if (y > node_max.Y) {
y = node_max.Y; // Let's see if we can still go downward anyway
u32 vi = vm->m_area.index(x, y, z);
content_t c = vm->m_data[vi].getContent();
if (ndef->get(c).walkable)
continue;
}
i = vm->m_area.index(x, y, z); i = vm->m_area.index(x, y, z);
for (; y >= node_min.Y; y--) { for (; y >= node_min.Y; y--) {
if (vm->m_data[i].getContent() != CONTENT_AIR) content_t c = vm->m_data[i].getContent();
if (ndef->get(c).walkable)
break; break;
vm->m_area.add_y(em, i, -1); vm->m_area.add_y(em, i, -1);
} }
@ -456,35 +488,36 @@ void MapgenV7::addTopNodes() {
vm->m_data[i] = MapNode(biome->c_top); vm->m_data[i] = MapNode(biome->c_top);
vm->m_area.add_y(em, i, 1); vm->m_area.add_y(em, i, 1);
} }
} // If dirt, grow grass on it.
} if (vm->m_data[i].getContent() == CONTENT_AIR) {
}
void MapgenV7::growGrass() {
for (s16 z = node_min.Z; z <= node_max.Z; z++)
for (s16 x = node_min.X; x <= node_max.X; x++) {
// Find the lowest surface to which enough light ends up to make
// grass grow. Basically just wait until not air and not leaves.
s16 surface_y = 0;
{
v3s16 em = vm->m_area.getExtent();
u32 i = vm->m_area.index(x, node_max.Y, z);
s16 y;
// Go to ground level
for (y = node_max.Y; y >= node_min.Y; y--) {
MapNode &n = vm->m_data[i];
if (ndef->get(n).param_type != CPT_LIGHT ||
ndef->get(n).liquid_type != LIQUID_NONE)
break;
vm->m_area.add_y(em, i, -1); vm->m_area.add_y(em, i, -1);
if (vm->m_data[i].getContent() == c_dirt)
vm->m_data[i] = MapNode(c_dirt_with_grass);
}
}
} }
surface_y = (y >= node_min.Y) ? y : node_min.Y;
} }
u32 i = vm->m_area.index(x, surface_y, z);
MapNode *n = &vm->m_data[i]; #include "mapgen_v6.h"
if (n->getContent() == c_dirt && surface_y >= water_level - 20) void MapgenV7::generateCaves(int max_stone_y) {
n->setContent(c_dirt_with_grass); PseudoRandom ps(blockseed + 21343);
PseudoRandom ps2(blockseed + 1032);
int volume_nodes = (node_max.X - node_min.X + 1) *
(node_max.Y - node_min.Y + 1) * MAP_BLOCKSIZE;
float cave_amount = NoisePerlin2D(&nparams_v6_def_cave,
node_min.X, node_min.Y, seed);
u32 caves_count = MYMAX(0.0, cave_amount) * volume_nodes / 50000;
for (u32 i = 0; i < caves_count; i++) {
CaveV6 cave(this, &ps, &ps2, false, c_water_source, c_lava_source);
cave.makeCave(node_min, node_max, max_stone_y);
}
u32 bruises_count = (ps.range(1, 6) == 1) ? ps.range(0, ps.range(0, 2)) : 1;
for (u32 i = 0; i < bruises_count; i++) {
CaveV6 cave(this, &ps, &ps2, true, c_water_source, c_lava_source);
cave.makeCave(node_min, node_max, max_stone_y);
} }
} }

View File

@ -109,7 +109,8 @@ public:
void testBiomes(); void testBiomes();
void addTopNodes(); void addTopNodes();
void growGrass();
void generateCaves(int max_stone_y);
}; };
struct MapgenFactoryV7 : public MapgenFactory { struct MapgenFactoryV7 : public MapgenFactory {

View File

@ -749,7 +749,7 @@ int ObjectRef::l_hud_add(lua_State *L)
elem->text = getstringfield_default(L, 2, "text", ""); elem->text = getstringfield_default(L, 2, "text", "");
elem->number = getintfield_default(L, 2, "number", 0); elem->number = getintfield_default(L, 2, "number", 0);
elem->item = getintfield_default(L, 2, "item", 0); elem->item = getintfield_default(L, 2, "item", 0);
elem->dir = getintfield_default(L, 2, "dir", 0); elem->dir = getintfield_default(L, 2, "direction", 0);
u32 id = get_server(L)->hudAdd(player, elem); u32 id = get_server(L)->hudAdd(player, elem);
if (id == (u32)-1) { if (id == (u32)-1) {
@ -788,16 +788,18 @@ int ObjectRef::l_hud_change(lua_State *L)
if (player == NULL) if (player == NULL)
return 0; return 0;
u32 id = -1; u32 id = !lua_isnil(L, 2) ? lua_tonumber(L, 2) : -1;
if (!lua_isnil(L, 2))
id = lua_tonumber(L, 2);
HudElementStat stat = (HudElementStat)getenumfield(L, 3, "stat",
es_HudElementStat, HUD_STAT_NUMBER);
if (id >= player->hud.size()) if (id >= player->hud.size())
return 0; return 0;
HudElementStat stat = HUD_STAT_NUMBER;
if (!lua_isnil(L, 3)) {
int statint;
std::string statstr = lua_tostring(L, 3);
stat = string_to_enum(es_HudElementStat, statint, statstr) ?
(HudElementStat)statint : HUD_STAT_NUMBER;
}
void *value = NULL; void *value = NULL;
HudElement *e = player->hud[id]; HudElement *e = player->hud[id];
if (!e) if (!e)

View File

@ -4951,36 +4951,28 @@ v3f findSpawnPos(ServerMap &map)
{ {
s32 range = 1 + i; s32 range = 1 + i;
// We're going to try to throw the player to this position // We're going to try to throw the player to this position
v2s16 nodepos2d = v2s16(-range + (myrand()%(range*2)), v2s16 nodepos2d = v2s16(
-range + (myrand() % (range * 2)),
-range + (myrand() % (range * 2))); -range + (myrand() % (range * 2)));
//v2s16 sectorpos = getNodeSectorPos(nodepos2d);
// Get ground height at point (fallbacks to heightmap function)
s16 groundheight = map.findGroundLevel(nodepos2d);
// Don't go underwater
if(groundheight <= water_level)
{
//infostream<<"-> Underwater"<<std::endl;
continue;
}
// Don't go to high places
if(groundheight > water_level + 6)
{
//infostream<<"-> Underwater"<<std::endl;
continue;
}
nodepos = v3s16(nodepos2d.X, groundheight-2, nodepos2d.Y); // Get ground height at point
s16 groundheight = map.findGroundLevel(nodepos2d);
if (groundheight <= water_level) // Don't go underwater
continue;
if (groundheight > water_level + 6) // Don't go to high places
continue;
nodepos = v3s16(nodepos2d.X, groundheight, nodepos2d.Y);
bool is_good = false; bool is_good = false;
s32 air_count = 0; s32 air_count = 0;
for (s32 i = 0; i < 10; i++) { for (s32 i = 0; i < 10; i++) {
v3s16 blockpos = getNodeBlockPos(nodepos); v3s16 blockpos = getNodeBlockPos(nodepos);
map.emergeBlock(blockpos, true); map.emergeBlock(blockpos, true);
MapNode n = map.getNodeNoEx(nodepos); content_t c = map.getNodeNoEx(nodepos).getContent();
if(n.getContent() == CONTENT_AIR){ if (c == CONTENT_AIR || c == CONTENT_IGNORE) {
air_count++; air_count++;
if (air_count >= 2){ if (air_count >= 2){
is_good = true; is_good = true;
nodepos.Y -= 1;
break; break;
} }
} }