diff options
-rw-r--r-- | CMakeLists.txt | 2 | ||||
-rw-r--r-- | cmake/Modules/FindGettextLib.cmake | 21 | ||||
-rw-r--r-- | data/glass.png | bin | 1309 -> 381 bytes | |||
-rw-r--r-- | data/heart.png | bin | 308 -> 258 bytes | |||
-rw-r--r-- | data/menulogo.png | bin | 498 -> 653 bytes | |||
-rw-r--r-- | data/oerkki1.png | bin | 250 -> 333 bytes | |||
-rw-r--r-- | data/oerkki1_damaged.png | bin | 341 -> 291 bytes | |||
-rw-r--r-- | data/player.png | bin | 212 -> 652 bytes | |||
-rw-r--r-- | data/player_back.png | bin | 201 -> 292 bytes | |||
-rw-r--r-- | data/rat.png | bin | 920 -> 276 bytes | |||
-rw-r--r-- | data/unknown_block.png | bin | 582 -> 287 bytes | |||
-rw-r--r-- | minetest-icon-24x24.png | bin | 0 -> 913 bytes | |||
-rw-r--r-- | pnoise.py | 102 | ||||
-rw-r--r-- | po/it/minetest.po | 124 | ||||
-rw-r--r-- | po/minetest.pot | 113 | ||||
-rw-r--r-- | src/CMakeLists.txt | 88 | ||||
-rw-r--r-- | src/client.cpp | 1 | ||||
-rw-r--r-- | src/cmake_config.h.in | 4 | ||||
-rw-r--r-- | src/config.h | 11 | ||||
-rw-r--r-- | src/gettext.h | 14 | ||||
-rw-r--r-- | src/guiPauseMenu.cpp | 2 | ||||
-rw-r--r-- | src/keycode.cpp | 1 | ||||
-rw-r--r-- | src/main.cpp | 6 | ||||
-rw-r--r-- | src/map.cpp | 423 | ||||
-rw-r--r-- | src/mapblock.cpp | 2 | ||||
-rw-r--r-- | src/mapnode.h | 7 | ||||
-rw-r--r-- | src/servermain.cpp | 2 | ||||
-rwxr-xr-x | util/updatepo.sh | 65 |
28 files changed, 685 insertions, 303 deletions
diff --git a/CMakeLists.txt b/CMakeLists.txt index b4a5bb02e..aae390f38 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -5,7 +5,7 @@ if(${CMAKE_VERSION} STREQUAL "2.8.2") endif(${CMAKE_VERSION} STREQUAL "2.8.2") # This can be read from ${PROJECT_NAME} after project() is called -project(minetest) +project(minetest-delta) set(VERSION_MAJOR 0) set(VERSION_MINOR 2) diff --git a/cmake/Modules/FindGettextLib.cmake b/cmake/Modules/FindGettextLib.cmake index b99fd33b8..18935eaad 100644 --- a/cmake/Modules/FindGettextLib.cmake +++ b/cmake/Modules/FindGettextLib.cmake @@ -16,21 +16,6 @@ FIND_PROGRAM(GETTEXT_MSGFMT PATHS "${CUSTOM_GETTEXT_PATH}/bin" DOC "path to msgfmt") -FIND_PROGRAM(GETTEXT_MSGMERGE - NAMES msgmerge - PATHS "${CUSTOM_GETTEXT_PATH}/bin" - DOC "path to msgmerge") - -FIND_PROGRAM(GETTEXT_MSGEN - NAMES msgen - PATHS "${CUSTOM_GETTEXT_PATH}/bin" - DOC "path to msgen") - -FIND_PROGRAM(GETTEXT_EXTRACT - NAMES xgettext - PATHS "${CUSTOM_GETTEXT_PATH}/bin" - DOC "path to xgettext") - # modern Linux, as well as Mac, seem to not need require special linking # they do not because gettext is part of glibc # TODO check the requirements on other BSDs and older Linux @@ -71,10 +56,14 @@ ENDIF() IF(GETTEXT_FOUND) SET(GETTEXT_PO_PATH ${CMAKE_SOURCE_DIR}/po) SET(GETTEXT_MO_BUILD_PATH ${CMAKE_BINARY_DIR}/locale/<locale>/LC_MESSAGES) - SET(GETTEXT_MO_DEST_PATH locale/<locale>/LC_MESSAGES) + SET(GETTEXT_MO_DEST_PATH ${DATADIR}/../locale/<locale>/LC_MESSAGES) FILE(GLOB GETTEXT_AVAILABLE_LOCALES RELATIVE ${GETTEXT_PO_PATH} "${GETTEXT_PO_PATH}/*") + LIST(REMOVE_ITEM GETTEXT_AVAILABLE_LOCALES minetest.pot) MACRO(SET_MO_PATHS _buildvar _destvar _locale) STRING(REPLACE "<locale>" ${_locale} ${_buildvar} ${GETTEXT_MO_BUILD_PATH}) STRING(REPLACE "<locale>" ${_locale} ${_destvar} ${GETTEXT_MO_DEST_PATH}) ENDMACRO(SET_MO_PATHS) +ELSE() + SET(GETTEXT_INCLUDE_DIR "") + SET(GETTEXT_LIBRARY "") ENDIF() diff --git a/data/glass.png b/data/glass.png Binary files differindex 8598ce670..35ea596d5 100644 --- a/data/glass.png +++ b/data/glass.png diff --git a/data/heart.png b/data/heart.png Binary files differindex 6bc183e04..bea1aefd6 100644 --- a/data/heart.png +++ b/data/heart.png diff --git a/data/menulogo.png b/data/menulogo.png Binary files differindex 76595c48d..cb6983e5c 100644 --- a/data/menulogo.png +++ b/data/menulogo.png diff --git a/data/oerkki1.png b/data/oerkki1.png Binary files differindex 33cbac9e7..1256a8a57 100644 --- a/data/oerkki1.png +++ b/data/oerkki1.png diff --git a/data/oerkki1_damaged.png b/data/oerkki1_damaged.png Binary files differindex 9b777387c..99e4bd362 100644 --- a/data/oerkki1_damaged.png +++ b/data/oerkki1_damaged.png diff --git a/data/player.png b/data/player.png Binary files differindex 90adf9747..60ac4854b 100644 --- a/data/player.png +++ b/data/player.png diff --git a/data/player_back.png b/data/player_back.png Binary files differindex 530aa7519..447c1fd8f 100644 --- a/data/player_back.png +++ b/data/player_back.png diff --git a/data/rat.png b/data/rat.png Binary files differindex d1a0e2ae2..96d44c3fa 100644 --- a/data/rat.png +++ b/data/rat.png diff --git a/data/unknown_block.png b/data/unknown_block.png Binary files differindex a27cb8ca9..8a8e0109c 100644 --- a/data/unknown_block.png +++ b/data/unknown_block.png diff --git a/minetest-icon-24x24.png b/minetest-icon-24x24.png Binary files differnew file mode 100644 index 000000000..4d587c410 --- /dev/null +++ b/minetest-icon-24x24.png diff --git a/pnoise.py b/pnoise.py new file mode 100644 index 000000000..fcab5ac15 --- /dev/null +++ b/pnoise.py @@ -0,0 +1,102 @@ +# +# A python perlin noise implementation, from +# http://www.fundza.com/c4serious/noise/perlin/perlin.html +# +# This is used for testing how to create maps with a python script. +# + +import math +p = ( +151,160,137,91,90,15,131,13,201,95,96,53,194,233,7,225,140,36,103, +30,69,142,8,99,37,240,21,10,23,190,6,148,247,120,234,75,0,26,197, +62,94,252,219,203,117,35,11,32,57,177,33,88,237,149,56,87,174,20, +125,136,171,168,68,175,74,165,71,134,139,48,27,166,77,146,158,231, +83,111,229,122,60,211,133,230,220,105,92,41,55,46,245,40,244,102, +143,54,65,25,63,161,1,216,80,73,209,76,132,187,208,89,18,169,200, +196,135,130,116,188,159,86,164,100,109,198,173,186,3,64,52,217,226, +250,124,123,5,202,38,147,118,126,255,82,85,212,207,206,59,227,47,16, +58,17,182,189,28,42,223,183,170,213,119,248,152,2,44,154,163,70, +221,153,101,155,167,43,172,9,129,22,39,253,19,98,108,110,79,113, +224,232,178,185,112,104,218,246,97,228,251,34,242,193,238,210,144, +12,191,179,162,241,81,51,145,235,249,14,239,107,49,192,214,31,181, +199,106,157,184,84,204,176,115,121,50,45,127,4,150,254,138,236, +205,93,222,114,67,29,24,72,243,141,128,195,78,66,215,61,156,180, +151,160,137,91,90,15,131,13,201,95,96,53,194,233,7,225,140,36,103, +30,69,142,8,99,37,240,21,10,23,190,6,148,247,120,234,75,0,26,197, +62,94,252,219,203,117,35,11,32,57,177,33,88,237,149,56,87,174,20, +125,136,171,168,68,175,74,165,71,134,139,48,27,166,77,146,158,231, +83,111,229,122,60,211,133,230,220,105,92,41,55,46,245,40,244,102, +143,54,65,25,63,161,1,216,80,73,209,76,132,187,208,89,18,169,200, +196,135,130,116,188,159,86,164,100,109,198,173,186,3,64,52,217,226, +250,124,123,5,202,38,147,118,126,255,82,85,212,207,206,59,227,47,16, +58,17,182,189,28,42,223,183,170,213,119,248,152,2,44,154,163,70, +221,153,101,155,167,43,172,9,129,22,39,253,19,98,108,110,79,113, +224,232,178,185,112,104,218,246,97,228,251,34,242,193,238,210,144, +12,191,179,162,241,81,51,145,235,249,14,239,107,49,192,214,31,181, +199,106,157,184,84,204,176,115,121,50,45,127,4,150,254,138,236, +205,93,222,114,67,29,24,72,243,141,128,195,78,66,215,61,156,180) + +def lerp(t, a, b): + return a + t * (b - a) + +def fade(t): + return t * t * t * (t * (t * 6 - 15) + 10) + +def grad(hash, x, y, z): + h = hash & 15 + if h < 8: + u = x + else: + u = y + if h < 4: + v = y + elif h == 12 or h == 14: + v = x + else: + v = z + if h & 1 != 0: + u = -u + if h & 2 != 0: + v = -v + return u + v + +def pnoise(x, y, z): + global p + X = int(math.floor(x)) & 255 + Y = int(math.floor(y)) & 255 + Z = int(math.floor(z)) & 255 + x -= math.floor(x) + y -= math.floor(y) + z -= math.floor(z) + + u = fade(x) + v = fade(y) + w = fade(z) + + A = p[X] + Y + AA = p[A] + Z + AB = p[A + 1] + Z + B = p[X + 1] + Y + BA = p[B] + Z + BB = p[B + 1] + Z + + pAA = p[AA] + pAB = p[AB] + pBA = p[BA] + pBB = p[BB] + pAA1 = p[AA + 1] + pBA1 = p[BA + 1] + pAB1 = p[AB + 1] + pBB1 = p[BB + 1] + + gradAA = grad(pAA, x, y, z) + gradBA = grad(pBA, x-1, y, z) + gradAB = grad(pAB, x, y-1, z) + gradBB = grad(pBB, x-1, y-1, z) + gradAA1 = grad(pAA1,x, y, z-1) + gradBA1 = grad(pBA1,x-1, y, z-1) + gradAB1 = grad(pAB1,x, y-1, z-1) + gradBB1 = grad(pBB1,x-1, y-1, z-1) + return lerp(w, + lerp(v, lerp(u, gradAA, gradBA), lerp(u, gradAB, gradBB)), + lerp(v, lerp(u, gradAA1,gradBA1),lerp(u, gradAB1,gradBB1))) diff --git a/po/it/minetest.po b/po/it/minetest.po new file mode 100644 index 000000000..8f6631135 --- /dev/null +++ b/po/it/minetest.po @@ -0,0 +1,124 @@ +# Italian translations for minetest package. +# Copyright (C) 2011 THE minetest'S COPYRIGHT HOLDER +# This file is distributed under the same license as the minetest package. +# Giuseppe Bilotta <giuseppe.bilotta@gmail.com>, 2011. +# +msgid "" +msgstr "" +"Project-Id-Version: minetest\n" +"Report-Msgid-Bugs-To: \n" +"POT-Creation-Date: 2011-07-24 18:56+0200\n" +"PO-Revision-Date: 2011-07-24 18:56+0200\n" +"Last-Translator: Giuseppe Bilotta <giuseppe.bilotta@gmail.com>\n" +"Language-Team: Italian\n" +"Language: it\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" + +#: src/guiMainMenu.cpp:180 +msgid "Name/Password" +msgstr "Nome/Password" + +#: src/guiMainMenu.cpp:203 +msgid "Address/Port" +msgstr "Indirizzo/Porta" + +#: src/guiMainMenu.cpp:223 +msgid "Leave address blank to start a local server." +msgstr "Lascia vuoto l'indirizzo per avviare un server locale" + +#: src/guiMainMenu.cpp:230 +msgid "Fancy trees" +msgstr "Alberi strani" + +#: src/guiMainMenu.cpp:236 +msgid "Smooth Lighting" +msgstr "" + +#: src/guiMainMenu.cpp:244 +msgid "Start Game / Connect" +msgstr "Avvia Gioco / Connetti" + +#: src/guiMainMenu.cpp:253 +msgid "Change keys" +msgstr "Modifica tasti" + +#: src/guiMainMenu.cpp:276 +msgid "Creative Mode" +msgstr "Modalità creativa" + +#: src/guiMainMenu.cpp:282 +msgid "Enable Damage" +msgstr "Attiva Danno" + +#: src/guiMainMenu.cpp:290 +msgid "Delete map" +msgstr "Cancella mappa" + +#: src/guiMessageMenu.cpp:93 src/guiTextInputMenu.cpp:111 +msgid "Proceed" +msgstr "Procedi" + +#: src/guiPasswordChange.cpp:102 +msgid "Old Password" +msgstr "Vecchia password" + +#: src/guiPasswordChange.cpp:117 +msgid "New Password" +msgstr "Nuova password" + +#: src/guiPasswordChange.cpp:131 +msgid "Confirm Password" +msgstr "Conferma password" + +#: src/guiPasswordChange.cpp:146 +msgid "Change" +msgstr "Modifica" + +#: src/guiPasswordChange.cpp:155 +msgid "Passwords do not match!" +msgstr "Le password non corrispondono!" + +#: src/guiPauseMenu.cpp:110 +msgid "Continue" +msgstr "Continua" + +#: src/guiPauseMenu.cpp:117 +msgid "Change Password" +msgstr "Cambia password" + +#: src/guiPauseMenu.cpp:124 +msgid "Disconnect" +msgstr "Disconnetti" + +#: src/guiPauseMenu.cpp:131 +msgid "Exit to OS" +msgstr "Esci al S.O." + +#: src/guiPauseMenu.cpp:138 +msgid "" +"Keys:\n" +"- WASD: Walk\n" +"- Mouse left: dig blocks\n" +"- Mouse right: place blocks\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 "" +"Tasti:\n" +"- WASD: Cammina\n" +"- Mouse left: scava blocchi\n" +"- Mouse right: piazza blocchi\n" +"- Mouse wheel: seleziona oggetto\n" +"- 0...9: seleziona oggetto\n" +"- Shift: furtivo\n" +"- R: (Dis)attiva motra tutti i blocchi caricati\n" +"- I: Inventario\n" +"- ESC: Questo menu\n" +"- T: Parla\n" diff --git a/po/minetest.pot b/po/minetest.pot new file mode 100644 index 000000000..e359bf4bc --- /dev/null +++ b/po/minetest.pot @@ -0,0 +1,113 @@ +# 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: 2011-07-24 18:56+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/guiMainMenu.cpp:180 +msgid "Name/Password" +msgstr "" + +#: src/guiMainMenu.cpp:203 +msgid "Address/Port" +msgstr "" + +#: src/guiMainMenu.cpp:223 +msgid "Leave address blank to start a local server." +msgstr "" + +#: src/guiMainMenu.cpp:230 +msgid "Fancy trees" +msgstr "" + +#: src/guiMainMenu.cpp:236 +msgid "Smooth Lighting" +msgstr "" + +#: src/guiMainMenu.cpp:244 +msgid "Start Game / Connect" +msgstr "" + +#: src/guiMainMenu.cpp:253 +msgid "Change keys" +msgstr "" + +#: src/guiMainMenu.cpp:276 +msgid "Creative Mode" +msgstr "" + +#: src/guiMainMenu.cpp:282 +msgid "Enable Damage" +msgstr "" + +#: src/guiMainMenu.cpp:290 +msgid "Delete map" +msgstr "" + +#: src/guiMessageMenu.cpp:93 src/guiTextInputMenu.cpp:111 +msgid "Proceed" +msgstr "" + +#: src/guiPasswordChange.cpp:102 +msgid "Old Password" +msgstr "" + +#: src/guiPasswordChange.cpp:117 +msgid "New Password" +msgstr "" + +#: src/guiPasswordChange.cpp:131 +msgid "Confirm Password" +msgstr "" + +#: src/guiPasswordChange.cpp:146 +msgid "Change" +msgstr "" + +#: src/guiPasswordChange.cpp:155 +msgid "Passwords do not match!" +msgstr "" + +#: src/guiPauseMenu.cpp:110 +msgid "Continue" +msgstr "" + +#: src/guiPauseMenu.cpp:117 +msgid "Change Password" +msgstr "" + +#: src/guiPauseMenu.cpp:124 +msgid "Disconnect" +msgstr "" + +#: src/guiPauseMenu.cpp:131 +msgid "Exit to OS" +msgstr "" + +#: src/guiPauseMenu.cpp:138 +msgid "" +"Keys:\n" +"- WASD: Walk\n" +"- Mouse left: dig blocks\n" +"- Mouse right: place blocks\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 "" diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt index 8ce69b2ad..fcdb3ccbc 100644 --- a/src/CMakeLists.txt +++ b/src/CMakeLists.txt @@ -1,15 +1,19 @@ +project(minetest-delta) cmake_minimum_required( VERSION 2.6 ) -project(minetest) - if(RUN_IN_PLACE) add_definitions ( -DRUN_IN_PLACE ) endif(RUN_IN_PLACE) -OPTION(USE_GETTEXT "Use GetText for internationalization" OFF) +# user-visible option to enable/disable gettext usage +OPTION(ENABLE_GETTEXT "Use GetText for internationalization" ON) + +# this is only set to 1 if gettext is enabled _and_ available +set(USE_GETTEXT 0) -if(USE_GETTEXT) - find_package(GettextLib REQUIRED) +find_package(GettextLib) + +if(GETTEXT_FOUND AND ENABLE_GETTEXT) message(STATUS "gettext include path: ${GETTEXT_INCLUDE_DIR}") message(STATUS "gettext msgfmt path: ${GETTEXT_MSGFMT}") if(WIN32) @@ -17,16 +21,13 @@ if(USE_GETTEXT) message(STATUS "gettext dll: ${GETTEXT_DLL}") message(STATUS "gettext iconv dll: ${GETTEXT_ICONV_DLL}") endif() - if (GETTEXT_FOUND) - add_definitions( -DUSE_GETTEXT ) - message(STATUS "GetText enabled; locales found: ${GETTEXT_AVAILABLE_LOCALES}") - else() - message(STATUS "ERROR: GetText enabled but not found, disabling") - set(USE_GETTEXT FALSE) - endif(GETTEXT_FOUND) -else(USE_GETTEXT) + set(USE_GETTEXT 1) + message(STATUS "GetText enabled; locales found: ${GETTEXT_AVAILABLE_LOCALES}") +elseif(GETTEXT_FOUND AND NOT ENABLE_GETTEXT) + MESSAGE(STATUS "GetText found but disabled;") +else(GETTEXT_FOUND AND ENABLE_GETTEXT) message(STATUS "GetText disabled") -endif(USE_GETTEXT) +endif(GETTEXT_FOUND AND ENABLE_GETTEXT) if(NOT MSVC) set(USE_GPROF 0 CACHE BOOL "Use -pg flag for g++") @@ -269,7 +270,7 @@ if(BUILD_CLIENT) install(FILES ${images} DESTINATION ${DATADIR}) - if (USE_GETTEXT) + if(USE_GETTEXT) foreach(LOCALE ${GETTEXT_AVAILABLE_LOCALES}) set_mo_paths(MO_BUILD_PATH MO_DEST_PATH ${LOCALE}) set(MO_BUILD_PATH "${MO_BUILD_PATH}/${PROJECT_NAME}.mo") @@ -300,54 +301,29 @@ if(BUILD_SERVER) endif(BUILD_SERVER) if (USE_GETTEXT) - add_custom_command(OUTPUT "${GETTEXT_PO_PATH}/en" - COMMAND ${CMAKE_COMMAND} -E make_directory "${GETTEXT_PO_PATH}/en" - COMMENT "po-update [en]: creating translation template base directory") - set(POT_FILE "${GETTEXT_PO_PATH}/en/minetest.pot") - file(GLOB GETTEXT_POT_DEPS *.cpp *.h) - file(GLOB GETTEXT_POT_DEPS_REL RELATIVE ${CMAKE_SOURCE_DIR} *.cpp *.h) - add_custom_command(OUTPUT ${POT_FILE} - COMMAND ${GETTEXT_EXTRACT} -F -n -o ${POT_FILE} ${GETTEXT_POT_DEPS_REL} - DEPENDS "${GETTEXT_PO_PATH}/en" ${GETTEXT_POT_DEPS} - WORKING_DIRECTORY ${CMAKE_SOURCE_DIR} - COMMENT "po-update [en]: updating translation template") - - set(PO_FILES) set(MO_FILES) foreach(LOCALE ${GETTEXT_AVAILABLE_LOCALES}) - # skip the 'en' locale which is treated separately - if (NOT LOCALE STREQUAL "en") - set(PO_FILE_PATH "${GETTEXT_PO_PATH}/${LOCALE}/minetest.po") - add_custom_command(OUTPUT ${PO_FILE_PATH} - COMMAND ${GETTEXT_MSGMERGE} -F -U ${PO_FILE_PATH} ${POT_FILE} - DEPENDS ${POT_FILE} - WORKING_DIRECTORY "${GETTEXT_PO_PATH}/${LOCALE}" - COMMENT "po-update [${LOCALE}]: updating strings") - + set(PO_FILE_PATH "${GETTEXT_PO_PATH}/${LOCALE}/minetest.po") + set_mo_paths(MO_BUILD_PATH MO_DEST_PATH ${LOCALE}) + set(MO_FILE_PATH "${MO_BUILD_PATH}/${PROJECT_NAME}.mo") + + add_custom_command(OUTPUT ${MO_BUILD_PATH} + COMMAND ${CMAKE_COMMAND} -E make_directory ${MO_BUILD_PATH} + COMMENT "mo-update [${LOCALE}]: Creating locale directory.") + + add_custom_command( + OUTPUT ${MO_FILE_PATH} + COMMAND ${GETTEXT_MSGFMT} -o ${MO_FILE_PATH} ${PO_FILE_PATH} + DEPENDS ${MO_BUILD_PATH} ${PO_FILE_PATH} + WORKING_DIRECTORY "${GETTEXT_PO_PATH}/${LOCALE}" + COMMENT "mo-update [${LOCALE}]: Creating mo file." + ) - set_mo_paths(MO_BUILD_PATH MO_DEST_PATH ${LOCALE}) - add_custom_command(OUTPUT ${MO_BUILD_PATH} - COMMAND ${CMAKE_COMMAND} -E make_directory ${MO_BUILD_PATH} - COMMENT "mo-update [${LOCALE}]: Creating locale directory.") - - set(MO_FILE_PATH "${MO_BUILD_PATH}/minetest.mo") - - add_custom_command( - OUTPUT ${MO_FILE_PATH} - COMMAND ${GETTEXT_MSGFMT} -o ${MO_FILE_PATH} ${PO_FILE_PATH} - DEPENDS ${MO_BUILD_PATH} ${PO_FILE_PATH} - WORKING_DIRECTORY "${GETTEXT_PO_PATH}/${LOCALE}" - COMMENT "mo-update [${LOCALE}]: Creating mo file." - ) - - set(MO_FILES ${MO_FILES} ${MO_FILE_PATH}) - set(PO_FILES ${PO_FILES} ${PO_FILE_PATH}) - endif(NOT LOCALE STREQUAL "en") + set(MO_FILES ${MO_FILES} ${MO_FILE_PATH}) endforeach(LOCALE ${GETTEXT_AVAILABLE_LOCALES}) add_custom_target(translations ALL COMMENT "mo update" DEPENDS ${MO_FILES}) - add_custom_target(updatepo COMMENT "po update" DEPENDS ${PO_FILES}) endif(USE_GETTEXT) # Subdirectories diff --git a/src/client.cpp b/src/client.cpp index 7ebb30fba..4f0baa573 100644 --- a/src/client.cpp +++ b/src/client.cpp @@ -932,7 +932,6 @@ void Client::ProcessData(u8 *data, u32 datasize, u16 sender_peer_id) */ //m_env.getClientMap().updateMeshes(block->getPos(), getDayNightRatio()); - /* Add it to mesh update queue and set it to be acknowledged after update. */ diff --git a/src/cmake_config.h.in b/src/cmake_config.h.in index 5e375191f..7cbb11f6b 100644 --- a/src/cmake_config.h.in +++ b/src/cmake_config.h.in @@ -3,14 +3,16 @@ #ifndef CMAKE_CONFIG_H #define CMAKE_CONFIG_H +#define PROJECT_NAME "@PROJECT_NAME@" #define INSTALL_PREFIX "@CMAKE_INSTALL_PREFIX@" #define VERSION_STRING "@VERSION_STRING@" +#define USE_GETTEXT @USE_GETTEXT@ #ifdef NDEBUG #define BUILD_TYPE "Release" #else #define BUILD_TYPE "Debug" #endif -#define BUILD_INFO "VER="VERSION_STRING" RUN_IN_PLACE=@RUN_IN_PLACE@ INSTALL_PREFIX=@CMAKE_INSTALL_PREFIX@ BUILD_TYPE="BUILD_TYPE +#define BUILD_INFO "VER="VERSION_STRING" RUN_IN_PLACE=@RUN_IN_PLACE@ USE_GETTEXT=@USE_GETTEXT@ INSTALL_PREFIX=@CMAKE_INSTALL_PREFIX@ BUILD_TYPE="BUILD_TYPE #endif diff --git a/src/config.h b/src/config.h index b24cf6a69..54b89a060 100644 --- a/src/config.h +++ b/src/config.h @@ -9,6 +9,8 @@ #ifdef USE_CMAKE_CONFIG_H #include "cmake_config.h" #else + #define PROJECT_NAME "minetest" + //#define INSTALL_PREFIX "" #define VERSION_STRING "unknown" #ifdef NDEBUG @@ -21,8 +23,13 @@ #else #define RUN_IN_PLACE_BOOLSTRING "0" #endif - #define BUILD_INFO "NON-CMAKE RUN_IN_PLACE="RUN_IN_PLACE_BOOLSTRING" BUILD_TYPE="BUILD_TYPE -#endif + #if USE_GETTEXT + #define USE_GETTEXT_BOOLSTRING "1" + #else + #define USE_GETTEXT_BOOLSTRING "0" + #endif + #define BUILD_INFO "NON-CMAKE RUN_IN_PLACE="RUN_IN_PLACE_BOOLSTRING" USE_GETTEXT="USE_GETTEXT_BOOLSTRING" BUILD_TYPE="BUILD_TYPE +#endif #endif diff --git a/src/gettext.h b/src/gettext.h index 8ddb95346..493f9b21b 100644 --- a/src/gettext.h +++ b/src/gettext.h @@ -1,15 +1,23 @@ -#ifdef USE_GETTEXT +#include "config.h" // for USE_GETTEXT + +#if USE_GETTEXT #include <libintl.h> #else #define gettext(String) String -#define bindtextdomain(domain, dir) /* */ -#define textdomain(domain) /* */ #endif #define _(String) gettext(String) #define gettext_noop(String) String #define N_(String) gettext_noop (String) +inline void init_gettext(const char *path) { +#if USE_GETTEXT + setlocale(LC_MESSAGES, ""); + bindtextdomain(PROJECT_NAME, path); + textdomain(PROJECT_NAME); +#endif +} + inline wchar_t* chartowchar_t(const char *str) { size_t l = strlen(str)+1; diff --git a/src/guiPauseMenu.cpp b/src/guiPauseMenu.cpp index c10bcf039..61485518c 100644 --- a/src/guiPauseMenu.cpp +++ b/src/guiPauseMenu.cpp @@ -172,7 +172,7 @@ void GUIPauseMenu::regenerateGui(v2u32 screensize) );*/
std::ostringstream os;
- os<<"Minetest-c55\n";
+ os<<"Minetest-delta\n";
os<<"by Perttu Ahola and contributors\n";
os<<"celeron55@gmail.com\n";
os<<BUILD_INFO<<"\n";
diff --git a/src/keycode.cpp b/src/keycode.cpp index d6472d2ea..f014914d0 100644 --- a/src/keycode.cpp +++ b/src/keycode.cpp @@ -233,4 +233,3 @@ void clearKeyCache() { g_key_setting_cache.clear(); } - diff --git a/src/main.cpp b/src/main.cpp index 09c299004..da17b84bc 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -1161,9 +1161,7 @@ int main(int argc, char *argv[]) // Create user data directory fs::CreateDir(porting::path_userdata); - setlocale(LC_MESSAGES, ""); - bindtextdomain("minetest", (porting::path_userdata+"/locale").c_str()); - textdomain("minetest"); + init_gettext((porting::path_data+"/../locale").c_str()); // Initialize debug streams #ifdef RUN_IN_PLACE @@ -1184,7 +1182,7 @@ int main(int argc, char *argv[]) BEGIN_DEBUG_EXCEPTION_HANDLER // Print startup message - dstream<<DTIME<<"minetest-c55" + dstream<<DTIME<<PROJECT_NAME " with SER_FMT_VER_HIGHEST="<<(int)SER_FMT_VER_HIGHEST <<", "<<BUILD_INFO <<std::endl; diff --git a/src/map.cpp b/src/map.cpp index 830627066..092ce97fd 100644 --- a/src/map.cpp +++ b/src/map.cpp @@ -1540,6 +1540,17 @@ void Map::PrintInfo(std::ostream &out) #define WATER_DROP_BOOST 4 +enum NeighborType { + NEIGHBOR_UPPER, + NEIGHBOR_SAME_LEVEL, + NEIGHBOR_LOWER +}; +struct NodeNeighbor { + MapNode n; + NeighborType t; + v3s16 p; +}; + void Map::transformLiquids(core::map<v3s16, MapBlock*> & modified_blocks) { DSTACK(__FUNCTION_NAME); @@ -1559,240 +1570,220 @@ void Map::transformLiquids(core::map<v3s16, MapBlock*> & modified_blocks) v3s16 p0 = m_transforming_liquid.pop_front(); MapNode n0 = getNodeNoEx(p0); - - // Don't deal with non-liquids - if(content_liquid(n0.getContent()) == false) - continue; - - bool is_source = !content_flowing_liquid(n0.getContent()); - - u8 liquid_level = 8; - if(is_source == false) - liquid_level = n0.param2 & 0x0f; - - // Turn possible source into non-source - u8 nonsource_c = make_liquid_flowing(n0.getContent()); - + /* - If not source, check that some node flows into this one - and what is the level of liquid in this one - */ - if(is_source == false) - { - s8 new_liquid_level_max = -1; - - v3s16 dirs_from[5] = { - v3s16(0,1,0), // top - v3s16(0,0,1), // back - v3s16(1,0,0), // right - v3s16(0,0,-1), // front - v3s16(-1,0,0), // left - }; - for(u16 i=0; i<5; i++) - { - bool from_top = (i==0); - - v3s16 p2 = p0 + dirs_from[i]; - MapNode n2 = getNodeNoEx(p2); - - if(content_liquid(n2.getContent())) - { - u8 n2_nonsource_c = make_liquid_flowing(n2.getContent()); - // Check that the liquids are the same type - if(n2_nonsource_c != nonsource_c) - { - dstream<<"WARNING: Not handling: different liquids" - " collide"<<std::endl; - continue; + Collect information about current node + */ + s8 liquid_level = -1; + u8 liquid_kind = CONTENT_IGNORE; + LiquidType liquid_type = content_features(n0.getContent()).liquid_type; + switch (liquid_type) { + case LIQUID_SOURCE: + liquid_level = 8; + liquid_kind = content_features(n0.getContent()).liquid_alternative_flowing; + break; + case LIQUID_FLOWING: + liquid_level = (n0.param2 & LIQUID_LEVEL_MASK); + liquid_kind = n0.getContent(); + break; + case LIQUID_NONE: + // if this is an air node, it *could* be transformed into a liquid. otherwise, + // continue with the next node. + if (n0.getContent() != CONTENT_AIR) + continue; + liquid_kind = CONTENT_AIR; + break; + } + + /* + Collect information about the environment + */ + v3s16 dirs[6] = { + v3s16( 0, 1, 0), // top + v3s16( 0,-1, 0), // bottom + v3s16( 1, 0, 0), // right + v3s16(-1, 0, 0), // left + v3s16( 0, 0, 1), // back + v3s16( 0, 0,-1), // front + }; + NodeNeighbor sources[6]; // surrounding sources + int num_sources = 0; + NodeNeighbor flows[6]; // surrounding flowing liquid nodes + int num_flows = 0; + NodeNeighbor airs[6]; // surrounding air + int num_airs = 0; + NodeNeighbor neutrals[6]; // nodes that are solid or another kind of liquid + int num_neutrals = 0; + bool flowing_down = false; + for (u16 i = 0; i < 6; i++) { + NeighborType nt = NEIGHBOR_SAME_LEVEL; + switch (i) { + case 0: + nt = NEIGHBOR_UPPER; + break; + case 1: + nt = NEIGHBOR_LOWER; + break; + } + v3s16 npos = p0 + dirs[i]; + NodeNeighbor nb = {getNodeNoEx(npos), nt, npos}; + switch (content_features(nb.n.getContent()).liquid_type) { + case LIQUID_NONE: + if (nb.n.getContent() == CONTENT_AIR) { + airs[num_airs++] = nb; + // if the current node happens to be a flowing node, it will start to flow down here. + if (nb.t == NEIGHBOR_LOWER) + flowing_down = true; + } else { + neutrals[num_neutrals++] = nb; } - bool n2_is_source = !content_flowing_liquid(n2.getContent()); - s8 n2_liquid_level = 8; - if(n2_is_source == false) - n2_liquid_level = n2.param2 & 0x07; - - s8 new_liquid_level = -1; - if(from_top) - { - //new_liquid_level = 7; - if(n2_liquid_level >= 7 - WATER_DROP_BOOST) - new_liquid_level = 7; - else - new_liquid_level = n2_liquid_level + WATER_DROP_BOOST; + break; + case LIQUID_SOURCE: + // if this node is not (yet) of a liquid type, choose the first liquid type we encounter + if (liquid_kind == CONTENT_AIR) + liquid_kind = content_features(nb.n.getContent()).liquid_alternative_flowing; + if (content_features(nb.n.getContent()).liquid_alternative_flowing !=liquid_kind) { + neutrals[num_neutrals++] = nb; + } else { + sources[num_sources++] = nb; } - else if(n2_liquid_level > 0) - { - new_liquid_level = n2_liquid_level - 1; + break; + case LIQUID_FLOWING: + // if this node is not (yet) of a liquid type, choose the first liquid type we encounter + if (liquid_kind == CONTENT_AIR) + liquid_kind = content_features(nb.n.getContent()).liquid_alternative_flowing; + if (content_features(nb.n.getContent()).liquid_alternative_flowing != liquid_kind) { + neutrals[num_neutrals++] = nb; + } else { + flows[num_flows++] = nb; + if (nb.t == NEIGHBOR_LOWER) + flowing_down = true; } - - if(new_liquid_level > new_liquid_level_max) - new_liquid_level_max = new_liquid_level; - } - } //for - - /* - If liquid level should be something else, update it and - add all the neighboring water nodes to the transform queue. - */ - if(new_liquid_level_max != liquid_level) - { - if(new_liquid_level_max == -1) - { - // Remove water alltoghether - n0.setContent(CONTENT_AIR); - n0.param2 = 0; - setNode(p0, n0); - } - else - { - n0.param2 = new_liquid_level_max; - setNode(p0, n0); - } - - // Block has been modified - { - v3s16 blockpos = getNodeBlockPos(p0); - MapBlock *block = getBlockNoCreateNoEx(blockpos); - if(block != NULL) - modified_blocks.insert(blockpos, block); + break; + } + } + + /* + decide on the type (and possibly level) of the current node + */ + u8 new_node_content; + s8 new_node_level = -1; + if (num_sources >= 2 || liquid_type == LIQUID_SOURCE) { + // liquid_kind will be set to either the flowing alternative of the node (if it's a liquid) + // or the flowing alternative of the first of the surrounding sources (if it's air), so + // it's perfectly safe to use liquid_kind here to determine the new node content. + new_node_content = content_features(liquid_kind).liquid_alternative_source; + } else if (num_sources == 1 && sources[0].t != NEIGHBOR_LOWER) { + // liquid_kind is set properly, see above + new_node_content = liquid_kind; + new_node_level = 7; + } else { + // no surrounding sources, so get the maximum level that can flow into this node + for (u16 i = 0; i < num_flows; i++) { + u8 nb_liquid_level = (flows[i].n.param2 & LIQUID_LEVEL_MASK); + switch (flows[i].t) { + case NEIGHBOR_UPPER: + if (nb_liquid_level + WATER_DROP_BOOST > new_node_level) { + new_node_level = 7; + if (nb_liquid_level + WATER_DROP_BOOST < 7) + new_node_level = nb_liquid_level + WATER_DROP_BOOST; + } + break; + case NEIGHBOR_LOWER: + break; + case NEIGHBOR_SAME_LEVEL: + if ((flows[i].n.param2 & LIQUID_FLOW_DOWN_MASK) != LIQUID_FLOW_DOWN_MASK && + nb_liquid_level > 0 && nb_liquid_level - 1 > new_node_level) { + new_node_level = nb_liquid_level - 1; + } + break; } - - /* - Add neighboring non-source liquid nodes to transform queue. - */ - v3s16 dirs[6] = { - v3s16(0,0,1), // back - v3s16(0,1,0), // top - v3s16(1,0,0), // right - v3s16(0,0,-1), // front - v3s16(0,-1,0), // bottom - v3s16(-1,0,0), // left - }; - for(u16 i=0; i<6; i++) - { - v3s16 p2 = p0 + dirs[i]; - - MapNode n2 = getNodeNoEx(p2); - if(content_flowing_liquid(n2.getContent())) - { - m_transforming_liquid.push_back(p2); + } + // don't flow as far in open terrain - if there isn't at least one adjacent solid block, + // substract another unit from the resulting water level. + if (!flowing_down && new_node_level >= 1) { + bool at_wall = false; + for (u16 i = 0; i < num_neutrals; i++) { + if (neutrals[i].t == NEIGHBOR_SAME_LEVEL) { + at_wall = true; + break; } } + if (!at_wall) + new_node_level -= 1; } + + if (new_node_level >= 0) + new_node_content = liquid_kind; + else + new_node_content = CONTENT_AIR; } - - // Get a new one from queue if the node has turned into non-water - if(content_liquid(n0.getContent()) == false) + + /* + check if anything has changed. if not, just continue with the next node. + */ + if (new_node_content == n0.getContent() && (content_features(n0.getContent()).liquid_type != LIQUID_FLOWING || + ((n0.param2 & LIQUID_LEVEL_MASK) == (u8)new_node_level && + ((n0.param2 & LIQUID_FLOW_DOWN_MASK) == LIQUID_FLOW_DOWN_MASK) + == flowing_down))) continue; - + + /* - Flow water from this node - */ - v3s16 dirs_to[5] = { - v3s16(0,-1,0), // bottom - v3s16(0,0,1), // back - v3s16(1,0,0), // right - v3s16(0,0,-1), // front - v3s16(-1,0,0), // left - }; - for(u16 i=0; i<5; i++) - { - bool to_bottom = (i == 0); - - // If liquid is at lowest possible height, it's not going - // anywhere except down - if(liquid_level == 0 && to_bottom == false) - continue; - - u8 liquid_next_level = 0; - // If going to bottom - if(to_bottom) - { - //liquid_next_level = 7; - if(liquid_level >= 7 - WATER_DROP_BOOST) - liquid_next_level = 7; - else - liquid_next_level = liquid_level + WATER_DROP_BOOST; - } - else - liquid_next_level = liquid_level - 1; - - bool n2_changed = false; - bool flowed = false; - - v3s16 p2 = p0 + dirs_to[i]; - - MapNode n2 = getNodeNoEx(p2); - //dstream<<"[1] n2.param="<<(int)n2.param<<std::endl; - - if(content_liquid(n2.getContent())) - { - u8 n2_nonsource_c = make_liquid_flowing(n2.getContent()); - // Check that the liquids are the same type - if(n2_nonsource_c != nonsource_c) - { - dstream<<"WARNING: Not handling: different liquids" - " collide"<<std::endl; - continue; - } - bool n2_is_source = !content_flowing_liquid(n2.getContent()); - u8 n2_liquid_level = 8; - if(n2_is_source == false) - n2_liquid_level = n2.param2 & 0x07; - - if(to_bottom) - { - flowed = true; - } - - if(n2_is_source) - { - // Just flow into the source, nothing changes. - // n2_changed is not set because destination didn't change - flowed = true; + update the current node + */ + bool flow_down_enabled = (flowing_down && ((n0.param2 & LIQUID_FLOW_DOWN_MASK) != LIQUID_FLOW_DOWN_MASK)); + n0.setContent(new_node_content); + if (content_features(n0.getContent()).liquid_type == LIQUID_FLOWING) { + // set level to last 3 bits, flowing down bit to 4th bit + n0.param2 = (flowing_down ? LIQUID_FLOW_DOWN_MASK : 0x00) | (new_node_level & LIQUID_LEVEL_MASK); + } else { + n0.param2 = 0; + } + setNode(p0, n0); + v3s16 blockpos = getNodeBlockPos(p0); + MapBlock *block = getBlockNoCreateNoEx(blockpos); + if(block != NULL) + modified_blocks.insert(blockpos, block); + + /* + enqueue neighbors for update if neccessary + */ + switch (content_features(n0.getContent()).liquid_type) { + case LIQUID_SOURCE: + // make sure source flows into all neighboring nodes + for (u16 i = 0; i < num_flows; i++) + if (flows[i].t != NEIGHBOR_UPPER) + m_transforming_liquid.push_back(flows[i].p); + for (u16 i = 0; i < num_airs; i++) + if (airs[i].t != NEIGHBOR_UPPER) + m_transforming_liquid.push_back(airs[i].p); + break; + case LIQUID_NONE: + // this flow has turned to air; neighboring flows might need to do the same + for (u16 i = 0; i < num_flows; i++) + m_transforming_liquid.push_back(flows[i].p); + break; + case LIQUID_FLOWING: + for (u16 i = 0; i < num_flows; i++) { + u8 flow_level = (flows[i].n.param2 & LIQUID_LEVEL_MASK); + // liquid_level is still the ORIGINAL level of this node. + if (flows[i].t != NEIGHBOR_UPPER && ((flow_level < liquid_level || flow_level < new_node_level) || + flow_down_enabled)) + m_transforming_liquid.push_back(flows[i].p); } - else - { - if(liquid_next_level > liquid_level) - { - n2.param2 = liquid_next_level; - setNode(p2, n2); - - n2_changed = true; - flowed = true; - } + for (u16 i = 0; i < num_airs; i++) { + if (airs[i].t != NEIGHBOR_UPPER && (airs[i].t == NEIGHBOR_LOWER || new_node_level > 0)) + m_transforming_liquid.push_back(airs[i].p); } - } - else if(n2.getContent() == CONTENT_AIR) - { - n2.setContent(nonsource_c); - n2.param2 = liquid_next_level; - setNode(p2, n2); - - n2_changed = true; - flowed = true; - } - - //dstream<<"[2] n2.param="<<(int)n2.param<<std::endl; - - if(n2_changed) - { - m_transforming_liquid.push_back(p2); - - v3s16 blockpos = getNodeBlockPos(p2); - MapBlock *block = getBlockNoCreateNoEx(blockpos); - if(block != NULL) - modified_blocks.insert(blockpos, block); - } - - // If n2_changed to bottom, don't flow anywhere else - if(to_bottom && flowed && !is_source) break; } - + loopcount++; //if(loopcount >= 100000) - if(loopcount >= initial_size * 1) + if(loopcount >= initial_size * 10) { break; + } } //dstream<<"Map::transformLiquids(): loopcount="<<loopcount<<std::endl; } diff --git a/src/mapblock.cpp b/src/mapblock.cpp index b7981348c..44ca75ff0 100644 --- a/src/mapblock.cpp +++ b/src/mapblock.cpp @@ -909,10 +909,12 @@ std::string analyze_block(MapBlock *block) else desc<<"is_ug [ ], "; +#ifndef SERVER if(block->getMeshExpired()) desc<<"mesh_exp [X], "; else desc<<"mesh_exp [ ], "; +#endif if(block->getLightingExpired()) desc<<"lighting_exp [X], "; diff --git a/src/mapnode.h b/src/mapnode.h index 956de6852..3cca985bc 100644 --- a/src/mapnode.h +++ b/src/mapnode.h @@ -401,9 +401,16 @@ enum LightBank }; /* + Masks for MapNode.param2 of flowing liquids + */ +#define LIQUID_LEVEL_MASK 0x07 +#define LIQUID_FLOW_DOWN_MASK 0x08 + +/* This is the stuff what the whole world consists of. */ + struct MapNode { /* diff --git a/src/servermain.cpp b/src/servermain.cpp index 146c548c5..b8fb9ba2b 100644 --- a/src/servermain.cpp +++ b/src/servermain.cpp @@ -162,7 +162,7 @@ int main(int argc, char *argv[]) BEGIN_DEBUG_EXCEPTION_HANDLER // Print startup message - dstream<<DTIME<<"minetest-c55" + dstream<<DTIME<<PROJECT_NAME << " with SER_FMT_VER_HIGHEST="<<(int)SER_FMT_VER_HIGHEST <<", "<<BUILD_INFO <<std::endl; diff --git a/util/updatepo.sh b/util/updatepo.sh new file mode 100755 index 000000000..bcfa4c4de --- /dev/null +++ b/util/updatepo.sh @@ -0,0 +1,65 @@ +#!/bin/sh + +# Update/create minetest po files + +# an auxiliary function to abort processing with an optional error +# message +abort() { + test -n "$1" && echo >&2 "$1" + exit 1 +} + +# The po/ directory is assumed to be parallel to the directory where +# this script is. Relative paths are fine for us so we can just +# use the following trick (works both for manual invocations and for +# script found from PATH) +scriptisin="$(dirname "$(which "$0")")" + +# The script is executed from the parent of po/, which is also the +# parent of the script directory and of the src/ directory. +# We go through $scriptisin so that it can be executed from whatever +# directory and still work correctly +cd "$scriptisin/.." + +test -e po || abort "po/ directory not found" +test -d po || abort "po/ is not a directory!" + +# Get a list of the languages we have to update/create + +cd po || abort "couldn't change directory to po!" + +# This assumes that we won't have dirnames with space, which is +# the case for language codes, which are the only subdirs we expect to +# find in po/ anyway. If you put anything else there, you need to suffer +# the consequences of your actions, so we don't do sanity checks +langs="" + +for lang in * ; do + if test ! -d $lang; then + continue + fi + langs="$langs $lang" +done + +# go back +cd .. + +# First thing first, update the .pot template. We place it in the po/ +# directory at the top level. You a recent enough xgettext that supports +# --package-name +potfile=po/minetest.pot +xgettext --package-name=minetest -F -n -o $potfile src/*.cpp src/*.h + +# Now iterate on all languages and create the po file if missing, or update it +# if it exists already +for lang in $langs ; do # note the missing quotes around $langs + pofile=po/$lang/minetest.po + if test -e $pofile; then + echo "[$lang]: updating strings" + msgmerge -F -U $pofile $potfile + else + # This will ask for the translator identity + echo "[$lang]: NEW strings" + msginit -l $lang -o $pofile -i $potfile + fi +done |