diff --git a/ChangeLog.md b/ChangeLog.md index 20db36fee..cd7468304 100644 --- a/ChangeLog.md +++ b/ChangeLog.md @@ -1,3 +1,22 @@ +# 1.4.4 -> 1.4.5 + +### Stability +* Fixed crash on creature spellcasting +* Fixed crash on unit entering magical obstacles such as quicksands +* Fixed freeze on map loading on some systems + +### Random Maps Generator +* Fixed placement of guards sometimes resulting into open connection into third zone +* Fixed rare crash on multithreaded access during placement of artifacts or wandering monsters + +### Map Editor +* Fixed inspector using wrong editor for some values + +# 1.4.3 -> 1.4.4 + +### General +* Fixed crash on generation of random maps + # 1.4.2 -> 1.4.3 ### General diff --git a/android/vcmi-app/build.gradle b/android/vcmi-app/build.gradle index 7a88a69fd..b8ab1c6ef 100644 --- a/android/vcmi-app/build.gradle +++ b/android/vcmi-app/build.gradle @@ -10,8 +10,8 @@ android { applicationId "is.xyz.vcmi" minSdk 19 targetSdk 33 - versionCode 1441 - versionName "1.4.4" + versionCode 1450 + versionName "1.4.5" setProperty("archivesBaseName", "vcmi") } diff --git a/client/eventsSDL/InputSourceText.cpp b/client/eventsSDL/InputSourceText.cpp index 72afc978d..96edf5fe1 100644 --- a/client/eventsSDL/InputSourceText.cpp +++ b/client/eventsSDL/InputSourceText.cpp @@ -21,10 +21,6 @@ #include -#ifdef VCMI_APPLE -# include -#endif - void InputSourceText::handleEventTextInput(const SDL_TextInputEvent & text) { GH.events().dispatchTextInput(text.text); @@ -37,38 +33,27 @@ void InputSourceText::handleEventTextEditing(const SDL_TextEditingEvent & text) void InputSourceText::startTextInput(const Rect & whereInput) { - -#ifdef VCMI_APPLE - dispatch_async(dispatch_get_main_queue(), ^{ -#endif - - Rect rectInScreenCoordinates = GH.screenHandler().convertLogicalPointsToWindow(whereInput); - SDL_Rect textInputRect = CSDL_Ext::toSDL(rectInScreenCoordinates); - - SDL_SetTextInputRect(&textInputRect); - - if (SDL_IsTextInputActive() == SDL_FALSE) + GH.dispatchMainThread([whereInput]() { - SDL_StartTextInput(); - } + Rect rectInScreenCoordinates = GH.screenHandler().convertLogicalPointsToWindow(whereInput); + SDL_Rect textInputRect = CSDL_Ext::toSDL(rectInScreenCoordinates); -#ifdef VCMI_APPLE + SDL_SetTextInputRect(&textInputRect); + + if (SDL_IsTextInputActive() == SDL_FALSE) + { + SDL_StartTextInput(); + } }); -#endif } void InputSourceText::stopTextInput() { -#ifdef VCMI_APPLE - dispatch_async(dispatch_get_main_queue(), ^{ -#endif - - if (SDL_IsTextInputActive() == SDL_TRUE) + GH.dispatchMainThread([]() { - SDL_StopTextInput(); - } - -#ifdef VCMI_APPLE + if (SDL_IsTextInputActive() == SDL_TRUE) + { + SDL_StopTextInput(); + } }); -#endif } diff --git a/client/widgets/TextControls.cpp b/client/widgets/TextControls.cpp index 344d20757..6fbab6605 100644 --- a/client/widgets/TextControls.cpp +++ b/client/widgets/TextControls.cpp @@ -553,8 +553,7 @@ Point CGStatusBar::getBorderSize() CTextInput::CTextInput(const Rect & Pos, EFonts font, const CFunctionList & CB, bool giveFocusToInput) : CLabel(Pos.x, Pos.y, font, ETextAlignment::CENTER), - cb(CB), - CFocusable(std::make_shared(this)) + cb(CB) { setRedrawParent(true); pos.h = Pos.h; @@ -570,7 +569,7 @@ CTextInput::CTextInput(const Rect & Pos, EFonts font, const CFunctionList & CB) - :cb(CB), CFocusable(std::make_shared(this)) + :cb(CB) { pos += Pos.topLeft(); pos.h = Pos.h; @@ -587,7 +586,6 @@ CTextInput::CTextInput(const Rect & Pos, const Point & bgOffset, const ImagePath } CTextInput::CTextInput(const Rect & Pos, std::shared_ptr srf) - :CFocusable(std::make_shared(this)) { pos += Pos.topLeft(); OBJ_CONSTRUCTION; @@ -603,20 +601,15 @@ CTextInput::CTextInput(const Rect & Pos, std::shared_ptr srf) #endif } -std::atomic CKeyboardFocusListener::usageIndex(0); +std::atomic CFocusable::usageIndex(0); -CKeyboardFocusListener::CKeyboardFocusListener(CTextInput * textInput) - :textInput(textInput) +void CFocusable::focusGot() { -} - -void CKeyboardFocusListener::focusGot() -{ - GH.startTextInput(textInput->pos); + GH.startTextInput(pos); usageIndex++; } -void CKeyboardFocusListener::focusLost() +void CFocusable::focusLost() { if(0 == --usageIndex) { @@ -769,12 +762,6 @@ void CTextInput::numberFilter(std::string & text, const std::string & oldText, i } CFocusable::CFocusable() - :CFocusable(std::make_shared()) -{ -} - -CFocusable::CFocusable(std::shared_ptr focusListener) - : focusListener(focusListener) { focus = false; focusables.push_back(this); @@ -785,7 +772,7 @@ CFocusable::~CFocusable() if(hasFocus()) { inputWithFocus = nullptr; - focusListener->focusLost(); + focusLost(); } focusables -= this; @@ -799,13 +786,13 @@ bool CFocusable::hasFocus() const void CFocusable::giveFocus() { focus = true; - focusListener->focusGot(); + focusGot(); redraw(); if(inputWithFocus) { inputWithFocus->focus = false; - inputWithFocus->focusListener->focusLost(); + inputWithFocus->focusLost(); inputWithFocus->redraw(); } @@ -837,7 +824,7 @@ void CFocusable::removeFocus() if(this == inputWithFocus) { focus = false; - focusListener->focusLost(); + focusLost(); redraw(); inputWithFocus = nullptr; diff --git a/client/widgets/TextControls.h b/client/widgets/TextControls.h index 7c6b5266b..d922d0f87 100644 --- a/client/widgets/TextControls.h +++ b/client/widgets/TextControls.h @@ -163,25 +163,12 @@ public: void clear() override; void setEnteringMode(bool on) override; void setEnteredText(const std::string & text) override; - -}; - -class CFocusable; - -class IFocusListener -{ -public: - virtual void focusGot() {}; - virtual void focusLost() {}; - virtual ~IFocusListener() = default; }; /// UIElement which can get input focus class CFocusable : public virtual CIntObject { -private: - std::shared_ptr focusListener; - + static std::atomic usageIndex; public: bool focus; //only one focusable control can have focus at one moment @@ -190,38 +177,27 @@ public: void removeFocus(); //remove focus bool hasFocus() const; + void focusGot(); + void focusLost(); + static std::list focusables; //all existing objs static CFocusable * inputWithFocus; //who has focus now CFocusable(); - CFocusable(std::shared_ptr focusListener); ~CFocusable(); }; -class CTextInput; -class CKeyboardFocusListener : public IFocusListener -{ -private: - static std::atomic usageIndex; - CTextInput * textInput; - -public: - CKeyboardFocusListener(CTextInput * textInput); - void focusGot() override; - void focusLost() override; -}; - /// Text input box where players can enter text class CTextInput : public CLabel, public CFocusable { std::string newText; std::string helpBox; //for right-click help - + protected: std::string visibleText() override; public: - + CFunctionList cb; CFunctionList filters; void setText(const std::string & nText) override; diff --git a/cmake_modules/VersionDefinition.cmake b/cmake_modules/VersionDefinition.cmake index 14867224a..1e8c6240a 100644 --- a/cmake_modules/VersionDefinition.cmake +++ b/cmake_modules/VersionDefinition.cmake @@ -1,6 +1,6 @@ set(VCMI_VERSION_MAJOR 1) set(VCMI_VERSION_MINOR 4) -set(VCMI_VERSION_PATCH 4) +set(VCMI_VERSION_PATCH 5) add_definitions( -DVCMI_VERSION_MAJOR=${VCMI_VERSION_MAJOR} -DVCMI_VERSION_MINOR=${VCMI_VERSION_MINOR} diff --git a/debian/changelog b/debian/changelog index 144b17e94..a2ad89bfa 100644 --- a/debian/changelog +++ b/debian/changelog @@ -1,3 +1,9 @@ +vcmi (1.4.5) jammy; urgency=medium + + * New upstream release + + -- Ivan Savenko Tue, 23 Jan 2024 12:00:00 +0200 + vcmi (1.4.4) jammy; urgency=medium * New upstream release diff --git a/launcher/eu.vcmi.VCMI.metainfo.xml b/launcher/eu.vcmi.VCMI.metainfo.xml index c043968f3..d1e30f3ad 100644 --- a/launcher/eu.vcmi.VCMI.metainfo.xml +++ b/launcher/eu.vcmi.VCMI.metainfo.xml @@ -76,6 +76,7 @@ + diff --git a/launcher/modManager/cmodlist.cpp b/launcher/modManager/cmodlist.cpp index b36d4b198..6facca796 100644 --- a/launcher/modManager/cmodlist.cpp +++ b/launcher/modManager/cmodlist.cpp @@ -38,6 +38,9 @@ bool CModEntry::isEnabled() const if(!isInstalled()) return false; + if (!isVisible()) + return false; + return modSettings["active"].toBool(); } diff --git a/launcher/modManager/cmodlistview_moc.cpp b/launcher/modManager/cmodlistview_moc.cpp index f27573aef..556b7945b 100644 --- a/launcher/modManager/cmodlistview_moc.cpp +++ b/launcher/modManager/cmodlistview_moc.cpp @@ -521,7 +521,7 @@ QStringList CModListView::findDependentMods(QString mod, bool excludeDisabled) { auto current = modModel->getMod(modName); - if(!current.isInstalled()) + if(!current.isInstalled() || !current.isVisible()) continue; if(current.getDependencies().contains(mod, Qt::CaseInsensitive)) diff --git a/launcher/translation/spanish.ts b/launcher/translation/spanish.ts index 10c94498e..ae2c67cbf 100644 --- a/launcher/translation/spanish.ts +++ b/launcher/translation/spanish.ts @@ -6,84 +6,84 @@ VCMI on Discord - VCMI en Discord + VCMI en Discord Have a question? Found a bug? Want to help? Join us! - ¿Tienes alguna pregunta? ¿Encontraste algún error? ¿Quieres ayudar? ¡Únete a nosotros! + ¿Tienes alguna pregunta? ¿Encontraste algún error? ¿Quieres ayudar? ¡Únete a nosotros! VCMI on Github - VCMI en Github + VCMI en Github Our Community - + Nuestra comunidad VCMI on Slack - VCMI en Slack + VCMI en Slack Build Information - + Información de la versión User data directory - Directorio de datos del usuario + Directorio de datos del usuario Open - Abrir + Abrir Check for updates - + Comprobar actualizaciones Game version - + Versión del juego Log files directory - Directorio de archivos de registro + Directorio de archivos de registro Data Directories - Directorios de datos + Directorios de datos Game data directory - + Directorio de los datos del juego Operating System - + Sistema operativo Project homepage - + Página web del proyecto Report a bug - + Informar de un error @@ -121,7 +121,7 @@ Maps - + Mapas @@ -180,7 +180,7 @@ Compatibility - Compatibilidad + Compatibilidad @@ -319,7 +319,7 @@ Size - + Tamaño @@ -410,12 +410,12 @@ Downloading %s%. %p% (%v MB out of %m MB) finished - + Descargando %s%. %p% (%v MB de %m MB) completado Download failed - + Descarga fallida @@ -424,30 +424,37 @@ Encountered errors: - + No se han podido descargar todos los ficheros. + +Errores encontrados: + + Install successfully downloaded? - + + +Instalar lo correctamente descargado? Installing mod %1 - + Instalando mod %1 Operation failed - + Operación fallida Encountered errors: - + Errores encontrados: + @@ -482,94 +489,94 @@ Install successfully downloaded? Interface Scaling - + Escala de la interfaz Neutral AI in battles - + IA neutral en batallas Enemy AI in battles - + IA enemiga en batallas Additional repository - + Repositorio adicional Adventure Map Allies - + Aliados en el Mapa de aventuras Adventure Map Enemies - + Enemigos en el Mapa de aventuras Windowed - + Ventana Borderless fullscreen - + Ventana completa sin bordes Exclusive fullscreen - + Pantalla completa Autosave limit (0 = off) - + Límite de autosaves (0 = sin límite) Friendly AI in battles - + IA amistosa en batallas Framerate Limit - + Límite de fotogramas Autosave prefix - + Prefijo autoguardado empty = map name prefix - + Vacio = prefijo del mapa Refresh now - + Actualizar Default repository - + Repositorio por defecto Renderer - + Render On - Encendido + Activado @@ -584,7 +591,7 @@ Install successfully downloaded? Reserved screen area - + Área de pantalla reservada @@ -614,7 +621,7 @@ Install successfully downloaded? VSync - + Sincronización vertical @@ -640,7 +647,13 @@ Windowed - game will run inside a window that covers part of your screen Borderless Windowed Mode - game will run in a window that covers entirely of your screen, using same resolution as your screen. Fullscreen Exclusive Mode - game will cover entirety of your screen and will use selected resolution. - + Selecciona el modo de visualización del juego + +En ventana - el juego se ejecutará dentro de una ventana que forma parte de tu pantalla. + +Ventana sin bordes - el juego se ejecutará en una ventana que cubre completamente tu pantalla, usando la misma resolución. + +Pantalla completa - el juego cubrirá la totalidad de la pantalla y utilizará la resolución seleccionada. @@ -698,27 +711,27 @@ Fullscreen Exclusive Mode - game will cover entirety of your screen and will use Form - + Formulario Users in lobby - + Usuarios en la sala Global chat - + Chat general type you message - + Escribe tu mensaje send - + Enviar @@ -792,12 +805,12 @@ Fullscreen Exclusive Mode - game will cover entirety of your screen and will use Interface Improvements - + Mejora de la interfaz Install mod that provides various interface improvements, such as better interface for random maps and selectable actions in battles - + Instalar mod que proporciona varias mejoras en la interfaz, como mejor interacción en los mapas aleatorios y más opciones en las batallas @@ -921,7 +934,7 @@ Ten en cuenta que para usar VCMI debes ser dueño de los archivos de datos origi Czech - + Czech (Checo) @@ -936,7 +949,7 @@ Ten en cuenta que para usar VCMI debes ser dueño de los archivos de datos origi Finnish - + Finnish (Finlandés) @@ -951,12 +964,12 @@ Ten en cuenta que para usar VCMI debes ser dueño de los archivos de datos origi Hungarian - + Hungarian (Húngaro) Italian - + Italian (Italiano) @@ -971,7 +984,7 @@ Ten en cuenta que para usar VCMI debes ser dueño de los archivos de datos origi Portuguese - + Portuguese (Portugués) @@ -986,12 +999,12 @@ Ten en cuenta que para usar VCMI debes ser dueño de los archivos de datos origi Swedish - + Swedish (Sueco) Turkish - + Turkish (Turco) @@ -1001,7 +1014,7 @@ Ten en cuenta que para usar VCMI debes ser dueño de los archivos de datos origi Vietnamese - + Vietnamese (Vietnamita) @@ -1011,12 +1024,12 @@ Ten en cuenta que para usar VCMI debes ser dueño de los archivos de datos origi Other (Cyrillic Script) - + Otro (Escritura cirílica) Other (West European) - + Otro (Europa del Este) @@ -1151,7 +1164,7 @@ Ten en cuenta que para usar VCMI debes ser dueño de los archivos de datos origi Help - + Ayuda diff --git a/lib/bonuses/CBonusSystemNode.cpp b/lib/bonuses/CBonusSystemNode.cpp index 8306e3ae1..92634975d 100644 --- a/lib/bonuses/CBonusSystemNode.cpp +++ b/lib/bonuses/CBonusSystemNode.cpp @@ -273,6 +273,10 @@ CBonusSystemNode::~CBonusSystemNode() void CBonusSystemNode::attachTo(CBonusSystemNode & parent) { + // quick workaround to prevent multithreaded access to bonus system in RMG + static boost::mutex attachMutex; + boost::lock_guard lock(attachMutex); + assert(!vstd::contains(parents, &parent)); parents.push_back(&parent); @@ -646,4 +650,4 @@ int64_t CBonusSystemNode::getTreeVersion() const return treeChanged; } -VCMI_LIB_NAMESPACE_END \ No newline at end of file +VCMI_LIB_NAMESPACE_END diff --git a/lib/rmg/modificators/ConnectionsPlacer.cpp b/lib/rmg/modificators/ConnectionsPlacer.cpp index 73e9b5837..f765eeb00 100644 --- a/lib/rmg/modificators/ConnectionsPlacer.cpp +++ b/lib/rmg/modificators/ConnectionsPlacer.cpp @@ -177,6 +177,21 @@ void ConnectionsPlacer::selfSideDirectConnection(const rmg::ZoneConnection & con int3 potentialPos = zone.areaPossible().nearest(borderPos); assert(borderPos != potentialPos); + //Check if guard pos doesn't touch any 3rd zone. This would create unwanted passage to 3rd zone + bool adjacentZone = false; + map.foreach_neighbour(potentialPos, [this, &adjacentZone, otherZoneId](int3 & pos) + { + auto zoneId = map.getZoneID(pos); + if (zoneId != zone.getId() && zoneId != otherZoneId) + { + adjacentZone = true; + } + }); + if (adjacentZone) + { + continue; + } + //Take into account distance to objects from both sides float dist = std::min(map.getTileInfo(potentialPos).getNearestObjectDistance(), map.getTileInfo(borderPos).getNearestObjectDistance()); diff --git a/mapeditor/inspector/inspector.h b/mapeditor/inspector/inspector.h index 432e40ab0..94c2b80c2 100644 --- a/mapeditor/inspector/inspector.h +++ b/mapeditor/inspector/inspector.h @@ -128,7 +128,6 @@ protected: { itemKey = keyItems[key]; table->setItem(table->row(itemKey), 1, itemValue); - if(delegate) table->setItemDelegateForRow(table->row(itemKey), delegate); } else @@ -139,7 +138,6 @@ protected: table->setRowCount(row + 1); table->setItem(row, 0, itemKey); table->setItem(row, 1, itemValue); - if(delegate) table->setItemDelegateForRow(row, delegate); ++row; }