From 298bb3d8f7b2e089b7bc2c6ebeb77eae9bf56b88 Mon Sep 17 00:00:00 2001 From: Loic Blot Date: Fri, 19 Mar 2021 18:37:07 +0100 Subject: [PATCH 01/72] Drop irrUString from MT, it's owned by irrlicht now --- src/irrlicht_changes/irrUString.h | 3891 ----------------------------- 1 file changed, 3891 deletions(-) delete mode 100644 src/irrlicht_changes/irrUString.h diff --git a/src/irrlicht_changes/irrUString.h b/src/irrlicht_changes/irrUString.h deleted file mode 100644 index 09172ee6d..000000000 --- a/src/irrlicht_changes/irrUString.h +++ /dev/null @@ -1,3891 +0,0 @@ -/* - Basic Unicode string class for Irrlicht. - Copyright (c) 2009-2011 John Norman - - This software is provided 'as-is', without any express or implied - warranty. In no event will the authors be held liable for any - damages arising from the use of this software. - - Permission is granted to anyone to use this software for any - purpose, including commercial applications, and to alter it and - redistribute it freely, subject to the following restrictions: - - 1. The origin of this software must not be misrepresented; you - must not claim that you wrote the original software. If you use - this software in a product, an acknowledgment in the product - documentation would be appreciated but is not required. - - 2. Altered source versions must be plainly marked as such, and - must not be misrepresented as being the original software. - - 3. This notice may not be removed or altered from any source - distribution. - - The original version of this class can be located at: - http://irrlicht.suckerfreegames.com/ - - John Norman - john@suckerfreegames.com -*/ - -#pragma once - -#if (__cplusplus > 199711L) || (_MSC_VER >= 1600) || defined(__GXX_EXPERIMENTAL_CXX0X__) -# define USTRING_CPP0X -# if defined(__GXX_EXPERIMENTAL_CXX0X__) && ((__GNUC__ > 4) || ((__GNUC__ == 4) && (__GNUC_MINOR__ >= 5))) -# define USTRING_CPP0X_NEWLITERALS -# endif -#endif - -#include -#include -#include -#include - -#ifdef _WIN32 -#define __BYTE_ORDER 0 -#define __LITTLE_ENDIAN 0 -#define __BIG_ENDIAN 1 -#elif defined(__MACH__) && defined(__APPLE__) -#include -#elif defined(__FreeBSD__) || defined(__DragonFly__) -#include -#else -#include -#endif - -#ifdef USTRING_CPP0X -# include -#endif - -#ifndef USTRING_NO_STL -# include -# include -# include -#endif - -#include "irrTypes.h" -#include "irrAllocator.h" -#include "irrArray.h" -#include "irrMath.h" -#include "irrString.h" -#include "path.h" - -//! UTF-16 surrogate start values. -static const irr::u16 UTF16_HI_SURROGATE = 0xD800; -static const irr::u16 UTF16_LO_SURROGATE = 0xDC00; - -//! Is a UTF-16 code point a surrogate? -#define UTF16_IS_SURROGATE(c) (((c) & 0xF800) == 0xD800) -#define UTF16_IS_SURROGATE_HI(c) (((c) & 0xFC00) == 0xD800) -#define UTF16_IS_SURROGATE_LO(c) (((c) & 0xFC00) == 0xDC00) - - -namespace irr -{ - - // Define our character types. -#ifdef USTRING_CPP0X_NEWLITERALS // C++0x - typedef char32_t uchar32_t; - typedef char16_t uchar16_t; - typedef char uchar8_t; -#else - typedef u32 uchar32_t; - typedef u16 uchar16_t; - typedef u8 uchar8_t; -#endif - -namespace core -{ - -namespace unicode -{ - -//! The unicode replacement character. Used to replace invalid characters. -const irr::u16 UTF_REPLACEMENT_CHARACTER = 0xFFFD; - -//! Convert a UTF-16 surrogate pair into a UTF-32 character. -//! \param high The high value of the pair. -//! \param low The low value of the pair. -//! \return The UTF-32 character expressed by the surrogate pair. -inline uchar32_t toUTF32(uchar16_t high, uchar16_t low) -{ - // Convert the surrogate pair into a single UTF-32 character. - uchar32_t x = ((high & ((1 << 6) -1)) << 10) | (low & ((1 << 10) -1)); - uchar32_t wu = ((high >> 6) & ((1 << 5) - 1)) + 1; - return (wu << 16) | x; -} - -//! Swaps the endianness of a 16-bit value. -//! \return The new value. -inline uchar16_t swapEndian16(const uchar16_t& c) -{ - return ((c >> 8) & 0x00FF) | ((c << 8) & 0xFF00); -} - -//! Swaps the endianness of a 32-bit value. -//! \return The new value. -inline uchar32_t swapEndian32(const uchar32_t& c) -{ - return ((c >> 24) & 0x000000FF) | - ((c >> 8) & 0x0000FF00) | - ((c << 8) & 0x00FF0000) | - ((c << 24) & 0xFF000000); -} - -//! The Unicode byte order mark. -const u16 BOM = 0xFEFF; - -//! The size of the Unicode byte order mark in terms of the Unicode character size. -const u8 BOM_UTF8_LEN = 3; -const u8 BOM_UTF16_LEN = 1; -const u8 BOM_UTF32_LEN = 1; - -//! Unicode byte order marks for file operations. -const u8 BOM_ENCODE_UTF8[3] = { 0xEF, 0xBB, 0xBF }; -const u8 BOM_ENCODE_UTF16_BE[2] = { 0xFE, 0xFF }; -const u8 BOM_ENCODE_UTF16_LE[2] = { 0xFF, 0xFE }; -const u8 BOM_ENCODE_UTF32_BE[4] = { 0x00, 0x00, 0xFE, 0xFF }; -const u8 BOM_ENCODE_UTF32_LE[4] = { 0xFF, 0xFE, 0x00, 0x00 }; - -//! The size in bytes of the Unicode byte marks for file operations. -const u8 BOM_ENCODE_UTF8_LEN = 3; -const u8 BOM_ENCODE_UTF16_LEN = 2; -const u8 BOM_ENCODE_UTF32_LEN = 4; - -//! Unicode encoding type. -enum EUTF_ENCODE -{ - EUTFE_NONE = 0, - EUTFE_UTF8, - EUTFE_UTF16, - EUTFE_UTF16_LE, - EUTFE_UTF16_BE, - EUTFE_UTF32, - EUTFE_UTF32_LE, - EUTFE_UTF32_BE -}; - -//! Unicode endianness. -enum EUTF_ENDIAN -{ - EUTFEE_NATIVE = 0, - EUTFEE_LITTLE, - EUTFEE_BIG -}; - -//! Returns the specified unicode byte order mark in a byte array. -//! The byte order mark is the first few bytes in a text file that signifies its encoding. -/** \param mode The Unicode encoding method that we want to get the byte order mark for. - If EUTFE_UTF16 or EUTFE_UTF32 is passed, it uses the native system endianness. **/ -//! \return An array that contains a byte order mark. -inline core::array getUnicodeBOM(EUTF_ENCODE mode) -{ -#define COPY_ARRAY(source, size) \ - memcpy(ret.pointer(), source, size); \ - ret.set_used(size) - - core::array ret(4); - switch (mode) - { - case EUTFE_UTF8: - COPY_ARRAY(BOM_ENCODE_UTF8, BOM_ENCODE_UTF8_LEN); - break; - case EUTFE_UTF16: - #ifdef __BIG_ENDIAN__ - COPY_ARRAY(BOM_ENCODE_UTF16_BE, BOM_ENCODE_UTF16_LEN); - #else - COPY_ARRAY(BOM_ENCODE_UTF16_LE, BOM_ENCODE_UTF16_LEN); - #endif - break; - case EUTFE_UTF16_BE: - COPY_ARRAY(BOM_ENCODE_UTF16_BE, BOM_ENCODE_UTF16_LEN); - break; - case EUTFE_UTF16_LE: - COPY_ARRAY(BOM_ENCODE_UTF16_LE, BOM_ENCODE_UTF16_LEN); - break; - case EUTFE_UTF32: - #ifdef __BIG_ENDIAN__ - COPY_ARRAY(BOM_ENCODE_UTF32_BE, BOM_ENCODE_UTF32_LEN); - #else - COPY_ARRAY(BOM_ENCODE_UTF32_LE, BOM_ENCODE_UTF32_LEN); - #endif - break; - case EUTFE_UTF32_BE: - COPY_ARRAY(BOM_ENCODE_UTF32_BE, BOM_ENCODE_UTF32_LEN); - break; - case EUTFE_UTF32_LE: - COPY_ARRAY(BOM_ENCODE_UTF32_LE, BOM_ENCODE_UTF32_LEN); - break; - case EUTFE_NONE: - // TODO sapier: fixed warning only, - // don't know if something needs to be done here - break; - } - return ret; - -#undef COPY_ARRAY -} - -//! Detects if the given data stream starts with a unicode BOM. -//! \param data The data stream to check. -//! \return The unicode BOM associated with the data stream, or EUTFE_NONE if none was found. -inline EUTF_ENCODE determineUnicodeBOM(const char* data) -{ - if (memcmp(data, BOM_ENCODE_UTF8, 3) == 0) return EUTFE_UTF8; - if (memcmp(data, BOM_ENCODE_UTF16_BE, 2) == 0) return EUTFE_UTF16_BE; - if (memcmp(data, BOM_ENCODE_UTF16_LE, 2) == 0) return EUTFE_UTF16_LE; - if (memcmp(data, BOM_ENCODE_UTF32_BE, 4) == 0) return EUTFE_UTF32_BE; - if (memcmp(data, BOM_ENCODE_UTF32_LE, 4) == 0) return EUTFE_UTF32_LE; - return EUTFE_NONE; -} - -} // end namespace unicode - - -//! UTF-16 string class. -template > -class ustring16 -{ -public: - - ///------------------/// - /// iterator classes /// - ///------------------/// - - //! Access an element in a unicode string, allowing one to change it. - class _ustring16_iterator_access - { - public: - _ustring16_iterator_access(const ustring16* s, u32 p) : ref(s), pos(p) {} - - //! Allow the class to be interpreted as a single UTF-32 character. - operator uchar32_t() const - { - return _get(); - } - - //! Allow one to change the character in the unicode string. - //! \param c The new character to use. - //! \return Myself. - _ustring16_iterator_access& operator=(const uchar32_t c) - { - _set(c); - return *this; - } - - //! Increments the value by 1. - //! \return Myself. - _ustring16_iterator_access& operator++() - { - _set(_get() + 1); - return *this; - } - - //! Increments the value by 1, returning the old value. - //! \return A unicode character. - uchar32_t operator++(int) - { - uchar32_t old = _get(); - _set(old + 1); - return old; - } - - //! Decrements the value by 1. - //! \return Myself. - _ustring16_iterator_access& operator--() - { - _set(_get() - 1); - return *this; - } - - //! Decrements the value by 1, returning the old value. - //! \return A unicode character. - uchar32_t operator--(int) - { - uchar32_t old = _get(); - _set(old - 1); - return old; - } - - //! Adds to the value by a specified amount. - //! \param val The amount to add to this character. - //! \return Myself. - _ustring16_iterator_access& operator+=(int val) - { - _set(_get() + val); - return *this; - } - - //! Subtracts from the value by a specified amount. - //! \param val The amount to subtract from this character. - //! \return Myself. - _ustring16_iterator_access& operator-=(int val) - { - _set(_get() - val); - return *this; - } - - //! Multiples the value by a specified amount. - //! \param val The amount to multiply this character by. - //! \return Myself. - _ustring16_iterator_access& operator*=(int val) - { - _set(_get() * val); - return *this; - } - - //! Divides the value by a specified amount. - //! \param val The amount to divide this character by. - //! \return Myself. - _ustring16_iterator_access& operator/=(int val) - { - _set(_get() / val); - return *this; - } - - //! Modulos the value by a specified amount. - //! \param val The amount to modulo this character by. - //! \return Myself. - _ustring16_iterator_access& operator%=(int val) - { - _set(_get() % val); - return *this; - } - - //! Adds to the value by a specified amount. - //! \param val The amount to add to this character. - //! \return A unicode character. - uchar32_t operator+(int val) const - { - return _get() + val; - } - - //! Subtracts from the value by a specified amount. - //! \param val The amount to subtract from this character. - //! \return A unicode character. - uchar32_t operator-(int val) const - { - return _get() - val; - } - - //! Multiplies the value by a specified amount. - //! \param val The amount to multiply this character by. - //! \return A unicode character. - uchar32_t operator*(int val) const - { - return _get() * val; - } - - //! Divides the value by a specified amount. - //! \param val The amount to divide this character by. - //! \return A unicode character. - uchar32_t operator/(int val) const - { - return _get() / val; - } - - //! Modulos the value by a specified amount. - //! \param val The amount to modulo this character by. - //! \return A unicode character. - uchar32_t operator%(int val) const - { - return _get() % val; - } - - private: - //! Gets a uchar32_t from our current position. - uchar32_t _get() const - { - const uchar16_t* a = ref->c_str(); - if (!UTF16_IS_SURROGATE(a[pos])) - return static_cast(a[pos]); - else - { - if (pos + 1 >= ref->size_raw()) - return 0; - - return unicode::toUTF32(a[pos], a[pos + 1]); - } - } - - //! Sets a uchar32_t at our current position. - void _set(uchar32_t c) - { - ustring16* ref2 = const_cast*>(ref); - const uchar16_t* a = ref2->c_str(); - if (c > 0xFFFF) - { - // c will be multibyte, so split it up into the high and low surrogate pairs. - uchar16_t x = static_cast(c); - uchar16_t vh = UTF16_HI_SURROGATE | ((((c >> 16) & ((1 << 5) - 1)) - 1) << 6) | (x >> 10); - uchar16_t vl = UTF16_LO_SURROGATE | (x & ((1 << 10) - 1)); - - // If the previous position was a surrogate pair, just replace them. Else, insert the low pair. - if (UTF16_IS_SURROGATE_HI(a[pos]) && pos + 1 != ref2->size_raw()) - ref2->replace_raw(vl, static_cast(pos) + 1); - else ref2->insert_raw(vl, static_cast(pos) + 1); - - ref2->replace_raw(vh, static_cast(pos)); - } - else - { - // c will be a single byte. - uchar16_t vh = static_cast(c); - - // If the previous position was a surrogate pair, remove the extra byte. - if (UTF16_IS_SURROGATE_HI(a[pos])) - ref2->erase_raw(static_cast(pos) + 1); - - ref2->replace_raw(vh, static_cast(pos)); - } - } - - const ustring16* ref; - u32 pos; - }; - typedef typename ustring16::_ustring16_iterator_access access; - - - //! Iterator to iterate through a UTF-16 string. -#ifndef USTRING_NO_STL - class _ustring16_const_iterator : public std::iterator< - std::bidirectional_iterator_tag, // iterator_category - access, // value_type - ptrdiff_t, // difference_type - const access, // pointer - const access // reference - > -#else - class _ustring16_const_iterator -#endif - { - public: - typedef _ustring16_const_iterator _Iter; - typedef std::iterator _Base; - typedef const access const_pointer; - typedef const access const_reference; - -#ifndef USTRING_NO_STL - typedef typename _Base::value_type value_type; - typedef typename _Base::difference_type difference_type; - typedef typename _Base::difference_type distance_type; - typedef typename _Base::pointer pointer; - typedef const_reference reference; -#else - typedef access value_type; - typedef u32 difference_type; - typedef u32 distance_type; - typedef const_pointer pointer; - typedef const_reference reference; -#endif - - //! Constructors. - _ustring16_const_iterator(const _Iter& i) : ref(i.ref), pos(i.pos) {} - _ustring16_const_iterator(const ustring16& s) : ref(&s), pos(0) {} - _ustring16_const_iterator(const ustring16& s, const u32 p) : ref(&s), pos(0) - { - if (ref->size_raw() == 0 || p == 0) - return; - - // Go to the appropriate position. - u32 i = p; - u32 sr = ref->size_raw(); - const uchar16_t* a = ref->c_str(); - while (i != 0 && pos < sr) - { - if (UTF16_IS_SURROGATE_HI(a[pos])) - pos += 2; - else ++pos; - --i; - } - } - - //! Test for equalness. - bool operator==(const _Iter& iter) const - { - if (ref == iter.ref && pos == iter.pos) - return true; - return false; - } - - //! Test for unequalness. - bool operator!=(const _Iter& iter) const - { - if (ref != iter.ref || pos != iter.pos) - return true; - return false; - } - - //! Switch to the next full character in the string. - _Iter& operator++() - { // ++iterator - if (pos == ref->size_raw()) return *this; - const uchar16_t* a = ref->c_str(); - if (UTF16_IS_SURROGATE_HI(a[pos])) - pos += 2; // TODO: check for valid low surrogate? - else ++pos; - if (pos > ref->size_raw()) pos = ref->size_raw(); - return *this; - } - - //! Switch to the next full character in the string, returning the previous position. - _Iter operator++(int) - { // iterator++ - _Iter _tmp(*this); - ++*this; - return _tmp; - } - - //! Switch to the previous full character in the string. - _Iter& operator--() - { // --iterator - if (pos == 0) return *this; - const uchar16_t* a = ref->c_str(); - --pos; - if (UTF16_IS_SURROGATE_LO(a[pos]) && pos != 0) // low surrogate, go back one more. - --pos; - return *this; - } - - //! Switch to the previous full character in the string, returning the previous position. - _Iter operator--(int) - { // iterator-- - _Iter _tmp(*this); - --*this; - return _tmp; - } - - //! Advance a specified number of full characters in the string. - //! \return Myself. - _Iter& operator+=(const difference_type v) - { - if (v == 0) return *this; - if (v < 0) return operator-=(v * -1); - - if (pos >= ref->size_raw()) - return *this; - - // Go to the appropriate position. - // TODO: Don't force u32 on an x64 OS. Make it agnostic. - u32 i = (u32)v; - u32 sr = ref->size_raw(); - const uchar16_t* a = ref->c_str(); - while (i != 0 && pos < sr) - { - if (UTF16_IS_SURROGATE_HI(a[pos])) - pos += 2; - else ++pos; - --i; - } - if (pos > sr) - pos = sr; - - return *this; - } - - //! Go back a specified number of full characters in the string. - //! \return Myself. - _Iter& operator-=(const difference_type v) - { - if (v == 0) return *this; - if (v > 0) return operator+=(v * -1); - - if (pos == 0) - return *this; - - // Go to the appropriate position. - // TODO: Don't force u32 on an x64 OS. Make it agnostic. - u32 i = (u32)v; - const uchar16_t* a = ref->c_str(); - while (i != 0 && pos != 0) - { - --pos; - if (UTF16_IS_SURROGATE_LO(a[pos]) != 0 && pos != 0) - --pos; - --i; - } - - return *this; - } - - //! Return a new iterator that is a variable number of full characters forward from the current position. - _Iter operator+(const difference_type v) const - { - _Iter ret(*this); - ret += v; - return ret; - } - - //! Return a new iterator that is a variable number of full characters backward from the current position. - _Iter operator-(const difference_type v) const - { - _Iter ret(*this); - ret -= v; - return ret; - } - - //! Returns the distance between two iterators. - difference_type operator-(const _Iter& iter) const - { - // Make sure we reference the same object! - if (ref != iter.ref) - return difference_type(); - - _Iter i = iter; - difference_type ret; - - // Walk up. - if (pos > i.pos) - { - while (pos > i.pos) - { - ++i; - ++ret; - } - return ret; - } - - // Walk down. - while (pos < i.pos) - { - --i; - --ret; - } - return ret; - } - - //! Accesses the full character at the iterator's position. - const_reference operator*() const - { - if (pos >= ref->size_raw()) - { - const uchar16_t* a = ref->c_str(); - u32 p = ref->size_raw(); - if (UTF16_IS_SURROGATE_LO(a[p])) - --p; - reference ret(ref, p); - return ret; - } - const_reference ret(ref, pos); - return ret; - } - - //! Accesses the full character at the iterator's position. - reference operator*() - { - if (pos >= ref->size_raw()) - { - const uchar16_t* a = ref->c_str(); - u32 p = ref->size_raw(); - if (UTF16_IS_SURROGATE_LO(a[p])) - --p; - reference ret(ref, p); - return ret; - } - reference ret(ref, pos); - return ret; - } - - //! Accesses the full character at the iterator's position. - const_pointer operator->() const - { - return operator*(); - } - - //! Accesses the full character at the iterator's position. - pointer operator->() - { - return operator*(); - } - - //! Is the iterator at the start of the string? - bool atStart() const - { - return pos == 0; - } - - //! Is the iterator at the end of the string? - bool atEnd() const - { - const uchar16_t* a = ref->c_str(); - if (UTF16_IS_SURROGATE(a[pos])) - return (pos + 1) >= ref->size_raw(); - else return pos >= ref->size_raw(); - } - - //! Moves the iterator to the start of the string. - void toStart() - { - pos = 0; - } - - //! Moves the iterator to the end of the string. - void toEnd() - { - pos = ref->size_raw(); - } - - //! Returns the iterator's position. - //! \return The iterator's position. - u32 getPos() const - { - return pos; - } - - protected: - const ustring16* ref; - u32 pos; - }; - - //! Iterator to iterate through a UTF-16 string. - class _ustring16_iterator : public _ustring16_const_iterator - { - public: - typedef _ustring16_iterator _Iter; - typedef _ustring16_const_iterator _Base; - typedef typename _Base::const_pointer const_pointer; - typedef typename _Base::const_reference const_reference; - - - typedef typename _Base::value_type value_type; - typedef typename _Base::difference_type difference_type; - typedef typename _Base::distance_type distance_type; - typedef access pointer; - typedef access reference; - - using _Base::pos; - using _Base::ref; - - //! Constructors. - _ustring16_iterator(const _Iter& i) : _ustring16_const_iterator(i) {} - _ustring16_iterator(const ustring16& s) : _ustring16_const_iterator(s) {} - _ustring16_iterator(const ustring16& s, const u32 p) : _ustring16_const_iterator(s, p) {} - - //! Accesses the full character at the iterator's position. - reference operator*() const - { - if (pos >= ref->size_raw()) - { - const uchar16_t* a = ref->c_str(); - u32 p = ref->size_raw(); - if (UTF16_IS_SURROGATE_LO(a[p])) - --p; - reference ret(ref, p); - return ret; - } - reference ret(ref, pos); - return ret; - } - - //! Accesses the full character at the iterator's position. - reference operator*() - { - if (pos >= ref->size_raw()) - { - const uchar16_t* a = ref->c_str(); - u32 p = ref->size_raw(); - if (UTF16_IS_SURROGATE_LO(a[p])) - --p; - reference ret(ref, p); - return ret; - } - reference ret(ref, pos); - return ret; - } - - //! Accesses the full character at the iterator's position. - pointer operator->() const - { - return operator*(); - } - - //! Accesses the full character at the iterator's position. - pointer operator->() - { - return operator*(); - } - }; - - typedef typename ustring16::_ustring16_iterator iterator; - typedef typename ustring16::_ustring16_const_iterator const_iterator; - - ///----------------------/// - /// end iterator classes /// - ///----------------------/// - - //! Default constructor - ustring16() - : array(0), allocated(1), used(0) - { -#if __BYTE_ORDER == __BIG_ENDIAN - encoding = unicode::EUTFE_UTF16_BE; -#else - encoding = unicode::EUTFE_UTF16_LE; -#endif - array = allocator.allocate(1); // new u16[1]; - array[0] = 0x0; - } - - - //! Constructor - ustring16(const ustring16& other) - : array(0), allocated(0), used(0) - { -#if __BYTE_ORDER == __BIG_ENDIAN - encoding = unicode::EUTFE_UTF16_BE; -#else - encoding = unicode::EUTFE_UTF16_LE; -#endif - *this = other; - } - - - //! Constructor from other string types - template - ustring16(const string& other) - : array(0), allocated(0), used(0) - { -#if __BYTE_ORDER == __BIG_ENDIAN - encoding = unicode::EUTFE_UTF16_BE; -#else - encoding = unicode::EUTFE_UTF16_LE; -#endif - *this = other; - } - - -#ifndef USTRING_NO_STL - //! Constructor from std::string - template - ustring16(const std::basic_string& other) - : array(0), allocated(0), used(0) - { -#if __BYTE_ORDER == __BIG_ENDIAN - encoding = unicode::EUTFE_UTF16_BE; -#else - encoding = unicode::EUTFE_UTF16_LE; -#endif - *this = other.c_str(); - } - - - //! Constructor from iterator. - template - ustring16(Itr first, Itr last) - : array(0), allocated(0), used(0) - { -#if __BYTE_ORDER == __BIG_ENDIAN - encoding = unicode::EUTFE_UTF16_BE; -#else - encoding = unicode::EUTFE_UTF16_LE; -#endif - reserve(std::distance(first, last)); - array[used] = 0; - - for (; first != last; ++first) - append((uchar32_t)*first); - } -#endif - - -#ifndef USTRING_CPP0X_NEWLITERALS - //! Constructor for copying a character string from a pointer. - ustring16(const char* const c) - : array(0), allocated(0), used(0) - { -#if __BYTE_ORDER == __BIG_ENDIAN - encoding = unicode::EUTFE_UTF16_BE; -#else - encoding = unicode::EUTFE_UTF16_LE; -#endif - - loadDataStream(c, strlen(c)); - //append((uchar8_t*)c); - } - - - //! Constructor for copying a character string from a pointer with a given length. - ustring16(const char* const c, u32 length) - : array(0), allocated(0), used(0) - { -#if __BYTE_ORDER == __BIG_ENDIAN - encoding = unicode::EUTFE_UTF16_BE; -#else - encoding = unicode::EUTFE_UTF16_LE; -#endif - - loadDataStream(c, length); - } -#endif - - - //! Constructor for copying a UTF-8 string from a pointer. - ustring16(const uchar8_t* const c) - : array(0), allocated(0), used(0) - { -#if __BYTE_ORDER == __BIG_ENDIAN - encoding = unicode::EUTFE_UTF16_BE; -#else - encoding = unicode::EUTFE_UTF16_LE; -#endif - - append(c); - } - - - //! Constructor for copying a UTF-8 string from a single char. - ustring16(const char c) - : array(0), allocated(0), used(0) - { -#if __BYTE_ORDER == __BIG_ENDIAN - encoding = unicode::EUTFE_UTF16_BE; -#else - encoding = unicode::EUTFE_UTF16_LE; -#endif - - append((uchar32_t)c); - } - - - //! Constructor for copying a UTF-8 string from a pointer with a given length. - ustring16(const uchar8_t* const c, u32 length) - : array(0), allocated(0), used(0) - { -#if __BYTE_ORDER == __BIG_ENDIAN - encoding = unicode::EUTFE_UTF16_BE; -#else - encoding = unicode::EUTFE_UTF16_LE; -#endif - - append(c, length); - } - - - //! Constructor for copying a UTF-16 string from a pointer. - ustring16(const uchar16_t* const c) - : array(0), allocated(0), used(0) - { -#if __BYTE_ORDER == __BIG_ENDIAN - encoding = unicode::EUTFE_UTF16_BE; -#else - encoding = unicode::EUTFE_UTF16_LE; -#endif - - append(c); - } - - - //! Constructor for copying a UTF-16 string from a pointer with a given length - ustring16(const uchar16_t* const c, u32 length) - : array(0), allocated(0), used(0) - { -#if __BYTE_ORDER == __BIG_ENDIAN - encoding = unicode::EUTFE_UTF16_BE; -#else - encoding = unicode::EUTFE_UTF16_LE; -#endif - - append(c, length); - } - - - //! Constructor for copying a UTF-32 string from a pointer. - ustring16(const uchar32_t* const c) - : array(0), allocated(0), used(0) - { -#if __BYTE_ORDER == __BIG_ENDIAN - encoding = unicode::EUTFE_UTF16_BE; -#else - encoding = unicode::EUTFE_UTF16_LE; -#endif - - append(c); - } - - - //! Constructor for copying a UTF-32 from a pointer with a given length. - ustring16(const uchar32_t* const c, u32 length) - : array(0), allocated(0), used(0) - { -#if __BYTE_ORDER == __BIG_ENDIAN - encoding = unicode::EUTFE_UTF16_BE; -#else - encoding = unicode::EUTFE_UTF16_LE; -#endif - - append(c, length); - } - - - //! Constructor for copying a wchar_t string from a pointer. - ustring16(const wchar_t* const c) - : array(0), allocated(0), used(0) - { -#if __BYTE_ORDER == __BIG_ENDIAN - encoding = unicode::EUTFE_UTF16_BE; -#else - encoding = unicode::EUTFE_UTF16_LE; -#endif - - if (sizeof(wchar_t) == 4) - append(reinterpret_cast(c)); - else if (sizeof(wchar_t) == 2) - append(reinterpret_cast(c)); - else if (sizeof(wchar_t) == 1) - append(reinterpret_cast(c)); - } - - - //! Constructor for copying a wchar_t string from a pointer with a given length. - ustring16(const wchar_t* const c, u32 length) - : array(0), allocated(0), used(0) - { -#if __BYTE_ORDER == __BIG_ENDIAN - encoding = unicode::EUTFE_UTF16_BE; -#else - encoding = unicode::EUTFE_UTF16_LE; -#endif - - if (sizeof(wchar_t) == 4) - append(reinterpret_cast(c), length); - else if (sizeof(wchar_t) == 2) - append(reinterpret_cast(c), length); - else if (sizeof(wchar_t) == 1) - append(reinterpret_cast(c), length); - } - - -#ifdef USTRING_CPP0X - //! Constructor for moving a ustring16 - ustring16(ustring16&& other) - : array(other.array), encoding(other.encoding), allocated(other.allocated), used(other.used) - { - //std::cout << "MOVE constructor" << std::endl; - other.array = 0; - other.allocated = 0; - other.used = 0; - } -#endif - - - //! Destructor - ~ustring16() - { - allocator.deallocate(array); // delete [] array; - } - - - //! Assignment operator - ustring16& operator=(const ustring16& other) - { - if (this == &other) - return *this; - - used = other.size_raw(); - if (used >= allocated) - { - allocator.deallocate(array); // delete [] array; - allocated = used + 1; - array = allocator.allocate(used + 1); //new u16[used]; - } - - const uchar16_t* p = other.c_str(); - for (u32 i=0; i<=used; ++i, ++p) - array[i] = *p; - - array[used] = 0; - - // Validate our new UTF-16 string. - validate(); - - return *this; - } - - -#ifdef USTRING_CPP0X - //! Move assignment operator - ustring16& operator=(ustring16&& other) - { - if (this != &other) - { - //std::cout << "MOVE operator=" << std::endl; - allocator.deallocate(array); - - array = other.array; - allocated = other.allocated; - encoding = other.encoding; - used = other.used; - other.array = 0; - other.used = 0; - } - return *this; - } -#endif - - - //! Assignment operator for other string types - template - ustring16& operator=(const string& other) - { - *this = other.c_str(); - return *this; - } - - - //! Assignment operator for UTF-8 strings - ustring16& operator=(const uchar8_t* const c) - { - if (!array) - { - array = allocator.allocate(1); //new u16[1]; - allocated = 1; - } - used = 0; - array[used] = 0x0; - if (!c) return *this; - - //! Append our string now. - append(c); - return *this; - } - - - //! Assignment operator for UTF-16 strings - ustring16& operator=(const uchar16_t* const c) - { - if (!array) - { - array = allocator.allocate(1); //new u16[1]; - allocated = 1; - } - used = 0; - array[used] = 0x0; - if (!c) return *this; - - //! Append our string now. - append(c); - return *this; - } - - - //! Assignment operator for UTF-32 strings - ustring16& operator=(const uchar32_t* const c) - { - if (!array) - { - array = allocator.allocate(1); //new u16[1]; - allocated = 1; - } - used = 0; - array[used] = 0x0; - if (!c) return *this; - - //! Append our string now. - append(c); - return *this; - } - - - //! Assignment operator for wchar_t strings. - /** Note that this assumes that a correct unicode string is stored in the wchar_t string. - Since wchar_t changes depending on its platform, it could either be a UTF-8, -16, or -32 string. - This function assumes you are storing the correct unicode encoding inside the wchar_t string. **/ - ustring16& operator=(const wchar_t* const c) - { - if (sizeof(wchar_t) == 4) - *this = reinterpret_cast(c); - else if (sizeof(wchar_t) == 2) - *this = reinterpret_cast(c); - else if (sizeof(wchar_t) == 1) - *this = reinterpret_cast(c); - - return *this; - } - - - //! Assignment operator for other strings. - /** Note that this assumes that a correct unicode string is stored in the string. **/ - template - ustring16& operator=(const B* const c) - { - if (sizeof(B) == 4) - *this = reinterpret_cast(c); - else if (sizeof(B) == 2) - *this = reinterpret_cast(c); - else if (sizeof(B) == 1) - *this = reinterpret_cast(c); - - return *this; - } - - - //! Direct access operator - access operator [](const u32 index) - { - _IRR_DEBUG_BREAK_IF(index>=size()) // bad index - iterator iter(*this, index); - return iter.operator*(); - } - - - //! Direct access operator - const access operator [](const u32 index) const - { - _IRR_DEBUG_BREAK_IF(index>=size()) // bad index - const_iterator iter(*this, index); - return iter.operator*(); - } - - - //! Equality operator - bool operator ==(const uchar16_t* const str) const - { - if (!str) - return false; - - u32 i; - for(i=0; array[i] && str[i]; ++i) - if (array[i] != str[i]) - return false; - - return !array[i] && !str[i]; - } - - - //! Equality operator - bool operator ==(const ustring16& other) const - { - for(u32 i=0; array[i] && other.array[i]; ++i) - if (array[i] != other.array[i]) - return false; - - return used == other.used; - } - - - //! Is smaller comparator - bool operator <(const ustring16& other) const - { - for(u32 i=0; array[i] && other.array[i]; ++i) - { - s32 diff = array[i] - other.array[i]; - if ( diff ) - return diff < 0; - } - - return used < other.used; - } - - - //! Inequality operator - bool operator !=(const uchar16_t* const str) const - { - return !(*this == str); - } - - - //! Inequality operator - bool operator !=(const ustring16& other) const - { - return !(*this == other); - } - - - //! Returns the length of a ustring16 in full characters. - //! \return Length of a ustring16 in full characters. - u32 size() const - { - const_iterator i(*this, 0); - u32 pos = 0; - while (!i.atEnd()) - { - ++i; - ++pos; - } - return pos; - } - - - //! Informs if the ustring is empty or not. - //! \return True if the ustring is empty, false if not. - bool empty() const - { - return (size_raw() == 0); - } - - - //! Returns a pointer to the raw UTF-16 string data. - //! \return pointer to C-style NUL terminated array of UTF-16 code points. - const uchar16_t* c_str() const - { - return array; - } - - - //! Compares the first n characters of this string with another. - //! \param other Other string to compare to. - //! \param n Number of characters to compare. - //! \return True if the n first characters of both strings are equal. - bool equalsn(const ustring16& other, u32 n) const - { - u32 i; - const uchar16_t* oa = other.c_str(); - for(i=0; i < n && array[i] && oa[i]; ++i) - if (array[i] != oa[i]) - return false; - - // if one (or both) of the strings was smaller then they - // are only equal if they have the same length - return (i == n) || (used == other.used); - } - - - //! Compares the first n characters of this string with another. - //! \param str Other string to compare to. - //! \param n Number of characters to compare. - //! \return True if the n first characters of both strings are equal. - bool equalsn(const uchar16_t* const str, u32 n) const - { - if (!str) - return false; - u32 i; - for(i=0; i < n && array[i] && str[i]; ++i) - if (array[i] != str[i]) - return false; - - // if one (or both) of the strings was smaller then they - // are only equal if they have the same length - return (i == n) || (array[i] == 0 && str[i] == 0); - } - - - //! Appends a character to this ustring16 - //! \param character The character to append. - //! \return A reference to our current string. - ustring16& append(uchar32_t character) - { - if (used + 2 >= allocated) - reallocate(used + 2); - - if (character > 0xFFFF) - { - used += 2; - - // character will be multibyte, so split it up into a surrogate pair. - uchar16_t x = static_cast(character); - uchar16_t vh = UTF16_HI_SURROGATE | ((((character >> 16) & ((1 << 5) - 1)) - 1) << 6) | (x >> 10); - uchar16_t vl = UTF16_LO_SURROGATE | (x & ((1 << 10) - 1)); - array[used-2] = vh; - array[used-1] = vl; - } - else - { - ++used; - array[used-1] = character; - } - array[used] = 0; - - return *this; - } - - - //! Appends a UTF-8 string to this ustring16 - //! \param other The UTF-8 string to append. - //! \param length The length of the string to append. - //! \return A reference to our current string. - ustring16& append(const uchar8_t* const other, u32 length=0xffffffff) - { - if (!other) - return *this; - - // Determine if the string is long enough for a BOM. - u32 len = 0; - const uchar8_t* p = other; - do - { - ++len; - } while (*p++ && len < unicode::BOM_ENCODE_UTF8_LEN); - - // Check for BOM. - unicode::EUTF_ENCODE c_bom = unicode::EUTFE_NONE; - if (len == unicode::BOM_ENCODE_UTF8_LEN) - { - if (memcmp(other, unicode::BOM_ENCODE_UTF8, unicode::BOM_ENCODE_UTF8_LEN) == 0) - c_bom = unicode::EUTFE_UTF8; - } - - // If a BOM was found, don't include it in the string. - const uchar8_t* c2 = other; - if (c_bom != unicode::EUTFE_NONE) - { - c2 = other + unicode::BOM_UTF8_LEN; - length -= unicode::BOM_UTF8_LEN; - } - - // Calculate the size of the string to read in. - len = 0; - p = c2; - do - { - ++len; - } while(*p++ && len < length); - if (len > length) - len = length; - - // If we need to grow the array, do it now. - if (used + len >= allocated) - reallocate(used + (len * 2)); - u32 start = used; - - // Convert UTF-8 to UTF-16. - u32 pos = start; - for (u32 l = 0; l> 6) & 0x03) == 0x02) - { // Invalid continuation byte. - array[pos++] = unicode::UTF_REPLACEMENT_CHARACTER; - ++l; - } - else if (c2[l] == 0xC0 || c2[l] == 0xC1) - { // Invalid byte - overlong encoding. - array[pos++] = unicode::UTF_REPLACEMENT_CHARACTER; - ++l; - } - else if ((c2[l] & 0xF8) == 0xF0) - { // 4 bytes UTF-8, 2 bytes UTF-16. - // Check for a full string. - if ((l + 3) >= len) - { - array[pos++] = unicode::UTF_REPLACEMENT_CHARACTER; - l += 3; - break; - } - - // Validate. - bool valid = true; - u8 l2 = 0; - if (valid && (((c2[l+1] >> 6) & 0x03) == 0x02)) ++l2; else valid = false; - if (valid && (((c2[l+2] >> 6) & 0x03) == 0x02)) ++l2; else valid = false; - if (valid && (((c2[l+3] >> 6) & 0x03) == 0x02)) ++l2; else valid = false; - if (!valid) - { - array[pos++] = unicode::UTF_REPLACEMENT_CHARACTER; - l += l2; - continue; - } - - // Decode. - uchar8_t b1 = ((c2[l] & 0x7) << 2) | ((c2[l+1] >> 4) & 0x3); - uchar8_t b2 = ((c2[l+1] & 0xF) << 4) | ((c2[l+2] >> 2) & 0xF); - uchar8_t b3 = ((c2[l+2] & 0x3) << 6) | (c2[l+3] & 0x3F); - uchar32_t v = b3 | ((uchar32_t)b2 << 8) | ((uchar32_t)b1 << 16); - - // Split v up into a surrogate pair. - uchar16_t x = static_cast(v); - uchar16_t vh = UTF16_HI_SURROGATE | ((((v >> 16) & ((1 << 5) - 1)) - 1) << 6) | (x >> 10); - uchar16_t vl = UTF16_LO_SURROGATE | (x & ((1 << 10) - 1)); - - array[pos++] = vh; - array[pos++] = vl; - l += 4; - ++used; // Using two shorts this time, so increase used by 1. - } - else if ((c2[l] & 0xF0) == 0xE0) - { // 3 bytes UTF-8, 1 byte UTF-16. - // Check for a full string. - if ((l + 2) >= len) - { - array[pos++] = unicode::UTF_REPLACEMENT_CHARACTER; - l += 2; - break; - } - - // Validate. - bool valid = true; - u8 l2 = 0; - if (valid && (((c2[l+1] >> 6) & 0x03) == 0x02)) ++l2; else valid = false; - if (valid && (((c2[l+2] >> 6) & 0x03) == 0x02)) ++l2; else valid = false; - if (!valid) - { - array[pos++] = unicode::UTF_REPLACEMENT_CHARACTER; - l += l2; - continue; - } - - // Decode. - uchar8_t b1 = ((c2[l] & 0xF) << 4) | ((c2[l+1] >> 2) & 0xF); - uchar8_t b2 = ((c2[l+1] & 0x3) << 6) | (c2[l+2] & 0x3F); - uchar16_t ch = b2 | ((uchar16_t)b1 << 8); - array[pos++] = ch; - l += 3; - } - else if ((c2[l] & 0xE0) == 0xC0) - { // 2 bytes UTF-8, 1 byte UTF-16. - // Check for a full string. - if ((l + 1) >= len) - { - array[pos++] = unicode::UTF_REPLACEMENT_CHARACTER; - l += 1; - break; - } - - // Validate. - if (((c2[l+1] >> 6) & 0x03) != 0x02) - { - array[pos++] = unicode::UTF_REPLACEMENT_CHARACTER; - ++l; - continue; - } - - // Decode. - uchar8_t b1 = (c2[l] >> 2) & 0x7; - uchar8_t b2 = ((c2[l] & 0x3) << 6) | (c2[l+1] & 0x3F); - uchar16_t ch = b2 | ((uchar16_t)b1 << 8); - array[pos++] = ch; - l += 2; - } - else - { // 1 byte UTF-8, 1 byte UTF-16. - // Validate. - if (c2[l] > 0x7F) - { // Values above 0xF4 are restricted and aren't used. By now, anything above 0x7F is invalid. - array[pos++] = unicode::UTF_REPLACEMENT_CHARACTER; - } - else array[pos++] = static_cast(c2[l]); - ++l; - } - } - array[used] = 0; - - // Validate our new UTF-16 string. - validate(); - - return *this; - } - - - //! Appends a UTF-16 string to this ustring16 - //! \param other The UTF-16 string to append. - //! \param length The length of the string to append. - //! \return A reference to our current string. - ustring16& append(const uchar16_t* const other, u32 length=0xffffffff) - { - if (!other) - return *this; - - // Determine if the string is long enough for a BOM. - u32 len = 0; - const uchar16_t* p = other; - do - { - ++len; - } while (*p++ && len < unicode::BOM_ENCODE_UTF16_LEN); - - // Check for the BOM to determine the string's endianness. - unicode::EUTF_ENDIAN c_end = unicode::EUTFEE_NATIVE; - if (memcmp(other, unicode::BOM_ENCODE_UTF16_LE, unicode::BOM_ENCODE_UTF16_LEN) == 0) - c_end = unicode::EUTFEE_LITTLE; - else if (memcmp(other, unicode::BOM_ENCODE_UTF16_BE, unicode::BOM_ENCODE_UTF16_LEN) == 0) - c_end = unicode::EUTFEE_BIG; - - // If a BOM was found, don't include it in the string. - const uchar16_t* c2 = other; - if (c_end != unicode::EUTFEE_NATIVE) - { - c2 = other + unicode::BOM_UTF16_LEN; - length -= unicode::BOM_UTF16_LEN; - } - - // Calculate the size of the string to read in. - len = 0; - p = c2; - do - { - ++len; - } while(*p++ && len < length); - if (len > length) - len = length; - - // If we need to grow the size of the array, do it now. - if (used + len >= allocated) - reallocate(used + (len * 2)); - u32 start = used; - used += len; - - // Copy the string now. - unicode::EUTF_ENDIAN m_end = getEndianness(); - for (u32 l = start; l < start + len; ++l) - { - array[l] = (uchar16_t)c2[l]; - if (c_end != unicode::EUTFEE_NATIVE && c_end != m_end) - array[l] = unicode::swapEndian16(array[l]); - } - - array[used] = 0; - - // Validate our new UTF-16 string. - validate(); - return *this; - } - - - //! Appends a UTF-32 string to this ustring16 - //! \param other The UTF-32 string to append. - //! \param length The length of the string to append. - //! \return A reference to our current string. - ustring16& append(const uchar32_t* const other, u32 length=0xffffffff) - { - if (!other) - return *this; - - // Check for the BOM to determine the string's endianness. - unicode::EUTF_ENDIAN c_end = unicode::EUTFEE_NATIVE; - if (memcmp(other, unicode::BOM_ENCODE_UTF32_LE, unicode::BOM_ENCODE_UTF32_LEN) == 0) - c_end = unicode::EUTFEE_LITTLE; - else if (memcmp(other, unicode::BOM_ENCODE_UTF32_BE, unicode::BOM_ENCODE_UTF32_LEN) == 0) - c_end = unicode::EUTFEE_BIG; - - // If a BOM was found, don't include it in the string. - const uchar32_t* c2 = other; - if (c_end != unicode::EUTFEE_NATIVE) - { - c2 = other + unicode::BOM_UTF32_LEN; - length -= unicode::BOM_UTF32_LEN; - } - - // Calculate the size of the string to read in. - u32 len = 0; - const uchar32_t* p = c2; - do - { - ++len; - } while(*p++ && len < length); - if (len > length) - len = length; - - // If we need to grow the size of the array, do it now. - // In case all of the UTF-32 string is split into surrogate pairs, do len * 2. - if (used + (len * 2) >= allocated) - reallocate(used + ((len * 2) * 2)); - u32 start = used; - - // Convert UTF-32 to UTF-16. - unicode::EUTF_ENDIAN m_end = getEndianness(); - u32 pos = start; - for (u32 l = 0; l 0xFFFF) - { - // Split ch up into a surrogate pair as it is over 16 bits long. - uchar16_t x = static_cast(ch); - uchar16_t vh = UTF16_HI_SURROGATE | ((((ch >> 16) & ((1 << 5) - 1)) - 1) << 6) | (x >> 10); - uchar16_t vl = UTF16_LO_SURROGATE | (x & ((1 << 10) - 1)); - array[pos++] = vh; - array[pos++] = vl; - ++used; // Using two shorts, so increased used again. - } - else if (ch >= 0xD800 && ch <= 0xDFFF) - { - // Between possible UTF-16 surrogates (invalid!) - array[pos++] = unicode::UTF_REPLACEMENT_CHARACTER; - } - else array[pos++] = static_cast(ch); - } - array[used] = 0; - - // Validate our new UTF-16 string. - validate(); - - return *this; - } - - - //! Appends a ustring16 to this ustring16 - //! \param other The string to append to this one. - //! \return A reference to our current string. - ustring16& append(const ustring16& other) - { - const uchar16_t* oa = other.c_str(); - - u32 len = other.size_raw(); - - if (used + len >= allocated) - reallocate(used + len); - - for (u32 l=0; l& append(const ustring16& other, u32 length) - { - if (other.size() == 0) - return *this; - - if (other.size() < length) - { - append(other); - return *this; - } - - if (used + length * 2 >= allocated) - reallocate(used + length * 2); - - const_iterator iter(other, 0); - u32 l = length; - while (!iter.atEnd() && l) - { - uchar32_t c = *iter; - append(c); - ++iter; - --l; - } - - return *this; - } - - - //! Reserves some memory. - //! \param count The amount of characters to reserve. - void reserve(u32 count) - { - if (count < allocated) - return; - - reallocate(count); - } - - - //! Finds first occurrence of character. - //! \param c The character to search for. - //! \return Position where the character has been found, or -1 if not found. - s32 findFirst(uchar32_t c) const - { - const_iterator i(*this, 0); - - s32 pos = 0; - while (!i.atEnd()) - { - uchar32_t t = *i; - if (c == t) - return pos; - ++pos; - ++i; - } - - return -1; - } - - //! Finds first occurrence of a character of a list. - //! \param c A list of characters to find. For example if the method should find the first occurrence of 'a' or 'b', this parameter should be "ab". - //! \param count The amount of characters in the list. Usually, this should be strlen(c). - //! \return Position where one of the characters has been found, or -1 if not found. - s32 findFirstChar(const uchar32_t* const c, u32 count=1) const - { - if (!c || !count) - return -1; - - const_iterator i(*this, 0); - - s32 pos = 0; - while (!i.atEnd()) - { - uchar32_t t = *i; - for (u32 j=0; j& str, const u32 start = 0) const - { - u32 my_size = size(); - u32 their_size = str.size(); - - if (their_size == 0 || my_size - start < their_size) - return -1; - - const_iterator i(*this, start); - - s32 pos = start; - while (!i.atEnd()) - { - const_iterator i2(i); - const_iterator j(str, 0); - uchar32_t t1 = (uchar32_t)*i2; - uchar32_t t2 = (uchar32_t)*j; - while (t1 == t2) - { - ++i2; - ++j; - if (j.atEnd()) - return pos; - t1 = (uchar32_t)*i2; - t2 = (uchar32_t)*j; - } - ++i; - ++pos; - } - - return -1; - } - - - //! Finds another ustring16 in this ustring16. - //! \param str The string to find. - //! \param start The start position of the search. - //! \return Positions where the string has been found, or -1 if not found. - s32 find_raw(const ustring16& str, const u32 start = 0) const - { - const uchar16_t* data = str.c_str(); - if (data && *data) - { - u32 len = 0; - - while (data[len]) - ++len; - - if (len > used) - return -1; - - for (u32 i=start; i<=used-len; ++i) - { - u32 j=0; - - while(data[j] && array[i+j] == data[j]) - ++j; - - if (!data[j]) - return i; - } - } - - return -1; - } - - - //! Returns a substring. - //! \param begin: Start of substring. - //! \param length: Length of substring. - //! \return A reference to our current string. - ustring16 subString(u32 begin, s32 length) const - { - u32 len = size(); - // if start after ustring16 - // or no proper substring length - if ((length <= 0) || (begin>=len)) - return ustring16(""); - // clamp length to maximal value - if ((length+begin) > len) - length = len-begin; - - ustring16 o; - o.reserve((length+1) * 2); - - const_iterator i(*this, begin); - while (!i.atEnd() && length) - { - o.append(*i); - ++i; - --length; - } - - return o; - } - - - //! Appends a character to this ustring16. - //! \param c Character to append. - //! \return A reference to our current string. - ustring16& operator += (char c) - { - append((uchar32_t)c); - return *this; - } - - - //! Appends a character to this ustring16. - //! \param c Character to append. - //! \return A reference to our current string. - ustring16& operator += (uchar32_t c) - { - append(c); - return *this; - } - - - //! Appends a number to this ustring16. - //! \param c Number to append. - //! \return A reference to our current string. - ustring16& operator += (short c) - { - append(core::stringc(c)); - return *this; - } - - - //! Appends a number to this ustring16. - //! \param c Number to append. - //! \return A reference to our current string. - ustring16& operator += (unsigned short c) - { - append(core::stringc(c)); - return *this; - } - - -#ifdef USTRING_CPP0X_NEWLITERALS - //! Appends a number to this ustring16. - //! \param c Number to append. - //! \return A reference to our current string. - ustring16& operator += (int c) - { - append(core::stringc(c)); - return *this; - } - - - //! Appends a number to this ustring16. - //! \param c Number to append. - //! \return A reference to our current string. - ustring16& operator += (unsigned int c) - { - append(core::stringc(c)); - return *this; - } -#endif - - - //! Appends a number to this ustring16. - //! \param c Number to append. - //! \return A reference to our current string. - ustring16& operator += (long c) - { - append(core::stringc(c)); - return *this; - } - - - //! Appends a number to this ustring16. - //! \param c Number to append. - //! \return A reference to our current string. - ustring16& operator += (unsigned long c) - { - append(core::stringc(c)); - return *this; - } - - - //! Appends a number to this ustring16. - //! \param c Number to append. - //! \return A reference to our current string. - ustring16& operator += (double c) - { - append(core::stringc(c)); - return *this; - } - - - //! Appends a char ustring16 to this ustring16. - //! \param c Char ustring16 to append. - //! \return A reference to our current string. - ustring16& operator += (const uchar16_t* const c) - { - append(c); - return *this; - } - - - //! Appends a ustring16 to this ustring16. - //! \param other ustring16 to append. - //! \return A reference to our current string. - ustring16& operator += (const ustring16& other) - { - append(other); - return *this; - } - - - //! Replaces all characters of a given type with another one. - //! \param toReplace Character to replace. - //! \param replaceWith Character replacing the old one. - //! \return A reference to our current string. - ustring16& replace(uchar32_t toReplace, uchar32_t replaceWith) - { - iterator i(*this, 0); - while (!i.atEnd()) - { - typename ustring16::access a = *i; - if ((uchar32_t)a == toReplace) - a = replaceWith; - ++i; - } - return *this; - } - - - //! Replaces all instances of a string with another one. - //! \param toReplace The string to replace. - //! \param replaceWith The string replacing the old one. - //! \return A reference to our current string. - ustring16& replace(const ustring16& toReplace, const ustring16& replaceWith) - { - if (toReplace.size() == 0) - return *this; - - const uchar16_t* other = toReplace.c_str(); - const uchar16_t* replace = replaceWith.c_str(); - const u32 other_size = toReplace.size_raw(); - const u32 replace_size = replaceWith.size_raw(); - - // Determine the delta. The algorithm will change depending on the delta. - s32 delta = replace_size - other_size; - - // A character for character replace. The string will not shrink or grow. - if (delta == 0) - { - s32 pos = 0; - while ((pos = find_raw(other, pos)) != -1) - { - for (u32 i = 0; i < replace_size; ++i) - array[pos + i] = replace[i]; - ++pos; - } - return *this; - } - - // We are going to be removing some characters. The string will shrink. - if (delta < 0) - { - u32 i = 0; - for (u32 pos = 0; pos <= used; ++i, ++pos) - { - // Is this potentially a match? - if (array[pos] == *other) - { - // Check to see if we have a match. - u32 j; - for (j = 0; j < other_size; ++j) - { - if (array[pos + j] != other[j]) - break; - } - - // If we have a match, replace characters. - if (j == other_size) - { - for (j = 0; j < replace_size; ++j) - array[i + j] = replace[j]; - i += replace_size - 1; - pos += other_size - 1; - continue; - } - } - - // No match found, just copy characters. - array[i - 1] = array[pos]; - } - array[i] = 0; - used = i; - - return *this; - } - - // We are going to be adding characters, so the string size will increase. - // Count the number of times toReplace exists in the string so we can allocate the new size. - u32 find_count = 0; - s32 pos = 0; - while ((pos = find_raw(other, pos)) != -1) - { - ++find_count; - ++pos; - } - - // Re-allocate the string now, if needed. - u32 len = delta * find_count; - if (used + len >= allocated) - reallocate(used + len); - - // Start replacing. - pos = 0; - while ((pos = find_raw(other, pos)) != -1) - { - uchar16_t* start = array + pos + other_size - 1; - uchar16_t* ptr = array + used; - uchar16_t* end = array + used + delta; - - // Shift characters to make room for the string. - while (ptr != start) - { - *end = *ptr; - --ptr; - --end; - } - - // Add the new string now. - for (u32 i = 0; i < replace_size; ++i) - array[pos + i] = replace[i]; - - pos += replace_size; - used += delta; - } - - // Terminate the string and return ourself. - array[used] = 0; - return *this; - } - - - //! Removes characters from a ustring16.. - //! \param c The character to remove. - //! \return A reference to our current string. - ustring16& remove(uchar32_t c) - { - u32 pos = 0; - u32 found = 0; - u32 len = (c > 0xFFFF ? 2 : 1); // Remove characters equal to the size of c as a UTF-16 character. - for (u32 i=0; i<=used; ++i) - { - uchar32_t uc32 = 0; - if (!UTF16_IS_SURROGATE_HI(array[i])) - uc32 |= array[i]; - else if (i + 1 <= used) - { - // Convert the surrogate pair into a single UTF-32 character. - uc32 = unicode::toUTF32(array[i], array[i + 1]); - } - u32 len2 = (uc32 > 0xFFFF ? 2 : 1); - - if (uc32 == c) - { - found += len; - continue; - } - - array[pos++] = array[i]; - if (len2 == 2) - array[pos++] = array[++i]; - } - used -= found; - array[used] = 0; - return *this; - } - - - //! Removes a ustring16 from the ustring16. - //! \param toRemove The string to remove. - //! \return A reference to our current string. - ustring16& remove(const ustring16& toRemove) - { - u32 size = toRemove.size_raw(); - if (size == 0) return *this; - - const uchar16_t* tra = toRemove.c_str(); - u32 pos = 0; - u32 found = 0; - for (u32 i=0; i<=used; ++i) - { - u32 j = 0; - while (j < size) - { - if (array[i + j] != tra[j]) - break; - ++j; - } - if (j == size) - { - found += size; - i += size - 1; - continue; - } - - array[pos++] = array[i]; - } - used -= found; - array[used] = 0; - return *this; - } - - - //! Removes characters from the ustring16. - //! \param characters The characters to remove. - //! \return A reference to our current string. - ustring16& removeChars(const ustring16& characters) - { - if (characters.size_raw() == 0) - return *this; - - u32 pos = 0; - u32 found = 0; - const_iterator iter(characters); - for (u32 i=0; i<=used; ++i) - { - uchar32_t uc32 = 0; - if (!UTF16_IS_SURROGATE_HI(array[i])) - uc32 |= array[i]; - else if (i + 1 <= used) - { - // Convert the surrogate pair into a single UTF-32 character. - uc32 = unicode::toUTF32(array[i], array[i+1]); - } - u32 len2 = (uc32 > 0xFFFF ? 2 : 1); - - bool cont = false; - iter.toStart(); - while (!iter.atEnd()) - { - uchar32_t c = *iter; - if (uc32 == c) - { - found += (c > 0xFFFF ? 2 : 1); // Remove characters equal to the size of c as a UTF-16 character. - ++i; - cont = true; - break; - } - ++iter; - } - if (cont) continue; - - array[pos++] = array[i]; - if (len2 == 2) - array[pos++] = array[++i]; - } - used -= found; - array[used] = 0; - return *this; - } - - - //! Trims the ustring16. - //! Removes the specified characters (by default, Latin-1 whitespace) from the begining and the end of the ustring16. - //! \param whitespace The characters that are to be considered as whitespace. - //! \return A reference to our current string. - ustring16& trim(const ustring16& whitespace = " \t\n\r") - { - core::array utf32white = whitespace.toUTF32(); - - // find start and end of the substring without the specified characters - const s32 begin = findFirstCharNotInList(utf32white.const_pointer(), whitespace.used + 1); - if (begin == -1) - return (*this=""); - - const s32 end = findLastCharNotInList(utf32white.const_pointer(), whitespace.used + 1); - - return (*this = subString(begin, (end +1) - begin)); - } - - - //! Erases a character from the ustring16. - //! May be slow, because all elements following after the erased element have to be copied. - //! \param index Index of element to be erased. - //! \return A reference to our current string. - ustring16& erase(u32 index) - { - _IRR_DEBUG_BREAK_IF(index>used) // access violation - - iterator i(*this, index); - - uchar32_t t = *i; - u32 len = (t > 0xFFFF ? 2 : 1); - - for (u32 j = static_cast(i.getPos()) + len; j <= used; ++j) - array[j - len] = array[j]; - - used -= len; - array[used] = 0; - - return *this; - } - - - //! Validate the existing ustring16, checking for valid surrogate pairs and checking for proper termination. - //! \return A reference to our current string. - ustring16& validate() - { - // Validate all unicode characters. - for (u32 i=0; i= allocated) || UTF16_IS_SURROGATE_LO(array[i])) - array[i] = unicode::UTF_REPLACEMENT_CHARACTER; - else if (UTF16_IS_SURROGATE_HI(array[i]) && !UTF16_IS_SURROGATE_LO(array[i+1])) - array[i] = unicode::UTF_REPLACEMENT_CHARACTER; - ++i; - } - if (array[i] >= 0xFDD0 && array[i] <= 0xFDEF) - array[i] = unicode::UTF_REPLACEMENT_CHARACTER; - } - - // terminate - used = 0; - if (allocated > 0) - { - used = allocated - 1; - array[used] = 0; - } - return *this; - } - - - //! Gets the last char of the ustring16, or 0. - //! \return The last char of the ustring16, or 0. - uchar32_t lastChar() const - { - if (used < 1) - return 0; - - if (UTF16_IS_SURROGATE_LO(array[used-1])) - { - // Make sure we have a paired surrogate. - if (used < 2) - return 0; - - // Check for an invalid surrogate. - if (!UTF16_IS_SURROGATE_HI(array[used-2])) - return 0; - - // Convert the surrogate pair into a single UTF-32 character. - return unicode::toUTF32(array[used-2], array[used-1]); - } - else - { - return array[used-1]; - } - } - - - //! Split the ustring16 into parts. - /** This method will split a ustring16 at certain delimiter characters - into the container passed in as reference. The type of the container - has to be given as template parameter. It must provide a push_back and - a size method. - \param ret The result container - \param c C-style ustring16 of delimiter characters - \param count Number of delimiter characters - \param ignoreEmptyTokens Flag to avoid empty substrings in the result - container. If two delimiters occur without a character in between, an - empty substring would be placed in the result. If this flag is set, - only non-empty strings are stored. - \param keepSeparators Flag which allows to add the separator to the - result ustring16. If this flag is true, the concatenation of the - substrings results in the original ustring16. Otherwise, only the - characters between the delimiters are returned. - \return The number of resulting substrings - */ - template - u32 split(container& ret, const uchar32_t* const c, u32 count=1, bool ignoreEmptyTokens=true, bool keepSeparators=false) const - { - if (!c) - return 0; - - const_iterator i(*this); - const u32 oldSize=ret.size(); - u32 pos = 0; - u32 lastpos = 0; - u32 lastpospos = 0; - bool lastWasSeparator = false; - while (!i.atEnd()) - { - uchar32_t ch = *i; - bool foundSeparator = false; - for (u32 j=0; j(&array[lastpospos], pos - lastpos)); - foundSeparator = true; - lastpos = (keepSeparators ? pos : pos + 1); - lastpospos = (keepSeparators ? i.getPos() : i.getPos() + 1); - break; - } - } - lastWasSeparator = foundSeparator; - ++pos; - ++i; - } - u32 s = size() + 1; - if (s > lastpos) - ret.push_back(ustring16(&array[lastpospos], s - lastpos)); - return ret.size()-oldSize; - } - - - //! Split the ustring16 into parts. - /** This method will split a ustring16 at certain delimiter characters - into the container passed in as reference. The type of the container - has to be given as template parameter. It must provide a push_back and - a size method. - \param ret The result container - \param c A unicode string of delimiter characters - \param ignoreEmptyTokens Flag to avoid empty substrings in the result - container. If two delimiters occur without a character in between, an - empty substring would be placed in the result. If this flag is set, - only non-empty strings are stored. - \param keepSeparators Flag which allows to add the separator to the - result ustring16. If this flag is true, the concatenation of the - substrings results in the original ustring16. Otherwise, only the - characters between the delimiters are returned. - \return The number of resulting substrings - */ - template - u32 split(container& ret, const ustring16& c, bool ignoreEmptyTokens=true, bool keepSeparators=false) const - { - core::array v = c.toUTF32(); - return split(ret, v.pointer(), v.size(), ignoreEmptyTokens, keepSeparators); - } - - - //! Gets the size of the allocated memory buffer for the string. - //! \return The size of the allocated memory buffer. - u32 capacity() const - { - return allocated; - } - - - //! Returns the raw number of UTF-16 code points in the string which includes the individual surrogates. - //! \return The raw number of UTF-16 code points, excluding the trialing NUL. - u32 size_raw() const - { - return used; - } - - - //! Inserts a character into the string. - //! \param c The character to insert. - //! \param pos The position to insert the character. - //! \return A reference to our current string. - ustring16& insert(uchar32_t c, u32 pos) - { - u8 len = (c > 0xFFFF ? 2 : 1); - - if (used + len >= allocated) - reallocate(used + len); - - used += len; - - iterator iter(*this, pos); - for (u32 i = used - 2; i > iter.getPos(); --i) - array[i] = array[i - len]; - - if (c > 0xFFFF) - { - // c will be multibyte, so split it up into a surrogate pair. - uchar16_t x = static_cast(c); - uchar16_t vh = UTF16_HI_SURROGATE | ((((c >> 16) & ((1 << 5) - 1)) - 1) << 6) | (x >> 10); - uchar16_t vl = UTF16_LO_SURROGATE | (x & ((1 << 10) - 1)); - array[iter.getPos()] = vh; - array[iter.getPos()+1] = vl; - } - else - { - array[iter.getPos()] = static_cast(c); - } - array[used] = 0; - return *this; - } - - - //! Inserts a string into the string. - //! \param c The string to insert. - //! \param pos The position to insert the string. - //! \return A reference to our current string. - ustring16& insert(const ustring16& c, u32 pos) - { - u32 len = c.size_raw(); - if (len == 0) return *this; - - if (used + len >= allocated) - reallocate(used + len); - - used += len; - - iterator iter(*this, pos); - for (u32 i = used - 2; i > iter.getPos() + len; --i) - array[i] = array[i - len]; - - const uchar16_t* s = c.c_str(); - for (u32 i = 0; i < len; ++i) - { - array[pos++] = *s; - ++s; - } - - array[used] = 0; - return *this; - } - - - //! Inserts a character into the string. - //! \param c The character to insert. - //! \param pos The position to insert the character. - //! \return A reference to our current string. - ustring16& insert_raw(uchar16_t c, u32 pos) - { - if (used + 1 >= allocated) - reallocate(used + 1); - - ++used; - - for (u32 i = used - 1; i > pos; --i) - array[i] = array[i - 1]; - - array[pos] = c; - array[used] = 0; - return *this; - } - - - //! Removes a character from string. - //! \param pos Position of the character to remove. - //! \return A reference to our current string. - ustring16& erase_raw(u32 pos) - { - for (u32 i=pos; i<=used; ++i) - { - array[i] = array[i + 1]; - } - --used; - array[used] = 0; - return *this; - } - - - //! Replaces a character in the string. - //! \param c The new character. - //! \param pos The position of the character to replace. - //! \return A reference to our current string. - ustring16& replace_raw(uchar16_t c, u32 pos) - { - array[pos] = c; - return *this; - } - - - //! Returns an iterator to the beginning of the string. - //! \return An iterator to the beginning of the string. - iterator begin() - { - iterator i(*this, 0); - return i; - } - - - //! Returns an iterator to the beginning of the string. - //! \return An iterator to the beginning of the string. - const_iterator begin() const - { - const_iterator i(*this, 0); - return i; - } - - - //! Returns an iterator to the beginning of the string. - //! \return An iterator to the beginning of the string. - const_iterator cbegin() const - { - const_iterator i(*this, 0); - return i; - } - - - //! Returns an iterator to the end of the string. - //! \return An iterator to the end of the string. - iterator end() - { - iterator i(*this, 0); - i.toEnd(); - return i; - } - - - //! Returns an iterator to the end of the string. - //! \return An iterator to the end of the string. - const_iterator end() const - { - const_iterator i(*this, 0); - i.toEnd(); - return i; - } - - - //! Returns an iterator to the end of the string. - //! \return An iterator to the end of the string. - const_iterator cend() const - { - const_iterator i(*this, 0); - i.toEnd(); - return i; - } - - - //! Converts the string to a UTF-8 encoded string. - //! \param addBOM If true, the proper unicode byte-order mark will be prefixed to the string. - //! \return A string containing the UTF-8 encoded string. - core::string toUTF8_s(const bool addBOM = false) const - { - core::string ret; - ret.reserve(used * 4 + (addBOM ? unicode::BOM_UTF8_LEN : 0) + 1); - const_iterator iter(*this, 0); - - // Add the byte order mark if the user wants it. - if (addBOM) - { - ret.append(unicode::BOM_ENCODE_UTF8[0]); - ret.append(unicode::BOM_ENCODE_UTF8[1]); - ret.append(unicode::BOM_ENCODE_UTF8[2]); - } - - while (!iter.atEnd()) - { - uchar32_t c = *iter; - if (c > 0xFFFF) - { // 4 bytes - uchar8_t b1 = (0x1E << 3) | ((c >> 18) & 0x7); - uchar8_t b2 = (0x2 << 6) | ((c >> 12) & 0x3F); - uchar8_t b3 = (0x2 << 6) | ((c >> 6) & 0x3F); - uchar8_t b4 = (0x2 << 6) | (c & 0x3F); - ret.append(b1); - ret.append(b2); - ret.append(b3); - ret.append(b4); - } - else if (c > 0x7FF) - { // 3 bytes - uchar8_t b1 = (0xE << 4) | ((c >> 12) & 0xF); - uchar8_t b2 = (0x2 << 6) | ((c >> 6) & 0x3F); - uchar8_t b3 = (0x2 << 6) | (c & 0x3F); - ret.append(b1); - ret.append(b2); - ret.append(b3); - } - else if (c > 0x7F) - { // 2 bytes - uchar8_t b1 = (0x6 << 5) | ((c >> 6) & 0x1F); - uchar8_t b2 = (0x2 << 6) | (c & 0x3F); - ret.append(b1); - ret.append(b2); - } - else - { // 1 byte - ret.append(static_cast(c)); - } - ++iter; - } - return ret; - } - - - //! Converts the string to a UTF-8 encoded string array. - //! \param addBOM If true, the proper unicode byte-order mark will be prefixed to the string. - //! \return An array containing the UTF-8 encoded string. - core::array toUTF8(const bool addBOM = false) const - { - core::array ret(used * 4 + (addBOM ? unicode::BOM_UTF8_LEN : 0) + 1); - const_iterator iter(*this, 0); - - // Add the byte order mark if the user wants it. - if (addBOM) - { - ret.push_back(unicode::BOM_ENCODE_UTF8[0]); - ret.push_back(unicode::BOM_ENCODE_UTF8[1]); - ret.push_back(unicode::BOM_ENCODE_UTF8[2]); - } - - while (!iter.atEnd()) - { - uchar32_t c = *iter; - if (c > 0xFFFF) - { // 4 bytes - uchar8_t b1 = (0x1E << 3) | ((c >> 18) & 0x7); - uchar8_t b2 = (0x2 << 6) | ((c >> 12) & 0x3F); - uchar8_t b3 = (0x2 << 6) | ((c >> 6) & 0x3F); - uchar8_t b4 = (0x2 << 6) | (c & 0x3F); - ret.push_back(b1); - ret.push_back(b2); - ret.push_back(b3); - ret.push_back(b4); - } - else if (c > 0x7FF) - { // 3 bytes - uchar8_t b1 = (0xE << 4) | ((c >> 12) & 0xF); - uchar8_t b2 = (0x2 << 6) | ((c >> 6) & 0x3F); - uchar8_t b3 = (0x2 << 6) | (c & 0x3F); - ret.push_back(b1); - ret.push_back(b2); - ret.push_back(b3); - } - else if (c > 0x7F) - { // 2 bytes - uchar8_t b1 = (0x6 << 5) | ((c >> 6) & 0x1F); - uchar8_t b2 = (0x2 << 6) | (c & 0x3F); - ret.push_back(b1); - ret.push_back(b2); - } - else - { // 1 byte - ret.push_back(static_cast(c)); - } - ++iter; - } - ret.push_back(0); - return ret; - } - - -#ifdef USTRING_CPP0X_NEWLITERALS // C++0x - //! Converts the string to a UTF-16 encoded string. - //! \param endian The desired endianness of the string. - //! \param addBOM If true, the proper unicode byte-order mark will be prefixed to the string. - //! \return A string containing the UTF-16 encoded string. - core::string toUTF16_s(const unicode::EUTF_ENDIAN endian = unicode::EUTFEE_NATIVE, const bool addBOM = false) const - { - core::string ret; - ret.reserve(used + (addBOM ? unicode::BOM_UTF16_LEN : 0) + 1); - - // Add the BOM if specified. - if (addBOM) - { - if (endian == unicode::EUTFEE_NATIVE) - ret[0] = unicode::BOM; - else if (endian == unicode::EUTFEE_LITTLE) - { - uchar8_t* ptr8 = reinterpret_cast(&ret[0]); - *ptr8++ = unicode::BOM_ENCODE_UTF16_LE[0]; - *ptr8 = unicode::BOM_ENCODE_UTF16_LE[1]; - } - else - { - uchar8_t* ptr8 = reinterpret_cast(&ret[0]); - *ptr8++ = unicode::BOM_ENCODE_UTF16_BE[0]; - *ptr8 = unicode::BOM_ENCODE_UTF16_BE[1]; - } - } - - ret.append(array); - if (endian != unicode::EUTFEE_NATIVE && getEndianness() != endian) - { - char16_t* ptr = ret.c_str(); - for (u32 i = 0; i < ret.size(); ++i) - *ptr++ = unicode::swapEndian16(*ptr); - } - return ret; - } -#endif - - - //! Converts the string to a UTF-16 encoded string array. - //! Unfortunately, no toUTF16_s() version exists due to limitations with Irrlicht's string class. - //! \param endian The desired endianness of the string. - //! \param addBOM If true, the proper unicode byte-order mark will be prefixed to the string. - //! \return An array containing the UTF-16 encoded string. - core::array toUTF16(const unicode::EUTF_ENDIAN endian = unicode::EUTFEE_NATIVE, const bool addBOM = false) const - { - core::array ret(used + (addBOM ? unicode::BOM_UTF16_LEN : 0) + 1); - uchar16_t* ptr = ret.pointer(); - - // Add the BOM if specified. - if (addBOM) - { - if (endian == unicode::EUTFEE_NATIVE) - *ptr = unicode::BOM; - else if (endian == unicode::EUTFEE_LITTLE) - { - uchar8_t* ptr8 = reinterpret_cast(ptr); - *ptr8++ = unicode::BOM_ENCODE_UTF16_LE[0]; - *ptr8 = unicode::BOM_ENCODE_UTF16_LE[1]; - } - else - { - uchar8_t* ptr8 = reinterpret_cast(ptr); - *ptr8++ = unicode::BOM_ENCODE_UTF16_BE[0]; - *ptr8 = unicode::BOM_ENCODE_UTF16_BE[1]; - } - ++ptr; - } - - memcpy((void*)ptr, (void*)array, used * sizeof(uchar16_t)); - if (endian != unicode::EUTFEE_NATIVE && getEndianness() != endian) - { - for (u32 i = 0; i <= used; ++i) - ptr[i] = unicode::swapEndian16(ptr[i]); - } - ret.set_used(used + (addBOM ? unicode::BOM_UTF16_LEN : 0)); - ret.push_back(0); - return ret; - } - - -#ifdef USTRING_CPP0X_NEWLITERALS // C++0x - //! Converts the string to a UTF-32 encoded string. - //! \param endian The desired endianness of the string. - //! \param addBOM If true, the proper unicode byte-order mark will be prefixed to the string. - //! \return A string containing the UTF-32 encoded string. - core::string toUTF32_s(const unicode::EUTF_ENDIAN endian = unicode::EUTFEE_NATIVE, const bool addBOM = false) const - { - core::string ret; - ret.reserve(size() + 1 + (addBOM ? unicode::BOM_UTF32_LEN : 0)); - const_iterator iter(*this, 0); - - // Add the BOM if specified. - if (addBOM) - { - if (endian == unicode::EUTFEE_NATIVE) - ret.append(unicode::BOM); - else - { - union - { - uchar32_t full; - u8 chunk[4]; - } t; - - if (endian == unicode::EUTFEE_LITTLE) - { - t.chunk[0] = unicode::BOM_ENCODE_UTF32_LE[0]; - t.chunk[1] = unicode::BOM_ENCODE_UTF32_LE[1]; - t.chunk[2] = unicode::BOM_ENCODE_UTF32_LE[2]; - t.chunk[3] = unicode::BOM_ENCODE_UTF32_LE[3]; - } - else - { - t.chunk[0] = unicode::BOM_ENCODE_UTF32_BE[0]; - t.chunk[1] = unicode::BOM_ENCODE_UTF32_BE[1]; - t.chunk[2] = unicode::BOM_ENCODE_UTF32_BE[2]; - t.chunk[3] = unicode::BOM_ENCODE_UTF32_BE[3]; - } - ret.append(t.full); - } - } - - while (!iter.atEnd()) - { - uchar32_t c = *iter; - if (endian != unicode::EUTFEE_NATIVE && getEndianness() != endian) - c = unicode::swapEndian32(c); - ret.append(c); - ++iter; - } - return ret; - } -#endif - - - //! Converts the string to a UTF-32 encoded string array. - //! Unfortunately, no toUTF32_s() version exists due to limitations with Irrlicht's string class. - //! \param endian The desired endianness of the string. - //! \param addBOM If true, the proper unicode byte-order mark will be prefixed to the string. - //! \return An array containing the UTF-32 encoded string. - core::array toUTF32(const unicode::EUTF_ENDIAN endian = unicode::EUTFEE_NATIVE, const bool addBOM = false) const - { - core::array ret(size() + (addBOM ? unicode::BOM_UTF32_LEN : 0) + 1); - const_iterator iter(*this, 0); - - // Add the BOM if specified. - if (addBOM) - { - if (endian == unicode::EUTFEE_NATIVE) - ret.push_back(unicode::BOM); - else - { - union - { - uchar32_t full; - u8 chunk[4]; - } t; - - if (endian == unicode::EUTFEE_LITTLE) - { - t.chunk[0] = unicode::BOM_ENCODE_UTF32_LE[0]; - t.chunk[1] = unicode::BOM_ENCODE_UTF32_LE[1]; - t.chunk[2] = unicode::BOM_ENCODE_UTF32_LE[2]; - t.chunk[3] = unicode::BOM_ENCODE_UTF32_LE[3]; - } - else - { - t.chunk[0] = unicode::BOM_ENCODE_UTF32_BE[0]; - t.chunk[1] = unicode::BOM_ENCODE_UTF32_BE[1]; - t.chunk[2] = unicode::BOM_ENCODE_UTF32_BE[2]; - t.chunk[3] = unicode::BOM_ENCODE_UTF32_BE[3]; - } - ret.push_back(t.full); - } - } - ret.push_back(0); - - while (!iter.atEnd()) - { - uchar32_t c = *iter; - if (endian != unicode::EUTFEE_NATIVE && getEndianness() != endian) - c = unicode::swapEndian32(c); - ret.push_back(c); - ++iter; - } - return ret; - } - - - //! Converts the string to a wchar_t encoded string. - /** The size of a wchar_t changes depending on the platform. This function will store a - correct UTF-8, -16, or -32 encoded string depending on the size of a wchar_t. **/ - //! \param endian The desired endianness of the string. - //! \param addBOM If true, the proper unicode byte-order mark will be prefixed to the string. - //! \return A string containing the wchar_t encoded string. - core::string toWCHAR_s(const unicode::EUTF_ENDIAN endian = unicode::EUTFEE_NATIVE, const bool addBOM = false) const - { - if (sizeof(wchar_t) == 4) - { - core::array a(toUTF32(endian, addBOM)); - core::stringw ret(a.pointer()); - return ret; - } - else if (sizeof(wchar_t) == 2) - { - if (endian == unicode::EUTFEE_NATIVE && addBOM == false) - { - core::stringw ret(array); - return ret; - } - else - { - core::array a(toUTF16(endian, addBOM)); - core::stringw ret(a.pointer()); - return ret; - } - } - else if (sizeof(wchar_t) == 1) - { - core::array a(toUTF8(addBOM)); - core::stringw ret(a.pointer()); - return ret; - } - - // Shouldn't happen. - return core::stringw(); - } - - - //! Converts the string to a wchar_t encoded string array. - /** The size of a wchar_t changes depending on the platform. This function will store a - correct UTF-8, -16, or -32 encoded string depending on the size of a wchar_t. **/ - //! \param endian The desired endianness of the string. - //! \param addBOM If true, the proper unicode byte-order mark will be prefixed to the string. - //! \return An array containing the wchar_t encoded string. - core::array toWCHAR(const unicode::EUTF_ENDIAN endian = unicode::EUTFEE_NATIVE, const bool addBOM = false) const - { - if (sizeof(wchar_t) == 4) - { - core::array a(toUTF32(endian, addBOM)); - core::array ret(a.size()); - ret.set_used(a.size()); - memcpy((void*)ret.pointer(), (void*)a.pointer(), a.size() * sizeof(uchar32_t)); - return ret; - } - if (sizeof(wchar_t) == 2) - { - if (endian == unicode::EUTFEE_NATIVE && addBOM == false) - { - core::array ret(used); - ret.set_used(used); - memcpy((void*)ret.pointer(), (void*)array, used * sizeof(uchar16_t)); - return ret; - } - else - { - core::array a(toUTF16(endian, addBOM)); - core::array ret(a.size()); - ret.set_used(a.size()); - memcpy((void*)ret.pointer(), (void*)a.pointer(), a.size() * sizeof(uchar16_t)); - return ret; - } - } - if (sizeof(wchar_t) == 1) - { - core::array a(toUTF8(addBOM)); - core::array ret(a.size()); - ret.set_used(a.size()); - memcpy((void*)ret.pointer(), (void*)a.pointer(), a.size() * sizeof(uchar8_t)); - return ret; - } - - // Shouldn't happen. - return core::array(); - } - - //! Converts the string to a properly encoded io::path string. - //! \param endian The desired endianness of the string. - //! \param addBOM If true, the proper unicode byte-order mark will be prefixed to the string. - //! \return An io::path string containing the properly encoded string. - io::path toPATH_s(const unicode::EUTF_ENDIAN endian = unicode::EUTFEE_NATIVE, const bool addBOM = false) const - { -#if defined(_IRR_WCHAR_FILESYSTEM) - return toWCHAR_s(endian, addBOM); -#else - return toUTF8_s(addBOM); -#endif - } - - //! Loads an unknown stream of data. - //! Will attempt to determine if the stream is unicode data. Useful for loading from files. - //! \param data The data stream to load from. - //! \param data_size The length of the data string. - //! \return A reference to our current string. - ustring16& loadDataStream(const char* data, size_t data_size) - { - // Clear our string. - *this = ""; - if (!data) - return *this; - - unicode::EUTF_ENCODE e = unicode::determineUnicodeBOM(data); - switch (e) - { - default: - case unicode::EUTFE_UTF8: - append((uchar8_t*)data, data_size); - break; - - case unicode::EUTFE_UTF16: - case unicode::EUTFE_UTF16_BE: - case unicode::EUTFE_UTF16_LE: - append((uchar16_t*)data, data_size / 2); - break; - - case unicode::EUTFE_UTF32: - case unicode::EUTFE_UTF32_BE: - case unicode::EUTFE_UTF32_LE: - append((uchar32_t*)data, data_size / 4); - break; - } - - return *this; - } - - //! Gets the encoding of the Unicode string this class contains. - //! \return An enum describing the current encoding of this string. - const unicode::EUTF_ENCODE getEncoding() const - { - return encoding; - } - - //! Gets the endianness of the Unicode string this class contains. - //! \return An enum describing the endianness of this string. - const unicode::EUTF_ENDIAN getEndianness() const - { - if (encoding == unicode::EUTFE_UTF16_LE || - encoding == unicode::EUTFE_UTF32_LE) - return unicode::EUTFEE_LITTLE; - else return unicode::EUTFEE_BIG; - } - -private: - - //! Reallocate the string, making it bigger or smaller. - //! \param new_size The new size of the string. - void reallocate(u32 new_size) - { - uchar16_t* old_array = array; - - array = allocator.allocate(new_size + 1); //new u16[new_size]; - allocated = new_size + 1; - if (old_array == 0) return; - - u32 amount = used < new_size ? used : new_size; - for (u32 i=0; i<=amount; ++i) - array[i] = old_array[i]; - - if (allocated <= used) - used = allocated - 1; - - array[used] = 0; - - allocator.deallocate(old_array); // delete [] old_array; - } - - //--- member variables - - uchar16_t* array; - unicode::EUTF_ENCODE encoding; - u32 allocated; - u32 used; - TAlloc allocator; - //irrAllocator allocator; -}; - -typedef ustring16 > ustring; - - -//! Appends two ustring16s. -template -inline ustring16 operator+(const ustring16& left, const ustring16& right) -{ - ustring16 ret(left); - ret += right; - return ret; -} - - -//! Appends a ustring16 and a null-terminated unicode string. -template -inline ustring16 operator+(const ustring16& left, const B* const right) -{ - ustring16 ret(left); - ret += right; - return ret; -} - - -//! Appends a ustring16 and a null-terminated unicode string. -template -inline ustring16 operator+(const B* const left, const ustring16& right) -{ - ustring16 ret(left); - ret += right; - return ret; -} - - -//! Appends a ustring16 and an Irrlicht string. -template -inline ustring16 operator+(const ustring16& left, const string& right) -{ - ustring16 ret(left); - ret += right; - return ret; -} - - -//! Appends a ustring16 and an Irrlicht string. -template -inline ustring16 operator+(const string& left, const ustring16& right) -{ - ustring16 ret(left); - ret += right; - return ret; -} - - -//! Appends a ustring16 and a std::basic_string. -template -inline ustring16 operator+(const ustring16& left, const std::basic_string& right) -{ - ustring16 ret(left); - ret += right; - return ret; -} - - -//! Appends a ustring16 and a std::basic_string. -template -inline ustring16 operator+(const std::basic_string& left, const ustring16& right) -{ - ustring16 ret(left); - ret += right; - return ret; -} - - -//! Appends a ustring16 and a char. -template -inline ustring16 operator+(const ustring16& left, const char right) -{ - ustring16 ret(left); - ret += right; - return ret; -} - - -//! Appends a ustring16 and a char. -template -inline ustring16 operator+(const char left, const ustring16& right) -{ - ustring16 ret(left); - ret += right; - return ret; -} - - -#ifdef USTRING_CPP0X_NEWLITERALS -//! Appends a ustring16 and a uchar32_t. -template -inline ustring16 operator+(const ustring16& left, const uchar32_t right) -{ - ustring16 ret(left); - ret += right; - return ret; -} - - -//! Appends a ustring16 and a uchar32_t. -template -inline ustring16 operator+(const uchar32_t left, const ustring16& right) -{ - ustring16 ret(left); - ret += right; - return ret; -} -#endif - - -//! Appends a ustring16 and a short. -template -inline ustring16 operator+(const ustring16& left, const short right) -{ - ustring16 ret(left); - ret += core::stringc(right); - return ret; -} - - -//! Appends a ustring16 and a short. -template -inline ustring16 operator+(const short left, const ustring16& right) -{ - ustring16 ret((core::stringc(left))); - ret += right; - return ret; -} - - -//! Appends a ustring16 and an unsigned short. -template -inline ustring16 operator+(const ustring16& left, const unsigned short right) -{ - ustring16 ret(left); - ret += core::stringc(right); - return ret; -} - - -//! Appends a ustring16 and an unsigned short. -template -inline ustring16 operator+(const unsigned short left, const ustring16& right) -{ - ustring16 ret((core::stringc(left))); - ret += right; - return ret; -} - - -//! Appends a ustring16 and an int. -template -inline ustring16 operator+(const ustring16& left, const int right) -{ - ustring16 ret(left); - ret += core::stringc(right); - return ret; -} - - -//! Appends a ustring16 and an int. -template -inline ustring16 operator+(const int left, const ustring16& right) -{ - ustring16 ret((core::stringc(left))); - ret += right; - return ret; -} - - -//! Appends a ustring16 and an unsigned int. -template -inline ustring16 operator+(const ustring16& left, const unsigned int right) -{ - ustring16 ret(left); - ret += core::stringc(right); - return ret; -} - - -//! Appends a ustring16 and an unsigned int. -template -inline ustring16 operator+(const unsigned int left, const ustring16& right) -{ - ustring16 ret((core::stringc(left))); - ret += right; - return ret; -} - - -//! Appends a ustring16 and a long. -template -inline ustring16 operator+(const ustring16& left, const long right) -{ - ustring16 ret(left); - ret += core::stringc(right); - return ret; -} - - -//! Appends a ustring16 and a long. -template -inline ustring16 operator+(const long left, const ustring16& right) -{ - ustring16 ret((core::stringc(left))); - ret += right; - return ret; -} - - -//! Appends a ustring16 and an unsigned long. -template -inline ustring16 operator+(const ustring16& left, const unsigned long right) -{ - ustring16 ret(left); - ret += core::stringc(right); - return ret; -} - - -//! Appends a ustring16 and an unsigned long. -template -inline ustring16 operator+(const unsigned long left, const ustring16& right) -{ - ustring16 ret((core::stringc(left))); - ret += right; - return ret; -} - - -//! Appends a ustring16 and a float. -template -inline ustring16 operator+(const ustring16& left, const float right) -{ - ustring16 ret(left); - ret += core::stringc(right); - return ret; -} - - -//! Appends a ustring16 and a float. -template -inline ustring16 operator+(const float left, const ustring16& right) -{ - ustring16 ret((core::stringc(left))); - ret += right; - return ret; -} - - -//! Appends a ustring16 and a double. -template -inline ustring16 operator+(const ustring16& left, const double right) -{ - ustring16 ret(left); - ret += core::stringc(right); - return ret; -} - - -//! Appends a ustring16 and a double. -template -inline ustring16 operator+(const double left, const ustring16& right) -{ - ustring16 ret((core::stringc(left))); - ret += right; - return ret; -} - - -#ifdef USTRING_CPP0X -//! Appends two ustring16s. -template -inline ustring16&& operator+(const ustring16& left, ustring16&& right) -{ - //std::cout << "MOVE operator+(&, &&)" << std::endl; - right.insert(left, 0); - return std::move(right); -} - - -//! Appends two ustring16s. -template -inline ustring16&& operator+(ustring16&& left, const ustring16& right) -{ - //std::cout << "MOVE operator+(&&, &)" << std::endl; - left.append(right); - return std::move(left); -} - - -//! Appends two ustring16s. -template -inline ustring16&& operator+(ustring16&& left, ustring16&& right) -{ - //std::cout << "MOVE operator+(&&, &&)" << std::endl; - if ((right.size_raw() <= left.capacity() - left.size_raw()) || - (right.capacity() - right.size_raw() < left.size_raw())) - { - left.append(right); - return std::move(left); - } - else - { - right.insert(left, 0); - return std::move(right); - } -} - - -//! Appends a ustring16 and a null-terminated unicode string. -template -inline ustring16&& operator+(ustring16&& left, const B* const right) -{ - //std::cout << "MOVE operator+(&&, B*)" << std::endl; - left.append(right); - return std::move(left); -} - - -//! Appends a ustring16 and a null-terminated unicode string. -template -inline ustring16&& operator+(const B* const left, ustring16&& right) -{ - //std::cout << "MOVE operator+(B*, &&)" << std::endl; - right.insert(left, 0); - return std::move(right); -} - - -//! Appends a ustring16 and an Irrlicht string. -template -inline ustring16&& operator+(const string& left, ustring16&& right) -{ - //std::cout << "MOVE operator+(&, &&)" << std::endl; - right.insert(left, 0); - return std::move(right); -} - - -//! Appends a ustring16 and an Irrlicht string. -template -inline ustring16&& operator+(ustring16&& left, const string& right) -{ - //std::cout << "MOVE operator+(&&, &)" << std::endl; - left.append(right); - return std::move(left); -} - - -//! Appends a ustring16 and a std::basic_string. -template -inline ustring16&& operator+(const std::basic_string& left, ustring16&& right) -{ - //std::cout << "MOVE operator+(&, &&)" << std::endl; - right.insert(core::ustring16(left), 0); - return std::move(right); -} - - -//! Appends a ustring16 and a std::basic_string. -template -inline ustring16&& operator+(ustring16&& left, const std::basic_string& right) -{ - //std::cout << "MOVE operator+(&&, &)" << std::endl; - left.append(right); - return std::move(left); -} - - -//! Appends a ustring16 and a char. -template -inline ustring16 operator+(ustring16&& left, const char right) -{ - left.append((uchar32_t)right); - return std::move(left); -} - - -//! Appends a ustring16 and a char. -template -inline ustring16 operator+(const char left, ustring16&& right) -{ - right.insert((uchar32_t)left, 0); - return std::move(right); -} - - -#ifdef USTRING_CPP0X_NEWLITERALS -//! Appends a ustring16 and a uchar32_t. -template -inline ustring16 operator+(ustring16&& left, const uchar32_t right) -{ - left.append(right); - return std::move(left); -} - - -//! Appends a ustring16 and a uchar32_t. -template -inline ustring16 operator+(const uchar32_t left, ustring16&& right) -{ - right.insert(left, 0); - return std::move(right); -} -#endif - - -//! Appends a ustring16 and a short. -template -inline ustring16 operator+(ustring16&& left, const short right) -{ - left.append(core::stringc(right)); - return std::move(left); -} - - -//! Appends a ustring16 and a short. -template -inline ustring16 operator+(const short left, ustring16&& right) -{ - right.insert(core::stringc(left), 0); - return std::move(right); -} - - -//! Appends a ustring16 and an unsigned short. -template -inline ustring16 operator+(ustring16&& left, const unsigned short right) -{ - left.append(core::stringc(right)); - return std::move(left); -} - - -//! Appends a ustring16 and an unsigned short. -template -inline ustring16 operator+(const unsigned short left, ustring16&& right) -{ - right.insert(core::stringc(left), 0); - return std::move(right); -} - - -//! Appends a ustring16 and an int. -template -inline ustring16 operator+(ustring16&& left, const int right) -{ - left.append(core::stringc(right)); - return std::move(left); -} - - -//! Appends a ustring16 and an int. -template -inline ustring16 operator+(const int left, ustring16&& right) -{ - right.insert(core::stringc(left), 0); - return std::move(right); -} - - -//! Appends a ustring16 and an unsigned int. -template -inline ustring16 operator+(ustring16&& left, const unsigned int right) -{ - left.append(core::stringc(right)); - return std::move(left); -} - - -//! Appends a ustring16 and an unsigned int. -template -inline ustring16 operator+(const unsigned int left, ustring16&& right) -{ - right.insert(core::stringc(left), 0); - return std::move(right); -} - - -//! Appends a ustring16 and a long. -template -inline ustring16 operator+(ustring16&& left, const long right) -{ - left.append(core::stringc(right)); - return std::move(left); -} - - -//! Appends a ustring16 and a long. -template -inline ustring16 operator+(const long left, ustring16&& right) -{ - right.insert(core::stringc(left), 0); - return std::move(right); -} - - -//! Appends a ustring16 and an unsigned long. -template -inline ustring16 operator+(ustring16&& left, const unsigned long right) -{ - left.append(core::stringc(right)); - return std::move(left); -} - - -//! Appends a ustring16 and an unsigned long. -template -inline ustring16 operator+(const unsigned long left, ustring16&& right) -{ - right.insert(core::stringc(left), 0); - return std::move(right); -} - - -//! Appends a ustring16 and a float. -template -inline ustring16 operator+(ustring16&& left, const float right) -{ - left.append(core::stringc(right)); - return std::move(left); -} - - -//! Appends a ustring16 and a float. -template -inline ustring16 operator+(const float left, ustring16&& right) -{ - right.insert(core::stringc(left), 0); - return std::move(right); -} - - -//! Appends a ustring16 and a double. -template -inline ustring16 operator+(ustring16&& left, const double right) -{ - left.append(core::stringc(right)); - return std::move(left); -} - - -//! Appends a ustring16 and a double. -template -inline ustring16 operator+(const double left, ustring16&& right) -{ - right.insert(core::stringc(left), 0); - return std::move(right); -} -#endif - - -#ifndef USTRING_NO_STL -//! Writes a ustring16 to an ostream. -template -inline std::ostream& operator<<(std::ostream& out, const ustring16& in) -{ - out << in.toUTF8_s().c_str(); - return out; -} - -//! Writes a ustring16 to a wostream. -template -inline std::wostream& operator<<(std::wostream& out, const ustring16& in) -{ - out << in.toWCHAR_s().c_str(); - return out; -} -#endif - - -#ifndef USTRING_NO_STL - -namespace unicode -{ - -//! Hashing algorithm for hashing a ustring. Used for things like unordered_maps. -//! Algorithm taken from std::hash. -class hash : public std::unary_function -{ - public: - size_t operator()(const core::ustring& s) const - { - size_t ret = 2166136261U; - size_t index = 0; - size_t stride = 1 + s.size_raw() / 10; - - core::ustring::const_iterator i = s.begin(); - while (i != s.end()) - { - // TODO: Don't force u32 on an x64 OS. Make it agnostic. - ret = 16777619U * ret ^ (size_t)s[(u32)index]; - index += stride; - i += stride; - } - return (ret); - } -}; - -} // end namespace unicode - -#endif - -} // end namespace core -} // end namespace irr From 6a26d6d15a9a122681772c29a7f3b0c36ac9c62e Mon Sep 17 00:00:00 2001 From: sfan5 Date: Thu, 25 Mar 2021 15:09:49 +0100 Subject: [PATCH 02/72] Adjust build config for Irrlicht changes (again) --- .gitlab-ci.yml | 2 +- README.md | 4 ++-- cmake/Modules/FindIrrlicht.cmake | 29 ++++++++++++++++++----------- util/buildbot/buildwin32.sh | 6 +++--- util/buildbot/buildwin64.sh | 6 +++--- util/ci/common.sh | 2 +- 6 files changed, 28 insertions(+), 21 deletions(-) diff --git a/.gitlab-ci.yml b/.gitlab-ci.yml index 39ff576cf..9764648e1 100644 --- a/.gitlab-ci.yml +++ b/.gitlab-ci.yml @@ -9,7 +9,7 @@ stages: - deploy variables: - IRRLICHT_TAG: "1.9.0mt0" + IRRLICHT_TAG: "1.9.0mt1" MINETEST_GAME_REPO: "https://github.com/minetest/minetest_game.git" CONTAINER_IMAGE: registry.gitlab.com/$CI_PROJECT_PATH diff --git a/README.md b/README.md index e767f1fe3..662b5c4ca 100644 --- a/README.md +++ b/README.md @@ -259,9 +259,9 @@ Library specific options: GETTEXT_INCLUDE_DIR - Only when building with gettext; directory that contains iconv.h GETTEXT_LIBRARY - Only when building with gettext on Windows; path to libintl.dll.a GETTEXT_MSGFMT - Only when building with gettext; path to msgfmt/msgfmt.exe - IRRLICHT_DLL - Only on Windows; path to Irrlicht.dll + IRRLICHT_DLL - Only on Windows; path to IrrlichtMt.dll IRRLICHT_INCLUDE_DIR - Directory that contains IrrCompileConfig.h - IRRLICHT_LIBRARY - Path to libIrrlicht.a/libIrrlicht.so/libIrrlicht.dll.a/Irrlicht.lib + IRRLICHT_LIBRARY - Path to libIrrlichtMt.a/libIrrlichtMt.so/libIrrlichtMt.dll.a/IrrlichtMt.lib LEVELDB_INCLUDE_DIR - Only when building with LevelDB; directory that contains db.h LEVELDB_LIBRARY - Only when building with LevelDB; path to libleveldb.a/libleveldb.so/libleveldb.dll.a LEVELDB_DLL - Only when building with LevelDB on Windows; path to libleveldb.dll diff --git a/cmake/Modules/FindIrrlicht.cmake b/cmake/Modules/FindIrrlicht.cmake index 8296de685..bb501b3b4 100644 --- a/cmake/Modules/FindIrrlicht.cmake +++ b/cmake/Modules/FindIrrlicht.cmake @@ -3,24 +3,31 @@ mark_as_advanced(IRRLICHT_LIBRARY IRRLICHT_INCLUDE_DIR IRRLICHT_DLL) # Find include directory and libraries -if(TRUE) +# find our fork first, then upstream (TODO: remove this?) +foreach(libname IN ITEMS IrrlichtMt Irrlicht) + string(TOLOWER "${libname}" libname2) + find_path(IRRLICHT_INCLUDE_DIR NAMES irrlicht.h - DOC "Path to the directory with Irrlicht includes" + DOC "Path to the directory with IrrlichtMt includes" PATHS - /usr/local/include/irrlicht - /usr/include/irrlicht - /system/develop/headers/irrlicht #Haiku - PATH_SUFFIXES "include/irrlicht" + /usr/local/include/${libname2} + /usr/include/${libname2} + /system/develop/headers/${libname2} #Haiku + PATH_SUFFIXES "include/${libname2}" ) - find_library(IRRLICHT_LIBRARY NAMES libIrrlicht Irrlicht - DOC "Path to the Irrlicht library file" + find_library(IRRLICHT_LIBRARY NAMES lib${libname} ${libname} + DOC "Path to the IrrlichtMt library file" PATHS /usr/local/lib /usr/lib /system/develop/lib # Haiku ) -endif() + + if(IRRLICHT_INCLUDE_DIR OR IRRLICHT_LIBRARY) + break() + endif() +endforeach() # Users will likely need to edit these mark_as_advanced(CLEAR IRRLICHT_LIBRARY IRRLICHT_INCLUDE_DIR) @@ -29,8 +36,8 @@ mark_as_advanced(CLEAR IRRLICHT_LIBRARY IRRLICHT_INCLUDE_DIR) if(WIN32) # If VCPKG_APPLOCAL_DEPS is ON, dll's are automatically handled by VCPKG if(NOT VCPKG_APPLOCAL_DEPS) - find_file(IRRLICHT_DLL NAMES Irrlicht.dll - DOC "Path of the Irrlicht dll (for installation)" + find_file(IRRLICHT_DLL NAMES IrrlichtMt.dll + DOC "Path of the IrrlichtMt dll (for installation)" ) endif() endif(WIN32) diff --git a/util/buildbot/buildwin32.sh b/util/buildbot/buildwin32.sh index db3a23375..1a66a9764 100755 --- a/util/buildbot/buildwin32.sh +++ b/util/buildbot/buildwin32.sh @@ -31,7 +31,7 @@ if [ -z "$toolchain_file" ]; then fi echo "Using $toolchain_file" -irrlicht_version=1.9.0mt0 +irrlicht_version=1.9.0mt1 ogg_version=1.3.2 vorbis_version=1.3.5 curl_version=7.65.3 @@ -122,8 +122,8 @@ cmake .. \ -DENABLE_FREETYPE=1 \ -DENABLE_LEVELDB=1 \ \ - -DIRRLICHT_INCLUDE_DIR=$libdir/irrlicht/include/irrlicht \ - -DIRRLICHT_LIBRARY=$libdir/irrlicht/lib/libIrrlicht.dll.a \ + -DIRRLICHT_INCLUDE_DIR=$libdir/irrlicht/include/irrlichtmt \ + -DIRRLICHT_LIBRARY=$libdir/irrlicht/lib/libIrrlichtMt.dll.a \ -DIRRLICHT_DLL="$irr_dlls" \ \ -DZLIB_INCLUDE_DIR=$libdir/zlib/include \ diff --git a/util/buildbot/buildwin64.sh b/util/buildbot/buildwin64.sh index 53c6d1ea9..54bfbef69 100755 --- a/util/buildbot/buildwin64.sh +++ b/util/buildbot/buildwin64.sh @@ -20,7 +20,7 @@ packagedir=$builddir/packages libdir=$builddir/libs toolchain_file=$dir/toolchain_x86_64-w64-mingw32.cmake -irrlicht_version=1.9.0mt0 +irrlicht_version=1.9.0mt1 ogg_version=1.3.2 vorbis_version=1.3.5 curl_version=7.65.3 @@ -112,8 +112,8 @@ cmake .. \ -DENABLE_FREETYPE=1 \ -DENABLE_LEVELDB=1 \ \ - -DIRRLICHT_INCLUDE_DIR=$libdir/irrlicht/include/irrlicht \ - -DIRRLICHT_LIBRARY=$libdir/irrlicht/lib/libIrrlicht.dll.a \ + -DIRRLICHT_INCLUDE_DIR=$libdir/irrlicht/include/irrlichtmt \ + -DIRRLICHT_LIBRARY=$libdir/irrlicht/lib/libIrrlichtMt.dll.a \ -DIRRLICHT_DLL="$irr_dlls" \ \ -DZLIB_INCLUDE_DIR=$libdir/zlib/include \ diff --git a/util/ci/common.sh b/util/ci/common.sh index d73c31b2f..ca2ecbc29 100644 --- a/util/ci/common.sh +++ b/util/ci/common.sh @@ -12,7 +12,7 @@ install_linux_deps() { shift pkgs+=(libirrlicht-dev) else - wget "https://github.com/minetest/irrlicht/releases/download/1.9.0mt0/ubuntu-bionic.tar.gz" + wget "https://github.com/minetest/irrlicht/releases/download/1.9.0mt1/ubuntu-bionic.tar.gz" sudo tar -xaf ubuntu-bionic.tar.gz -C /usr/local fi From fc1512cca64ca9e44ed60372355a0cf1f7b2fe09 Mon Sep 17 00:00:00 2001 From: HybridDog <3192173+HybridDog@users.noreply.github.com> Date: Fri, 26 Mar 2021 20:59:05 +0100 Subject: [PATCH 03/72] Translate chatcommand delay message and replace minetest with core (#11113) --- builtin/game/chat.lua | 13 +++++++------ 1 file changed, 7 insertions(+), 6 deletions(-) diff --git a/builtin/game/chat.lua b/builtin/game/chat.lua index bf2d7851e..10da054fd 100644 --- a/builtin/game/chat.lua +++ b/builtin/game/chat.lua @@ -75,9 +75,9 @@ core.register_on_chat_message(function(name, message) local has_privs, missing_privs = core.check_player_privs(name, cmd_def.privs) if has_privs then core.set_last_run_mod(cmd_def.mod_origin) - local t_before = minetest.get_us_time() + local t_before = core.get_us_time() local success, result = cmd_def.func(name, param) - local delay = (minetest.get_us_time() - t_before) / 1000000 + local delay = (core.get_us_time() - t_before) / 1000000 if success == false and result == nil then core.chat_send_player(name, "-!- "..S("Invalid command usage.")) local help_def = core.registered_chatcommands["help"] @@ -91,11 +91,12 @@ core.register_on_chat_message(function(name, message) if delay > msg_time_threshold then -- Show how much time it took to execute the command if result then - result = result .. - minetest.colorize("#f3d2ff", " (%.5g s)"):format(delay) + result = result .. core.colorize("#f3d2ff", S(" (@1 s)", + string.format("%.5f", delay))) else - result = minetest.colorize("#f3d2ff", - "Command execution took %.5f s"):format(delay) + result = core.colorize("#f3d2ff", S( + "Command execution took @1 s", + string.format("%.5f", delay))) end end if result then From 5f4c78a77d99834887a714944899df92a4ebb573 Mon Sep 17 00:00:00 2001 From: sfan5 Date: Fri, 26 Mar 2021 23:08:39 +0100 Subject: [PATCH 04/72] Fix broken include check and correct Gitlab-CI script --- .gitlab-ci.yml | 2 +- CMakeLists.txt | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/.gitlab-ci.yml b/.gitlab-ci.yml index 9764648e1..5e16cdfe5 100644 --- a/.gitlab-ci.yml +++ b/.gitlab-ci.yml @@ -26,7 +26,7 @@ variables: - cd .. - mkdir cmakebuild - cd cmakebuild - - cmake -DIRRLICHT_LIBRARY=$PWD/../irrlicht/lib/Linux/libIrrlicht.a -DIRRLICHT_INCLUDE_DIR=$PWD/../irrlicht/include -DCMAKE_INSTALL_PREFIX=../artifact/minetest/usr/ -DCMAKE_BUILD_TYPE=Release -DRUN_IN_PLACE=FALSE -DENABLE_GETTEXT=TRUE -DBUILD_SERVER=TRUE .. + - cmake -DIRRLICHT_LIBRARY=$PWD/../irrlicht/lib/Linux/libIrrlichtMt.a -DIRRLICHT_INCLUDE_DIR=$PWD/../irrlicht/include -DCMAKE_INSTALL_PREFIX=../artifact/minetest/usr/ -DCMAKE_BUILD_TYPE=Release -DRUN_IN_PLACE=FALSE -DENABLE_GETTEXT=TRUE -DBUILD_SERVER=TRUE .. - make -j2 - make install artifacts: diff --git a/CMakeLists.txt b/CMakeLists.txt index e4bda3afb..c46ff6c77 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -61,7 +61,7 @@ set(CMAKE_MODULE_PATH ${CMAKE_MODULE_PATH} "${CMAKE_SOURCE_DIR}/cmake/Modules/") find_package(Irrlicht) if(BUILD_CLIENT AND NOT IRRLICHT_FOUND) message(FATAL_ERROR "Irrlicht is required to build the client, but it was not found.") -elseif(IRRLICHT_INCLUDE_DIR STREQUAL "") +elseif(NOT IRRLICHT_INCLUDE_DIR) message(FATAL_ERROR "Irrlicht headers are required to build the server, but none found.") endif() From 8d89f5f0cc1db47542bd355babad06b6bda54f51 Mon Sep 17 00:00:00 2001 From: sfan5 Date: Mon, 29 Mar 2021 19:55:24 +0200 Subject: [PATCH 05/72] Replace fallback font nonsense with automatic per-glyph fallback (#11084) --- builtin/settingtypes.txt | 13 +--- po/minetest.pot | 12 ---- src/CMakeLists.txt | 3 + src/client/fontengine.cpp | 95 +++++++++++++---------------- src/client/fontengine.h | 8 ++- src/defaultsettings.cpp | 5 -- src/irrlicht_changes/CGUITTFont.cpp | 64 +++++++++++++++++-- src/irrlicht_changes/CGUITTFont.h | 7 ++- 8 files changed, 119 insertions(+), 88 deletions(-) diff --git a/builtin/settingtypes.txt b/builtin/settingtypes.txt index 75efe64da..1f8bf97b7 100644 --- a/builtin/settingtypes.txt +++ b/builtin/settingtypes.txt @@ -859,7 +859,7 @@ font_path (Regular font path) filepath fonts/Arimo-Regular.ttf font_path_bold (Bold font path) filepath fonts/Arimo-Bold.ttf font_path_italic (Italic font path) filepath fonts/Arimo-Italic.ttf -font_path_bolditalic (Bold and italic font path) filepath fonts/Arimo-BoldItalic.ttf +font_path_bold_italic (Bold and italic font path) filepath fonts/Arimo-BoldItalic.ttf # Font size of the monospace font in point (pt). mono_font_size (Monospace font size) int 15 1 @@ -872,16 +872,7 @@ mono_font_path (Monospace font path) filepath fonts/Cousine-Regular.ttf mono_font_path_bold (Bold monospace font path) filepath fonts/Cousine-Bold.ttf mono_font_path_italic (Italic monospace font path) filepath fonts/Cousine-Italic.ttf -mono_font_path_bolditalic (Bold and italic monospace font path) filepath fonts/Cousine-BoldItalic.ttf - -# Font size of the fallback font in point (pt). -fallback_font_size (Fallback font size) int 15 1 - -# Shadow offset (in pixels) of the fallback font. If 0, then shadow will not be drawn. -fallback_font_shadow (Fallback font shadow) int 1 - -# Opaqueness (alpha) of the shadow behind the fallback font, between 0 and 255. -fallback_font_shadow_alpha (Fallback font shadow alpha) int 128 0 255 +mono_font_path_bold_italic (Bold and italic monospace font path) filepath fonts/Cousine-BoldItalic.ttf # Path of the fallback font. # If “freetype” setting is enabled: Must be a TrueType font. diff --git a/po/minetest.pot b/po/minetest.pot index 9881f5032..b5556d3f3 100644 --- a/po/minetest.pot +++ b/po/minetest.pot @@ -1085,18 +1085,6 @@ msgstr "" msgid "Invalid gamespec." msgstr "" -#. ~ DO NOT TRANSLATE THIS LITERALLY! -#. This is a special string. Put either "no" or "yes" -#. into the translation field (literally). -#. Choose "yes" if the language requires use of the fallback -#. font, "no" otherwise. -#. The fallback font is (normally) required for languages with -#. non-Latin script, like Chinese. -#. When in doubt, test your translation. -#: src/client/fontengine.cpp -msgid "needs_fallback_font" -msgstr "" - #: src/client/game.cpp msgid "Shutting down..." msgstr "" diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt index 8a6eabccc..4bb6877d9 100644 --- a/src/CMakeLists.txt +++ b/src/CMakeLists.txt @@ -668,7 +668,10 @@ endif(BUILD_SERVER) # see issue #4638 set(GETTEXT_BLACKLISTED_LOCALES ar + dv he + hi + kn ky ms_Arab th diff --git a/src/client/fontengine.cpp b/src/client/fontengine.cpp index 47218c0d9..0382c2f18 100644 --- a/src/client/fontengine.cpp +++ b/src/client/fontengine.cpp @@ -56,7 +56,7 @@ FontEngine::FontEngine(gui::IGUIEnvironment* env) : readSettings(); - if (m_currentMode == FM_Standard) { + if (m_currentMode != FM_Simple) { g_settings->registerChangedCallback("font_size", font_setting_changed, NULL); g_settings->registerChangedCallback("font_bold", font_setting_changed, NULL); g_settings->registerChangedCallback("font_italic", font_setting_changed, NULL); @@ -66,12 +66,7 @@ FontEngine::FontEngine(gui::IGUIEnvironment* env) : g_settings->registerChangedCallback("font_path_bolditalic", font_setting_changed, NULL); g_settings->registerChangedCallback("font_shadow", font_setting_changed, NULL); g_settings->registerChangedCallback("font_shadow_alpha", font_setting_changed, NULL); - } - else if (m_currentMode == FM_Fallback) { - g_settings->registerChangedCallback("fallback_font_size", font_setting_changed, NULL); g_settings->registerChangedCallback("fallback_font_path", font_setting_changed, NULL); - g_settings->registerChangedCallback("fallback_font_shadow", font_setting_changed, NULL); - g_settings->registerChangedCallback("fallback_font_shadow_alpha", font_setting_changed, NULL); } g_settings->registerChangedCallback("mono_font_path", font_setting_changed, NULL); @@ -101,6 +96,11 @@ void FontEngine::cleanCache() /******************************************************************************/ irr::gui::IGUIFont *FontEngine::getFont(FontSpec spec) +{ + return getFont(spec, false); +} + +irr::gui::IGUIFont *FontEngine::getFont(FontSpec spec, bool may_fail) { if (spec.mode == FM_Unspecified) { spec.mode = m_currentMode; @@ -112,6 +112,10 @@ irr::gui::IGUIFont *FontEngine::getFont(FontSpec spec) // Support for those could be added, but who cares? spec.bold = false; spec.italic = false; + } else if (spec.mode == _FM_Fallback) { + // Fallback font doesn't support these either + spec.bold = false; + spec.italic = false; } // Fallback to default size @@ -130,6 +134,13 @@ irr::gui::IGUIFont *FontEngine::getFont(FontSpec spec) else font = initFont(spec); + if (!font && !may_fail) { + errorstream << "Minetest cannot continue without a valid font. " + "Please correct the 'font_path' setting or install the font " + "file in the proper location." << std::endl; + abort(); + } + m_font_cache[spec.getHash()][spec.size] = font; return font; @@ -204,20 +215,9 @@ unsigned int FontEngine::getFontSize(FontMode mode) void FontEngine::readSettings() { if (USE_FREETYPE && g_settings->getBool("freetype")) { - m_default_size[FM_Standard] = g_settings->getU16("font_size"); - m_default_size[FM_Fallback] = g_settings->getU16("fallback_font_size"); - m_default_size[FM_Mono] = g_settings->getU16("mono_font_size"); - - /*~ DO NOT TRANSLATE THIS LITERALLY! - This is a special string. Put either "no" or "yes" - into the translation field (literally). - Choose "yes" if the language requires use of the fallback - font, "no" otherwise. - The fallback font is (normally) required for languages with - non-Latin script, like Chinese. - When in doubt, test your translation. */ - m_currentMode = is_yes(gettext("needs_fallback_font")) ? - FM_Fallback : FM_Standard; + m_default_size[FM_Standard] = g_settings->getU16("font_size"); + m_default_size[_FM_Fallback] = g_settings->getU16("font_size"); + m_default_size[FM_Mono] = g_settings->getU16("mono_font_size"); m_default_bold = g_settings->getBool("font_bold"); m_default_italic = g_settings->getBool("font_italic"); @@ -271,18 +271,8 @@ gui::IGUIFont *FontEngine::initFont(const FontSpec &spec) assert(spec.size != FONT_SIZE_UNSPECIFIED); std::string setting_prefix = ""; - - switch (spec.mode) { - case FM_Fallback: - setting_prefix = "fallback_"; - break; - case FM_Mono: - case FM_SimpleMono: - setting_prefix = "mono_"; - break; - default: - break; - } + if (spec.mode == FM_Mono) + setting_prefix = "mono_"; std::string setting_suffix = ""; if (spec.bold) @@ -305,38 +295,41 @@ gui::IGUIFont *FontEngine::initFont(const FontSpec &spec) g_settings->getU16NoEx(setting_prefix + "font_shadow_alpha", font_shadow_alpha); - std::string wanted_font_path; - wanted_font_path = g_settings->get(setting_prefix + "font_path" + setting_suffix); + std::string path_setting; + if (spec.mode == _FM_Fallback) + path_setting = "fallback_font_path"; + else + path_setting = setting_prefix + "font_path" + setting_suffix; std::string fallback_settings[] = { - wanted_font_path, - g_settings->get("fallback_font_path"), - Settings::getLayer(SL_DEFAULTS)->get(setting_prefix + "font_path") + g_settings->get(path_setting), + Settings::getLayer(SL_DEFAULTS)->get(path_setting) }; #if USE_FREETYPE for (const std::string &font_path : fallback_settings) { - irr::gui::IGUIFont *font = gui::CGUITTFont::createTTFont(m_env, + gui::CGUITTFont *font = gui::CGUITTFont::createTTFont(m_env, font_path.c_str(), size, true, true, font_shadow, font_shadow_alpha); - if (font) - return font; - - errorstream << "FontEngine: Cannot load '" << font_path << + if (!font) { + errorstream << "FontEngine: Cannot load '" << font_path << "'. Trying to fall back to another path." << std::endl; + continue; + } + + if (spec.mode != _FM_Fallback) { + FontSpec spec2(spec); + spec2.mode = _FM_Fallback; + font->setFallback(getFont(spec2, true)); + } + return font; } - - - // give up - errorstream << "minetest can not continue without a valid font. " - "Please correct the 'font_path' setting or install the font " - "file in the proper location" << std::endl; #else - errorstream << "FontEngine: Tried to load freetype fonts but Minetest was" - " not compiled with that library." << std::endl; + errorstream << "FontEngine: Tried to load TTF font but Minetest was" + " compiled without Freetype." << std::endl; #endif - abort(); + return nullptr; } /** initialize a font without freetype */ diff --git a/src/client/fontengine.h b/src/client/fontengine.h index e27ef60e9..3d389ea48 100644 --- a/src/client/fontengine.h +++ b/src/client/fontengine.h @@ -33,7 +33,7 @@ with this program; if not, write to the Free Software Foundation, Inc., enum FontMode : u8 { FM_Standard = 0, FM_Mono, - FM_Fallback, + _FM_Fallback, // do not use directly FM_Simple, FM_SimpleMono, FM_MaxMode, @@ -47,7 +47,7 @@ struct FontSpec { bold(bold), italic(italic) {} - u16 getHash() + u16 getHash() const { return (mode << 2) | (static_cast(bold) << 1) | static_cast(italic); } @@ -132,10 +132,12 @@ public: void readSettings(); private: + irr::gui::IGUIFont *getFont(FontSpec spec, bool may_fail); + /** update content of font cache in case of a setting change made it invalid */ void updateFontCache(); - /** initialize a new font */ + /** initialize a new TTF font */ gui::IGUIFont *initFont(const FontSpec &spec); /** initialize a font without freetype */ diff --git a/src/defaultsettings.cpp b/src/defaultsettings.cpp index 9d155f76c..a0d4e9d14 100644 --- a/src/defaultsettings.cpp +++ b/src/defaultsettings.cpp @@ -304,12 +304,7 @@ void set_default_settings() settings->setDefault("mono_font_path_bold_italic", porting::getDataPath("fonts" DIR_DELIM "Cousine-BoldItalic.ttf")); settings->setDefault("fallback_font_path", porting::getDataPath("fonts" DIR_DELIM "DroidSansFallbackFull.ttf")); - settings->setDefault("fallback_font_shadow", "1"); - settings->setDefault("fallback_font_shadow_alpha", "128"); - std::string font_size_str = std::to_string(TTF_DEFAULT_FONT_SIZE); - - settings->setDefault("fallback_font_size", font_size_str); #else settings->setDefault("freetype", "false"); settings->setDefault("font_path", porting::getDataPath("fonts" DIR_DELIM "mono_dejavu_sans")); diff --git a/src/irrlicht_changes/CGUITTFont.cpp b/src/irrlicht_changes/CGUITTFont.cpp index 960b2320a..8b01e88ae 100644 --- a/src/irrlicht_changes/CGUITTFont.cpp +++ b/src/irrlicht_changes/CGUITTFont.cpp @@ -275,7 +275,8 @@ CGUITTFont* CGUITTFont::create(IrrlichtDevice *device, const io::path& filename, //! Constructor. CGUITTFont::CGUITTFont(IGUIEnvironment *env) : use_monochrome(false), use_transparency(true), use_hinting(true), use_auto_hinting(true), -batch_load_size(1), Device(0), Environment(env), Driver(0), GlobalKerningWidth(0), GlobalKerningHeight(0) +batch_load_size(1), Device(0), Environment(env), Driver(0), GlobalKerningWidth(0), GlobalKerningHeight(0), +shadow_offset(0), shadow_alpha(0), fallback(0) { #ifdef _DEBUG setDebugName("CGUITTFont"); @@ -640,7 +641,30 @@ void CGUITTFont::draw(const EnrichedString &text, const core::rect& positio if (current_color < colors.size()) applied_colors.push_back(colors[current_color]); } - offset.X += getWidthFromCharacter(currentChar); + if (n > 0) + { + offset.X += getWidthFromCharacter(currentChar); + } + else if (fallback != 0) + { + // Let the fallback font draw it, this isn't super efficient but hopefully that doesn't matter + wchar_t l1[] = { (wchar_t) currentChar, 0 }, l2 = (wchar_t) previousChar; + + if (visible) + { + // Apply kerning. + offset.X += fallback->getKerningWidth(l1, &l2); + offset.Y += fallback->getKerningHeight(); + + u32 current_color = iter.getPos(); + fallback->draw(core::stringw(l1), + core::rect({offset.X-1, offset.Y-1}, position.LowerRightCorner), // ??? + current_color < colors.size() ? colors[current_color] : video::SColor(255, 255, 255, 255), + false, false, clip); + } + + offset.X += fallback->getDimension(l1).Width; + } previousChar = currentChar; ++iter; @@ -766,6 +790,12 @@ inline u32 CGUITTFont::getWidthFromCharacter(uchar32_t c) const int w = Glyphs[n-1].advance.x / 64; return w; } + if (fallback != 0) + { + wchar_t s[] = { (wchar_t) c, 0 }; + return fallback->getDimension(s).Width; + } + if (c >= 0x2000) return (font_metrics.ascender / 64); else return (font_metrics.ascender / 64) / 2; @@ -789,6 +819,12 @@ inline u32 CGUITTFont::getHeightFromCharacter(uchar32_t c) const s32 height = (font_metrics.ascender / 64) - Glyphs[n-1].offset.Y + Glyphs[n-1].source_rect.getHeight(); return height; } + if (fallback != 0) + { + wchar_t s[] = { (wchar_t) c, 0 }; + return fallback->getDimension(s).Height; + } + if (c >= 0x2000) return (font_metrics.ascender / 64); else return (font_metrics.ascender / 64) / 2; @@ -804,9 +840,9 @@ u32 CGUITTFont::getGlyphIndexByChar(uchar32_t c) const // Get the glyph. u32 glyph = FT_Get_Char_Index(tt_face, c); - // Check for a valid glyph. If it is invalid, attempt to use the replacement character. + // Check for a valid glyph. if (glyph == 0) - glyph = FT_Get_Char_Index(tt_face, core::unicode::UTF_REPLACEMENT_CHARACTER); + return 0; // If our glyph is already loaded, don't bother doing any batch loading code. if (glyph != 0 && Glyphs[glyph - 1].isLoaded) @@ -922,13 +958,26 @@ core::vector2di CGUITTFont::getKerning(const uchar32_t thisLetter, const uchar32 core::vector2di ret(GlobalKerningWidth, GlobalKerningHeight); + u32 n = getGlyphIndexByChar(thisLetter); + + // If we don't have this glyph, ask fallback font + if (n == 0) + { + if (fallback != 0) { + wchar_t l1 = (wchar_t) thisLetter, l2 = (wchar_t) previousLetter; + ret.X = fallback->getKerningWidth(&l1, &l2); + ret.Y = fallback->getKerningHeight(); + } + return ret; + } + // If we don't have kerning, no point in continuing. if (!FT_HAS_KERNING(tt_face)) return ret; // Get the kerning information. FT_Vector v; - FT_Get_Kerning(tt_face, getGlyphIndexByChar(previousLetter), getGlyphIndexByChar(thisLetter), FT_KERNING_DEFAULT, &v); + FT_Get_Kerning(tt_face, getGlyphIndexByChar(previousLetter), n, FT_KERNING_DEFAULT, &v); // If we have a scalable font, the return value will be in font points. if (FT_IS_SCALABLE(tt_face)) @@ -960,6 +1009,9 @@ void CGUITTFont::setInvisibleCharacters(const core::ustring& s) video::IImage* CGUITTFont::createTextureFromChar(const uchar32_t& ch) { u32 n = getGlyphIndexByChar(ch); + if (n == 0) + n = getGlyphIndexByChar((uchar32_t) core::unicode::UTF_REPLACEMENT_CHARACTER); + const SGUITTGlyph& glyph = Glyphs[n-1]; CGUITTGlyphPage* page = Glyph_Pages[glyph.glyph_page]; @@ -1147,6 +1199,8 @@ core::array CGUITTFont::addTextSceneNode(const wchar_t* text container.push_back(current_node); } offset.X += getWidthFromCharacter(current_char); + // Note that fallback font handling is missing here (Minetest never uses this) + previous_char = current_char; ++text; } diff --git a/src/irrlicht_changes/CGUITTFont.h b/src/irrlicht_changes/CGUITTFont.h index 310f74f67..a26a1db76 100644 --- a/src/irrlicht_changes/CGUITTFont.h +++ b/src/irrlicht_changes/CGUITTFont.h @@ -269,7 +269,7 @@ namespace gui video::SColor color, bool hcenter=false, bool vcenter=false, const core::rect* clip=0); - virtual void draw(const EnrichedString& text, const core::rect& position, + void draw(const EnrichedString& text, const core::rect& position, video::SColor color, bool hcenter=false, bool vcenter=false, const core::rect* clip=0); @@ -313,6 +313,9 @@ namespace gui //! Get the last glyph page's index. u32 getLastGlyphPageIndex() const { return Glyph_Pages.size() - 1; } + //! Set font that should be used for glyphs not present in ours + void setFallback(gui::IGUIFont* font) { fallback = font; } + //! Create corresponding character's software image copy from the font, //! so you can use this data just like any ordinary video::IImage. //! \param ch The character you need @@ -387,6 +390,8 @@ namespace gui core::ustring Invisible; u32 shadow_offset; u32 shadow_alpha; + + gui::IGUIFont* fallback; }; } // end namespace gui From 7c24a9ebef5c92bbdb930df6119276b74737fc76 Mon Sep 17 00:00:00 2001 From: Wuzzy Date: Sun, 28 Mar 2021 21:55:56 +0200 Subject: [PATCH 06/72] Update CONTRIBUTING info on translating builtin --- .github/CONTRIBUTING.md | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/.github/CONTRIBUTING.md b/.github/CONTRIBUTING.md index b01a89509..fbd372b3b 100644 --- a/.github/CONTRIBUTING.md +++ b/.github/CONTRIBUTING.md @@ -70,7 +70,9 @@ Feature requests are welcome but take a moment to see if your idea follows the r ## Translations -Translations of Minetest are performed using Weblate. You can access the project page with a list of current languages [here](https://hosted.weblate.org/projects/minetest/minetest/). +The core translations of Minetest are performed using Weblate. You can access the project page with a list of current languages [here](https://hosted.weblate.org/projects/minetest/minetest/). + +Builtin (the component which contains things like server messages, chat command descriptions, privilege descriptions) is translated separately; it needs to be translated by editing a `.tr` text file. See [Translation](https://dev.minetest.net/Translation) for more information. ## Donations From 7ad8ca62dcd0532e6b2e444e84ca6a5b5b5d8e95 Mon Sep 17 00:00:00 2001 From: Wuzzy Date: Mon, 29 Mar 2021 17:57:48 +0000 Subject: [PATCH 07/72] Clean up various misleading and/or confusing messages and texts related to priv changes (#11126) --- builtin/game/chat.lua | 102 +++++++++++++++++++++++++++--------- builtin/game/privileges.lua | 8 ++- 2 files changed, 85 insertions(+), 25 deletions(-) diff --git a/builtin/game/chat.lua b/builtin/game/chat.lua index 10da054fd..0bd12c25f 100644 --- a/builtin/game/chat.lua +++ b/builtin/game/chat.lua @@ -167,6 +167,18 @@ core.register_chatcommand("admin", { end, }) +local function privileges_of(name, privs) + if not privs then + privs = core.get_player_privs(name) + end + local privstr = core.privs_to_string(privs, ", ") + if privstr == "" then + return S("@1 does not have any privileges.", name) + else + return S("Privileges of @1: @2", name, privstr) + end +end + core.register_chatcommand("privs", { params = S("[]"), description = S("Show privileges of yourself or another player"), @@ -176,9 +188,7 @@ core.register_chatcommand("privs", { if not core.player_exists(name) then return false, S("Player @1 does not exist.", name) end - return true, S("Privileges of @1: @2", name, - core.privs_to_string( - core.get_player_privs(name), ", ")) + return true, privileges_of(name) end, }) @@ -227,7 +237,10 @@ local function handle_grant_command(caller, grantname, grantprivstr) core.string_to_privs(core.settings:get("basic_privs") or "interact,shout") for priv, _ in pairs(grantprivs) do if not basic_privs[priv] and not caller_privs.privs then - return false, S("Your privileges are insufficient.") + return false, S("Your privileges are insufficient. ".. + "'@1' only allows you to grant: @2", + "basic_privs", + core.privs_to_string(basic_privs, ', ')) end if not core.registered_privileges[priv] then privs_unknown = privs_unknown .. S("Unknown privilege: @1", priv) .. "\n" @@ -246,15 +259,13 @@ local function handle_grant_command(caller, grantname, grantprivstr) if grantname ~= caller then core.chat_send_player(grantname, S("@1 granted you privileges: @2", caller, - core.privs_to_string(grantprivs, ' '))) + core.privs_to_string(grantprivs, ', '))) end - return true, S("Privileges of @1: @2", grantname, - core.privs_to_string( - core.get_player_privs(grantname), ' ')) + return true, privileges_of(grantname) end core.register_chatcommand("grant", { - params = S(" ( | all)"), + params = S(" ( [, [<...>]] | all)"), description = S("Give privileges to player"), func = function(name, param) local grantname, grantprivstr = string.match(param, "([^ ]+) (.+)") @@ -266,7 +277,7 @@ core.register_chatcommand("grant", { }) core.register_chatcommand("grantme", { - params = S(" | all"), + params = S(" [, [<...>]] | all"), description = S("Grant privileges to yourself"), func = function(name, param) if param == "" then @@ -286,16 +297,13 @@ local function handle_revoke_command(caller, revokename, revokeprivstr) return false, S("Player @1 does not exist.", revokename) end - local revokeprivs = core.string_to_privs(revokeprivstr) local privs = core.get_player_privs(revokename) - local basic_privs = - core.string_to_privs(core.settings:get("basic_privs") or "interact,shout") - for priv, _ in pairs(revokeprivs) do - if not basic_privs[priv] and not caller_privs.privs then - return false, S("Your privileges are insufficient.") - end - end + local revokeprivs = core.string_to_privs(revokeprivstr) + local is_singleplayer = core.is_singleplayer() + local is_admin = not is_singleplayer + and revokename == core.settings:get("name") + and revokename ~= "" if revokeprivstr == "all" then revokeprivs = privs privs = {} @@ -305,27 +313,73 @@ local function handle_revoke_command(caller, revokename, revokeprivstr) end end + local privs_unknown = "" + local basic_privs = + core.string_to_privs(core.settings:get("basic_privs") or "interact,shout") + local irrevokable = {} + local has_irrevokable_priv = false + for priv, _ in pairs(revokeprivs) do + if not basic_privs[priv] and not caller_privs.privs then + return false, S("Your privileges are insufficient. ".. + "'@1' only allows you to revoke: @2", + "basic_privs", + core.privs_to_string(basic_privs, ', ')) + end + local def = core.registered_privileges[priv] + if not def then + privs_unknown = privs_unknown .. S("Unknown privilege: @1", priv) .. "\n" + elseif is_singleplayer and def.give_to_singleplayer then + irrevokable[priv] = true + elseif is_admin and def.give_to_admin then + irrevokable[priv] = true + end + end + for priv, _ in pairs(irrevokable) do + revokeprivs[priv] = nil + has_irrevokable_priv = true + end + if privs_unknown ~= "" then + return false, privs_unknown + end + if has_irrevokable_priv then + if is_singleplayer then + core.chat_send_player(caller, + S("Note: Cannot revoke in singleplayer: @1", + core.privs_to_string(irrevokable, ', '))) + elseif is_admin then + core.chat_send_player(caller, + S("Note: Cannot revoke from admin: @1", + core.privs_to_string(irrevokable, ', '))) + end + end + + local revokecount = 0 for priv, _ in pairs(revokeprivs) do -- call the on_revoke callbacks core.run_priv_callbacks(revokename, priv, caller, "revoke") + revokecount = revokecount + 1 end core.set_player_privs(revokename, privs) + local new_privs = core.get_player_privs(revokename) + + if revokecount == 0 then + return false, S("No privileges were revoked.") + end + core.log("action", caller..' revoked (' ..core.privs_to_string(revokeprivs, ', ') ..') privileges from '..revokename) if revokename ~= caller then core.chat_send_player(revokename, S("@1 revoked privileges from you: @2", caller, - core.privs_to_string(revokeprivs, ' '))) + core.privs_to_string(revokeprivs, ', '))) end - return true, S("Privileges of @1: @2", revokename, - core.privs_to_string( - core.get_player_privs(revokename), ' ')) + return true, privileges_of(revokename, new_privs) end core.register_chatcommand("revoke", { - params = S(" ( | all)"), + params = S(" ( [, [<...>]] | all)"), description = S("Remove privileges from player"), privs = {}, func = function(name, param) @@ -338,7 +392,7 @@ core.register_chatcommand("revoke", { }) core.register_chatcommand("revokeme", { - params = S(" | all"), + params = S(" [, [<...>]] | all"), description = S("Revoke privileges from yourself"), privs = {}, func = function(name, param) diff --git a/builtin/game/privileges.lua b/builtin/game/privileges.lua index aee32a34e..1d3efb525 100644 --- a/builtin/game/privileges.lua +++ b/builtin/game/privileges.lua @@ -32,7 +32,13 @@ end core.register_privilege("interact", S("Can interact with things and modify the world")) core.register_privilege("shout", S("Can speak in chat")) -core.register_privilege("basic_privs", S("Can modify 'shout' and 'interact' privileges")) + +local basic_privs = + core.string_to_privs((core.settings:get("basic_privs") or "shout,interact")) +local basic_privs_desc = S("Can modify basic privileges (@1)", + core.privs_to_string(basic_privs, ', ')) +core.register_privilege("basic_privs", basic_privs_desc) + core.register_privilege("privs", S("Can modify privileges")) core.register_privilege("teleport", { From fde2785fe363c55e8acfd17af71375a231df41c1 Mon Sep 17 00:00:00 2001 From: Emojigit <55009343+Emojigit@users.noreply.github.com> Date: Tue, 30 Mar 2021 01:58:39 +0800 Subject: [PATCH 08/72] Update language choices in settingtypes.txt (#11124) --- builtin/settingtypes.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/builtin/settingtypes.txt b/builtin/settingtypes.txt index 1f8bf97b7..67f4877a3 100644 --- a/builtin/settingtypes.txt +++ b/builtin/settingtypes.txt @@ -1386,7 +1386,7 @@ name (Player name) string # Set the language. Leave empty to use the system language. # A restart is required after changing this. -language (Language) enum ,ar,ca,cs,da,de,dv,el,en,eo,es,et,eu,fil,fr,hu,id,it,ja,ja_KS,jbo,kk,kn,lo,lt,ms,my,nb,nl,nn,pl,pt,pt_BR,ro,ru,sl,sr_Cyrl,sv,sw,th,tr,uk,vi +language (Language) enum ,be,bg,ca,cs,da,de,el,en,eo,es,et,eu,fi,fr,gd,gl,hu,id,it,ja,jbo,kk,ko,lt,lv,ms,nb,nl,nn,pl,pt,pt_BR,ro,ru,sk,sl,sr_Cyrl,sr_Latn,sv,sw,tr,uk,vi,zh_CN,zh_TW # Level of logging to be written to debug.txt: # - (no logging) From 3b78a223717c69918a5af422e21561f47ec74ce1 Mon Sep 17 00:00:00 2001 From: Vitaliy Date: Tue, 30 Mar 2021 01:25:11 +0300 Subject: [PATCH 09/72] Degrotate support for mesh nodes (#7840) --- builtin/game/item.lua | 6 ++- doc/lua_api.txt | 11 +++-- games/devtest/mods/testnodes/drawtypes.lua | 56 +++++++++++++++++++++- src/client/content_mapblock.cpp | 16 +++++-- src/client/content_mapblock.h | 2 +- src/mapnode.cpp | 21 ++++++++ src/mapnode.h | 3 ++ src/nodedef.cpp | 3 +- src/nodedef.h | 4 +- src/script/common/c_content.cpp | 3 +- src/script/cpp_api/s_node.cpp | 1 + 11 files changed, 113 insertions(+), 13 deletions(-) diff --git a/builtin/game/item.lua b/builtin/game/item.lua index b68177c22..17746e9a8 100644 --- a/builtin/game/item.lua +++ b/builtin/game/item.lua @@ -157,7 +157,7 @@ end function core.is_colored_paramtype(ptype) return (ptype == "color") or (ptype == "colorfacedir") or - (ptype == "colorwallmounted") + (ptype == "colorwallmounted") or (ptype == "colordegrotate") end function core.strip_param2_color(param2, paramtype2) @@ -168,6 +168,8 @@ function core.strip_param2_color(param2, paramtype2) param2 = math.floor(param2 / 32) * 32 elseif paramtype2 == "colorwallmounted" then param2 = math.floor(param2 / 8) * 8 + elseif paramtype2 == "colordegrotate" then + param2 = math.floor(param2 / 32) * 32 end -- paramtype2 == "color" requires no modification. return param2 @@ -345,6 +347,8 @@ function core.item_place_node(itemstack, placer, pointed_thing, param2, color_divisor = 8 elseif def.paramtype2 == "colorfacedir" then color_divisor = 32 + elseif def.paramtype2 == "colordegrotate" then + color_divisor = 32 end if color_divisor then local color = math.floor(metatable.palette_index / color_divisor) diff --git a/doc/lua_api.txt b/doc/lua_api.txt index 737a690f6..8804c9e7f 100644 --- a/doc/lua_api.txt +++ b/doc/lua_api.txt @@ -1048,9 +1048,9 @@ The function of `param2` is determined by `paramtype2` in node definition. * The height of the 'plantlike' section is stored in `param2`. * The height is (`param2` / 16) nodes. * `paramtype2 = "degrotate"` - * Only valid for "plantlike" drawtype. The rotation of the node is stored in - `param2`. - * Values range 0 - 179. The value stored in `param2` is multiplied by two to + * Valid for `plantlike` and `mesh` drawtypes. The rotation of the node is + stored in `param2`. + * Values range 0–239. The value stored in `param2` is multiplied by 1.5 to get the actual rotation in degrees of the node. * `paramtype2 = "meshoptions"` * Only valid for "plantlike" drawtype. `param2` encodes the shape and @@ -1088,6 +1088,11 @@ The function of `param2` is determined by `paramtype2` in node definition. * `param2` values 0-63 define 64 levels of internal liquid, 0 being empty and 63 being full. * Liquid texture is defined using `special_tiles = {"modname_tilename.png"}` +* `paramtype2 = "colordegrotate"` + * Same as `degrotate`, but with colors. + * The first (most-significant) three bits of `param2` tells which color + is picked from the palette. The palette should have 8 pixels. + * Remaining 5 bits store rotation in range 0–23 (i.e. in 15° steps) * `paramtype2 = "none"` * `param2` will not be used by the engine and can be used to store an arbitrary value diff --git a/games/devtest/mods/testnodes/drawtypes.lua b/games/devtest/mods/testnodes/drawtypes.lua index ff970144d..02d71b50d 100644 --- a/games/devtest/mods/testnodes/drawtypes.lua +++ b/games/devtest/mods/testnodes/drawtypes.lua @@ -223,6 +223,30 @@ minetest.register_node("testnodes:plantlike_waving", { -- param2 will rotate +local function rotate_on_rightclick(pos, node, clicker) + local def = minetest.registered_nodes[node.name] + local aux1 = clicker:get_player_control().aux1 + + local deg, deg_max + local color, color_mult = 0, 0 + if def.paramtype2 == "degrotate" then + deg = node.param2 + deg_max = 240 + elseif def.paramtype2 == "colordegrotate" then + -- MSB [3x color, 5x rotation] LSB + deg = node.param2 % 2^5 + deg_max = 24 + color_mult = 2^5 + color = math.floor(node.param2 / color_mult) + end + + deg = (deg + (aux1 and 10 or 1)) % deg_max + node.param2 = color * color_mult + deg + minetest.swap_node(pos, node) + minetest.chat_send_player(clicker:get_player_name(), + "Rotation is now " .. deg .. " / " .. deg_max) +end + minetest.register_node("testnodes:plantlike_degrotate", { description = S("Degrotate Plantlike Drawtype Test Node"), drawtype = "plantlike", @@ -230,12 +254,42 @@ minetest.register_node("testnodes:plantlike_degrotate", { paramtype2 = "degrotate", tiles = { "testnodes_plantlike_degrotate.png" }, - + on_rightclick = rotate_on_rightclick, + place_param2 = 7, walkable = false, sunlight_propagates = true, groups = { dig_immediate = 3 }, }) +minetest.register_node("testnodes:mesh_degrotate", { + description = S("Degrotate Mesh Drawtype Test Node"), + drawtype = "mesh", + paramtype = "light", + paramtype2 = "degrotate", + mesh = "testnodes_pyramid.obj", + tiles = { "testnodes_mesh_stripes2.png" }, + + on_rightclick = rotate_on_rightclick, + place_param2 = 7, + sunlight_propagates = true, + groups = { dig_immediate = 3 }, +}) + +minetest.register_node("testnodes:mesh_colordegrotate", { + description = S("Color Degrotate Mesh Drawtype Test Node"), + drawtype = "mesh", + paramtype2 = "colordegrotate", + palette = "testnodes_palette_facedir.png", + mesh = "testnodes_pyramid.obj", + tiles = { "testnodes_mesh_stripes2.png" }, + + on_rightclick = rotate_on_rightclick, + -- color index 1, 7 steps rotated + place_param2 = 1 * 2^5 + 7, + sunlight_propagates = true, + groups = { dig_immediate = 3 }, +}) + -- param2 will change height minetest.register_node("testnodes:plantlike_leveled", { description = S("Leveled Plantlike Drawtype Test Node"), diff --git a/src/client/content_mapblock.cpp b/src/client/content_mapblock.cpp index 90284ecce..ce7235bca 100644 --- a/src/client/content_mapblock.cpp +++ b/src/client/content_mapblock.cpp @@ -968,7 +968,7 @@ void MapblockMeshGenerator::drawPlantlike() draw_style = PLANT_STYLE_CROSS; scale = BS / 2 * f->visual_scale; offset = v3f(0, 0, 0); - rotate_degree = 0; + rotate_degree = 0.0f; random_offset_Y = false; face_num = 0; plant_height = 1.0; @@ -988,7 +988,8 @@ void MapblockMeshGenerator::drawPlantlike() break; case CPT2_DEGROTATE: - rotate_degree = n.param2 * 2; + case CPT2_COLORED_DEGROTATE: + rotate_degree = 1.5f * n.getDegRotate(nodedef); break; case CPT2_LEVELED: @@ -1343,6 +1344,7 @@ void MapblockMeshGenerator::drawMeshNode() u8 facedir = 0; scene::IMesh* mesh; bool private_mesh; // as a grab/drop pair is not thread-safe + int degrotate = 0; if (f->param_type_2 == CPT2_FACEDIR || f->param_type_2 == CPT2_COLORED_FACEDIR) { @@ -1354,9 +1356,12 @@ void MapblockMeshGenerator::drawMeshNode() facedir = n.getWallMounted(nodedef); if (!enable_mesh_cache) facedir = wallmounted_to_facedir[facedir]; + } else if (f->param_type_2 == CPT2_DEGROTATE || + f->param_type_2 == CPT2_COLORED_DEGROTATE) { + degrotate = n.getDegRotate(nodedef); } - if (!data->m_smooth_lighting && f->mesh_ptr[facedir]) { + if (!data->m_smooth_lighting && f->mesh_ptr[facedir] && !degrotate) { // use cached meshes private_mesh = false; mesh = f->mesh_ptr[facedir]; @@ -1364,7 +1369,10 @@ void MapblockMeshGenerator::drawMeshNode() // no cache, clone and rotate mesh private_mesh = true; mesh = cloneMesh(f->mesh_ptr[0]); - rotateMeshBy6dFacedir(mesh, facedir); + if (facedir) + rotateMeshBy6dFacedir(mesh, facedir); + else if (degrotate) + rotateMeshXZby(mesh, 1.5f * degrotate); recalculateBoundingBox(mesh); meshmanip->recalculateNormals(mesh, true, false); } else diff --git a/src/client/content_mapblock.h b/src/client/content_mapblock.h index 487d84a07..a6c450d1f 100644 --- a/src/client/content_mapblock.h +++ b/src/client/content_mapblock.h @@ -139,7 +139,7 @@ public: // plantlike-specific PlantlikeStyle draw_style; v3f offset; - int rotate_degree; + float rotate_degree; bool random_offset_Y; int face_num; float plant_height; diff --git a/src/mapnode.cpp b/src/mapnode.cpp index 0551f3b6f..20980b238 100644 --- a/src/mapnode.cpp +++ b/src/mapnode.cpp @@ -177,6 +177,16 @@ v3s16 MapNode::getWallMountedDir(const NodeDefManager *nodemgr) const } } +u8 MapNode::getDegRotate(const NodeDefManager *nodemgr) const +{ + const ContentFeatures &f = nodemgr->get(*this); + if (f.param_type_2 == CPT2_DEGROTATE) + return getParam2() % 240; + if (f.param_type_2 == CPT2_COLORED_DEGROTATE) + return 10 * ((getParam2() & 0x1F) % 24); + return 0; +} + void MapNode::rotateAlongYAxis(const NodeDefManager *nodemgr, Rotation rot) { ContentParamType2 cpt2 = nodemgr->get(*this).param_type_2; @@ -230,6 +240,17 @@ void MapNode::rotateAlongYAxis(const NodeDefManager *nodemgr, Rotation rot) Rotation oldrot = wallmounted_to_rot[wmountface - 2]; param2 &= ~7; param2 |= rot_to_wallmounted[(oldrot - rot) & 3]; + } else if (cpt2 == CPT2_DEGROTATE) { + int angle = param2; // in 1.5° + angle += 60 * rot; // don’t do that on u8 + angle %= 240; + param2 = angle; + } else if (cpt2 == CPT2_COLORED_DEGROTATE) { + int angle = param2 & 0x1F; // in 15° + int color = param2 & 0xE0; + angle += 6 * rot; + angle %= 24; + param2 = color | angle; } } diff --git a/src/mapnode.h b/src/mapnode.h index a9ae63ba3..28ff9e43d 100644 --- a/src/mapnode.h +++ b/src/mapnode.h @@ -240,6 +240,9 @@ struct MapNode u8 getWallMounted(const NodeDefManager *nodemgr) const; v3s16 getWallMountedDir(const NodeDefManager *nodemgr) const; + /// @returns Rotation in range 0–239 (in 1.5° steps) + u8 getDegRotate(const NodeDefManager *nodemgr) const; + void rotateAlongYAxis(const NodeDefManager *nodemgr, Rotation rot); /*! diff --git a/src/nodedef.cpp b/src/nodedef.cpp index 8a1f6203b..3dcac439f 100644 --- a/src/nodedef.cpp +++ b/src/nodedef.cpp @@ -944,7 +944,8 @@ void ContentFeatures::updateTextures(ITextureSource *tsrc, IShaderSource *shdsrc if (param_type_2 == CPT2_COLOR || param_type_2 == CPT2_COLORED_FACEDIR || - param_type_2 == CPT2_COLORED_WALLMOUNTED) + param_type_2 == CPT2_COLORED_WALLMOUNTED || + param_type_2 == CPT2_COLORED_DEGROTATE) palette = tsrc->getPalette(palette_name); if (drawtype == NDT_MESH && !mesh.empty()) { diff --git a/src/nodedef.h b/src/nodedef.h index 3e77624eb..b8cf7c14d 100644 --- a/src/nodedef.h +++ b/src/nodedef.h @@ -67,7 +67,7 @@ enum ContentParamType2 CPT2_WALLMOUNTED, // Block level like FLOWINGLIQUID CPT2_LEVELED, - // 2D rotation for things like plants + // 2D rotation CPT2_DEGROTATE, // Mesh options for plants CPT2_MESHOPTIONS, @@ -79,6 +79,8 @@ enum ContentParamType2 CPT2_COLORED_WALLMOUNTED, // Glasslike framed drawtype internal liquid level, param2 values 0 to 63 CPT2_GLASSLIKE_LIQUID_LEVEL, + // 3 bits of palette index, then degrotate + CPT2_COLORED_DEGROTATE, }; enum LiquidType diff --git a/src/script/common/c_content.cpp b/src/script/common/c_content.cpp index eca0c89d1..52baeae9d 100644 --- a/src/script/common/c_content.cpp +++ b/src/script/common/c_content.cpp @@ -685,7 +685,8 @@ void read_content_features(lua_State *L, ContentFeatures &f, int index) if (!f.palette_name.empty() && !(f.param_type_2 == CPT2_COLOR || f.param_type_2 == CPT2_COLORED_FACEDIR || - f.param_type_2 == CPT2_COLORED_WALLMOUNTED)) + f.param_type_2 == CPT2_COLORED_WALLMOUNTED || + f.param_type_2 == CPT2_COLORED_DEGROTATE)) warningstream << "Node " << f.name.c_str() << " has a palette, but not a suitable paramtype2." << std::endl; diff --git a/src/script/cpp_api/s_node.cpp b/src/script/cpp_api/s_node.cpp index f23fbfbde..029cb6308 100644 --- a/src/script/cpp_api/s_node.cpp +++ b/src/script/cpp_api/s_node.cpp @@ -65,6 +65,7 @@ struct EnumString ScriptApiNode::es_ContentParamType2[] = {CPT2_COLORED_FACEDIR, "colorfacedir"}, {CPT2_COLORED_WALLMOUNTED, "colorwallmounted"}, {CPT2_GLASSLIKE_LIQUID_LEVEL, "glasslikeliquidlevel"}, + {CPT2_COLORED_DEGROTATE, "colordegrotate"}, {0, NULL}, }; From 6c9be39db0d8ae2759cc8d6d5c4b952d13cf4f64 Mon Sep 17 00:00:00 2001 From: Wuzzy Date: Mon, 29 Mar 2021 22:27:46 +0000 Subject: [PATCH 10/72] Fix wield image of plantlike_rooted (#11067) --- src/client/wieldmesh.cpp | 10 +++++++++- 1 file changed, 9 insertions(+), 1 deletion(-) diff --git a/src/client/wieldmesh.cpp b/src/client/wieldmesh.cpp index 387eb17c3..9806644df 100644 --- a/src/client/wieldmesh.cpp +++ b/src/client/wieldmesh.cpp @@ -395,7 +395,6 @@ void WieldMeshSceneNode::setItem(const ItemStack &item, Client *client, bool che case NDT_TORCHLIKE: case NDT_RAILLIKE: case NDT_PLANTLIKE: - case NDT_PLANTLIKE_ROOTED: case NDT_FLOWINGLIQUID: { v3f wscale = def.wield_scale; if (f.drawtype == NDT_FLOWINGLIQUID) @@ -411,6 +410,15 @@ void WieldMeshSceneNode::setItem(const ItemStack &item, Client *client, bool che m_colors.emplace_back(l1.has_color, l1.color); break; } + case NDT_PLANTLIKE_ROOTED: { + setExtruded(tsrc->getTextureName(f.special_tiles[0].layers[0].texture_id), + "", def.wield_scale, tsrc, + f.special_tiles[0].layers[0].animation_frame_count); + // Add color + const TileLayer &l0 = f.special_tiles[0].layers[0]; + m_colors.emplace_back(l0.has_color, l0.color); + break; + } case NDT_NORMAL: case NDT_ALLFACES: case NDT_LIQUID: From f345d00a436b88e6583896065aab237ff12a9d3d Mon Sep 17 00:00:00 2001 From: sfan5 Date: Tue, 30 Mar 2021 14:04:14 +0200 Subject: [PATCH 11/72] Add entry in features table for degrotate changes --- builtin/game/features.lua | 1 + doc/lua_api.txt | 3 +++ 2 files changed, 4 insertions(+) diff --git a/builtin/game/features.lua b/builtin/game/features.lua index 36ff1f0b0..8f0604448 100644 --- a/builtin/game/features.lua +++ b/builtin/game/features.lua @@ -19,6 +19,7 @@ core.features = { object_step_has_moveresult = true, direct_velocity_on_players = true, use_texture_alpha_string_modes = true, + degrotate_240_steps = true, } function core.has_feature(arg) diff --git a/doc/lua_api.txt b/doc/lua_api.txt index 8804c9e7f..66363be77 100644 --- a/doc/lua_api.txt +++ b/doc/lua_api.txt @@ -4397,6 +4397,9 @@ Utilities direct_velocity_on_players = true, -- nodedef's use_texture_alpha accepts new string modes (5.4.0) use_texture_alpha_string_modes = true, + -- degrotate param2 rotates in units of 1.5° instead of 2° + -- thus changing the range of values from 0-179 to 0-240 (5.5.0) + degrotate_240_steps = true, } * `minetest.has_feature(arg)`: returns `boolean, missing_features` From f4118a4fdebe5c8a4a467afe5b3f49a0bd74c37a Mon Sep 17 00:00:00 2001 From: SmallJoker Date: Tue, 30 Mar 2021 21:49:15 +0200 Subject: [PATCH 12/72] Consistent title bar + render information in mainmenu (#10764) --- builtin/mainmenu/init.lua | 4 ++-- builtin/mainmenu/{tab_credits.lua => tab_about.lua} | 11 ++++++++--- doc/menu_lua_api.txt | 3 ++- src/client/game.cpp | 12 ++++++++++++ src/script/lua_api/l_mainmenu.cpp | 12 ++++-------- 5 files changed, 28 insertions(+), 14 deletions(-) rename builtin/mainmenu/{tab_credits.lua => tab_about.lua} (94%) diff --git a/builtin/mainmenu/init.lua b/builtin/mainmenu/init.lua index 45089c7c9..0c8578cd6 100644 --- a/builtin/mainmenu/init.lua +++ b/builtin/mainmenu/init.lua @@ -49,7 +49,7 @@ local tabs = {} tabs.settings = dofile(menupath .. DIR_DELIM .. "tab_settings.lua") tabs.content = dofile(menupath .. DIR_DELIM .. "tab_content.lua") -tabs.credits = dofile(menupath .. DIR_DELIM .. "tab_credits.lua") +tabs.about = dofile(menupath .. DIR_DELIM .. "tab_about.lua") tabs.local_game = dofile(menupath .. DIR_DELIM .. "tab_local.lua") tabs.play_online = dofile(menupath .. DIR_DELIM .. "tab_online.lua") @@ -98,7 +98,7 @@ local function init_globals() tv_main:add(tabs.content) tv_main:add(tabs.settings) - tv_main:add(tabs.credits) + tv_main:add(tabs.about) tv_main:set_global_event_handler(main_event_handler) tv_main:set_fixed_size(false) diff --git a/builtin/mainmenu/tab_credits.lua b/builtin/mainmenu/tab_about.lua similarity index 94% rename from builtin/mainmenu/tab_credits.lua rename to builtin/mainmenu/tab_about.lua index a34dd58bb..a1a7d4bfb 100644 --- a/builtin/mainmenu/tab_credits.lua +++ b/builtin/mainmenu/tab_about.lua @@ -97,8 +97,8 @@ local function buildCreditList(source) end return { - name = "credits", - caption = fgettext("Credits"), + name = "about", + caption = fgettext("About"), cbf_formspec = function(tabview, name, tabdata) local logofile = defaulttexturedir .. "logo.png" local version = core.get_version() @@ -119,11 +119,16 @@ return { buildCreditList(previous_contributors) .. "," .. ";1]" + -- Render information + fs = fs .. "label[0.75,4.9;" .. + fgettext("Active renderer:") .. "\n" .. + core.formspec_escape(core.get_screen_info().render_info) .. "]" + if PLATFORM ~= "Android" then fs = fs .. "tooltip[userdata;" .. fgettext("Opens the directory that contains user-provided worlds, games, mods,\n" .. "and texture packs in a file manager / explorer.") .. "]" - fs = fs .. "button[0,4.75;3.5,1;userdata;" .. fgettext("Open User Data Directory") .. "]" + fs = fs .. "button[0,4;3.5,1;userdata;" .. fgettext("Open User Data Directory") .. "]" end return fs diff --git a/doc/menu_lua_api.txt b/doc/menu_lua_api.txt index 90ec527b0..f4dfff261 100644 --- a/doc/menu_lua_api.txt +++ b/doc/menu_lua_api.txt @@ -204,7 +204,8 @@ core.get_screen_info() display_width = , display_height = , window_width = , - window_height = + window_height = , + render_info = } diff --git a/src/client/game.cpp b/src/client/game.cpp index 31c782c51..334f1da67 100644 --- a/src/client/game.cpp +++ b/src/client/game.cpp @@ -1390,9 +1390,21 @@ bool Game::createClient(const GameStartData &start_data) std::wstring str = utf8_to_wide(PROJECT_NAME_C); str += L" "; str += utf8_to_wide(g_version_hash); + { + const wchar_t *text = nullptr; + if (simple_singleplayer_mode) + text = wgettext("Singleplayer"); + else + text = wgettext("Multiplayer"); + str += L" ["; + str += text; + str += L"]"; + delete text; + } str += L" ["; str += driver->getName(); str += L"]"; + device->setWindowCaption(str.c_str()); LocalPlayer *player = client->getEnv().getLocalPlayer(); diff --git a/src/script/lua_api/l_mainmenu.cpp b/src/script/lua_api/l_mainmenu.cpp index ba7f708a4..6826ece05 100644 --- a/src/script/lua_api/l_mainmenu.cpp +++ b/src/script/lua_api/l_mainmenu.cpp @@ -856,14 +856,6 @@ int ModApiMainMenu::l_get_screen_info(lua_State *L) lua_pushnumber(L,RenderingEngine::getDisplayDensity()); lua_settable(L, top); - lua_pushstring(L,"display_width"); - lua_pushnumber(L,RenderingEngine::getDisplaySize().X); - lua_settable(L, top); - - lua_pushstring(L,"display_height"); - lua_pushnumber(L,RenderingEngine::getDisplaySize().Y); - lua_settable(L, top); - const v2u32 &window_size = RenderingEngine::get_instance()->getWindowSize(); lua_pushstring(L,"window_width"); lua_pushnumber(L, window_size.X); @@ -872,6 +864,10 @@ int ModApiMainMenu::l_get_screen_info(lua_State *L) lua_pushstring(L,"window_height"); lua_pushnumber(L, window_size.Y); lua_settable(L, top); + + lua_pushstring(L, "render_info"); + lua_pushstring(L, wide_to_utf8(RenderingEngine::get_video_driver()->getName()).c_str()); + lua_settable(L, top); return 1; } From 88d1fcfe237470b6eaed079f95a048e5f39b1861 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Lars=20M=C3=BCller?= <34514239+appgurueu@users.noreply.github.com> Date: Tue, 30 Mar 2021 21:49:50 +0200 Subject: [PATCH 13/72] Block & report player self-interaction (#11137) --- doc/lua_api.txt | 1 + src/network/serverpackethandler.cpp | 6 ++++++ 2 files changed, 7 insertions(+) diff --git a/doc/lua_api.txt b/doc/lua_api.txt index 66363be77..d333ca58b 100644 --- a/doc/lua_api.txt +++ b/doc/lua_api.txt @@ -4662,6 +4662,7 @@ Call these functions only at load time! * `cheat`: `{type=}`, where `` is one of: * `moved_too_fast` * `interacted_too_far` + * `interacted_with_self` * `interacted_while_dead` * `finished_unknown_dig` * `dug_unbreakable` diff --git a/src/network/serverpackethandler.cpp b/src/network/serverpackethandler.cpp index 5b378a083..708ddbf20 100644 --- a/src/network/serverpackethandler.cpp +++ b/src/network/serverpackethandler.cpp @@ -1051,6 +1051,12 @@ void Server::handleCommand_Interact(NetworkPacket *pkt) if (pointed.type == POINTEDTHING_NODE) { target_pos = intToFloat(pointed.node_undersurface, BS); } else if (pointed.type == POINTEDTHING_OBJECT) { + if (playersao->getId() == pointed_object->getId()) { + actionstream << "Server: " << player->getName() + << " attempted to interact with themselves" << std::endl; + m_script->on_cheat(playersao, "interacted_with_self"); + return; + } target_pos = pointed_object->getBasePosition(); } float d = playersao->getEyePosition().getDistanceFrom(target_pos); From 0d90ed6d921baefbb1a969df69f7b86e702e962f Mon Sep 17 00:00:00 2001 From: sfan5 Date: Tue, 30 Mar 2021 21:50:39 +0200 Subject: [PATCH 14/72] Draw items as 2D images (instead of meshes) when possible --- src/client/hud.cpp | 44 +++++++++++++++++++++++++++++--------------- 1 file changed, 29 insertions(+), 15 deletions(-) diff --git a/src/client/hud.cpp b/src/client/hud.cpp index 74c1828e3..e5c7a4cfd 100644 --- a/src/client/hud.cpp +++ b/src/client/hud.cpp @@ -945,10 +945,16 @@ void drawItemStack( return; } - const ItemDefinition &def = item.getDefinition(client->idef()); - ItemMesh *imesh = client->idef()->getWieldMesh(def.name, client); + const static thread_local bool enable_animations = + g_settings->getBool("inventory_items_animations"); - if (imesh && imesh->mesh) { + const ItemDefinition &def = item.getDefinition(client->idef()); + + // Render as mesh if animated or no inventory image + if ((enable_animations && rotation_kind < IT_ROT_NONE) || def.inventory_image.empty()) { + ItemMesh *imesh = client->idef()->getWieldMesh(def.name, client); + if (!imesh || !imesh->mesh) + return; scene::IMesh *mesh = imesh->mesh; driver->clearBuffers(video::ECBF_DEPTH); s32 delta = 0; @@ -992,9 +998,6 @@ void drawItemStack( core::matrix4 matrix; matrix.makeIdentity(); - static thread_local bool enable_animations = - g_settings->getBool("inventory_items_animations"); - if (enable_animations) { float timer_f = (float) delta / 5000.f; matrix.setRotationDegrees(v3f( @@ -1039,16 +1042,27 @@ void drawItemStack( driver->setTransform(video::ETS_VIEW, oldViewMat); driver->setTransform(video::ETS_PROJECTION, oldProjMat); driver->setViewPort(oldViewPort); + } else { // Otherwise just draw as 2D + video::ITexture *texture = client->idef()->getInventoryTexture(def.name, client); + if (!texture) + return; + video::SColor color = + client->idef()->getItemstackColor(item, client); + const video::SColor colors[] = { color, color, color, color }; - // draw the inventory_overlay - if (def.type == ITEM_NODE && def.inventory_image.empty() && - !def.inventory_overlay.empty()) { - ITextureSource *tsrc = client->getTextureSource(); - video::ITexture *overlay_texture = tsrc->getTexture(def.inventory_overlay); - core::dimension2d dimens = overlay_texture->getOriginalSize(); - core::rect srcrect(0, 0, dimens.Width, dimens.Height); - draw2DImageFilterScaled(driver, overlay_texture, rect, srcrect, clip, 0, true); - } + draw2DImageFilterScaled(driver, texture, rect, + core::rect({0, 0}, core::dimension2di(texture->getOriginalSize())), + clip, colors, true); + } + + // draw the inventory_overlay + if (def.type == ITEM_NODE && def.inventory_image.empty() && + !def.inventory_overlay.empty()) { + ITextureSource *tsrc = client->getTextureSource(); + video::ITexture *overlay_texture = tsrc->getTexture(def.inventory_overlay); + core::dimension2d dimens = overlay_texture->getOriginalSize(); + core::rect srcrect(0, 0, dimens.Width, dimens.Height); + draw2DImageFilterScaled(driver, overlay_texture, rect, srcrect, clip, 0, true); } if (def.type == ITEM_TOOL && item.wear != 0) { From 1e4913cd76f5d31456d04a5ce23e66d5c60060de Mon Sep 17 00:00:00 2001 From: sfan5 Date: Wed, 31 Mar 2021 13:15:47 +0200 Subject: [PATCH 15/72] Irrlicht support code maintenance --- src/client/clientlauncher.cpp | 2 -- src/client/content_cao.cpp | 3 --- src/client/game.cpp | 23 ----------------------- src/client/keycode.cpp | 2 -- src/client/mesh.cpp | 8 -------- src/client/wieldmesh.cpp | 2 -- src/irrlicht_changes/CGUITTFont.cpp | 8 -------- src/irrlicht_changes/CGUITTFont.h | 2 +- src/irrlicht_changes/static_text.cpp | 4 ---- src/irrlicht_changes/static_text.h | 4 ---- src/irrlichttypes.h | 26 ++++---------------------- 11 files changed, 5 insertions(+), 79 deletions(-) diff --git a/src/client/clientlauncher.cpp b/src/client/clientlauncher.cpp index 2bb0bc385..b1b801947 100644 --- a/src/client/clientlauncher.cpp +++ b/src/client/clientlauncher.cpp @@ -178,11 +178,9 @@ bool ClientLauncher::run(GameStartData &start_data, const Settings &cmd_args) g_fontengine = new FontEngine(guienv); FATAL_ERROR_IF(g_fontengine == NULL, "Font engine creation failed."); -#if (IRRLICHT_VERSION_MAJOR >= 1 && IRRLICHT_VERSION_MINOR >= 8) || IRRLICHT_VERSION_MAJOR >= 2 // Irrlicht 1.8 input colours skin->setColor(gui::EGDC_EDITABLE, video::SColor(255, 128, 128, 128)); skin->setColor(gui::EGDC_FOCUSED_EDITABLE, video::SColor(255, 96, 134, 49)); -#endif // Create the menu clouds if (!g_menucloudsmgr) diff --git a/src/client/content_cao.cpp b/src/client/content_cao.cpp index 97ae9afc4..63b8821f4 100644 --- a/src/client/content_cao.cpp +++ b/src/client/content_cao.cpp @@ -1473,11 +1473,8 @@ void GenericCAO::updateAnimation() if (m_animated_meshnode->getAnimationSpeed() != m_animation_speed) m_animated_meshnode->setAnimationSpeed(m_animation_speed); m_animated_meshnode->setTransitionTime(m_animation_blend); -// Requires Irrlicht 1.8 or greater -#if (IRRLICHT_VERSION_MAJOR == 1 && IRRLICHT_VERSION_MINOR >= 8) || IRRLICHT_VERSION_MAJOR > 1 if (m_animated_meshnode->getLoopMode() != m_animation_loop) m_animated_meshnode->setLoopMode(m_animation_loop); -#endif } void GenericCAO::updateAnimationSpeed() diff --git a/src/client/game.cpp b/src/client/game.cpp index 334f1da67..22b7ee875 100644 --- a/src/client/game.cpp +++ b/src/client/game.cpp @@ -400,12 +400,7 @@ public: }; -// before 1.8 there isn't a "integer interface", only float -#if (IRRLICHT_VERSION_MAJOR == 1 && IRRLICHT_VERSION_MINOR < 8) -typedef f32 SamplerLayer_t; -#else typedef s32 SamplerLayer_t; -#endif class GameGlobalShaderConstantSetter : public IShaderConstantSetter @@ -513,38 +508,20 @@ public: float eye_position_array[3]; v3f epos = m_client->getEnv().getLocalPlayer()->getEyePosition(); -#if (IRRLICHT_VERSION_MAJOR == 1 && IRRLICHT_VERSION_MINOR < 8) - eye_position_array[0] = epos.X; - eye_position_array[1] = epos.Y; - eye_position_array[2] = epos.Z; -#else epos.getAs3Values(eye_position_array); -#endif m_eye_position_pixel.set(eye_position_array, services); m_eye_position_vertex.set(eye_position_array, services); if (m_client->getMinimap()) { float minimap_yaw_array[3]; v3f minimap_yaw = m_client->getMinimap()->getYawVec(); -#if (IRRLICHT_VERSION_MAJOR == 1 && IRRLICHT_VERSION_MINOR < 8) - minimap_yaw_array[0] = minimap_yaw.X; - minimap_yaw_array[1] = minimap_yaw.Y; - minimap_yaw_array[2] = minimap_yaw.Z; -#else minimap_yaw.getAs3Values(minimap_yaw_array); -#endif m_minimap_yaw.set(minimap_yaw_array, services); } float camera_offset_array[3]; v3f offset = intToFloat(m_client->getCamera()->getOffset(), BS); -#if (IRRLICHT_VERSION_MAJOR == 1 && IRRLICHT_VERSION_MINOR < 8) - camera_offset_array[0] = offset.X; - camera_offset_array[1] = offset.Y; - camera_offset_array[2] = offset.Z; -#else offset.getAs3Values(camera_offset_array); -#endif m_camera_offset_pixel.set(camera_offset_array, services); m_camera_offset_vertex.set(camera_offset_array, services); diff --git a/src/client/keycode.cpp b/src/client/keycode.cpp index ce5214f54..fac077f0f 100644 --- a/src/client/keycode.cpp +++ b/src/client/keycode.cpp @@ -197,7 +197,6 @@ static const struct table_key table[] = { DEFINEKEY1(KEY_MODECHANGE, N_("IME Mode Change")) DEFINEKEY1(KEY_APPS, N_("Apps")) DEFINEKEY1(KEY_SLEEP, N_("Sleep")) -#if !(IRRLICHT_VERSION_MAJOR <= 1 && IRRLICHT_VERSION_MINOR <= 7 && IRRLICHT_VERSION_REVISION < 3) DEFINEKEY1(KEY_OEM_1, "OEM 1") // KEY_OEM_[0-9] and KEY_OEM_102 are assigned to multiple DEFINEKEY1(KEY_OEM_2, "OEM 2") // different chars (on different platforms too) and thus w/o char DEFINEKEY1(KEY_OEM_3, "OEM 3") @@ -208,7 +207,6 @@ static const struct table_key table[] = { DEFINEKEY1(KEY_OEM_8, "OEM 8") DEFINEKEY1(KEY_OEM_AX, "OEM AX") DEFINEKEY1(KEY_OEM_102, "OEM 102") -#endif DEFINEKEY1(KEY_ATTN, "Attn") DEFINEKEY1(KEY_CRSEL, "CrSel") DEFINEKEY1(KEY_EXSEL, "ExSel") diff --git a/src/client/mesh.cpp b/src/client/mesh.cpp index 2400a374c..e43139218 100644 --- a/src/client/mesh.cpp +++ b/src/client/mesh.cpp @@ -27,14 +27,6 @@ with this program; if not, write to the Free Software Foundation, Inc., #include #include -// In Irrlicht 1.8 the signature of ITexture::lock was changed from -// (bool, u32) to (E_TEXTURE_LOCK_MODE, u32). -#if IRRLICHT_VERSION_MAJOR == 1 && IRRLICHT_VERSION_MINOR <= 7 -#define MY_ETLM_READ_ONLY true -#else -#define MY_ETLM_READ_ONLY video::ETLM_READ_ONLY -#endif - inline static void applyShadeFactor(video::SColor& color, float factor) { color.setRed(core::clamp(core::round32(color.getRed()*factor), 0, 255)); diff --git a/src/client/wieldmesh.cpp b/src/client/wieldmesh.cpp index 9806644df..e76bbfa9e 100644 --- a/src/client/wieldmesh.cpp +++ b/src/client/wieldmesh.cpp @@ -294,9 +294,7 @@ void WieldMeshSceneNode::setExtruded(const std::string &imagename, } material.setFlag(video::EMF_ANISOTROPIC_FILTER, m_anisotropic_filter); // mipmaps cause "thin black line" artifacts -#if (IRRLICHT_VERSION_MAJOR == 1 && IRRLICHT_VERSION_MINOR >= 8) || IRRLICHT_VERSION_MAJOR >= 2 material.setFlag(video::EMF_USE_MIP_MAPS, false); -#endif if (m_enable_shaders) { material.setTexture(2, tsrc->getShaderFlagsTexture(false)); } diff --git a/src/irrlicht_changes/CGUITTFont.cpp b/src/irrlicht_changes/CGUITTFont.cpp index 8b01e88ae..05a1ae43e 100644 --- a/src/irrlicht_changes/CGUITTFont.cpp +++ b/src/irrlicht_changes/CGUITTFont.cpp @@ -1021,11 +1021,7 @@ video::IImage* CGUITTFont::createTextureFromChar(const uchar32_t& ch) video::ITexture* tex = page->texture; // Acquire a read-only lock of the corresponding page texture. - #if IRRLICHT_VERSION_MAJOR==1 && IRRLICHT_VERSION_MINOR>=8 void* ptr = tex->lock(video::ETLM_READ_ONLY); - #else - void* ptr = tex->lock(true); - #endif video::ECOLOR_FORMAT format = tex->getColorFormat(); core::dimension2du tex_size = tex->getOriginalSize(); @@ -1182,11 +1178,7 @@ core::array CGUITTFont::addTextSceneNode(const wchar_t* text // Now we copy planes corresponding to the letter size. IMeshManipulator* mani = smgr->getMeshManipulator(); IMesh* meshcopy = mani->createMeshCopy(shared_plane_ptr_); - #if IRRLICHT_VERSION_MAJOR==1 && IRRLICHT_VERSION_MINOR>=8 mani->scale(meshcopy, vector3df((f32)letter_size.Width, (f32)letter_size.Height, 1)); - #else - mani->scaleMesh(meshcopy, vector3df((f32)letter_size.Width, (f32)letter_size.Height, 1)); - #endif ISceneNode* current_node = smgr->addMeshSceneNode(meshcopy, parent, -1, current_pos); meshcopy->drop(); diff --git a/src/irrlicht_changes/CGUITTFont.h b/src/irrlicht_changes/CGUITTFont.h index a26a1db76..141ea3931 100644 --- a/src/irrlicht_changes/CGUITTFont.h +++ b/src/irrlicht_changes/CGUITTFont.h @@ -34,7 +34,7 @@ #include #include #include -#include "irrUString.h" +#include #include "util/enriched_string.h" #include FT_FREETYPE_H diff --git a/src/irrlicht_changes/static_text.cpp b/src/irrlicht_changes/static_text.cpp index a8cc33352..b20707bbd 100644 --- a/src/irrlicht_changes/static_text.cpp +++ b/src/irrlicht_changes/static_text.cpp @@ -246,11 +246,7 @@ void StaticText::setTextAlignment(EGUI_ALIGNMENT horizontal, EGUI_ALIGNMENT vert } -#if IRRLICHT_VERSION_MAJOR == 1 && IRRLICHT_VERSION_MINOR <= 7 -const video::SColor& StaticText::getOverrideColor() const -#else video::SColor StaticText::getOverrideColor() const -#endif { return ColoredText.getDefaultColor(); } diff --git a/src/irrlicht_changes/static_text.h b/src/irrlicht_changes/static_text.h index 786129d57..83bbf4c3d 100644 --- a/src/irrlicht_changes/static_text.h +++ b/src/irrlicht_changes/static_text.h @@ -134,11 +134,7 @@ namespace gui virtual void setTextAlignment(EGUI_ALIGNMENT horizontal, EGUI_ALIGNMENT vertical); //! Gets the override color - #if IRRLICHT_VERSION_MAJOR == 1 && IRRLICHT_VERSION_MINOR <= 7 - virtual const video::SColor& getOverrideColor() const; - #else virtual video::SColor getOverrideColor() const; - #endif #if IRRLICHT_VERSION_MAJOR == 1 && IRRLICHT_VERSION_MINOR > 8 //! Gets the currently used text color diff --git a/src/irrlichttypes.h b/src/irrlichttypes.h index 794776b26..93c2d105b 100644 --- a/src/irrlichttypes.h +++ b/src/irrlichttypes.h @@ -19,16 +19,11 @@ with this program; if not, write to the Free Software Foundation, Inc., #pragma once -/* Ensure that is included before , unless building on - * MSVC, to address an irrlicht issue: https://sourceforge.net/p/irrlicht/bugs/433/ - * - * TODO: Decide whether or not we support non-compliant C++ compilers like old - * versions of MSCV. If we do not then can always be included - * regardless of the compiler. +/* + * IrrlichtMt already includes stdint.h in irrTypes.h. This works everywhere + * we need it to (including recent MSVC), so should be fine here too. */ -#ifndef _MSC_VER -# include -#endif +#include #include @@ -36,19 +31,6 @@ using namespace irr; namespace irr { -// Irrlicht 1.8+ defines 64bit unsigned symbol in irrTypes.h -#if (IRRLICHT_VERSION_MAJOR == 1 && IRRLICHT_VERSION_MINOR < 8) -#ifdef _MSC_VER - // Windows - typedef long long s64; - typedef unsigned long long u64; -#else - // Posix - typedef int64_t s64; - typedef uint64_t u64; -#endif -#endif - #if (IRRLICHT_VERSION_MAJOR == 1 && IRRLICHT_VERSION_MINOR >= 9) namespace core { template From 3560691c0aecd89dc7f7d91ed8c4f1eaa9715eaf Mon Sep 17 00:00:00 2001 From: Vincent Robinson Date: Thu, 1 Apr 2021 15:18:58 -0700 Subject: [PATCH 16/72] Add `math.round` and fix `vector.round` (#10803) --- .luacheckrc | 2 +- builtin/common/misc_helpers.lua | 9 +++++++++ builtin/common/vector.lua | 6 +++--- doc/lua_api.txt | 3 +++ 4 files changed, 16 insertions(+), 4 deletions(-) diff --git a/.luacheckrc b/.luacheckrc index e010ab95c..a922bdea9 100644 --- a/.luacheckrc +++ b/.luacheckrc @@ -20,7 +20,7 @@ read_globals = { string = {fields = {"split", "trim"}}, table = {fields = {"copy", "getn", "indexof", "insert_all"}}, - math = {fields = {"hypot"}}, + math = {fields = {"hypot", "round"}}, } globals = { diff --git a/builtin/common/misc_helpers.lua b/builtin/common/misc_helpers.lua index 0f3897f47..d5f25f2fe 100644 --- a/builtin/common/misc_helpers.lua +++ b/builtin/common/misc_helpers.lua @@ -244,6 +244,15 @@ function math.factorial(x) return v end + +function math.round(x) + if x >= 0 then + return math.floor(x + 0.5) + end + return math.ceil(x - 0.5) +end + + function core.formspec_escape(text) if text ~= nil then text = string.gsub(text,"\\","\\\\") diff --git a/builtin/common/vector.lua b/builtin/common/vector.lua index d6437deda..b04c12610 100644 --- a/builtin/common/vector.lua +++ b/builtin/common/vector.lua @@ -41,9 +41,9 @@ end function vector.round(v) return { - x = math.floor(v.x + 0.5), - y = math.floor(v.y + 0.5), - z = math.floor(v.z + 0.5) + x = math.round(v.x), + y = math.round(v.y), + z = math.round(v.z) } end diff --git a/doc/lua_api.txt b/doc/lua_api.txt index d333ca58b..8a8f57eb3 100644 --- a/doc/lua_api.txt +++ b/doc/lua_api.txt @@ -3163,6 +3163,7 @@ For the following functions, `v`, `v1`, `v2` are vectors, * Returns a vector, each dimension rounded down. * `vector.round(v)`: * Returns a vector, each dimension rounded to nearest integer. + * At a multiple of 0.5, rounds away from zero. * `vector.apply(v, func)`: * Returns a vector where the function `func` has been applied to each component. @@ -3237,6 +3238,8 @@ Helper functions * If the absolute value of `x` is within the `tolerance` or `x` is NaN, `0` is returned. * `math.factorial(x)`: returns the factorial of `x` +* `math.round(x)`: Returns `x` rounded to the nearest integer. + * At a multiple of 0.5, rounds away from zero. * `string.split(str, separator, include_empty, max_splits, sep_is_pattern)` * `separator`: string, default: `","` * `include_empty`: boolean, default: `false` From 34888a914e1eccce8082f45089aec17d5a2815c2 Mon Sep 17 00:00:00 2001 From: sfan5 Date: Fri, 2 Apr 2021 00:19:39 +0200 Subject: [PATCH 17/72] Sort out cURL timeouts and increase default --- builtin/settingtypes.txt | 7 +++--- doc/lua_api.txt | 2 +- src/client/clientmedia.cpp | 8 ++----- src/client/clientmedia.h | 1 - src/convert_json.cpp | 47 +------------------------------------- src/convert_json.h | 3 --- src/defaultsettings.cpp | 2 +- src/httpfetch.cpp | 21 ++++++++--------- 8 files changed, 18 insertions(+), 73 deletions(-) diff --git a/builtin/settingtypes.txt b/builtin/settingtypes.txt index 67f4877a3..f7412c1ee 100644 --- a/builtin/settingtypes.txt +++ b/builtin/settingtypes.txt @@ -1413,9 +1413,8 @@ enable_ipv6 (IPv6) bool true [*Advanced] -# Default timeout for cURL, stated in milliseconds. -# Only has an effect if compiled with cURL. -curl_timeout (cURL timeout) int 5000 +# Maximum time an interactive request (e.g. server list fetch) may take, stated in milliseconds. +curl_timeout (cURL interactive timeout) int 20000 # Limits number of parallel HTTP requests. Affects: # - Media fetch if server uses remote_media setting. @@ -1424,7 +1423,7 @@ curl_timeout (cURL timeout) int 5000 # Only has an effect if compiled with cURL. curl_parallel_limit (cURL parallel limit) int 8 -# Maximum time in ms a file download (e.g. a mod download) may take. +# Maximum time a file download (e.g. a mod download) may take, stated in milliseconds. curl_file_download_timeout (cURL file download timeout) int 300000 # Makes DirectX work with LuaJIT. Disable if it causes troubles. diff --git a/doc/lua_api.txt b/doc/lua_api.txt index 8a8f57eb3..3630221e3 100644 --- a/doc/lua_api.txt +++ b/doc/lua_api.txt @@ -8394,7 +8394,7 @@ Used by `HTTPApiTable.fetch` and `HTTPApiTable.fetch_async`. url = "http://example.org", timeout = 10, - -- Timeout for connection in seconds. Default is 3 seconds. + -- Timeout for request to be completed in seconds. Default depends on engine settings. method = "GET", "POST", "PUT" or "DELETE" -- The http method to use. Defaults to "GET". diff --git a/src/client/clientmedia.cpp b/src/client/clientmedia.cpp index c4c08c05d..0f9ba5356 100644 --- a/src/client/clientmedia.cpp +++ b/src/client/clientmedia.cpp @@ -216,7 +216,6 @@ void ClientMediaDownloader::initialStep(Client *client) // This is the first time we use httpfetch, so alloc a caller ID m_httpfetch_caller = httpfetch_caller_alloc(); - m_httpfetch_timeout = g_settings->getS32("curl_timeout"); // Set the active fetch limit to curl_parallel_limit or 84, // whichever is greater. This gives us some leeway so that @@ -258,8 +257,6 @@ void ClientMediaDownloader::initialStep(Client *client) remote->baseurl + MTHASHSET_FILE_NAME; fetch_request.caller = m_httpfetch_caller; fetch_request.request_id = m_httpfetch_next_id; // == i - fetch_request.timeout = m_httpfetch_timeout; - fetch_request.connect_timeout = m_httpfetch_timeout; fetch_request.method = HTTP_POST; fetch_request.raw_data = required_hash_set; fetch_request.extra_headers.emplace_back( @@ -432,9 +429,8 @@ void ClientMediaDownloader::startRemoteMediaTransfers() fetch_request.url = url; fetch_request.caller = m_httpfetch_caller; fetch_request.request_id = m_httpfetch_next_id; - fetch_request.timeout = 0; // no data timeout! - fetch_request.connect_timeout = - m_httpfetch_timeout; + fetch_request.timeout = + g_settings->getS32("curl_file_download_timeout"); httpfetch_async(fetch_request); m_remote_file_transfers.insert(std::make_pair( diff --git a/src/client/clientmedia.h b/src/client/clientmedia.h index 5a918535b..e97a0f24b 100644 --- a/src/client/clientmedia.h +++ b/src/client/clientmedia.h @@ -137,7 +137,6 @@ private: // Status of remote transfers unsigned long m_httpfetch_caller; unsigned long m_httpfetch_next_id = 0; - long m_httpfetch_timeout = 0; s32 m_httpfetch_active = 0; s32 m_httpfetch_active_limit = 0; s32 m_outstanding_hash_sets = 0; diff --git a/src/convert_json.cpp b/src/convert_json.cpp index e9ff1e56c..686113fa8 100644 --- a/src/convert_json.cpp +++ b/src/convert_json.cpp @@ -17,56 +17,11 @@ with this program; if not, write to the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. */ -#include #include #include +#include #include "convert_json.h" -#include "content/mods.h" -#include "config.h" -#include "log.h" -#include "settings.h" -#include "httpfetch.h" -#include "porting.h" - -Json::Value fetchJsonValue(const std::string &url, - std::vector *extra_headers) -{ - HTTPFetchRequest fetch_request; - HTTPFetchResult fetch_result; - fetch_request.url = url; - fetch_request.caller = HTTPFETCH_SYNC; - - if (extra_headers != NULL) - fetch_request.extra_headers = *extra_headers; - - httpfetch_sync(fetch_request, fetch_result); - - if (!fetch_result.succeeded) { - return Json::Value(); - } - Json::Value root; - std::istringstream stream(fetch_result.data); - - Json::CharReaderBuilder builder; - builder.settings_["collectComments"] = false; - std::string errs; - - if (!Json::parseFromStream(builder, stream, &root, &errs)) { - errorstream << "URL: " << url << std::endl; - errorstream << "Failed to parse json data " << errs << std::endl; - if (fetch_result.data.size() > 100) { - errorstream << "Data (" << fetch_result.data.size() - << " bytes) printed to warningstream." << std::endl; - warningstream << "data: \"" << fetch_result.data << "\"" << std::endl; - } else { - errorstream << "data: \"" << fetch_result.data << "\"" << std::endl; - } - return Json::Value(); - } - - return root; -} void fastWriteJson(const Json::Value &value, std::ostream &to) { diff --git a/src/convert_json.h b/src/convert_json.h index 2c094a946..d1d487e77 100644 --- a/src/convert_json.h +++ b/src/convert_json.h @@ -22,9 +22,6 @@ with this program; if not, write to the Free Software Foundation, Inc., #include #include -Json::Value fetchJsonValue(const std::string &url, - std::vector *extra_headers); - void fastWriteJson(const Json::Value &value, std::ostream &to); std::string fastWriteJson(const Json::Value &value); diff --git a/src/defaultsettings.cpp b/src/defaultsettings.cpp index a0d4e9d14..4ecf77c0e 100644 --- a/src/defaultsettings.cpp +++ b/src/defaultsettings.cpp @@ -56,7 +56,7 @@ void set_default_settings() settings->setDefault("client_unload_unused_data_timeout", "600"); settings->setDefault("client_mapblock_limit", "7500"); settings->setDefault("enable_build_where_you_stand", "false"); - settings->setDefault("curl_timeout", "5000"); + settings->setDefault("curl_timeout", "20000"); settings->setDefault("curl_parallel_limit", "8"); settings->setDefault("curl_file_download_timeout", "300000"); settings->setDefault("curl_verify_cert", "true"); diff --git a/src/httpfetch.cpp b/src/httpfetch.cpp index 65202ce3e..6137782ff 100644 --- a/src/httpfetch.cpp +++ b/src/httpfetch.cpp @@ -22,7 +22,7 @@ with this program; if not, write to the Free Software Foundation, Inc., #include #include #include -#include +#include #include #include #include "network/socket.h" // for select() @@ -37,13 +37,14 @@ with this program; if not, write to the Free Software Foundation, Inc., #include "settings.h" #include "noise.h" -std::mutex g_httpfetch_mutex; -std::map > g_httpfetch_results; -PcgRandom g_callerid_randomness; +static std::mutex g_httpfetch_mutex; +static std::unordered_map> + g_httpfetch_results; +static PcgRandom g_callerid_randomness; HTTPFetchRequest::HTTPFetchRequest() : timeout(g_settings->getS32("curl_timeout")), - connect_timeout(timeout), + connect_timeout(10 * 1000), useragent(std::string(PROJECT_NAME_C "/") + g_version_hash + " (" + porting::get_sysinfo() + ")") { } @@ -54,7 +55,7 @@ static void httpfetch_deliver_result(const HTTPFetchResult &fetch_result) unsigned long caller = fetch_result.caller; if (caller != HTTPFETCH_DISCARD) { MutexAutoLock lock(g_httpfetch_mutex); - g_httpfetch_results[caller].push(fetch_result); + g_httpfetch_results[caller].emplace(fetch_result); } } @@ -67,8 +68,7 @@ unsigned long httpfetch_caller_alloc() // Check each caller ID except HTTPFETCH_DISCARD const unsigned long discard = HTTPFETCH_DISCARD; for (unsigned long caller = discard + 1; caller != discard; ++caller) { - std::map >::iterator - it = g_httpfetch_results.find(caller); + auto it = g_httpfetch_results.find(caller); if (it == g_httpfetch_results.end()) { verbosestream << "httpfetch_caller_alloc: allocating " << caller << std::endl; @@ -127,8 +127,7 @@ bool httpfetch_async_get(unsigned long caller, HTTPFetchResult &fetch_result) MutexAutoLock lock(g_httpfetch_mutex); // Check that caller exists - std::map >::iterator - it = g_httpfetch_results.find(caller); + auto it = g_httpfetch_results.find(caller); if (it == g_httpfetch_results.end()) return false; @@ -138,7 +137,7 @@ bool httpfetch_async_get(unsigned long caller, HTTPFetchResult &fetch_result) return false; // Pop first result - fetch_result = caller_results.front(); + fetch_result = std::move(caller_results.front()); caller_results.pop(); return true; } From 024d47e0d38c382c6b1974bb4d019058acd77e67 Mon Sep 17 00:00:00 2001 From: sfan5 Date: Fri, 2 Apr 2021 00:20:16 +0200 Subject: [PATCH 18/72] CGUITTFont optimizations (#11136) --- src/gui/guiChatConsole.cpp | 1 - src/irrlicht_changes/CGUITTFont.cpp | 39 +++++++++++++++++----------- src/irrlicht_changes/CGUITTFont.h | 3 ++- src/irrlicht_changes/static_text.cpp | 7 +---- 4 files changed, 27 insertions(+), 23 deletions(-) diff --git a/src/gui/guiChatConsole.cpp b/src/gui/guiChatConsole.cpp index a4e91fe78..b7af0ca0f 100644 --- a/src/gui/guiChatConsole.cpp +++ b/src/gui/guiChatConsole.cpp @@ -326,7 +326,6 @@ void GUIChatConsole::drawText() tmp->draw( fragment.text, destrect, - video::SColor(255, 255, 255, 255), false, false, &AbsoluteClippingRect); diff --git a/src/irrlicht_changes/CGUITTFont.cpp b/src/irrlicht_changes/CGUITTFont.cpp index 05a1ae43e..e785ea837 100644 --- a/src/irrlicht_changes/CGUITTFont.cpp +++ b/src/irrlicht_changes/CGUITTFont.cpp @@ -547,12 +547,12 @@ void CGUITTFont::setFontHinting(const bool enable, const bool enable_auto_hintin void CGUITTFont::draw(const core::stringw& text, const core::rect& position, video::SColor color, bool hcenter, bool vcenter, const core::rect* clip) { - draw(EnrichedString(std::wstring(text.c_str()), color), position, color, hcenter, vcenter, clip); + draw(EnrichedString(std::wstring(text.c_str()), color), position, hcenter, vcenter, clip); } -void CGUITTFont::draw(const EnrichedString &text, const core::rect& position, video::SColor color, bool hcenter, bool vcenter, const core::rect* clip) +void CGUITTFont::draw(const EnrichedString &text, const core::rect& position, bool hcenter, bool vcenter, const core::rect* clip) { - std::vector colors = text.getColors(); + const std::vector &colors = text.getColors(); if (!Driver) return; @@ -562,6 +562,7 @@ void CGUITTFont::draw(const EnrichedString &text, const core::rect& positio { Glyph_Pages[i]->render_positions.clear(); Glyph_Pages[i]->render_source_rects.clear(); + Glyph_Pages[i]->render_colors.clear(); } // Set up some variables. @@ -590,7 +591,6 @@ void CGUITTFont::draw(const EnrichedString &text, const core::rect& positio u32 n; uchar32_t previousChar = 0; core::ustring::const_iterator iter(utext); - std::vector applied_colors; while (!iter.atEnd()) { uchar32_t currentChar = *iter; @@ -636,10 +636,11 @@ void CGUITTFont::draw(const EnrichedString &text, const core::rect& positio CGUITTGlyphPage* const page = Glyph_Pages[glyph.glyph_page]; page->render_positions.push_back(core::position2di(offset.X + offx, offset.Y + offy)); page->render_source_rects.push_back(glyph.source_rect); + if (iter.getPos() < colors.size()) + page->render_colors.push_back(colors[iter.getPos()]); + else + page->render_colors.push_back(video::SColor(255,255,255,255)); Render_Map.set(glyph.glyph_page, page); - u32 current_color = iter.getPos(); - if (current_color < colors.size()) - applied_colors.push_back(colors[current_color]); } if (n > 0) { @@ -688,16 +689,24 @@ void CGUITTFont::draw(const EnrichedString &text, const core::rect& positio for (size_t i = 0; i < page->render_positions.size(); ++i) page->render_positions[i] -= core::vector2di(shadow_offset, shadow_offset); } + // render runs of matching color in batch + size_t ibegin; + video::SColor colprev; for (size_t i = 0; i < page->render_positions.size(); ++i) { - irr::video::SColor col; - if (!applied_colors.empty()) { - col = applied_colors[i < applied_colors.size() ? i : 0]; - } else { - col = irr::video::SColor(255, 255, 255, 255); - } + ibegin = i; + colprev = page->render_colors[i]; + do + ++i; + while (i < page->render_positions.size() && page->render_colors[i] == colprev); + core::array tmp_positions; + core::array tmp_source_rects; + tmp_positions.set_pointer(&page->render_positions[ibegin], i - ibegin, false, false); // no copy + tmp_source_rects.set_pointer(&page->render_source_rects[ibegin], i - ibegin, false, false); + --i; + if (!use_transparency) - col.color |= 0xff000000; - Driver->draw2DImage(page->texture, page->render_positions[i], page->render_source_rects[i], clip, col, true); + colprev.color |= 0xff000000; + Driver->draw2DImageBatch(page->texture, tmp_positions, tmp_source_rects, clip, colprev, true); } } } diff --git a/src/irrlicht_changes/CGUITTFont.h b/src/irrlicht_changes/CGUITTFont.h index 141ea3931..7b04ae828 100644 --- a/src/irrlicht_changes/CGUITTFont.h +++ b/src/irrlicht_changes/CGUITTFont.h @@ -199,6 +199,7 @@ namespace gui core::array render_positions; core::array render_source_rects; + core::array render_colors; private: core::array glyph_to_be_paged; @@ -270,7 +271,7 @@ namespace gui const core::rect* clip=0); void draw(const EnrichedString& text, const core::rect& position, - video::SColor color, bool hcenter=false, bool vcenter=false, + bool hcenter=false, bool vcenter=false, const core::rect* clip=0); //! Returns the dimension of a character produced by this font. diff --git a/src/irrlicht_changes/static_text.cpp b/src/irrlicht_changes/static_text.cpp index b20707bbd..8908a91f7 100644 --- a/src/irrlicht_changes/static_text.cpp +++ b/src/irrlicht_changes/static_text.cpp @@ -108,16 +108,11 @@ void StaticText::draw() font->getDimension(str.c_str()).Width; } - //str = colorizeText(BrokenText[i].c_str(), colors, previous_color); - //if (!colors.empty()) - // previous_color = colors[colors.size() - 1]; - #if USE_FREETYPE if (font->getType() == irr::gui::EGFT_CUSTOM) { irr::gui::CGUITTFont *tmp = static_cast(font); tmp->draw(str, - r, previous_color, // FIXME - HAlign == EGUIA_CENTER, VAlign == EGUIA_CENTER, + r, HAlign == EGUIA_CENTER, VAlign == EGUIA_CENTER, (RestrainTextInside ? &AbsoluteClippingRect : NULL)); } else #endif From c4b048fbb395bcfaa0627e5de672dd1064a7301e Mon Sep 17 00:00:00 2001 From: Loic Blot Date: Fri, 2 Apr 2021 09:25:50 +0200 Subject: [PATCH 19/72] fix: don't send the whole local context to the docker image --- .dockerignore | 4 ++++ Dockerfile | 2 +- 2 files changed, 5 insertions(+), 1 deletion(-) create mode 100644 .dockerignore diff --git a/.dockerignore b/.dockerignore new file mode 100644 index 000000000..bda43ebc0 --- /dev/null +++ b/.dockerignore @@ -0,0 +1,4 @@ +./cmake-build-* +./build/* +./cache/* +Dockerfile diff --git a/Dockerfile b/Dockerfile index 33eba64ca..a1b5a7be3 100644 --- a/Dockerfile +++ b/Dockerfile @@ -49,7 +49,7 @@ RUN mkdir build && \ make -j2 && \ make install -FROM alpine:3.11 +FROM alpine:3.13 RUN apk add --no-cache sqlite-libs curl gmp libstdc++ libgcc libpq luajit jsoncpp && \ adduser -D minetest --uid 30000 -h /var/lib/minetest && \ From 78da79b60f65d7a236b8589a508e41aba834649b Mon Sep 17 00:00:00 2001 From: Loic Blot Date: Fri, 2 Apr 2021 09:26:03 +0200 Subject: [PATCH 20/72] fix: use irrlicht fork instead of the standard library --- Dockerfile | 13 +++++++++++-- 1 file changed, 11 insertions(+), 2 deletions(-) diff --git a/Dockerfile b/Dockerfile index a1b5a7be3..e9a008bbf 100644 --- a/Dockerfile +++ b/Dockerfile @@ -1,6 +1,7 @@ -FROM alpine:3.11 +FROM alpine:3.13 ENV MINETEST_GAME_VERSION master +ENV IRRLICHT_VERSION master COPY .git /usr/src/minetest/.git COPY CMakeLists.txt /usr/src/minetest/CMakeLists.txt @@ -18,7 +19,7 @@ COPY textures /usr/src/minetest/textures WORKDIR /usr/src/minetest -RUN apk add --no-cache git build-base irrlicht-dev cmake bzip2-dev libpng-dev \ +RUN apk add --no-cache git build-base cmake bzip2-dev libpng-dev \ jpeg-dev libxxf86vm-dev mesa-dev sqlite-dev libogg-dev \ libvorbis-dev openal-soft-dev curl-dev freetype-dev zlib-dev \ gmp-dev jsoncpp-dev postgresql-dev luajit-dev ca-certificates && \ @@ -36,6 +37,14 @@ RUN git clone --recursive https://github.com/jupp0r/prometheus-cpp/ && \ make -j2 && \ make install +RUN git clone --depth=1 https://github.com/minetest/irrlicht/ -b ${IRRLICHT_VERSION} && \ + mkdir irrlicht/build && \ + cd irrlicht/build && \ + cmake .. \ + -DCMAKE_BUILD_TYPE=Release && \ + make -j2 && \ + make install + WORKDIR /usr/src/minetest RUN mkdir build && \ cd build && \ From 5de849713eb30c88c6d37b2fe9faa7ed65ce51f2 Mon Sep 17 00:00:00 2001 From: Loic Blot Date: Fri, 2 Apr 2021 12:25:52 +0200 Subject: [PATCH 21/72] fix(docker): reduce the number of required libraries on build --- Dockerfile | 11 ++--------- 1 file changed, 2 insertions(+), 9 deletions(-) diff --git a/Dockerfile b/Dockerfile index e9a008bbf..7cb6bec84 100644 --- a/Dockerfile +++ b/Dockerfile @@ -19,9 +19,7 @@ COPY textures /usr/src/minetest/textures WORKDIR /usr/src/minetest -RUN apk add --no-cache git build-base cmake bzip2-dev libpng-dev \ - jpeg-dev libxxf86vm-dev mesa-dev sqlite-dev libogg-dev \ - libvorbis-dev openal-soft-dev curl-dev freetype-dev zlib-dev \ +RUN apk add --no-cache git build-base cmake sqlite-dev curl-dev zlib-dev \ gmp-dev jsoncpp-dev postgresql-dev luajit-dev ca-certificates && \ git clone --depth=1 -b ${MINETEST_GAME_VERSION} https://github.com/minetest/minetest_game.git ./games/minetest_game && \ rm -fr ./games/minetest_game/.git @@ -38,12 +36,7 @@ RUN git clone --recursive https://github.com/jupp0r/prometheus-cpp/ && \ make install RUN git clone --depth=1 https://github.com/minetest/irrlicht/ -b ${IRRLICHT_VERSION} && \ - mkdir irrlicht/build && \ - cd irrlicht/build && \ - cmake .. \ - -DCMAKE_BUILD_TYPE=Release && \ - make -j2 && \ - make install + cp -r irrlicht/include /usr/include/irrlichtmt WORKDIR /usr/src/minetest RUN mkdir build && \ From 88783679cf95803a615b70ed3686daaac65a74a6 Mon Sep 17 00:00:00 2001 From: Loic Blot Date: Fri, 2 Apr 2021 14:17:24 +0200 Subject: [PATCH 22/72] fix(ci): ensure we build on docker only modifications --- .github/workflows/build.yml | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index ae24dc574..0cf18d228 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -13,6 +13,8 @@ on: - 'util/buildbot/**' - 'util/ci/**' - '.github/workflows/**.yml' + - 'Dockerfile' + - '.dockerignore' pull_request: paths: - 'lib/**.[ch]' @@ -24,6 +26,8 @@ on: - 'util/buildbot/**' - 'util/ci/**' - '.github/workflows/**.yml' + - 'Dockerfile' + - '.dockerignore' jobs: # This is our minor gcc compiler From 3e1904fa8c4aae3448d58b7e60545a4fdd8234f3 Mon Sep 17 00:00:00 2001 From: Wuzzy Date: Mon, 5 Apr 2021 11:37:58 +0000 Subject: [PATCH 23/72] Devtest: Remove testnodes_show_fallback_image --- games/devtest/mods/testnodes/drawtypes.lua | 20 ------------------- games/devtest/mods/testnodes/settingtypes.txt | 4 ---- games/devtest/settingtypes.txt | 5 ----- 3 files changed, 29 deletions(-) delete mode 100644 games/devtest/mods/testnodes/settingtypes.txt diff --git a/games/devtest/mods/testnodes/drawtypes.lua b/games/devtest/mods/testnodes/drawtypes.lua index 02d71b50d..f6d48b06f 100644 --- a/games/devtest/mods/testnodes/drawtypes.lua +++ b/games/devtest/mods/testnodes/drawtypes.lua @@ -15,22 +15,6 @@ testing this node easier and more convenient. local S = minetest.get_translator("testnodes") --- If set to true, will show an inventory image for nodes that have no inventory image as of Minetest 5.1.0. --- This is due to . --- This is only added to make the items more visible to avoid confusion, but you will no longer see --- the default inventory images for these items. When you want to test the default inventory image of drawtypes, --- this should be turned off. --- TODO: Remove support for fallback inventory image as soon #9209 is fixed. -local SHOW_FALLBACK_IMAGE = minetest.settings:get_bool("testnodes_show_fallback_image", false) - -local fallback_image = function(img) - if SHOW_FALLBACK_IMAGE then - return img - else - return nil - end -end - -- A regular cube minetest.register_node("testnodes:normal", { description = S("Normal Drawtype Test Node"), @@ -158,7 +142,6 @@ minetest.register_node("testnodes:torchlike", { walkable = false, sunlight_propagates = true, groups = { dig_immediate = 3 }, - inventory_image = fallback_image("testnodes_torchlike_floor.png"), }) minetest.register_node("testnodes:torchlike_wallmounted", { @@ -176,7 +159,6 @@ minetest.register_node("testnodes:torchlike_wallmounted", { walkable = false, sunlight_propagates = true, groups = { dig_immediate = 3 }, - inventory_image = fallback_image("testnodes_torchlike_floor.png"), }) @@ -192,7 +174,6 @@ minetest.register_node("testnodes:signlike", { walkable = false, groups = { dig_immediate = 3 }, sunlight_propagates = true, - inventory_image = fallback_image("testnodes_signlike.png"), }) minetest.register_node("testnodes:plantlike", { @@ -510,7 +491,6 @@ minetest.register_node("testnodes:airlike", { walkable = false, groups = { dig_immediate = 3 }, sunlight_propagates = true, - inventory_image = fallback_image("testnodes_airlike.png"), }) -- param2 changes liquid height diff --git a/games/devtest/mods/testnodes/settingtypes.txt b/games/devtest/mods/testnodes/settingtypes.txt deleted file mode 100644 index 7f753bf3e..000000000 --- a/games/devtest/mods/testnodes/settingtypes.txt +++ /dev/null @@ -1,4 +0,0 @@ -# If set to true, will show an inventory image for nodes that have no inventory image as of Minetest 5.1.0. -# This is due to . -# This is only added to make the items more visible to avoid confusion, but you will no longer see the default inventory images for these items. When you want to test the default inventory image of drawtypes, this should be turned off. -testnodes_show_fallback_image (Use fallback inventory images) bool false diff --git a/games/devtest/settingtypes.txt b/games/devtest/settingtypes.txt index 40ee5845b..c4365643e 100644 --- a/games/devtest/settingtypes.txt +++ b/games/devtest/settingtypes.txt @@ -30,8 +30,3 @@ devtest_dungeon_mossycobble (Generate mossy cobblestone) bool false # If enabled, some very basic biomes will be registered. devtest_register_biomes (Register biomes) bool true - -# If set to true, will show an inventory image for nodes that have no inventory image as of Minetest 5.1.0. -# This is due to . -# This is only added to make the items more visible to avoid confusion, but you will no longer see the default inventory images for these items. When you want to test the default inventory image of drawtypes, this should be turned off. -testnodes_show_fallback_image (Use fallback inventory images) bool false From f0bad0e2badbb7d4777aac7de1b50239bca4010a Mon Sep 17 00:00:00 2001 From: sfan5 Date: Mon, 5 Apr 2021 13:38:31 +0200 Subject: [PATCH 24/72] Reserve vectors before pushing and other code quality changes (#11161) --- src/client/clientmap.cpp | 9 +++++---- src/client/clouds.cpp | 2 +- src/client/hud.cpp | 16 ++++++++-------- src/client/sky.cpp | 26 +++++++++++++------------- src/client/sky.h | 22 +++++++++++----------- src/clientiface.cpp | 1 - src/gui/guiButtonItemImage.cpp | 4 ++-- src/gui/guiButtonItemImage.h | 6 +++--- src/inventory.cpp | 7 ++++--- src/nodedef.cpp | 4 ++-- src/nodedef.h | 2 +- src/nodemetadata.cpp | 16 +++++++--------- src/pathfinder.cpp | 2 +- src/settings.cpp | 5 +++-- src/util/areastore.cpp | 9 ++++----- src/util/container.h | 23 ++++++++++------------- src/util/enriched_string.cpp | 10 +++------- src/util/enriched_string.h | 34 +++++++++++++++++++++------------- src/voxelalgorithms.cpp | 14 ++++++-------- src/voxelalgorithms.h | 2 +- 20 files changed, 106 insertions(+), 108 deletions(-) diff --git a/src/client/clientmap.cpp b/src/client/clientmap.cpp index be8343009..c5b47532c 100644 --- a/src/client/clientmap.cpp +++ b/src/client/clientmap.cpp @@ -499,12 +499,12 @@ int ClientMap::getBackgroundBrightness(float max_d, u32 daylight_factor, static v3f z_directions[50] = { v3f(-100, 0, 0) }; - static f32 z_offsets[sizeof(z_directions)/sizeof(*z_directions)] = { + static f32 z_offsets[50] = { -1000, }; - if(z_directions[0].X < -99){ - for(u32 i=0; i 35*BS) sunlight_min_d = 35*BS; std::vector values; - for(u32 i=0; i a; a.buildRotateFromTo(v3f(0,1,0), z_dir); diff --git a/src/client/clouds.cpp b/src/client/clouds.cpp index 253dee8b9..5a075aaf0 100644 --- a/src/client/clouds.cpp +++ b/src/client/clouds.cpp @@ -170,7 +170,7 @@ void Clouds::render() // Read noise - std::vector grid(m_cloud_radius_i * 2 * m_cloud_radius_i * 2); // vector is broken + std::vector grid(m_cloud_radius_i * 2 * m_cloud_radius_i * 2); std::vector vertices; vertices.reserve(16 * m_cloud_radius_i * m_cloud_radius_i); diff --git a/src/client/hud.cpp b/src/client/hud.cpp index e5c7a4cfd..6d332490c 100644 --- a/src/client/hud.cpp +++ b/src/client/hud.cpp @@ -336,22 +336,22 @@ void Hud::drawLuaElements(const v3s16 &camera_offset) irr::gui::IGUIFont* font = g_fontengine->getFont(); // Reorder elements by z_index - std::vector ids; + std::vector elems; + elems.reserve(player->maxHudId()); for (size_t i = 0; i != player->maxHudId(); i++) { HudElement *e = player->getHud(i); if (!e) continue; - auto it = ids.begin(); - while (it != ids.end() && player->getHud(*it)->z_index <= e->z_index) + auto it = elems.begin(); + while (it != elems.end() && (*it)->z_index <= e->z_index) ++it; - ids.insert(it, i); + elems.insert(it, e); } - for (size_t i : ids) { - HudElement *e = player->getHud(i); + for (HudElement *e : elems) { v2s32 pos(floor(e->pos.X * (float) m_screensize.X + 0.5), floor(e->pos.Y * (float) m_screensize.Y + 0.5)); @@ -522,8 +522,8 @@ void Hud::drawLuaElements(const v3s16 &camera_offset) client->getMinimap()->drawMinimap(rect); break; } default: - infostream << "Hud::drawLuaElements: ignoring drawform " << e->type << - " of hud element ID " << i << " due to unrecognized type" << std::endl; + infostream << "Hud::drawLuaElements: ignoring drawform " << e->type + << " due to unrecognized type" << std::endl; } } } diff --git a/src/client/sky.cpp b/src/client/sky.cpp index caf695e7a..44c8f1574 100644 --- a/src/client/sky.cpp +++ b/src/client/sky.cpp @@ -82,13 +82,13 @@ Sky::Sky(s32 id, ITextureSource *tsrc, IShaderSource *ssrc) : // Ensures that sun and moon textures and tonemaps are correct. setSkyDefaults(); m_sun_texture = tsrc->isKnownSourceImage(m_sun_params.texture) ? - tsrc->getTextureForMesh(m_sun_params.texture) : NULL; + tsrc->getTextureForMesh(m_sun_params.texture) : nullptr; m_moon_texture = tsrc->isKnownSourceImage(m_moon_params.texture) ? - tsrc->getTextureForMesh(m_moon_params.texture) : NULL; + tsrc->getTextureForMesh(m_moon_params.texture) : nullptr; m_sun_tonemap = tsrc->isKnownSourceImage(m_sun_params.tonemap) ? - tsrc->getTexture(m_sun_params.tonemap) : NULL; + tsrc->getTexture(m_sun_params.tonemap) : nullptr; m_moon_tonemap = tsrc->isKnownSourceImage(m_moon_params.tonemap) ? - tsrc->getTexture(m_moon_params.tonemap) : NULL; + tsrc->getTexture(m_moon_params.tonemap) : nullptr; if (m_sun_texture) { m_materials[3] = baseMaterial(); @@ -744,14 +744,14 @@ void Sky::place_sky_body( } } -void Sky::setSunTexture(std::string sun_texture, - std::string sun_tonemap, ITextureSource *tsrc) +void Sky::setSunTexture(const std::string &sun_texture, + const std::string &sun_tonemap, ITextureSource *tsrc) { // Ignore matching textures (with modifiers) entirely, // but lets at least update the tonemap before hand. m_sun_params.tonemap = sun_tonemap; m_sun_tonemap = tsrc->isKnownSourceImage(m_sun_params.tonemap) ? - tsrc->getTexture(m_sun_params.tonemap) : NULL; + tsrc->getTexture(m_sun_params.tonemap) : nullptr; m_materials[3].Lighting = !!m_sun_tonemap; if (m_sun_params.texture == sun_texture) @@ -780,7 +780,7 @@ void Sky::setSunTexture(std::string sun_texture, } } -void Sky::setSunriseTexture(std::string sunglow_texture, +void Sky::setSunriseTexture(const std::string &sunglow_texture, ITextureSource* tsrc) { // Ignore matching textures (with modifiers) entirely. @@ -792,14 +792,14 @@ void Sky::setSunriseTexture(std::string sunglow_texture, ); } -void Sky::setMoonTexture(std::string moon_texture, - std::string moon_tonemap, ITextureSource *tsrc) +void Sky::setMoonTexture(const std::string &moon_texture, + const std::string &moon_tonemap, ITextureSource *tsrc) { // Ignore matching textures (with modifiers) entirely, // but lets at least update the tonemap before hand. m_moon_params.tonemap = moon_tonemap; m_moon_tonemap = tsrc->isKnownSourceImage(m_moon_params.tonemap) ? - tsrc->getTexture(m_moon_params.tonemap) : NULL; + tsrc->getTexture(m_moon_params.tonemap) : nullptr; m_materials[4].Lighting = !!m_moon_tonemap; if (m_moon_params.texture == moon_texture) @@ -893,7 +893,7 @@ void Sky::setSkyColors(const SkyColor &sky_color) } void Sky::setHorizonTint(video::SColor sun_tint, video::SColor moon_tint, - std::string use_sun_tint) + const std::string &use_sun_tint) { // Change sun and moon tinting: m_sky_params.fog_sun_tint = sun_tint; @@ -907,7 +907,7 @@ void Sky::setHorizonTint(video::SColor sun_tint, video::SColor moon_tint, m_default_tint = true; } -void Sky::addTextureToSkybox(std::string texture, int material_id, +void Sky::addTextureToSkybox(const std::string &texture, int material_id, ITextureSource *tsrc) { // Sanity check for more than six textures. diff --git a/src/client/sky.h b/src/client/sky.h index 342a97596..dc7da5021 100644 --- a/src/client/sky.h +++ b/src/client/sky.h @@ -65,15 +65,15 @@ public: } void setSunVisible(bool sun_visible) { m_sun_params.visible = sun_visible; } - void setSunTexture(std::string sun_texture, - std::string sun_tonemap, ITextureSource *tsrc); + void setSunTexture(const std::string &sun_texture, + const std::string &sun_tonemap, ITextureSource *tsrc); void setSunScale(f32 sun_scale) { m_sun_params.scale = sun_scale; } void setSunriseVisible(bool glow_visible) { m_sun_params.sunrise_visible = glow_visible; } - void setSunriseTexture(std::string sunglow_texture, ITextureSource* tsrc); + void setSunriseTexture(const std::string &sunglow_texture, ITextureSource* tsrc); void setMoonVisible(bool moon_visible) { m_moon_params.visible = moon_visible; } - void setMoonTexture(std::string moon_texture, - std::string moon_tonemap, ITextureSource *tsrc); + void setMoonTexture(const std::string &moon_texture, + const std::string &moon_tonemap, ITextureSource *tsrc); void setMoonScale(f32 moon_scale) { m_moon_params.scale = moon_scale; } void setStarsVisible(bool stars_visible) { m_star_params.visible = stars_visible; } @@ -87,21 +87,21 @@ public: void setVisible(bool visible) { m_visible = visible; } // Set only from set_sky API void setCloudsEnabled(bool clouds_enabled) { m_clouds_enabled = clouds_enabled; } - void setFallbackBgColor(const video::SColor &fallback_bg_color) + void setFallbackBgColor(video::SColor fallback_bg_color) { m_fallback_bg_color = fallback_bg_color; } - void overrideColors(const video::SColor &bgcolor, const video::SColor &skycolor) + void overrideColors(video::SColor bgcolor, video::SColor skycolor) { m_bgcolor = bgcolor; m_skycolor = skycolor; } void setSkyColors(const SkyColor &sky_color); void setHorizonTint(video::SColor sun_tint, video::SColor moon_tint, - std::string use_sun_tint); + const std::string &use_sun_tint); void setInClouds(bool clouds) { m_in_clouds = clouds; } void clearSkyboxTextures() { m_sky_params.textures.clear(); } - void addTextureToSkybox(std::string texture, int material_id, + void addTextureToSkybox(const std::string &texture, int material_id, ITextureSource *tsrc); const video::SColorf &getCurrentStarColor() const { return m_star_color; } @@ -126,7 +126,7 @@ private: } // Mix two colors by a given amount - video::SColor m_mix_scolor(video::SColor col1, video::SColor col2, f32 factor) + static video::SColor m_mix_scolor(video::SColor col1, video::SColor col2, f32 factor) { video::SColor result = video::SColor( col1.getAlpha() * (1 - factor) + col2.getAlpha() * factor, @@ -135,7 +135,7 @@ private: col1.getBlue() * (1 - factor) + col2.getBlue() * factor); return result; } - video::SColorf m_mix_scolorf(video::SColorf col1, video::SColorf col2, f32 factor) + static video::SColorf m_mix_scolorf(video::SColorf col1, video::SColorf col2, f32 factor) { video::SColorf result = video::SColorf(col1.r * (1 - factor) + col2.r * factor, diff --git a/src/clientiface.cpp b/src/clientiface.cpp index 797afd3c1..f35dcd0eb 100644 --- a/src/clientiface.cpp +++ b/src/clientiface.cpp @@ -671,7 +671,6 @@ void ClientInterface::UpdatePlayerList() std::vector clients = getClientIDs(); m_clients_names.clear(); - if (!clients.empty()) infostream<<"Players:"< rectangle, - ISimpleTextureSource *tsrc, std::string item, Client *client, + ISimpleTextureSource *tsrc, const std::string &item, Client *client, bool noclip) : GUIButton (environment, parent, id, rectangle, tsrc, noclip) { @@ -44,7 +44,7 @@ GUIButtonItemImage::GUIButtonItemImage(gui::IGUIEnvironment *environment, GUIButtonItemImage *GUIButtonItemImage::addButton(IGUIEnvironment *environment, const core::rect &rectangle, ISimpleTextureSource *tsrc, - IGUIElement *parent, s32 id, const wchar_t *text, std::string item, + IGUIElement *parent, s32 id, const wchar_t *text, const std::string &item, Client *client) { GUIButtonItemImage *button = new GUIButtonItemImage(environment, diff --git a/src/gui/guiButtonItemImage.h b/src/gui/guiButtonItemImage.h index b90ac757e..205e957a7 100644 --- a/src/gui/guiButtonItemImage.h +++ b/src/gui/guiButtonItemImage.h @@ -33,13 +33,13 @@ public: //! constructor GUIButtonItemImage(gui::IGUIEnvironment *environment, gui::IGUIElement *parent, s32 id, core::rect rectangle, ISimpleTextureSource *tsrc, - std::string item, Client *client, bool noclip = false); + const std::string &item, Client *client, bool noclip = false); //! Do not drop returned handle static GUIButtonItemImage *addButton(gui::IGUIEnvironment *environment, const core::rect &rectangle, ISimpleTextureSource *tsrc, - IGUIElement *parent, s32 id, const wchar_t *text, std::string item, - Client *client); + IGUIElement *parent, s32 id, const wchar_t *text, + const std::string &item, Client *client); private: Client *m_client; diff --git a/src/inventory.cpp b/src/inventory.cpp index 1ef9b13cd..fc1aaf371 100644 --- a/src/inventory.cpp +++ b/src/inventory.cpp @@ -965,13 +965,14 @@ InventoryList * Inventory::getList(const std::string &name) { s32 i = getListIndex(name); if(i == -1) - return NULL; + return nullptr; return m_lists[i]; } std::vector Inventory::getLists() { std::vector lists; + lists.reserve(m_lists.size()); for (auto list : m_lists) { lists.push_back(list); } @@ -990,11 +991,11 @@ bool Inventory::deleteList(const std::string &name) return true; } -const InventoryList * Inventory::getList(const std::string &name) const +const InventoryList *Inventory::getList(const std::string &name) const { s32 i = getListIndex(name); if(i == -1) - return NULL; + return nullptr; return m_lists[i]; } diff --git a/src/nodedef.cpp b/src/nodedef.cpp index 3dcac439f..dd862e606 100644 --- a/src/nodedef.cpp +++ b/src/nodedef.cpp @@ -1544,10 +1544,10 @@ void NodeDefManager::deSerialize(std::istream &is) } -void NodeDefManager::addNameIdMapping(content_t i, std::string name) +void NodeDefManager::addNameIdMapping(content_t i, const std::string &name) { m_name_id_mapping.set(i, name); - m_name_id_mapping_with_aliases.insert(std::make_pair(name, i)); + m_name_id_mapping_with_aliases.emplace(name, i); } diff --git a/src/nodedef.h b/src/nodedef.h index b8cf7c14d..0de4dbc21 100644 --- a/src/nodedef.h +++ b/src/nodedef.h @@ -725,7 +725,7 @@ private: * @param i a content ID * @param name a node name */ - void addNameIdMapping(content_t i, std::string name); + void addNameIdMapping(content_t i, const std::string &name); /*! * Removes a content ID from all groups. diff --git a/src/nodemetadata.cpp b/src/nodemetadata.cpp index 6447c8785..f98732385 100644 --- a/src/nodemetadata.cpp +++ b/src/nodemetadata.cpp @@ -206,10 +206,9 @@ NodeMetadataList::~NodeMetadataList() std::vector NodeMetadataList::getAllKeys() { std::vector keys; - - NodeMetadataMap::const_iterator it; - for (it = m_data.begin(); it != m_data.end(); ++it) - keys.push_back(it->first); + keys.reserve(m_data.size()); + for (const auto &it : m_data) + keys.push_back(it.first); return keys; } @@ -218,7 +217,7 @@ NodeMetadata *NodeMetadataList::get(v3s16 p) { NodeMetadataMap::const_iterator n = m_data.find(p); if (n == m_data.end()) - return NULL; + return nullptr; return n->second; } @@ -235,7 +234,7 @@ void NodeMetadataList::remove(v3s16 p) void NodeMetadataList::set(v3s16 p, NodeMetadata *d) { remove(p); - m_data.insert(std::make_pair(p, d)); + m_data.emplace(p, d); } void NodeMetadataList::clear() @@ -251,9 +250,8 @@ void NodeMetadataList::clear() int NodeMetadataList::countNonEmpty() const { int n = 0; - NodeMetadataMap::const_iterator it; - for (it = m_data.begin(); it != m_data.end(); ++it) { - if (!it->second->empty()) + for (const auto &it : m_data) { + if (!it.second->empty()) n++; } return n; diff --git a/src/pathfinder.cpp b/src/pathfinder.cpp index 1cb84997a..c45ce9158 100644 --- a/src/pathfinder.cpp +++ b/src/pathfinder.cpp @@ -1428,7 +1428,7 @@ std::string Pathfinder::dirToName(PathDirections dir) } /******************************************************************************/ -void Pathfinder::printPath(std::vector path) +void Pathfinder::printPath(const std::vector &path) { unsigned int current = 0; for (std::vector::iterator i = path.begin(); diff --git a/src/settings.cpp b/src/settings.cpp index 3415ff818..cff393e5f 100644 --- a/src/settings.cpp +++ b/src/settings.cpp @@ -43,11 +43,11 @@ std::unordered_map Settings::s_flags; Settings *Settings::createLayer(SettingsLayer sl, const std::string &end_tag) { if ((int)sl < 0 || sl >= SL_TOTAL_COUNT) - throw new BaseException("Invalid settings layer"); + throw BaseException("Invalid settings layer"); Settings *&pos = s_layers[(size_t)sl]; if (pos) - throw new BaseException("Setting layer " + std::to_string(sl) + " already exists"); + throw BaseException("Setting layer " + std::to_string(sl) + " already exists"); pos = new Settings(end_tag); pos->m_settingslayer = sl; @@ -638,6 +638,7 @@ std::vector Settings::getNames() const MutexAutoLock lock(m_mutex); std::vector names; + names.reserve(m_settings.size()); for (const auto &settings_it : m_settings) { names.push_back(settings_it.first); } diff --git a/src/util/areastore.cpp b/src/util/areastore.cpp index cea526336..67bfef0c0 100644 --- a/src/util/areastore.cpp +++ b/src/util/areastore.cpp @@ -96,16 +96,15 @@ void AreaStore::deserialize(std::istream &is) u16 num_areas = readU16(is); std::vector areas; + areas.reserve(num_areas); for (u32 i = 0; i < num_areas; ++i) { Area a(U32_MAX); a.minedge = readV3S16(is); a.maxedge = readV3S16(is); u16 data_len = readU16(is); - char *data = new char[data_len]; - is.read(data, data_len); - a.data = std::string(data, data_len); - areas.emplace_back(a); - delete [] data; + a.data = std::string(data_len, '\0'); + is.read(&a.data[0], data_len); + areas.emplace_back(std::move(a)); } bool read_ids = is.good(); // EOF for old formats diff --git a/src/util/container.h b/src/util/container.h index 2ad2bbfc7..1c4a219f0 100644 --- a/src/util/container.h +++ b/src/util/container.h @@ -90,8 +90,7 @@ public: bool get(const Key &name, Value *result) const { MutexAutoLock lock(m_mutex); - typename std::map::const_iterator n = - m_values.find(name); + auto n = m_values.find(name); if (n == m_values.end()) return false; if (result) @@ -103,11 +102,9 @@ public: { MutexAutoLock lock(m_mutex); std::vector result; - for (typename std::map::const_iterator - it = m_values.begin(); - it != m_values.end(); ++it){ + result.reserve(m_values.size()); + for (auto it = m_values.begin(); it != m_values.end(); ++it) result.push_back(it->second); - } return result; } @@ -136,7 +133,7 @@ public: return m_queue.empty(); } - void push_back(T t) + void push_back(const T &t) { MutexAutoLock lock(m_mutex); m_queue.push_back(t); @@ -151,7 +148,7 @@ public: if (m_signal.wait(wait_time_max_ms)) { MutexAutoLock lock(m_mutex); - T t = m_queue.front(); + T t = std::move(m_queue.front()); m_queue.pop_front(); return t; } @@ -164,7 +161,7 @@ public: if (m_signal.wait(wait_time_max_ms)) { MutexAutoLock lock(m_mutex); - T t = m_queue.front(); + T t = std::move(m_queue.front()); m_queue.pop_front(); return t; } @@ -178,7 +175,7 @@ public: MutexAutoLock lock(m_mutex); - T t = m_queue.front(); + T t = std::move(m_queue.front()); m_queue.pop_front(); return t; } @@ -188,7 +185,7 @@ public: if (m_signal.wait(wait_time_max_ms)) { MutexAutoLock lock(m_mutex); - T t = m_queue.back(); + T t = std::move(m_queue.back()); m_queue.pop_back(); return t; } @@ -204,7 +201,7 @@ public: if (m_signal.wait(wait_time_max_ms)) { MutexAutoLock lock(m_mutex); - T t = m_queue.back(); + T t = std::move(m_queue.back()); m_queue.pop_back(); return t; } @@ -218,7 +215,7 @@ public: MutexAutoLock lock(m_mutex); - T t = m_queue.back(); + T t = std::move(m_queue.back()); m_queue.pop_back(); return t; } diff --git a/src/util/enriched_string.cpp b/src/util/enriched_string.cpp index 762d094eb..b1f95215e 100644 --- a/src/util/enriched_string.cpp +++ b/src/util/enriched_string.cpp @@ -65,12 +65,14 @@ void EnrichedString::operator=(const wchar_t *str) addAtEnd(translate_string(std::wstring(str)), m_default_color); } -void EnrichedString::addAtEnd(const std::wstring &s, const SColor &initial_color) +void EnrichedString::addAtEnd(const std::wstring &s, SColor initial_color) { SColor color(initial_color); bool use_default = (m_default_length == m_string.size() && color == m_default_color); + m_colors.reserve(m_colors.size() + s.size()); + size_t i = 0; while (i < s.length()) { if (s[i] != L'\x1b') { @@ -200,12 +202,6 @@ const std::wstring &EnrichedString::getString() const return m_string; } -void EnrichedString::setDefaultColor(const irr::video::SColor &color) -{ - m_default_color = color; - updateDefaultColor(); -} - void EnrichedString::updateDefaultColor() { sanity_check(m_default_length <= m_colors.size()); diff --git a/src/util/enriched_string.h b/src/util/enriched_string.h index c8a095887..16a0eef74 100644 --- a/src/util/enriched_string.h +++ b/src/util/enriched_string.h @@ -23,18 +23,22 @@ with this program; if not, write to the Free Software Foundation, Inc., #include #include +using namespace irr; + class EnrichedString { public: EnrichedString(); EnrichedString(const std::wstring &s, - const irr::video::SColor &color = irr::video::SColor(255, 255, 255, 255)); + const video::SColor &color = video::SColor(255, 255, 255, 255)); EnrichedString(const wchar_t *str, - const irr::video::SColor &color = irr::video::SColor(255, 255, 255, 255)); + const video::SColor &color = video::SColor(255, 255, 255, 255)); EnrichedString(const std::wstring &string, - const std::vector &colors); - void clear(); + const std::vector &colors); void operator=(const wchar_t *str); - void addAtEnd(const std::wstring &s, const irr::video::SColor &color); + + void clear(); + + void addAtEnd(const std::wstring &s, video::SColor color); // Adds the character source[i] at the end. // An EnrichedString should always be able to be copied @@ -49,12 +53,16 @@ public: EnrichedString operator+(const EnrichedString &other) const; void operator+=(const EnrichedString &other); const wchar_t *c_str() const; - const std::vector &getColors() const; + const std::vector &getColors() const; const std::wstring &getString() const; - void setDefaultColor(const irr::video::SColor &color); + inline void setDefaultColor(video::SColor color) + { + m_default_color = color; + updateDefaultColor(); + } void updateDefaultColor(); - inline const irr::video::SColor &getDefaultColor() const + inline const video::SColor &getDefaultColor() const { return m_default_color; } @@ -80,11 +88,11 @@ public: { return m_has_background; } - inline irr::video::SColor getBackground() const + inline video::SColor getBackground() const { return m_background; } - inline void setBackground(const irr::video::SColor &color) + inline void setBackground(video::SColor color) { m_background = color; m_has_background = true; @@ -92,10 +100,10 @@ public: private: std::wstring m_string; - std::vector m_colors; + std::vector m_colors; bool m_has_background; - irr::video::SColor m_default_color; - irr::video::SColor m_background; + video::SColor m_default_color; + video::SColor m_background; // This variable defines the length of the default-colored text. // Change this to a std::vector if an "end coloring" tag is wanted. size_t m_default_length = 0; diff --git a/src/voxelalgorithms.cpp b/src/voxelalgorithms.cpp index 62fd68890..ffb70aa71 100644 --- a/src/voxelalgorithms.cpp +++ b/src/voxelalgorithms.cpp @@ -65,7 +65,7 @@ struct ChangingLight { ChangingLight() = default; - ChangingLight(const relative_v3 &rel_pos, const mapblock_v3 &block_pos, + ChangingLight(relative_v3 rel_pos, mapblock_v3 block_pos, MapBlock *b, direction source_dir) : rel_position(rel_pos), block_position(block_pos), @@ -125,8 +125,8 @@ struct LightQueue { * The parameters are the same as in ChangingLight's constructor. * \param light light level of the ChangingLight */ - inline void push(u8 light, const relative_v3 &rel_pos, - const mapblock_v3 &block_pos, MapBlock *block, + inline void push(u8 light, relative_v3 rel_pos, + mapblock_v3 block_pos, MapBlock *block, direction source_dir) { assert(light <= LIGHT_SUN); @@ -467,7 +467,7 @@ bool is_sunlight_above(Map *map, v3s16 pos, const NodeDefManager *ndef) static const LightBank banks[] = { LIGHTBANK_DAY, LIGHTBANK_NIGHT }; void update_lighting_nodes(Map *map, - std::vector > &oldnodes, + const std::vector> &oldnodes, std::map &modified_blocks) { const NodeDefManager *ndef = map->getNodeDefManager(); @@ -482,8 +482,7 @@ void update_lighting_nodes(Map *map, // won't change, since they didn't get their light from a // modified node. u8 min_safe_light = 0; - for (std::vector >::iterator it = - oldnodes.begin(); it < oldnodes.end(); ++it) { + for (auto it = oldnodes.cbegin(); it < oldnodes.cend(); ++it) { u8 old_light = it->second.getLight(bank, ndef); if (old_light > min_safe_light) { min_safe_light = old_light; @@ -495,8 +494,7 @@ void update_lighting_nodes(Map *map, min_safe_light++; } // For each changed node process sunlight and initialize - for (std::vector >::iterator it = - oldnodes.begin(); it < oldnodes.end(); ++it) { + for (auto it = oldnodes.cbegin(); it < oldnodes.cend(); ++it) { // Get position and block of the changed node v3s16 p = it->first; relative_v3 rel_pos; diff --git a/src/voxelalgorithms.h b/src/voxelalgorithms.h index 1452f30f4..bcbd3b586 100644 --- a/src/voxelalgorithms.h +++ b/src/voxelalgorithms.h @@ -45,7 +45,7 @@ namespace voxalgo */ void update_lighting_nodes( Map *map, - std::vector > &oldnodes, + const std::vector> &oldnodes, std::map &modified_blocks); /*! From c11208c4b55bc6b17e523761befed6156027edf9 Mon Sep 17 00:00:00 2001 From: SmallJoker Date: Mon, 5 Apr 2021 13:38:50 +0200 Subject: [PATCH 25/72] Game: Scale damage flash to max HP The flash intensity is calculated proportionally to the maximal HP. --- src/client/content_cao.h | 2 ++ src/client/game.cpp | 12 ++++++++---- 2 files changed, 10 insertions(+), 4 deletions(-) diff --git a/src/client/content_cao.h b/src/client/content_cao.h index 7c134fb48..cc026d34e 100644 --- a/src/client/content_cao.h +++ b/src/client/content_cao.h @@ -174,6 +174,8 @@ public: const bool isImmortal(); + inline const ObjectProperties &getProperties() const { return m_prop; } + scene::ISceneNode *getSceneNode() const; scene::IAnimatedMeshSceneNode *getAnimatedMeshSceneNode() const; diff --git a/src/client/game.cpp b/src/client/game.cpp index 22b7ee875..949e53214 100644 --- a/src/client/game.cpp +++ b/src/client/game.cpp @@ -2568,14 +2568,18 @@ void Game::handleClientEvent_PlayerDamage(ClientEvent *event, CameraOrientation // Damage flash and hurt tilt are not used at death if (client->getHP() > 0) { - runData.damage_flash += 95.0f + 3.2f * event->player_damage.amount; - runData.damage_flash = MYMIN(runData.damage_flash, 127.0f); - LocalPlayer *player = client->getEnv().getLocalPlayer(); + f32 hp_max = player->getCAO() ? + player->getCAO()->getProperties().hp_max : PLAYER_MAX_HP_DEFAULT; + f32 damage_ratio = event->player_damage.amount / hp_max; + + runData.damage_flash += 95.0f + 64.f * damage_ratio; + runData.damage_flash = MYMIN(runData.damage_flash, 127.0f); + player->hurt_tilt_timer = 1.5f; player->hurt_tilt_strength = - rangelim(event->player_damage.amount / 4.0f, 1.0f, 4.0f); + rangelim(damage_ratio * 5.0f, 1.0f, 4.0f); } // Play damage sound From 19c283546c5418382ed3ab648ca165ef1cc7994b Mon Sep 17 00:00:00 2001 From: sfan5 Date: Mon, 5 Apr 2021 15:21:43 +0200 Subject: [PATCH 26/72] Don't apply connection timeout limit to locally hosted servers fixes #11085 --- src/client/game.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/client/game.cpp b/src/client/game.cpp index 949e53214..edb054032 100644 --- a/src/client/game.cpp +++ b/src/client/game.cpp @@ -1536,7 +1536,7 @@ bool Game::connectToServer(const GameStartData &start_data, } else { wait_time += dtime; // Only time out if we aren't waiting for the server we started - if (!start_data.isSinglePlayer() && wait_time > 10) { + if (!start_data.address.empty() && wait_time > 10) { *error_message = "Connection timed out."; errorstream << *error_message << std::endl; break; From 23325277659132e95b346307b591c944625bda16 Mon Sep 17 00:00:00 2001 From: DS Date: Mon, 5 Apr 2021 15:55:56 +0200 Subject: [PATCH 27/72] Add vector.to_string and vector.from_string (#10323) Writing vectors as strings is very common and should belong to `vector.*`. `minetest.pos_to_string` is also too long to write, implies that one should only use it for positions and leaves no spaces after the commas. --- builtin/common/tests/vector_spec.lua | 19 +++++++++++++++++++ builtin/common/vector.lua | 16 ++++++++++++++++ doc/lua_api.txt | 10 ++++++++++ 3 files changed, 45 insertions(+) diff --git a/builtin/common/tests/vector_spec.lua b/builtin/common/tests/vector_spec.lua index 0f287363a..104c656e9 100644 --- a/builtin/common/tests/vector_spec.lua +++ b/builtin/common/tests/vector_spec.lua @@ -48,6 +48,25 @@ describe("vector", function() assert.same({ x = 41, y = 52, z = 63 }, vector.offset(vector.new(1, 2, 3), 40, 50, 60)) end) + it("to_string()", function() + local v = vector.new(1, 2, 3.14) + assert.same("(1, 2, 3.14)", vector.to_string(v)) + end) + + it("from_string()", function() + local v = vector.new(1, 2, 3.14) + assert.same({v, 13}, {vector.from_string("(1, 2, 3.14)")}) + assert.same({v, 12}, {vector.from_string("(1,2 ,3.14)")}) + assert.same({v, 12}, {vector.from_string("(1,2,3.14,)")}) + assert.same({v, 11}, {vector.from_string("(1 2 3.14)")}) + assert.same({v, 15}, {vector.from_string("( 1, 2, 3.14 )")}) + assert.same({v, 15}, {vector.from_string(" ( 1, 2, 3.14) ")}) + assert.same({vector.new(), 8}, {vector.from_string("(0,0,0) ( 1, 2, 3.14) ")}) + assert.same({v, 22}, {vector.from_string("(0,0,0) ( 1, 2, 3.14) ", 8)}) + assert.same({v, 22}, {vector.from_string("(0,0,0) ( 1, 2, 3.14) ", 9)}) + assert.same(nil, vector.from_string("nothing")) + end) + -- This function is needed because of floating point imprecision. local function almost_equal(a, b) if type(a) == "number" then diff --git a/builtin/common/vector.lua b/builtin/common/vector.lua index b04c12610..2ef8fc617 100644 --- a/builtin/common/vector.lua +++ b/builtin/common/vector.lua @@ -12,6 +12,22 @@ function vector.new(a, b, c) return {x=0, y=0, z=0} end +function vector.from_string(s, init) + local x, y, z, np = string.match(s, "^%s*%(%s*([^%s,]+)%s*[,%s]%s*([^%s,]+)%s*[,%s]" .. + "%s*([^%s,]+)%s*[,%s]?%s*%)()", init) + x = tonumber(x) + y = tonumber(y) + z = tonumber(z) + if not (x and y and z) then + return nil + end + return {x = x, y = y, z = z}, np +end + +function vector.to_string(v) + return string.format("(%g, %g, %g)", v.x, v.y, v.z) +end + function vector.equals(a, b) return a.x == b.x and a.y == b.y and diff --git a/doc/lua_api.txt b/doc/lua_api.txt index 3630221e3..6c1e46c7e 100644 --- a/doc/lua_api.txt +++ b/doc/lua_api.txt @@ -3149,6 +3149,16 @@ For the following functions, `v`, `v1`, `v2` are vectors, * Returns a vector. * A copy of `a` if `a` is a vector. * `{x = a, y = b, z = c}`, if all of `a`, `b`, `c` are defined numbers. +* `vector.from_string(s[, init])`: + * Returns `v, np`, where `v` is a vector read from the given string `s` and + `np` is the next position in the string after the vector. + * Returns `nil` on failure. + * `s`: Has to begin with a substring of the form `"(x, y, z)"`. Additional + spaces, leaving away commas and adding an additional comma to the end + is allowed. + * `init`: If given starts looking for the vector at this string index. +* `vector.to_string(v)`: + * Returns a string of the form `"(x, y, z)"`. * `vector.direction(p1, p2)`: * Returns a vector of length 1 with direction `p1` to `p2`. * If `p1` and `p2` are identical, returns `{x = 0, y = 0, z = 0}`. From 85163b531f283c52111c3964fd382e4ed1dafeb8 Mon Sep 17 00:00:00 2001 From: yw05 <37980625+yw05@users.noreply.github.com> Date: Mon, 5 Apr 2021 15:56:29 +0200 Subject: [PATCH 28/72] Make edit boxes respond to string input (IME) (#11156) Make edit boxes respond to string input events (introduced in minetest/irrlicht#23) that are usually triggered by entering text with an IME. --- src/gui/guiChatConsole.cpp | 8 +++++ src/gui/guiChatConsole.h | 2 ++ src/gui/guiEditBox.cpp | 65 ++++++++++++++++++++++---------------- src/gui/guiEditBox.h | 3 ++ 4 files changed, 51 insertions(+), 27 deletions(-) diff --git a/src/gui/guiChatConsole.cpp b/src/gui/guiChatConsole.cpp index b7af0ca0f..baaaea5e8 100644 --- a/src/gui/guiChatConsole.cpp +++ b/src/gui/guiChatConsole.cpp @@ -17,6 +17,7 @@ with this program; if not, write to the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. */ +#include "IrrCompileConfig.h" #include "guiChatConsole.h" #include "chat.h" #include "client/client.h" @@ -618,6 +619,13 @@ bool GUIChatConsole::OnEvent(const SEvent& event) m_chat_backend->scroll(rows); } } +#if (IRRLICHT_VERSION_MT_REVISION >= 2) + else if(event.EventType == EET_STRING_INPUT_EVENT) + { + prompt.input(std::wstring(event.StringInput.Str->c_str())); + return true; + } +#endif return Parent ? Parent->OnEvent(event) : false; } diff --git a/src/gui/guiChatConsole.h b/src/gui/guiChatConsole.h index 896342ab0..1152f2b2d 100644 --- a/src/gui/guiChatConsole.h +++ b/src/gui/guiChatConsole.h @@ -72,6 +72,8 @@ public: virtual void setVisible(bool visible); + virtual bool acceptsIME() { return true; } + private: void reformatConsole(); void recalculateConsolePosition(); diff --git a/src/gui/guiEditBox.cpp b/src/gui/guiEditBox.cpp index cd5a0868d..ba548aa2d 100644 --- a/src/gui/guiEditBox.cpp +++ b/src/gui/guiEditBox.cpp @@ -19,6 +19,7 @@ with this program; if not, write to the Free Software Foundation, Inc., #include "guiEditBox.h" +#include "IrrCompileConfig.h" #include "IGUISkin.h" #include "IGUIEnvironment.h" #include "IGUIFont.h" @@ -216,6 +217,11 @@ bool GUIEditBox::OnEvent(const SEvent &event) if (processMouse(event)) return true; break; +#if (IRRLICHT_VERSION_MT_REVISION >= 2) + case EET_STRING_INPUT_EVENT: + inputString(*event.StringInput.Str); + return true; +#endif default: break; } @@ -669,40 +675,45 @@ bool GUIEditBox::onKeyDelete(const SEvent &event, s32 &mark_begin, s32 &mark_end } void GUIEditBox::inputChar(wchar_t c) +{ + if (c == 0) + return; + core::stringw s(&c, 1); + inputString(s); +} + +void GUIEditBox::inputString(const core::stringw &str) { if (!isEnabled() || !m_writable) return; - if (c != 0) { - if (Text.size() < m_max || m_max == 0) { - core::stringw s; + u32 len = str.size(); + if (Text.size()+len <= m_max || m_max == 0) { + core::stringw s; + if (m_mark_begin != m_mark_end) { + // replace marked text + s32 real_begin = m_mark_begin < m_mark_end ? m_mark_begin : m_mark_end; + s32 real_end = m_mark_begin < m_mark_end ? m_mark_end : m_mark_begin; - if (m_mark_begin != m_mark_end) { - // clang-format off - // replace marked text - s32 real_begin = m_mark_begin < m_mark_end ? m_mark_begin : m_mark_end; - s32 real_end = m_mark_begin < m_mark_end ? m_mark_end : m_mark_begin; - - s = Text.subString(0, real_begin); - s.append(c); - s.append(Text.subString(real_end, Text.size() - real_end)); - Text = s; - m_cursor_pos = real_begin + 1; - // clang-format on - } else { - // add new character - s = Text.subString(0, m_cursor_pos); - s.append(c); - s.append(Text.subString(m_cursor_pos, - Text.size() - m_cursor_pos)); - Text = s; - ++m_cursor_pos; - } - - m_blink_start_time = porting::getTimeMs(); - setTextMarkers(0, 0); + s = Text.subString(0, real_begin); + s.append(str); + s.append(Text.subString(real_end, Text.size() - real_end)); + Text = s; + m_cursor_pos = real_begin + len; + } else { + // append string + s = Text.subString(0, m_cursor_pos); + s.append(str); + s.append(Text.subString(m_cursor_pos, + Text.size() - m_cursor_pos)); + Text = s; + m_cursor_pos += len; } + + m_blink_start_time = porting::getTimeMs(); + setTextMarkers(0, 0); } + breakText(); sendGuiEvent(EGET_EDITBOX_CHANGED); calculateScrollPos(); diff --git a/src/gui/guiEditBox.h b/src/gui/guiEditBox.h index c616d75d1..2a5c911bc 100644 --- a/src/gui/guiEditBox.h +++ b/src/gui/guiEditBox.h @@ -138,6 +138,8 @@ public: virtual void deserializeAttributes( io::IAttributes *in, io::SAttributeReadWriteOptions *options); + virtual bool acceptsIME() { return isEnabled() && m_writable; }; + protected: virtual void breakText() = 0; @@ -156,6 +158,7 @@ protected: virtual s32 getCursorPos(s32 x, s32 y) = 0; bool processKey(const SEvent &event); + virtual void inputString(const core::stringw &str); virtual void inputChar(wchar_t c); //! returns the line number that the cursor is on From 57218aa9d1cdfcbb101987591b60beb6ab766ca9 Mon Sep 17 00:00:00 2001 From: sfan5 Date: Fri, 9 Apr 2021 21:16:45 +0200 Subject: [PATCH 29/72] Update Android build config --- build/android/native/jni/Android.mk | 15 +-------------- 1 file changed, 1 insertion(+), 14 deletions(-) diff --git a/build/android/native/jni/Android.mk b/build/android/native/jni/Android.mk index 140947e6a..477392af0 100644 --- a/build/android/native/jni/Android.mk +++ b/build/android/native/jni/Android.mk @@ -14,7 +14,7 @@ include $(PREBUILT_STATIC_LIBRARY) include $(CLEAR_VARS) LOCAL_MODULE := Irrlicht -LOCAL_SRC_FILES := deps/Android/Irrlicht/${NDK_TOOLCHAIN_VERSION}/$(APP_ABI)/libIrrlicht.a +LOCAL_SRC_FILES := deps/Android/Irrlicht/${NDK_TOOLCHAIN_VERSION}/$(APP_ABI)/libIrrlichtMt.a include $(PREBUILT_STATIC_LIBRARY) #include $(CLEAR_VARS) @@ -47,18 +47,6 @@ LOCAL_MODULE := OpenAL LOCAL_SRC_FILES := deps/Android/OpenAL-Soft/${NDK_TOOLCHAIN_VERSION}/$(APP_ABI)/libopenal.a include $(PREBUILT_STATIC_LIBRARY) -# You can use `OpenSSL and Crypto` instead `mbedTLS mbedx509 mbedcrypto`, -#but it increase APK size on ~0.7MB -#include $(CLEAR_VARS) -#LOCAL_MODULE := OpenSSL -#LOCAL_SRC_FILES := deps/Android/OpenSSL/${NDK_TOOLCHAIN_VERSION}/$(APP_ABI)/libssl.a -#include $(PREBUILT_STATIC_LIBRARY) - -#include $(CLEAR_VARS) -#LOCAL_MODULE := Crypto -#LOCAL_SRC_FILES := deps/Android/OpenSSL/${NDK_TOOLCHAIN_VERSION}/$(APP_ABI)/libcrypto.a -#include $(PREBUILT_STATIC_LIBRARY) - include $(CLEAR_VARS) LOCAL_MODULE := Vorbis LOCAL_SRC_FILES := deps/Android/Vorbis/${NDK_TOOLCHAIN_VERSION}/$(APP_ABI)/libvorbis.a @@ -207,7 +195,6 @@ LOCAL_SRC_FILES += \ LOCAL_SRC_FILES += deps/Android/sqlite/sqlite3.c LOCAL_STATIC_LIBRARIES += Curl Freetype Irrlicht OpenAL mbedTLS mbedx509 mbedcrypto Vorbis LuaJIT android_native_app_glue $(PROFILER_LIBS) #LevelDB -#OpenSSL Crypto LOCAL_LDLIBS := -lEGL -lGLESv1_CM -lGLESv2 -landroid -lOpenSLES From e89e6c8380ba5dc865f94b1cb4e6fd7e96369436 Mon Sep 17 00:00:00 2001 From: Wuzzy Date: Mon, 5 Apr 2021 17:18:45 +0200 Subject: [PATCH 30/72] Don't reseed stars when changing star count --- src/client/sky.cpp | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/client/sky.cpp b/src/client/sky.cpp index 44c8f1574..46a3f2621 100644 --- a/src/client/sky.cpp +++ b/src/client/sky.cpp @@ -57,6 +57,8 @@ Sky::Sky(s32 id, ITextureSource *tsrc, IShaderSource *ssrc) : scene::ISceneNode(RenderingEngine::get_scene_manager()->getRootSceneNode(), RenderingEngine::get_scene_manager(), id) { + m_seed = (u64)myrand() << 32 | myrand(); + setAutomaticCulling(scene::EAC_OFF); m_box.MaxEdge.set(0, 0, 0); m_box.MinEdge.set(0, 0, 0); @@ -833,7 +835,6 @@ void Sky::setStarCount(u16 star_count, bool force_update) // Allow force updating star count at game init. if (m_star_params.count != star_count || force_update) { m_star_params.count = star_count; - m_seed = (u64)myrand() << 32 | myrand(); updateStars(); } } From 8c7e214875c811b8e7ff8473b020498af4fbbafe Mon Sep 17 00:00:00 2001 From: Wuzzy Date: Fri, 2 Apr 2021 15:59:28 +0200 Subject: [PATCH 31/72] Update builtin locale files --- builtin/locale/__builtin.de.tr | 35 ++++++++++++++++++++++++++++------ builtin/locale/__builtin.it.tr | 33 +++++++++++++++++++++++++++----- builtin/locale/template.txt | 26 ++++++++++++++++++++----- 3 files changed, 78 insertions(+), 16 deletions(-) diff --git a/builtin/locale/__builtin.de.tr b/builtin/locale/__builtin.de.tr index eaadf611b..963ab8477 100644 --- a/builtin/locale/__builtin.de.tr +++ b/builtin/locale/__builtin.de.tr @@ -2,6 +2,8 @@ Empty command.=Leerer Befehl. Invalid command: @1=Ungültiger Befehl: @1 Invalid command usage.=Ungültige Befehlsverwendung. + (@1 s)= +Command execution took @1 s= You don't have permission to run this command (missing privileges: @1).=Sie haben keine Erlaubnis, diesen Befehl auszuführen (fehlende Privilegien: @1). Unable to get position of player @1.=Konnte Position vom Spieler @1 nicht ermitteln. Incorrect area format. Expected: (x1,y1,z1) (x2,y2,z2)=Ungültiges Gebietsformat. Erwartet: (x1,y1,z1) (x2,y2,z2) @@ -10,24 +12,30 @@ Show chat action (e.g., '/me orders a pizza' displays ' orders a pi Show the name of the server owner=Den Namen des Servereigentümers zeigen The administrator of this server is @1.=Der Administrator dieses Servers ist @1. There's no administrator named in the config file.=In der Konfigurationsdatei wurde kein Administrator angegeben. +@1 does not have any privileges.= +Privileges of @1: @2=Privilegien von @1: @2 []=[] Show privileges of yourself or another player=Ihre eigenen Privilegien oder die eines anderen Spielers anzeigen Player @1 does not exist.=Spieler @1 existiert nicht. -Privileges of @1: @2=Privilegien von @1: @2 = Return list of all online players with privilege=Liste aller Spieler mit einem Privileg ausgeben Invalid parameters (see /help haspriv).=Ungültige Parameter (siehe „/help haspriv“). Unknown privilege!=Unbekanntes Privileg! Players online with the "@1" privilege: @2=Derzeit online spielende Spieler mit dem „@1“-Privileg: @2 Your privileges are insufficient.=Ihre Privilegien sind unzureichend. +Your privileges are insufficient. '@1' only allows you to grant: @2= Unknown privilege: @1=Unbekanntes Privileg: @1 @1 granted you privileges: @2=@1 gewährte Ihnen Privilegien: @2 - ( | all)= ( | all) + ( [, [<...>]] | all)= Give privileges to player=Privileg an Spieler vergeben Invalid parameters (see /help grant).=Ungültige Parameter (siehe „/help grant“). - | all= | all + [, [<...>]] | all= Grant privileges to yourself=Privilegien an Ihnen selbst vergeben Invalid parameters (see /help grantme).=Ungültige Parameter (siehe „/help grantme“). +Your privileges are insufficient. '@1' only allows you to revoke: @2= +Note: Cannot revoke in singleplayer: @1= +Note: Cannot revoke from admin: @1= +No privileges were revoked.= @1 revoked privileges from you: @2=@1 entfernte Privilegien von Ihnen: @2 Remove privileges from player=Privilegien von Spieler entfernen Invalid parameters (see /help revoke).=Ungültige Parameter (siehe „/help revoke“). @@ -156,7 +164,6 @@ Kicked @1.=@1 hinausgeworfen. Clear all objects in world=Alle Objekte in der Welt löschen Invalid usage, see /help clearobjects.=Ungültige Verwendung, siehe /help clearobjects. Clearing all objects. This may take a long time. You may experience a timeout. (by @1)=Lösche alle Objekte. Dies kann eine lange Zeit dauern. Eine Netzwerkzeitüberschreitung könnte für Sie auftreten. (von @1) -Objects cleared.=Objekte gelöscht. Cleared all objects.=Alle Objekte gelöscht. = Send a direct message to a player=Eine Direktnachricht an einen Spieler senden @@ -184,7 +191,6 @@ Available commands:=Verfügbare Befehle: Command not available: @1=Befehl nicht verfügbar: @1 [all | privs | ]=[all | privs | ] Get help for commands or list privileges=Hilfe für Befehle erhalten oder Privilegien auflisten -Available privileges:=Verfügbare Privilegien: Command=Befehl Parameters=Parameter For more information, click on any entry in the list.=Für mehr Informationen klicken Sie auf einen beliebigen Eintrag in der Liste. @@ -194,16 +200,20 @@ Available commands: (see also: /help )=Verfügbare Befehle: (siehe auch: /h Close=Schließen Privilege=Privileg Description=Beschreibung +Available privileges:=Verfügbare Privilegien: print [] | dump [] | save [ []] | reset=print [] | dump [] | save [ []] Handle the profiler and profiling data=Den Profiler und Profilingdaten verwalten Statistics written to action log.=Statistiken zum Aktionsprotokoll geschrieben. Statistics were reset.=Statistiken wurden zurückgesetzt. Usage: @1=Verwendung: @1 Format can be one of txt, csv, lua, json, json_pretty (structures may be subject to change).=Format kann entweder „txt“, „csv“, „lua“, „json“ oder „json_pretty“ sein (die Struktur kann sich in Zukunft ändern). +@1 joined the game.= +@1 left the game.= +@1 left the game (timed out).= (no description)=(keine Beschreibung) Can interact with things and modify the world=Kann mit Dingen interagieren und die Welt verändern Can speak in chat=Kann im Chat sprechen -Can modify 'shout' and 'interact' privileges=Kann die „shout“- und „interact“-Privilegien anpassen +Can modify basic privileges (@1)= Can modify privileges=Kann Privilegien anpassen Can teleport self=Kann sich selbst teleportieren Can teleport other players=Kann andere Spieler teleportieren @@ -223,3 +233,16 @@ Unknown Item=Unbekannter Gegenstand Air=Luft Ignore=Ignorieren You can't place 'ignore' nodes!=Sie können keine „ignore“-Blöcke platzieren! +Values below show absolute/relative times spend per server step by the instrumented function.= +A total of @1 sample(s) were taken.= +The output is limited to '@1'.= +Saving of profile failed: @1= +Profile saved to @1= + + +##### not used anymore ##### + + ( | all)= ( | all) + | all= | all +Objects cleared.=Objekte gelöscht. +Can modify 'shout' and 'interact' privileges=Kann die „shout“- und „interact“-Privilegien anpassen diff --git a/builtin/locale/__builtin.it.tr b/builtin/locale/__builtin.it.tr index 94bc870c8..8bce1d0d2 100644 --- a/builtin/locale/__builtin.it.tr +++ b/builtin/locale/__builtin.it.tr @@ -2,6 +2,8 @@ Empty command.=Comando vuoto. Invalid command: @1=Comando non valido: @1 Invalid command usage.=Utilizzo del comando non valido. + (@1 s)= +Command execution took @1 s= You don't have permission to run this command (missing privileges: @1).=Non hai il permesso di eseguire questo comando (privilegi mancanti: @1). Unable to get position of player @1.=Impossibile ottenere la posizione del giocatore @1. Incorrect area format. Expected: (x1,y1,z1) (x2,y2,z2)=Formato dell'area non corretto. Richiesto: (x1,y1,z1) (x2,y2,z2) @@ -10,24 +12,30 @@ Show chat action (e.g., '/me orders a pizza' displays ' orders a pi Show the name of the server owner=Mostra il nome del proprietario del server The administrator of this server is @1.=L'amministratore di questo server è @1. There's no administrator named in the config file.=Non c'è nessun amministratore nel file di configurazione. +@1 does not have any privileges.= +Privileges of @1: @2=Privilegi di @1: @2 []=[] Show privileges of yourself or another player=Mostra i privilegi propri o di un altro giocatore Player @1 does not exist.=Il giocatore @1 non esiste. -Privileges of @1: @2=Privilegi di @1: @2 = Return list of all online players with privilege=Ritorna una lista di tutti i giocatori connessi col tale privilegio Invalid parameters (see /help haspriv).=Parametri non validi (vedi /help haspriv). Unknown privilege!=Privilegio sconosciuto! Players online with the "@1" privilege: @2=Giocatori connessi con il privilegio "@1": @2 Your privileges are insufficient.=I tuoi privilegi sono insufficienti. +Your privileges are insufficient. '@1' only allows you to grant: @2= Unknown privilege: @1=Privilegio sconosciuto: @1 @1 granted you privileges: @2=@1 ti ha assegnato i seguenti privilegi: @2 - ( | all)= ( | all) + ( [, [<...>]] | all)= Give privileges to player=Dà privilegi al giocatore Invalid parameters (see /help grant).=Parametri non validi (vedi /help grant). - | all= | all + [, [<...>]] | all= Grant privileges to yourself=Assegna dei privilegi a te stessǝ Invalid parameters (see /help grantme).=Parametri non validi (vedi /help grantme). +Your privileges are insufficient. '@1' only allows you to revoke: @2= +Note: Cannot revoke in singleplayer: @1= +Note: Cannot revoke from admin: @1= +No privileges were revoked.= @1 revoked privileges from you: @2=@1 ti ha revocato i seguenti privilegi: @2 Remove privileges from player=Rimuove privilegi dal giocatore Invalid parameters (see /help revoke).=Parametri non validi (vedi /help revoke). @@ -183,7 +191,6 @@ Available commands:=Comandi disponibili: Command not available: @1=Comando non disponibile: @1 [all | privs | ]=[all | privs | ] Get help for commands or list privileges=Richiama la finestra d'aiuto dei comandi o dei privilegi -Available privileges:=Privilegi disponibili: Command=Comando Parameters=Parametri For more information, click on any entry in the list.=Per più informazioni, clicca su una qualsiasi voce dell'elenco. @@ -193,16 +200,20 @@ Available commands: (see also: /help )=Comandi disponibili: (vedi anche /he Close=Chiudi Privilege=Privilegio Description=Descrizione +Available privileges:=Privilegi disponibili: print [] | dump [] | save [ []] | reset=print [] | dump [] | save [ []] | reset Handle the profiler and profiling data=Gestisce il profiler e i dati da esso elaborati Statistics written to action log.=Statistiche scritte nel log delle azioni. Statistics were reset.=Le statistiche sono state resettate. Usage: @1=Utilizzo: @1 Format can be one of txt, csv, lua, json, json_pretty (structures may be subject to change).=I formati supportati sono txt, csv, lua, json e json_pretty (le strutture potrebbero essere soggetti a cambiamenti). +@1 joined the game.= +@1 left the game.= +@1 left the game (timed out).= (no description)=(nessuna descrizione) Can interact with things and modify the world=Si può interagire con le cose e modificare il mondo Can speak in chat=Si può parlare in chat -Can modify 'shout' and 'interact' privileges=Si possono modificare i privilegi 'shout' e 'interact' +Can modify basic privileges (@1)= Can modify privileges=Si possono modificare i privilegi Can teleport self=Si può teletrasportare se stessз Can teleport other players=Si possono teletrasportare gli altri giocatori @@ -222,3 +233,15 @@ Unknown Item=Oggetto sconosciuto Air=Aria Ignore=Ignora You can't place 'ignore' nodes!=Non puoi piazzare nodi 'ignore'! +Values below show absolute/relative times spend per server step by the instrumented function.= +A total of @1 sample(s) were taken.= +The output is limited to '@1'.= +Saving of profile failed: @1= +Profile saved to @1= + + +##### not used anymore ##### + + ( | all)= ( | all) + | all= | all +Can modify 'shout' and 'interact' privileges=Si possono modificare i privilegi 'shout' e 'interact' diff --git a/builtin/locale/template.txt b/builtin/locale/template.txt index c5ace1a2f..db0ee07b8 100644 --- a/builtin/locale/template.txt +++ b/builtin/locale/template.txt @@ -2,6 +2,8 @@ Empty command.= Invalid command: @1= Invalid command usage.= + (@1 s)= +Command execution took @1 s= You don't have permission to run this command (missing privileges: @1).= Unable to get position of player @1.= Incorrect area format. Expected: (x1,y1,z1) (x2,y2,z2)= @@ -10,24 +12,30 @@ Show chat action (e.g., '/me orders a pizza' displays ' orders a pi Show the name of the server owner= The administrator of this server is @1.= There's no administrator named in the config file.= +@1 does not have any privileges.= +Privileges of @1: @2= []= Show privileges of yourself or another player= Player @1 does not exist.= -Privileges of @1: @2= = Return list of all online players with privilege= Invalid parameters (see /help haspriv).= Unknown privilege!= Players online with the "@1" privilege: @2= Your privileges are insufficient.= +Your privileges are insufficient. '@1' only allows you to grant: @2= Unknown privilege: @1= @1 granted you privileges: @2= - ( | all)= + ( [, [<...>]] | all)= Give privileges to player= Invalid parameters (see /help grant).= - | all= + [, [<...>]] | all= Grant privileges to yourself= Invalid parameters (see /help grantme).= +Your privileges are insufficient. '@1' only allows you to revoke: @2= +Note: Cannot revoke in singleplayer: @1= +Note: Cannot revoke from admin: @1= +No privileges were revoked.= @1 revoked privileges from you: @2= Remove privileges from player= Invalid parameters (see /help revoke).= @@ -183,7 +191,6 @@ Available commands:= Command not available: @1= [all | privs | ]= Get help for commands or list privileges= -Available privileges:= Command= Parameters= For more information, click on any entry in the list.= @@ -193,16 +200,20 @@ Available commands: (see also: /help )= Close= Privilege= Description= +Available privileges:= print [] | dump [] | save [ []] | reset= Handle the profiler and profiling data= Statistics written to action log.= Statistics were reset.= Usage: @1= Format can be one of txt, csv, lua, json, json_pretty (structures may be subject to change).= +@1 joined the game.= +@1 left the game.= +@1 left the game (timed out).= (no description)= Can interact with things and modify the world= Can speak in chat= -Can modify 'shout' and 'interact' privileges= +Can modify basic privileges (@1)= Can modify privileges= Can teleport self= Can teleport other players= @@ -222,3 +233,8 @@ Unknown Item= Air= Ignore= You can't place 'ignore' nodes!= +Values below show absolute/relative times spend per server step by the instrumented function.= +A total of @1 sample(s) were taken.= +The output is limited to '@1'.= +Saving of profile failed: @1= +Profile saved to @1= From a0e7a4a0df8fe49907abad2e28f9709d571386e1 Mon Sep 17 00:00:00 2001 From: Wuzzy Date: Fri, 2 Apr 2021 16:02:22 +0200 Subject: [PATCH 32/72] Update German builtin translation --- builtin/locale/__builtin.de.tr | 46 ++++++++++++++-------------------- 1 file changed, 19 insertions(+), 27 deletions(-) diff --git a/builtin/locale/__builtin.de.tr b/builtin/locale/__builtin.de.tr index 963ab8477..e8bc1fd84 100644 --- a/builtin/locale/__builtin.de.tr +++ b/builtin/locale/__builtin.de.tr @@ -2,8 +2,8 @@ Empty command.=Leerer Befehl. Invalid command: @1=Ungültiger Befehl: @1 Invalid command usage.=Ungültige Befehlsverwendung. - (@1 s)= -Command execution took @1 s= + (@1 s)= (@1 s) +Command execution took @1 s=Befehlsausführung brauchte @1 s You don't have permission to run this command (missing privileges: @1).=Sie haben keine Erlaubnis, diesen Befehl auszuführen (fehlende Privilegien: @1). Unable to get position of player @1.=Konnte Position vom Spieler @1 nicht ermitteln. Incorrect area format. Expected: (x1,y1,z1) (x2,y2,z2)=Ungültiges Gebietsformat. Erwartet: (x1,y1,z1) (x2,y2,z2) @@ -12,7 +12,7 @@ Show chat action (e.g., '/me orders a pizza' displays ' orders a pi Show the name of the server owner=Den Namen des Servereigentümers zeigen The administrator of this server is @1.=Der Administrator dieses Servers ist @1. There's no administrator named in the config file.=In der Konfigurationsdatei wurde kein Administrator angegeben. -@1 does not have any privileges.= +@1 does not have any privileges.=@1 hat keine Privilegien. Privileges of @1: @2=Privilegien von @1: @2 []=[] Show privileges of yourself or another player=Ihre eigenen Privilegien oder die eines anderen Spielers anzeigen @@ -23,19 +23,19 @@ Invalid parameters (see /help haspriv).=Ungültige Parameter (siehe „/help has Unknown privilege!=Unbekanntes Privileg! Players online with the "@1" privilege: @2=Derzeit online spielende Spieler mit dem „@1“-Privileg: @2 Your privileges are insufficient.=Ihre Privilegien sind unzureichend. -Your privileges are insufficient. '@1' only allows you to grant: @2= +Your privileges are insufficient. '@1' only allows you to grant: @2=Ihre Privilegien sind unzureichend. Mit „@1“ können Sie nur folgendes gewähren: @2 Unknown privilege: @1=Unbekanntes Privileg: @1 @1 granted you privileges: @2=@1 gewährte Ihnen Privilegien: @2 - ( [, [<...>]] | all)= + ( [, [<...>]] | all)= ( [, [<...>]] | all) Give privileges to player=Privileg an Spieler vergeben Invalid parameters (see /help grant).=Ungültige Parameter (siehe „/help grant“). - [, [<...>]] | all= + [, [<...>]] | all= [, [<...>]] | all Grant privileges to yourself=Privilegien an Ihnen selbst vergeben Invalid parameters (see /help grantme).=Ungültige Parameter (siehe „/help grantme“). -Your privileges are insufficient. '@1' only allows you to revoke: @2= -Note: Cannot revoke in singleplayer: @1= -Note: Cannot revoke from admin: @1= -No privileges were revoked.= +Your privileges are insufficient. '@1' only allows you to revoke: @2=Ihre Privilegien sind unzureichend. Mit „@1“ können Sie nur folgendes entziehen: @2 +Note: Cannot revoke in singleplayer: @1=Anmerkung: Im Einzelspielermodus kann man folgendes nicht entziehen: @1 +Note: Cannot revoke from admin: @1=Anmerkung: Vom Admin kann man folgendes nicht entziehen: @1 +No privileges were revoked.=Es wurden keine Privilegien entzogen. @1 revoked privileges from you: @2=@1 entfernte Privilegien von Ihnen: @2 Remove privileges from player=Privilegien von Spieler entfernen Invalid parameters (see /help revoke).=Ungültige Parameter (siehe „/help revoke“). @@ -207,13 +207,13 @@ Statistics written to action log.=Statistiken zum Aktionsprotokoll geschrieben. Statistics were reset.=Statistiken wurden zurückgesetzt. Usage: @1=Verwendung: @1 Format can be one of txt, csv, lua, json, json_pretty (structures may be subject to change).=Format kann entweder „txt“, „csv“, „lua“, „json“ oder „json_pretty“ sein (die Struktur kann sich in Zukunft ändern). -@1 joined the game.= -@1 left the game.= -@1 left the game (timed out).= +@1 joined the game.=@1 ist dem Spiel beigetreten. +@1 left the game.=@1 hat das Spiel verlassen. +@1 left the game (timed out).=@1 hat das Spiel verlassen (Netzwerkzeitüberschreitung). (no description)=(keine Beschreibung) Can interact with things and modify the world=Kann mit Dingen interagieren und die Welt verändern Can speak in chat=Kann im Chat sprechen -Can modify basic privileges (@1)= +Can modify basic privileges (@1)=Kann grundlegende Privilegien anpassen (@1) Can modify privileges=Kann Privilegien anpassen Can teleport self=Kann sich selbst teleportieren Can teleport other players=Kann andere Spieler teleportieren @@ -233,16 +233,8 @@ Unknown Item=Unbekannter Gegenstand Air=Luft Ignore=Ignorieren You can't place 'ignore' nodes!=Sie können keine „ignore“-Blöcke platzieren! -Values below show absolute/relative times spend per server step by the instrumented function.= -A total of @1 sample(s) were taken.= -The output is limited to '@1'.= -Saving of profile failed: @1= -Profile saved to @1= - - -##### not used anymore ##### - - ( | all)= ( | all) - | all= | all -Objects cleared.=Objekte gelöscht. -Can modify 'shout' and 'interact' privileges=Kann die „shout“- und „interact“-Privilegien anpassen +Values below show absolute/relative times spend per server step by the instrumented function.=Die unten angegebenen Werte zeigen absolute/relative Zeitspannen, die je Server-Step von der instrumentierten Funktion in Anspruch genommen wurden. +A total of @1 sample(s) were taken.=Es wurden insgesamt @1 Datenpunkt(e) aufgezeichnet. +The output is limited to '@1'.=Die Ausgabe ist beschränkt auf „@1“. +Saving of profile failed: @1=Speichern des Profils fehlgeschlagen: @1 +Profile saved to @1=Profil abgespeichert nach @1 From 0abc1e98edb87b2e23eecccfd6b1393ac7fb4f56 Mon Sep 17 00:00:00 2001 From: sfan5 Date: Fri, 9 Apr 2021 22:36:10 +0200 Subject: [PATCH 33/72] Fix server favorites not saving when client/serverlist/ doesn't exist already (#11152) --- builtin/mainmenu/serverlistmgr.lua | 10 ++++++---- src/script/lua_api/l_mainmenu.cpp | 19 +++++++++++-------- src/script/lua_api/l_mainmenu.h | 2 +- 3 files changed, 18 insertions(+), 13 deletions(-) diff --git a/builtin/mainmenu/serverlistmgr.lua b/builtin/mainmenu/serverlistmgr.lua index 9876d8ac5..964d0c584 100644 --- a/builtin/mainmenu/serverlistmgr.lua +++ b/builtin/mainmenu/serverlistmgr.lua @@ -90,8 +90,11 @@ function serverlistmgr.sync() end -------------------------------------------------------------------------------- -local function get_favorites_path() +local function get_favorites_path(folder) local base = core.get_user_path() .. DIR_DELIM .. "client" .. DIR_DELIM .. "serverlist" .. DIR_DELIM + if folder then + return base + end return base .. core.settings:get("serverlist_file") end @@ -103,9 +106,8 @@ local function save_favorites(favorites) core.settings:set("serverlist_file", filename:sub(1, #filename - 4) .. ".json") end - local path = get_favorites_path() - core.create_dir(path) - core.safe_file_write(path, core.write_json(favorites)) + assert(core.create_dir(get_favorites_path(true))) + core.safe_file_write(get_favorites_path(), core.write_json(favorites)) end -------------------------------------------------------------------------------- diff --git a/src/script/lua_api/l_mainmenu.cpp b/src/script/lua_api/l_mainmenu.cpp index 6826ece05..6488cd0fc 100644 --- a/src/script/lua_api/l_mainmenu.cpp +++ b/src/script/lua_api/l_mainmenu.cpp @@ -716,21 +716,24 @@ int ModApiMainMenu::l_get_mainmenu_path(lua_State *L) } /******************************************************************************/ -bool ModApiMainMenu::mayModifyPath(const std::string &path) +bool ModApiMainMenu::mayModifyPath(std::string path) { + path = fs::RemoveRelativePathComponents(path); + if (fs::PathStartsWith(path, fs::TempPath())) return true; - if (fs::PathStartsWith(path, fs::RemoveRelativePathComponents(porting::path_user + DIR_DELIM "games"))) - return true; + std::string path_user = fs::RemoveRelativePathComponents(porting::path_user); - if (fs::PathStartsWith(path, fs::RemoveRelativePathComponents(porting::path_user + DIR_DELIM "mods"))) + if (fs::PathStartsWith(path, path_user + DIR_DELIM "client")) return true; - - if (fs::PathStartsWith(path, fs::RemoveRelativePathComponents(porting::path_user + DIR_DELIM "textures"))) + if (fs::PathStartsWith(path, path_user + DIR_DELIM "games")) return true; - - if (fs::PathStartsWith(path, fs::RemoveRelativePathComponents(porting::path_user + DIR_DELIM "worlds"))) + if (fs::PathStartsWith(path, path_user + DIR_DELIM "mods")) + return true; + if (fs::PathStartsWith(path, path_user + DIR_DELIM "textures")) + return true; + if (fs::PathStartsWith(path, path_user + DIR_DELIM "worlds")) return true; if (fs::PathStartsWith(path, fs::RemoveRelativePathComponents(porting::path_cache))) diff --git a/src/script/lua_api/l_mainmenu.h b/src/script/lua_api/l_mainmenu.h index 49ce7c251..33ac9e721 100644 --- a/src/script/lua_api/l_mainmenu.h +++ b/src/script/lua_api/l_mainmenu.h @@ -58,7 +58,7 @@ private: * @param path path to check * @return true if the path may be modified */ - static bool mayModifyPath(const std::string &path); + static bool mayModifyPath(std::string path); //api calls From 4b8209d9a44425156ba89a4763f63ea088daccb3 Mon Sep 17 00:00:00 2001 From: Wuzzy Date: Sun, 11 Apr 2021 15:09:37 +0000 Subject: [PATCH 34/72] Modifying fall damage via armor group (#11080) Adds a new fall_damage_add_percent armor group which influences the fall damage in addition to the existing node group. --- doc/lua_api.txt | 15 +++++++++++++-- src/client/clientenvironment.cpp | 26 +++++++++++++++++++------- 2 files changed, 32 insertions(+), 9 deletions(-) diff --git a/doc/lua_api.txt b/doc/lua_api.txt index 6c1e46c7e..7d413a9e9 100644 --- a/doc/lua_api.txt +++ b/doc/lua_api.txt @@ -1730,7 +1730,15 @@ to games. * `3`: the node always gets the digging time 0 seconds (torch) * `disable_jump`: Player (and possibly other things) cannot jump from node or if their feet are in the node. Note: not supported for `new_move = false` -* `fall_damage_add_percent`: damage speed = `speed * (1 + value/100)` +* `fall_damage_add_percent`: modifies the fall damage suffered when hitting + the top of this node. There's also an armor group with the same name. + The final player damage is determined by the following formula: + damage = + collision speed + * ((node_fall_damage_add_percent + 100) / 100) -- node group + * ((player_fall_damage_add_percent + 100) / 100) -- player armor group + - (14) -- constant tolerance + Negative damage values are discarded as no damage. * `falling_node`: if there is no walkable block under the node it will fall * `float`: the node will not fall through liquids * `level`: Can be used to give an additional sense of progression in the game. @@ -1750,12 +1758,15 @@ to games. `"toolrepair"` crafting recipe -### `ObjectRef` groups +### `ObjectRef` armor groups * `immortal`: Skips all damage and breath handling for an object. This group will also hide the integrated HUD status bars for players. It is automatically set to all players when damage is disabled on the server and cannot be reset (subject to change). +* `fall_damage_add_percent`: Modifies the fall damage suffered by players + when they hit the ground. It is analog to the node group with the same + name. See the node group above for the exact calculation. * `punch_operable`: For entities; disables the regular damage mechanism for players punching it by hand or a non-tool item, so that it can do something else than take damage. diff --git a/src/client/clientenvironment.cpp b/src/client/clientenvironment.cpp index fc7cbe254..1bdf5390d 100644 --- a/src/client/clientenvironment.cpp +++ b/src/client/clientenvironment.cpp @@ -235,7 +235,16 @@ void ClientEnvironment::step(float dtime) &player_collisions); } - bool player_immortal = lplayer->getCAO() && lplayer->getCAO()->isImmortal(); + bool player_immortal = false; + f32 player_fall_factor = 1.0f; + GenericCAO *playercao = lplayer->getCAO(); + if (playercao) { + player_immortal = playercao->isImmortal(); + int addp_p = itemgroup_get(playercao->getGroups(), + "fall_damage_add_percent"); + // convert armor group into an usable fall damage factor + player_fall_factor = 1.0f + (float)addp_p / 100.0f; + } for (const CollisionInfo &info : player_collisions) { v3f speed_diff = info.new_speed - info.old_speed;; @@ -248,17 +257,20 @@ void ClientEnvironment::step(float dtime) speed_diff.Z = 0; f32 pre_factor = 1; // 1 hp per node/s f32 tolerance = BS*14; // 5 without damage - f32 post_factor = 1; // 1 hp per node/s if (info.type == COLLISION_NODE) { const ContentFeatures &f = m_client->ndef()-> get(m_map->getNode(info.node_p)); - // Determine fall damage multiplier - int addp = itemgroup_get(f.groups, "fall_damage_add_percent"); - pre_factor = 1.0f + (float)addp / 100.0f; + // Determine fall damage modifier + int addp_n = itemgroup_get(f.groups, "fall_damage_add_percent"); + // convert node group to an usable fall damage factor + f32 node_fall_factor = 1.0f + (float)addp_n / 100.0f; + // combine both player fall damage modifiers + pre_factor = node_fall_factor * player_fall_factor; } float speed = pre_factor * speed_diff.getLength(); - if (speed > tolerance && !player_immortal) { - f32 damage_f = (speed - tolerance) / BS * post_factor; + + if (speed > tolerance && !player_immortal && pre_factor > 0.0f) { + f32 damage_f = (speed - tolerance) / BS; u16 damage = (u16)MYMIN(damage_f + 0.5, U16_MAX); if (damage != 0) { damageLocalPlayer(damage, true); From 4d0fef8ae87aa7b940d43485e7f6466eaa3d111e Mon Sep 17 00:00:00 2001 From: sfan5 Date: Sun, 11 Apr 2021 17:10:06 +0200 Subject: [PATCH 35/72] Buildbot changes to allow out-of-tree builds (#11180) * Do proper out-of-tree builds with buildbot * Don't write to bin/ for cross builds * This allows safely building multiple builds from the same source dir, e.g. with the buildbot. * Disable Gettext (by default) and Freetype (entirely) for server builds --- src/CMakeLists.txt | 13 +++++++----- util/buildbot/buildwin32.sh | 40 ++++++++++++++++++------------------- util/buildbot/buildwin64.sh | 39 ++++++++++++++++++------------------ 3 files changed, 47 insertions(+), 45 deletions(-) diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt index 4bb6877d9..26441063f 100644 --- a/src/CMakeLists.txt +++ b/src/CMakeLists.txt @@ -55,7 +55,7 @@ if(NOT USE_CURL) endif() -option(ENABLE_GETTEXT "Use GetText for internationalization" TRUE) +option(ENABLE_GETTEXT "Use GetText for internationalization" ${BUILD_CLIENT}) set(USE_GETTEXT FALSE) if(ENABLE_GETTEXT) @@ -120,13 +120,13 @@ endif() option(ENABLE_FREETYPE "Enable FreeType2 (TrueType fonts and basic unicode support)" TRUE) set(USE_FREETYPE FALSE) -if(ENABLE_FREETYPE) +if(BUILD_CLIENT AND ENABLE_FREETYPE) find_package(Freetype) if(FREETYPE_FOUND) message(STATUS "Freetype enabled.") set(USE_FREETYPE TRUE) endif() -endif(ENABLE_FREETYPE) +endif() option(ENABLE_CURSES "Enable ncurses console" TRUE) set(USE_CURSES FALSE) @@ -526,8 +526,11 @@ if(USE_CURL) endif() -set(EXECUTABLE_OUTPUT_PATH "${CMAKE_SOURCE_DIR}/bin") - +# When cross-compiling assume the user doesn't want to run the executable anyway, +# otherwise place it in /bin/ since Minetest can only run from there. +if(NOT CMAKE_CROSSCOMPILING) + set(EXECUTABLE_OUTPUT_PATH "${CMAKE_SOURCE_DIR}/bin") +endif() if(BUILD_CLIENT) add_executable(${PROJECT_NAME} ${client_SRCS} ${extra_windows_SRCS}) diff --git a/util/buildbot/buildwin32.sh b/util/buildbot/buildwin32.sh index 1a66a9764..df62062c9 100755 --- a/util/buildbot/buildwin32.sh +++ b/util/buildbot/buildwin32.sh @@ -85,36 +85,36 @@ cd $libdir [ -d luajit ] || unzip -o $packagedir/luajit-$luajit_version.zip -d luajit [ -d leveldb ] || unzip -o $packagedir/libleveldb-$leveldb_version.zip -d leveldb -# Get minetest -cd $builddir -if [ ! "x$EXISTING_MINETEST_DIR" = "x" ]; then - cd /$EXISTING_MINETEST_DIR # must be absolute path +# Set source dir, downloading Minetest as needed +if [ -n "$EXISTING_MINETEST_DIR" ]; then + sourcedir="$( cd "$EXISTING_MINETEST_DIR" && pwd )" else - [ -d $CORE_NAME ] && (cd $CORE_NAME && git pull) || (git clone -b $CORE_BRANCH $CORE_GIT) - cd $CORE_NAME + sourcedir=$PWD/$CORE_NAME + [ -d $CORE_NAME ] && { pushd $CORE_NAME; git pull; popd; } || \ + git clone -b $CORE_BRANCH $CORE_GIT $CORE_NAME + if [ -z "$NO_MINETEST_GAME" ]; then + [ -d games/$GAME_NAME ] && { pushd games/$GAME_NAME; git pull; popd; } || \ + git clone -b $GAME_BRANCH $GAME_GIT games/$GAME_NAME + fi fi -git_hash=$(git rev-parse --short HEAD) -# Get minetest_game -if [ "x$NO_MINETEST_GAME" = "x" ]; then - cd games - [ -d $GAME_NAME ] && (cd $GAME_NAME && git pull) || (git clone -b $GAME_BRANCH $GAME_GIT) - cd .. -fi +git_hash=$(cd $sourcedir && git rev-parse --short HEAD) + +# Build the thing +cd $builddir +[ -d build ] && rm -rf build +mkdir build +cd build irr_dlls=$(echo $libdir/irrlicht/bin/*.dll | tr ' ' ';') vorbis_dlls=$(echo $libdir/libvorbis/bin/libvorbis{,file}-*.dll | tr ' ' ';') gettext_dlls=$(echo $libdir/gettext/bin/lib{intl,iconv}-*.dll | tr ' ' ';') -# Build the thing -[ -d _build ] && rm -Rf _build/ -mkdir _build -cd _build -cmake .. \ +cmake -S $sourcedir -B . \ + -DCMAKE_TOOLCHAIN_FILE=$toolchain_file \ -DCMAKE_INSTALL_PREFIX=/tmp \ -DVERSION_EXTRA=$git_hash \ -DBUILD_CLIENT=1 -DBUILD_SERVER=0 \ - -DCMAKE_TOOLCHAIN_FILE=$toolchain_file \ \ -DENABLE_SOUND=1 \ -DENABLE_CURL=1 \ @@ -170,7 +170,7 @@ cmake .. \ make -j$(nproc) -[ "x$NO_PACKAGE" = "x" ] && make package +[ -z "$NO_PACKAGE" ] && make package exit 0 # EOF diff --git a/util/buildbot/buildwin64.sh b/util/buildbot/buildwin64.sh index 54bfbef69..c35ece35b 100755 --- a/util/buildbot/buildwin64.sh +++ b/util/buildbot/buildwin64.sh @@ -60,7 +60,6 @@ cd $builddir [ -e $packagedir/openal_stripped.zip ] || wget http://minetest.kitsunemimi.pw/openal_stripped64.zip \ -c -O $packagedir/openal_stripped.zip - # Extract stuff cd $libdir [ -d irrlicht ] || unzip -o $packagedir/irrlicht-$irrlicht_version.zip -d irrlicht @@ -75,32 +74,32 @@ cd $libdir [ -d luajit ] || unzip -o $packagedir/luajit-$luajit_version.zip -d luajit [ -d leveldb ] || unzip -o $packagedir/libleveldb-$leveldb_version.zip -d leveldb -# Get minetest -cd $builddir -if [ ! "x$EXISTING_MINETEST_DIR" = "x" ]; then - cd /$EXISTING_MINETEST_DIR # must be absolute path +# Set source dir, downloading Minetest as needed +if [ -n "$EXISTING_MINETEST_DIR" ]; then + sourcedir="$( cd "$EXISTING_MINETEST_DIR" && pwd )" else - [ -d $CORE_NAME ] && (cd $CORE_NAME && git pull) || (git clone -b $CORE_BRANCH $CORE_GIT) - cd $CORE_NAME + sourcedir=$PWD/$CORE_NAME + [ -d $CORE_NAME ] && { pushd $CORE_NAME; git pull; popd; } || \ + git clone -b $CORE_BRANCH $CORE_GIT $CORE_NAME + if [ -z "$NO_MINETEST_GAME" ]; then + [ -d games/$GAME_NAME ] && { pushd games/$GAME_NAME; git pull; popd; } || \ + git clone -b $GAME_BRANCH $GAME_GIT games/$GAME_NAME + fi fi -git_hash=$(git rev-parse --short HEAD) -# Get minetest_game -if [ "x$NO_MINETEST_GAME" = "x" ]; then - cd games - [ -d $GAME_NAME ] && (cd $GAME_NAME && git pull) || (git clone -b $GAME_BRANCH $GAME_GIT) - cd .. -fi +git_hash=$(cd $sourcedir && git rev-parse --short HEAD) + +# Build the thing +cd $builddir +[ -d build ] && rm -rf build +mkdir build +cd build irr_dlls=$(echo $libdir/irrlicht/bin/*.dll | tr ' ' ';') vorbis_dlls=$(echo $libdir/libvorbis/bin/libvorbis{,file}-*.dll | tr ' ' ';') gettext_dlls=$(echo $libdir/gettext/bin/lib{intl,iconv}-*.dll | tr ' ' ';') -# Build the thing -[ -d _build ] && rm -Rf _build/ -mkdir _build -cd _build -cmake .. \ +cmake -S $sourcedir -B . \ -DCMAKE_TOOLCHAIN_FILE=$toolchain_file \ -DCMAKE_INSTALL_PREFIX=/tmp \ -DVERSION_EXTRA=$git_hash \ @@ -160,7 +159,7 @@ cmake .. \ make -j$(nproc) -[ "x$NO_PACKAGE" = "x" ] && make package +[ -z "$NO_PACKAGE" ] && make package exit 0 # EOF From bbe120308f2944eade833b4f16cfc3b42b01fa34 Mon Sep 17 00:00:00 2001 From: SmallJoker Date: Tue, 13 Apr 2021 20:02:18 +0200 Subject: [PATCH 36/72] Attachments: Avoid data loss caused by set_attach() in callbacks (#11181) --- src/server/unit_sao.cpp | 11 ++++++++--- 1 file changed, 8 insertions(+), 3 deletions(-) diff --git a/src/server/unit_sao.cpp b/src/server/unit_sao.cpp index 2371640ca..fa6c8f0f4 100644 --- a/src/server/unit_sao.cpp +++ b/src/server/unit_sao.cpp @@ -134,16 +134,21 @@ void UnitSAO::setAttachment(int parent_id, const std::string &bone, v3f position int old_parent = m_attachment_parent_id; m_attachment_parent_id = parent_id; + + // The detach callbacks might call to setAttachment() again. + // Ensure the attachment params are applied after this callback is run. + if (parent_id != old_parent) + onDetach(old_parent); + + m_attachment_parent_id = parent_id; m_attachment_bone = bone; m_attachment_position = position; m_attachment_rotation = rotation; m_force_visible = force_visible; m_attachment_sent = false; - if (parent_id != old_parent) { - onDetach(old_parent); + if (parent_id != old_parent) onAttach(parent_id); - } } void UnitSAO::getAttachment(int *parent_id, std::string *bone, v3f *position, From a106bfd456509b676ccba0ac9bef75c214819028 Mon Sep 17 00:00:00 2001 From: benrob0329 Date: Tue, 13 Apr 2021 14:02:43 -0400 Subject: [PATCH 37/72] Also return the ObjectRef from minetest.spawn_falling_node() (#11184) --- builtin/game/falling.lua | 2 +- doc/lua_api.txt | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/builtin/game/falling.lua b/builtin/game/falling.lua index 057d0d0ed..5450542ff 100644 --- a/builtin/game/falling.lua +++ b/builtin/game/falling.lua @@ -407,7 +407,7 @@ local function convert_to_falling_node(pos, node) obj:get_luaentity():set_node(node, metatable) core.remove_node(pos) - return true + return true, obj end function core.spawn_falling_node(pos) diff --git a/doc/lua_api.txt b/doc/lua_api.txt index 7d413a9e9..4c963465a 100644 --- a/doc/lua_api.txt +++ b/doc/lua_api.txt @@ -4927,7 +4927,7 @@ Environment access * Punch node with the same effects that a player would cause * `minetest.spawn_falling_node(pos)` * Change node into falling node - * Returns `true` if successful, `false` on failure + * Returns `true` and the ObjectRef of the spawned entity if successful, `false` on failure * `minetest.find_nodes_with_meta(pos1, pos2)` * Get a table of positions of nodes that have metadata within a region From 52c0384bd1c9f564f7a6deab93e560dc49ff8915 Mon Sep 17 00:00:00 2001 From: sfan5 Date: Fri, 16 Apr 2021 23:39:16 +0200 Subject: [PATCH 38/72] Fix ignored OpenGLES2 include path and cmake warning --- cmake/Modules/FindOpenGLES2.cmake | 3 +-- src/CMakeLists.txt | 4 ++++ 2 files changed, 5 insertions(+), 2 deletions(-) diff --git a/cmake/Modules/FindOpenGLES2.cmake b/cmake/Modules/FindOpenGLES2.cmake index a47126705..ce04191dd 100644 --- a/cmake/Modules/FindOpenGLES2.cmake +++ b/cmake/Modules/FindOpenGLES2.cmake @@ -42,7 +42,7 @@ else() ) include(FindPackageHandleStandardArgs) - find_package_handle_standard_args(OPENGLES2 DEFAULT_MSG OPENGLES2_LIBRARY OPENGLES2_INCLUDE_DIR) + find_package_handle_standard_args(OpenGLES2 DEFAULT_MSG OPENGLES2_LIBRARY OPENGLES2_INCLUDE_DIR) find_path(EGL_INCLUDE_DIR EGL/egl.h PATHS /usr/openwin/share/include @@ -59,7 +59,6 @@ else() /usr/lib ) - include(FindPackageHandleStandardArgs) find_package_handle_standard_args(EGL DEFAULT_MSG EGL_LIBRARY EGL_INCLUDE_DIR) endif() diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt index 26441063f..16b5bf991 100644 --- a/src/CMakeLists.txt +++ b/src/CMakeLists.txt @@ -513,6 +513,10 @@ include_directories( ${PROJECT_SOURCE_DIR}/script ) +if(ENABLE_GLES) + include_directories(${OPENGLES2_INCLUDE_DIR} ${EGL_INCLUDE_DIR}) +endif() + if(USE_GETTEXT) include_directories(${GETTEXT_INCLUDE_DIR}) endif() From 623f0a8613bd8677e259366a1d540deedb9d2302 Mon Sep 17 00:00:00 2001 From: sfan5 Date: Sun, 28 Mar 2021 22:53:48 +0200 Subject: [PATCH 39/72] Isolate library tables between sandbox and insecure env --- src/script/cpp_api/s_security.cpp | 44 ++++++++++++++++++++++++++++++- 1 file changed, 43 insertions(+), 1 deletion(-) diff --git a/src/script/cpp_api/s_security.cpp b/src/script/cpp_api/s_security.cpp index 63058d7c3..add7b1658 100644 --- a/src/script/cpp_api/s_security.cpp +++ b/src/script/cpp_api/s_security.cpp @@ -45,6 +45,21 @@ static inline void copy_safe(lua_State *L, const char *list[], unsigned len, int } } +static void shallow_copy_table(lua_State *L, int from=-2, int to=-1) +{ + if (from < 0) from = lua_gettop(L) + from + 1; + if (to < 0) to = lua_gettop(L) + to + 1; + lua_pushnil(L); + while (lua_next(L, from) != 0) { + assert(lua_type(L, -1) != LUA_TTABLE); + // duplicate key and value for lua_rawset + lua_pushvalue(L, -2); + lua_pushvalue(L, -2); + lua_rawset(L, to); + lua_pop(L, 1); + } +} + // Pushes the original version of a library function on the stack, from the old version static inline void push_original(lua_State *L, const char *lib, const char *func) { @@ -83,7 +98,10 @@ void ScriptApiSecurity::initializeSecurity() "unpack", "_VERSION", "xpcall", - // Completely safe libraries + }; + static const char *whitelist_tables[] = { + // These libraries are completely safe BUT we need to duplicate their table + // to ensure the sandbox can't affect the insecure env "coroutine", "string", "table", @@ -167,6 +185,17 @@ void ScriptApiSecurity::initializeSecurity() lua_pop(L, 1); + // Copy safe libraries + for (const char *libname : whitelist_tables) { + lua_getfield(L, old_globals, libname); + lua_newtable(L); + shallow_copy_table(L); + + lua_setglobal(L, libname); + lua_pop(L, 1); + } + + // Copy safe IO functions lua_getfield(L, old_globals, "io"); lua_newtable(L); @@ -222,6 +251,19 @@ void ScriptApiSecurity::initializeSecurity() #endif lua_pop(L, 1); // Pop globals_backup + + + /* + * In addition to copying the tables in whitelist_tables, we also need to + * replace the string metatable. Otherwise old_globals.string would + * be accessible via getmetatable("").__index from inside the sandbox. + */ + lua_pushliteral(L, ""); + lua_newtable(L); + lua_getglobal(L, "string"); + lua_setfield(L, -2, "__index"); + lua_setmetatable(L, -2); + lua_pop(L, 1); // Pop empty string } void ScriptApiSecurity::initializeSecurityClient() From 0077982fb78a8ed39a90da03c0898d12583fed64 Mon Sep 17 00:00:00 2001 From: sfan5 Date: Sun, 18 Apr 2021 16:07:13 +0200 Subject: [PATCH 40/72] GLES fixes (#11205) * Consistently set float precision for GLES * Enable DPI scaling on Windows+GLES --- src/client/renderingengine.cpp | 4 ++++ src/client/shader.cpp | 12 +++++++----- 2 files changed, 11 insertions(+), 5 deletions(-) diff --git a/src/client/renderingengine.cpp b/src/client/renderingengine.cpp index 4f59bbae3..d2d136a61 100644 --- a/src/client/renderingengine.cpp +++ b/src/client/renderingengine.cpp @@ -335,6 +335,10 @@ static bool getWindowHandle(irr::video::IVideoDriver *driver, HWND &hWnd) case video::EDT_DIRECT3D9: hWnd = reinterpret_cast(exposedData.D3D9.HWnd); break; +#if ENABLE_GLES + case video::EDT_OGLES1: + case video::EDT_OGLES2: +#endif case video::EDT_OPENGL: hWnd = reinterpret_cast(exposedData.OpenGLWin32.HWnd); break; diff --git a/src/client/shader.cpp b/src/client/shader.cpp index b3e4911f4..58946b90f 100644 --- a/src/client/shader.cpp +++ b/src/client/shader.cpp @@ -579,8 +579,10 @@ ShaderInfo ShaderSource::generateShader(const std::string &name, if (use_gles) { shaders_header << R"( #version 100 - )"; + )"; vertex_header = R"( + precision mediump float; + uniform highp mat4 mWorldView; uniform highp mat4 mWorldViewProj; uniform mediump mat4 mTexture; @@ -592,17 +594,17 @@ ShaderInfo ShaderSource::generateShader(const std::string &name, attribute mediump vec3 inVertexNormal; attribute mediump vec4 inVertexTangent; attribute mediump vec4 inVertexBinormal; - )"; + )"; fragment_header = R"( precision mediump float; - )"; + )"; } else { shaders_header << R"( #version 120 #define lowp #define mediump #define highp - )"; + )"; vertex_header = R"( #define mWorldView gl_ModelViewMatrix #define mWorldViewProj gl_ModelViewProjectionMatrix @@ -615,7 +617,7 @@ ShaderInfo ShaderSource::generateShader(const std::string &name, #define inVertexNormal gl_Normal #define inVertexTangent gl_MultiTexCoord1 #define inVertexBinormal gl_MultiTexCoord2 - )"; + )"; } bool use_discard = use_gles; From 16e5b39e1dbe503684effb11f4b87a641c3e43e6 Mon Sep 17 00:00:00 2001 From: Seth Traverse Date: Tue, 20 Apr 2021 10:23:31 -0700 Subject: [PATCH 41/72] Add a key to toggle map block bounds (#11172) It's often useful to know where the map block boundaries are for doing server admin work and the like. Adds three modes: single mapblock, range of 5, and disabled. --- src/client/game.cpp | 2 ++ src/client/hud.cpp | 48 +++++++++++++++++++++++++ src/client/hud.h | 11 ++++++ src/client/inputhandler.cpp | 1 + src/client/keys.h | 1 + src/client/render/core.cpp | 1 + src/defaultsettings.cpp | 1 + src/gui/guiKeyChangeMenu.cpp | 68 +++++++++++++++++++----------------- 8 files changed, 100 insertions(+), 33 deletions(-) diff --git a/src/client/game.cpp b/src/client/game.cpp index edb054032..b092b95e2 100644 --- a/src/client/game.cpp +++ b/src/client/game.cpp @@ -1932,6 +1932,8 @@ void Game::processKeyInput() toggleCinematic(); } else if (wasKeyDown(KeyType::SCREENSHOT)) { client->makeScreenshot(); + } else if (wasKeyDown(KeyType::TOGGLE_BLOCK_BOUNDS)) { + hud->toggleBlockBounds(); } else if (wasKeyDown(KeyType::TOGGLE_HUD)) { m_game_ui->toggleHud(); } else if (wasKeyDown(KeyType::MINIMAP)) { diff --git a/src/client/hud.cpp b/src/client/hud.cpp index 6d332490c..c58c7e822 100644 --- a/src/client/hud.cpp +++ b/src/client/hud.cpp @@ -862,6 +862,54 @@ void Hud::drawSelectionMesh() } } +void Hud::toggleBlockBounds() +{ + m_block_bounds_mode = static_cast(m_block_bounds_mode + 1); + + if (m_block_bounds_mode >= BLOCK_BOUNDS_MAX) { + m_block_bounds_mode = BLOCK_BOUNDS_OFF; + } +} + +void Hud::drawBlockBounds() +{ + if (m_block_bounds_mode == BLOCK_BOUNDS_OFF) { + return; + } + + video::SMaterial old_material = driver->getMaterial2D(); + driver->setMaterial(m_selection_material); + + v3s16 pos = player->getStandingNodePos(); + + v3s16 blockPos( + floorf((float) pos.X / MAP_BLOCKSIZE), + floorf((float) pos.Y / MAP_BLOCKSIZE), + floorf((float) pos.Z / MAP_BLOCKSIZE) + ); + + v3f offset = intToFloat(client->getCamera()->getOffset(), BS); + + s8 radius = m_block_bounds_mode == BLOCK_BOUNDS_ALL ? 2 : 0; + + v3f halfNode = v3f(BS, BS, BS) / 2.0f; + + for (s8 x = -radius; x <= radius; x++) + for (s8 y = -radius; y <= radius; y++) + for (s8 z = -radius; z <= radius; z++) { + v3s16 blockOffset(x, y, z); + + aabb3f box( + intToFloat((blockPos + blockOffset) * MAP_BLOCKSIZE, BS) - offset - halfNode, + intToFloat(((blockPos + blockOffset) * MAP_BLOCKSIZE) + (MAP_BLOCKSIZE - 1), BS) - offset + halfNode + ); + + driver->draw3DBox(box, video::SColor(255, 255, 0, 0)); + } + + driver->setMaterial(old_material); +} + void Hud::updateSelectionMesh(const v3s16 &camera_offset) { m_camera_offset = camera_offset; diff --git a/src/client/hud.h b/src/client/hud.h index d46545d71..7046a16fb 100644 --- a/src/client/hud.h +++ b/src/client/hud.h @@ -59,6 +59,9 @@ public: Inventory *inventory); ~Hud(); + void toggleBlockBounds(); + void drawBlockBounds(); + void drawHotbar(u16 playeritem); void resizeHotbar(); void drawCrosshair(); @@ -125,6 +128,14 @@ private: scene::SMeshBuffer m_rotation_mesh_buffer; + enum BlockBoundsMode + { + BLOCK_BOUNDS_OFF, + BLOCK_BOUNDS_CURRENT, + BLOCK_BOUNDS_ALL, + BLOCK_BOUNDS_MAX + } m_block_bounds_mode = BLOCK_BOUNDS_OFF; + enum { HIGHLIGHT_BOX, diff --git a/src/client/inputhandler.cpp b/src/client/inputhandler.cpp index b7e70fa6c..980765efa 100644 --- a/src/client/inputhandler.cpp +++ b/src/client/inputhandler.cpp @@ -60,6 +60,7 @@ void KeyCache::populate() key[KeyType::DEC_VOLUME] = getKeySetting("keymap_decrease_volume"); key[KeyType::CINEMATIC] = getKeySetting("keymap_cinematic"); key[KeyType::SCREENSHOT] = getKeySetting("keymap_screenshot"); + key[KeyType::TOGGLE_BLOCK_BOUNDS] = getKeySetting("keymap_toggle_block_bounds"); key[KeyType::TOGGLE_HUD] = getKeySetting("keymap_toggle_hud"); key[KeyType::TOGGLE_CHAT] = getKeySetting("keymap_toggle_chat"); key[KeyType::TOGGLE_FOG] = getKeySetting("keymap_toggle_fog"); diff --git a/src/client/keys.h b/src/client/keys.h index 9f90da6b8..e120a2d92 100644 --- a/src/client/keys.h +++ b/src/client/keys.h @@ -59,6 +59,7 @@ public: DEC_VOLUME, CINEMATIC, SCREENSHOT, + TOGGLE_BLOCK_BOUNDS, TOGGLE_HUD, TOGGLE_CHAT, TOGGLE_FOG, diff --git a/src/client/render/core.cpp b/src/client/render/core.cpp index 92a7137ea..3c4583623 100644 --- a/src/client/render/core.cpp +++ b/src/client/render/core.cpp @@ -76,6 +76,7 @@ void RenderingCore::draw3D() driver->setTransform(video::ETS_WORLD, core::IdentityMatrix); if (!show_hud) return; + hud->drawBlockBounds(); hud->drawSelectionMesh(); if (draw_wield_tool) camera->drawWieldedTool(); diff --git a/src/defaultsettings.cpp b/src/defaultsettings.cpp index 4ecf77c0e..871290944 100644 --- a/src/defaultsettings.cpp +++ b/src/defaultsettings.cpp @@ -97,6 +97,7 @@ void set_default_settings() settings->setDefault("keymap_increase_volume", ""); settings->setDefault("keymap_decrease_volume", ""); settings->setDefault("keymap_cinematic", ""); + settings->setDefault("keymap_toggle_block_bounds", ""); settings->setDefault("keymap_toggle_hud", "KEY_F1"); settings->setDefault("keymap_toggle_chat", "KEY_F2"); settings->setDefault("keymap_toggle_fog", "KEY_F3"); diff --git a/src/gui/guiKeyChangeMenu.cpp b/src/gui/guiKeyChangeMenu.cpp index 84678b629..29d5138f0 100644 --- a/src/gui/guiKeyChangeMenu.cpp +++ b/src/gui/guiKeyChangeMenu.cpp @@ -70,6 +70,7 @@ enum GUI_ID_KEY_MINIMAP_BUTTON, GUI_ID_KEY_SCREENSHOT_BUTTON, GUI_ID_KEY_CHATLOG_BUTTON, + GUI_ID_KEY_BLOCK_BOUNDS_BUTTON, GUI_ID_KEY_HUD_BUTTON, GUI_ID_KEY_FOG_BUTTON, GUI_ID_KEY_DEC_RANGE_BUTTON, @@ -412,37 +413,38 @@ void GUIKeyChangeMenu::add_key(int id, const wchar_t *button_name, const std::st void GUIKeyChangeMenu::init_keys() { - this->add_key(GUI_ID_KEY_FORWARD_BUTTON, wgettext("Forward"), "keymap_forward"); - this->add_key(GUI_ID_KEY_BACKWARD_BUTTON, wgettext("Backward"), "keymap_backward"); - this->add_key(GUI_ID_KEY_LEFT_BUTTON, wgettext("Left"), "keymap_left"); - this->add_key(GUI_ID_KEY_RIGHT_BUTTON, wgettext("Right"), "keymap_right"); - this->add_key(GUI_ID_KEY_AUX1_BUTTON, wgettext("Aux1"), "keymap_aux1"); - this->add_key(GUI_ID_KEY_JUMP_BUTTON, wgettext("Jump"), "keymap_jump"); - this->add_key(GUI_ID_KEY_SNEAK_BUTTON, wgettext("Sneak"), "keymap_sneak"); - this->add_key(GUI_ID_KEY_DROP_BUTTON, wgettext("Drop"), "keymap_drop"); - this->add_key(GUI_ID_KEY_INVENTORY_BUTTON, wgettext("Inventory"), "keymap_inventory"); - this->add_key(GUI_ID_KEY_HOTBAR_PREV_BUTTON,wgettext("Prev. item"), "keymap_hotbar_previous"); - this->add_key(GUI_ID_KEY_HOTBAR_NEXT_BUTTON,wgettext("Next item"), "keymap_hotbar_next"); - this->add_key(GUI_ID_KEY_ZOOM_BUTTON, wgettext("Zoom"), "keymap_zoom"); - this->add_key(GUI_ID_KEY_CAMERA_BUTTON, wgettext("Change camera"), "keymap_camera_mode"); - this->add_key(GUI_ID_KEY_MINIMAP_BUTTON, wgettext("Toggle minimap"), "keymap_minimap"); - this->add_key(GUI_ID_KEY_FLY_BUTTON, wgettext("Toggle fly"), "keymap_freemove"); - this->add_key(GUI_ID_KEY_PITCH_MOVE, wgettext("Toggle pitchmove"), "keymap_pitchmove"); - this->add_key(GUI_ID_KEY_FAST_BUTTON, wgettext("Toggle fast"), "keymap_fastmove"); - this->add_key(GUI_ID_KEY_NOCLIP_BUTTON, wgettext("Toggle noclip"), "keymap_noclip"); - this->add_key(GUI_ID_KEY_MUTE_BUTTON, wgettext("Mute"), "keymap_mute"); - this->add_key(GUI_ID_KEY_DEC_VOLUME_BUTTON,wgettext("Dec. volume"), "keymap_decrease_volume"); - this->add_key(GUI_ID_KEY_INC_VOLUME_BUTTON,wgettext("Inc. volume"), "keymap_increase_volume"); - this->add_key(GUI_ID_KEY_AUTOFWD_BUTTON, wgettext("Autoforward"), "keymap_autoforward"); - this->add_key(GUI_ID_KEY_CHAT_BUTTON, wgettext("Chat"), "keymap_chat"); - this->add_key(GUI_ID_KEY_SCREENSHOT_BUTTON,wgettext("Screenshot"), "keymap_screenshot"); - this->add_key(GUI_ID_KEY_RANGE_BUTTON, wgettext("Range select"), "keymap_rangeselect"); - this->add_key(GUI_ID_KEY_DEC_RANGE_BUTTON, wgettext("Dec. range"), "keymap_decrease_viewing_range_min"); - this->add_key(GUI_ID_KEY_INC_RANGE_BUTTON, wgettext("Inc. range"), "keymap_increase_viewing_range_min"); - this->add_key(GUI_ID_KEY_CONSOLE_BUTTON, wgettext("Console"), "keymap_console"); - this->add_key(GUI_ID_KEY_CMD_BUTTON, wgettext("Command"), "keymap_cmd"); - this->add_key(GUI_ID_KEY_CMD_LOCAL_BUTTON, wgettext("Local command"), "keymap_cmd_local"); - this->add_key(GUI_ID_KEY_HUD_BUTTON, wgettext("Toggle HUD"), "keymap_toggle_hud"); - this->add_key(GUI_ID_KEY_CHATLOG_BUTTON, wgettext("Toggle chat log"), "keymap_toggle_chat"); - this->add_key(GUI_ID_KEY_FOG_BUTTON, wgettext("Toggle fog"), "keymap_toggle_fog"); + this->add_key(GUI_ID_KEY_FORWARD_BUTTON, wgettext("Forward"), "keymap_forward"); + this->add_key(GUI_ID_KEY_BACKWARD_BUTTON, wgettext("Backward"), "keymap_backward"); + this->add_key(GUI_ID_KEY_LEFT_BUTTON, wgettext("Left"), "keymap_left"); + this->add_key(GUI_ID_KEY_RIGHT_BUTTON, wgettext("Right"), "keymap_right"); + this->add_key(GUI_ID_KEY_AUX1_BUTTON, wgettext("Aux1"), "keymap_aux1"); + this->add_key(GUI_ID_KEY_JUMP_BUTTON, wgettext("Jump"), "keymap_jump"); + this->add_key(GUI_ID_KEY_SNEAK_BUTTON, wgettext("Sneak"), "keymap_sneak"); + this->add_key(GUI_ID_KEY_DROP_BUTTON, wgettext("Drop"), "keymap_drop"); + this->add_key(GUI_ID_KEY_INVENTORY_BUTTON, wgettext("Inventory"), "keymap_inventory"); + this->add_key(GUI_ID_KEY_HOTBAR_PREV_BUTTON, wgettext("Prev. item"), "keymap_hotbar_previous"); + this->add_key(GUI_ID_KEY_HOTBAR_NEXT_BUTTON, wgettext("Next item"), "keymap_hotbar_next"); + this->add_key(GUI_ID_KEY_ZOOM_BUTTON, wgettext("Zoom"), "keymap_zoom"); + this->add_key(GUI_ID_KEY_CAMERA_BUTTON, wgettext("Change camera"), "keymap_camera_mode"); + this->add_key(GUI_ID_KEY_MINIMAP_BUTTON, wgettext("Toggle minimap"), "keymap_minimap"); + this->add_key(GUI_ID_KEY_FLY_BUTTON, wgettext("Toggle fly"), "keymap_freemove"); + this->add_key(GUI_ID_KEY_PITCH_MOVE, wgettext("Toggle pitchmove"), "keymap_pitchmove"); + this->add_key(GUI_ID_KEY_FAST_BUTTON, wgettext("Toggle fast"), "keymap_fastmove"); + this->add_key(GUI_ID_KEY_NOCLIP_BUTTON, wgettext("Toggle noclip"), "keymap_noclip"); + this->add_key(GUI_ID_KEY_MUTE_BUTTON, wgettext("Mute"), "keymap_mute"); + this->add_key(GUI_ID_KEY_DEC_VOLUME_BUTTON, wgettext("Dec. volume"), "keymap_decrease_volume"); + this->add_key(GUI_ID_KEY_INC_VOLUME_BUTTON, wgettext("Inc. volume"), "keymap_increase_volume"); + this->add_key(GUI_ID_KEY_AUTOFWD_BUTTON, wgettext("Autoforward"), "keymap_autoforward"); + this->add_key(GUI_ID_KEY_CHAT_BUTTON, wgettext("Chat"), "keymap_chat"); + this->add_key(GUI_ID_KEY_SCREENSHOT_BUTTON, wgettext("Screenshot"), "keymap_screenshot"); + this->add_key(GUI_ID_KEY_RANGE_BUTTON, wgettext("Range select"), "keymap_rangeselect"); + this->add_key(GUI_ID_KEY_DEC_RANGE_BUTTON, wgettext("Dec. range"), "keymap_decrease_viewing_range_min"); + this->add_key(GUI_ID_KEY_INC_RANGE_BUTTON, wgettext("Inc. range"), "keymap_increase_viewing_range_min"); + this->add_key(GUI_ID_KEY_CONSOLE_BUTTON, wgettext("Console"), "keymap_console"); + this->add_key(GUI_ID_KEY_CMD_BUTTON, wgettext("Command"), "keymap_cmd"); + this->add_key(GUI_ID_KEY_CMD_LOCAL_BUTTON, wgettext("Local command"), "keymap_cmd_local"); + this->add_key(GUI_ID_KEY_BLOCK_BOUNDS_BUTTON, wgettext("Block bounds"), "keymap_toggle_block_bounds"); + this->add_key(GUI_ID_KEY_HUD_BUTTON, wgettext("Toggle HUD"), "keymap_toggle_hud"); + this->add_key(GUI_ID_KEY_CHATLOG_BUTTON, wgettext("Toggle chat log"), "keymap_toggle_chat"); + this->add_key(GUI_ID_KEY_FOG_BUTTON, wgettext("Toggle fog"), "keymap_toggle_fog"); } From 90a7bd6a0afb6509e96bcb373f95b448ee7f3b1d Mon Sep 17 00:00:00 2001 From: Wuzzy Date: Tue, 20 Apr 2021 17:50:03 +0000 Subject: [PATCH 42/72] Put torch/signlike node on floor if no paramtype2 (#11074) --- builtin/game/falling.lua | 15 +++++-------- doc/lua_api.txt | 16 ++++++++----- games/devtest/mods/testnodes/drawtypes.lua | 26 ++++++++++++++-------- src/client/wieldmesh.cpp | 10 +++++---- src/mapnode.cpp | 5 ++++- 5 files changed, 44 insertions(+), 28 deletions(-) diff --git a/builtin/game/falling.lua b/builtin/game/falling.lua index 5450542ff..1f0a63993 100644 --- a/builtin/game/falling.lua +++ b/builtin/game/falling.lua @@ -84,9 +84,6 @@ core.register_entity(":__builtin:falling_node", { local textures if def.tiles and def.tiles[1] then local tile = def.tiles[1] - if def.drawtype == "torchlike" and def.paramtype2 ~= "wallmounted" then - tile = def.tiles[2] or def.tiles[1] - end if type(tile) == "table" then tile = tile.name end @@ -147,11 +144,7 @@ core.register_entity(":__builtin:falling_node", { -- Rotate entity if def.drawtype == "torchlike" then - if def.paramtype2 == "wallmounted" then - self.object:set_yaw(math.pi*0.25) - else - self.object:set_yaw(-math.pi*0.25) - end + self.object:set_yaw(math.pi*0.25) elseif ((node.param2 ~= 0 or def.drawtype == "nodebox" or def.drawtype == "mesh") and (def.wield_image == "" or def.wield_image == nil)) or def.drawtype == "signlike" @@ -165,8 +158,12 @@ core.register_entity(":__builtin:falling_node", { if euler then self.object:set_rotation(euler) end - elseif (def.paramtype2 == "wallmounted" or def.paramtype2 == "colorwallmounted") then + elseif (def.paramtype2 == "wallmounted" or def.paramtype2 == "colorwallmounted" or def.drawtype == "signlike") then local rot = node.param2 % 8 + if (def.drawtype == "signlike" and def.paramtype2 ~= "wallmounted" and def.paramtype2 ~= "colorwallmounted") then + -- Change rotation to "floor" by default for non-wallmounted paramtype2 + rot = 1 + end local pitch, yaw, roll = 0, 0, 0 if def.drawtype == "nodebox" or def.drawtype == "mesh" then if rot == 0 then diff --git a/doc/lua_api.txt b/doc/lua_api.txt index 4c963465a..5f72b8b2b 100644 --- a/doc/lua_api.txt +++ b/doc/lua_api.txt @@ -1140,14 +1140,20 @@ Look for examples in `games/devtest` or `games/minetest_game`. used to compensate for how `glasslike` reduces visual thickness. * `torchlike` * A single vertical texture. - * If placed on top of a node, uses the first texture specified in `tiles`. - * If placed against the underside of a node, uses the second texture - specified in `tiles`. - * If placed on the side of a node, uses the third texture specified in - `tiles` and is perpendicular to that node. + * If `paramtype2="[color]wallmounted": + * If placed on top of a node, uses the first texture specified in `tiles`. + * If placed against the underside of a node, uses the second texture + specified in `tiles`. + * If placed on the side of a node, uses the third texture specified in + `tiles` and is perpendicular to that node. + * If `paramtype2="none"`: + * Will be rendered as if placed on top of a node (see + above) and only the first texture is used. * `signlike` * A single texture parallel to, and mounted against, the top, underside or side of a node. + * If `paramtype2="[color]wallmounted", it rotates according to `param2` + * If `paramtype2="none"`, it will always be on the floor. * `plantlike` * Two vertical and diagonal textures at right-angles to each other. * See `paramtype2 = "meshoptions"` above for other options. diff --git a/games/devtest/mods/testnodes/drawtypes.lua b/games/devtest/mods/testnodes/drawtypes.lua index f6d48b06f..881ba75aa 100644 --- a/games/devtest/mods/testnodes/drawtypes.lua +++ b/games/devtest/mods/testnodes/drawtypes.lua @@ -129,14 +129,10 @@ minetest.register_node("testnodes:fencelike", { }) minetest.register_node("testnodes:torchlike", { - description = S("Torchlike Drawtype Test Node"), + description = S("Floor Torchlike Drawtype Test Node"), drawtype = "torchlike", paramtype = "light", - tiles = { - "testnodes_torchlike_floor.png", - "testnodes_torchlike_ceiling.png", - "testnodes_torchlike_wall.png", - }, + tiles = { "testnodes_torchlike_floor.png^[colorize:#FF0000:64" }, walkable = false, @@ -161,9 +157,21 @@ minetest.register_node("testnodes:torchlike_wallmounted", { groups = { dig_immediate = 3 }, }) - - minetest.register_node("testnodes:signlike", { + description = S("Floor Signlike Drawtype Test Node"), + drawtype = "signlike", + paramtype = "light", + tiles = { "testnodes_signlike.png^[colorize:#FF0000:64" }, + + + walkable = false, + groups = { dig_immediate = 3 }, + sunlight_propagates = true, + inventory_image = fallback_image("testnodes_signlike.png"), +}) + + +minetest.register_node("testnodes:signlike_wallmounted", { description = S("Wallmounted Signlike Drawtype Test Node"), drawtype = "signlike", paramtype = "light", @@ -583,7 +591,7 @@ scale("plantlike", scale("torchlike_wallmounted", S("Double-sized Wallmounted Torchlike Drawtype Test Node"), S("Half-sized Wallmounted Torchlike Drawtype Test Node")) -scale("signlike", +scale("signlike_wallmounted", S("Double-sized Wallmounted Signlike Drawtype Test Node"), S("Half-sized Wallmounted Signlike Drawtype Test Node")) scale("firelike", diff --git a/src/client/wieldmesh.cpp b/src/client/wieldmesh.cpp index e76bbfa9e..d9d5e57cd 100644 --- a/src/client/wieldmesh.cpp +++ b/src/client/wieldmesh.cpp @@ -313,12 +313,14 @@ static scene::SMesh *createSpecialNodeMesh(Client *client, MapNode n, // keep it } else if (f.param_type_2 == CPT2_WALLMOUNTED || f.param_type_2 == CPT2_COLORED_WALLMOUNTED) { - if (f.drawtype == NDT_TORCHLIKE) - n.setParam2(1); - else if (f.drawtype == NDT_SIGNLIKE || + if (f.drawtype == NDT_TORCHLIKE || + f.drawtype == NDT_SIGNLIKE || f.drawtype == NDT_NODEBOX || - f.drawtype == NDT_MESH) + f.drawtype == NDT_MESH) { n.setParam2(4); + } + } else if (f.drawtype == NDT_SIGNLIKE || f.drawtype == NDT_TORCHLIKE) { + n.setParam2(1); } gen.renderSingle(n.getContent(), n.getParam2()); diff --git a/src/mapnode.cpp b/src/mapnode.cpp index 20980b238..c885bfe1d 100644 --- a/src/mapnode.cpp +++ b/src/mapnode.cpp @@ -159,8 +159,11 @@ u8 MapNode::getWallMounted(const NodeDefManager *nodemgr) const { const ContentFeatures &f = nodemgr->get(*this); if (f.param_type_2 == CPT2_WALLMOUNTED || - f.param_type_2 == CPT2_COLORED_WALLMOUNTED) + f.param_type_2 == CPT2_COLORED_WALLMOUNTED) { return getParam2() & 0x07; + } else if (f.drawtype == NDT_SIGNLIKE || f.drawtype == NDT_TORCHLIKE) { + return 1; + } return 0; } From 1da73418cd2ea0e03e8289f54a47dededcf8b331 Mon Sep 17 00:00:00 2001 From: sfan5 Date: Tue, 20 Apr 2021 19:50:19 +0200 Subject: [PATCH 43/72] Enable cleanTransparent filter for mipmapping and improve its' algorithm (#11145) --- builtin/settingtypes.txt | 11 ++-- src/client/guiscalingfilter.cpp | 2 +- src/client/imagefilters.cpp | 107 ++++++++++++++++++++++++++------ src/client/imagefilters.h | 6 +- src/client/minimap.cpp | 3 +- src/client/tile.cpp | 8 ++- 6 files changed, 105 insertions(+), 32 deletions(-) diff --git a/builtin/settingtypes.txt b/builtin/settingtypes.txt index f7412c1ee..00d1b87d7 100644 --- a/builtin/settingtypes.txt +++ b/builtin/settingtypes.txt @@ -504,18 +504,17 @@ bilinear_filter (Bilinear filtering) bool false trilinear_filter (Trilinear filtering) bool false # Filtered textures can blend RGB values with fully-transparent neighbors, -# which PNG optimizers usually discard, sometimes resulting in a dark or -# light edge to transparent textures. Apply this filter to clean that up -# at texture load time. +# which PNG optimizers usually discard, often resulting in dark or +# light edges to transparent textures. Apply a filter to clean that up +# at texture load time. This is automatically enabled if mipmapping is enabled. texture_clean_transparent (Clean transparent textures) bool false # When using bilinear/trilinear/anisotropic filters, low-resolution textures # can be blurred, so automatically upscale them with nearest-neighbor # interpolation to preserve crisp pixels. This sets the minimum texture size # for the upscaled textures; higher values look sharper, but require more -# memory. Powers of 2 are recommended. Setting this higher than 1 may not -# have a visible effect unless bilinear/trilinear/anisotropic filtering is -# enabled. +# memory. Powers of 2 are recommended. This setting is ONLY applies if +# bilinear/trilinear/anisotropic filtering is enabled. # This is also used as the base node texture size for world-aligned # texture autoscaling. texture_min_size (Minimum texture size) int 64 diff --git a/src/client/guiscalingfilter.cpp b/src/client/guiscalingfilter.cpp index 8c565a52f..cf371d8ba 100644 --- a/src/client/guiscalingfilter.cpp +++ b/src/client/guiscalingfilter.cpp @@ -102,7 +102,7 @@ video::ITexture *guiScalingResizeCached(video::IVideoDriver *driver, if (!g_settings->getBool("gui_scaling_filter_txr2img")) return src; srcimg = driver->createImageFromData(src->getColorFormat(), - src->getSize(), src->lock(), false); + src->getSize(), src->lock(video::ETLM_READ_ONLY), false); src->unlock(); g_imgCache[origname] = srcimg; } diff --git a/src/client/imagefilters.cpp b/src/client/imagefilters.cpp index 0fa501410..7b2ef9822 100644 --- a/src/client/imagefilters.cpp +++ b/src/client/imagefilters.cpp @@ -19,63 +19,134 @@ with this program; if not, write to the Free Software Foundation, Inc., #include "imagefilters.h" #include "util/numeric.h" #include +#include +#include + +// Simple 2D bitmap class with just the functionality needed here +class Bitmap { + u32 linesize, lines; + std::vector data; + + static inline u32 bytepos(u32 index) { return index >> 3; } + static inline u8 bitpos(u32 index) { return index & 7; } + +public: + Bitmap(u32 width, u32 height) : linesize(width), lines(height), + data(bytepos(width * height) + 1) {} + + inline bool get(u32 x, u32 y) const { + u32 index = y * linesize + x; + return data[bytepos(index)] & (1 << bitpos(index)); + } + + inline void set(u32 x, u32 y) { + u32 index = y * linesize + x; + data[bytepos(index)] |= 1 << bitpos(index); + } + + inline bool all() const { + for (u32 i = 0; i < data.size() - 1; i++) { + if (data[i] != 0xff) + return false; + } + // last byte not entirely filled + for (u8 i = 0; i < bitpos(linesize * lines); i++) { + bool value_of_bit = data.back() & (1 << i); + if (!value_of_bit) + return false; + } + return true; + } + + inline void copy(Bitmap &to) const { + assert(to.linesize == linesize && to.lines == lines); + to.data = data; + } +}; /* Fill in RGB values for transparent pixels, to correct for odd colors * appearing at borders when blending. This is because many PNG optimizers * like to discard RGB values of transparent pixels, but when blending then - * with non-transparent neighbors, their RGB values will shpw up nonetheless. + * with non-transparent neighbors, their RGB values will show up nonetheless. * * This function modifies the original image in-place. * * Parameter "threshold" is the alpha level below which pixels are considered - * transparent. Should be 127 for 3d where alpha is threshold, but 0 for - * 2d where alpha is blended. + * transparent. Should be 127 when the texture is used with ALPHA_CHANNEL_REF, + * 0 when alpha blending is used. */ void imageCleanTransparent(video::IImage *src, u32 threshold) { core::dimension2d dim = src->getDimension(); - // Walk each pixel looking for fully transparent ones. + Bitmap bitmap(dim.Width, dim.Height); + + // First pass: Mark all opaque pixels // Note: loop y around x for better cache locality. for (u32 ctry = 0; ctry < dim.Height; ctry++) for (u32 ctrx = 0; ctrx < dim.Width; ctrx++) { + if (src->getPixel(ctrx, ctry).getAlpha() > threshold) + bitmap.set(ctrx, ctry); + } - // Ignore opaque pixels. - irr::video::SColor c = src->getPixel(ctrx, ctry); - if (c.getAlpha() > threshold) + // Exit early if all pixels opaque + if (bitmap.all()) + return; + + Bitmap newmap = bitmap; + + // Then repeatedly look for transparent pixels, filling them in until + // we're finished (capped at 50 iterations). + for (u32 iter = 0; iter < 50; iter++) { + + for (u32 ctry = 0; ctry < dim.Height; ctry++) + for (u32 ctrx = 0; ctrx < dim.Width; ctrx++) { + // Skip pixels we have already processed + if (bitmap.get(ctrx, ctry)) continue; - // Sample size and total weighted r, g, b values. + video::SColor c = src->getPixel(ctrx, ctry); + + // Sample size and total weighted r, g, b values u32 ss = 0, sr = 0, sg = 0, sb = 0; - // Walk each neighbor pixel (clipped to image bounds). + // Walk each neighbor pixel (clipped to image bounds) for (u32 sy = (ctry < 1) ? 0 : (ctry - 1); sy <= (ctry + 1) && sy < dim.Height; sy++) for (u32 sx = (ctrx < 1) ? 0 : (ctrx - 1); sx <= (ctrx + 1) && sx < dim.Width; sx++) { - - // Ignore transparent pixels. - irr::video::SColor d = src->getPixel(sx, sy); - if (d.getAlpha() <= threshold) + // Ignore pixels we haven't processed + if (!bitmap.get(sx, sy)) continue; - - // Add RGB values weighted by alpha. - u32 a = d.getAlpha(); + + // Add RGB values weighted by alpha IF the pixel is opaque, otherwise + // use full weight since we want to propagate colors. + video::SColor d = src->getPixel(sx, sy); + u32 a = d.getAlpha() <= threshold ? 255 : d.getAlpha(); ss += a; sr += a * d.getRed(); sg += a * d.getGreen(); sb += a * d.getBlue(); } - // If we found any neighbor RGB data, set pixel to average - // weighted by alpha. + // Set pixel to average weighted by alpha if (ss > 0) { c.setRed(sr / ss); c.setGreen(sg / ss); c.setBlue(sb / ss); src->setPixel(ctrx, ctry, c); + newmap.set(ctrx, ctry); } } + + if (newmap.all()) + return; + + // Apply changes to bitmap for next run. This is done so we don't introduce + // a bias in color propagation in the direction pixels are processed. + newmap.copy(bitmap); + + } } /* Scale a region of an image into another image, using nearest-neighbor with diff --git a/src/client/imagefilters.h b/src/client/imagefilters.h index 5676faf85..c9bdefbb6 100644 --- a/src/client/imagefilters.h +++ b/src/client/imagefilters.h @@ -23,13 +23,13 @@ with this program; if not, write to the Free Software Foundation, Inc., /* Fill in RGB values for transparent pixels, to correct for odd colors * appearing at borders when blending. This is because many PNG optimizers * like to discard RGB values of transparent pixels, but when blending then - * with non-transparent neighbors, their RGB values will shpw up nonetheless. + * with non-transparent neighbors, their RGB values will show up nonetheless. * * This function modifies the original image in-place. * * Parameter "threshold" is the alpha level below which pixels are considered - * transparent. Should be 127 for 3d where alpha is threshold, but 0 for - * 2d where alpha is blended. + * transparent. Should be 127 when the texture is used with ALPHA_CHANNEL_REF, + * 0 when alpha blending is used. */ void imageCleanTransparent(video::IImage *src, u32 threshold); diff --git a/src/client/minimap.cpp b/src/client/minimap.cpp index dd810ee0a..97977c366 100644 --- a/src/client/minimap.cpp +++ b/src/client/minimap.cpp @@ -491,7 +491,8 @@ video::ITexture *Minimap::getMinimapTexture() // Want to use texture source, to : 1 find texture, 2 cache it video::ITexture* texture = m_tsrc->getTexture(data->mode.texture); video::IImage* image = driver->createImageFromData( - texture->getColorFormat(), texture->getSize(), texture->lock(), true, false); + texture->getColorFormat(), texture->getSize(), + texture->lock(video::ETLM_READ_ONLY), true, false); texture->unlock(); auto dim = image->getDimension(); diff --git a/src/client/tile.cpp b/src/client/tile.cpp index 7e3901247..d9f8c75a7 100644 --- a/src/client/tile.cpp +++ b/src/client/tile.cpp @@ -427,6 +427,7 @@ private: std::unordered_map m_palettes; // Cached settings needed for making textures from meshes + bool m_setting_mipmap; bool m_setting_trilinear_filter; bool m_setting_bilinear_filter; }; @@ -447,6 +448,7 @@ TextureSource::TextureSource() // Cache some settings // Note: Since this is only done once, the game must be restarted // for these settings to take effect + m_setting_mipmap = g_settings->getBool("mip_map"); m_setting_trilinear_filter = g_settings->getBool("trilinear_filter"); m_setting_bilinear_filter = g_settings->getBool("bilinear_filter"); } @@ -667,7 +669,7 @@ video::ITexture* TextureSource::getTexture(const std::string &name, u32 *id) video::ITexture* TextureSource::getTextureForMesh(const std::string &name, u32 *id) { static thread_local bool filter_needed = - g_settings->getBool("texture_clean_transparent") || + g_settings->getBool("texture_clean_transparent") || m_setting_mipmap || ((m_setting_trilinear_filter || m_setting_bilinear_filter) && g_settings->getS32("texture_min_size") > 1); // Avoid duplicating texture if it won't actually change @@ -1636,8 +1638,8 @@ bool TextureSource::generateImagePart(std::string part_of_name, return false; } - // Apply the "clean transparent" filter, if configured. - if (g_settings->getBool("texture_clean_transparent")) + // Apply the "clean transparent" filter, if needed + if (m_setting_mipmap || g_settings->getBool("texture_clean_transparent")) imageCleanTransparent(baseimg, 127); /* Upscale textures to user's requested minimum size. This is a trick to make From a24899bf2dcd58916922d671ee8761448b6876e5 Mon Sep 17 00:00:00 2001 From: sfan5 Date: Tue, 20 Apr 2021 19:50:34 +0200 Subject: [PATCH 44/72] Look for PostgreSQL library properly and fix CI --- README.md | 2 +- src/CMakeLists.txt | 11 ++++++++++- util/ci/common.sh | 3 +-- 3 files changed, 12 insertions(+), 4 deletions(-) diff --git a/README.md b/README.md index 662b5c4ca..0b9907992 100644 --- a/README.md +++ b/README.md @@ -133,7 +133,7 @@ Compiling | Dependency | Version | Commentary | |------------|---------|------------| | GCC | 4.9+ | Can be replaced with Clang 3.4+ | -| CMake | 2.6+ | | +| CMake | 3.5+ | | | Irrlicht | - | Custom version required, see https://github.com/minetest/irrlicht | | SQLite3 | 3.0+ | | | LuaJIT | 2.0+ | Bundled Lua 5.1 is used if not present | diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt index 16b5bf991..f70e77dcc 100644 --- a/src/CMakeLists.txt +++ b/src/CMakeLists.txt @@ -146,7 +146,16 @@ option(ENABLE_POSTGRESQL "Enable PostgreSQL backend" TRUE) set(USE_POSTGRESQL FALSE) if(ENABLE_POSTGRESQL) - find_package("PostgreSQL") + if(CMAKE_VERSION VERSION_LESS "3.20") + find_package(PostgreSQL QUIET) + # Before CMake 3.20 FindPostgreSQL.cmake always looked for server includes + # but we don't need them, so continue anyway if only those are missing. + if(PostgreSQL_INCLUDE_DIR AND PostgreSQL_LIBRARY) + set(PostgreSQL_FOUND TRUE) + endif() + else() + find_package(PostgreSQL) + endif() if(PostgreSQL_FOUND) set(USE_POSTGRESQL TRUE) diff --git a/util/ci/common.sh b/util/ci/common.sh index ca2ecbc29..1083581b5 100644 --- a/util/ci/common.sh +++ b/util/ci/common.sh @@ -5,8 +5,7 @@ install_linux_deps() { local pkgs=(cmake libpng-dev \ libjpeg-dev libxxf86vm-dev libgl1-mesa-dev libsqlite3-dev \ libhiredis-dev libogg-dev libgmp-dev libvorbis-dev libopenal-dev \ - gettext libpq-dev postgresql-server-dev-all libleveldb-dev \ - libcurl4-openssl-dev) + gettext libpq-dev libleveldb-dev libcurl4-openssl-dev) if [[ "$1" == "--old-irr" ]]; then shift From daf862a38a0df84a7e4cd387e41c55ae4467f4d2 Mon Sep 17 00:00:00 2001 From: sfan5 Date: Wed, 21 Apr 2021 16:42:34 +0200 Subject: [PATCH 45/72] Fix devtest Lua error fallback_image() was removed in 3e1904fa8c4aae3448d58b7e60545a4fdd8234f3, which was written after this PR but merged before it. --- games/devtest/mods/testnodes/drawtypes.lua | 1 - 1 file changed, 1 deletion(-) diff --git a/games/devtest/mods/testnodes/drawtypes.lua b/games/devtest/mods/testnodes/drawtypes.lua index 881ba75aa..3bf631714 100644 --- a/games/devtest/mods/testnodes/drawtypes.lua +++ b/games/devtest/mods/testnodes/drawtypes.lua @@ -167,7 +167,6 @@ minetest.register_node("testnodes:signlike", { walkable = false, groups = { dig_immediate = 3 }, sunlight_propagates = true, - inventory_image = fallback_image("testnodes_signlike.png"), }) From 3e2145d662d26443e96ac7191eda093c85c6f2bc Mon Sep 17 00:00:00 2001 From: sfan5 Date: Wed, 21 Apr 2021 20:25:18 +0200 Subject: [PATCH 46/72] Fix two CMake build issues * PostgreSQL fallback code missed the includes (closes #11219) * build failed when Freetype enabled but not found --- src/CMakeLists.txt | 1 + src/irrlicht_changes/CMakeLists.txt | 2 +- 2 files changed, 2 insertions(+), 1 deletion(-) diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt index f70e77dcc..5298a8f0d 100644 --- a/src/CMakeLists.txt +++ b/src/CMakeLists.txt @@ -152,6 +152,7 @@ if(ENABLE_POSTGRESQL) # but we don't need them, so continue anyway if only those are missing. if(PostgreSQL_INCLUDE_DIR AND PostgreSQL_LIBRARY) set(PostgreSQL_FOUND TRUE) + set(PostgreSQL_INCLUDE_DIRS ${PostgreSQL_INCLUDE_DIR}) endif() else() find_package(PostgreSQL) diff --git a/src/irrlicht_changes/CMakeLists.txt b/src/irrlicht_changes/CMakeLists.txt index d2f66ab77..87c88f7e8 100644 --- a/src/irrlicht_changes/CMakeLists.txt +++ b/src/irrlicht_changes/CMakeLists.txt @@ -3,7 +3,7 @@ if (BUILD_CLIENT) ${CMAKE_CURRENT_SOURCE_DIR}/static_text.cpp ) - if (ENABLE_FREETYPE) + if (USE_FREETYPE) set(client_irrlicht_changes_SRCS ${client_irrlicht_changes_SRCS} ${CMAKE_CURRENT_SOURCE_DIR}/CGUITTFont.cpp ) From 074e6a67def42ab9c91b8638c914869d516a9cd7 Mon Sep 17 00:00:00 2001 From: Vincent Robinson Date: Fri, 23 Apr 2021 12:37:24 -0700 Subject: [PATCH 47/72] Add `minetest.colorspec_to_colorstring` (#10425) --- doc/client_lua_api.txt | 8 +- doc/lua_api.txt | 8 +- src/script/lua_api/l_util.cpp | 24 +- src/script/lua_api/l_util.h | 3 + src/util/string.cpp | 413 ++++++++++++++++------------------ 5 files changed, 232 insertions(+), 224 deletions(-) diff --git a/doc/client_lua_api.txt b/doc/client_lua_api.txt index c2c552440..1e8015f7b 100644 --- a/doc/client_lua_api.txt +++ b/doc/client_lua_api.txt @@ -651,6 +651,9 @@ Minetest namespace reference * `minetest.sha1(data, [raw])`: returns the sha1 hash of data * `data`: string of data to hash * `raw`: return raw bytes instead of hex digits, default: false +* `minetest.colorspec_to_colorstring(colorspec)`: Converts a ColorSpec to a + ColorString. If the ColorSpec is invalid, returns `nil`. + * `colorspec`: The ColorSpec to convert * `minetest.get_csm_restrictions()`: returns a table of `Flags` indicating the restrictions applied to the current mod. * If a flag in this table is set to true, the feature is RESTRICTED. @@ -1348,9 +1351,8 @@ The following functions provide escape sequences: Named colors are also supported and are equivalent to [CSS Color Module Level 4](http://dev.w3.org/csswg/css-color/#named-colors). -To specify the value of the alpha channel, append `#AA` to the end of the color name -(e.g. `colorname#08`). For named colors the hexadecimal string representing the alpha -value must (always) be two hexadecimal digits. +To specify the value of the alpha channel, append `#A` or `#AA` to the end of +the color name (e.g. `colorname#08`). `Color` ------------- diff --git a/doc/lua_api.txt b/doc/lua_api.txt index 5f72b8b2b..75cd6b7cc 100644 --- a/doc/lua_api.txt +++ b/doc/lua_api.txt @@ -3100,9 +3100,8 @@ Colors Named colors are also supported and are equivalent to [CSS Color Module Level 4](http://dev.w3.org/csswg/css-color/#named-colors). -To specify the value of the alpha channel, append `#AA` to the end of the color -name (e.g. `colorname#08`). For named colors the hexadecimal string -representing the alpha value must (always) be two hexadecimal digits. +To specify the value of the alpha channel, append `#A` or `#AA` to the end of +the color name (e.g. `colorname#08`). `ColorSpec` ----------- @@ -4489,6 +4488,9 @@ Utilities * `minetest.sha1(data, [raw])`: returns the sha1 hash of data * `data`: string of data to hash * `raw`: return raw bytes instead of hex digits, default: false +* `minetest.colorspec_to_colorstring(colorspec)`: Converts a ColorSpec to a + ColorString. If the ColorSpec is invalid, returns `nil`. + * `colorspec`: The ColorSpec to convert Logging ------- diff --git a/src/script/lua_api/l_util.cpp b/src/script/lua_api/l_util.cpp index 203a0dd28..8de2d67c8 100644 --- a/src/script/lua_api/l_util.cpp +++ b/src/script/lua_api/l_util.cpp @@ -17,6 +17,7 @@ with this program; if not, write to the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. */ +#include "irrlichttypes_extrabloated.h" #include "lua_api/l_util.h" #include "lua_api/l_internal.h" #include "lua_api/l_settings.h" @@ -40,7 +41,7 @@ with this program; if not, write to the Free Software Foundation, Inc., #include "util/hex.h" #include "util/sha1.h" #include - +#include // log([level,] text) // Writes a line to the logger. @@ -479,6 +480,23 @@ int ModApiUtil::l_sha1(lua_State *L) return 1; } +// colorspec_to_colorstring(colorspec) +int ModApiUtil::l_colorspec_to_colorstring(lua_State *L) +{ + NO_MAP_LOCK_REQUIRED; + + video::SColor color(0); + if (read_color(L, 1, &color)) { + char colorstring[10]; + snprintf(colorstring, 10, "#%02X%02X%02X%02X", + color.getRed(), color.getGreen(), color.getBlue(), color.getAlpha()); + lua_pushstring(L, colorstring); + return 1; + } + + return 0; +} + void ModApiUtil::Initialize(lua_State *L, int top) { API_FCT(log); @@ -513,6 +531,7 @@ void ModApiUtil::Initialize(lua_State *L, int top) API_FCT(get_version); API_FCT(sha1); + API_FCT(colorspec_to_colorstring); LuaSettings::create(L, g_settings, g_settings_path); lua_setfield(L, top, "settings"); @@ -537,6 +556,7 @@ void ModApiUtil::InitializeClient(lua_State *L, int top) API_FCT(get_version); API_FCT(sha1); + API_FCT(colorspec_to_colorstring); } void ModApiUtil::InitializeAsync(lua_State *L, int top) @@ -564,8 +584,8 @@ void ModApiUtil::InitializeAsync(lua_State *L, int top) API_FCT(get_version); API_FCT(sha1); + API_FCT(colorspec_to_colorstring); LuaSettings::create(L, g_settings, g_settings_path); lua_setfield(L, top, "settings"); } - diff --git a/src/script/lua_api/l_util.h b/src/script/lua_api/l_util.h index dbdd62b99..6943a6afb 100644 --- a/src/script/lua_api/l_util.h +++ b/src/script/lua_api/l_util.h @@ -101,6 +101,9 @@ private: // sha1(string, raw) static int l_sha1(lua_State *L); + // colorspec_to_colorstring(colorspec) + static int l_colorspec_to_colorstring(lua_State *L); + public: static void Initialize(lua_State *L, int top); static void InitializeAsync(lua_State *L, int top); diff --git a/src/util/string.cpp b/src/util/string.cpp index 611ad35cb..eec5ab4cd 100644 --- a/src/util/string.cpp +++ b/src/util/string.cpp @@ -30,7 +30,7 @@ with this program; if not, write to the Free Software Foundation, Inc., #include #include #include -#include +#include #ifndef _WIN32 #include @@ -44,10 +44,6 @@ with this program; if not, write to the Free Software Foundation, Inc., #define BSD_ICONV_USED #endif -static bool parseHexColorString(const std::string &value, video::SColor &color, - unsigned char default_alpha = 0xff); -static bool parseNamedColorString(const std::string &value, video::SColor &color); - #ifndef _WIN32 static bool convert(const char *to, const char *from, char *outbuf, @@ -324,29 +320,10 @@ u64 read_seed(const char *str) return num; } -bool parseColorString(const std::string &value, video::SColor &color, bool quiet, - unsigned char default_alpha) -{ - bool success; - - if (value[0] == '#') - success = parseHexColorString(value, color, default_alpha); - else - success = parseNamedColorString(value, color); - - if (!success && !quiet) - errorstream << "Invalid color: \"" << value << "\"" << std::endl; - - return success; -} - static bool parseHexColorString(const std::string &value, video::SColor &color, unsigned char default_alpha) { - unsigned char components[] = { 0x00, 0x00, 0x00, default_alpha }; // R,G,B,A - - if (value[0] != '#') - return false; + u8 components[] = {0x00, 0x00, 0x00, default_alpha}; // R,G,B,A size_t len = value.size(); bool short_form; @@ -358,198 +335,182 @@ static bool parseHexColorString(const std::string &value, video::SColor &color, else return false; - bool success = true; - for (size_t pos = 1, cc = 0; pos < len; pos++, cc++) { - assert(cc < sizeof components / sizeof components[0]); if (short_form) { - unsigned char d; - if (!hex_digit_decode(value[pos], d)) { - success = false; - break; - } + u8 d; + if (!hex_digit_decode(value[pos], d)) + return false; + components[cc] = (d & 0xf) << 4 | (d & 0xf); } else { - unsigned char d1, d2; + u8 d1, d2; if (!hex_digit_decode(value[pos], d1) || - !hex_digit_decode(value[pos+1], d2)) { - success = false; - break; - } + !hex_digit_decode(value[pos+1], d2)) + return false; + components[cc] = (d1 & 0xf) << 4 | (d2 & 0xf); - pos++; // skip the second digit -- it's already used + pos++; // skip the second digit -- it's already used } } - if (success) { - color.setRed(components[0]); - color.setGreen(components[1]); - color.setBlue(components[2]); - color.setAlpha(components[3]); - } + color.setRed(components[0]); + color.setGreen(components[1]); + color.setBlue(components[2]); + color.setAlpha(components[3]); - return success; + return true; } -struct ColorContainer { - ColorContainer(); - std::map colors; +const static std::unordered_map s_named_colors = { + {"aliceblue", 0xf0f8ff}, + {"antiquewhite", 0xfaebd7}, + {"aqua", 0x00ffff}, + {"aquamarine", 0x7fffd4}, + {"azure", 0xf0ffff}, + {"beige", 0xf5f5dc}, + {"bisque", 0xffe4c4}, + {"black", 00000000}, + {"blanchedalmond", 0xffebcd}, + {"blue", 0x0000ff}, + {"blueviolet", 0x8a2be2}, + {"brown", 0xa52a2a}, + {"burlywood", 0xdeb887}, + {"cadetblue", 0x5f9ea0}, + {"chartreuse", 0x7fff00}, + {"chocolate", 0xd2691e}, + {"coral", 0xff7f50}, + {"cornflowerblue", 0x6495ed}, + {"cornsilk", 0xfff8dc}, + {"crimson", 0xdc143c}, + {"cyan", 0x00ffff}, + {"darkblue", 0x00008b}, + {"darkcyan", 0x008b8b}, + {"darkgoldenrod", 0xb8860b}, + {"darkgray", 0xa9a9a9}, + {"darkgreen", 0x006400}, + {"darkgrey", 0xa9a9a9}, + {"darkkhaki", 0xbdb76b}, + {"darkmagenta", 0x8b008b}, + {"darkolivegreen", 0x556b2f}, + {"darkorange", 0xff8c00}, + {"darkorchid", 0x9932cc}, + {"darkred", 0x8b0000}, + {"darksalmon", 0xe9967a}, + {"darkseagreen", 0x8fbc8f}, + {"darkslateblue", 0x483d8b}, + {"darkslategray", 0x2f4f4f}, + {"darkslategrey", 0x2f4f4f}, + {"darkturquoise", 0x00ced1}, + {"darkviolet", 0x9400d3}, + {"deeppink", 0xff1493}, + {"deepskyblue", 0x00bfff}, + {"dimgray", 0x696969}, + {"dimgrey", 0x696969}, + {"dodgerblue", 0x1e90ff}, + {"firebrick", 0xb22222}, + {"floralwhite", 0xfffaf0}, + {"forestgreen", 0x228b22}, + {"fuchsia", 0xff00ff}, + {"gainsboro", 0xdcdcdc}, + {"ghostwhite", 0xf8f8ff}, + {"gold", 0xffd700}, + {"goldenrod", 0xdaa520}, + {"gray", 0x808080}, + {"green", 0x008000}, + {"greenyellow", 0xadff2f}, + {"grey", 0x808080}, + {"honeydew", 0xf0fff0}, + {"hotpink", 0xff69b4}, + {"indianred", 0xcd5c5c}, + {"indigo", 0x4b0082}, + {"ivory", 0xfffff0}, + {"khaki", 0xf0e68c}, + {"lavender", 0xe6e6fa}, + {"lavenderblush", 0xfff0f5}, + {"lawngreen", 0x7cfc00}, + {"lemonchiffon", 0xfffacd}, + {"lightblue", 0xadd8e6}, + {"lightcoral", 0xf08080}, + {"lightcyan", 0xe0ffff}, + {"lightgoldenrodyellow", 0xfafad2}, + {"lightgray", 0xd3d3d3}, + {"lightgreen", 0x90ee90}, + {"lightgrey", 0xd3d3d3}, + {"lightpink", 0xffb6c1}, + {"lightsalmon", 0xffa07a}, + {"lightseagreen", 0x20b2aa}, + {"lightskyblue", 0x87cefa}, + {"lightslategray", 0x778899}, + {"lightslategrey", 0x778899}, + {"lightsteelblue", 0xb0c4de}, + {"lightyellow", 0xffffe0}, + {"lime", 0x00ff00}, + {"limegreen", 0x32cd32}, + {"linen", 0xfaf0e6}, + {"magenta", 0xff00ff}, + {"maroon", 0x800000}, + {"mediumaquamarine", 0x66cdaa}, + {"mediumblue", 0x0000cd}, + {"mediumorchid", 0xba55d3}, + {"mediumpurple", 0x9370db}, + {"mediumseagreen", 0x3cb371}, + {"mediumslateblue", 0x7b68ee}, + {"mediumspringgreen", 0x00fa9a}, + {"mediumturquoise", 0x48d1cc}, + {"mediumvioletred", 0xc71585}, + {"midnightblue", 0x191970}, + {"mintcream", 0xf5fffa}, + {"mistyrose", 0xffe4e1}, + {"moccasin", 0xffe4b5}, + {"navajowhite", 0xffdead}, + {"navy", 0x000080}, + {"oldlace", 0xfdf5e6}, + {"olive", 0x808000}, + {"olivedrab", 0x6b8e23}, + {"orange", 0xffa500}, + {"orangered", 0xff4500}, + {"orchid", 0xda70d6}, + {"palegoldenrod", 0xeee8aa}, + {"palegreen", 0x98fb98}, + {"paleturquoise", 0xafeeee}, + {"palevioletred", 0xdb7093}, + {"papayawhip", 0xffefd5}, + {"peachpuff", 0xffdab9}, + {"peru", 0xcd853f}, + {"pink", 0xffc0cb}, + {"plum", 0xdda0dd}, + {"powderblue", 0xb0e0e6}, + {"purple", 0x800080}, + {"red", 0xff0000}, + {"rosybrown", 0xbc8f8f}, + {"royalblue", 0x4169e1}, + {"saddlebrown", 0x8b4513}, + {"salmon", 0xfa8072}, + {"sandybrown", 0xf4a460}, + {"seagreen", 0x2e8b57}, + {"seashell", 0xfff5ee}, + {"sienna", 0xa0522d}, + {"silver", 0xc0c0c0}, + {"skyblue", 0x87ceeb}, + {"slateblue", 0x6a5acd}, + {"slategray", 0x708090}, + {"slategrey", 0x708090}, + {"snow", 0xfffafa}, + {"springgreen", 0x00ff7f}, + {"steelblue", 0x4682b4}, + {"tan", 0xd2b48c}, + {"teal", 0x008080}, + {"thistle", 0xd8bfd8}, + {"tomato", 0xff6347}, + {"turquoise", 0x40e0d0}, + {"violet", 0xee82ee}, + {"wheat", 0xf5deb3}, + {"white", 0xffffff}, + {"whitesmoke", 0xf5f5f5}, + {"yellow", 0xffff00}, + {"yellowgreen", 0x9acd32} }; -ColorContainer::ColorContainer() -{ - colors["aliceblue"] = 0xf0f8ff; - colors["antiquewhite"] = 0xfaebd7; - colors["aqua"] = 0x00ffff; - colors["aquamarine"] = 0x7fffd4; - colors["azure"] = 0xf0ffff; - colors["beige"] = 0xf5f5dc; - colors["bisque"] = 0xffe4c4; - colors["black"] = 00000000; - colors["blanchedalmond"] = 0xffebcd; - colors["blue"] = 0x0000ff; - colors["blueviolet"] = 0x8a2be2; - colors["brown"] = 0xa52a2a; - colors["burlywood"] = 0xdeb887; - colors["cadetblue"] = 0x5f9ea0; - colors["chartreuse"] = 0x7fff00; - colors["chocolate"] = 0xd2691e; - colors["coral"] = 0xff7f50; - colors["cornflowerblue"] = 0x6495ed; - colors["cornsilk"] = 0xfff8dc; - colors["crimson"] = 0xdc143c; - colors["cyan"] = 0x00ffff; - colors["darkblue"] = 0x00008b; - colors["darkcyan"] = 0x008b8b; - colors["darkgoldenrod"] = 0xb8860b; - colors["darkgray"] = 0xa9a9a9; - colors["darkgreen"] = 0x006400; - colors["darkgrey"] = 0xa9a9a9; - colors["darkkhaki"] = 0xbdb76b; - colors["darkmagenta"] = 0x8b008b; - colors["darkolivegreen"] = 0x556b2f; - colors["darkorange"] = 0xff8c00; - colors["darkorchid"] = 0x9932cc; - colors["darkred"] = 0x8b0000; - colors["darksalmon"] = 0xe9967a; - colors["darkseagreen"] = 0x8fbc8f; - colors["darkslateblue"] = 0x483d8b; - colors["darkslategray"] = 0x2f4f4f; - colors["darkslategrey"] = 0x2f4f4f; - colors["darkturquoise"] = 0x00ced1; - colors["darkviolet"] = 0x9400d3; - colors["deeppink"] = 0xff1493; - colors["deepskyblue"] = 0x00bfff; - colors["dimgray"] = 0x696969; - colors["dimgrey"] = 0x696969; - colors["dodgerblue"] = 0x1e90ff; - colors["firebrick"] = 0xb22222; - colors["floralwhite"] = 0xfffaf0; - colors["forestgreen"] = 0x228b22; - colors["fuchsia"] = 0xff00ff; - colors["gainsboro"] = 0xdcdcdc; - colors["ghostwhite"] = 0xf8f8ff; - colors["gold"] = 0xffd700; - colors["goldenrod"] = 0xdaa520; - colors["gray"] = 0x808080; - colors["green"] = 0x008000; - colors["greenyellow"] = 0xadff2f; - colors["grey"] = 0x808080; - colors["honeydew"] = 0xf0fff0; - colors["hotpink"] = 0xff69b4; - colors["indianred"] = 0xcd5c5c; - colors["indigo"] = 0x4b0082; - colors["ivory"] = 0xfffff0; - colors["khaki"] = 0xf0e68c; - colors["lavender"] = 0xe6e6fa; - colors["lavenderblush"] = 0xfff0f5; - colors["lawngreen"] = 0x7cfc00; - colors["lemonchiffon"] = 0xfffacd; - colors["lightblue"] = 0xadd8e6; - colors["lightcoral"] = 0xf08080; - colors["lightcyan"] = 0xe0ffff; - colors["lightgoldenrodyellow"] = 0xfafad2; - colors["lightgray"] = 0xd3d3d3; - colors["lightgreen"] = 0x90ee90; - colors["lightgrey"] = 0xd3d3d3; - colors["lightpink"] = 0xffb6c1; - colors["lightsalmon"] = 0xffa07a; - colors["lightseagreen"] = 0x20b2aa; - colors["lightskyblue"] = 0x87cefa; - colors["lightslategray"] = 0x778899; - colors["lightslategrey"] = 0x778899; - colors["lightsteelblue"] = 0xb0c4de; - colors["lightyellow"] = 0xffffe0; - colors["lime"] = 0x00ff00; - colors["limegreen"] = 0x32cd32; - colors["linen"] = 0xfaf0e6; - colors["magenta"] = 0xff00ff; - colors["maroon"] = 0x800000; - colors["mediumaquamarine"] = 0x66cdaa; - colors["mediumblue"] = 0x0000cd; - colors["mediumorchid"] = 0xba55d3; - colors["mediumpurple"] = 0x9370db; - colors["mediumseagreen"] = 0x3cb371; - colors["mediumslateblue"] = 0x7b68ee; - colors["mediumspringgreen"] = 0x00fa9a; - colors["mediumturquoise"] = 0x48d1cc; - colors["mediumvioletred"] = 0xc71585; - colors["midnightblue"] = 0x191970; - colors["mintcream"] = 0xf5fffa; - colors["mistyrose"] = 0xffe4e1; - colors["moccasin"] = 0xffe4b5; - colors["navajowhite"] = 0xffdead; - colors["navy"] = 0x000080; - colors["oldlace"] = 0xfdf5e6; - colors["olive"] = 0x808000; - colors["olivedrab"] = 0x6b8e23; - colors["orange"] = 0xffa500; - colors["orangered"] = 0xff4500; - colors["orchid"] = 0xda70d6; - colors["palegoldenrod"] = 0xeee8aa; - colors["palegreen"] = 0x98fb98; - colors["paleturquoise"] = 0xafeeee; - colors["palevioletred"] = 0xdb7093; - colors["papayawhip"] = 0xffefd5; - colors["peachpuff"] = 0xffdab9; - colors["peru"] = 0xcd853f; - colors["pink"] = 0xffc0cb; - colors["plum"] = 0xdda0dd; - colors["powderblue"] = 0xb0e0e6; - colors["purple"] = 0x800080; - colors["red"] = 0xff0000; - colors["rosybrown"] = 0xbc8f8f; - colors["royalblue"] = 0x4169e1; - colors["saddlebrown"] = 0x8b4513; - colors["salmon"] = 0xfa8072; - colors["sandybrown"] = 0xf4a460; - colors["seagreen"] = 0x2e8b57; - colors["seashell"] = 0xfff5ee; - colors["sienna"] = 0xa0522d; - colors["silver"] = 0xc0c0c0; - colors["skyblue"] = 0x87ceeb; - colors["slateblue"] = 0x6a5acd; - colors["slategray"] = 0x708090; - colors["slategrey"] = 0x708090; - colors["snow"] = 0xfffafa; - colors["springgreen"] = 0x00ff7f; - colors["steelblue"] = 0x4682b4; - colors["tan"] = 0xd2b48c; - colors["teal"] = 0x008080; - colors["thistle"] = 0xd8bfd8; - colors["tomato"] = 0xff6347; - colors["turquoise"] = 0x40e0d0; - colors["violet"] = 0xee82ee; - colors["wheat"] = 0xf5deb3; - colors["white"] = 0xffffff; - colors["whitesmoke"] = 0xf5f5f5; - colors["yellow"] = 0xffff00; - colors["yellowgreen"] = 0x9acd32; - -} - -static const ColorContainer named_colors; - static bool parseNamedColorString(const std::string &value, video::SColor &color) { std::string color_name; @@ -570,9 +531,8 @@ static bool parseNamedColorString(const std::string &value, video::SColor &color color_name = lowercase(color_name); - std::map::const_iterator it; - it = named_colors.colors.find(color_name); - if (it == named_colors.colors.end()) + auto it = s_named_colors.find(color_name); + if (it == s_named_colors.end()) return false; u32 color_temp = it->second; @@ -580,21 +540,26 @@ static bool parseNamedColorString(const std::string &value, video::SColor &color /* An empty string for alpha is ok (none of the color table entries * have an alpha value either). Color strings without an alpha specified * are interpreted as fully opaque - * - * For named colors the supplied alpha string (representing a hex value) - * must be exactly two digits. For example: colorname#08 */ if (!alpha_string.empty()) { - if (alpha_string.length() != 2) - return false; + if (alpha_string.size() == 1) { + u8 d; + if (!hex_digit_decode(alpha_string[0], d)) + return false; - unsigned char d1, d2; - if (!hex_digit_decode(alpha_string.at(0), d1) - || !hex_digit_decode(alpha_string.at(1), d2)) + color_temp |= ((d & 0xf) << 4 | (d & 0xf)) << 24; + } else if (alpha_string.size() == 2) { + u8 d1, d2; + if (!hex_digit_decode(alpha_string[0], d1) + || !hex_digit_decode(alpha_string[1], d2)) + return false; + + color_temp |= ((d1 & 0xf) << 4 | (d2 & 0xf)) << 24; + } else { return false; - color_temp |= ((d1 & 0xf) << 4 | (d2 & 0xf)) << 24; + } } else { - color_temp |= 0xff << 24; // Fully opaque + color_temp |= 0xff << 24; // Fully opaque } color = video::SColor(color_temp); @@ -602,6 +567,22 @@ static bool parseNamedColorString(const std::string &value, video::SColor &color return true; } +bool parseColorString(const std::string &value, video::SColor &color, bool quiet, + unsigned char default_alpha) +{ + bool success; + + if (value[0] == '#') + success = parseHexColorString(value, color, default_alpha); + else + success = parseNamedColorString(value, color); + + if (!success && !quiet) + errorstream << "Invalid color: \"" << value << "\"" << std::endl; + + return success; +} + void str_replace(std::string &str, char from, char to) { std::replace(str.begin(), str.end(), from, to); From 776015c350bc0210a13dd1a077c086cb81314c09 Mon Sep 17 00:00:00 2001 From: Wuzzy Date: Fri, 23 Apr 2021 19:37:45 +0000 Subject: [PATCH 48/72] =?UTF-8?q?Rename=20=E2=80=9CIrrlicht=E2=80=9D=20to?= =?UTF-8?q?=20=E2=80=9CIrrlichtMt=E2=80=9D=20in=20documentation?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- CMakeLists.txt | 6 +++--- LICENSE.txt | 3 ++- README.md | 6 +++--- builtin/settingtypes.txt | 2 +- minetest.conf.example | 2 +- 5 files changed, 10 insertions(+), 9 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index c46ff6c77..1f90847ea 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -60,9 +60,9 @@ set(CMAKE_MODULE_PATH ${CMAKE_MODULE_PATH} "${CMAKE_SOURCE_DIR}/cmake/Modules/") # This is done here so that relative search paths are more reasonable find_package(Irrlicht) if(BUILD_CLIENT AND NOT IRRLICHT_FOUND) - message(FATAL_ERROR "Irrlicht is required to build the client, but it was not found.") + message(FATAL_ERROR "IrrlichtMt is required to build the client, but it was not found.") elseif(NOT IRRLICHT_INCLUDE_DIR) - message(FATAL_ERROR "Irrlicht headers are required to build the server, but none found.") + message(FATAL_ERROR "Irrlicht or IrrlichtMt headers are required to build the server, but none found.") endif() include(CheckSymbolExists) @@ -71,7 +71,7 @@ unset(HAS_FORKED_IRRLICHT CACHE) check_symbol_exists(IRRLICHT_VERSION_MT "IrrCompileConfig.h" HAS_FORKED_IRRLICHT) if(NOT HAS_FORKED_IRRLICHT) string(CONCAT EXPLANATION_MSG - "Irrlicht found, but it is not Minetest's Irrlicht fork. " + "Irrlicht found, but it is not IrrlichtMt (Minetest's Irrlicht fork). " "The Minetest team has forked Irrlicht to make their own customizations. " "It can be found here: https://github.com/minetest/irrlicht") if(BUILD_CLIENT) diff --git a/LICENSE.txt b/LICENSE.txt index 2d1c0c795..ab44488a7 100644 --- a/LICENSE.txt +++ b/LICENSE.txt @@ -87,7 +87,8 @@ with this program; if not, write to the Free Software Foundation, Inc., Irrlicht --------------- -This program uses the Irrlicht Engine. http://irrlicht.sourceforge.net/ +This program uses IrrlichtMt, Minetest's fork of +the Irrlicht Engine. http://irrlicht.sourceforge.net/ The Irrlicht Engine License diff --git a/README.md b/README.md index 0b9907992..013687685 100644 --- a/README.md +++ b/README.md @@ -134,7 +134,7 @@ Compiling |------------|---------|------------| | GCC | 4.9+ | Can be replaced with Clang 3.4+ | | CMake | 3.5+ | | -| Irrlicht | - | Custom version required, see https://github.com/minetest/irrlicht | +| IrrlichtMt | - | Custom version of Irrlicht, see https://github.com/minetest/irrlicht | | SQLite3 | 3.0+ | | | LuaJIT | 2.0+ | Bundled Lua 5.1 is used if not present | | GMP | 5.0.0+ | Bundled mini-GMP is used if not present | @@ -209,7 +209,7 @@ Run it: - You can disable the client build by specifying `-DBUILD_CLIENT=FALSE`. - You can select between Release and Debug build by `-DCMAKE_BUILD_TYPE=`. - Debug build is slower, but gives much more useful output in a debugger. -- If you build a bare server you don't need to have the Irrlicht library installed. +- If you build a bare server you don't need to have the Irrlicht or IrrlichtMt library installed. - In that case use `-DIRRLICHT_INCLUDE_DIR=/some/where/irrlicht/include`. ### CMake options @@ -229,7 +229,7 @@ General options and their default values: ENABLE_CURSES=ON - Build with (n)curses; Enables a server side terminal (command line option: --terminal) ENABLE_FREETYPE=ON - Build with FreeType2; Allows using TTF fonts ENABLE_GETTEXT=ON - Build with Gettext; Allows using translations - ENABLE_GLES=OFF - Build for OpenGL ES instead of OpenGL (requires support by Irrlicht) + ENABLE_GLES=OFF - Build for OpenGL ES instead of OpenGL (requires support by IrrlichtMt) ENABLE_LEVELDB=ON - Build with LevelDB; Enables use of LevelDB map backend ENABLE_POSTGRESQL=ON - Build with libpq; Enables use of PostgreSQL map backend (PostgreSQL 9.5 or greater recommended) ENABLE_REDIS=ON - Build with libhiredis; Enables use of Redis map backend diff --git a/builtin/settingtypes.txt b/builtin/settingtypes.txt index 00d1b87d7..d13bac91b 100644 --- a/builtin/settingtypes.txt +++ b/builtin/settingtypes.txt @@ -661,7 +661,7 @@ lighting_boost_spread (Light curve boost spread) float 0.2 0.0 0.4 # Path to texture directory. All textures are first searched from here. texture_path (Texture path) path -# The rendering back-end for Irrlicht. +# The rendering back-end. # A restart is required after changing this. # Note: On Android, stick with OGLES1 if unsure! App may fail to start otherwise. # On other platforms, OpenGL is recommended. diff --git a/minetest.conf.example b/minetest.conf.example index 47c03ff80..6343c8234 100644 --- a/minetest.conf.example +++ b/minetest.conf.example @@ -761,7 +761,7 @@ # type: path # texture_path = -# The rendering back-end for Irrlicht. +# The rendering back-end. # A restart is required after changing this. # Note: On Android, stick with OGLES1 if unsure! App may fail to start otherwise. # On other platforms, OpenGL is recommended. From 9660ae288a4e520907a29f34ea7ed20acdcbc212 Mon Sep 17 00:00:00 2001 From: sfan5 Date: Tue, 27 Apr 2021 11:50:40 +0200 Subject: [PATCH 49/72] Update library versions in buildbot (#11229) --- util/buildbot/buildwin32.sh | 85 +++++++++++++++++-------------------- util/buildbot/buildwin64.sh | 85 +++++++++++++++++-------------------- 2 files changed, 76 insertions(+), 94 deletions(-) diff --git a/util/buildbot/buildwin32.sh b/util/buildbot/buildwin32.sh index df62062c9..468df05a9 100755 --- a/util/buildbot/buildwin32.sh +++ b/util/buildbot/buildwin32.sh @@ -16,7 +16,6 @@ fi builddir=$1 mkdir -p $builddir builddir="$( cd "$builddir" && pwd )" -packagedir=$builddir/packages libdir=$builddir/libs # Test which win32 compiler is present @@ -32,58 +31,50 @@ fi echo "Using $toolchain_file" irrlicht_version=1.9.0mt1 -ogg_version=1.3.2 -vorbis_version=1.3.5 -curl_version=7.65.3 +ogg_version=1.3.4 +vorbis_version=1.3.7 +curl_version=7.76.1 gettext_version=0.20.1 -freetype_version=2.10.1 -sqlite3_version=3.27.2 +freetype_version=2.10.4 +sqlite3_version=3.35.5 luajit_version=2.1.0-beta3 -leveldb_version=1.22 +leveldb_version=1.23 zlib_version=1.2.11 -mkdir -p $packagedir mkdir -p $libdir -cd $builddir +download () { + local url=$1 + local filename=$2 + [ -z "$filename" ] && filename=${url##*/} + local foldername=${filename%%[.-]*} + local extract=$3 + [ -z "$extract" ] && extract=unzip + + [ -d "./$foldername" ] && return 0 + wget "$url" -c -O "./$filename" + if [ "$extract" = "unzip" ]; then + unzip -o "$filename" -d "$foldername" + elif [ "$extract" = "unzip_nofolder" ]; then + unzip -o "$filename" + else + return 1 + fi +} # Get stuff -[ -e $packagedir/irrlicht-$irrlicht_version.zip ] || wget https://github.com/minetest/irrlicht/releases/download/$irrlicht_version/win32.zip \ - -c -O $packagedir/irrlicht-$irrlicht_version.zip -[ -e $packagedir/zlib-$zlib_version.zip ] || wget http://minetest.kitsunemimi.pw/zlib-$zlib_version-win32.zip \ - -c -O $packagedir/zlib-$zlib_version.zip -[ -e $packagedir/libogg-$ogg_version.zip ] || wget http://minetest.kitsunemimi.pw/libogg-$ogg_version-win32.zip \ - -c -O $packagedir/libogg-$ogg_version.zip -[ -e $packagedir/libvorbis-$vorbis_version.zip ] || wget http://minetest.kitsunemimi.pw/libvorbis-$vorbis_version-win32.zip \ - -c -O $packagedir/libvorbis-$vorbis_version.zip -[ -e $packagedir/curl-$curl_version.zip ] || wget http://minetest.kitsunemimi.pw/curl-$curl_version-win32.zip \ - -c -O $packagedir/curl-$curl_version.zip -[ -e $packagedir/gettext-$gettext_version.zip ] || wget http://minetest.kitsunemimi.pw/gettext-$gettext_version-win32.zip \ - -c -O $packagedir/gettext-$gettext_version.zip -[ -e $packagedir/freetype2-$freetype_version.zip ] || wget http://minetest.kitsunemimi.pw/freetype2-$freetype_version-win32.zip \ - -c -O $packagedir/freetype2-$freetype_version.zip -[ -e $packagedir/sqlite3-$sqlite3_version.zip ] || wget http://minetest.kitsunemimi.pw/sqlite3-$sqlite3_version-win32.zip \ - -c -O $packagedir/sqlite3-$sqlite3_version.zip -[ -e $packagedir/luajit-$luajit_version.zip ] || wget http://minetest.kitsunemimi.pw/luajit-$luajit_version-win32.zip \ - -c -O $packagedir/luajit-$luajit_version.zip -[ -e $packagedir/libleveldb-$leveldb_version.zip ] || wget http://minetest.kitsunemimi.pw/libleveldb-$leveldb_version-win32.zip \ - -c -O $packagedir/libleveldb-$leveldb_version.zip -[ -e $packagedir/openal_stripped.zip ] || wget http://minetest.kitsunemimi.pw/openal_stripped.zip \ - -c -O $packagedir/openal_stripped.zip - -# Extract stuff cd $libdir -[ -d irrlicht ] || unzip -o $packagedir/irrlicht-$irrlicht_version.zip -d irrlicht -[ -d zlib ] || unzip -o $packagedir/zlib-$zlib_version.zip -d zlib -[ -d libogg ] || unzip -o $packagedir/libogg-$ogg_version.zip -d libogg -[ -d libvorbis ] || unzip -o $packagedir/libvorbis-$vorbis_version.zip -d libvorbis -[ -d libcurl ] || unzip -o $packagedir/curl-$curl_version.zip -d libcurl -[ -d gettext ] || unzip -o $packagedir/gettext-$gettext_version.zip -d gettext -[ -d freetype ] || unzip -o $packagedir/freetype2-$freetype_version.zip -d freetype -[ -d sqlite3 ] || unzip -o $packagedir/sqlite3-$sqlite3_version.zip -d sqlite3 -[ -d openal_stripped ] || unzip -o $packagedir/openal_stripped.zip -[ -d luajit ] || unzip -o $packagedir/luajit-$luajit_version.zip -d luajit -[ -d leveldb ] || unzip -o $packagedir/libleveldb-$leveldb_version.zip -d leveldb +download "https://github.com/minetest/irrlicht/releases/download/$irrlicht_version/win32.zip" irrlicht-$irrlicht_version.zip +download "http://minetest.kitsunemimi.pw/zlib-$zlib_version-win32.zip" +download "http://minetest.kitsunemimi.pw/libogg-$ogg_version-win32.zip" +download "http://minetest.kitsunemimi.pw/libvorbis-$vorbis_version-win32.zip" +download "http://minetest.kitsunemimi.pw/curl-$curl_version-win32.zip" +download "http://minetest.kitsunemimi.pw/gettext-$gettext_version-win32.zip" +download "http://minetest.kitsunemimi.pw/freetype2-$freetype_version-win32.zip" freetype-$freetype_version.zip +download "http://minetest.kitsunemimi.pw/sqlite3-$sqlite3_version-win32.zip" +download "http://minetest.kitsunemimi.pw/luajit-$luajit_version-win32.zip" +download "http://minetest.kitsunemimi.pw/libleveldb-$leveldb_version-win32.zip" leveldb-$leveldb_version.zip +download "http://minetest.kitsunemimi.pw/openal_stripped.zip" '' unzip_nofolder # Set source dir, downloading Minetest as needed if [ -n "$EXISTING_MINETEST_DIR" ]; then @@ -146,9 +137,9 @@ cmake -S $sourcedir -B . \ -DOPENAL_LIBRARY=$libdir/openal_stripped/lib/libOpenAL32.dll.a \ -DOPENAL_DLL=$libdir/openal_stripped/bin/OpenAL32.dll \ \ - -DCURL_DLL=$libdir/libcurl/bin/libcurl-4.dll \ - -DCURL_INCLUDE_DIR=$libdir/libcurl/include \ - -DCURL_LIBRARY=$libdir/libcurl/lib/libcurl.dll.a \ + -DCURL_DLL=$libdir/curl/bin/libcurl-4.dll \ + -DCURL_INCLUDE_DIR=$libdir/curl/include \ + -DCURL_LIBRARY=$libdir/curl/lib/libcurl.dll.a \ \ -DGETTEXT_MSGFMT=`which msgfmt` \ -DGETTEXT_DLL="$gettext_dlls" \ diff --git a/util/buildbot/buildwin64.sh b/util/buildbot/buildwin64.sh index c35ece35b..b9b23a133 100755 --- a/util/buildbot/buildwin64.sh +++ b/util/buildbot/buildwin64.sh @@ -16,63 +16,54 @@ fi builddir=$1 mkdir -p $builddir builddir="$( cd "$builddir" && pwd )" -packagedir=$builddir/packages libdir=$builddir/libs toolchain_file=$dir/toolchain_x86_64-w64-mingw32.cmake irrlicht_version=1.9.0mt1 -ogg_version=1.3.2 -vorbis_version=1.3.5 -curl_version=7.65.3 +ogg_version=1.3.4 +vorbis_version=1.3.7 +curl_version=7.76.1 gettext_version=0.20.1 -freetype_version=2.10.1 -sqlite3_version=3.27.2 +freetype_version=2.10.4 +sqlite3_version=3.35.5 luajit_version=2.1.0-beta3 -leveldb_version=1.22 +leveldb_version=1.23 zlib_version=1.2.11 -mkdir -p $packagedir mkdir -p $libdir -cd $builddir +download () { + local url=$1 + local filename=$2 + [ -z "$filename" ] && filename=${url##*/} + local foldername=${filename%%[.-]*} + local extract=$3 + [ -z "$extract" ] && extract=unzip + + [ -d "./$foldername" ] && return 0 + wget "$url" -c -O "./$filename" + if [ "$extract" = "unzip" ]; then + unzip -o "$filename" -d "$foldername" + elif [ "$extract" = "unzip_nofolder" ]; then + unzip -o "$filename" + else + return 1 + fi +} # Get stuff -[ -e $packagedir/irrlicht-$irrlicht_version.zip ] || wget https://github.com/minetest/irrlicht/releases/download/$irrlicht_version/win64.zip \ - -c -O $packagedir/irrlicht-$irrlicht_version.zip -[ -e $packagedir/zlib-$zlib_version.zip ] || wget http://minetest.kitsunemimi.pw/zlib-$zlib_version-win64.zip \ - -c -O $packagedir/zlib-$zlib_version.zip -[ -e $packagedir/libogg-$ogg_version.zip ] || wget http://minetest.kitsunemimi.pw/libogg-$ogg_version-win64.zip \ - -c -O $packagedir/libogg-$ogg_version.zip -[ -e $packagedir/libvorbis-$vorbis_version.zip ] || wget http://minetest.kitsunemimi.pw/libvorbis-$vorbis_version-win64.zip \ - -c -O $packagedir/libvorbis-$vorbis_version.zip -[ -e $packagedir/curl-$curl_version.zip ] || wget http://minetest.kitsunemimi.pw/curl-$curl_version-win64.zip \ - -c -O $packagedir/curl-$curl_version.zip -[ -e $packagedir/gettext-$gettext_version.zip ] || wget http://minetest.kitsunemimi.pw/gettext-$gettext_version-win64.zip \ - -c -O $packagedir/gettext-$gettext_version.zip -[ -e $packagedir/freetype2-$freetype_version.zip ] || wget http://minetest.kitsunemimi.pw/freetype2-$freetype_version-win64.zip \ - -c -O $packagedir/freetype2-$freetype_version.zip -[ -e $packagedir/sqlite3-$sqlite3_version.zip ] || wget http://minetest.kitsunemimi.pw/sqlite3-$sqlite3_version-win64.zip \ - -c -O $packagedir/sqlite3-$sqlite3_version.zip -[ -e $packagedir/luajit-$luajit_version.zip ] || wget http://minetest.kitsunemimi.pw/luajit-$luajit_version-win64.zip \ - -c -O $packagedir/luajit-$luajit_version.zip -[ -e $packagedir/libleveldb-$leveldb_version.zip ] || wget http://minetest.kitsunemimi.pw/libleveldb-$leveldb_version-win64.zip \ - -c -O $packagedir/libleveldb-$leveldb_version.zip -[ -e $packagedir/openal_stripped.zip ] || wget http://minetest.kitsunemimi.pw/openal_stripped64.zip \ - -c -O $packagedir/openal_stripped.zip - -# Extract stuff cd $libdir -[ -d irrlicht ] || unzip -o $packagedir/irrlicht-$irrlicht_version.zip -d irrlicht -[ -d zlib ] || unzip -o $packagedir/zlib-$zlib_version.zip -d zlib -[ -d libogg ] || unzip -o $packagedir/libogg-$ogg_version.zip -d libogg -[ -d libvorbis ] || unzip -o $packagedir/libvorbis-$vorbis_version.zip -d libvorbis -[ -d libcurl ] || unzip -o $packagedir/curl-$curl_version.zip -d libcurl -[ -d gettext ] || unzip -o $packagedir/gettext-$gettext_version.zip -d gettext -[ -d freetype ] || unzip -o $packagedir/freetype2-$freetype_version.zip -d freetype -[ -d sqlite3 ] || unzip -o $packagedir/sqlite3-$sqlite3_version.zip -d sqlite3 -[ -d openal_stripped ] || unzip -o $packagedir/openal_stripped.zip -[ -d luajit ] || unzip -o $packagedir/luajit-$luajit_version.zip -d luajit -[ -d leveldb ] || unzip -o $packagedir/libleveldb-$leveldb_version.zip -d leveldb +download "https://github.com/minetest/irrlicht/releases/download/$irrlicht_version/win64.zip" irrlicht-$irrlicht_version.zip +download "http://minetest.kitsunemimi.pw/zlib-$zlib_version-win64.zip" +download "http://minetest.kitsunemimi.pw/libogg-$ogg_version-win64.zip" +download "http://minetest.kitsunemimi.pw/libvorbis-$vorbis_version-win64.zip" +download "http://minetest.kitsunemimi.pw/curl-$curl_version-win64.zip" +download "http://minetest.kitsunemimi.pw/gettext-$gettext_version-win64.zip" +download "http://minetest.kitsunemimi.pw/freetype2-$freetype_version-win64.zip" freetype-$freetype_version.zip +download "http://minetest.kitsunemimi.pw/sqlite3-$sqlite3_version-win64.zip" +download "http://minetest.kitsunemimi.pw/luajit-$luajit_version-win64.zip" +download "http://minetest.kitsunemimi.pw/libleveldb-$leveldb_version-win64.zip" leveldb-$leveldb_version.zip +download "http://minetest.kitsunemimi.pw/openal_stripped64.zip" 'openal_stripped.zip' unzip_nofolder # Set source dir, downloading Minetest as needed if [ -n "$EXISTING_MINETEST_DIR" ]; then @@ -135,9 +126,9 @@ cmake -S $sourcedir -B . \ -DOPENAL_LIBRARY=$libdir/openal_stripped/lib/libOpenAL32.dll.a \ -DOPENAL_DLL=$libdir/openal_stripped/bin/OpenAL32.dll \ \ - -DCURL_DLL=$libdir/libcurl/bin/libcurl-4.dll \ - -DCURL_INCLUDE_DIR=$libdir/libcurl/include \ - -DCURL_LIBRARY=$libdir/libcurl/lib/libcurl.dll.a \ + -DCURL_DLL=$libdir/curl/bin/libcurl-4.dll \ + -DCURL_INCLUDE_DIR=$libdir/curl/include \ + -DCURL_LIBRARY=$libdir/curl/lib/libcurl.dll.a \ \ -DGETTEXT_MSGFMT=`which msgfmt` \ -DGETTEXT_DLL="$gettext_dlls" \ From 734fb2c811cdb0c26153c2bd5b62e458343963e7 Mon Sep 17 00:00:00 2001 From: sfan5 Date: Wed, 28 Apr 2021 08:38:18 +0200 Subject: [PATCH 50/72] Add helpful error messages if Irrlicht library / include dir are set incorrectly (#11232) --- cmake/Modules/FindIrrlicht.cmake | 20 +++++++++++++++++--- 1 file changed, 17 insertions(+), 3 deletions(-) diff --git a/cmake/Modules/FindIrrlicht.cmake b/cmake/Modules/FindIrrlicht.cmake index bb501b3b4..058e93878 100644 --- a/cmake/Modules/FindIrrlicht.cmake +++ b/cmake/Modules/FindIrrlicht.cmake @@ -1,5 +1,5 @@ -mark_as_advanced(IRRLICHT_LIBRARY IRRLICHT_INCLUDE_DIR IRRLICHT_DLL) +mark_as_advanced(IRRLICHT_DLL) # Find include directory and libraries @@ -29,8 +29,22 @@ foreach(libname IN ITEMS IrrlichtMt Irrlicht) endif() endforeach() -# Users will likely need to edit these -mark_as_advanced(CLEAR IRRLICHT_LIBRARY IRRLICHT_INCLUDE_DIR) +# Handholding for users +if(IRRLICHT_INCLUDE_DIR AND (NOT IS_DIRECTORY "${IRRLICHT_INCLUDE_DIR}" OR + NOT EXISTS "${IRRLICHT_INCLUDE_DIR}/irrlicht.h")) + message(WARNING "IRRLICHT_INCLUDE_DIR was set to ${IRRLICHT_INCLUDE_DIR} " + "but irrlicht.h does not exist inside. The path will not be used.") + unset(IRRLICHT_INCLUDE_DIR CACHE) +endif() +if(WIN32 OR CMAKE_SYSTEM_NAME STREQUAL "Linux" OR APPLE) + # (only on systems where we're sure how a valid library looks like) + if(IRRLICHT_LIBRARY AND (IS_DIRECTORY "${IRRLICHT_LIBRARY}" OR + NOT IRRLICHT_LIBRARY MATCHES "\\.(a|so|dylib|lib)([.0-9]+)?$")) + message(WARNING "IRRLICHT_LIBRARY was set to ${IRRLICHT_LIBRARY} " + "but is not a valid library file. The path will not be used.") + unset(IRRLICHT_LIBRARY CACHE) + endif() +endif() # On Windows, find the DLL for installation if(WIN32) From 228f1c67704ab8014d30a3301bd15a1a88324ce0 Mon Sep 17 00:00:00 2001 From: Wuzzy Date: Wed, 28 Apr 2021 06:38:47 +0000 Subject: [PATCH 51/72] Fix rotation for falling mesh degrotate nodes (#11159) --- builtin/game/falling.lua | 8 ++++++++ games/devtest/mods/experimental/commands.lua | 8 +++++--- games/devtest/mods/testnodes/drawtypes.lua | 13 +++++++------ 3 files changed, 20 insertions(+), 9 deletions(-) diff --git a/builtin/game/falling.lua b/builtin/game/falling.lua index 1f0a63993..2cc0d8fac 100644 --- a/builtin/game/falling.lua +++ b/builtin/game/falling.lua @@ -205,6 +205,14 @@ core.register_entity(":__builtin:falling_node", { end end self.object:set_rotation({x=pitch, y=yaw, z=roll}) + elseif (def.drawtype == "mesh" and def.paramtype2 == "degrotate") then + local p2 = (node.param2 - (def.place_param2 or 0)) % 240 + local yaw = (p2 / 240) * (math.pi * 2) + self.object:set_yaw(yaw) + elseif (def.drawtype == "mesh" and def.paramtype2 == "colordegrotate") then + local p2 = (node.param2 % 32 - (def.place_param2 or 0) % 32) % 24 + local yaw = (p2 / 24) * (math.pi * 2) + self.object:set_yaw(yaw) end end end, diff --git a/games/devtest/mods/experimental/commands.lua b/games/devtest/mods/experimental/commands.lua index 8bfa467e1..e42ae954d 100644 --- a/games/devtest/mods/experimental/commands.lua +++ b/games/devtest/mods/experimental/commands.lua @@ -131,10 +131,11 @@ local function place_nodes(param) p2_max = 63 elseif def.paramtype2 == "leveled" then p2_max = 127 - elseif def.paramtype2 == "degrotate" and def.drawtype == "plantlike" then - p2_max = 179 + elseif def.paramtype2 == "degrotate" and (def.drawtype == "plantlike" or def.drawtype == "mesh") then + p2_max = 239 elseif def.paramtype2 == "colorfacedir" or def.paramtype2 == "colorwallmounted" or + def.paramtype2 == "colordegrotate" or def.paramtype2 == "color" then p2_max = 255 end @@ -143,7 +144,8 @@ local function place_nodes(param) -- Skip undefined param2 values if not ((def.paramtype2 == "meshoptions" and p2 % 8 > 4) or (def.paramtype2 == "colorwallmounted" and p2 % 8 > 5) or - (def.paramtype2 == "colorfacedir" and p2 % 32 > 23)) then + ((def.paramtype2 == "colorfacedir" or def.paramtype2 == "colordegrotate") + and p2 % 32 > 23)) then minetest.set_node(pos, { name = itemstring, param2 = p2 }) nodes_placed = nodes_placed + 1 diff --git a/games/devtest/mods/testnodes/drawtypes.lua b/games/devtest/mods/testnodes/drawtypes.lua index 3bf631714..2bc7ec2e3 100644 --- a/games/devtest/mods/testnodes/drawtypes.lua +++ b/games/devtest/mods/testnodes/drawtypes.lua @@ -254,11 +254,11 @@ minetest.register_node("testnodes:mesh_degrotate", { drawtype = "mesh", paramtype = "light", paramtype2 = "degrotate", - mesh = "testnodes_pyramid.obj", + mesh = "testnodes_ocorner.obj", tiles = { "testnodes_mesh_stripes2.png" }, on_rightclick = rotate_on_rightclick, - place_param2 = 7, + place_param2 = 10, -- 15° sunlight_propagates = true, groups = { dig_immediate = 3 }, }) @@ -266,14 +266,15 @@ minetest.register_node("testnodes:mesh_degrotate", { minetest.register_node("testnodes:mesh_colordegrotate", { description = S("Color Degrotate Mesh Drawtype Test Node"), drawtype = "mesh", + paramtype = "light", paramtype2 = "colordegrotate", palette = "testnodes_palette_facedir.png", - mesh = "testnodes_pyramid.obj", - tiles = { "testnodes_mesh_stripes2.png" }, + mesh = "testnodes_ocorner.obj", + tiles = { "testnodes_mesh_stripes3.png" }, on_rightclick = rotate_on_rightclick, - -- color index 1, 7 steps rotated - place_param2 = 1 * 2^5 + 7, + -- color index 1, 1 step (=15°) rotated + place_param2 = 1 * 2^5 + 1, sunlight_propagates = true, groups = { dig_immediate = 3 }, }) From 83a7b48bb1312cf9851706c2b6adc7877556e8d5 Mon Sep 17 00:00:00 2001 From: sfan5 Date: Tue, 27 Apr 2021 23:41:35 +0200 Subject: [PATCH 52/72] Fix Windows pipelines on Gitlab-CI --- .gitlab-ci.yml | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/.gitlab-ci.yml b/.gitlab-ci.yml index 5e16cdfe5..597e7ab52 100644 --- a/.gitlab-ci.yml +++ b/.gitlab-ci.yml @@ -171,10 +171,10 @@ build:fedora-28: ## .generic_win_template: - image: ubuntu:bionic + image: ubuntu:focal before_script: - apt-get update - - apt-get install -y wget xz-utils unzip git cmake gettext + - DEBIAN_FRONTEND=noninteractive apt-get install -y wget xz-utils unzip git cmake gettext - wget -nv http://minetest.kitsunemimi.pw/mingw-w64-${WIN_ARCH}_9.2.0_ubuntu18.04.tar.xz -O mingw.tar.xz - tar -xaf mingw.tar.xz -C /usr @@ -184,13 +184,13 @@ build:fedora-28: artifacts: expire_in: 1h paths: - - _build/* + - build/build/*.zip .package_win_template: extends: .generic_win_template stage: package script: - - unzip _build/minetest-*.zip + - unzip build/build/*.zip - cp -p /usr/${WIN_ARCH}-w64-mingw32/bin/libgcc*.dll minetest-*-win*/bin/ - cp -p /usr/${WIN_ARCH}-w64-mingw32/bin/libstdc++*.dll minetest-*-win*/bin/ - cp -p /usr/${WIN_ARCH}-w64-mingw32/bin/libwinpthread*.dll minetest-*-win*/bin/ From bc1888ff21d50eb21c8f4d381e5dcc8049f7e36c Mon Sep 17 00:00:00 2001 From: Loic Blot Date: Wed, 28 Apr 2021 09:55:51 +0200 Subject: [PATCH 53/72] fix: drop old irrlicht <1.8 compat on Client::loadMedia --- src/client/client.cpp | 7 ------- 1 file changed, 7 deletions(-) diff --git a/src/client/client.cpp b/src/client/client.cpp index 0486bc0a9..5db0b8f5d 100644 --- a/src/client/client.cpp +++ b/src/client/client.cpp @@ -663,15 +663,8 @@ bool Client::loadMedia(const std::string &data, const std::string &filename, io::IFileSystem *irrfs = RenderingEngine::get_filesystem(); video::IVideoDriver *vdrv = RenderingEngine::get_video_driver(); -#if IRRLICHT_VERSION_MAJOR == 1 && IRRLICHT_VERSION_MINOR > 8 io::IReadFile *rfile = irrfs->createMemoryReadFile( data.c_str(), data.size(), "_tempreadfile"); -#else - // Silly irrlicht's const-incorrectness - Buffer data_rw(data.c_str(), data.size()); - io::IReadFile *rfile = irrfs->createMemoryReadFile( - *data_rw, data_rw.getSize(), "_tempreadfile"); -#endif FATAL_ERROR_IF(!rfile, "Could not create irrlicht memory file."); From e34d28af9f4b779b7a137f0e4017e499266e1931 Mon Sep 17 00:00:00 2001 From: Loic Blot Date: Wed, 28 Apr 2021 10:22:13 +0200 Subject: [PATCH 54/72] refacto: rendering engine singleton removal step 1 (filesystem) Make the RenderingEngine filesystem member non accessible from everywhere This permits also to determine that some lua code has directly a logic to extract zip file. Move this logic inside client, it's not the lua stack role to perform a such complex operation Found also another irrlicht <1.8 compat code to remove --- src/client/client.cpp | 84 +++++++++++++++++++++++++++---- src/client/client.h | 6 +++ src/client/game.cpp | 2 +- src/client/renderingengine.h | 5 +- src/script/lua_api/l_mainmenu.cpp | 73 +-------------------------- 5 files changed, 84 insertions(+), 86 deletions(-) diff --git a/src/client/client.cpp b/src/client/client.cpp index 5db0b8f5d..d7e69f349 100644 --- a/src/client/client.cpp +++ b/src/client/client.cpp @@ -97,6 +97,7 @@ Client::Client( NodeDefManager *nodedef, ISoundManager *sound, MtEventManager *event, + RenderingEngine *rendering_engine, bool ipv6, GameUI *game_ui ): @@ -106,6 +107,7 @@ Client::Client( m_nodedef(nodedef), m_sound(sound), m_event(event), + m_rendering_engine(rendering_engine), m_mesh_update_thread(this), m_env( new ClientMap(this, control, 666), @@ -660,8 +662,8 @@ bool Client::loadMedia(const std::string &data, const std::string &filename, TRACESTREAM(<< "Client: Attempting to load image " << "file \"" << filename << "\"" << std::endl); - io::IFileSystem *irrfs = RenderingEngine::get_filesystem(); - video::IVideoDriver *vdrv = RenderingEngine::get_video_driver(); + io::IFileSystem *irrfs = m_rendering_engine->get_filesystem(); + video::IVideoDriver *vdrv = m_rendering_engine->get_video_driver(); io::IReadFile *rfile = irrfs->createMemoryReadFile( data.c_str(), data.size(), "_tempreadfile"); @@ -728,6 +730,72 @@ bool Client::loadMedia(const std::string &data, const std::string &filename, return false; } +bool Client::extractZipFile(const char *filename, const std::string &destination) +{ + auto fs = m_rendering_engine->get_filesystem(); + + if (!fs->addFileArchive(filename, false, false, io::EFAT_ZIP)) { + return false; + } + + sanity_check(fs->getFileArchiveCount() > 0); + + /**********************************************************************/ + /* WARNING this is not threadsafe!! */ + /**********************************************************************/ + io::IFileArchive* opened_zip = fs->getFileArchive(fs->getFileArchiveCount() - 1); + + const io::IFileList* files_in_zip = opened_zip->getFileList(); + + unsigned int number_of_files = files_in_zip->getFileCount(); + + for (unsigned int i=0; i < number_of_files; i++) { + std::string fullpath = destination; + fullpath += DIR_DELIM; + fullpath += files_in_zip->getFullFileName(i).c_str(); + std::string fullpath_dir = fs::RemoveLastPathComponent(fullpath); + + if (!files_in_zip->isDirectory(i)) { + if (!fs::PathExists(fullpath_dir) && !fs::CreateAllDirs(fullpath_dir)) { + fs->removeFileArchive(fs->getFileArchiveCount()-1); + return false; + } + + io::IReadFile* toread = opened_zip->createAndOpenFile(i); + + FILE *targetfile = fopen(fullpath.c_str(),"wb"); + + if (targetfile == NULL) { + fs->removeFileArchive(fs->getFileArchiveCount()-1); + return false; + } + + char read_buffer[1024]; + long total_read = 0; + + while (total_read < toread->getSize()) { + + unsigned int bytes_read = + toread->read(read_buffer,sizeof(read_buffer)); + if ((bytes_read == 0 ) || + (fwrite(read_buffer, 1, bytes_read, targetfile) != bytes_read)) + { + fclose(targetfile); + fs->removeFileArchive(fs->getFileArchiveCount() - 1); + return false; + } + total_read += bytes_read; + } + + fclose(targetfile); + } + + } + + fs->removeFileArchive(fs->getFileArchiveCount() - 1); + return true; +} + // Virtual methods from con::PeerHandler void Client::peerAdded(con::Peer *peer) { @@ -1910,23 +1978,17 @@ scene::IAnimatedMesh* Client::getMesh(const std::string &filename, bool cache) // Create the mesh, remove it from cache and return it // This allows unique vertex colors and other properties for each instance -#if IRRLICHT_VERSION_MAJOR == 1 && IRRLICHT_VERSION_MINOR > 8 - io::IReadFile *rfile = RenderingEngine::get_filesystem()->createMemoryReadFile( + io::IReadFile *rfile = m_rendering_engine->get_filesystem()->createMemoryReadFile( data.c_str(), data.size(), filename.c_str()); -#else - Buffer data_rw(data.c_str(), data.size()); // Const-incorrect Irrlicht - io::IReadFile *rfile = RenderingEngine::get_filesystem()->createMemoryReadFile( - *data_rw, data_rw.getSize(), filename.c_str()); -#endif FATAL_ERROR_IF(!rfile, "Could not create/open RAM file"); - scene::IAnimatedMesh *mesh = RenderingEngine::get_scene_manager()->getMesh(rfile); + scene::IAnimatedMesh *mesh = m_rendering_engine->get_scene_manager()->getMesh(rfile); rfile->drop(); if (!mesh) return nullptr; mesh->grab(); if (!cache) - RenderingEngine::get_mesh_cache()->removeMesh(mesh); + m_rendering_engine->get_mesh_cache()->removeMesh(mesh); return mesh; } diff --git a/src/client/client.h b/src/client/client.h index 2dba1506e..bcb7d6b09 100644 --- a/src/client/client.h +++ b/src/client/client.h @@ -45,6 +45,7 @@ struct ClientEvent; struct MeshMakeData; struct ChatMessage; class MapBlockMesh; +class RenderingEngine; class IWritableTextureSource; class IWritableShaderSource; class IWritableItemDefManager; @@ -123,6 +124,7 @@ public: NodeDefManager *nodedef, ISoundManager *sound, MtEventManager *event, + RenderingEngine *rendering_engine, bool ipv6, GameUI *game_ui ); @@ -379,6 +381,9 @@ public: // Insert a media file appropriately into the appropriate manager bool loadMedia(const std::string &data, const std::string &filename, bool from_media_push = false); + + bool extractZipFile(const char *filename, const std::string &destination); + // Send a request for conventional media transfer void request_media(const std::vector &file_requests); @@ -469,6 +474,7 @@ private: NodeDefManager *m_nodedef; ISoundManager *m_sound; MtEventManager *m_event; + RenderingEngine *m_rendering_engine; MeshUpdateThread m_mesh_update_thread; diff --git a/src/client/game.cpp b/src/client/game.cpp index b092b95e2..612072136 100644 --- a/src/client/game.cpp +++ b/src/client/game.cpp @@ -1465,7 +1465,7 @@ bool Game::connectToServer(const GameStartData &start_data, start_data.password, start_data.address, *draw_control, texture_src, shader_src, itemdef_manager, nodedef_manager, sound, eventmgr, - connect_address.isIPv6(), m_game_ui.get()); + RenderingEngine::get_instance(), connect_address.isIPv6(), m_game_ui.get()); client->m_simple_singleplayer_mode = simple_singleplayer_mode; diff --git a/src/client/renderingengine.h b/src/client/renderingengine.h index 34cc60630..5807421ef 100644 --- a/src/client/renderingengine.h +++ b/src/client/renderingengine.h @@ -59,10 +59,9 @@ public: static RenderingEngine *get_instance() { return s_singleton; } - static io::IFileSystem *get_filesystem() + io::IFileSystem *get_filesystem() { - sanity_check(s_singleton && s_singleton->m_device); - return s_singleton->m_device->getFileSystem(); + return m_device->getFileSystem(); } static video::IVideoDriver *get_video_driver() diff --git a/src/script/lua_api/l_mainmenu.cpp b/src/script/lua_api/l_mainmenu.cpp index 6488cd0fc..1e8dea909 100644 --- a/src/script/lua_api/l_mainmenu.cpp +++ b/src/script/lua_api/l_mainmenu.cpp @@ -34,9 +34,7 @@ with this program; if not, write to the Free Software Foundation, Inc., #include "serverlist.h" #include "mapgen/mapgen.h" #include "settings.h" - -#include -#include +#include "client/client.h" #include "client/renderingengine.h" #include "network/networkprotocol.h" @@ -630,74 +628,7 @@ int ModApiMainMenu::l_extract_zip(lua_State *L) if (ModApiMainMenu::mayModifyPath(absolute_destination)) { fs::CreateAllDirs(absolute_destination); - - io::IFileSystem *fs = RenderingEngine::get_filesystem(); - - if (!fs->addFileArchive(zipfile, false, false, io::EFAT_ZIP)) { - lua_pushboolean(L,false); - return 1; - } - - sanity_check(fs->getFileArchiveCount() > 0); - - /**********************************************************************/ - /* WARNING this is not threadsafe!! */ - /**********************************************************************/ - io::IFileArchive* opened_zip = - fs->getFileArchive(fs->getFileArchiveCount()-1); - - const io::IFileList* files_in_zip = opened_zip->getFileList(); - - unsigned int number_of_files = files_in_zip->getFileCount(); - - for (unsigned int i=0; i < number_of_files; i++) { - std::string fullpath = destination; - fullpath += DIR_DELIM; - fullpath += files_in_zip->getFullFileName(i).c_str(); - std::string fullpath_dir = fs::RemoveLastPathComponent(fullpath); - - if (!files_in_zip->isDirectory(i)) { - if (!fs::PathExists(fullpath_dir) && !fs::CreateAllDirs(fullpath_dir)) { - fs->removeFileArchive(fs->getFileArchiveCount()-1); - lua_pushboolean(L,false); - return 1; - } - - io::IReadFile* toread = opened_zip->createAndOpenFile(i); - - FILE *targetfile = fopen(fullpath.c_str(),"wb"); - - if (targetfile == NULL) { - fs->removeFileArchive(fs->getFileArchiveCount()-1); - lua_pushboolean(L,false); - return 1; - } - - char read_buffer[1024]; - long total_read = 0; - - while (total_read < toread->getSize()) { - - unsigned int bytes_read = - toread->read(read_buffer,sizeof(read_buffer)); - if ((bytes_read == 0 ) || - (fwrite(read_buffer, 1, bytes_read, targetfile) != bytes_read)) - { - fclose(targetfile); - fs->removeFileArchive(fs->getFileArchiveCount()-1); - lua_pushboolean(L,false); - return 1; - } - total_read += bytes_read; - } - - fclose(targetfile); - } - - } - - fs->removeFileArchive(fs->getFileArchiveCount()-1); - lua_pushboolean(L,true); + lua_pushboolean(L, getClient(L)->extractZipFile(zipfile, destination)); return 1; } From e0716384d6c7abfa228b039056f1e872ca7bb8cf Mon Sep 17 00:00:00 2001 From: Loic Blot Date: Wed, 28 Apr 2021 10:53:36 +0200 Subject: [PATCH 55/72] refacto: add RenderingEngine::cleanupMeshCache This permits to prevent client to own the mesh cache cleanup logic. It's better in RenderingEngine --- src/client/client.cpp | 7 +------ src/client/renderingengine.cpp | 9 +++++++++ src/client/renderingengine.h | 1 + 3 files changed, 11 insertions(+), 6 deletions(-) diff --git a/src/client/client.cpp b/src/client/client.cpp index d7e69f349..48097be2e 100644 --- a/src/client/client.cpp +++ b/src/client/client.cpp @@ -300,12 +300,7 @@ Client::~Client() } // cleanup 3d model meshes on client shutdown - while (RenderingEngine::get_mesh_cache()->getMeshCount() != 0) { - scene::IAnimatedMesh *mesh = RenderingEngine::get_mesh_cache()->getMeshByIndex(0); - - if (mesh) - RenderingEngine::get_mesh_cache()->removeMesh(mesh); - } + m_rendering_engine->cleanupMeshCache(); delete m_minimap; m_minimap = nullptr; diff --git a/src/client/renderingengine.cpp b/src/client/renderingengine.cpp index d2d136a61..970bcf95b 100644 --- a/src/client/renderingengine.cpp +++ b/src/client/renderingengine.cpp @@ -225,6 +225,15 @@ bool RenderingEngine::print_video_modes() return videomode_list != NULL; } +void RenderingEngine::cleanupMeshCache() +{ + auto mesh_cache = m_device->getSceneManager()->getMeshCache(); + while (mesh_cache->getMeshCount() != 0) { + if (scene::IAnimatedMesh *mesh = mesh_cache->getMeshByIndex(0)) + m_rendering_engine->get_mesh_cache()->removeMesh(mesh); + } +} + bool RenderingEngine::setupTopLevelWindow(const std::string &name) { // FIXME: It would make more sense for there to be a switch of some diff --git a/src/client/renderingengine.h b/src/client/renderingengine.h index 5807421ef..fae431f1f 100644 --- a/src/client/renderingengine.h +++ b/src/client/renderingengine.h @@ -56,6 +56,7 @@ public: bool setWindowIcon(); bool setXorgWindowIconFromPath(const std::string &icon_file); static bool print_video_modes(); + void cleanupMeshCache(); static RenderingEngine *get_instance() { return s_singleton; } From 74125a74d34e9b1a003107d4ef6b95b8483d2464 Mon Sep 17 00:00:00 2001 From: Loic Blot Date: Wed, 28 Apr 2021 11:07:28 +0200 Subject: [PATCH 56/72] refacto: hide mesh_cache inside the rendering engine This permit cleaner access to meshCache and ensure we don't access to it from all the code --- src/client/client.cpp | 2 +- src/client/game.cpp | 25 +------------------------ src/client/renderingengine.cpp | 7 ++++++- src/client/renderingengine.h | 11 +++++------ 4 files changed, 13 insertions(+), 32 deletions(-) diff --git a/src/client/client.cpp b/src/client/client.cpp index 48097be2e..15979df02 100644 --- a/src/client/client.cpp +++ b/src/client/client.cpp @@ -1983,7 +1983,7 @@ scene::IAnimatedMesh* Client::getMesh(const std::string &filename, bool cache) return nullptr; mesh->grab(); if (!cache) - m_rendering_engine->get_mesh_cache()->removeMesh(mesh); + m_rendering_engine->removeMesh(mesh); return mesh; } diff --git a/src/client/game.cpp b/src/client/game.cpp index 612072136..8400d7639 100644 --- a/src/client/game.cpp +++ b/src/client/game.cpp @@ -652,8 +652,6 @@ public: protected: - void extendedResourceCleanup(); - // Basic initialisation bool init(const std::string &map_dir, const std::string &address, u16 port, const SubgameSpec &gamespec); @@ -968,7 +966,7 @@ Game::~Game() delete itemdef_manager; delete draw_control; - extendedResourceCleanup(); + clearTextureNameCache(); g_settings->deregisterChangedCallback("doubletap_jump", &settingChangedCallback, this); @@ -4063,27 +4061,6 @@ void Game::readSettings() ****************************************************************************/ /****************************************************************************/ -void Game::extendedResourceCleanup() -{ - // Extended resource accounting - infostream << "Irrlicht resources after cleanup:" << std::endl; - infostream << "\tRemaining meshes : " - << RenderingEngine::get_mesh_cache()->getMeshCount() << std::endl; - infostream << "\tRemaining textures : " - << driver->getTextureCount() << std::endl; - - for (unsigned int i = 0; i < driver->getTextureCount(); i++) { - irr::video::ITexture *texture = driver->getTextureByIndex(i); - infostream << "\t\t" << i << ":" << texture->getName().getPath().c_str() - << std::endl; - } - - clearTextureNameCache(); - infostream << "\tRemaining materials: " - << driver-> getMaterialRendererCount() - << " (note: irrlicht doesn't support removing renderers)" << std::endl; -} - void Game::showDeathFormspec() { static std::string formspec_str = diff --git a/src/client/renderingengine.cpp b/src/client/renderingengine.cpp index 970bcf95b..da9022477 100644 --- a/src/client/renderingengine.cpp +++ b/src/client/renderingengine.cpp @@ -225,12 +225,17 @@ bool RenderingEngine::print_video_modes() return videomode_list != NULL; } +void RenderingEngine::removeMesh(const irr::scene::IMesh* mesh) +{ + m_device->getSceneManager()->getMeshCache()->removeMesh(mesh); +} + void RenderingEngine::cleanupMeshCache() { auto mesh_cache = m_device->getSceneManager()->getMeshCache(); while (mesh_cache->getMeshCount() != 0) { if (scene::IAnimatedMesh *mesh = mesh_cache->getMeshByIndex(0)) - m_rendering_engine->get_mesh_cache()->removeMesh(mesh); + mesh_cache->removeMesh(mesh); } } diff --git a/src/client/renderingengine.h b/src/client/renderingengine.h index fae431f1f..73b55229e 100644 --- a/src/client/renderingengine.h +++ b/src/client/renderingengine.h @@ -26,6 +26,9 @@ with this program; if not, write to the Free Software Foundation, Inc., #include "irrlichttypes_extrabloated.h" #include "debug.h" +namespace irr { namespace scene { +class IMesh; +}} class ITextureSource; class Camera; class Client; @@ -58,6 +61,8 @@ public: static bool print_video_modes(); void cleanupMeshCache(); + void removeMesh(const irr::scene::IMesh* mesh); + static RenderingEngine *get_instance() { return s_singleton; } io::IFileSystem *get_filesystem() @@ -71,12 +76,6 @@ public: return s_singleton->m_device->getVideoDriver(); } - static scene::IMeshCache *get_mesh_cache() - { - sanity_check(s_singleton && s_singleton->m_device); - return s_singleton->m_device->getSceneManager()->getMeshCache(); - } - static scene::ISceneManager *get_scene_manager() { sanity_check(s_singleton && s_singleton->m_device); From 258101a91031f3ff9ee01a974030b02529ffdac0 Mon Sep 17 00:00:00 2001 From: Loic Blot Date: Wed, 28 Apr 2021 12:48:13 +0200 Subject: [PATCH 57/72] refacto: RenderingEngine is now better hidden * No more access to the singleton instance from everywhere (RenderingEngine::get_instance dropped) * RenderingEngine::get_timer_time is now non static * RenderingEngine::draw_menu_scene is now non static * RenderingEngine::draw_scene is now non static * RenderingEngine::{initialize,finalize} are now non static * RenderingEngine::run is now non static * RenderingEngine::getWindowSize now have a static helper. It was mandatory to hide the global get_instance access --- src/client/camera.cpp | 2 +- src/client/clientlauncher.cpp | 57 ++++++++++++++++--------------- src/client/clientlauncher.h | 1 + src/client/game.cpp | 54 +++++++++++++++-------------- src/client/game.h | 4 ++- src/client/gameui.cpp | 6 ++-- src/client/hud.cpp | 6 ++-- src/client/minimap.cpp | 2 +- src/client/renderingengine.cpp | 12 +++---- src/client/renderingengine.h | 51 ++++++++------------------- src/gui/guiEngine.cpp | 30 ++++++++-------- src/gui/guiEngine.h | 3 ++ src/main.cpp | 3 +- src/script/lua_api/l_mainmenu.cpp | 2 +- 14 files changed, 112 insertions(+), 121 deletions(-) diff --git a/src/client/camera.cpp b/src/client/camera.cpp index 5158d0dd1..f6892295b 100644 --- a/src/client/camera.cpp +++ b/src/client/camera.cpp @@ -541,7 +541,7 @@ void Camera::update(LocalPlayer* player, f32 frametime, f32 busytime, f32 tool_r m_curr_fov_degrees = rangelim(m_curr_fov_degrees, 1.0f, 160.0f); // FOV and aspect ratio - const v2u32 &window_size = RenderingEngine::get_instance()->getWindowSize(); + const v2u32 &window_size = RenderingEngine::getWindowSize(); m_aspect = (f32) window_size.X / (f32) window_size.Y; m_fov_y = m_curr_fov_degrees * M_PI / 180.0; // Increase vertical FOV on lower aspect ratios (<16:10) diff --git a/src/client/clientlauncher.cpp b/src/client/clientlauncher.cpp index b1b801947..6db5f2e70 100644 --- a/src/client/clientlauncher.cpp +++ b/src/client/clientlauncher.cpp @@ -80,7 +80,7 @@ ClientLauncher::~ClientLauncher() delete g_fontengine; delete g_gamecallback; - delete RenderingEngine::get_instance(); + delete m_rendering_engine; #if USE_SOUND g_sound_manager_singleton.reset(); @@ -101,7 +101,7 @@ bool ClientLauncher::run(GameStartData &start_data, const Settings &cmd_args) // List video modes if requested if (list_video_modes) - return RenderingEngine::print_video_modes(); + return m_rendering_engine->print_video_modes(); #if USE_SOUND if (g_settings->getBool("enable_sound")) @@ -120,12 +120,12 @@ bool ClientLauncher::run(GameStartData &start_data, const Settings &cmd_args) return true; } - if (RenderingEngine::get_video_driver() == NULL) { + if (m_rendering_engine->get_video_driver() == NULL) { errorstream << "Could not initialize video driver." << std::endl; return false; } - RenderingEngine::get_instance()->setupTopLevelWindow(PROJECT_NAME_C); + m_rendering_engine->setupTopLevelWindow(PROJECT_NAME_C); /* This changes the minimum allowed number of vertices in a VBO. @@ -136,15 +136,15 @@ bool ClientLauncher::run(GameStartData &start_data, const Settings &cmd_args) // Create game callback for menus g_gamecallback = new MainGameCallback(); - RenderingEngine::get_instance()->setResizable(true); + m_rendering_engine->setResizable(true); init_input(); - RenderingEngine::get_scene_manager()->getParameters()-> + m_rendering_engine->get_scene_manager()->getParameters()-> setAttribute(scene::ALLOW_ZWRITE_ON_TRANSPARENT, true); - guienv = RenderingEngine::get_gui_env(); - skin = RenderingEngine::get_gui_env()->getSkin(); + guienv = m_rendering_engine->get_gui_env(); + skin = guienv->getSkin(); skin->setColor(gui::EGDC_BUTTON_TEXT, video::SColor(255, 255, 255, 255)); skin->setColor(gui::EGDC_3D_LIGHT, video::SColor(0, 0, 0, 0)); skin->setColor(gui::EGDC_3D_HIGH_LIGHT, video::SColor(255, 30, 30, 30)); @@ -166,7 +166,7 @@ bool ClientLauncher::run(GameStartData &start_data, const Settings &cmd_args) sprite_path.append("checkbox_16.png"); // Texture dimensions should be a power of 2 gui::IGUISpriteBank *sprites = skin->getSpriteBank(); - video::IVideoDriver *driver = RenderingEngine::get_video_driver(); + video::IVideoDriver *driver = m_rendering_engine->get_video_driver(); video::ITexture *sprite_texture = driver->getTexture(sprite_path.c_str()); if (sprite_texture) { s32 sprite_id = sprites->addTextureAsSprite(sprite_texture); @@ -184,7 +184,7 @@ bool ClientLauncher::run(GameStartData &start_data, const Settings &cmd_args) // Create the menu clouds if (!g_menucloudsmgr) - g_menucloudsmgr = RenderingEngine::get_scene_manager()->createNewSceneManager(); + g_menucloudsmgr = m_rendering_engine->get_scene_manager()->createNewSceneManager(); if (!g_menuclouds) g_menuclouds = new Clouds(g_menucloudsmgr, -1, rand()); g_menuclouds->setHeight(100.0f); @@ -212,11 +212,11 @@ bool ClientLauncher::run(GameStartData &start_data, const Settings &cmd_args) bool retval = true; bool *kill = porting::signal_handler_killstatus(); - while (RenderingEngine::run() && !*kill && + while (m_rendering_engine->run() && !*kill && !g_gamecallback->shutdown_requested) { // Set the window caption const wchar_t *text = wgettext("Main Menu"); - RenderingEngine::get_raw_device()-> + m_rendering_engine->get_raw_device()-> setWindowCaption((utf8_to_wide(PROJECT_NAME_C) + L" " + utf8_to_wide(g_version_hash) + L" [" + text + L"]").c_str()); @@ -224,14 +224,14 @@ bool ClientLauncher::run(GameStartData &start_data, const Settings &cmd_args) try { // This is used for catching disconnects - RenderingEngine::get_gui_env()->clear(); + m_rendering_engine->get_gui_env()->clear(); /* We need some kind of a root node to be able to add custom gui elements directly on the screen. Otherwise they won't be automatically drawn. */ - guiroot = RenderingEngine::get_gui_env()->addStaticText(L"", + guiroot = m_rendering_engine->get_gui_env()->addStaticText(L"", core::rect(0, 0, 10000, 10000)); bool game_has_run = launch_game(error_message, reconnect_requested, @@ -254,29 +254,30 @@ bool ClientLauncher::run(GameStartData &start_data, const Settings &cmd_args) } // Break out of menu-game loop to shut down cleanly - if (!RenderingEngine::get_raw_device()->run() || *kill) { + if (!m_rendering_engine->run() || *kill) { if (!g_settings_path.empty()) g_settings->updateConfigFile(g_settings_path.c_str()); break; } - RenderingEngine::get_video_driver()->setTextureCreationFlag( + m_rendering_engine->get_video_driver()->setTextureCreationFlag( video::ETCF_CREATE_MIP_MAPS, g_settings->getBool("mip_map")); #ifdef HAVE_TOUCHSCREENGUI - receiver->m_touchscreengui = new TouchScreenGUI(RenderingEngine::get_raw_device(), receiver); + receiver->m_touchscreengui = new TouchScreenGUI(m_rendering_engine->get_raw_device(), receiver); g_touchscreengui = receiver->m_touchscreengui; #endif the_game( kill, input, + m_rendering_engine, start_data, error_message, chat_backend, &reconnect_requested ); - RenderingEngine::get_scene_manager()->clear(); + m_rendering_engine->get_scene_manager()->clear(); #ifdef HAVE_TOUCHSCREENGUI delete g_touchscreengui; @@ -344,8 +345,8 @@ void ClientLauncher::init_args(GameStartData &start_data, const Settings &cmd_ar bool ClientLauncher::init_engine() { receiver = new MyEventReceiver(); - new RenderingEngine(receiver); - return RenderingEngine::get_raw_device() != nullptr; + m_rendering_engine = new RenderingEngine(receiver); + return m_rendering_engine->get_raw_device() != nullptr; } void ClientLauncher::init_input() @@ -362,7 +363,7 @@ void ClientLauncher::init_input() // Make sure this is called maximum once per // irrlicht device, otherwise it will give you // multiple events for the same joystick. - if (RenderingEngine::get_raw_device()->activateJoysticks(infos)) { + if (m_rendering_engine->get_raw_device()->activateJoysticks(infos)) { infostream << "Joystick support enabled" << std::endl; joystick_infos.reserve(infos.size()); for (u32 i = 0; i < infos.size(); i++) { @@ -469,7 +470,7 @@ bool ClientLauncher::launch_game(std::string &error_message, start_data.address.empty() && !start_data.name.empty(); } - if (!RenderingEngine::run()) + if (!m_rendering_engine->run()) return false; if (!start_data.isSinglePlayer() && start_data.name.empty()) { @@ -541,14 +542,14 @@ bool ClientLauncher::launch_game(std::string &error_message, void ClientLauncher::main_menu(MainMenuData *menudata) { bool *kill = porting::signal_handler_killstatus(); - video::IVideoDriver *driver = RenderingEngine::get_video_driver(); + video::IVideoDriver *driver = m_rendering_engine->get_video_driver(); infostream << "Waiting for other menus" << std::endl; - while (RenderingEngine::get_raw_device()->run() && !*kill) { + while (m_rendering_engine->run() && !*kill) { if (!isMenuActive()) break; driver->beginScene(true, true, video::SColor(255, 128, 128, 128)); - RenderingEngine::get_gui_env()->drawAll(); + m_rendering_engine->get_gui_env()->drawAll(); driver->endScene(); // On some computers framerate doesn't seem to be automatically limited sleep_ms(25); @@ -557,14 +558,14 @@ void ClientLauncher::main_menu(MainMenuData *menudata) // Cursor can be non-visible when coming from the game #ifndef ANDROID - RenderingEngine::get_raw_device()->getCursorControl()->setVisible(true); + m_rendering_engine->get_raw_device()->getCursorControl()->setVisible(true); #endif /* show main menu */ - GUIEngine mymenu(&input->joystick, guiroot, &g_menumgr, menudata, *kill); + GUIEngine mymenu(&input->joystick, guiroot, m_rendering_engine, &g_menumgr, menudata, *kill); /* leave scene manager in a clean state */ - RenderingEngine::get_scene_manager()->clear(); + m_rendering_engine->get_scene_manager()->clear(); } void ClientLauncher::speed_tests() diff --git a/src/client/clientlauncher.h b/src/client/clientlauncher.h index b280d8e6b..79727e1fe 100644 --- a/src/client/clientlauncher.h +++ b/src/client/clientlauncher.h @@ -49,6 +49,7 @@ private: bool list_video_modes = false; bool skip_main_menu = false; bool random_input = false; + RenderingEngine *m_rendering_engine = nullptr; InputHandler *input = nullptr; MyEventReceiver *receiver = nullptr; gui::IGUISkin *skin = nullptr; diff --git a/src/client/game.cpp b/src/client/game.cpp index 8400d7639..33707df4a 100644 --- a/src/client/game.cpp +++ b/src/client/game.cpp @@ -642,6 +642,7 @@ public: bool startup(bool *kill, InputHandler *input, + RenderingEngine *rendering_engine, const GameStartData &game_params, std::string &error_message, bool *reconnect, @@ -853,6 +854,7 @@ private: these items (e.g. device) */ IrrlichtDevice *device; + RenderingEngine *m_rendering_engine; video::IVideoDriver *driver; scene::ISceneManager *smgr; bool *kill; @@ -994,6 +996,7 @@ Game::~Game() bool Game::startup(bool *kill, InputHandler *input, + RenderingEngine *rendering_engine, const GameStartData &start_data, std::string &error_message, bool *reconnect, @@ -1001,21 +1004,21 @@ bool Game::startup(bool *kill, { // "cache" - this->device = RenderingEngine::get_raw_device(); + m_rendering_engine = rendering_engine; + device = m_rendering_engine->get_raw_device(); this->kill = kill; this->error_message = &error_message; - this->reconnect_requested = reconnect; + reconnect_requested = reconnect; this->input = input; this->chat_backend = chat_backend; - this->simple_singleplayer_mode = start_data.isSinglePlayer(); + simple_singleplayer_mode = start_data.isSinglePlayer(); input->keycache.populate(); driver = device->getVideoDriver(); - smgr = RenderingEngine::get_scene_manager(); + smgr = m_rendering_engine->get_scene_manager(); - RenderingEngine::get_scene_manager()->getParameters()-> - setAttribute(scene::OBJ_LOADER_IGNORE_MATERIAL_FILES, true); + smgr->getParameters()->setAttribute(scene::OBJ_LOADER_IGNORE_MATERIAL_FILES, true); // Reinit runData runData = GameRunData(); @@ -1036,7 +1039,7 @@ bool Game::startup(bool *kill, if (!createClient(start_data)) return false; - RenderingEngine::initialize(client, hud); + m_rendering_engine->initialize(client, hud); return true; } @@ -1055,7 +1058,7 @@ void Game::run() Profiler::GraphValues dummyvalues; g_profiler->graphGet(dummyvalues); - draw_times.last_time = RenderingEngine::get_timer_time(); + draw_times.last_time = m_rendering_engine->get_timer_time(); set_light_table(g_settings->getFloat("display_gamma")); @@ -1067,12 +1070,12 @@ void Game::run() irr::core::dimension2d previous_screen_size(g_settings->getU16("screen_w"), g_settings->getU16("screen_h")); - while (RenderingEngine::run() + while (m_rendering_engine->run() && !(*kill || g_gamecallback->shutdown_requested || (server && server->isShutdownRequested()))) { const irr::core::dimension2d ¤t_screen_size = - RenderingEngine::get_video_driver()->getScreenSize(); + m_rendering_engine->get_video_driver()->getScreenSize(); // Verify if window size has changed and save it if it's the case // Ensure evaluating settings->getBool after verifying screensize // First condition is cheaper @@ -1085,7 +1088,7 @@ void Game::run() } // Calculate dtime = - // RenderingEngine::run() from this iteration + // m_rendering_engine->run() from this iteration // + Sleep time until the wanted FPS are reached limitFps(&draw_times, &dtime); @@ -1134,7 +1137,7 @@ void Game::run() void Game::shutdown() { - RenderingEngine::finalize(); + m_rendering_engine->finalize(); #if IRRLICHT_VERSION_MAJOR == 1 && IRRLICHT_VERSION_MINOR <= 8 if (g_settings->get("3d_mode") == "pageflip") { driver->setRenderTarget(irr::video::ERT_STEREO_BOTH_BUFFERS); @@ -1463,7 +1466,7 @@ bool Game::connectToServer(const GameStartData &start_data, start_data.password, start_data.address, *draw_control, texture_src, shader_src, itemdef_manager, nodedef_manager, sound, eventmgr, - RenderingEngine::get_instance(), connect_address.isIPv6(), m_game_ui.get()); + m_rendering_engine, connect_address.isIPv6(), m_game_ui.get()); client->m_simple_singleplayer_mode = simple_singleplayer_mode; @@ -1485,9 +1488,9 @@ bool Game::connectToServer(const GameStartData &start_data, f32 dtime; f32 wait_time = 0; // in seconds - fps_control.last_time = RenderingEngine::get_timer_time(); + fps_control.last_time = m_rendering_engine->get_timer_time(); - while (RenderingEngine::run()) { + while (m_rendering_engine->run()) { limitFps(&fps_control, &dtime); @@ -1524,7 +1527,7 @@ bool Game::connectToServer(const GameStartData &start_data, if (client->m_is_registration_confirmation_state) { if (registration_confirmation_shown) { // Keep drawing the GUI - RenderingEngine::draw_menu_scene(guienv, dtime, true); + m_rendering_engine->draw_menu_scene(guienv, dtime, true); } else { registration_confirmation_shown = true; (new GUIConfirmRegistration(guienv, guienv->getRootGUIElement(), -1, @@ -1560,9 +1563,9 @@ bool Game::getServerContent(bool *aborted) FpsControl fps_control = { 0 }; f32 dtime; // in seconds - fps_control.last_time = RenderingEngine::get_timer_time(); + fps_control.last_time = m_rendering_engine->get_timer_time(); - while (RenderingEngine::run()) { + while (m_rendering_engine->run()) { limitFps(&fps_control, &dtime); @@ -1600,13 +1603,13 @@ bool Game::getServerContent(bool *aborted) if (!client->itemdefReceived()) { const wchar_t *text = wgettext("Item definitions..."); progress = 25; - RenderingEngine::draw_load_screen(text, guienv, texture_src, + m_rendering_engine->draw_load_screen(text, guienv, texture_src, dtime, progress); delete[] text; } else if (!client->nodedefReceived()) { const wchar_t *text = wgettext("Node definitions..."); progress = 30; - RenderingEngine::draw_load_screen(text, guienv, texture_src, + m_rendering_engine->draw_load_screen(text, guienv, texture_src, dtime, progress); delete[] text; } else { @@ -1633,7 +1636,7 @@ bool Game::getServerContent(bool *aborted) } progress = 30 + client->mediaReceiveProgress() * 35 + 0.5; - RenderingEngine::draw_load_screen(utf8_to_wide(message.str()), guienv, + m_rendering_engine->draw_load_screen(utf8_to_wide(message.str()), guienv, texture_src, dtime, progress); } } @@ -3886,7 +3889,7 @@ void Game::updateFrame(ProfilerGraph *graph, RunStats *stats, f32 dtime, } catch (SettingNotFoundException) { } #endif - RenderingEngine::draw_scene(skycolor, m_game_ui->m_flags.show_hud, + m_rendering_engine->draw_scene(skycolor, m_game_ui->m_flags.show_hud, m_game_ui->m_flags.show_minimap, draw_wield_tool, draw_crosshair); /* @@ -4016,7 +4019,7 @@ inline void Game::limitFps(FpsControl *fps_timings, f32 *dtime) void Game::showOverlayMessage(const char *msg, float dtime, int percent, bool draw_clouds) { const wchar_t *wmsg = wgettext(msg); - RenderingEngine::draw_load_screen(wmsg, guienv, texture_src, dtime, percent, + m_rendering_engine->draw_load_screen(wmsg, guienv, texture_src, dtime, percent, draw_clouds); delete[] wmsg; } @@ -4229,6 +4232,7 @@ void Game::showPauseMenu() void the_game(bool *kill, InputHandler *input, + RenderingEngine *rendering_engine, const GameStartData &start_data, std::string &error_message, ChatBackend &chat_backend, @@ -4243,8 +4247,8 @@ void the_game(bool *kill, try { - if (game.startup(kill, input, start_data, error_message, - reconnect_requested, &chat_backend)) { + if (game.startup(kill, input, rendering_engine, start_data, + error_message, reconnect_requested, &chat_backend)) { game.run(); } diff --git a/src/client/game.h b/src/client/game.h index d04153271..fbbf106db 100644 --- a/src/client/game.h +++ b/src/client/game.h @@ -23,7 +23,8 @@ with this program; if not, write to the Free Software Foundation, Inc., #include class InputHandler; -class ChatBackend; /* to avoid having to include chat.h */ +class ChatBackend; +class RenderingEngine; struct SubgameSpec; struct GameStartData; @@ -45,6 +46,7 @@ struct CameraOrientation { void the_game(bool *kill, InputHandler *input, + RenderingEngine *rendering_engine, const GameStartData &start_data, std::string &error_message, ChatBackend &chat_backend, diff --git a/src/client/gameui.cpp b/src/client/gameui.cpp index 0c08efeb5..ebc6b108c 100644 --- a/src/client/gameui.cpp +++ b/src/client/gameui.cpp @@ -97,7 +97,7 @@ void GameUI::update(const RunStats &stats, Client *client, MapDrawControl *draw_ const CameraOrientation &cam, const PointedThing &pointed_old, const GUIChatConsole *chat_console, float dtime) { - v2u32 screensize = RenderingEngine::get_instance()->getWindowSize(); + v2u32 screensize = RenderingEngine::getWindowSize(); if (m_flags.show_debug) { static float drawtime_avg = 0; @@ -228,7 +228,7 @@ void GameUI::setChatText(const EnrichedString &chat_text, u32 recent_chat_count) if (m_flags.show_debug) chat_y += 2 * g_fontengine->getLineHeight(); - const v2u32 &window_size = RenderingEngine::get_instance()->getWindowSize(); + const v2u32 &window_size = RenderingEngine::getWindowSize(); core::rect chat_size(10, chat_y, window_size.X - 20, 0); @@ -260,7 +260,7 @@ void GameUI::updateProfiler() core::position2di upper_left(6, 50); core::position2di lower_right = upper_left; lower_right.X += size.Width + 10; - lower_right.Y += size.Height; + lower_right.Y += size.Height; m_guitext_profiler->setRelativePosition(core::rect(upper_left, lower_right)); } diff --git a/src/client/hud.cpp b/src/client/hud.cpp index c58c7e822..ceea96832 100644 --- a/src/client/hud.cpp +++ b/src/client/hud.cpp @@ -747,7 +747,7 @@ void Hud::drawHotbar(u16 playeritem) { s32 width = hotbar_itemcount * (m_hotbar_imagesize + m_padding * 2); v2s32 pos = centerlowerpos - v2s32(width / 2, m_hotbar_imagesize + m_padding * 3); - const v2u32 &window_size = RenderingEngine::get_instance()->getWindowSize(); + const v2u32 &window_size = RenderingEngine::getWindowSize(); if ((float) width / (float) window_size.X <= g_settings->getFloat("hud_hotbar_max_width")) { if (player->hud_flags & HUD_FLAG_HOTBAR_VISIBLE) { @@ -874,7 +874,7 @@ void Hud::toggleBlockBounds() void Hud::drawBlockBounds() { if (m_block_bounds_mode == BLOCK_BOUNDS_OFF) { - return; + return; } video::SMaterial old_material = driver->getMaterial2D(); @@ -956,7 +956,7 @@ void Hud::updateSelectionMesh(const v3s16 &camera_offset) } void Hud::resizeHotbar() { - const v2u32 &window_size = RenderingEngine::get_instance()->getWindowSize(); + const v2u32 &window_size = RenderingEngine::getWindowSize(); if (m_screensize != window_size) { m_hotbar_imagesize = floor(HOTBAR_IMAGE_SIZE * diff --git a/src/client/minimap.cpp b/src/client/minimap.cpp index 97977c366..f26aa1c70 100644 --- a/src/client/minimap.cpp +++ b/src/client/minimap.cpp @@ -577,7 +577,7 @@ scene::SMeshBuffer *Minimap::getMinimapMeshBuffer() void Minimap::drawMinimap() { // Non hud managed minimap drawing (legacy minimap) - v2u32 screensize = RenderingEngine::get_instance()->getWindowSize(); + v2u32 screensize = RenderingEngine::getWindowSize(); const u32 size = 0.25 * screensize.Y; drawMinimap(core::rect( diff --git a/src/client/renderingengine.cpp b/src/client/renderingengine.cpp index da9022477..ec8f47576 100644 --- a/src/client/renderingengine.cpp +++ b/src/client/renderingengine.cpp @@ -159,7 +159,7 @@ RenderingEngine::~RenderingEngine() s_singleton = nullptr; } -v2u32 RenderingEngine::getWindowSize() const +v2u32 RenderingEngine::_getWindowSize() const { if (core) return core->getVirtualSize(); @@ -497,7 +497,7 @@ void RenderingEngine::_draw_load_screen(const std::wstring &text, gui::IGUIEnvironment *guienv, ITextureSource *tsrc, float dtime, int percent, bool clouds) { - v2u32 screensize = RenderingEngine::get_instance()->getWindowSize(); + v2u32 screensize = getWindowSize(); v2s32 textsize(g_fontengine->getTextWidth(text), g_fontengine->getLineHeight()); v2s32 center(screensize.X / 2, screensize.Y / 2); @@ -565,7 +565,7 @@ void RenderingEngine::_draw_load_screen(const std::wstring &text, /* Draws the menu scene including (optional) cloud background. */ -void RenderingEngine::_draw_menu_scene(gui::IGUIEnvironment *guienv, +void RenderingEngine::draw_menu_scene(gui::IGUIEnvironment *guienv, float dtime, bool clouds) { bool cloud_menu_background = clouds && g_settings->getBool("menu_clouds"); @@ -613,19 +613,19 @@ std::vector RenderingEngine::getSupportedVideoDrivers return drivers; } -void RenderingEngine::_initialize(Client *client, Hud *hud) +void RenderingEngine::initialize(Client *client, Hud *hud) { const std::string &draw_mode = g_settings->get("3d_mode"); core.reset(createRenderingCore(draw_mode, m_device, client, hud)); core->initialize(); } -void RenderingEngine::_finalize() +void RenderingEngine::finalize() { core.reset(); } -void RenderingEngine::_draw_scene(video::SColor skycolor, bool show_hud, +void RenderingEngine::draw_scene(video::SColor skycolor, bool show_hud, bool show_minimap, bool draw_wield_tool, bool draw_crosshair) { core->draw(skycolor, show_hud, show_minimap, draw_wield_tool, draw_crosshair); diff --git a/src/client/renderingengine.h b/src/client/renderingengine.h index 73b55229e..5462aa667 100644 --- a/src/client/renderingengine.h +++ b/src/client/renderingengine.h @@ -44,7 +44,6 @@ public: RenderingEngine(IEventReceiver *eventReceiver); ~RenderingEngine(); - v2u32 getWindowSize() const; void setResizable(bool resize); video::IVideoDriver *getVideoDriver() { return driver; } @@ -63,7 +62,11 @@ public: void removeMesh(const irr::scene::IMesh* mesh); - static RenderingEngine *get_instance() { return s_singleton; } + static v2u32 getWindowSize() + { + sanity_check(s_singleton); + return s_singleton->_getWindowSize(); + } io::IFileSystem *get_filesystem() { @@ -88,11 +91,9 @@ public: return s_singleton->m_device; } - static u32 get_timer_time() + u32 get_timer_time() { - sanity_check(s_singleton && s_singleton->m_device && - s_singleton->m_device->getTimer()); - return s_singleton->m_device->getTimer()->getTime(); + return m_device->getTimer()->getTime(); } static gui::IGUIEnvironment *get_gui_env() @@ -109,30 +110,16 @@ public: text, guienv, tsrc, dtime, percent, clouds); } - inline static void draw_menu_scene( - gui::IGUIEnvironment *guienv, float dtime, bool clouds) - { - s_singleton->_draw_menu_scene(guienv, dtime, clouds); - } + void draw_menu_scene(gui::IGUIEnvironment *guienv, float dtime, bool clouds); + void draw_scene(video::SColor skycolor, bool show_hud, + bool show_minimap, bool draw_wield_tool, bool draw_crosshair); - inline static void draw_scene(video::SColor skycolor, bool show_hud, - bool show_minimap, bool draw_wield_tool, bool draw_crosshair) - { - s_singleton->_draw_scene(skycolor, show_hud, show_minimap, - draw_wield_tool, draw_crosshair); - } + void initialize(Client *client, Hud *hud); + void finalize(); - inline static void initialize(Client *client, Hud *hud) + bool run() { - s_singleton->_initialize(client, hud); - } - - inline static void finalize() { s_singleton->_finalize(); } - - static bool run() - { - sanity_check(s_singleton && s_singleton->m_device); - return s_singleton->m_device->run(); + return m_device->run(); } static std::vector> getSupportedVideoModes(); @@ -143,15 +130,7 @@ private: ITextureSource *tsrc, float dtime = 0, int percent = 0, bool clouds = true); - void _draw_menu_scene(gui::IGUIEnvironment *guienv, float dtime = 0, - bool clouds = true); - - void _draw_scene(video::SColor skycolor, bool show_hud, bool show_minimap, - bool draw_wield_tool, bool draw_crosshair); - - void _initialize(Client *client, Hud *hud); - - void _finalize(); + v2u32 _getWindowSize() const; std::unique_ptr core; irr::IrrlichtDevice *m_device = nullptr; diff --git a/src/gui/guiEngine.cpp b/src/gui/guiEngine.cpp index 93463ad70..0c7b96492 100644 --- a/src/gui/guiEngine.cpp +++ b/src/gui/guiEngine.cpp @@ -121,12 +121,14 @@ void MenuMusicFetcher::fetchSounds(const std::string &name, /******************************************************************************/ GUIEngine::GUIEngine(JoystickController *joystick, gui::IGUIElement *parent, + RenderingEngine *rendering_engine, IMenuManager *menumgr, MainMenuData *data, bool &kill) : + m_rendering_engine(rendering_engine), m_parent(parent), m_menumanager(menumgr), - m_smgr(RenderingEngine::get_scene_manager()), + m_smgr(rendering_engine->get_scene_manager()), m_data(data), m_kill(kill) { @@ -138,7 +140,7 @@ GUIEngine::GUIEngine(JoystickController *joystick, m_buttonhandler = new TextDestGuiEngine(this); //create texture source - m_texture_source = new MenuTextureSource(RenderingEngine::get_video_driver()); + m_texture_source = new MenuTextureSource(rendering_engine->get_video_driver()); //create soundmanager MenuMusicFetcher soundfetcher; @@ -156,7 +158,7 @@ GUIEngine::GUIEngine(JoystickController *joystick, g_fontengine->getTextHeight()); rect += v2s32(4, 0); - m_irr_toplefttext = gui::StaticText::add(RenderingEngine::get_gui_env(), + m_irr_toplefttext = gui::StaticText::add(rendering_engine->get_gui_env(), m_toplefttext, rect, false, true, 0, -1); //create formspecsource @@ -232,7 +234,7 @@ void GUIEngine::run() { // Always create clouds because they may or may not be // needed based on the game selected - video::IVideoDriver *driver = RenderingEngine::get_video_driver(); + video::IVideoDriver *driver = m_rendering_engine->get_video_driver(); cloudInit(); @@ -259,10 +261,10 @@ void GUIEngine::run() fog_pixelfog, fog_rangefog); } - while (RenderingEngine::run() && (!m_startgame) && (!m_kill)) { + while (m_rendering_engine->run() && (!m_startgame) && (!m_kill)) { const irr::core::dimension2d ¤t_screen_size = - RenderingEngine::get_video_driver()->getScreenSize(); + m_rendering_engine->get_video_driver()->getScreenSize(); // Verify if window size has changed and save it if it's the case // Ensure evaluating settings->getBool after verifying screensize // First condition is cheaper @@ -293,11 +295,11 @@ void GUIEngine::run() drawHeader(driver); drawFooter(driver); - RenderingEngine::get_gui_env()->drawAll(); + m_rendering_engine->get_gui_env()->drawAll(); driver->endScene(); - IrrlichtDevice *device = RenderingEngine::get_raw_device(); + IrrlichtDevice *device = m_rendering_engine->get_raw_device(); u32 frametime_min = 1000 / (device->isWindowFocused() ? g_settings->getFloat("fps_max") : g_settings->getFloat("fps_max_unfocused")); @@ -330,7 +332,7 @@ GUIEngine::~GUIEngine() //clean up texture pointers for (image_definition &texture : m_textures) { if (texture.texture) - RenderingEngine::get_video_driver()->removeTexture(texture.texture); + m_rendering_engine->get_video_driver()->removeTexture(texture.texture); } delete m_texture_source; @@ -350,13 +352,13 @@ void GUIEngine::cloudInit() v3f(0,0,0), v3f(0, 60, 100)); m_cloud.camera->setFarValue(10000); - m_cloud.lasttime = RenderingEngine::get_timer_time(); + m_cloud.lasttime = m_rendering_engine->get_timer_time(); } /******************************************************************************/ void GUIEngine::cloudPreProcess() { - u32 time = RenderingEngine::get_timer_time(); + u32 time = m_rendering_engine->get_timer_time(); if(time > m_cloud.lasttime) m_cloud.dtime = (time - m_cloud.lasttime) / 1000.0; @@ -377,7 +379,7 @@ void GUIEngine::cloudPostProcess(u32 frametime_min, IrrlichtDevice *device) u32 busytime_u32; // not using getRealTime is necessary for wine - u32 time = RenderingEngine::get_timer_time(); + u32 time = m_rendering_engine->get_timer_time(); if(time > m_cloud.lasttime) busytime_u32 = time - m_cloud.lasttime; else @@ -528,7 +530,7 @@ void GUIEngine::drawFooter(video::IVideoDriver *driver) bool GUIEngine::setTexture(texture_layer layer, const std::string &texturepath, bool tile_image, unsigned int minsize) { - video::IVideoDriver *driver = RenderingEngine::get_video_driver(); + video::IVideoDriver *driver = m_rendering_engine->get_video_driver(); if (m_textures[layer].texture) { driver->removeTexture(m_textures[layer].texture); @@ -595,7 +597,7 @@ void GUIEngine::updateTopLeftTextSize() rect += v2s32(4, 0); m_irr_toplefttext->remove(); - m_irr_toplefttext = gui::StaticText::add(RenderingEngine::get_gui_env(), + m_irr_toplefttext = gui::StaticText::add(m_rendering_engine->get_gui_env(), m_toplefttext, rect, false, true, 0, -1); } diff --git a/src/gui/guiEngine.h b/src/gui/guiEngine.h index eef1ad8aa..70abce181 100644 --- a/src/gui/guiEngine.h +++ b/src/gui/guiEngine.h @@ -50,6 +50,7 @@ struct image_definition { /* forward declarations */ /******************************************************************************/ class GUIEngine; +class RenderingEngine; class MainMenuScripting; class Clouds; struct MainMenuData; @@ -150,6 +151,7 @@ public: */ GUIEngine(JoystickController *joystick, gui::IGUIElement *parent, + RenderingEngine *rendering_engine, IMenuManager *menumgr, MainMenuData *data, bool &kill); @@ -188,6 +190,7 @@ private: /** update size of topleftext element */ void updateTopLeftTextSize(); + RenderingEngine *m_rendering_engine = nullptr; /** parent gui element */ gui::IGUIElement *m_parent = nullptr; /** manager to add menus to */ diff --git a/src/main.cpp b/src/main.cpp index 39b441d2c..7f96836b5 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -225,8 +225,7 @@ int main(int argc, char *argv[]) return run_dedicated_server(game_params, cmd_args) ? 0 : 1; #ifndef SERVER - ClientLauncher launcher; - retval = launcher.run(game_params, cmd_args) ? 0 : 1; + retval = ClientLauncher().run(game_params, cmd_args) ? 0 : 1; #else retval = 0; #endif diff --git a/src/script/lua_api/l_mainmenu.cpp b/src/script/lua_api/l_mainmenu.cpp index 1e8dea909..a5bb5f261 100644 --- a/src/script/lua_api/l_mainmenu.cpp +++ b/src/script/lua_api/l_mainmenu.cpp @@ -790,7 +790,7 @@ int ModApiMainMenu::l_get_screen_info(lua_State *L) lua_pushnumber(L,RenderingEngine::getDisplayDensity()); lua_settable(L, top); - const v2u32 &window_size = RenderingEngine::get_instance()->getWindowSize(); + const v2u32 &window_size = RenderingEngine::getWindowSize(); lua_pushstring(L,"window_width"); lua_pushnumber(L, window_size.X); lua_settable(L, top); From 1bc855646e2c920c1df55bb73416f72295c020f4 Mon Sep 17 00:00:00 2001 From: Loic Blot Date: Thu, 29 Apr 2021 08:51:17 +0200 Subject: [PATCH 58/72] refacto: protect some RenderingEngine::get_scene_manager * protect it from Camera, Sky, ClientMap object calls * rename Game::sky to Game::m_sky --- src/client/camera.cpp | 4 +- src/client/camera.h | 3 +- src/client/client.cpp | 2 +- src/client/clientmap.cpp | 7 ++-- src/client/clientmap.h | 1 + src/client/game.cpp | 83 ++++++++++++++++++++-------------------- src/client/sky.cpp | 6 +-- src/client/sky.h | 2 +- 8 files changed, 56 insertions(+), 52 deletions(-) diff --git a/src/client/camera.cpp b/src/client/camera.cpp index f6892295b..2629a6359 100644 --- a/src/client/camera.cpp +++ b/src/client/camera.cpp @@ -43,11 +43,11 @@ with this program; if not, write to the Free Software Foundation, Inc., #define WIELDMESH_AMPLITUDE_X 7.0f #define WIELDMESH_AMPLITUDE_Y 10.0f -Camera::Camera(MapDrawControl &draw_control, Client *client): +Camera::Camera(MapDrawControl &draw_control, Client *client, RenderingEngine *rendering_engine): m_draw_control(draw_control), m_client(client) { - scene::ISceneManager *smgr = RenderingEngine::get_scene_manager(); + auto smgr = rendering_engine->get_scene_manager(); // note: making the camera node a child of the player node // would lead to unexpected behaviour, so we don't do that. m_playernode = smgr->addEmptySceneNode(smgr->getRootSceneNode()); diff --git a/src/client/camera.h b/src/client/camera.h index 6fd8d9aa7..593a97d80 100644 --- a/src/client/camera.h +++ b/src/client/camera.h @@ -30,6 +30,7 @@ with this program; if not, write to the Free Software Foundation, Inc., class LocalPlayer; struct MapDrawControl; class Client; +class RenderingEngine; class WieldMeshSceneNode; struct Nametag @@ -78,7 +79,7 @@ enum CameraMode {CAMERA_MODE_FIRST, CAMERA_MODE_THIRD, CAMERA_MODE_THIRD_FRONT}; class Camera { public: - Camera(MapDrawControl &draw_control, Client *client); + Camera(MapDrawControl &draw_control, Client *client, RenderingEngine *rendering_engine); ~Camera(); // Get camera scene node. diff --git a/src/client/client.cpp b/src/client/client.cpp index 15979df02..d1c5cd948 100644 --- a/src/client/client.cpp +++ b/src/client/client.cpp @@ -110,7 +110,7 @@ Client::Client( m_rendering_engine(rendering_engine), m_mesh_update_thread(this), m_env( - new ClientMap(this, control, 666), + new ClientMap(this, rendering_engine, control, 666), tsrc, this ), m_particle_manager(&m_env), diff --git a/src/client/clientmap.cpp b/src/client/clientmap.cpp index c5b47532c..6dc535898 100644 --- a/src/client/clientmap.cpp +++ b/src/client/clientmap.cpp @@ -64,12 +64,13 @@ void MeshBufListList::add(scene::IMeshBuffer *buf, v3s16 position, u8 layer) ClientMap::ClientMap( Client *client, + RenderingEngine *rendering_engine, MapDrawControl &control, s32 id ): Map(client), - scene::ISceneNode(RenderingEngine::get_scene_manager()->getRootSceneNode(), - RenderingEngine::get_scene_manager(), id), + scene::ISceneNode(rendering_engine->get_scene_manager()->getRootSceneNode(), + rendering_engine->get_scene_manager(), id), m_client(client), m_control(control) { @@ -317,7 +318,7 @@ void ClientMap::renderMap(video::IVideoDriver* driver, s32 pass) v3f block_pos_r = intToFloat(block->getPosRelative() + MAP_BLOCKSIZE / 2, BS); float d = camera_position.getDistanceFrom(block_pos_r); d = MYMAX(0,d - BLOCK_MAX_RADIUS); - + // Mesh animation if (pass == scene::ESNRP_SOLID) { //MutexAutoLock lock(block->mesh_mutex); diff --git a/src/client/clientmap.h b/src/client/clientmap.h index 57cc4427e..80add4a44 100644 --- a/src/client/clientmap.h +++ b/src/client/clientmap.h @@ -68,6 +68,7 @@ class ClientMap : public Map, public scene::ISceneNode public: ClientMap( Client *client, + RenderingEngine *rendering_engine, MapDrawControl &control, s32 id ); diff --git a/src/client/game.cpp b/src/client/game.cpp index 33707df4a..aa794a755 100644 --- a/src/client/game.cpp +++ b/src/client/game.cpp @@ -839,7 +839,7 @@ private: MapDrawControl *draw_control = nullptr; Camera *camera = nullptr; Clouds *clouds = nullptr; // Free using ->Drop() - Sky *sky = nullptr; // Free using ->Drop() + Sky *m_sky = nullptr; // Free using ->Drop() Hud *hud = nullptr; Minimap *mapper = nullptr; @@ -1159,8 +1159,8 @@ void Game::shutdown() if (gui_chat_console) gui_chat_console->drop(); - if (sky) - sky->drop(); + if (m_sky) + m_sky->drop(); /* cleanup menus */ while (g_menumgr.menuCount() > 0) { @@ -1293,7 +1293,7 @@ bool Game::createClient(const GameStartData &start_data) { showOverlayMessage(N_("Creating client..."), 0, 10); - draw_control = new MapDrawControl; + draw_control = new MapDrawControl(); if (!draw_control) return false; @@ -1334,7 +1334,7 @@ bool Game::createClient(const GameStartData &start_data) /* Camera */ - camera = new Camera(*draw_control, client); + camera = new Camera(*draw_control, client, m_rendering_engine); if (!camera->successfullyCreated(*error_message)) return false; client->setCamera(camera); @@ -1346,8 +1346,8 @@ bool Game::createClient(const GameStartData &start_data) /* Skybox */ - sky = new Sky(-1, texture_src, shader_src); - scsf->setSky(sky); + m_sky = new Sky(-1, m_rendering_engine, texture_src, shader_src); + scsf->setSky(m_sky); skybox = NULL; // This is used/set later on in the main run loop /* Pre-calculated values @@ -2754,23 +2754,23 @@ void Game::handleClientEvent_HudChange(ClientEvent *event, CameraOrientation *ca void Game::handleClientEvent_SetSky(ClientEvent *event, CameraOrientation *cam) { - sky->setVisible(false); + m_sky->setVisible(false); // Whether clouds are visible in front of a custom skybox. - sky->setCloudsEnabled(event->set_sky->clouds); + m_sky->setCloudsEnabled(event->set_sky->clouds); if (skybox) { skybox->remove(); skybox = NULL; } // Clear the old textures out in case we switch rendering type. - sky->clearSkyboxTextures(); + m_sky->clearSkyboxTextures(); // Handle according to type if (event->set_sky->type == "regular") { // Shows the mesh skybox - sky->setVisible(true); + m_sky->setVisible(true); // Update mesh based skybox colours if applicable. - sky->setSkyColors(event->set_sky->sky_color); - sky->setHorizonTint( + m_sky->setSkyColors(event->set_sky->sky_color); + m_sky->setHorizonTint( event->set_sky->fog_sun_tint, event->set_sky->fog_moon_tint, event->set_sky->fog_tint_type @@ -2778,61 +2778,62 @@ void Game::handleClientEvent_SetSky(ClientEvent *event, CameraOrientation *cam) } else if (event->set_sky->type == "skybox" && event->set_sky->textures.size() == 6) { // Disable the dyanmic mesh skybox: - sky->setVisible(false); + m_sky->setVisible(false); // Set fog colors: - sky->setFallbackBgColor(event->set_sky->bgcolor); + m_sky->setFallbackBgColor(event->set_sky->bgcolor); // Set sunrise and sunset fog tinting: - sky->setHorizonTint( + m_sky->setHorizonTint( event->set_sky->fog_sun_tint, event->set_sky->fog_moon_tint, event->set_sky->fog_tint_type ); // Add textures to skybox. for (int i = 0; i < 6; i++) - sky->addTextureToSkybox(event->set_sky->textures[i], i, texture_src); + m_sky->addTextureToSkybox(event->set_sky->textures[i], i, texture_src); } else { // Handle everything else as plain color. if (event->set_sky->type != "plain") infostream << "Unknown sky type: " << (event->set_sky->type) << std::endl; - sky->setVisible(false); - sky->setFallbackBgColor(event->set_sky->bgcolor); + m_sky->setVisible(false); + m_sky->setFallbackBgColor(event->set_sky->bgcolor); // Disable directional sun/moon tinting on plain or invalid skyboxes. - sky->setHorizonTint( + m_sky->setHorizonTint( event->set_sky->bgcolor, event->set_sky->bgcolor, "custom" ); } + delete event->set_sky; } void Game::handleClientEvent_SetSun(ClientEvent *event, CameraOrientation *cam) { - sky->setSunVisible(event->sun_params->visible); - sky->setSunTexture(event->sun_params->texture, + m_sky->setSunVisible(event->sun_params->visible); + m_sky->setSunTexture(event->sun_params->texture, event->sun_params->tonemap, texture_src); - sky->setSunScale(event->sun_params->scale); - sky->setSunriseVisible(event->sun_params->sunrise_visible); - sky->setSunriseTexture(event->sun_params->sunrise, texture_src); + m_sky->setSunScale(event->sun_params->scale); + m_sky->setSunriseVisible(event->sun_params->sunrise_visible); + m_sky->setSunriseTexture(event->sun_params->sunrise, texture_src); delete event->sun_params; } void Game::handleClientEvent_SetMoon(ClientEvent *event, CameraOrientation *cam) { - sky->setMoonVisible(event->moon_params->visible); - sky->setMoonTexture(event->moon_params->texture, + m_sky->setMoonVisible(event->moon_params->visible); + m_sky->setMoonTexture(event->moon_params->texture, event->moon_params->tonemap, texture_src); - sky->setMoonScale(event->moon_params->scale); + m_sky->setMoonScale(event->moon_params->scale); delete event->moon_params; } void Game::handleClientEvent_SetStars(ClientEvent *event, CameraOrientation *cam) { - sky->setStarsVisible(event->star_params->visible); - sky->setStarCount(event->star_params->count, false); - sky->setStarColor(event->star_params->starcolor); - sky->setStarScale(event->star_params->scale); + m_sky->setStarsVisible(event->star_params->visible); + m_sky->setStarCount(event->star_params->count, false); + m_sky->setStarColor(event->star_params->starcolor); + m_sky->setStarScale(event->star_params->scale); delete event->star_params; } @@ -3709,7 +3710,7 @@ void Game::updateFrame(ProfilerGraph *graph, RunStats *stats, f32 dtime, direct_brightness = time_brightness; sunlight_seen = true; } else { - float old_brightness = sky->getBrightness(); + float old_brightness = m_sky->getBrightness(); direct_brightness = client->getEnv().getClientMap() .getBackgroundBrightness(MYMIN(runData.fog_range * 1.2, 60 * BS), daynight_ratio, (int)(old_brightness * 255.5), &sunlight_seen) @@ -3736,7 +3737,7 @@ void Game::updateFrame(ProfilerGraph *graph, RunStats *stats, f32 dtime, runData.time_of_day_smooth = time_of_day_smooth; - sky->update(time_of_day_smooth, time_brightness, direct_brightness, + m_sky->update(time_of_day_smooth, time_brightness, direct_brightness, sunlight_seen, camera->getCameraMode(), player->getYaw(), player->getPitch()); @@ -3744,7 +3745,7 @@ void Game::updateFrame(ProfilerGraph *graph, RunStats *stats, f32 dtime, Update clouds */ if (clouds) { - if (sky->getCloudsVisible()) { + if (m_sky->getCloudsVisible()) { clouds->setVisible(true); clouds->step(dtime); // camera->getPosition is not enough for 3rd person views @@ -3754,14 +3755,14 @@ void Game::updateFrame(ProfilerGraph *graph, RunStats *stats, f32 dtime, camera_node_position.Y = camera_node_position.Y + camera_offset.Y * BS; camera_node_position.Z = camera_node_position.Z + camera_offset.Z * BS; clouds->update(camera_node_position, - sky->getCloudColor()); + m_sky->getCloudColor()); if (clouds->isCameraInsideCloud() && m_cache_enable_fog) { // if inside clouds, and fog enabled, use that as sky // color(s) video::SColor clouds_dark = clouds->getColor() .getInterpolated(video::SColor(255, 0, 0, 0), 0.9); - sky->overrideColors(clouds_dark, clouds->getColor()); - sky->setInClouds(true); + m_sky->overrideColors(clouds_dark, clouds->getColor()); + m_sky->setInClouds(true); runData.fog_range = std::fmin(runData.fog_range * 0.5f, 32.0f * BS); // do not draw clouds after all clouds->setVisible(false); @@ -3782,7 +3783,7 @@ void Game::updateFrame(ProfilerGraph *graph, RunStats *stats, f32 dtime, if (m_cache_enable_fog) { driver->setFog( - sky->getBgColor(), + m_sky->getBgColor(), video::EFT_FOG_LINEAR, runData.fog_range * m_cache_fog_start, runData.fog_range * 1.0, @@ -3792,7 +3793,7 @@ void Game::updateFrame(ProfilerGraph *graph, RunStats *stats, f32 dtime, ); } else { driver->setFog( - sky->getBgColor(), + m_sky->getBgColor(), video::EFT_FOG_LINEAR, 100000 * BS, 110000 * BS, @@ -3872,7 +3873,7 @@ void Game::updateFrame(ProfilerGraph *graph, RunStats *stats, f32 dtime, /* Drawing begins */ - const video::SColor &skycolor = sky->getSkyColor(); + const video::SColor &skycolor = m_sky->getSkyColor(); TimeTaker tt_draw("Draw scene"); driver->beginScene(true, true, skycolor); diff --git a/src/client/sky.cpp b/src/client/sky.cpp index 46a3f2621..47296a7a5 100644 --- a/src/client/sky.cpp +++ b/src/client/sky.cpp @@ -53,9 +53,9 @@ static video::SMaterial baseMaterial() return mat; }; -Sky::Sky(s32 id, ITextureSource *tsrc, IShaderSource *ssrc) : - scene::ISceneNode(RenderingEngine::get_scene_manager()->getRootSceneNode(), - RenderingEngine::get_scene_manager(), id) +Sky::Sky(s32 id, RenderingEngine *rendering_engine, ITextureSource *tsrc, IShaderSource *ssrc) : + scene::ISceneNode(rendering_engine->get_scene_manager()->getRootSceneNode(), + rendering_engine->get_scene_manager(), id) { m_seed = (u64)myrand() << 32 | myrand(); diff --git a/src/client/sky.h b/src/client/sky.h index dc7da5021..121a16bb7 100644 --- a/src/client/sky.h +++ b/src/client/sky.h @@ -36,7 +36,7 @@ class Sky : public scene::ISceneNode { public: //! constructor - Sky(s32 id, ITextureSource *tsrc, IShaderSource *ssrc); + Sky(s32 id, RenderingEngine *rendering_engine, ITextureSource *tsrc, IShaderSource *ssrc); virtual void OnRegisterSceneNode(); From 809e68fdc0f7855730ee3409e6f1ddfe975b671f Mon Sep 17 00:00:00 2001 From: Loic Blot Date: Thu, 29 Apr 2021 09:07:36 +0200 Subject: [PATCH 59/72] refacto: don't use RenderingEngine singleton on CAO * we don't need on CAO side more than SceneManager, and temporary. Pass only required SceneManager as a parameter to build CAO and add them to the current scene * Use temporary the RenderingEngine singleton from ClientEnvironment, waitfor for better solution * Make ClientActiveObject::addToScene virtual function mandatory to be defined by children to ensure we don't forget to properly define it --- src/client/clientenvironment.cpp | 2 +- src/client/clientobject.h | 6 ++++- src/client/content_cao.cpp | 30 +++++++++------------ src/client/content_cao.h | 2 +- src/unittest/test_clientactiveobjectmgr.cpp | 1 + 5 files changed, 20 insertions(+), 21 deletions(-) diff --git a/src/client/clientenvironment.cpp b/src/client/clientenvironment.cpp index 1bdf5390d..9c40484bf 100644 --- a/src/client/clientenvironment.cpp +++ b/src/client/clientenvironment.cpp @@ -352,7 +352,7 @@ u16 ClientEnvironment::addActiveObject(ClientActiveObject *object) if (!m_ao_manager.registerObject(object)) return 0; - object->addToScene(m_texturesource); + object->addToScene(m_texturesource, RenderingEngine::get_scene_manager()); // Update lighting immediately object->updateLight(getDayNightRatio()); diff --git a/src/client/clientobject.h b/src/client/clientobject.h index ecd8059ef..dbc2f22cf 100644 --- a/src/client/clientobject.h +++ b/src/client/clientobject.h @@ -33,13 +33,17 @@ class LocalPlayer; struct ItemStack; class WieldMeshSceneNode; +namespace irr { namespace scene { + class ISceneManager; +}} + class ClientActiveObject : public ActiveObject { public: ClientActiveObject(u16 id, Client *client, ClientEnvironment *env); virtual ~ClientActiveObject(); - virtual void addToScene(ITextureSource *tsrc) {} + virtual void addToScene(ITextureSource *tsrc, irr::scene::ISceneManager *smgr) = 0; virtual void removeFromScene(bool permanent) {} virtual void updateLight(u32 day_night_ratio) {} diff --git a/src/client/content_cao.cpp b/src/client/content_cao.cpp index 63b8821f4..a2fbbf001 100644 --- a/src/client/content_cao.cpp +++ b/src/client/content_cao.cpp @@ -24,7 +24,6 @@ with this program; if not, write to the Free Software Foundation, Inc., #include #include #include "client/client.h" -#include "client/renderingengine.h" #include "client/sound.h" #include "client/tile.h" #include "util/basic_macros.h" @@ -189,7 +188,7 @@ public: static ClientActiveObject* create(Client *client, ClientEnvironment *env); - void addToScene(ITextureSource *tsrc); + void addToScene(ITextureSource *tsrc, irr::scene::ISceneManager *smgr); void removeFromScene(bool permanent); void updateLight(u32 day_night_ratio); void updateNodePos(); @@ -220,7 +219,7 @@ ClientActiveObject* TestCAO::create(Client *client, ClientEnvironment *env) return new TestCAO(client, env); } -void TestCAO::addToScene(ITextureSource *tsrc) +void TestCAO::addToScene(ITextureSource *tsrc, irr::scene::ISceneManager *smgr) { if(m_node != NULL) return; @@ -249,7 +248,7 @@ void TestCAO::addToScene(ITextureSource *tsrc) // Add to mesh mesh->addMeshBuffer(buf); buf->drop(); - m_node = RenderingEngine::get_scene_manager()->addMeshSceneNode(mesh, NULL); + m_node = smgr->addMeshSceneNode(mesh, NULL); mesh->drop(); updateNodePos(); } @@ -591,9 +590,9 @@ void GenericCAO::removeFromScene(bool permanent) m_client->getMinimap()->removeMarker(&m_marker); } -void GenericCAO::addToScene(ITextureSource *tsrc) +void GenericCAO::addToScene(ITextureSource *tsrc, irr::scene::ISceneManager *smgr) { - m_smgr = RenderingEngine::get_scene_manager(); + m_smgr = smgr; if (getSceneNode() != NULL) { return; @@ -625,8 +624,7 @@ void GenericCAO::addToScene(ITextureSource *tsrc) } auto grabMatrixNode = [this] { - m_matrixnode = RenderingEngine::get_scene_manager()-> - addDummyTransformationSceneNode(); + m_matrixnode = m_smgr->addDummyTransformationSceneNode(); m_matrixnode->grab(); }; @@ -644,7 +642,7 @@ void GenericCAO::addToScene(ITextureSource *tsrc) if (m_prop.visual == "sprite") { grabMatrixNode(); - m_spritenode = RenderingEngine::get_scene_manager()->addBillboardSceneNode( + m_spritenode = m_smgr->addBillboardSceneNode( m_matrixnode, v2f(1, 1), v3f(0,0,0), -1); m_spritenode->grab(); m_spritenode->setMaterialTexture(0, @@ -729,8 +727,7 @@ void GenericCAO::addToScene(ITextureSource *tsrc) mesh->addMeshBuffer(buf); buf->drop(); } - m_meshnode = RenderingEngine::get_scene_manager()-> - addMeshSceneNode(mesh, m_matrixnode); + m_meshnode = m_smgr->addMeshSceneNode(mesh, m_matrixnode); m_meshnode->grab(); mesh->drop(); // Set it to use the materials of the meshbuffers directly. @@ -739,8 +736,7 @@ void GenericCAO::addToScene(ITextureSource *tsrc) } else if (m_prop.visual == "cube") { grabMatrixNode(); scene::IMesh *mesh = createCubeMesh(v3f(BS,BS,BS)); - m_meshnode = RenderingEngine::get_scene_manager()-> - addMeshSceneNode(mesh, m_matrixnode); + m_meshnode = m_smgr->addMeshSceneNode(mesh, m_matrixnode); m_meshnode->grab(); mesh->drop(); @@ -753,8 +749,7 @@ void GenericCAO::addToScene(ITextureSource *tsrc) grabMatrixNode(); scene::IAnimatedMesh *mesh = m_client->getMesh(m_prop.mesh, true); if (mesh) { - m_animated_meshnode = RenderingEngine::get_scene_manager()-> - addAnimatedMeshSceneNode(mesh, m_matrixnode); + m_animated_meshnode = m_smgr->addAnimatedMeshSceneNode(mesh, m_matrixnode); m_animated_meshnode->grab(); mesh->drop(); // The scene node took hold of it @@ -795,8 +790,7 @@ void GenericCAO::addToScene(ITextureSource *tsrc) infostream << "serialized form: " << m_prop.wield_item << std::endl; item.deSerialize(m_prop.wield_item, m_client->idef()); } - m_wield_meshnode = new WieldMeshSceneNode( - RenderingEngine::get_scene_manager(), -1); + m_wield_meshnode = new WieldMeshSceneNode(m_smgr, -1); m_wield_meshnode->setItem(item, m_client, (m_prop.visual == "wielditem")); @@ -1074,7 +1068,7 @@ void GenericCAO::step(float dtime, ClientEnvironment *env) } removeFromScene(false); - addToScene(m_client->tsrc()); + addToScene(m_client->tsrc(), m_smgr); // Attachments, part 2: Now that the parent has been refreshed, put its attachments back for (u16 cao_id : m_attachment_child_ids) { diff --git a/src/client/content_cao.h b/src/client/content_cao.h index cc026d34e..32ec9c1c3 100644 --- a/src/client/content_cao.h +++ b/src/client/content_cao.h @@ -236,7 +236,7 @@ public: void removeFromScene(bool permanent); - void addToScene(ITextureSource *tsrc); + void addToScene(ITextureSource *tsrc, irr::scene::ISceneManager *smgr); inline void expireVisuals() { diff --git a/src/unittest/test_clientactiveobjectmgr.cpp b/src/unittest/test_clientactiveobjectmgr.cpp index 4d2846c8d..a43855c19 100644 --- a/src/unittest/test_clientactiveobjectmgr.cpp +++ b/src/unittest/test_clientactiveobjectmgr.cpp @@ -29,6 +29,7 @@ public: TestClientActiveObject() : ClientActiveObject(0, nullptr, nullptr) {} ~TestClientActiveObject() = default; ActiveObjectType getType() const { return ACTIVEOBJECT_TYPE_TEST; } + virtual void addToScene(ITextureSource *tsrc, irr::scene::ISceneManager *smgr) {} }; class TestClientActiveObjectMgr : public TestBase From a47a00228b7be97a740081ec9ed86f108021ad6d Mon Sep 17 00:00:00 2001 From: Loic Blot Date: Thu, 29 Apr 2021 09:20:01 +0200 Subject: [PATCH 60/72] refacto: drop unused Hud::smgr --- src/client/hud.h | 1 - 1 file changed, 1 deletion(-) diff --git a/src/client/hud.h b/src/client/hud.h index 7046a16fb..cbfdf1ba3 100644 --- a/src/client/hud.h +++ b/src/client/hud.h @@ -36,7 +36,6 @@ class Hud { public: video::IVideoDriver *driver; - scene::ISceneManager *smgr; gui::IGUIEnvironment *guienv; Client *client; LocalPlayer *player; From ccdd886e273ec2fa5f8cfe1d1f474914eccb2abf Mon Sep 17 00:00:00 2001 From: Loic Blot Date: Thu, 29 Apr 2021 09:30:19 +0200 Subject: [PATCH 61/72] refacto: Hud: make driver, client, player, inventory, tsrc private & drop unused guienv also fix c_content.h, on client it includes the src/client/hud.h instead of src/hud.h, which leads to wrong file dependency on the lua stack --- src/client/game.cpp | 2 +- src/client/hud.cpp | 7 +++---- src/client/hud.h | 15 +++++++-------- src/script/common/c_content.h | 2 +- 4 files changed, 12 insertions(+), 14 deletions(-) diff --git a/src/client/game.cpp b/src/client/game.cpp index aa794a755..81508f5f4 100644 --- a/src/client/game.cpp +++ b/src/client/game.cpp @@ -1389,7 +1389,7 @@ bool Game::createClient(const GameStartData &start_data) player->hurt_tilt_timer = 0; player->hurt_tilt_strength = 0; - hud = new Hud(guienv, client, player, &player->inventory); + hud = new Hud(client, player, &player->inventory); mapper = client->getMinimap(); diff --git a/src/client/hud.cpp b/src/client/hud.cpp index ceea96832..7f044cccd 100644 --- a/src/client/hud.cpp +++ b/src/client/hud.cpp @@ -45,11 +45,10 @@ with this program; if not, write to the Free Software Foundation, Inc., #define OBJECT_CROSSHAIR_LINE_SIZE 8 #define CROSSHAIR_LINE_SIZE 10 -Hud::Hud(gui::IGUIEnvironment *guienv, Client *client, LocalPlayer *player, +Hud::Hud(Client *client, LocalPlayer *player, Inventory *inventory) { driver = RenderingEngine::get_video_driver(); - this->guienv = guienv; this->client = client; this->player = player; this->inventory = inventory; @@ -315,7 +314,7 @@ bool Hud::calculateScreenPos(const v3s16 &camera_offset, HudElement *e, v2s32 *p { v3f w_pos = e->world_pos * BS; scene::ICameraSceneNode* camera = - RenderingEngine::get_scene_manager()->getActiveCamera(); + client->getSceneManager()->getActiveCamera(); w_pos -= intToFloat(camera_offset, BS); core::matrix4 trans = camera->getProjectionMatrix(); trans *= camera->getViewMatrix(); @@ -475,7 +474,7 @@ void Hud::drawLuaElements(const v3s16 &camera_offset) // Angle according to camera view v3f fore(0.f, 0.f, 1.f); - scene::ICameraSceneNode *cam = RenderingEngine::get_scene_manager()->getActiveCamera(); + scene::ICameraSceneNode *cam = client->getSceneManager()->getActiveCamera(); cam->getAbsoluteTransformation().rotateVect(fore); int angle = - fore.getHorizontalAngle().Y; diff --git a/src/client/hud.h b/src/client/hud.h index cbfdf1ba3..d341105d2 100644 --- a/src/client/hud.h +++ b/src/client/hud.h @@ -35,13 +35,6 @@ struct ItemStack; class Hud { public: - video::IVideoDriver *driver; - gui::IGUIEnvironment *guienv; - Client *client; - LocalPlayer *player; - Inventory *inventory; - ITextureSource *tsrc; - video::SColor crosshair_argb; video::SColor selectionbox_argb; @@ -54,7 +47,7 @@ public: bool pointing_at_object = false; - Hud(gui::IGUIEnvironment *guienv, Client *client, LocalPlayer *player, + Hud(Client *client, LocalPlayer *player, Inventory *inventory); ~Hud(); @@ -105,6 +98,12 @@ private: void drawCompassRotate(HudElement *e, video::ITexture *texture, const core::rect &rect, int way); + Client *client = nullptr; + video::IVideoDriver *driver = nullptr; + LocalPlayer *player = nullptr; + Inventory *inventory = nullptr; + ITextureSource *tsrc = nullptr; + float m_hud_scaling; // cached minetest setting float m_scale_factor; v3s16 m_camera_offset; diff --git a/src/script/common/c_content.h b/src/script/common/c_content.h index 29d576355..f54490e3a 100644 --- a/src/script/common/c_content.h +++ b/src/script/common/c_content.h @@ -39,7 +39,7 @@ extern "C" { #include "itemgroup.h" #include "itemdef.h" #include "c_types.h" -#include "hud.h" +#include "../../hud.h" namespace Json { class Value; } From 5a02c376ea5f2e7f1dd0a2bd4f08bf953ed4bfc8 Mon Sep 17 00:00:00 2001 From: Loic Blot Date: Thu, 29 Apr 2021 09:40:56 +0200 Subject: [PATCH 62/72] refacto: RenderingEngine::get_scene_manager() is now not callable from singleton This permits to make evidence that we have some bad object passing on various code parts. I fixed majority of them to reduce the scope of passed objects Unfortunately, for some edge cases i should have to expose ISceneManager from client, this should be fixed in the future when our POO will be cleaner client side (we have a mix of rendering and processing in majority of the client objects, it works but it's not clean) --- src/client/client.cpp | 5 +++++ src/client/client.h | 1 + src/client/clientenvironment.cpp | 2 +- src/client/content_mapblock.cpp | 16 +++++++--------- src/client/content_mapblock.h | 3 ++- src/client/mapblock_mesh.cpp | 4 ++-- src/client/particles.cpp | 4 ++-- src/client/renderingengine.h | 5 ++--- src/client/wieldmesh.cpp | 5 +++-- src/gui/guiFormSpecMenu.cpp | 2 +- src/nodedef.cpp | 4 ++-- 11 files changed, 28 insertions(+), 23 deletions(-) diff --git a/src/client/client.cpp b/src/client/client.cpp index d1c5cd948..2f4f2aac5 100644 --- a/src/client/client.cpp +++ b/src/client/client.cpp @@ -1475,6 +1475,11 @@ bool Client::updateWieldedItem() return true; } +irr::scene::ISceneManager* Client::getSceneManager() +{ + return m_rendering_engine->get_scene_manager(); +} + Inventory* Client::getInventory(const InventoryLocation &loc) { switch(loc.type){ diff --git a/src/client/client.h b/src/client/client.h index bcb7d6b09..be5970160 100644 --- a/src/client/client.h +++ b/src/client/client.h @@ -355,6 +355,7 @@ public: void setCamera(Camera* camera) { m_camera = camera; } Camera* getCamera () { return m_camera; } + irr::scene::ISceneManager *getSceneManager(); bool shouldShowMinimap() const; diff --git a/src/client/clientenvironment.cpp b/src/client/clientenvironment.cpp index 9c40484bf..7e3867537 100644 --- a/src/client/clientenvironment.cpp +++ b/src/client/clientenvironment.cpp @@ -352,7 +352,7 @@ u16 ClientEnvironment::addActiveObject(ClientActiveObject *object) if (!m_ao_manager.registerObject(object)) return 0; - object->addToScene(m_texturesource, RenderingEngine::get_scene_manager()); + object->addToScene(m_texturesource, m_client->getSceneManager()); // Update lighting immediately object->updateLight(getDayNightRatio()); diff --git a/src/client/content_mapblock.cpp b/src/client/content_mapblock.cpp index ce7235bca..e530f3d7f 100644 --- a/src/client/content_mapblock.cpp +++ b/src/client/content_mapblock.cpp @@ -60,18 +60,16 @@ static constexpr u16 quad_indices[] = {0, 1, 2, 2, 3, 0}; const std::string MapblockMeshGenerator::raillike_groupname = "connect_to_raillike"; -MapblockMeshGenerator::MapblockMeshGenerator(MeshMakeData *input, MeshCollector *output) +MapblockMeshGenerator::MapblockMeshGenerator(MeshMakeData *input, MeshCollector *output, + irr::scene::IMeshManipulator *mm): + data(input), + collector(output), + nodedef(data->m_client->ndef()), + meshmanip(mm), + blockpos_nodes(data->m_blockpos * MAP_BLOCKSIZE) { - data = input; - collector = output; - - nodedef = data->m_client->ndef(); - meshmanip = RenderingEngine::get_scene_manager()->getMeshManipulator(); - enable_mesh_cache = g_settings->getBool("enable_mesh_cache") && !data->m_smooth_lighting; // Mesh cache is not supported with smooth lighting - - blockpos_nodes = data->m_blockpos * MAP_BLOCKSIZE; } void MapblockMeshGenerator::useTile(int index, u8 set_flags, u8 reset_flags, bool special) diff --git a/src/client/content_mapblock.h b/src/client/content_mapblock.h index a6c450d1f..cbee49021 100644 --- a/src/client/content_mapblock.h +++ b/src/client/content_mapblock.h @@ -172,7 +172,8 @@ public: void drawNode(); public: - MapblockMeshGenerator(MeshMakeData *input, MeshCollector *output); + MapblockMeshGenerator(MeshMakeData *input, MeshCollector *output, + irr::scene::IMeshManipulator *mm); void generate(); void renderSingle(content_t node, u8 param2 = 0x00); }; diff --git a/src/client/mapblock_mesh.cpp b/src/client/mapblock_mesh.cpp index 167e1e3ec..72e68fe97 100644 --- a/src/client/mapblock_mesh.cpp +++ b/src/client/mapblock_mesh.cpp @@ -1072,8 +1072,8 @@ MapBlockMesh::MapBlockMesh(MeshMakeData *data, v3s16 camera_offset): */ { - MapblockMeshGenerator generator(data, &collector); - generator.generate(); + MapblockMeshGenerator(data, &collector, + data->m_client->getSceneManager()->getMeshManipulator()).generate(); } /* diff --git a/src/client/particles.cpp b/src/client/particles.cpp index 7acd996dc..288826a5f 100644 --- a/src/client/particles.cpp +++ b/src/client/particles.cpp @@ -64,8 +64,8 @@ Particle::Particle( v2f texsize, video::SColor color ): - scene::ISceneNode(RenderingEngine::get_scene_manager()->getRootSceneNode(), - RenderingEngine::get_scene_manager()) + scene::ISceneNode(((Client *)gamedef)->getSceneManager()->getRootSceneNode(), + ((Client *)gamedef)->getSceneManager()) { // Misc m_gamedef = gamedef; diff --git a/src/client/renderingengine.h b/src/client/renderingengine.h index 5462aa667..4d06baa23 100644 --- a/src/client/renderingengine.h +++ b/src/client/renderingengine.h @@ -79,10 +79,9 @@ public: return s_singleton->m_device->getVideoDriver(); } - static scene::ISceneManager *get_scene_manager() + scene::ISceneManager *get_scene_manager() { - sanity_check(s_singleton && s_singleton->m_device); - return s_singleton->m_device->getSceneManager(); + return m_device->getSceneManager(); } static irr::IrrlichtDevice *get_raw_device() diff --git a/src/client/wieldmesh.cpp b/src/client/wieldmesh.cpp index d9d5e57cd..08fd49fc0 100644 --- a/src/client/wieldmesh.cpp +++ b/src/client/wieldmesh.cpp @@ -307,7 +307,8 @@ static scene::SMesh *createSpecialNodeMesh(Client *client, MapNode n, MeshMakeData mesh_make_data(client, false); MeshCollector collector; mesh_make_data.setSmoothLighting(false); - MapblockMeshGenerator gen(&mesh_make_data, &collector); + MapblockMeshGenerator gen(&mesh_make_data, &collector, + client->getSceneManager()->getMeshManipulator()); if (n.getParam2()) { // keep it @@ -538,7 +539,7 @@ void getItemMesh(Client *client, const ItemStack &item, ItemMesh *result) content_t id = ndef->getId(def.name); FATAL_ERROR_IF(!g_extrusion_mesh_cache, "Extrusion mesh cache is not yet initialized"); - + scene::SMesh *mesh = nullptr; // Shading is on by default diff --git a/src/gui/guiFormSpecMenu.cpp b/src/gui/guiFormSpecMenu.cpp index fd35f2d84..fdcf27a0a 100644 --- a/src/gui/guiFormSpecMenu.cpp +++ b/src/gui/guiFormSpecMenu.cpp @@ -2794,7 +2794,7 @@ void GUIFormSpecMenu::parseModel(parserData *data, const std::string &element) core::rect rect(pos, pos + geom); - GUIScene *e = new GUIScene(Environment, RenderingEngine::get_scene_manager(), + GUIScene *e = new GUIScene(Environment, m_client->getSceneManager(), data->current_parent, rect, spec.fid); auto meshnode = e->setMesh(mesh); diff --git a/src/nodedef.cpp b/src/nodedef.cpp index dd862e606..65a76bcec 100644 --- a/src/nodedef.cpp +++ b/src/nodedef.cpp @@ -1446,8 +1446,8 @@ void NodeDefManager::updateTextures(IGameDef *gamedef, Client *client = (Client *)gamedef; ITextureSource *tsrc = client->tsrc(); IShaderSource *shdsrc = client->getShaderSource(); - scene::IMeshManipulator *meshmanip = - RenderingEngine::get_scene_manager()->getMeshManipulator(); + auto smgr = client->getSceneManager(); + scene::IMeshManipulator *meshmanip = smgr->getMeshManipulator(); TextureSettings tsettings; tsettings.readSettings(); From a93712458b2f8914fdb43ec436c5caf908ba93b8 Mon Sep 17 00:00:00 2001 From: Loic Blot Date: Thu, 29 Apr 2021 09:45:49 +0200 Subject: [PATCH 63/72] fix: don't use RenderingEngine singleton when it's possible --- src/client/client.cpp | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/src/client/client.cpp b/src/client/client.cpp index 2f4f2aac5..1a3a81378 100644 --- a/src/client/client.cpp +++ b/src/client/client.cpp @@ -1771,21 +1771,21 @@ void Client::afterContentReceived() // Rebuild inherited images and recreate textures infostream<<"- Rebuilding images and textures"<draw_load_screen(text, guienv, m_tsrc, 0, 70); m_tsrc->rebuildImagesAndTextures(); delete[] text; // Rebuild shaders infostream<<"- Rebuilding shaders"<draw_load_screen(text, guienv, m_tsrc, 0, 71); m_shsrc->rebuildShaders(); delete[] text; // Update node aliases infostream<<"- Updating node aliases"<draw_load_screen(text, guienv, m_tsrc, 0, 72); m_nodedef->updateAliases(m_itemdef); for (const auto &path : getTextureDirs()) { TextureOverrideSource override_source(path + DIR_DELIM + "override.txt"); @@ -1818,7 +1818,7 @@ void Client::afterContentReceived() m_script->on_client_ready(m_env.getLocalPlayer()); text = wgettext("Done!"); - RenderingEngine::draw_load_screen(text, guienv, m_tsrc, 0, 100); + m_rendering_engine->draw_load_screen(text, guienv, m_tsrc, 0, 100); infostream<<"Client::afterContentReceived() done"<get_video_driver(); irr::video::IImage* const raw_image = driver->createScreenShot(); if (!raw_image) From 48d5abd5bee7a3f956cb2b92745bed6313cf5d8a Mon Sep 17 00:00:00 2001 From: Loic Blot Date: Thu, 29 Apr 2021 20:38:35 +0200 Subject: [PATCH 64/72] refacto: remove get_gui_env & draw_load_screen from RenderingEngine singleton --- src/client/client.cpp | 6 +++--- src/client/client.h | 1 + src/client/game.cpp | 24 ++++++++++++------------ src/client/renderingengine.cpp | 2 +- src/client/renderingengine.h | 17 ++++------------- src/gui/guiEngine.cpp | 1 + src/gui/guiFormSpecMenu.cpp | 12 ++++++------ src/gui/guiFormSpecMenu.h | 6 ++++-- src/nodedef.cpp | 6 ++---- src/nodedef.h | 4 +--- src/script/lua_api/l_mainmenu.cpp | 5 +++-- 11 files changed, 38 insertions(+), 46 deletions(-) diff --git a/src/client/client.cpp b/src/client/client.cpp index 1a3a81378..c7aae1644 100644 --- a/src/client/client.cpp +++ b/src/client/client.cpp @@ -1731,7 +1731,7 @@ typedef struct TextureUpdateArgs { ITextureSource *tsrc; } TextureUpdateArgs; -void texture_update_progress(void *args, u32 progress, u32 max_progress) +void Client::showUpdateProgressTexture(void *args, u32 progress, u32 max_progress) { TextureUpdateArgs* targs = (TextureUpdateArgs*) args; u16 cur_percent = ceil(progress / (double) max_progress * 100.); @@ -1750,7 +1750,7 @@ void texture_update_progress(void *args, u32 progress, u32 max_progress) targs->last_time_ms = time_ms; std::basic_stringstream strm; strm << targs->text_base << " " << targs->last_percent << "%..."; - RenderingEngine::draw_load_screen(strm.str(), targs->guienv, targs->tsrc, 0, + m_rendering_engine->draw_load_screen(strm.str(), targs->guienv, targs->tsrc, 0, 72 + (u16) ((18. / 100.) * (double) targs->last_percent), true); } } @@ -1804,7 +1804,7 @@ void Client::afterContentReceived() tu_args.last_percent = 0; tu_args.text_base = wgettext("Initializing nodes"); tu_args.tsrc = m_tsrc; - m_nodedef->updateTextures(this, texture_update_progress, &tu_args); + m_nodedef->updateTextures(this, &tu_args); delete[] tu_args.text_base; // Start mesh update thread after setting up content definitions diff --git a/src/client/client.h b/src/client/client.h index be5970160..b819d4301 100644 --- a/src/client/client.h +++ b/src/client/client.h @@ -347,6 +347,7 @@ public: float mediaReceiveProgress(); void afterContentReceived(); + void showUpdateProgressTexture(void *args, u32 progress, u32 max_progress); float getRTT(); float getCurRate(); diff --git a/src/client/game.cpp b/src/client/game.cpp index 81508f5f4..2f0f50505 100644 --- a/src/client/game.cpp +++ b/src/client/game.cpp @@ -2047,8 +2047,8 @@ void Game::openInventory() || !client->getScript()->on_inventory_open(fs_src->m_client->getInventory(inventoryloc))) { TextDest *txt_dst = new TextDestPlayerInventory(client); auto *&formspec = m_game_ui->updateFormspec(""); - GUIFormSpecMenu::create(formspec, client, &input->joystick, fs_src, - txt_dst, client->getFormspecPrepend(), sound); + GUIFormSpecMenu::create(formspec, client, m_rendering_engine->get_gui_env(), + &input->joystick, fs_src, txt_dst, client->getFormspecPrepend(), sound); formspec->setFormSpec(fs_src->getForm(), inventoryloc); } @@ -2626,8 +2626,8 @@ void Game::handleClientEvent_ShowFormSpec(ClientEvent *event, CameraOrientation new TextDestPlayerInventory(client, *(event->show_formspec.formname)); auto *&formspec = m_game_ui->updateFormspec(*(event->show_formspec.formname)); - GUIFormSpecMenu::create(formspec, client, &input->joystick, - fs_src, txt_dst, client->getFormspecPrepend(), sound); + GUIFormSpecMenu::create(formspec, client, m_rendering_engine->get_gui_env(), + &input->joystick, fs_src, txt_dst, client->getFormspecPrepend(), sound); } delete event->show_formspec.formspec; @@ -2639,8 +2639,8 @@ void Game::handleClientEvent_ShowLocalFormSpec(ClientEvent *event, CameraOrienta FormspecFormSource *fs_src = new FormspecFormSource(*event->show_formspec.formspec); LocalFormspecHandler *txt_dst = new LocalFormspecHandler(*event->show_formspec.formname, client); - GUIFormSpecMenu::create(m_game_ui->getFormspecGUI(), client, &input->joystick, - fs_src, txt_dst, client->getFormspecPrepend(), sound); + GUIFormSpecMenu::create(m_game_ui->getFormspecGUI(), client, m_rendering_engine->get_gui_env(), + &input->joystick, fs_src, txt_dst, client->getFormspecPrepend(), sound); delete event->show_formspec.formspec; delete event->show_formspec.formname; @@ -3332,8 +3332,8 @@ bool Game::nodePlacement(const ItemDefinition &selected_def, TextDest *txt_dst = new TextDestNodeMetadata(nodepos, client); auto *&formspec = m_game_ui->updateFormspec(""); - GUIFormSpecMenu::create(formspec, client, &input->joystick, fs_src, - txt_dst, client->getFormspecPrepend(), sound); + GUIFormSpecMenu::create(formspec, client, m_rendering_engine->get_gui_env(), + &input->joystick, fs_src, txt_dst, client->getFormspecPrepend(), sound); formspec->setFormSpec(meta->getString("formspec"), inventoryloc); return false; @@ -4082,8 +4082,8 @@ void Game::showDeathFormspec() LocalFormspecHandler *txt_dst = new LocalFormspecHandler("MT_DEATH_SCREEN", client); auto *&formspec = m_game_ui->getFormspecGUI(); - GUIFormSpecMenu::create(formspec, client, &input->joystick, - fs_src, txt_dst, client->getFormspecPrepend(), sound); + GUIFormSpecMenu::create(formspec, client, m_rendering_engine->get_gui_env(), + &input->joystick, fs_src, txt_dst, client->getFormspecPrepend(), sound); formspec->setFocus("btn_respawn"); } @@ -4216,8 +4216,8 @@ void Game::showPauseMenu() LocalFormspecHandler *txt_dst = new LocalFormspecHandler("MT_PAUSE_MENU"); auto *&formspec = m_game_ui->getFormspecGUI(); - GUIFormSpecMenu::create(formspec, client, &input->joystick, - fs_src, txt_dst, client->getFormspecPrepend(), sound); + GUIFormSpecMenu::create(formspec, client, m_rendering_engine->get_gui_env(), + &input->joystick, fs_src, txt_dst, client->getFormspecPrepend(), sound); formspec->setFocus("btn_continue"); formspec->doPause = true; diff --git a/src/client/renderingengine.cpp b/src/client/renderingengine.cpp index ec8f47576..e74446aeb 100644 --- a/src/client/renderingengine.cpp +++ b/src/client/renderingengine.cpp @@ -493,7 +493,7 @@ bool RenderingEngine::setXorgWindowIconFromPath(const std::string &icon_file) Text will be removed when the screen is drawn the next time. Additionally, a progressbar can be drawn when percent is set between 0 and 100. */ -void RenderingEngine::_draw_load_screen(const std::wstring &text, +void RenderingEngine::draw_load_screen(const std::wstring &text, gui::IGUIEnvironment *guienv, ITextureSource *tsrc, float dtime, int percent, bool clouds) { diff --git a/src/client/renderingengine.h b/src/client/renderingengine.h index 4d06baa23..1fd85f5ef 100644 --- a/src/client/renderingengine.h +++ b/src/client/renderingengine.h @@ -95,19 +95,14 @@ public: return m_device->getTimer()->getTime(); } - static gui::IGUIEnvironment *get_gui_env() + gui::IGUIEnvironment *get_gui_env() { - sanity_check(s_singleton && s_singleton->m_device); - return s_singleton->m_device->getGUIEnvironment(); + return m_device->getGUIEnvironment(); } - inline static void draw_load_screen(const std::wstring &text, + void draw_load_screen(const std::wstring &text, gui::IGUIEnvironment *guienv, ITextureSource *tsrc, - float dtime = 0, int percent = 0, bool clouds = true) - { - s_singleton->_draw_load_screen( - text, guienv, tsrc, dtime, percent, clouds); - } + float dtime = 0, int percent = 0, bool clouds = true); void draw_menu_scene(gui::IGUIEnvironment *guienv, float dtime, bool clouds); void draw_scene(video::SColor skycolor, bool show_hud, @@ -125,10 +120,6 @@ public: static std::vector getSupportedVideoDrivers(); private: - void _draw_load_screen(const std::wstring &text, gui::IGUIEnvironment *guienv, - ITextureSource *tsrc, float dtime = 0, int percent = 0, - bool clouds = true); - v2u32 _getWindowSize() const; std::unique_ptr core; diff --git a/src/gui/guiEngine.cpp b/src/gui/guiEngine.cpp index 0c7b96492..694baf482 100644 --- a/src/gui/guiEngine.cpp +++ b/src/gui/guiEngine.cpp @@ -170,6 +170,7 @@ GUIEngine::GUIEngine(JoystickController *joystick, -1, m_menumanager, NULL /* &client */, + m_rendering_engine->get_gui_env(), m_texture_source, m_sound_manager, m_formspecgui, diff --git a/src/gui/guiFormSpecMenu.cpp b/src/gui/guiFormSpecMenu.cpp index fdcf27a0a..c6435804f 100644 --- a/src/gui/guiFormSpecMenu.cpp +++ b/src/gui/guiFormSpecMenu.cpp @@ -96,10 +96,10 @@ inline u32 clamp_u8(s32 value) GUIFormSpecMenu::GUIFormSpecMenu(JoystickController *joystick, gui::IGUIElement *parent, s32 id, IMenuManager *menumgr, - Client *client, ISimpleTextureSource *tsrc, ISoundManager *sound_manager, - IFormSource *fsrc, TextDest *tdst, + Client *client, gui::IGUIEnvironment *guienv, ISimpleTextureSource *tsrc, + ISoundManager *sound_manager, IFormSource *fsrc, TextDest *tdst, const std::string &formspecPrepend, bool remap_dbl_click): - GUIModalMenu(RenderingEngine::get_gui_env(), parent, id, menumgr, remap_dbl_click), + GUIModalMenu(guienv, parent, id, menumgr, remap_dbl_click), m_invmgr(client), m_tsrc(tsrc), m_sound_manager(sound_manager), @@ -145,12 +145,12 @@ GUIFormSpecMenu::~GUIFormSpecMenu() } void GUIFormSpecMenu::create(GUIFormSpecMenu *&cur_formspec, Client *client, - JoystickController *joystick, IFormSource *fs_src, TextDest *txt_dest, - const std::string &formspecPrepend, ISoundManager *sound_manager) + gui::IGUIEnvironment *guienv, JoystickController *joystick, IFormSource *fs_src, + TextDest *txt_dest, const std::string &formspecPrepend, ISoundManager *sound_manager) { if (cur_formspec == nullptr) { cur_formspec = new GUIFormSpecMenu(joystick, guiroot, -1, &g_menumgr, - client, client->getTextureSource(), sound_manager, fs_src, + client, guienv, client->getTextureSource(), sound_manager, fs_src, txt_dest, formspecPrepend); cur_formspec->doPause = false; diff --git a/src/gui/guiFormSpecMenu.h b/src/gui/guiFormSpecMenu.h index d658aba7b..926de66d5 100644 --- a/src/gui/guiFormSpecMenu.h +++ b/src/gui/guiFormSpecMenu.h @@ -152,6 +152,7 @@ public: gui::IGUIElement* parent, s32 id, IMenuManager *menumgr, Client *client, + gui::IGUIEnvironment *guienv, ISimpleTextureSource *tsrc, ISoundManager *sound_manager, IFormSource* fs_src, @@ -162,8 +163,9 @@ public: ~GUIFormSpecMenu(); static void create(GUIFormSpecMenu *&cur_formspec, Client *client, - JoystickController *joystick, IFormSource *fs_src, TextDest *txt_dest, - const std::string &formspecPrepend, ISoundManager *sound_manager); + gui::IGUIEnvironment *guienv, JoystickController *joystick, IFormSource *fs_src, + TextDest *txt_dest, const std::string &formspecPrepend, + ISoundManager *sound_manager); void setFormSpec(const std::string &formspec_string, const InventoryLocation ¤t_inventory_location) diff --git a/src/nodedef.cpp b/src/nodedef.cpp index 65a76bcec..db4043aa1 100644 --- a/src/nodedef.cpp +++ b/src/nodedef.cpp @@ -1435,9 +1435,7 @@ void NodeDefManager::applyTextureOverrides(const std::vector &o } } -void NodeDefManager::updateTextures(IGameDef *gamedef, - void (*progress_callback)(void *progress_args, u32 progress, u32 max_progress), - void *progress_callback_args) +void NodeDefManager::updateTextures(IGameDef *gamedef, void *progress_callback_args) { #ifndef SERVER infostream << "NodeDefManager::updateTextures(): Updating " @@ -1456,7 +1454,7 @@ void NodeDefManager::updateTextures(IGameDef *gamedef, for (u32 i = 0; i < size; i++) { ContentFeatures *f = &(m_content_features[i]); f->updateTextures(tsrc, shdsrc, meshmanip, client, tsettings); - progress_callback(progress_callback_args, i, size); + client->showUpdateProgressTexture(progress_callback_args, i, size); } #endif } diff --git a/src/nodedef.h b/src/nodedef.h index 0de4dbc21..8a6d88071 100644 --- a/src/nodedef.h +++ b/src/nodedef.h @@ -660,9 +660,7 @@ public: * total ContentFeatures. * @param progress_cbk_args passed to the callback function */ - void updateTextures(IGameDef *gamedef, - void (*progress_cbk)(void *progress_args, u32 progress, u32 max_progress), - void *progress_cbk_args); + void updateTextures(IGameDef *gamedef, void *progress_cbk_args); /*! * Writes the content of this manager to the given output stream. diff --git a/src/script/lua_api/l_mainmenu.cpp b/src/script/lua_api/l_mainmenu.cpp index a5bb5f261..b13398539 100644 --- a/src/script/lua_api/l_mainmenu.cpp +++ b/src/script/lua_api/l_mainmenu.cpp @@ -397,7 +397,8 @@ int ModApiMainMenu::l_show_keys_menu(lua_State *L) GUIEngine* engine = getGuiEngine(L); sanity_check(engine != NULL); - GUIKeyChangeMenu *kmenu = new GUIKeyChangeMenu(RenderingEngine::get_gui_env(), + GUIKeyChangeMenu *kmenu = new GUIKeyChangeMenu( + engine->m_rendering_engine->get_gui_env(), engine->m_parent, -1, engine->m_menumanager, @@ -694,7 +695,7 @@ int ModApiMainMenu::l_show_path_select_dialog(lua_State *L) bool is_file_select = readParam(L, 3); GUIFileSelectMenu* fileOpenMenu = - new GUIFileSelectMenu(RenderingEngine::get_gui_env(), + new GUIFileSelectMenu(engine->m_rendering_engine->get_gui_env(), engine->m_parent, -1, engine->m_menumanager, From de85bc9227ef0db01854fa0eef89256646b4d578 Mon Sep 17 00:00:00 2001 From: Loic Blot Date: Mon, 3 May 2021 10:27:00 +0200 Subject: [PATCH 65/72] fix: some code tidy about includes & irr namespaces --- src/client/client.cpp | 2 +- src/client/client.h | 2 +- src/client/clientobject.h | 6 +- src/client/clouds.cpp | 2 +- src/client/clouds.h | 3 +- src/client/content_cao.cpp | 14 ++-- src/client/content_cao.h | 2 +- src/client/content_mapblock.cpp | 2 +- src/client/content_mapblock.h | 2 +- src/client/game.cpp | 78 ++++++++++----------- src/client/renderingengine.cpp | 2 +- src/client/renderingengine.h | 5 +- src/script/common/c_content.h | 2 + src/unittest/test_clientactiveobjectmgr.cpp | 2 +- 14 files changed, 59 insertions(+), 65 deletions(-) diff --git a/src/client/client.cpp b/src/client/client.cpp index c7aae1644..c0da27e44 100644 --- a/src/client/client.cpp +++ b/src/client/client.cpp @@ -1475,7 +1475,7 @@ bool Client::updateWieldedItem() return true; } -irr::scene::ISceneManager* Client::getSceneManager() +scene::ISceneManager* Client::getSceneManager() { return m_rendering_engine->get_scene_manager(); } diff --git a/src/client/client.h b/src/client/client.h index b819d4301..c9a72b1b3 100644 --- a/src/client/client.h +++ b/src/client/client.h @@ -356,7 +356,7 @@ public: void setCamera(Camera* camera) { m_camera = camera; } Camera* getCamera () { return m_camera; } - irr::scene::ISceneManager *getSceneManager(); + scene::ISceneManager *getSceneManager(); bool shouldShowMinimap() const; diff --git a/src/client/clientobject.h b/src/client/clientobject.h index dbc2f22cf..b192f0dcd 100644 --- a/src/client/clientobject.h +++ b/src/client/clientobject.h @@ -33,17 +33,13 @@ class LocalPlayer; struct ItemStack; class WieldMeshSceneNode; -namespace irr { namespace scene { - class ISceneManager; -}} - class ClientActiveObject : public ActiveObject { public: ClientActiveObject(u16 id, Client *client, ClientEnvironment *env); virtual ~ClientActiveObject(); - virtual void addToScene(ITextureSource *tsrc, irr::scene::ISceneManager *smgr) = 0; + virtual void addToScene(ITextureSource *tsrc, scene::ISceneManager *smgr) = 0; virtual void removeFromScene(bool permanent) {} virtual void updateLight(u32 day_night_ratio) {} diff --git a/src/client/clouds.cpp b/src/client/clouds.cpp index 5a075aaf0..5008047af 100644 --- a/src/client/clouds.cpp +++ b/src/client/clouds.cpp @@ -30,7 +30,7 @@ with this program; if not, write to the Free Software Foundation, Inc., // Menu clouds are created later class Clouds; Clouds *g_menuclouds = NULL; -irr::scene::ISceneManager *g_menucloudsmgr = NULL; +scene::ISceneManager *g_menucloudsmgr = NULL; // Constant for now static constexpr const float cloud_size = BS * 64.0f; diff --git a/src/client/clouds.h b/src/client/clouds.h index a4d810faa..c009a05b7 100644 --- a/src/client/clouds.h +++ b/src/client/clouds.h @@ -29,8 +29,7 @@ class Clouds; extern Clouds *g_menuclouds; // Scene manager used for menu clouds -namespace irr{namespace scene{class ISceneManager;}} -extern irr::scene::ISceneManager *g_menucloudsmgr; +extern scene::ISceneManager *g_menucloudsmgr; class Clouds : public scene::ISceneNode { diff --git a/src/client/content_cao.cpp b/src/client/content_cao.cpp index a2fbbf001..6c7559364 100644 --- a/src/client/content_cao.cpp +++ b/src/client/content_cao.cpp @@ -188,7 +188,7 @@ public: static ClientActiveObject* create(Client *client, ClientEnvironment *env); - void addToScene(ITextureSource *tsrc, irr::scene::ISceneManager *smgr); + void addToScene(ITextureSource *tsrc, scene::ISceneManager *smgr); void removeFromScene(bool permanent); void updateLight(u32 day_night_ratio); void updateNodePos(); @@ -219,7 +219,7 @@ ClientActiveObject* TestCAO::create(Client *client, ClientEnvironment *env) return new TestCAO(client, env); } -void TestCAO::addToScene(ITextureSource *tsrc, irr::scene::ISceneManager *smgr) +void TestCAO::addToScene(ITextureSource *tsrc, scene::ISceneManager *smgr) { if(m_node != NULL) return; @@ -590,7 +590,7 @@ void GenericCAO::removeFromScene(bool permanent) m_client->getMinimap()->removeMarker(&m_marker); } -void GenericCAO::addToScene(ITextureSource *tsrc, irr::scene::ISceneManager *smgr) +void GenericCAO::addToScene(ITextureSource *tsrc, scene::ISceneManager *smgr) { m_smgr = smgr; @@ -1484,10 +1484,10 @@ void GenericCAO::updateBonePosition() if (m_bone_position.empty() || !m_animated_meshnode) return; - m_animated_meshnode->setJointMode(irr::scene::EJUOR_CONTROL); // To write positions to the mesh on render + m_animated_meshnode->setJointMode(scene::EJUOR_CONTROL); // To write positions to the mesh on render for (auto &it : m_bone_position) { std::string bone_name = it.first; - irr::scene::IBoneSceneNode* bone = m_animated_meshnode->getJointNode(bone_name.c_str()); + scene::IBoneSceneNode* bone = m_animated_meshnode->getJointNode(bone_name.c_str()); if (bone) { bone->setPosition(it.second.X); bone->setRotation(it.second.Y); @@ -1496,7 +1496,7 @@ void GenericCAO::updateBonePosition() // search through bones to find mistakenly rotated bones due to bug in Irrlicht for (u32 i = 0; i < m_animated_meshnode->getJointCount(); ++i) { - irr::scene::IBoneSceneNode *bone = m_animated_meshnode->getJointNode(i); + scene::IBoneSceneNode *bone = m_animated_meshnode->getJointNode(i); if (!bone) continue; @@ -1924,7 +1924,7 @@ void GenericCAO::updateMeshCulling() return; } - irr::scene::ISceneNode *node = getSceneNode(); + scene::ISceneNode *node = getSceneNode(); if (!node) return; diff --git a/src/client/content_cao.h b/src/client/content_cao.h index 32ec9c1c3..4bbba9134 100644 --- a/src/client/content_cao.h +++ b/src/client/content_cao.h @@ -236,7 +236,7 @@ public: void removeFromScene(bool permanent); - void addToScene(ITextureSource *tsrc, irr::scene::ISceneManager *smgr); + void addToScene(ITextureSource *tsrc, scene::ISceneManager *smgr); inline void expireVisuals() { diff --git a/src/client/content_mapblock.cpp b/src/client/content_mapblock.cpp index e530f3d7f..810c57138 100644 --- a/src/client/content_mapblock.cpp +++ b/src/client/content_mapblock.cpp @@ -61,7 +61,7 @@ static constexpr u16 quad_indices[] = {0, 1, 2, 2, 3, 0}; const std::string MapblockMeshGenerator::raillike_groupname = "connect_to_raillike"; MapblockMeshGenerator::MapblockMeshGenerator(MeshMakeData *input, MeshCollector *output, - irr::scene::IMeshManipulator *mm): + scene::IMeshManipulator *mm): data(input), collector(output), nodedef(data->m_client->ndef()), diff --git a/src/client/content_mapblock.h b/src/client/content_mapblock.h index cbee49021..237cc7847 100644 --- a/src/client/content_mapblock.h +++ b/src/client/content_mapblock.h @@ -173,7 +173,7 @@ public: public: MapblockMeshGenerator(MeshMakeData *input, MeshCollector *output, - irr::scene::IMeshManipulator *mm); + scene::IMeshManipulator *mm); void generate(); void renderSingle(content_t node, u8 param2 = 0x00); }; diff --git a/src/client/game.cpp b/src/client/game.cpp index 2f0f50505..eb1dbb5a3 100644 --- a/src/client/game.cpp +++ b/src/client/game.cpp @@ -839,7 +839,7 @@ private: MapDrawControl *draw_control = nullptr; Camera *camera = nullptr; Clouds *clouds = nullptr; // Free using ->Drop() - Sky *m_sky = nullptr; // Free using ->Drop() + Sky *sky = nullptr; // Free using ->Drop() Hud *hud = nullptr; Minimap *mapper = nullptr; @@ -1159,8 +1159,8 @@ void Game::shutdown() if (gui_chat_console) gui_chat_console->drop(); - if (m_sky) - m_sky->drop(); + if (sky) + sky->drop(); /* cleanup menus */ while (g_menumgr.menuCount() > 0) { @@ -1346,8 +1346,8 @@ bool Game::createClient(const GameStartData &start_data) /* Skybox */ - m_sky = new Sky(-1, m_rendering_engine, texture_src, shader_src); - scsf->setSky(m_sky); + sky = new Sky(-1, m_rendering_engine, texture_src, shader_src); + scsf->setSky(sky); skybox = NULL; // This is used/set later on in the main run loop /* Pre-calculated values @@ -2754,23 +2754,23 @@ void Game::handleClientEvent_HudChange(ClientEvent *event, CameraOrientation *ca void Game::handleClientEvent_SetSky(ClientEvent *event, CameraOrientation *cam) { - m_sky->setVisible(false); + sky->setVisible(false); // Whether clouds are visible in front of a custom skybox. - m_sky->setCloudsEnabled(event->set_sky->clouds); + sky->setCloudsEnabled(event->set_sky->clouds); if (skybox) { skybox->remove(); skybox = NULL; } // Clear the old textures out in case we switch rendering type. - m_sky->clearSkyboxTextures(); + sky->clearSkyboxTextures(); // Handle according to type if (event->set_sky->type == "regular") { // Shows the mesh skybox - m_sky->setVisible(true); + sky->setVisible(true); // Update mesh based skybox colours if applicable. - m_sky->setSkyColors(event->set_sky->sky_color); - m_sky->setHorizonTint( + sky->setSkyColors(event->set_sky->sky_color); + sky->setHorizonTint( event->set_sky->fog_sun_tint, event->set_sky->fog_moon_tint, event->set_sky->fog_tint_type @@ -2778,27 +2778,27 @@ void Game::handleClientEvent_SetSky(ClientEvent *event, CameraOrientation *cam) } else if (event->set_sky->type == "skybox" && event->set_sky->textures.size() == 6) { // Disable the dyanmic mesh skybox: - m_sky->setVisible(false); + sky->setVisible(false); // Set fog colors: - m_sky->setFallbackBgColor(event->set_sky->bgcolor); + sky->setFallbackBgColor(event->set_sky->bgcolor); // Set sunrise and sunset fog tinting: - m_sky->setHorizonTint( + sky->setHorizonTint( event->set_sky->fog_sun_tint, event->set_sky->fog_moon_tint, event->set_sky->fog_tint_type ); // Add textures to skybox. for (int i = 0; i < 6; i++) - m_sky->addTextureToSkybox(event->set_sky->textures[i], i, texture_src); + sky->addTextureToSkybox(event->set_sky->textures[i], i, texture_src); } else { // Handle everything else as plain color. if (event->set_sky->type != "plain") infostream << "Unknown sky type: " << (event->set_sky->type) << std::endl; - m_sky->setVisible(false); - m_sky->setFallbackBgColor(event->set_sky->bgcolor); + sky->setVisible(false); + sky->setFallbackBgColor(event->set_sky->bgcolor); // Disable directional sun/moon tinting on plain or invalid skyboxes. - m_sky->setHorizonTint( + sky->setHorizonTint( event->set_sky->bgcolor, event->set_sky->bgcolor, "custom" @@ -2810,30 +2810,30 @@ void Game::handleClientEvent_SetSky(ClientEvent *event, CameraOrientation *cam) void Game::handleClientEvent_SetSun(ClientEvent *event, CameraOrientation *cam) { - m_sky->setSunVisible(event->sun_params->visible); - m_sky->setSunTexture(event->sun_params->texture, + sky->setSunVisible(event->sun_params->visible); + sky->setSunTexture(event->sun_params->texture, event->sun_params->tonemap, texture_src); - m_sky->setSunScale(event->sun_params->scale); - m_sky->setSunriseVisible(event->sun_params->sunrise_visible); - m_sky->setSunriseTexture(event->sun_params->sunrise, texture_src); + sky->setSunScale(event->sun_params->scale); + sky->setSunriseVisible(event->sun_params->sunrise_visible); + sky->setSunriseTexture(event->sun_params->sunrise, texture_src); delete event->sun_params; } void Game::handleClientEvent_SetMoon(ClientEvent *event, CameraOrientation *cam) { - m_sky->setMoonVisible(event->moon_params->visible); - m_sky->setMoonTexture(event->moon_params->texture, + sky->setMoonVisible(event->moon_params->visible); + sky->setMoonTexture(event->moon_params->texture, event->moon_params->tonemap, texture_src); - m_sky->setMoonScale(event->moon_params->scale); + sky->setMoonScale(event->moon_params->scale); delete event->moon_params; } void Game::handleClientEvent_SetStars(ClientEvent *event, CameraOrientation *cam) { - m_sky->setStarsVisible(event->star_params->visible); - m_sky->setStarCount(event->star_params->count, false); - m_sky->setStarColor(event->star_params->starcolor); - m_sky->setStarScale(event->star_params->scale); + sky->setStarsVisible(event->star_params->visible); + sky->setStarCount(event->star_params->count, false); + sky->setStarColor(event->star_params->starcolor); + sky->setStarScale(event->star_params->scale); delete event->star_params; } @@ -3710,7 +3710,7 @@ void Game::updateFrame(ProfilerGraph *graph, RunStats *stats, f32 dtime, direct_brightness = time_brightness; sunlight_seen = true; } else { - float old_brightness = m_sky->getBrightness(); + float old_brightness = sky->getBrightness(); direct_brightness = client->getEnv().getClientMap() .getBackgroundBrightness(MYMIN(runData.fog_range * 1.2, 60 * BS), daynight_ratio, (int)(old_brightness * 255.5), &sunlight_seen) @@ -3737,7 +3737,7 @@ void Game::updateFrame(ProfilerGraph *graph, RunStats *stats, f32 dtime, runData.time_of_day_smooth = time_of_day_smooth; - m_sky->update(time_of_day_smooth, time_brightness, direct_brightness, + sky->update(time_of_day_smooth, time_brightness, direct_brightness, sunlight_seen, camera->getCameraMode(), player->getYaw(), player->getPitch()); @@ -3745,7 +3745,7 @@ void Game::updateFrame(ProfilerGraph *graph, RunStats *stats, f32 dtime, Update clouds */ if (clouds) { - if (m_sky->getCloudsVisible()) { + if (sky->getCloudsVisible()) { clouds->setVisible(true); clouds->step(dtime); // camera->getPosition is not enough for 3rd person views @@ -3755,14 +3755,14 @@ void Game::updateFrame(ProfilerGraph *graph, RunStats *stats, f32 dtime, camera_node_position.Y = camera_node_position.Y + camera_offset.Y * BS; camera_node_position.Z = camera_node_position.Z + camera_offset.Z * BS; clouds->update(camera_node_position, - m_sky->getCloudColor()); + sky->getCloudColor()); if (clouds->isCameraInsideCloud() && m_cache_enable_fog) { // if inside clouds, and fog enabled, use that as sky // color(s) video::SColor clouds_dark = clouds->getColor() .getInterpolated(video::SColor(255, 0, 0, 0), 0.9); - m_sky->overrideColors(clouds_dark, clouds->getColor()); - m_sky->setInClouds(true); + sky->overrideColors(clouds_dark, clouds->getColor()); + sky->setInClouds(true); runData.fog_range = std::fmin(runData.fog_range * 0.5f, 32.0f * BS); // do not draw clouds after all clouds->setVisible(false); @@ -3783,7 +3783,7 @@ void Game::updateFrame(ProfilerGraph *graph, RunStats *stats, f32 dtime, if (m_cache_enable_fog) { driver->setFog( - m_sky->getBgColor(), + sky->getBgColor(), video::EFT_FOG_LINEAR, runData.fog_range * m_cache_fog_start, runData.fog_range * 1.0, @@ -3793,7 +3793,7 @@ void Game::updateFrame(ProfilerGraph *graph, RunStats *stats, f32 dtime, ); } else { driver->setFog( - m_sky->getBgColor(), + sky->getBgColor(), video::EFT_FOG_LINEAR, 100000 * BS, 110000 * BS, @@ -3873,7 +3873,7 @@ void Game::updateFrame(ProfilerGraph *graph, RunStats *stats, f32 dtime, /* Drawing begins */ - const video::SColor &skycolor = m_sky->getSkyColor(); + const video::SColor &skycolor = sky->getSkyColor(); TimeTaker tt_draw("Draw scene"); driver->beginScene(true, true, skycolor); diff --git a/src/client/renderingengine.cpp b/src/client/renderingengine.cpp index e74446aeb..4f96a6e37 100644 --- a/src/client/renderingengine.cpp +++ b/src/client/renderingengine.cpp @@ -225,7 +225,7 @@ bool RenderingEngine::print_video_modes() return videomode_list != NULL; } -void RenderingEngine::removeMesh(const irr::scene::IMesh* mesh) +void RenderingEngine::removeMesh(const scene::IMesh* mesh) { m_device->getSceneManager()->getMeshCache()->removeMesh(mesh); } diff --git a/src/client/renderingengine.h b/src/client/renderingengine.h index 1fd85f5ef..28ddc8652 100644 --- a/src/client/renderingengine.h +++ b/src/client/renderingengine.h @@ -26,9 +26,6 @@ with this program; if not, write to the Free Software Foundation, Inc., #include "irrlichttypes_extrabloated.h" #include "debug.h" -namespace irr { namespace scene { -class IMesh; -}} class ITextureSource; class Camera; class Client; @@ -60,7 +57,7 @@ public: static bool print_video_modes(); void cleanupMeshCache(); - void removeMesh(const irr::scene::IMesh* mesh); + void removeMesh(const scene::IMesh* mesh); static v2u32 getWindowSize() { diff --git a/src/script/common/c_content.h b/src/script/common/c_content.h index f54490e3a..4dc614706 100644 --- a/src/script/common/c_content.h +++ b/src/script/common/c_content.h @@ -39,6 +39,8 @@ extern "C" { #include "itemgroup.h" #include "itemdef.h" #include "c_types.h" +// We do a explicit path include because by default c_content.h include src/client/hud.h +// prior to the src/hud.h, which is not good on server only build #include "../../hud.h" namespace Json { class Value; } diff --git a/src/unittest/test_clientactiveobjectmgr.cpp b/src/unittest/test_clientactiveobjectmgr.cpp index a43855c19..2d508cf32 100644 --- a/src/unittest/test_clientactiveobjectmgr.cpp +++ b/src/unittest/test_clientactiveobjectmgr.cpp @@ -29,7 +29,7 @@ public: TestClientActiveObject() : ClientActiveObject(0, nullptr, nullptr) {} ~TestClientActiveObject() = default; ActiveObjectType getType() const { return ACTIVEOBJECT_TYPE_TEST; } - virtual void addToScene(ITextureSource *tsrc, irr::scene::ISceneManager *smgr) {} + virtual void addToScene(ITextureSource *tsrc, scene::ISceneManager *smgr) {} }; class TestClientActiveObjectMgr : public TestBase From 08f1a7fbed4139a0147a067d38af353935d79b57 Mon Sep 17 00:00:00 2001 From: sfan5 Date: Wed, 21 Apr 2021 18:52:14 +0200 Subject: [PATCH 66/72] Use Irrlicht functions to query npot texture support --- src/CMakeLists.txt | 14 +++++------- src/client/guiscalingfilter.cpp | 3 +-- src/client/tile.cpp | 38 +++------------------------------ src/client/tile.h | 3 +-- 4 files changed, 10 insertions(+), 48 deletions(-) diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt index 5298a8f0d..9526e88f9 100644 --- a/src/CMakeLists.txt +++ b/src/CMakeLists.txt @@ -102,11 +102,11 @@ endif() option(ENABLE_GLES "Use OpenGL ES instead of OpenGL" FALSE) mark_as_advanced(ENABLE_GLES) if(BUILD_CLIENT) - if(ENABLE_GLES) - find_package(OpenGLES2 REQUIRED) - else() - # transitive dependency from Irrlicht (see longer explanation below) - if(NOT WIN32) + # transitive dependency from Irrlicht (see longer explanation below) + if(NOT WIN32) + if(ENABLE_GLES) + find_package(OpenGLES2 REQUIRED) + else() set(OPENGL_GL_PREFERENCE "LEGACY" CACHE STRING "See CMake Policy CMP0072 for reference. GLVND is broken on some nvidia setups") set(OpenGL_GL_PREFERENCE ${OPENGL_GL_PREFERENCE}) @@ -523,10 +523,6 @@ include_directories( ${PROJECT_SOURCE_DIR}/script ) -if(ENABLE_GLES) - include_directories(${OPENGLES2_INCLUDE_DIR} ${EGL_INCLUDE_DIR}) -endif() - if(USE_GETTEXT) include_directories(${GETTEXT_INCLUDE_DIR}) endif() diff --git a/src/client/guiscalingfilter.cpp b/src/client/guiscalingfilter.cpp index cf371d8ba..232219237 100644 --- a/src/client/guiscalingfilter.cpp +++ b/src/client/guiscalingfilter.cpp @@ -23,7 +23,6 @@ with this program; if not, write to the Free Software Foundation, Inc., #include "util/numeric.h" #include #include "client/renderingengine.h" -#include "client/tile.h" // hasNPotSupport() /* Maintain a static cache to store the images that correspond to textures * in a format that's manipulable by code. Some platforms exhibit issues @@ -117,7 +116,7 @@ video::ITexture *guiScalingResizeCached(video::IVideoDriver *driver, #if ENABLE_GLES // Some platforms are picky about textures being powers of 2, so expand // the image dimensions to the next power of 2, if necessary. - if (!hasNPotSupport()) { + if (!driver->queryFeature(video::EVDF_TEXTURE_NPOT)) { video::IImage *po2img = driver->createImage(src->getColorFormat(), core::dimension2d(npot2((u32)destrect.getWidth()), npot2((u32)destrect.getHeight()))); diff --git a/src/client/tile.cpp b/src/client/tile.cpp index d9f8c75a7..96312ea27 100644 --- a/src/client/tile.cpp +++ b/src/client/tile.cpp @@ -34,15 +34,6 @@ with this program; if not, write to the Free Software Foundation, Inc., #include "guiscalingfilter.h" #include "renderingengine.h" - -#if ENABLE_GLES -#ifdef _IRR_COMPILE_WITH_OGLES1_ -#include -#else -#include -#endif -#endif - /* A cache from texture name to texture path */ @@ -1013,42 +1004,19 @@ video::IImage* TextureSource::generateImage(const std::string &name) #if ENABLE_GLES - -static inline u16 get_GL_major_version() -{ - const GLubyte *gl_version = glGetString(GL_VERSION); - return (u16) (gl_version[0] - '0'); -} - -/** - * Check if hardware requires npot2 aligned textures - * @return true if alignment NOT(!) requires, false otherwise - */ - -bool hasNPotSupport() -{ - // Only GLES2 is trusted to correctly report npot support - // Note: we cache the boolean result, the GL context will never change. - static const bool supported = get_GL_major_version() > 1 && - glGetString(GL_EXTENSIONS) && - strstr((char *)glGetString(GL_EXTENSIONS), "GL_OES_texture_npot"); - return supported; -} - /** * Check and align image to npot2 if required by hardware * @param image image to check for npot2 alignment * @param driver driver to use for image operations * @return image or copy of image aligned to npot2 */ - -video::IImage * Align2Npot2(video::IImage * image, - video::IVideoDriver* driver) +video::IImage *Align2Npot2(video::IImage *image, + video::IVideoDriver *driver) { if (image == NULL) return image; - if (hasNPotSupport()) + if (driver->queryFeature(video::EVDF_TEXTURE_NPOT)) return image; core::dimension2d dim = image->getDimension(); diff --git a/src/client/tile.h b/src/client/tile.h index 49c46f749..fcdc46460 100644 --- a/src/client/tile.h +++ b/src/client/tile.h @@ -134,8 +134,7 @@ public: IWritableTextureSource *createTextureSource(); #if ENABLE_GLES -bool hasNPotSupport(); -video::IImage * Align2Npot2(video::IImage * image, irr::video::IVideoDriver* driver); +video::IImage *Align2Npot2(video::IImage *image, video::IVideoDriver *driver); #endif enum MaterialType{ From ba40b3950057c54609f8e4a56139563d30f8b84f Mon Sep 17 00:00:00 2001 From: sfan5 Date: Wed, 21 Apr 2021 18:21:12 +0200 Subject: [PATCH 67/72] Add basic client-server test to CI --- .github/workflows/build.yml | 8 +++- util/ci/common.sh | 4 +- util/test_multiplayer.sh | 79 ++++++++++++++++++++++--------------- 3 files changed, 57 insertions(+), 34 deletions(-) diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index 0cf18d228..d268aa0cb 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -80,7 +80,7 @@ jobs: - name: Install deps run: | source ./util/ci/common.sh - install_linux_deps clang-3.9 + install_linux_deps clang-3.9 gdb - name: Build run: | @@ -89,10 +89,14 @@ jobs: CC: clang-3.9 CXX: clang++-3.9 - - name: Test + - name: Unittest run: | ./bin/minetest --run-unittests + - name: Integration test + run: | + ./util/test_multiplayer.sh + # This is the current clang version clang_9: runs-on: ubuntu-18.04 diff --git a/util/ci/common.sh b/util/ci/common.sh index 1083581b5..eb282c823 100644 --- a/util/ci/common.sh +++ b/util/ci/common.sh @@ -11,7 +11,9 @@ install_linux_deps() { shift pkgs+=(libirrlicht-dev) else - wget "https://github.com/minetest/irrlicht/releases/download/1.9.0mt1/ubuntu-bionic.tar.gz" + # TODO: return old URL when IrrlichtMt 1.9.0mt2 is tagged + #wget "https://github.com/minetest/irrlicht/releases/download/1.9.0mt1/ubuntu-bionic.tar.gz" + wget "http://minetest.kitsunemimi.pw/irrlichtmt-patched-temporary.tgz" -O ubuntu-bionic.tar.gz sudo tar -xaf ubuntu-bionic.tar.gz -C /usr/local fi diff --git a/util/test_multiplayer.sh b/util/test_multiplayer.sh index 176cf11d9..9fb894a30 100755 --- a/util/test_multiplayer.sh +++ b/util/test_multiplayer.sh @@ -3,41 +3,58 @@ dir="$( cd "$( dirname "${BASH_SOURCE[0]}" )" && pwd )" gameid=devtest minetest=$dir/../bin/minetest testspath=$dir/../tests -worldpath=$testspath/testworld_$gameid -configpath=$testspath/configs -logpath=$testspath/log -conf_server=$configpath/minetest.conf.multi.server -conf_client1=$configpath/minetest.conf.multi.client1 -conf_client2=$configpath/minetest.conf.multi.client2 -log_server=$logpath/server.log -log_client1=$logpath/client1.log -log_client2=$logpath/client2.log +conf_client1=$testspath/client1.conf +conf_server=$testspath/server.conf +worldpath=$testspath/world -mkdir -p $worldpath -mkdir -p $configpath -mkdir -p $logpath +waitfor () { + n=30 + while [ $n -gt 0 ]; do + [ -f "$1" ] && return 0 + sleep 0.5 + ((n-=1)) + done + echo "Waiting for ${1##*/} timed out" + pkill -P $$ + exit 1 +} -echo -ne 'client1::shout,interact,settime,teleport,give -client2::shout,interact,settime,teleport,give -' > $worldpath/auth.txt +gdbrun () { + gdb -q -ex 'set confirm off' -ex 'r' -ex 'bt' -ex 'quit' --args "$@" +} -echo -ne '' > $conf_server +[ -e $minetest ] || { echo "executable $minetest missing"; exit 1; } -echo -ne '# client 1 config -screenW=500 -screenH=380 -name=client1 -viewing_range_nodes_min=10 -' > $conf_client1 +rm -rf $worldpath +mkdir -p $worldpath/worldmods/test -echo -ne '# client 2 config -screenW=500 -screenH=380 -name=client2 -viewing_range_nodes_min=10 -' > $conf_client2 +printf '%s\n' >$testspath/client1.conf \ + video_driver=null name=client1 viewing_range=10 \ + enable_{sound,minimap,shaders}=false -echo $(sleep 1; $minetest --disable-unittests --logfile $log_client1 --config $conf_client1 --go --address localhost) & -echo $(sleep 2; $minetest --disable-unittests --logfile $log_client2 --config $conf_client2 --go --address localhost) & -$minetest --disable-unittests --server --logfile $log_server --config $conf_server --world $worldpath --gameid $gameid +printf '%s\n' >$testspath/server.conf \ + max_block_send_distance=1 +cat >$worldpath/worldmods/test/init.lua <<"LUA" +core.after(0, function() + io.close(io.open(core.get_worldpath() .. "/startup", "w")) +end) +core.register_on_joinplayer(function(player) + io.close(io.open(core.get_worldpath() .. "/player_joined", "w")) + core.request_shutdown("", false, 2) +end) +LUA + +echo "Starting server" +gdbrun $minetest --server --config $conf_server --world $worldpath --gameid $gameid 2>&1 | sed -u 's/^/(server) /' & +waitfor $worldpath/startup + +echo "Starting client" +gdbrun $minetest --config $conf_client1 --go --address 127.0.0.1 2>&1 | sed -u 's/^/(client) /' & +waitfor $worldpath/player_joined + +echo "Waiting for client and server to exit" +wait + +echo "Success" +exit 0 From 225d4541ffb4d59001841747e0877a175da50c17 Mon Sep 17 00:00:00 2001 From: Loic Blot Date: Thu, 6 May 2021 09:02:11 +0200 Subject: [PATCH 68/72] fix: extractZipFile is not part of Client but more generic. This solve a crash from mainmenu while extracting the zip --- src/client/client.cpp | 66 ------------------------------- src/client/client.h | 2 - src/filesys.cpp | 64 ++++++++++++++++++++++++++++++ src/filesys.h | 6 +++ src/script/lua_api/l_mainmenu.cpp | 3 +- 5 files changed, 72 insertions(+), 69 deletions(-) diff --git a/src/client/client.cpp b/src/client/client.cpp index c0da27e44..00ae8f6b8 100644 --- a/src/client/client.cpp +++ b/src/client/client.cpp @@ -725,72 +725,6 @@ bool Client::loadMedia(const std::string &data, const std::string &filename, return false; } -bool Client::extractZipFile(const char *filename, const std::string &destination) -{ - auto fs = m_rendering_engine->get_filesystem(); - - if (!fs->addFileArchive(filename, false, false, io::EFAT_ZIP)) { - return false; - } - - sanity_check(fs->getFileArchiveCount() > 0); - - /**********************************************************************/ - /* WARNING this is not threadsafe!! */ - /**********************************************************************/ - io::IFileArchive* opened_zip = fs->getFileArchive(fs->getFileArchiveCount() - 1); - - const io::IFileList* files_in_zip = opened_zip->getFileList(); - - unsigned int number_of_files = files_in_zip->getFileCount(); - - for (unsigned int i=0; i < number_of_files; i++) { - std::string fullpath = destination; - fullpath += DIR_DELIM; - fullpath += files_in_zip->getFullFileName(i).c_str(); - std::string fullpath_dir = fs::RemoveLastPathComponent(fullpath); - - if (!files_in_zip->isDirectory(i)) { - if (!fs::PathExists(fullpath_dir) && !fs::CreateAllDirs(fullpath_dir)) { - fs->removeFileArchive(fs->getFileArchiveCount()-1); - return false; - } - - io::IReadFile* toread = opened_zip->createAndOpenFile(i); - - FILE *targetfile = fopen(fullpath.c_str(),"wb"); - - if (targetfile == NULL) { - fs->removeFileArchive(fs->getFileArchiveCount()-1); - return false; - } - - char read_buffer[1024]; - long total_read = 0; - - while (total_read < toread->getSize()) { - - unsigned int bytes_read = - toread->read(read_buffer,sizeof(read_buffer)); - if ((bytes_read == 0 ) || - (fwrite(read_buffer, 1, bytes_read, targetfile) != bytes_read)) - { - fclose(targetfile); - fs->removeFileArchive(fs->getFileArchiveCount() - 1); - return false; - } - total_read += bytes_read; - } - - fclose(targetfile); - } - - } - - fs->removeFileArchive(fs->getFileArchiveCount() - 1); - return true; -} - // Virtual methods from con::PeerHandler void Client::peerAdded(con::Peer *peer) { diff --git a/src/client/client.h b/src/client/client.h index c9a72b1b3..85ca24049 100644 --- a/src/client/client.h +++ b/src/client/client.h @@ -384,8 +384,6 @@ public: bool loadMedia(const std::string &data, const std::string &filename, bool from_media_push = false); - bool extractZipFile(const char *filename, const std::string &destination); - // Send a request for conventional media transfer void request_media(const std::vector &file_requests); diff --git a/src/filesys.cpp b/src/filesys.cpp index 5ffb4506e..99b030624 100644 --- a/src/filesys.cpp +++ b/src/filesys.cpp @@ -727,6 +727,70 @@ bool safeWriteToFile(const std::string &path, const std::string &content) return true; } +bool extractZipFile(io::IFileSystem *fs, const char *filename, const std::string &destination) +{ + if (!fs->addFileArchive(filename, false, false, io::EFAT_ZIP)) { + return false; + } + + sanity_check(fs->getFileArchiveCount() > 0); + + /**********************************************************************/ + /* WARNING this is not threadsafe!! */ + /**********************************************************************/ + io::IFileArchive* opened_zip = fs->getFileArchive(fs->getFileArchiveCount() - 1); + + const io::IFileList* files_in_zip = opened_zip->getFileList(); + + unsigned int number_of_files = files_in_zip->getFileCount(); + + for (unsigned int i=0; i < number_of_files; i++) { + std::string fullpath = destination; + fullpath += DIR_DELIM; + fullpath += files_in_zip->getFullFileName(i).c_str(); + std::string fullpath_dir = fs::RemoveLastPathComponent(fullpath); + + if (!files_in_zip->isDirectory(i)) { + if (!fs::PathExists(fullpath_dir) && !fs::CreateAllDirs(fullpath_dir)) { + fs->removeFileArchive(fs->getFileArchiveCount()-1); + return false; + } + + io::IReadFile* toread = opened_zip->createAndOpenFile(i); + + FILE *targetfile = fopen(fullpath.c_str(),"wb"); + + if (targetfile == NULL) { + fs->removeFileArchive(fs->getFileArchiveCount()-1); + return false; + } + + char read_buffer[1024]; + long total_read = 0; + + while (total_read < toread->getSize()) { + + unsigned int bytes_read = + toread->read(read_buffer,sizeof(read_buffer)); + if ((bytes_read == 0 ) || + (fwrite(read_buffer, 1, bytes_read, targetfile) != bytes_read)) + { + fclose(targetfile); + fs->removeFileArchive(fs->getFileArchiveCount() - 1); + return false; + } + total_read += bytes_read; + } + + fclose(targetfile); + } + + } + + fs->removeFileArchive(fs->getFileArchiveCount() - 1); + return true; +} + bool ReadFile(const std::string &path, std::string &out) { std::ifstream is(path, std::ios::binary | std::ios::ate); diff --git a/src/filesys.h b/src/filesys.h index cfbfa02bf..a9584b036 100644 --- a/src/filesys.h +++ b/src/filesys.h @@ -36,6 +36,10 @@ with this program; if not, write to the Free Software Foundation, Inc., #define PATH_DELIM ":" #endif +namespace irr { namespace io { +class IFileSystem; +}} + namespace fs { @@ -125,6 +129,8 @@ const char *GetFilenameFromPath(const char *path); bool safeWriteToFile(const std::string &path, const std::string &content); +bool extractZipFile(irr::io::IFileSystem *fs, const char *filename, const std::string &destination); + bool ReadFile(const std::string &path, std::string &out); bool Rename(const std::string &from, const std::string &to); diff --git a/src/script/lua_api/l_mainmenu.cpp b/src/script/lua_api/l_mainmenu.cpp index b13398539..ee3e72dea 100644 --- a/src/script/lua_api/l_mainmenu.cpp +++ b/src/script/lua_api/l_mainmenu.cpp @@ -628,8 +628,9 @@ int ModApiMainMenu::l_extract_zip(lua_State *L) std::string absolute_destination = fs::RemoveRelativePathComponents(destination); if (ModApiMainMenu::mayModifyPath(absolute_destination)) { + auto rendering_engine = getGuiEngine(L)->m_rendering_engine; fs::CreateAllDirs(absolute_destination); - lua_pushboolean(L, getClient(L)->extractZipFile(zipfile, destination)); + lua_pushboolean(L, fs::extractZipFile(rendering_engine->get_filesystem(), zipfile, destination)); return 1; } From 1bb8449734424f9e7afda8029b9a8cb2af392b61 Mon Sep 17 00:00:00 2001 From: Wuzzy Date: Thu, 6 May 2021 17:24:11 +0000 Subject: [PATCH 69/72] Improve liquid documentation (#11158) --- doc/lua_api.txt | 28 ++++++++++++++++++++++++++-- 1 file changed, 26 insertions(+), 2 deletions(-) diff --git a/doc/lua_api.txt b/doc/lua_api.txt index 75cd6b7cc..ef86efcc1 100644 --- a/doc/lua_api.txt +++ b/doc/lua_api.txt @@ -1112,8 +1112,20 @@ Look for examples in `games/devtest` or `games/minetest_game`. * Invisible, uses no texture. * `liquid` * The cubic source node for a liquid. + * Faces bordering to the same node are never rendered. + * Connects to node specified in `liquid_alternative_flowing`. + * Use `backface_culling = false` for the tiles you want to make + visible when inside the node. * `flowingliquid` * The flowing version of a liquid, appears with various heights and slopes. + * Faces bordering to the same node are never rendered. + * Connects to node specified in `liquid_alternative_source`. + * Node textures are defined with `special_tiles` where the first tile + is for the top and bottom faces and the second tile is for the side + faces. + * `tiles` is used for the item/inventory/wield image rendering. + * Use `backface_culling = false` for the special tiles you want to make + visible when inside the node * `glasslike` * Often used for partially-transparent nodes. * Only external sides of textures are visible. @@ -7453,7 +7465,16 @@ Used by `minetest.register_node`. -- If true, liquids flow into and replace this node. -- Warning: making a liquid node 'floodable' will cause problems. - liquidtype = "none", -- "none" / "source" / "flowing" + liquidtype = "none", -- specifies liquid physics + -- * "none": no liquid physics + -- * "source": spawns flowing liquid nodes at all 4 sides and below; + -- recommended drawtype: "liquid". + -- * "flowing": spawned from source, spawns more flowing liquid nodes + -- around it until `liquid_range` is reached; + -- will drain out without a source; + -- recommended drawtype: "flowingliquid". + -- If it's "source" or "flowing" and `liquid_range > 0`, then + -- both `liquid_alternative_*` fields must be specified liquid_alternative_flowing = "", -- Flowing version of source liquid @@ -7476,7 +7497,10 @@ Used by `minetest.register_node`. -- `minetest.set_node_level` and `minetest.add_node_level`. -- Values above 124 might causes collision detection issues. - liquid_range = 8, -- Number of flowing nodes around source (max. 8) + liquid_range = 8, + -- Maximum distance that flowing liquid nodes can spread around + -- source on flat land; + -- maximum = 8; set to 0 to disable liquid flow drowning = 0, -- Player will take this amount of damage if no bubbles are left From 7c2826cbc0f36027d4a9781f433150d1c5d0d03f Mon Sep 17 00:00:00 2001 From: lhofhansl Date: Thu, 6 May 2021 10:24:30 -0700 Subject: [PATCH 70/72] Fix build for newer versions of GCC (#11246) --- src/clientiface.h | 1 + 1 file changed, 1 insertion(+) diff --git a/src/clientiface.h b/src/clientiface.h index cc5292b71..dfd976741 100644 --- a/src/clientiface.h +++ b/src/clientiface.h @@ -31,6 +31,7 @@ with this program; if not, write to the Free Software Foundation, Inc., #include #include #include +#include #include class MapBlock; From 2443f1e2351d641d82597525e937792cce15be1e Mon Sep 17 00:00:00 2001 From: sfan5 Date: Sat, 8 May 2021 19:33:52 +0200 Subject: [PATCH 71/72] Fix overlays for 2D-drawn items fixes #11248 --- src/client/hud.cpp | 9 +++++++-- 1 file changed, 7 insertions(+), 2 deletions(-) diff --git a/src/client/hud.cpp b/src/client/hud.cpp index 7f044cccd..0bfdd5af0 100644 --- a/src/client/hud.cpp +++ b/src/client/hud.cpp @@ -997,6 +997,8 @@ void drawItemStack( const ItemDefinition &def = item.getDefinition(client->idef()); + bool draw_overlay = false; + // Render as mesh if animated or no inventory image if ((enable_animations && rotation_kind < IT_ROT_NONE) || def.inventory_image.empty()) { ItemMesh *imesh = client->idef()->getWieldMesh(def.name, client); @@ -1089,6 +1091,8 @@ void drawItemStack( driver->setTransform(video::ETS_VIEW, oldViewMat); driver->setTransform(video::ETS_PROJECTION, oldProjMat); driver->setViewPort(oldViewPort); + + draw_overlay = def.type == ITEM_NODE && def.inventory_image.empty(); } else { // Otherwise just draw as 2D video::ITexture *texture = client->idef()->getInventoryTexture(def.name, client); if (!texture) @@ -1100,11 +1104,12 @@ void drawItemStack( draw2DImageFilterScaled(driver, texture, rect, core::rect({0, 0}, core::dimension2di(texture->getOriginalSize())), clip, colors, true); + + draw_overlay = true; } // draw the inventory_overlay - if (def.type == ITEM_NODE && def.inventory_image.empty() && - !def.inventory_overlay.empty()) { + if (!def.inventory_overlay.empty() && draw_overlay) { ITextureSource *tsrc = client->getTextureSource(); video::ITexture *overlay_texture = tsrc->getTexture(def.inventory_overlay); core::dimension2d dimens = overlay_texture->getOriginalSize(); From 69c70dd319532f7860f211f4a527a902b0386e49 Mon Sep 17 00:00:00 2001 From: sfan5 Date: Sat, 8 May 2021 20:18:29 +0200 Subject: [PATCH 72/72] Fix swapped vertex colors on GLES2 --- client/shaders/default_shader/opengl_vertex.glsl | 4 ++++ client/shaders/minimap_shader/opengl_vertex.glsl | 4 ++++ client/shaders/nodes_shader/opengl_vertex.glsl | 10 +++++++--- client/shaders/object_shader/opengl_vertex.glsl | 4 ++++ client/shaders/selection_shader/opengl_vertex.glsl | 4 ++++ 5 files changed, 23 insertions(+), 3 deletions(-) diff --git a/client/shaders/default_shader/opengl_vertex.glsl b/client/shaders/default_shader/opengl_vertex.glsl index d95a3c2d3..a908ac953 100644 --- a/client/shaders/default_shader/opengl_vertex.glsl +++ b/client/shaders/default_shader/opengl_vertex.glsl @@ -3,5 +3,9 @@ varying lowp vec4 varColor; void main(void) { gl_Position = mWorldViewProj * inVertexPosition; +#ifdef GL_ES + varColor = inVertexColor.bgra; +#else varColor = inVertexColor; +#endif } diff --git a/client/shaders/minimap_shader/opengl_vertex.glsl b/client/shaders/minimap_shader/opengl_vertex.glsl index 1a9491805..b23d27181 100644 --- a/client/shaders/minimap_shader/opengl_vertex.glsl +++ b/client/shaders/minimap_shader/opengl_vertex.glsl @@ -7,5 +7,9 @@ void main(void) { varTexCoord = inTexCoord0.st; gl_Position = mWorldViewProj * inVertexPosition; +#ifdef GL_ES + varColor = inVertexColor.bgra; +#else varColor = inVertexColor; +#endif } diff --git a/client/shaders/nodes_shader/opengl_vertex.glsl b/client/shaders/nodes_shader/opengl_vertex.glsl index c68df4a8e..1a4840d35 100644 --- a/client/shaders/nodes_shader/opengl_vertex.glsl +++ b/client/shaders/nodes_shader/opengl_vertex.glsl @@ -146,10 +146,14 @@ void main(void) // the brightness, so now we have to multiply these // colors with the color of the incoming light. // The pre-baked colors are halved to prevent overflow. - vec4 color; +#ifdef GL_ES + vec4 color = inVertexColor.bgra; +#else + vec4 color = inVertexColor; +#endif // The alpha gives the ratio of sunlight in the incoming light. - float nightRatio = 1.0 - inVertexColor.a; - color.rgb = inVertexColor.rgb * (inVertexColor.a * dayLight.rgb + + float nightRatio = 1.0 - color.a; + color.rgb = color.rgb * (color.a * dayLight.rgb + nightRatio * artificialLight.rgb) * 2.0; color.a = 1.0; diff --git a/client/shaders/object_shader/opengl_vertex.glsl b/client/shaders/object_shader/opengl_vertex.glsl index b4a4d0aaa..f26224e82 100644 --- a/client/shaders/object_shader/opengl_vertex.glsl +++ b/client/shaders/object_shader/opengl_vertex.glsl @@ -49,5 +49,9 @@ void main(void) : directional_ambient(normalize(inVertexNormal)); #endif +#ifdef GL_ES + varColor = inVertexColor.bgra; +#else varColor = inVertexColor; +#endif } diff --git a/client/shaders/selection_shader/opengl_vertex.glsl b/client/shaders/selection_shader/opengl_vertex.glsl index 9ca87a9cf..39dde3056 100644 --- a/client/shaders/selection_shader/opengl_vertex.glsl +++ b/client/shaders/selection_shader/opengl_vertex.glsl @@ -6,5 +6,9 @@ void main(void) varTexCoord = inTexCoord0.st; gl_Position = mWorldViewProj * inVertexPosition; +#ifdef GL_ES + varColor = inVertexColor.bgra; +#else varColor = inVertexColor; +#endif }