Fixes and stuff

Using proper SDL Audio APIs now
Fixed borderless
Create game window before asset load
Bump up root loading worker thread count to 8
Fix not hearing other player songs on load-in
Fix issues with shipworlds missing ship.level property
Fix rare thread race with received chat packets on the server-side
This commit is contained in:
Kae 2023-06-21 15:25:10 +10:00
parent 0ec3000536
commit d6fdd96076
7 changed files with 64 additions and 41 deletions

View File

@ -262,6 +262,7 @@ public:
if (!m_sdlGlContext) if (!m_sdlGlContext)
throw ApplicationException::format("Application: Could not create OpenGL context: %s", SDL_GetError()); throw ApplicationException::format("Application: Could not create OpenGL context: %s", SDL_GetError());
SDL_GL_SwapWindow(m_sdlWindow);
setVSyncEnabled(m_windowVSync); setVSyncEnabled(m_windowVSync);
SDL_StopTextInput(); SDL_StopTextInput();
@ -277,13 +278,15 @@ public:
}; };
SDL_AudioSpec obtained = {}; SDL_AudioSpec obtained = {};
if (SDL_OpenAudioDevice(NULL, 0, &desired, &obtained, 0) < 0) { m_audioDevice = SDL_OpenAudioDevice(NULL, 0, &desired, &obtained, 0);
if (!m_audioDevice) {
Logger::error("Application: Could not open audio device, no sound available!"); Logger::error("Application: Could not open audio device, no sound available!");
} else if (obtained.freq != desired.freq || obtained.channels != desired.channels || obtained.format != desired.format) { } else if (obtained.freq != desired.freq || obtained.channels != desired.channels || obtained.format != desired.format) {
SDL_CloseAudio(); SDL_CloseAudioDevice(m_audioDevice);
Logger::error("Application: Could not open 44.1khz / 16 bit stereo audio device, no sound available!"); Logger::error("Application: Could not open 44.1khz / 16 bit stereo audio device, no sound available!");
} else { } else {
Logger::info("Application: Opened default audio device with 44.1khz / 16 bit stereo audio, %s sample size buffer", obtained.samples); Logger::info("Application: Opened default audio device with 44.1khz / 16 bit stereo audio, %s sample size buffer", obtained.samples);
SDL_PauseAudioDevice(m_audioDevice, 0);
} }
m_renderer = make_shared<OpenGl20Renderer>(); m_renderer = make_shared<OpenGl20Renderer>();
@ -291,7 +294,7 @@ public:
} }
~SdlPlatform() { ~SdlPlatform() {
SDL_CloseAudio(); SDL_CloseAudioDevice(m_audioDevice);
m_renderer.reset(); m_renderer.reset();
@ -370,7 +373,7 @@ public:
Logger::error("Application: threw exception during shutdown: %s", outputException(e, true)); Logger::error("Application: threw exception during shutdown: %s", outputException(e, true));
} }
SDL_CloseAudio(); SDL_CloseAudioDevice(m_audioDevice);
m_application.reset(); m_application.reset();
} }
@ -438,8 +441,10 @@ private:
void setNormalWindow(Vec2U windowSize) override { void setNormalWindow(Vec2U windowSize) override {
if (parent->m_windowMode != WindowMode::Normal || parent->m_windowSize != windowSize) { if (parent->m_windowMode != WindowMode::Normal || parent->m_windowSize != windowSize) {
if (parent->m_windowMode == WindowMode::Fullscreen || parent->m_windowMode == WindowMode::Borderless) if (parent->m_windowMode == WindowMode::Fullscreen || parent->m_windowMode == WindowMode::Borderless) {
SDL_SetWindowFullscreen(parent->m_sdlWindow, 0); SDL_SetWindowFullscreen(parent->m_sdlWindow, 0);
SDL_SetWindowBordered(parent->m_sdlWindow, SDL_TRUE);
}
else if (parent->m_windowMode == WindowMode::Maximized) else if (parent->m_windowMode == WindowMode::Maximized)
SDL_RestoreWindow(parent->m_sdlWindow); SDL_RestoreWindow(parent->m_sdlWindow);
@ -453,8 +458,10 @@ private:
void setMaximizedWindow() override { void setMaximizedWindow() override {
if (parent->m_windowMode != WindowMode::Maximized) { if (parent->m_windowMode != WindowMode::Maximized) {
if (parent->m_windowMode == WindowMode::Fullscreen || parent->m_windowMode == WindowMode::Borderless) if (parent->m_windowMode == WindowMode::Fullscreen || parent->m_windowMode == WindowMode::Borderless) {
SDL_SetWindowFullscreen(parent->m_sdlWindow, 0); SDL_SetWindowFullscreen(parent->m_sdlWindow, 0);
SDL_SetWindowBordered(parent->m_sdlWindow, SDL_TRUE);
}
SDL_MaximizeWindow(parent->m_sdlWindow); SDL_MaximizeWindow(parent->m_sdlWindow);
parent->m_windowMode = WindowMode::Maximized; parent->m_windowMode = WindowMode::Maximized;
@ -463,7 +470,9 @@ private:
void setBorderlessWindow() override { void setBorderlessWindow() override {
if (parent->m_windowMode != WindowMode::Borderless) { if (parent->m_windowMode != WindowMode::Borderless) {
SDL_SetWindowFullscreen(parent->m_sdlWindow, SDL_WINDOW_FULLSCREEN_DESKTOP); SDL_SetWindowFullscreen(parent->m_sdlWindow, 0);
SDL_SetWindowBordered(parent->m_sdlWindow, SDL_FALSE);
SDL_MaximizeWindow(parent->m_sdlWindow);
parent->m_windowMode = WindowMode::Borderless; parent->m_windowMode = WindowMode::Borderless;
SDL_DisplayMode actualDisplayMode; SDL_DisplayMode actualDisplayMode;
@ -656,6 +665,7 @@ private:
SDL_Window* m_sdlWindow = nullptr; SDL_Window* m_sdlWindow = nullptr;
SDL_GLContext m_sdlGlContext = nullptr; SDL_GLContext m_sdlGlContext = nullptr;
SDL_AudioDeviceID m_audioDevice = 0;
Vec2U m_windowSize = {800, 600}; Vec2U m_windowSize = {800, 600};
WindowMode m_windowMode = WindowMode::Normal; WindowMode m_windowMode = WindowMode::Normal;

View File

@ -693,33 +693,34 @@ void OpenGl20Renderer::GlRenderBuffer::set(List<RenderPrimitive> primitives) {
} }
void OpenGl20Renderer::logGlErrorSummary(String prefix) { void OpenGl20Renderer::logGlErrorSummary(String prefix) {
prefix += ": ";
Logger::error(prefix.utf8Ptr());
List<GLenum> errors; List<GLenum> errors;
while (GLenum error = glGetError()) while (GLenum error = glGetError())
errors.append(error); errors.append(error);
if (!errors.empty()) { if (GLenum error = glGetError()) {
String errorMessage = move(prefix); prefix += ": ";
errorMessage.append(": "); Logger::error(prefix.utf8Ptr());
for (auto const& error : errors) { do {
if (error == GL_INVALID_ENUM) { if (error == GL_INVALID_ENUM) {
errorMessage += " GL_INVALID_ENUM"; Logger::error("GL_INVALID_ENUM");
} else if (error == GL_INVALID_VALUE) { } else if (error == GL_INVALID_VALUE) {
errorMessage += " GL_INVALID_VALUE"; Logger::error("GL_INVALID_VALUE");
} else if (error == GL_INVALID_OPERATION) { } else if (error == GL_INVALID_OPERATION) {
errorMessage += " GL_INVALID_OPERATION"; Logger::error("GL_INVALID_OPERATION");
} else if (error == GL_INVALID_FRAMEBUFFER_OPERATION) { } else if (error == GL_INVALID_FRAMEBUFFER_OPERATION) {
errorMessage += " GL_INVALID_FRAMEBUFFER_OPERATION"; Logger::error("GL_INVALID_FRAMEBUFFER_OPERATION");
} else if (error == GL_OUT_OF_MEMORY) { } else if (error == GL_OUT_OF_MEMORY) {
errorMessage += " GL_OUT_OF_MEMORY"; Logger::error("GL_OUT_OF_MEMORY");
} else if (error == GL_STACK_UNDERFLOW) { } else if (error == GL_STACK_UNDERFLOW) {
errorMessage += " GL_STACK_UNDERFLOW"; Logger::error("GL_STACK_UNDERFLOW");
} else if (error == GL_STACK_OVERFLOW) { } else if (error == GL_STACK_OVERFLOW) {
errorMessage += " GL_STACK_OVERFLOW"; Logger::error("GL_STACK_OVERFLOW");
} else { } else {
errorMessage += " <UNRECOGNIZED GL ERROR>"; Logger::error("<UNRECOGNIZED GL ERROR>");
} }
} } while (error = glGetError());
Logger::error(errorMessage.utf8Ptr());
} }
} }

View File

@ -128,11 +128,6 @@ void ClientApplication::startup(StringList const& cmdLineArgs) {
m_root = rootLoader.initOrDie(cmdLineArgs).first; m_root = rootLoader.initOrDie(cmdLineArgs).first;
Logger::info("Client Version %s (%s) Source ID: %s Protocol: %s", StarVersionString, StarArchitectureString, StarSourceIdentifierString, StarProtocolVersion); Logger::info("Client Version %s (%s) Source ID: %s Protocol: %s", StarVersionString, StarArchitectureString, StarSourceIdentifierString, StarProtocolVersion);
auto assets = m_root->assets();
m_minInterfaceScale = assets->json("/interface.config:minInterfaceScale").toInt();
m_maxInterfaceScale = assets->json("/interface.config:maxInterfaceScale").toInt();
m_crossoverRes = jsonToVec2F(assets->json("/interface.config:interfaceCrossoverRes"));
} }
void ClientApplication::shutdown() { void ClientApplication::shutdown() {
@ -159,6 +154,11 @@ void ClientApplication::shutdown() {
void ClientApplication::applicationInit(ApplicationControllerPtr appController) { void ClientApplication::applicationInit(ApplicationControllerPtr appController) {
Application::applicationInit(appController); Application::applicationInit(appController);
auto assets = m_root->assets();
m_minInterfaceScale = assets->json("/interface.config:minInterfaceScale").toInt();
m_maxInterfaceScale = assets->json("/interface.config:maxInterfaceScale").toInt();
m_crossoverRes = jsonToVec2F(assets->json("/interface.config:interfaceCrossoverRes"));
appController->setCursorVisible(false); appController->setCursorVisible(false);
AudioFormat audioFormat = appController->enableAudio(); AudioFormat audioFormat = appController->enableAudio();
@ -178,7 +178,7 @@ void ClientApplication::applicationInit(ApplicationControllerPtr appController)
bool borderless = configuration->get("borderless").toBool(); bool borderless = configuration->get("borderless").toBool();
bool maximized = configuration->get("maximized").toBool(); bool maximized = configuration->get("maximized").toBool();
appController->setApplicationTitle(m_root->assets()->json("/client.config:windowTitle").toString()); appController->setApplicationTitle(assets->json("/client.config:windowTitle").toString());
appController->setVSyncEnabled(vsync); appController->setVSyncEnabled(vsync);
if (fullscreen) if (fullscreen)
@ -190,8 +190,8 @@ void ClientApplication::applicationInit(ApplicationControllerPtr appController)
else else
appController->setNormalWindow(windowedSize); appController->setNormalWindow(windowedSize);
appController->setMaxFrameSkip(m_root->assets()->json("/client.config:maxFrameSkip").toUInt()); appController->setMaxFrameSkip(assets->json("/client.config:maxFrameSkip").toUInt());
appController->setUpdateTrackWindow(m_root->assets()->json("/client.config:updateTrackWindow").toFloat()); appController->setUpdateTrackWindow(assets->json("/client.config:updateTrackWindow").toFloat());
} }
void ClientApplication::renderInit(RendererPtr renderer) { void ClientApplication::renderInit(RendererPtr renderer) {

View File

@ -57,7 +57,7 @@ namespace Star {
namespace { namespace {
unsigned const RootMaintenanceSleep = 5000; unsigned const RootMaintenanceSleep = 5000;
unsigned const RootLoadThreads = 2; unsigned const RootLoadThreads = 8;
} }
atomic<Root*> Root::s_singleton; atomic<Root*> Root::s_singleton;

View File

@ -18,6 +18,7 @@ Songbook::Songbook(String const& species) {
m_dataUpdated = false; m_dataUpdated = false;
m_dataChanged = false; m_dataChanged = false;
m_timeSourceEpoch = 0; m_timeSourceEpoch = 0;
m_epochUpdated = false;
m_globalNowDelta = 0; m_globalNowDelta = 0;
m_species = species; m_species = species;
m_stopped = true; m_stopped = true;
@ -72,6 +73,10 @@ void Songbook::update(EntityMode mode, World* world) {
return; return;
m_globalNowDelta = world->epochTime() * 1000 - Time::millisecondsSinceEpoch(); m_globalNowDelta = world->epochTime() * 1000 - Time::millisecondsSinceEpoch();
if (m_epochUpdated) {
m_epochUpdated = false;
m_timeSourceEpoch -= m_globalNowDelta;
}
if (m_dataUpdated) { if (m_dataUpdated) {
m_dataUpdated = false; m_dataUpdated = false;
if (!m_song.isNull()) { if (!m_song.isNull()) {
@ -652,6 +657,7 @@ void Songbook::play(Json const& song, String const& timeSource) {
m_timeSource = toString(Random::randu64()); m_timeSource = toString(Random::randu64());
{ {
m_epochUpdated = false;
m_timeSourceEpoch = Time::millisecondsSinceEpoch(); m_timeSourceEpoch = Time::millisecondsSinceEpoch();
MutexLocker lock(s_timeSourcesMutex); MutexLocker lock(s_timeSourcesMutex);
if (!s_timeSources.contains(m_timeSource)) { if (!s_timeSources.contains(m_timeSource)) {
@ -702,7 +708,8 @@ double Songbook::fundamentalPitch(double f) {
void Songbook::netElementsNeedLoad(bool) { void Songbook::netElementsNeedLoad(bool) {
if (m_songNetState.pullUpdated()) { if (m_songNetState.pullUpdated()) {
m_song = m_songNetState.get(); m_song = m_songNetState.get();
m_timeSourceEpoch = m_timeSourceEpochNetState.get() - m_globalNowDelta; m_timeSourceEpoch = m_timeSourceEpochNetState.get();
m_epochUpdated = true;
m_dataUpdated = true; m_dataUpdated = true;
} }
m_timeSource = m_timeSourceNetState.get(); m_timeSource = m_timeSourceNetState.get();

View File

@ -81,6 +81,7 @@ private:
String m_timeSource; String m_timeSource;
int64_t m_timeSourceEpoch; int64_t m_timeSourceEpoch;
bool m_epochUpdated;
String m_instrument; String m_instrument;
Json m_song; Json m_song;
bool m_stopped; bool m_stopped;

View File

@ -619,20 +619,23 @@ void UniverseServer::updateShips() {
if (auto shipWorld = getWorld(ClientShipWorldId(p.second->playerUuid()))) { if (auto shipWorld = getWorld(ClientShipWorldId(p.second->playerUuid()))) {
shipWorld->executeAction([&](WorldServerThread*, WorldServer* shipWorld) { shipWorld->executeAction([&](WorldServerThread*, WorldServer* shipWorld) {
auto const& speciesShips = m_speciesShips.get(p.second->playerSpecies()); auto const& speciesShips = m_speciesShips.get(p.second->playerSpecies());
unsigned oldShipLevel = shipWorld->getProperty("ship.level").toUInt(); Json jOldShipLevel = shipWorld->getProperty("ship.level");
unsigned newShipLevel = min<unsigned>(speciesShips.size() - 1, newShipUpgrades.shipLevel); unsigned newShipLevel = min<unsigned>(speciesShips.size() - 1, newShipUpgrades.shipLevel);
if (oldShipLevel < newShipLevel) {
for (unsigned i = oldShipLevel + 1; i <= newShipLevel; ++i) { if (jOldShipLevel.isType(Json::Type::Int)) {
auto shipStructure = WorldStructure(speciesShips[i]); auto oldShipLevel = jOldShipLevel.toUInt();
shipWorld->setCentralStructure(shipStructure); if (oldShipLevel < newShipLevel) {
newShipUpgrades.apply(shipStructure.configValue("shipUpgrades")); for (unsigned i = oldShipLevel + 1; i <= newShipLevel; ++i) {
auto shipStructure = WorldStructure(speciesShips[i]);
shipWorld->setCentralStructure(shipStructure);
newShipUpgrades.apply(shipStructure.configValue("shipUpgrades"));
}
p.second->setShipUpgrades(newShipUpgrades);
p.second->updateShipChunks(shipWorld->readChunks());
} }
p.second->setShipUpgrades(newShipUpgrades);
p.second->updateShipChunks(shipWorld->readChunks());
} }
shipWorld->setProperty("ship.level", newShipUpgrades.shipLevel); shipWorld->setProperty("ship.level", newShipUpgrades.shipLevel);
shipWorld->setProperty("ship.maxFuel", newShipUpgrades.maxFuel); shipWorld->setProperty("ship.maxFuel", newShipUpgrades.maxFuel);
shipWorld->setProperty("ship.crewSize", newShipUpgrades.crewSize); shipWorld->setProperty("ship.crewSize", newShipUpgrades.crewSize);
@ -1430,6 +1433,7 @@ void UniverseServer::packetsReceived(UniverseConnectionServer*, ConnectionId cli
clientFlyShip(clientId, flyShip->system, flyShip->location); clientFlyShip(clientId, flyShip->system, flyShip->location);
} else if (auto chatSend = as<ChatSendPacket>(packet)) { } else if (auto chatSend = as<ChatSendPacket>(packet)) {
RecursiveMutexLocker locker(m_mainLock);
m_pendingChat[clientId].append({move(chatSend->text), chatSend->sendMode}); m_pendingChat[clientId].append({move(chatSend->text), chatSend->sendMode});
} else if (auto clientContextUpdatePacket = as<ClientContextUpdatePacket>(packet)) { } else if (auto clientContextUpdatePacket = as<ClientContextUpdatePacket>(packet)) {