mirror of
https://github.com/vcmi/vcmi.git
synced 2024-12-24 22:14:36 +02:00
merge beta branch into develop
This commit is contained in:
commit
b275d9de72
@ -1079,7 +1079,8 @@ static bool recreateWindow(int w, int h, int bpp, bool fullscreen, int displayIn
|
||||
if (displayIndex < 0)
|
||||
displayIndex = 0;
|
||||
}
|
||||
#ifdef VCMI_IOS
|
||||
|
||||
#if defined(VCMI_ANDROID) || defined(VCMI_IOS)
|
||||
SDL_GetWindowSize(mainWindow, &w, &h);
|
||||
#else
|
||||
if(!checkVideoMode(displayIndex, w, h))
|
||||
|
@ -409,6 +409,8 @@ void CMusicHandler::release()
|
||||
|
||||
void CMusicHandler::playMusic(const std::string & musicURI, bool loop, bool fromStart)
|
||||
{
|
||||
boost::mutex::scoped_lock guard(mutex);
|
||||
|
||||
if (current && current->isPlaying() && current->isTrack(musicURI))
|
||||
return;
|
||||
|
||||
@ -422,6 +424,8 @@ void CMusicHandler::playMusicFromSet(const std::string & musicSet, const std::st
|
||||
|
||||
void CMusicHandler::playMusicFromSet(const std::string & whichSet, bool loop, bool fromStart)
|
||||
{
|
||||
boost::mutex::scoped_lock guard(mutex);
|
||||
|
||||
auto selectedSet = musicsSet.find(whichSet);
|
||||
if (selectedSet == musicsSet.end())
|
||||
{
|
||||
@ -441,8 +445,6 @@ void CMusicHandler::queueNext(std::unique_ptr<MusicEntry> queued)
|
||||
if (!initialized)
|
||||
return;
|
||||
|
||||
boost::mutex::scoped_lock guard(mutex);
|
||||
|
||||
next = std::move(queued);
|
||||
|
||||
if (current.get() == nullptr || !current->stop(1000))
|
||||
@ -487,13 +489,32 @@ void CMusicHandler::setVolume(ui32 percent)
|
||||
|
||||
void CMusicHandler::musicFinishedCallback()
|
||||
{
|
||||
boost::mutex::scoped_lock guard(mutex);
|
||||
// boost::mutex::scoped_lock guard(mutex);
|
||||
// FIXME: WORKAROUND FOR A POTENTIAL DEADLOCK
|
||||
// It is possible for:
|
||||
// 1) SDL thread to call this method on end of playback
|
||||
// 2) VCMI code to call queueNext() method to queue new file
|
||||
// this leads to:
|
||||
// 1) SDL thread waiting to acquire music lock in this method (while keeping internal SDL mutex locked)
|
||||
// 2) VCMI thread waiting to acquire internal SDL mutex (while keeping music mutex locked)
|
||||
// Because of that (and lack of clear way to fix that)
|
||||
// We will try to acquire lock here and if failed - do nothing
|
||||
// This may break music playback till next song is enqued but won't deadlock the game
|
||||
|
||||
if (!mutex.try_lock())
|
||||
{
|
||||
logGlobal->error("Failed to acquire mutex! Unable to restart music!");
|
||||
return;
|
||||
}
|
||||
|
||||
if (current.get() != nullptr)
|
||||
{
|
||||
// if music is looped, play it again
|
||||
if (current->play())
|
||||
{
|
||||
mutex.unlock();
|
||||
return;
|
||||
}
|
||||
else
|
||||
current.reset();
|
||||
}
|
||||
@ -503,6 +524,7 @@ void CMusicHandler::musicFinishedCallback()
|
||||
current.reset(next.release());
|
||||
current->play();
|
||||
}
|
||||
mutex.unlock();
|
||||
}
|
||||
|
||||
MusicEntry::MusicEntry(CMusicHandler *owner, std::string setName, std::string musicURI, bool looped, bool fromStart):
|
||||
@ -597,7 +619,7 @@ bool MusicEntry::play()
|
||||
|
||||
bool MusicEntry::stop(int fade_ms)
|
||||
{
|
||||
if (Mix_PlayingMusic())
|
||||
if (playing)
|
||||
{
|
||||
playing = false;
|
||||
loop = 0;
|
||||
|
@ -2251,6 +2251,8 @@ void CPlayerInterface::artifactRemoved(const ArtifactLocation &al)
|
||||
if (artWin)
|
||||
artWin->artifactRemoved(al);
|
||||
}
|
||||
|
||||
waitWhileDialog();
|
||||
}
|
||||
|
||||
void CPlayerInterface::artifactMoved(const ArtifactLocation &src, const ArtifactLocation &dst)
|
||||
@ -2265,6 +2267,8 @@ void CPlayerInterface::artifactMoved(const ArtifactLocation &src, const Artifact
|
||||
}
|
||||
if(!GH.objsToBlit.empty())
|
||||
GH.objsToBlit.back()->redraw();
|
||||
|
||||
waitWhileDialog();
|
||||
}
|
||||
|
||||
void CPlayerInterface::artifactPossibleAssembling(const ArtifactLocation & dst)
|
||||
|
@ -235,7 +235,11 @@ std::shared_ptr<CButton> CMenuEntry::createButton(CMenuScreen * parent, const Js
|
||||
if(posy < 0)
|
||||
posy = pos.h + posy;
|
||||
|
||||
return std::make_shared<CButton>(Point(posx, posy), button["name"].String(), help, command, (int)button["hotkey"].Float());
|
||||
auto result = std::make_shared<CButton>(Point(posx, posy), button["name"].String(), help, command, (int)button["hotkey"].Float());
|
||||
|
||||
if (button["center"].Bool())
|
||||
result->moveBy(Point(-result->pos.w/2, -result->pos.h/2));
|
||||
return result;
|
||||
}
|
||||
|
||||
CMenuEntry::CMenuEntry(CMenuScreen * parent, const JsonNode & config)
|
||||
|
@ -11,12 +11,16 @@
|
||||
[
|
||||
{"type" : "lod", "path" : "Data/H3ab_bmp.lod"},
|
||||
{"type" : "lod", "path" : "Data/H3bitmap.lod"},
|
||||
{"type" : "lod", "path" : "Data/h3abp_bm.lod"}, // Polish version of H3 only
|
||||
{"type" : "lod", "path" : "Data/H3pbitma.lod"}, // Polish version of H3 only
|
||||
{"type" : "dir", "path" : "Data"}
|
||||
],
|
||||
"SPRITES/":
|
||||
[
|
||||
{"type" : "lod", "path" : "Data/H3ab_spr.lod"},
|
||||
{"type" : "lod", "path" : "Data/H3sprite.lod"},
|
||||
{"type" : "lod", "path" : "Data/h3abp_sp.lod"}, // Polish version of H3 only
|
||||
{"type" : "lod", "path" : "Data/H3psprit.lod"}, // Polish version of H3 only
|
||||
{"type" : "dir", "path" : "Sprites"}
|
||||
],
|
||||
"SOUNDS/":
|
||||
|
@ -10,29 +10,29 @@
|
||||
"background" : "gamselbk",
|
||||
//"scalable" : true, //background will be scaled to screen size
|
||||
//"video" : {"x": 8, "y": 105, "name":"CREDITS.SMK" },//Floating WoG logo. Disabled due to different position in various versions of H3.
|
||||
//"images" : [],//Optioal, contains any additional images in the same format as video
|
||||
//"images" : [],//Optional, contains any additional images in the same format as video
|
||||
"items" :
|
||||
[
|
||||
{
|
||||
"name" : "main",
|
||||
"buttons":
|
||||
[
|
||||
{"x": 540, "y": 10, "name":"MMENUNG", "hotkey" : 110, "help": 3, "command": "to new"},
|
||||
{"x": 532, "y": 132, "name":"MMENULG", "hotkey" : 108, "help": 4, "command": "to load"},
|
||||
{"x": 524, "y": 251, "name":"MMENUHS", "hotkey" : 104, "help": 5, "command": "highscores"},
|
||||
{"x": 557, "y": 359, "name":"MMENUCR", "hotkey" : 99, "help": 6, "command": "to credits"},
|
||||
{"x": 586, "y": 468, "name":"MMENUQT", "hotkey" : 27, "help": 7, "command": "exit"}
|
||||
{"x": 644, "y": 70, "center" : true, "name":"MMENUNG", "hotkey" : 110, "help": 3, "command": "to new"},
|
||||
{"x": 645, "y": 192, "center" : true, "name":"MMENULG", "hotkey" : 108, "help": 4, "command": "to load"},
|
||||
{"x": 643, "y": 296, "center" : true, "name":"MMENUHS", "hotkey" : 104, "help": 5, "command": "highscores"},
|
||||
{"x": 643, "y": 414, "center" : true, "name":"MMENUCR", "hotkey" : 99, "help": 6, "command": "to credits"},
|
||||
{"x": 643, "y": 520, "center" : true, "name":"MMENUQT", "hotkey" : 27, "help": 7, "command": "exit"}
|
||||
]
|
||||
},
|
||||
{
|
||||
"name" : "new",
|
||||
"buttons":
|
||||
[
|
||||
{"x": 545, "y": 4, "name":"GTSINGL", "hotkey" : 115, "help": 10, "command": "start single"},
|
||||
{"x": 568, "y": 120, "name":"GTMULTI", "hotkey" : 109, "help": 12, "command": "start multi"},
|
||||
{"x": 541, "y": 233, "name":"GTCAMPN", "hotkey" : 99, "help": 11, "command": "to campaign"},
|
||||
{"x": 545, "y": 358, "name":"GTTUTOR", "hotkey" : 116, "help": 13, "command": "start tutorial"},
|
||||
{"x": 582, "y": 464, "name":"GTBACK", "hotkey" : 27, "help": 14, "command": "to main"}
|
||||
{"x": 649, "y": 65, "center" : true, "name":"GTSINGL", "hotkey" : 115, "help": 10, "command": "start single"},
|
||||
{"x": 649, "y": 180, "center" : true, "name":"GTMULTI", "hotkey" : 109, "help": 12, "command": "start multi"},
|
||||
{"x": 646, "y": 298, "center" : true, "name":"GTCAMPN", "hotkey" : 99, "help": 11, "command": "to campaign"},
|
||||
{"x": 647, "y": 412, "center" : true, "name":"GTTUTOR", "hotkey" : 116, "help": 13, "command": "start tutorial"},
|
||||
{"x": 645, "y": 517, "center" : true, "name":"GTBACK", "hotkey" : 27, "help": 14, "command": "to main"}
|
||||
],
|
||||
"images": [ {"x": 114, "y": 312, "name":"NEWGAME"} ]
|
||||
},
|
||||
@ -40,11 +40,11 @@
|
||||
"name" : "load",
|
||||
"buttons":
|
||||
[
|
||||
{"x": 545, "y": 8, "name":"GTSINGL", "hotkey" : 115, "help": 10, "command": "load single"},
|
||||
{"x": 568, "y": 120, "name":"GTMULTI", "hotkey" : 109, "help": 12, "command": "load multi"},
|
||||
{"x": 541, "y": 233, "name":"GTCAMPN", "hotkey" : 99, "help": 11, "command": "load campaign"},
|
||||
{"x": 545, "y": 358, "name":"GTTUTOR", "hotkey" : 116, "help": 13, "command": "load tutorial"},
|
||||
{"x": 582, "y": 464, "name":"GTBACK", "hotkey" : 27, "help": 14, "command": "to main"}
|
||||
{"x": 649, "y": 65, "center" : true, "name":"GTSINGL", "hotkey" : 115, "help": 10, "command": "load single"},
|
||||
{"x": 649, "y": 180, "center" : true, "name":"GTMULTI", "hotkey" : 109, "help": 12, "command": "load multi"},
|
||||
{"x": 646, "y": 298, "center" : true, "name":"GTCAMPN", "hotkey" : 99, "help": 11, "command": "load campaign"},
|
||||
{"x": 647, "y": 412, "center" : true, "name":"GTTUTOR", "hotkey" : 116, "help": 13, "command": "load tutorial"},
|
||||
{"x": 645, "y": 517, "center" : true, "name":"GTBACK", "hotkey" : 27, "help": 14, "command": "to main"}
|
||||
],
|
||||
"images": [ {"x": 114, "y": 312, "name":"LOADGAME"} ]
|
||||
},
|
||||
@ -52,11 +52,11 @@
|
||||
"name" : "campaign",
|
||||
"buttons":
|
||||
[
|
||||
{"x": 535, "y": 4, "name":"CSSSOD", "hotkey" : 119, "command": "campaigns sod"},
|
||||
{"x": 494, "y": 117, "name":"CSSROE", "hotkey" : 114, "command": "campaigns roe"},
|
||||
{"x": 486, "y": 241, "name":"CSSARM", "hotkey" : 97, "command": "campaigns ab"},
|
||||
{"x": 550, "y": 358, "name":"CSSCUS", "hotkey" : 99, "command": "start campaign"},
|
||||
{"x": 582, "y": 464, "name":"GTBACK", "hotkey" : 27, "command": "to new"}
|
||||
{"x": 634, "y": 67, "center" : true, "name":"CSSSOD", "hotkey" : 119, "command": "campaigns sod"},
|
||||
{"x": 637, "y": 181, "center" : true, "name":"CSSROE", "hotkey" : 114, "command": "campaigns roe"},
|
||||
{"x": 638, "y": 301, "center" : true, "name":"CSSARM", "hotkey" : 97, "command": "campaigns ab"},
|
||||
{"x": 638, "y": 413, "center" : true, "name":"CSSCUS", "hotkey" : 99, "command": "start campaign"},
|
||||
{"x": 639, "y": 518, "center" : true, "name":"CSSEXIT", "hotkey" : 27, "command": "to new"}
|
||||
],
|
||||
}
|
||||
]
|
||||
|
1
debian/rules
vendored
1
debian/rules
vendored
@ -8,6 +8,7 @@ override_dh_auto_configure:
|
||||
dh_auto_configure -- \
|
||||
-DCMAKE_INSTALL_RPATH_USE_LINK_PATH=ON \
|
||||
-DCMAKE_INSTALL_RPATH=/usr/lib/$(DEB_HOST_MULTIARCH)/vcmi \
|
||||
-DCMAKE_BUILD_TYPE=RelWithDebInfo \
|
||||
-DBIN_DIR=games \
|
||||
-DFORCE_BUNDLED_FL=OFF \
|
||||
-DENABLE_TEST=0
|
||||
|
@ -152,12 +152,12 @@ void CArchiveLoader::initSNDArchive(const std::string &mountPoint, CFileInputStr
|
||||
char filename[40];
|
||||
reader.read(reinterpret_cast<ui8*>(filename), 40);
|
||||
|
||||
//for some reason entries in snd have format NAME\0WAVRUBBISH....
|
||||
//we need to replace first \0 with dot and take the 3 chars with extension (and drop the rest)
|
||||
// for some reason entries in snd have format NAME\0WAVRUBBISH....
|
||||
// and Polish version does not have extension at all
|
||||
// we need to replace first \0 with dot and add wav extension manuall - we don't expect other types here anyway
|
||||
ArchiveEntry entry;
|
||||
entry.name = filename; // till 1st \0
|
||||
entry.name += '.';
|
||||
entry.name += std::string(filename + entry.name.size(), 3);
|
||||
entry.name += ".wav";
|
||||
|
||||
entry.offset = reader.readInt32();
|
||||
entry.fullSize = reader.readInt32();
|
||||
|
@ -31,9 +31,18 @@ using namespace boost::asio::ip;
|
||||
#define LIL_ENDIAN
|
||||
#endif
|
||||
|
||||
struct ConnectionBuffers
|
||||
{
|
||||
boost::asio::streambuf readBuffer;
|
||||
boost::asio::streambuf writeBuffer;
|
||||
};
|
||||
|
||||
void CConnection::init()
|
||||
{
|
||||
enableBufferedWrite = false;
|
||||
enableBufferedRead = false;
|
||||
connectionBuffers = std::make_unique<ConnectionBuffers>();
|
||||
|
||||
socket->set_option(boost::asio::ip::tcp::no_delay(true));
|
||||
try
|
||||
{
|
||||
@ -72,6 +81,7 @@ CConnection::CConnection(std::string host, ui16 port, std::string Name, std::str
|
||||
int i;
|
||||
boost::system::error_code error = asio::error::host_not_found;
|
||||
socket = std::make_shared<tcp::socket>(*io_service);
|
||||
|
||||
tcp::resolver resolver(*io_service);
|
||||
tcp::resolver::iterator end, pom, endpoint_iterator = resolver.resolve(tcp::resolver::query(host, std::to_string(port)),error);
|
||||
if(error)
|
||||
@ -138,10 +148,39 @@ CConnection::CConnection(std::shared_ptr<TAcceptor> acceptor, std::shared_ptr<bo
|
||||
}
|
||||
init();
|
||||
}
|
||||
|
||||
void CConnection::flushBuffers()
|
||||
{
|
||||
if(!enableBufferedWrite)
|
||||
return;
|
||||
|
||||
try
|
||||
{
|
||||
asio::write(*socket, connectionBuffers->writeBuffer);
|
||||
}
|
||||
catch(...)
|
||||
{
|
||||
//connection has been lost
|
||||
connected = false;
|
||||
throw;
|
||||
}
|
||||
|
||||
enableBufferedWrite = false;
|
||||
}
|
||||
|
||||
int CConnection::write(const void * data, unsigned size)
|
||||
{
|
||||
try
|
||||
{
|
||||
if(enableBufferedWrite)
|
||||
{
|
||||
std::ostream ostream(&connectionBuffers->writeBuffer);
|
||||
|
||||
ostream.write(static_cast<const char *>(data), size);
|
||||
|
||||
return size;
|
||||
}
|
||||
|
||||
int ret;
|
||||
ret = static_cast<int>(asio::write(*socket,asio::const_buffers_1(asio::const_buffer(data,size))));
|
||||
return ret;
|
||||
@ -153,10 +192,29 @@ int CConnection::write(const void * data, unsigned size)
|
||||
throw;
|
||||
}
|
||||
}
|
||||
|
||||
int CConnection::read(void * data, unsigned size)
|
||||
{
|
||||
try
|
||||
{
|
||||
if(enableBufferedRead)
|
||||
{
|
||||
auto available = connectionBuffers->readBuffer.size();
|
||||
|
||||
while(available < size)
|
||||
{
|
||||
auto bytesRead = socket->read_some(connectionBuffers->readBuffer.prepare(1024));
|
||||
connectionBuffers->readBuffer.commit(bytesRead);
|
||||
available = connectionBuffers->readBuffer.size();
|
||||
}
|
||||
|
||||
std::istream istream(&connectionBuffers->readBuffer);
|
||||
|
||||
istream.read(static_cast<char *>(data), size);
|
||||
|
||||
return size;
|
||||
}
|
||||
|
||||
int ret = static_cast<int>(asio::read(*socket,asio::mutable_buffers_1(asio::mutable_buffer(data,size))));
|
||||
return ret;
|
||||
}
|
||||
@ -167,6 +225,7 @@ int CConnection::read(void * data, unsigned size)
|
||||
throw;
|
||||
}
|
||||
}
|
||||
|
||||
CConnection::~CConnection()
|
||||
{
|
||||
if(handler)
|
||||
@ -210,6 +269,8 @@ void CConnection::reportState(vstd::CLoggerBase * out)
|
||||
|
||||
CPack * CConnection::retrievePack()
|
||||
{
|
||||
enableBufferedRead = true;
|
||||
|
||||
CPack * pack = nullptr;
|
||||
boost::unique_lock<boost::mutex> lock(*mutexRead);
|
||||
iser & pack;
|
||||
@ -222,6 +283,9 @@ CPack * CConnection::retrievePack()
|
||||
{
|
||||
pack->c = this->shared_from_this();
|
||||
}
|
||||
|
||||
enableBufferedRead = false;
|
||||
|
||||
return pack;
|
||||
}
|
||||
|
||||
@ -229,7 +293,12 @@ void CConnection::sendPack(const CPack * pack)
|
||||
{
|
||||
boost::unique_lock<boost::mutex> lock(*mutexWrite);
|
||||
logNetwork->trace("Sending a pack of type %s", typeid(*pack).name());
|
||||
|
||||
enableBufferedWrite = true;
|
||||
|
||||
oser & pack;
|
||||
|
||||
flushBuffers();
|
||||
}
|
||||
|
||||
void CConnection::disableStackSendingByID()
|
||||
|
@ -52,6 +52,7 @@ typedef boost::asio::basic_socket_acceptor<boost::asio::ip::tcp, boost::asio::so
|
||||
VCMI_LIB_NAMESPACE_BEGIN
|
||||
|
||||
struct CPack;
|
||||
struct ConnectionBuffers;
|
||||
|
||||
/// Main class for network communication
|
||||
/// Allows establishing connection and bidirectional read-write
|
||||
@ -63,8 +64,14 @@ class DLL_LINKAGE CConnection
|
||||
|
||||
int write(const void * data, unsigned size) override;
|
||||
int read(void * data, unsigned size) override;
|
||||
void flushBuffers();
|
||||
|
||||
std::shared_ptr<boost::asio::io_service> io_service; //can be empty if connection made from socket
|
||||
|
||||
bool enableBufferedWrite;
|
||||
bool enableBufferedRead;
|
||||
std::unique_ptr<ConnectionBuffers> connectionBuffers;
|
||||
|
||||
public:
|
||||
BinaryDeserializer iser;
|
||||
BinarySerializer oser;
|
||||
|
@ -87,6 +87,11 @@ warning ()
|
||||
warn_user=true
|
||||
}
|
||||
|
||||
#checks whether specified directory exists. Also works with globs
|
||||
dir_exists() {
|
||||
[ -d "$1" ]
|
||||
}
|
||||
|
||||
# check if selected options are correct.
|
||||
|
||||
if [[ -n "$data_dir" ]]
|
||||
@ -177,7 +182,7 @@ then
|
||||
cd "$data_dir" && innoextract "$gog_file"
|
||||
|
||||
# some versions of gog.com installer (or innoextract tool?) place game files inside /app directory
|
||||
if [[ -d "$data_dir"/app ]]
|
||||
if dir_exists "$data_dir"/app/[Dd][Aa][Tt][Aa]
|
||||
then
|
||||
data_dir="$data_dir"/app
|
||||
fi
|
||||
|
Loading…
Reference in New Issue
Block a user