mirror of
https://github.com/yairm210/Unciv.git
synced 2025-01-03 21:40:31 +07:00
Fix OutOfMemoryError when loading a game and another is already loaded (#7306)
* Fix OutOfMemoryError when loading a game and another is already loaded * Fix merge error...
This commit is contained in:
parent
119440ccec
commit
08cede4f5a
@ -24,7 +24,7 @@ buildscript {
|
|||||||
dependencies {
|
dependencies {
|
||||||
classpath("org.jetbrains.kotlin:kotlin-gradle-plugin:${com.unciv.build.BuildConfig.kotlinVersion}")
|
classpath("org.jetbrains.kotlin:kotlin-gradle-plugin:${com.unciv.build.BuildConfig.kotlinVersion}")
|
||||||
classpath("de.richsource.gradle.plugins:gwt-gradle-plugin:0.6")
|
classpath("de.richsource.gradle.plugins:gwt-gradle-plugin:0.6")
|
||||||
classpath("com.android.tools.build:gradle:7.0.4")
|
classpath("com.android.tools.build:gradle:7.1.3")
|
||||||
classpath("com.mobidevelop.robovm:robovm-gradle-plugin:2.3.1")
|
classpath("com.mobidevelop.robovm:robovm-gradle-plugin:2.3.1")
|
||||||
|
|
||||||
// This is for wrapping the .jar file into a standalone executable
|
// This is for wrapping the .jar file into a standalone executable
|
||||||
|
@ -37,6 +37,7 @@ import com.unciv.utils.concurrency.launchOnGLThread
|
|||||||
import com.unciv.utils.concurrency.withGLContext
|
import com.unciv.utils.concurrency.withGLContext
|
||||||
import com.unciv.utils.concurrency.withThreadPoolContext
|
import com.unciv.utils.concurrency.withThreadPoolContext
|
||||||
import com.unciv.utils.debug
|
import com.unciv.utils.debug
|
||||||
|
import kotlinx.coroutines.CancellationException
|
||||||
import java.io.PrintWriter
|
import java.io.PrintWriter
|
||||||
import java.util.*
|
import java.util.*
|
||||||
import kotlin.collections.ArrayDeque
|
import kotlin.collections.ArrayDeque
|
||||||
@ -405,6 +406,9 @@ class UncivGame(parameters: UncivGameParameters) : Game() {
|
|||||||
|
|
||||||
/** Handles an uncaught exception or error. First attempts a platform-specific handler, and if that didn't handle the exception or error, brings the game to a [CrashScreen]. */
|
/** Handles an uncaught exception or error. First attempts a platform-specific handler, and if that didn't handle the exception or error, brings the game to a [CrashScreen]. */
|
||||||
fun handleUncaughtThrowable(ex: Throwable) {
|
fun handleUncaughtThrowable(ex: Throwable) {
|
||||||
|
if (ex is CancellationException) {
|
||||||
|
return // kotlin coroutines use this for control flow... so we can just ignore them.
|
||||||
|
}
|
||||||
Log.error("Uncaught throwable", ex)
|
Log.error("Uncaught throwable", ex)
|
||||||
try {
|
try {
|
||||||
PrintWriter(files.fileWriter("lasterror.txt")).use {
|
PrintWriter(files.fileWriter("lasterror.txt")).use {
|
||||||
|
@ -24,6 +24,7 @@ class UncivStage(viewport: Viewport) : Stage(viewport) {
|
|||||||
private set
|
private set
|
||||||
|
|
||||||
private val events = EventBus.EventReceiver()
|
private val events = EventBus.EventReceiver()
|
||||||
|
|
||||||
init {
|
init {
|
||||||
lastKnownVisibleArea = Rectangle(0f, 0f, width, height)
|
lastKnownVisibleArea = Rectangle(0f, 0f, width, height)
|
||||||
events.receive(VisibleAreaChanged::class) {
|
events.receive(VisibleAreaChanged::class) {
|
||||||
@ -35,6 +36,11 @@ class UncivStage(viewport: Viewport) : Stage(viewport) {
|
|||||||
override fun dispose() {
|
override fun dispose() {
|
||||||
events.stopReceiving()
|
events.stopReceiving()
|
||||||
super.dispose()
|
super.dispose()
|
||||||
|
|
||||||
|
/** [Stage.dispose] is supposed to clear all references it holds. But it forgets the mouse over properties:
|
||||||
|
the [Stage.mouseOverActor] and [Stage.pointerOverActors]. [Stage.act] updates those properties,
|
||||||
|
and since there aren't any children left, sets all those properties to `null`. */
|
||||||
|
super.act()
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun draw() =
|
override fun draw() =
|
||||||
|
@ -212,8 +212,9 @@ class WorldScreen(
|
|||||||
}
|
}
|
||||||
|
|
||||||
override fun dispose() {
|
override fun dispose() {
|
||||||
super.dispose()
|
|
||||||
events.stopReceiving()
|
events.stopReceiving()
|
||||||
|
statusButtons.dispose()
|
||||||
|
super.dispose()
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun addKeyboardPresses() {
|
private fun addKeyboardPresses() {
|
||||||
|
@ -11,6 +11,7 @@ import com.badlogic.gdx.scenes.scene2d.ui.Image
|
|||||||
import com.badlogic.gdx.scenes.scene2d.ui.Label
|
import com.badlogic.gdx.scenes.scene2d.ui.Label
|
||||||
import com.badlogic.gdx.scenes.scene2d.ui.Stack
|
import com.badlogic.gdx.scenes.scene2d.ui.Stack
|
||||||
import com.badlogic.gdx.utils.Align
|
import com.badlogic.gdx.utils.Align
|
||||||
|
import com.badlogic.gdx.utils.Disposable
|
||||||
import com.unciv.UncivGame
|
import com.unciv.UncivGame
|
||||||
import com.unciv.logic.event.EventBus
|
import com.unciv.logic.event.EventBus
|
||||||
import com.unciv.logic.multiplayer.HasMultiplayerGameName
|
import com.unciv.logic.multiplayer.HasMultiplayerGameName
|
||||||
@ -26,14 +27,15 @@ import com.unciv.ui.utils.extensions.onClick
|
|||||||
import com.unciv.ui.utils.extensions.setSize
|
import com.unciv.ui.utils.extensions.setSize
|
||||||
import com.unciv.utils.concurrency.Concurrency
|
import com.unciv.utils.concurrency.Concurrency
|
||||||
import com.unciv.utils.concurrency.launchOnGLThread
|
import com.unciv.utils.concurrency.launchOnGLThread
|
||||||
|
import kotlinx.coroutines.Job
|
||||||
import kotlinx.coroutines.delay
|
import kotlinx.coroutines.delay
|
||||||
import java.time.Duration
|
import java.time.Duration
|
||||||
import java.time.Instant
|
import java.time.Instant
|
||||||
|
|
||||||
class MultiplayerStatusButton(
|
class MultiplayerStatusButton(
|
||||||
/*val*/ screen: BaseScreen,
|
screen: BaseScreen,
|
||||||
curGame: OnlineMultiplayerGame?
|
curGame: OnlineMultiplayerGame?
|
||||||
) : Button(BaseScreen.skin) {
|
) : Button(BaseScreen.skin), Disposable {
|
||||||
private var curGameName = curGame?.name
|
private var curGameName = curGame?.name
|
||||||
private val multiplayerImage = createMultiplayerImage()
|
private val multiplayerImage = createMultiplayerImage()
|
||||||
private val loadingImage = createLoadingImage()
|
private val loadingImage = createLoadingImage()
|
||||||
@ -43,6 +45,7 @@ class MultiplayerStatusButton(
|
|||||||
private var loadingStarted: Instant? = null
|
private var loadingStarted: Instant? = null
|
||||||
|
|
||||||
private val events = EventBus.EventReceiver()
|
private val events = EventBus.EventReceiver()
|
||||||
|
private var loadStopJob: Job? = null
|
||||||
|
|
||||||
init {
|
init {
|
||||||
turnIndicatorCell = add().padTop(10f).padBottom(10f)
|
turnIndicatorCell = add().padTop(10f).padBottom(10f)
|
||||||
@ -96,7 +99,7 @@ class MultiplayerStatusButton(
|
|||||||
} else {
|
} else {
|
||||||
Duration.ZERO
|
Duration.ZERO
|
||||||
}
|
}
|
||||||
Concurrency.run("Hide loading indicator") {
|
loadStopJob = Concurrency.run("Hide loading indicator") {
|
||||||
delay(waitFor.toMillis())
|
delay(waitFor.toMillis())
|
||||||
launchOnGLThread {
|
launchOnGLThread {
|
||||||
loadingImage.clearActions()
|
loadingImage.clearActions()
|
||||||
@ -147,11 +150,18 @@ class MultiplayerStatusButton(
|
|||||||
turnIndicator.flash()
|
turnIndicator.flash()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
override fun dispose() {
|
||||||
|
events.stopReceiving()
|
||||||
|
turnIndicator.dispose()
|
||||||
|
loadStopJob?.cancel()
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private class TurnIndicator : HorizontalGroup() {
|
private class TurnIndicator : HorizontalGroup(), Disposable {
|
||||||
val gameAmount = Label("2", BaseScreen.skin)
|
val gameAmount = Label("2", BaseScreen.skin)
|
||||||
val image: Image
|
val image: Image
|
||||||
|
private var job: Job? = null
|
||||||
init {
|
init {
|
||||||
image = ImageGetter.getImage("OtherIcons/ExclamationMark")
|
image = ImageGetter.getImage("OtherIcons/ExclamationMark")
|
||||||
image.setSize(30f)
|
image.setSize(30f)
|
||||||
@ -175,11 +185,15 @@ private class TurnIndicator : HorizontalGroup() {
|
|||||||
if (alternations == 0) return
|
if (alternations == 0) return
|
||||||
gameAmount.color = nextColor
|
gameAmount.color = nextColor
|
||||||
image.color = nextColor
|
image.color = nextColor
|
||||||
Concurrency.run("StatusButton color flash") {
|
job = Concurrency.run("StatusButton color flash") {
|
||||||
delay(500)
|
delay(500)
|
||||||
launchOnGLThread {
|
launchOnGLThread {
|
||||||
flash(alternations - 1, nextColor, curColor)
|
flash(alternations - 1, nextColor, curColor)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
override fun dispose() {
|
||||||
|
job?.cancel()
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@ -1,11 +1,12 @@
|
|||||||
package com.unciv.ui.worldscreen.status
|
package com.unciv.ui.worldscreen.status
|
||||||
|
|
||||||
import com.badlogic.gdx.scenes.scene2d.ui.HorizontalGroup
|
import com.badlogic.gdx.scenes.scene2d.ui.HorizontalGroup
|
||||||
|
import com.badlogic.gdx.utils.Disposable
|
||||||
|
|
||||||
class StatusButtons(
|
class StatusButtons(
|
||||||
nextTurnButton: NextTurnButton,
|
nextTurnButton: NextTurnButton,
|
||||||
multiplayerStatusButton: MultiplayerStatusButton? = null
|
multiplayerStatusButton: MultiplayerStatusButton? = null
|
||||||
) : HorizontalGroup() {
|
) : HorizontalGroup(), Disposable {
|
||||||
var multiplayerStatusButton: MultiplayerStatusButton? = multiplayerStatusButton
|
var multiplayerStatusButton: MultiplayerStatusButton? = multiplayerStatusButton
|
||||||
set(button) {
|
set(button) {
|
||||||
multiplayerStatusButton?.remove()
|
multiplayerStatusButton?.remove()
|
||||||
@ -23,4 +24,8 @@ class StatusButtons(
|
|||||||
}
|
}
|
||||||
addActor(nextTurnButton)
|
addActor(nextTurnButton)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
override fun dispose() {
|
||||||
|
multiplayerStatusButton?.dispose()
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user