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)
throw ApplicationException::format("Application: Could not create OpenGL context: %s", SDL_GetError());
SDL_GL_SwapWindow(m_sdlWindow);
setVSyncEnabled(m_windowVSync);
SDL_StopTextInput();
@ -277,13 +278,15 @@ public:
};
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!");
} 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!");
} else {
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>();
@ -291,7 +294,7 @@ public:
}
~SdlPlatform() {
SDL_CloseAudio();
SDL_CloseAudioDevice(m_audioDevice);
m_renderer.reset();
@ -370,7 +373,7 @@ public:
Logger::error("Application: threw exception during shutdown: %s", outputException(e, true));
}
SDL_CloseAudio();
SDL_CloseAudioDevice(m_audioDevice);
m_application.reset();
}
@ -438,8 +441,10 @@ private:
void setNormalWindow(Vec2U windowSize) override {
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_SetWindowBordered(parent->m_sdlWindow, SDL_TRUE);
}
else if (parent->m_windowMode == WindowMode::Maximized)
SDL_RestoreWindow(parent->m_sdlWindow);
@ -453,8 +458,10 @@ private:
void setMaximizedWindow() override {
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_SetWindowBordered(parent->m_sdlWindow, SDL_TRUE);
}
SDL_MaximizeWindow(parent->m_sdlWindow);
parent->m_windowMode = WindowMode::Maximized;
@ -463,7 +470,9 @@ private:
void setBorderlessWindow() override {
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;
SDL_DisplayMode actualDisplayMode;
@ -656,6 +665,7 @@ private:
SDL_Window* m_sdlWindow = nullptr;
SDL_GLContext m_sdlGlContext = nullptr;
SDL_AudioDeviceID m_audioDevice = 0;
Vec2U m_windowSize = {800, 600};
WindowMode m_windowMode = WindowMode::Normal;

View File

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

View File

@ -128,11 +128,6 @@ void ClientApplication::startup(StringList const& cmdLineArgs) {
m_root = rootLoader.initOrDie(cmdLineArgs).first;
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() {
@ -159,6 +154,11 @@ void ClientApplication::shutdown() {
void ClientApplication::applicationInit(ApplicationControllerPtr 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);
AudioFormat audioFormat = appController->enableAudio();
@ -178,7 +178,7 @@ void ClientApplication::applicationInit(ApplicationControllerPtr appController)
bool borderless = configuration->get("borderless").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);
if (fullscreen)
@ -190,8 +190,8 @@ void ClientApplication::applicationInit(ApplicationControllerPtr appController)
else
appController->setNormalWindow(windowedSize);
appController->setMaxFrameSkip(m_root->assets()->json("/client.config:maxFrameSkip").toUInt());
appController->setUpdateTrackWindow(m_root->assets()->json("/client.config:updateTrackWindow").toFloat());
appController->setMaxFrameSkip(assets->json("/client.config:maxFrameSkip").toUInt());
appController->setUpdateTrackWindow(assets->json("/client.config:updateTrackWindow").toFloat());
}
void ClientApplication::renderInit(RendererPtr renderer) {

View File

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

View File

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

View File

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

View File

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