diff --git a/.editorconfig b/.editorconfig
new file mode 100644
index 000000000..25cc3fffc
--- /dev/null
+++ b/.editorconfig
@@ -0,0 +1,11 @@
+root = true
+
+[*.cpp]
+indent_style = space
+indent_size = 4
+insert_final_newline = true
+
+[*.hpp]
+indent_style = space
+indent_size = 4
+insert_final_newline = true
\ No newline at end of file
diff --git a/.gitignore b/.gitignore
index 5d98a8317..e37fc7721 100644
--- a/.gitignore
+++ b/.gitignore
@@ -26,6 +26,7 @@ Doxygen
.settings
.directory
.idea
+files/windows/*.aps
cmake-build-*
## qt-creator
CMakeLists.txt.user*
diff --git a/.travis.yml b/.travis.yml
index aba38727c..52793ed65 100644
--- a/.travis.yml
+++ b/.travis.yml
@@ -12,8 +12,10 @@ branches:
- /openmw-.*$/
env:
global:
+ # The next declaration is the encrypted COVERITY_SCAN_TOKEN, created
+ # via the "travis encrypt" command using the project repo's public key
- secure: NZmvVuA0O9NJXVQ12tXQZHDJC2mbFgYNFcsicw0DgW1It2Nk5hxIkF0pfu4/Z59mhQuOPgRVjl5b0FKy2Axh0gkWc1DJEXGwNaiW5lpTMNWR1LJG5rxa8LrDUpFkycpbzfAFuTUZu5z3iYVv64XzELvBuqNGhPMu1LeBnrlech0jFNjkR9p5qtJGWb8zYcPMCC57rig8a9g1ABoVYS6UXjrKpx0946ZLRsE5ukc9pXsypGwPmOMyfzZkxxzIqFaxoE5JIEdaJTWba/6Za315ozYYIi/N35ROI1YAv5GHRe/Iw9XAa4vQpbDzjM7ZSsZdTvvQsSU598gD2xC6jFUKSrpW6GZKwM2x236fZLGnOk5Uw7DUbG+AwpcEmxBwoy9PjBl9ZF3tJykI0gROewCy8MODhdsVMKr1HGIMVBIJySm/RnNqtoDbYV8mYnSl5b8rwJiCajoiR8Zuv4CIfGneeH1a3DOQDPH/qkDsU6ilzF4ANsBlMUUpgY653KBMBmTlNuVZSH527tnD7Fg6JgHVuSQkTbRa1vSkR7Zcre604RZcAoaEdbX3bhVDasPPghU/I742L0RH3oQNlR09pPBDZ8kG7ydl4aPHwpCWnvXNM1vgxtGvnYLztwrse7IoaRXRYiMFmrso78WhMWUDKgvY4wV9aeUu0DtnMezZVIQwCKg=
- - macos_qt_formula=qt@5.7
+ - macos_qt_formula=qt
addons:
apt:
sources:
diff --git a/AUTHORS.md b/AUTHORS.md
index 6125ed36d..bb773c4ef 100644
--- a/AUTHORS.md
+++ b/AUTHORS.md
@@ -50,6 +50,7 @@ Programmers
Edmondo Tommasina (edmondo)
Eduard Cot (trombonecot)
Eli2
+ elsid
Emanuel Guével (potatoesmaster)
eroen
escondida
@@ -59,10 +60,11 @@ Programmers
Gašper Sedej
gugus/gus
Hallfaer Tuilinn
+ Haoda Wang (h313)
hristoast
Internecine
- Jacob Essex (Yacoby)
- Jannik Heller (scrawl)
+ Jacob Essex (Yacoby)
+ Jake Westrip (16bitint)
Jason Hooks (jhooks)
jeaye
Jeffrey Haines (Jyby)
@@ -131,12 +133,14 @@ Programmers
Roman Proskuryakov (kpp)
Sandy Carter (bwrsandman)
Scott Howard
+ scrawl
Sebastian Wick (swick)
Sergey Shambir
ShadowRadiance
Siimacore
sir_herrbatka
smbas
+ spycrab
Stefan Galowicz (bogglez)
Stanislav Bobrov (Jiub)
stil-t
@@ -145,6 +149,7 @@ Programmers
t6
terrorfisch
Thomas Luppi (Digmaster)
+ Will Herrmann (Thunderforge)
Tom Mason (wheybags)
Torben Leif Carrington (TorbenC)
viadanna
diff --git a/CHANGELOG.md b/CHANGELOG.md
index 87d826753..b390169c6 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -1,3 +1,82 @@
+0.42.0
+------
+
+ Bug #1956: Duplicate objects after loading the game, when a mod was edited
+ Bug #2100: Falling leaves in Vurt's Leafy West Gash II not rendered correctly
+ Bug #2116: Cant fit through some doorways pressed against staircases
+ Bug #2289: Some modal dialogs are not centered on the screen when the window resizes
+ Bug #2409: Softlock when pressing weapon/magic switch keys during chargen, afterwards switches weapons even though a text field is selected
+ Bug #2483: Previous/Next Weapon hotkeys triggered while typing the name of game save
+ Bug #2629: centeroncell, coc causes death / fall damage time to time when teleporting from high
+ Bug #2645: Cycling weapons is possible while console/pause menu is open
+ Bug #2678: Combat with water creatures do not end upon exiting water
+ Bug #2759: Light Problems in Therana's Chamber in Tel Branora
+ Bug #2771: unhandled sdl event of type 0x302
+ Bug #2777: (constant/on cast) disintegrate armor/weapon on self is seemingly not working
+ Bug #2838: Editor: '.' in a record name should be allowed
+ Bug #2909: NPCs appear floating when standing on a slope
+ Bug #3093: Controller movement cannot be used while mouse is moving
+ Bug #3134: Crash possible when using console with open container
+ Bug #3254: AI enemies hit between them.
+ Bug #3344: Editor: Verification results sorting by Type is not alphabetical.
+ Bug #3345: Editor: Cloned and added pathgrids are lost after reopen of saved omwgame file
+ Bug #3355: [MGSO] Physics maxing out in south cornerclub Balmora
+ Bug #3484: Editor: camera position is not set when changing cell via drag&drop
+ Bug #3508: Slowfall kills Jump momentum
+ Bug #3580: Crash: Error ElementBufferObject::remove BufferData<0> out of range
+ Bug #3581: NPCs wander too much
+ Bug #3601: Menu Titles not centered vertically
+ Bug #3607: [Mac OS] Beginning of NPC speech cut off (same issue as closed bug #3453)
+ Bug #3613: Can not map "next weapon" or "next spell" to controller
+ Bug #3617: Enchanted arrows don't explode when hitting the ground
+ Bug #3645: Unable to use steps in Vivec, Palace of Vivec
+ Bug #3650: Tamriel Rebuilt 16.09.1 – Hist Cuirass GND nif is rendered inside a Pink Box
+ Bug #3652: Item icon shadows get stuck in the alchemy GUI
+ Bug #3653: Incorrect swish sounds
+ Bug #3666: NPC collision should not be disabled until death animation has finished
+ Bug #3669: Editor: Text field was missing from book object editing dialogue
+ Bug #3670: Unhandled SDL event of type 0x304
+ Bug #3671: Incorrect local variable value after picking up bittercup
+ Bug #3686: Travelling followers doesn't increase travel fee
+ Bug #3689: Problematic greetings from Antares Big Mod that override the appropriate ones.
+ Bug #3690: Certain summoned creatures do not engage in combat with underwater creatures
+ Bug #3691: Enemies do not initiate combat with player followers on sight
+ Bug #3695: [Regression] Dispel does not always dispel spell effects in 0.41
+ Bug #3699: Crash on MWWorld::ProjectileManager::moveMagicBolts
+ Bug #3700: Climbing on rocks and mountains
+ Bug #3704: Creatures don't auto-equip their shields on creation
+ Bug #3705: AI combat engagement logic differs from vanilla
+ Bug #3707: Animation playing does some very odd things if pc comes in contact with the animated mesh
+ Bug #3712: [Mod] Freeze upon entering Adanumuran with mod Adanumuran Reclaimed
+ Bug #3713: [Regression] Cancelling dialogue or using travel with creatures throws a (possibly game-breaking) exception
+ Bug #3719: Dropped identification papers can't be picked up again
+ Bug #3722: Command spell doesn't bring enemies out of combat
+ Bug #3727: Using "Activate" mid-script-execution invalidates interpreter context
+ Bug #3746: Editor: Book records show attribute IDs instead of skill IDs for teached skills entry.
+ Bug #3755: Followers stop following after loading from savegame
+ Bug #3772: ModStat lowers attribute to 100 if it was greater
+ Bug #3781: Guns in Clean Hunter Rifles mod use crossbow sounds
+ Bug #3797: NPC and creature names don't show up in combat when RMB windows are displayed
+ Bug #3800: Wrong tooltip maximum width
+ Bug #3801: Drowning widget is bugged
+ Bug #3802: BarterOffer shouldn't limit pcMercantile
+ Bug #3813: Some fatal error
+ Bug #3816: Expression parser thinks the -> token is unexpected when a given explicit refID clashes with a journal ID
+ Bug #3822: Custom added creatures are not animated
+ Feature #451: Water sounds
+ Feature #2691: Light particles sometimes not shown in inventory character preview
+ Feature #3523: Light source on magic projectiles
+ Feature #3644: Nif NiSphericalCollider Unknown Record Type
+ Feature #3675: ess-Importer: convert mark location
+ Feature #3693: ess-Importer: convert last known exterior cell
+ Feature #3748: Editor: Replace "Scroll" check box in Book records with "Book Type" combo box.
+ Feature #3751: Editor: Replace "Xyz Blood" check boxes in NPC and Creature records with "Blood Type" combo box
+ Feature #3752: Editor: Replace emitter check boxes in Light records with "Emitter Type" combo box
+ Feature #3756: Editor: Replace "Female" check box in NPC records with "Gender" combo box
+ Feature #3757: Editor: Replace "Female" check box in BodyPart records with "Gender" combo box
+ Task #3092: const version of ContainerStoreIterator
+ Task #3795: /deps folder not in .gitignore
+
0.41.0
------
diff --git a/CI/deploy.osx.sh b/CI/deploy.osx.sh
index 1ff6f89c3..53bfa18b5 100755
--- a/CI/deploy.osx.sh
+++ b/CI/deploy.osx.sh
@@ -6,4 +6,4 @@ DATE=`date +'%d%m%Y'`
SHORT_COMMIT=`git rev-parse --short ${TRAVIS_COMMIT}`
TARGET_FILENAME="OpenMW-${DATE}-${SHORT_COMMIT}.dmg"
-curl --ssl --ftp-create-dirs -T *.dmg -u $OSX_FTP_USER:$OSX_FTP_PASSWORD "ftp://s3.mydevil.net:21/nightly/${TARGET_FILENAME}"
+curl --ssl --ftp-create-dirs -T *.dmg -u $OSX_FTP_USER:$OSX_FTP_PASSWORD "${OSX_FTP_URL}${TARGET_FILENAME}"
diff --git a/CMakeLists.txt b/CMakeLists.txt
index a184ad11f..8f6889515 100644
--- a/CMakeLists.txt
+++ b/CMakeLists.txt
@@ -25,7 +25,7 @@ endif()
message(STATUS "Configuring OpenMW...")
set(OPENMW_VERSION_MAJOR 0)
-set(OPENMW_VERSION_MINOR 41)
+set(OPENMW_VERSION_MINOR 42)
set(OPENMW_VERSION_RELEASE 0)
set(OPENMW_VERSION_COMMITHASH "")
@@ -436,7 +436,7 @@ IF(NOT WIN32 AND NOT APPLE)
# Install icon and desktop file
INSTALL(FILES "${OpenMW_BINARY_DIR}/openmw.desktop" DESTINATION "${DATAROOTDIR}/applications" COMPONENT "openmw")
INSTALL(FILES "${OpenMW_SOURCE_DIR}/files/launcher/images/openmw.png" DESTINATION "${ICONDIR}" COMPONENT "openmw")
- INSTALL(FILES "${OpenMW_BINARY_DIR}/openmw.appdata.xml" DESTINATION "${DATAROOTDIR}/appdata" COMPONENT "openmw")
+ INSTALL(FILES "${OpenMW_BINARY_DIR}/openmw.appdata.xml" DESTINATION "${DATAROOTDIR}/metainfo" COMPONENT "openmw")
IF(BUILD_OPENCS)
INSTALL(FILES "${OpenMW_BINARY_DIR}/openmw-cs.desktop" DESTINATION "${DATAROOTDIR}/applications" COMPONENT "opencs")
INSTALL(FILES "${OpenMW_SOURCE_DIR}/files/opencs/openmw-cs.png" DESTINATION "${ICONDIR}" COMPONENT "opencs")
@@ -768,17 +768,19 @@ if (WIN32)
endif()
# Apple bundling
-if (APPLE AND DESIRED_QT_VERSION MATCHES 5)
+if (OPENMW_OSX_DEPLOYMENT AND APPLE AND DESIRED_QT_VERSION MATCHES 5)
get_property(QT_COCOA_PLUGIN_PATH TARGET Qt5::QCocoaIntegrationPlugin PROPERTY LOCATION_RELEASE)
get_filename_component(QT_COCOA_PLUGIN_DIR "${QT_COCOA_PLUGIN_PATH}" DIRECTORY)
get_filename_component(QT_COCOA_PLUGIN_GROUP "${QT_COCOA_PLUGIN_DIR}" NAME)
get_filename_component(QT_COCOA_PLUGIN_NAME "${QT_COCOA_PLUGIN_PATH}" NAME)
- configure_file("${QT_COCOA_PLUGIN_PATH}" "${APP_BUNDLE_DIR}/Contents/MacOS/${QT_COCOA_PLUGIN_GROUP}/${QT_COCOA_PLUGIN_NAME}" COPYONLY)
+ configure_file("${QT_COCOA_PLUGIN_PATH}" "${APP_BUNDLE_DIR}/Contents/PlugIns/${QT_COCOA_PLUGIN_GROUP}/${QT_COCOA_PLUGIN_NAME}" COPYONLY)
+ configure_file("${OpenMW_SOURCE_DIR}/files/mac/qt.conf" "${APP_BUNDLE_DIR}/Contents/Resources/qt.conf" COPYONLY)
if (BUILD_OPENCS)
get_property(OPENCS_BUNDLE_NAME_TMP TARGET openmw-cs PROPERTY OUTPUT_NAME)
set(OPENCS_BUNDLE_NAME "${OPENCS_BUNDLE_NAME_TMP}.app")
- configure_file("${QT_COCOA_PLUGIN_PATH}" "${OPENCS_BUNDLE_NAME}/Contents/MacOS/${QT_COCOA_PLUGIN_GROUP}/${QT_COCOA_PLUGIN_NAME}" COPYONLY)
+ configure_file("${QT_COCOA_PLUGIN_PATH}" "${OPENCS_BUNDLE_NAME}/Contents/PlugIns/${QT_COCOA_PLUGIN_GROUP}/${QT_COCOA_PLUGIN_NAME}" COPYONLY)
+ configure_file("${OpenMW_SOURCE_DIR}/files/mac/qt.conf" "${OPENCS_BUNDLE_NAME}/Contents/Resources/qt.conf" COPYONLY)
endif ()
install(DIRECTORY "${APP_BUNDLE_DIR}" USE_SOURCE_PERMISSIONS DESTINATION "." COMPONENT Runtime)
@@ -837,8 +839,8 @@ if (APPLE AND DESIRED_QT_VERSION MATCHES 5)
install_plugins_for_bundle("${APP_BUNDLE_NAME}" PLUGINS)
install_plugins_for_bundle("${OPENCS_BUNDLE_NAME}" OPENCS_PLUGINS)
- set(PLUGINS ${PLUGINS} "${INSTALLED_OPENMW_APP}/Contents/MacOS/${QT_COCOA_PLUGIN_GROUP}/${QT_COCOA_PLUGIN_NAME}")
- set(OPENCS_PLUGINS ${OPENCS_PLUGINS} "${INSTALLED_OPENCS_APP}/Contents/MacOS/${QT_COCOA_PLUGIN_GROUP}/${QT_COCOA_PLUGIN_NAME}")
+ set(PLUGINS ${PLUGINS} "${INSTALLED_OPENMW_APP}/Contents/PlugIns/${QT_COCOA_PLUGIN_GROUP}/${QT_COCOA_PLUGIN_NAME}")
+ set(OPENCS_PLUGINS ${OPENCS_PLUGINS} "${INSTALLED_OPENCS_APP}/Contents/PlugIns/${QT_COCOA_PLUGIN_GROUP}/${QT_COCOA_PLUGIN_NAME}")
install(CODE "
function(gp_item_default_embedded_path_override item default_embedded_path_var)
@@ -848,12 +850,11 @@ if (APPLE AND DESIRED_QT_VERSION MATCHES 5)
endif()
endfunction()
- cmake_policy(SET CMP0009 OLD)
fixup_bundle(\"${INSTALLED_OPENMW_APP}\" \"${PLUGINS}\" \"\")
fixup_bundle(\"${INSTALLED_OPENCS_APP}\" \"${OPENCS_PLUGINS}\" \"\")
" COMPONENT Runtime)
include(CPack)
-endif (APPLE AND DESIRED_QT_VERSION MATCHES 5)
+endif ()
# Doxygen Target -- simply run 'make doc' or 'make doc_pages'
# output directory for 'make doc' is "${OpenMW_BINARY_DIR}/docs/Doxygen"
diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md
index 466910ca3..b5a7423d2 100644
--- a/CONTRIBUTING.md
+++ b/CONTRIBUTING.md
@@ -33,3 +33,38 @@ Furthermore, we advise to:
* Feel free to submit incomplete pull requests. Even if the work can not be merged yet, pull requests are a great place to collect early feedback. Just make sure to mark it as *[Incomplete]* or *[Do not merge yet]* in the title.
* If you plan on contributing often, please read the [Developer Reference](https://wiki.openmw.org/index.php?title=Developer_Reference) on our wiki, especially the [Policies and Standards](https://wiki.openmw.org/index.php?title=Policies_and_Standards).
* Make sure each of your changes has a clear objective. Unnecessary changes may lead to merge conflicts, clutter the commit history and slow down review. Code formatting 'fixes' should be avoided, unless you were already changing that particular line anyway.
+
+Guidelines for original engine "fixes"
+=================================
+
+From time to time you may be tempted to "fix" what you think was a "bug" in the original game engine.
+
+Unfortunately, the definition of what is a "bug" is not so clear. Consider that your "bug" is actually a feature unless proven otherwise:
+
+* We have no way of knowing what the original developers really intended (short of asking them, good luck with that).
+* What may seem like an illogical mechanic can actually be part of an attempt to balance the game.
+* Many people will actually like these "bugs" because that is what they remember the game for.
+* Exploits may be part of the fun of an open-world game - they reward knowledge with power. There are too many of them to plug them all, anyway.
+
+OpenMW, in its default configuration, is meant to be a faithful reimplementation of Morrowind, minus things like crash bugs, stability issues and design errors. However, we try to avoid touching anything that affects the core gameplay, the balancing of the game or introduces incompatibilities with existing mod content.
+
+That said, we may sometimes evaluate such issues on an individual basis. Common exceptions to the above would be:
+
+* Issues so glaring that they would severely limit the capabilities of the engine in the future (for example, the scripting engine not being allowed to access objects in remote cells)
+* Bugs where the intent is very obvious, and that have little to no balancing impact (e.g. the bug were being tired made it easier to repair items, instead of harder)
+* Bugs that were fixed in an official patch for Morrowind
+
+Feature additions policy
+=====================
+
+We get it, you have waited so long for feature XYZ to be available in Morrowind and now that OpenMW is here you can not wait to implement your ingenious idea and share it with the world.
+
+Unfortunately, since maintaining features comes at a cost and our resources are limited, we have to be a little selective in what features we allow into the main repository. Generally:
+
+- Features should be as generic and non-redundant as possible.
+- Any feature that is also possible with modding should be done as a mod instead.
+- In the future, OpenMW plans to expand the scope of what is possible with modding, e.g. by moving certain game logic into editable scripts.
+- Currently, modders can edit OpenMW's GUI skins and layout XML files, although there are still a few missing hooks (e.g. scripting support) in order to make this into a powerful way of modding.
+- If a feature introduces new game UI strings, that reduces its chance of being accepted because we do not currently have any way of localizing these to the user's Morrowind installation language.
+
+If you are in doubt of your feature being within our scope, it is probably best to start a forum discussion first. See the [settings documentation](https://openmw.readthedocs.io/en/stable/reference/modding/settings/index.html) and [Features list](https://wiki.openmw.org/index.php?title=Features) for some examples of features that were deemed acceptable.
diff --git a/apps/browser/QueryHelper.cpp b/apps/browser/QueryHelper.cpp
index 325e9df74..1307bd03b 100644
--- a/apps/browser/QueryHelper.cpp
+++ b/apps/browser/QueryHelper.cpp
@@ -27,9 +27,11 @@ QueryHelper::QueryHelper(QAbstractItemModel *model)
void QueryHelper::refresh()
{
if (!queryThread->isRunning())
+ {
_model->removeRows(0, _model->rowCount());
- queryThread->start();
- emit started();
+ queryThread->start();
+ emit started();
+ }
}
void QueryHelper::terminate()
diff --git a/apps/browser/netutils/QueryClient.cpp b/apps/browser/netutils/QueryClient.cpp
index c82957473..73d68ccf9 100644
--- a/apps/browser/netutils/QueryClient.cpp
+++ b/apps/browser/netutils/QueryClient.cpp
@@ -7,6 +7,7 @@
#include
#include
#include
+#include
using namespace RakNet;
using namespace std;
@@ -42,48 +43,87 @@ QueryClient &QueryClient::Get()
map QueryClient::Query()
{
- status = -1;
map query;
- if (Connect() == IS_NOT_CONNECTED)
- return query;
-
BitStream bs;
bs.Write((unsigned char) (ID_MASTER_QUERY));
- int code = peer->Send(&bs, HIGH_PRIORITY, RELIABLE_ORDERED, CHANNEL_MASTER, masterAddr, false);
+ qDebug() << "Locking mutex in QueryClient::Query()";
+ mxServers.lock();
+ status = -1;
+ int attempts = 3;
+ do
+ {
+ if (Connect() == IS_NOT_CONNECTED)
+ {
+ qDebug() << "Unlocking mutex in QueryClient::Query()";
+ mxServers.unlock();
+ return query;
+ }
- if (code == 0)
- return query;
+ int code = peer->Send(&bs, HIGH_PRIORITY, RELIABLE_ORDERED, CHANNEL_MASTER, masterAddr, false);
+
+ if (code == 0)
+ {
+ qDebug() << "Unlocking mutex in QueryClient::Query()";
+ mxServers.unlock();
+ return query;
+ }
+
+ pmq->SetServers(&query);
+ status = GetAnswer(ID_MASTER_QUERY);
+ RakSleep(100);
+ }
+ while(status != ID_MASTER_QUERY && attempts-- > 0);
+ if(status != ID_MASTER_QUERY)
+ qDebug() << "Getting query was failed";
+ qDebug() << "Unlocking mutex in QueryClient::Query()";
+ peer->CloseConnection(masterAddr, true);
+ mxServers.unlock();
+ qDebug() <<"Answer" << (status == ID_MASTER_QUERY ? "ok." : "wrong.");
- pmq->SetServers(&query);
- status = GetAnswer();
return query;
}
pair QueryClient::Update(RakNet::SystemAddress addr)
{
+ qDebug() << "Locking mutex in QueryClient::Update(RakNet::SystemAddress addr)";
pair server;
- if (Connect() == IS_NOT_CONNECTED)
- {
- status = -1;
- return server;
- }
-
BitStream bs;
bs.Write((unsigned char) (ID_MASTER_UPDATE));
bs.Write(addr);
- peer->Send(&bs, HIGH_PRIORITY, RELIABLE_ORDERED, CHANNEL_MASTER, masterAddr, false);
+ mxServers.lock();
+ status = -1;
+ int attempts = 3;
pmu->SetServer(&server);
- status = GetAnswer();
+ do
+ {
+ if (Connect() == IS_NOT_CONNECTED)
+ {
+ qDebug() << IS_NOT_CONNECTED;
+ qDebug() << "Unlocking mutex in QueryClient::Update(RakNet::SystemAddress addr)";
+ mxServers.unlock();
+ return server;
+ }
+
+ peer->Send(&bs, HIGH_PRIORITY, RELIABLE_ORDERED, CHANNEL_MASTER, masterAddr, false);
+ status = GetAnswer(ID_MASTER_UPDATE);
+ RakSleep(100);
+ }
+ while(status != ID_MASTER_UPDATE && attempts-- > 0);
+ if(status != ID_MASTER_UPDATE)
+ qDebug() << "Getting update was failed";
+ peer->CloseConnection(masterAddr, true);
+ qDebug() << "Unlocking mutex in QueryClient::Update(RakNet::SystemAddress addr)";
+ mxServers.unlock();
return server;
}
-MASTER_PACKETS QueryClient::GetAnswer()
+MASTER_PACKETS QueryClient::GetAnswer(MASTER_PACKETS waitingPacket)
{
RakNet::Packet *packet;
bool update = true;
unsigned char pid = 0;
- int id;
+ int id = -1;
while (update)
{
for (packet = peer->Receive(); packet; peer->DeallocatePacket(packet), packet = peer->Receive())
@@ -94,25 +134,37 @@ MASTER_PACKETS QueryClient::GetAnswer()
data.Read(pid);
switch(pid)
{
- case ID_DISCONNECTION_NOTIFICATION:
case ID_CONNECTION_LOST:
+ qDebug() << "ID_CONNECTION_LOST";
+ case ID_DISCONNECTION_NOTIFICATION:
+ qDebug() << "Disconnected";
update = false;
break;
case ID_MASTER_QUERY:
- pmq->Read();
+ qDebug() << "ID_MASTER_QUERY";
+ if (waitingPacket == ID_MASTER_QUERY)
+ pmq->Read();
+ else
+ qDebug() << "Got wrong packet";
update = false;
id = pid;
break;
case ID_MASTER_UPDATE:
- pmu->Read();
+ qDebug() << "ID_MASTER_UPDATE";
+ if (waitingPacket == ID_MASTER_UPDATE)
+ pmu->Read();
+ else
+ qDebug() << "Got wrong packet";
update = false;
id = pid;
break;
case ID_MASTER_ANNOUNCE:
+ qDebug() << "ID_MASTER_ANNOUNCE";
update = false;
id = pid;
break;
case ID_CONNECTION_REQUEST_ACCEPTED:
+ qDebug() << "ID_CONNECTION_REQUEST_ACCEPTED";
break;
default:
break;
@@ -125,6 +177,7 @@ MASTER_PACKETS QueryClient::GetAnswer()
ConnectionState QueryClient::Connect()
{
+
ConnectionAttemptResult car = peer->Connect(masterAddr.ToString(false), masterAddr.GetPort(), TES3MP_MASTERSERVER_PASSW,
strlen(TES3MP_MASTERSERVER_PASSW), 0, 0, 5, 500);
@@ -134,17 +187,19 @@ ConnectionState QueryClient::Connect()
switch (state)
{
case IS_CONNECTED:
+ qDebug() << "Connected";
return IS_CONNECTED;
case IS_NOT_CONNECTED:
case IS_DISCONNECTED:
case IS_SILENTLY_DISCONNECTING:
case IS_DISCONNECTING:
{
- //LOG_MESSAGE_SIMPLE(Log::LOG_WARN, "Cannot connect to master server: %d", masterAddr.ToString());
+ qDebug() << "Cannot connect to the master server. Code:"<< state;
return IS_NOT_CONNECTED;
}
case IS_PENDING:
case IS_CONNECTING:
+ qDebug() << "Pending";
break;
}
RakSleep(500);
diff --git a/apps/browser/netutils/QueryClient.hpp b/apps/browser/netutils/QueryClient.hpp
index 4acd6f553..807cc8704 100644
--- a/apps/browser/netutils/QueryClient.hpp
+++ b/apps/browser/netutils/QueryClient.hpp
@@ -10,6 +10,7 @@
#include
#include
#include
+#include
class QueryClient
{
@@ -26,7 +27,7 @@ public:
int Status();
private:
RakNet::ConnectionState Connect();
- MASTER_PACKETS GetAnswer();
+ MASTER_PACKETS GetAnswer(MASTER_PACKETS packet);
protected:
QueryClient();
~QueryClient();
@@ -37,6 +38,7 @@ private:
mwmp::PacketMasterQuery *pmq;
mwmp::PacketMasterUpdate *pmu;
std::pair server;
+ std::mutex mxServers;
};
diff --git a/apps/launcher/maindialog.cpp b/apps/launcher/maindialog.cpp
index 1c1d57016..10f3ae81b 100644
--- a/apps/launcher/maindialog.cpp
+++ b/apps/launcher/maindialog.cpp
@@ -172,7 +172,10 @@ Launcher::FirstRunDialogResult Launcher::MainDialog::showFirstRunDialog()
}
}
- return setup() ? FirstRunDialogResultContinue : FirstRunDialogResultFailure;
+ if (!setup() || !setupGameData()) {
+ return FirstRunDialogResultFailure;
+ }
+ return FirstRunDialogResultContinue;
}
void Launcher::MainDialog::setVersionLabel()
@@ -344,6 +347,11 @@ bool Launcher::MainDialog::setupGameSettings()
file.close();
}
+ return true;
+}
+
+bool Launcher::MainDialog::setupGameData()
+{
QStringList dataDirs;
// Check if the paths actually contain data files
diff --git a/apps/launcher/maindialog.hpp b/apps/launcher/maindialog.hpp
index 96b5c0b97..8d0d61b8f 100644
--- a/apps/launcher/maindialog.hpp
+++ b/apps/launcher/maindialog.hpp
@@ -72,6 +72,7 @@ namespace Launcher
bool setupLauncherSettings();
bool setupGameSettings();
bool setupGraphicsSettings();
+ bool setupGameData();
void setVersionLabel();
diff --git a/apps/master/MasterServer.cpp b/apps/master/MasterServer.cpp
index c3821d220..f52841317 100644
--- a/apps/master/MasterServer.cpp
+++ b/apps/master/MasterServer.cpp
@@ -16,6 +16,7 @@
using namespace RakNet;
using namespace std;
using namespace mwmp;
+using namespace chrono;
MasterServer::MasterServer(unsigned short maxConnections, unsigned short port)
{
@@ -55,10 +56,10 @@ void MasterServer::Thread()
{
Packet *packet = peer->Receive();
- auto now = chrono::steady_clock::now();
+ auto now = steady_clock::now();
if (now - startTime >= 60s)
{
- startTime = chrono::steady_clock::now();
+ startTime = steady_clock::now();
for (auto it = servers.begin(); it != servers.end();)
{
@@ -66,6 +67,17 @@ void MasterServer::Thread()
servers.erase(it++);
else ++it;
}
+ for(auto id = pendingACKs.begin(); id != pendingACKs.end();)
+ {
+ if(now - id->second >= 30s)
+ {
+ cout << "timeout: " << peer->GetSystemAddressFromGuid(id->first).ToString() << endl;
+ peer->CloseConnection(id->first, true);
+ id = pendingACKs.erase(id);
+ }
+ else
+ ++id;
+ }
}
if (packet == nullptr)
@@ -90,10 +102,10 @@ void MasterServer::Thread()
{
pmq.SetServers(reinterpret_cast