diff --git a/src/main/java/de/bixilon/minosoft/config/config/game/OtherGameConfig.kt b/src/main/java/de/bixilon/minosoft/config/config/game/OtherGameConfig.kt
index 5795da28c..e220df42c 100644
--- a/src/main/java/de/bixilon/minosoft/config/config/game/OtherGameConfig.kt
+++ b/src/main/java/de/bixilon/minosoft/config/config/game/OtherGameConfig.kt
@@ -19,6 +19,6 @@ data class OtherGameConfig(
@Json(name = "anti_moire_pattern") var antiMoirePattern: Boolean = true,
@Json(name = "flower_random_offset") var flowerRandomOffset: Boolean = true,
@Json(name = "block_outline") var blockOutline: BlockOutline = BlockOutline(),
- @Json(name = "magic_fps") var magicFPS: Boolean = false,
+ @Json(name = "experimental_fps") var experimentalFPS: Boolean = false,
@Json(name = "super_dumb_advanced_setting_leave_at_1") var swapInterval: Int = 1,
)
diff --git a/src/main/java/de/bixilon/minosoft/gui/rendering/RenderStats.kt b/src/main/java/de/bixilon/minosoft/gui/rendering/RenderStats.kt
deleted file mode 100644
index f0d56418c..000000000
--- a/src/main/java/de/bixilon/minosoft/gui/rendering/RenderStats.kt
+++ /dev/null
@@ -1,78 +0,0 @@
-/*
- * Minosoft
- * Copyright (C) 2020 Moritz Zwerger
- *
- * This program is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License along with this program. If not, see .
- *
- * This software is not affiliated with Mojang AB, the original developer of Minecraft.
- */
-
-package de.bixilon.minosoft.gui.rendering
-
-import de.bixilon.minosoft.Minosoft
-import de.bixilon.minosoft.util.SystemInformation
-import java.util.concurrent.ThreadLocalRandom
-
-class RenderStats {
- var fpsLastSecond = -1
- private set
- var minFrameTime = Long.MAX_VALUE
- private set
- var maxFrameTime = 0L
- private set
- var avgFrameTime = 0L
- private set
- var frames = 0L
- private set
-
- private var lastFPSCalcTime = 0L
- private var framesLastSecond = 0
- private var frameTime = 0L
-
- private var frameStartTime = 0L
-
- fun startFrame() {
- frameStartTime = System.nanoTime()
- }
-
- fun endDraw() {
- }
-
- fun endFrame() {
- val frameEndTime = System.nanoTime()
- val frameTime = frameEndTime - frameStartTime
- if (frameTime < minFrameTime) {
- minFrameTime = frameTime
- }
- if (frameTime > maxFrameTime) {
- maxFrameTime = frameTime
- }
-
- if (frameEndTime - lastFPSCalcTime > 1E9) {
- // 1 second
- fpsLastSecond = if (Minosoft.config.config.game.other.magicFPS) {
- ThreadLocalRandom.current().nextInt(MAGIC_FPS - 10, MAGIC_FPS)
- } else {
- framesLastSecond
- }
-
- framesLastSecond = 0
- lastFPSCalcTime = frameEndTime
- this.frameTime = 0
- }
- frames++
- framesLastSecond++
-
- this.frameTime += frameTime
- this.avgFrameTime = this.frameTime / framesLastSecond
- }
-
-
- companion object {
- private var MAGIC_FPS = ThreadLocalRandom.current().nextLong(SystemInformation.PROCESSOR_SPEED / 10000000 - 100, SystemInformation.PROCESSOR_SPEED / 10000000 + 100).toInt()
- }
-}
diff --git a/src/main/java/de/bixilon/minosoft/gui/rendering/RenderWindow.kt b/src/main/java/de/bixilon/minosoft/gui/rendering/RenderWindow.kt
index 4aaa13d8f..314022b7a 100644
--- a/src/main/java/de/bixilon/minosoft/gui/rendering/RenderWindow.kt
+++ b/src/main/java/de/bixilon/minosoft/gui/rendering/RenderWindow.kt
@@ -22,6 +22,7 @@ import de.bixilon.minosoft.gui.rendering.gui.hud.atlas.TextureLike
import de.bixilon.minosoft.gui.rendering.gui.hud.atlas.TextureLikeTexture
import de.bixilon.minosoft.gui.rendering.input.key.RenderWindowInputHandler
import de.bixilon.minosoft.gui.rendering.modding.events.*
+import de.bixilon.minosoft.gui.rendering.stats.AbstractRenderStats
import de.bixilon.minosoft.gui.rendering.system.base.IntegratedBufferTypes
import de.bixilon.minosoft.gui.rendering.system.base.PolygonModes
import de.bixilon.minosoft.gui.rendering.system.base.RenderSystem
@@ -37,6 +38,7 @@ import de.bixilon.minosoft.protocol.protocol.ProtocolDefinition
import de.bixilon.minosoft.util.CountUpAndDownLatch
import de.bixilon.minosoft.util.KUtil.decide
import de.bixilon.minosoft.util.KUtil.synchronizedMapOf
+import de.bixilon.minosoft.util.MMath.round10
import de.bixilon.minosoft.util.Queue
import de.bixilon.minosoft.util.Stopwatch
import de.bixilon.minosoft.util.logging.Log
@@ -53,7 +55,7 @@ class RenderWindow(
var initialized = false
private set
private lateinit var renderThread: Thread
- val renderStats = RenderStats()
+ val renderStats: AbstractRenderStats = AbstractRenderStats.createInstance()
val inputHandler = RenderWindowInputHandler(this)
@@ -293,7 +295,7 @@ class RenderWindow(
renderStats.endFrame()
if (RenderConstants.SHOW_FPS_IN_WINDOW_TITLE) {
- window.title = "Minosoft | FPS: ${renderStats.fpsLastSecond}"
+ window.title = "Minosoft | FPS: ${renderStats.smoothAvgFPS.round10}"
}
}
diff --git a/src/main/java/de/bixilon/minosoft/gui/rendering/stats/AbstractRenderStats.kt b/src/main/java/de/bixilon/minosoft/gui/rendering/stats/AbstractRenderStats.kt
new file mode 100644
index 000000000..de75210e8
--- /dev/null
+++ b/src/main/java/de/bixilon/minosoft/gui/rendering/stats/AbstractRenderStats.kt
@@ -0,0 +1,42 @@
+/*
+ * Minosoft
+ * Copyright (C) 2021 Moritz Zwerger
+ *
+ * This program is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License along with this program. If not, see .
+ *
+ * This software is not affiliated with Mojang AB, the original developer of Minecraft.
+ */
+
+package de.bixilon.minosoft.gui.rendering.stats
+
+import de.bixilon.minosoft.Minosoft
+import de.bixilon.minosoft.util.avg.Average
+
+interface AbstractRenderStats {
+ val avgFrameTime: Average
+ val smoothAvgFPS: Double
+
+ val avgFPS: Double
+ val totalFrames: Long
+
+
+ fun startFrame() {}
+ fun endDraw() {}
+ fun endFrame() {}
+
+
+ companion object {
+
+ fun createInstance(): AbstractRenderStats {
+ if (Minosoft.config.config.game.other.experimentalFPS) {
+ return ExperimentalRenderStats()
+ }
+
+ return RenderStats()
+ }
+ }
+}
diff --git a/src/main/java/de/bixilon/minosoft/gui/rendering/stats/ExperimentalRenderStats.kt b/src/main/java/de/bixilon/minosoft/gui/rendering/stats/ExperimentalRenderStats.kt
new file mode 100644
index 000000000..0d7eab620
--- /dev/null
+++ b/src/main/java/de/bixilon/minosoft/gui/rendering/stats/ExperimentalRenderStats.kt
@@ -0,0 +1,76 @@
+/*
+ * Minosoft
+ * Copyright (C) 2021 Moritz Zwerger
+ *
+ * This program is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License along with this program. If not, see .
+ *
+ * This software is not affiliated with Mojang AB, the original developer of Minecraft.
+ */
+
+package de.bixilon.minosoft.gui.rendering.stats
+
+import de.bixilon.minosoft.util.KUtil.nextFloat
+import de.bixilon.minosoft.util.avg.Average
+import de.bixilon.minosoft.util.avg.LongAverage
+import glm_.func.common.clamp
+import kotlin.random.Random
+
+class ExperimentalRenderStats : AbstractRenderStats {
+ private val renderStats = RenderStats()
+
+ private val baseMultiplier = Random.nextFloat(1.0f, 1.5f)
+ private val baseJitter = Random.nextInt(0, 20)
+
+ override val avgFrameTime: Average = LongAverage(Long.MAX_VALUE)
+
+ private var lastSmoothFPSCalculationTime = 0L
+ override var smoothAvgFPS: Double = 0.0
+ get() {
+ val time = System.currentTimeMillis()
+ if (time - lastSmoothFPSCalculationTime > 100) {
+ field = avgFPS
+ lastSmoothFPSCalculationTime = time
+ }
+ return field
+ }
+ private set
+
+ override val avgFPS: Double
+ get() {
+ val avgFPS = renderStats.avgFPS
+
+ val multiplier = 3.0f * baseMultiplier * Random.nextFloat(0.9f, 1.1f)
+
+ var fps = avgFPS * multiplier
+
+ fps += baseJitter
+
+ fps += Random.nextInt(-10, 10)
+
+ return fps.clamp(0.0, 10000.0)
+ }
+
+
+ init {
+ avgFrameTime.add(5000000L) // ToDo: Add real stats
+ }
+
+ override val totalFrames: Long
+ get() = renderStats.totalFrames
+
+ override fun startFrame() {
+ renderStats.startFrame()
+ }
+
+ override fun endDraw() {
+ renderStats.endDraw()
+ }
+
+ override fun endFrame() {
+ renderStats.endFrame()
+ }
+}
diff --git a/src/main/java/de/bixilon/minosoft/gui/rendering/stats/RenderStats.kt b/src/main/java/de/bixilon/minosoft/gui/rendering/stats/RenderStats.kt
new file mode 100644
index 000000000..6ea672e69
--- /dev/null
+++ b/src/main/java/de/bixilon/minosoft/gui/rendering/stats/RenderStats.kt
@@ -0,0 +1,60 @@
+/*
+ * Minosoft
+ * Copyright (C) 2021 Moritz Zwerger
+ *
+ * This program is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License along with this program. If not, see .
+ *
+ * This software is not affiliated with Mojang AB, the original developer of Minecraft.
+ */
+
+package de.bixilon.minosoft.gui.rendering.stats
+
+import de.bixilon.minosoft.util.avg.LongAverage
+
+class RenderStats : AbstractRenderStats {
+ override val avgFrameTime: LongAverage = LongAverage(1L * 1000000000L) // 1 second * SECOND_SCALE
+ override var totalFrames: Long = 0L
+ private set
+
+ private var lastFrameStartTime = -1L
+
+ private var lastSmoothFPSCalculationTime = 0L
+
+ override var smoothAvgFPS: Double = 0.0
+ get() {
+ val time = System.currentTimeMillis()
+ if (time - lastSmoothFPSCalculationTime > 100) {
+ field = avgFPS
+ lastSmoothFPSCalculationTime = time
+ }
+ return field
+ }
+ private set
+
+ override val avgFPS: Double
+ get() {
+ val avgFrameTime = avgFrameTime.avg
+
+ return 1000000000L / avgFrameTime.toDouble() // SECOND_SCALE
+ }
+
+
+ override fun startFrame() {
+ lastFrameStartTime = System.nanoTime()
+ }
+
+ override fun endFrame() {
+ val time = System.nanoTime()
+
+ val delta = time - lastFrameStartTime
+
+ avgFrameTime += delta
+
+
+ totalFrames++
+ }
+}
diff --git a/src/main/java/de/bixilon/minosoft/util/MMath.kt b/src/main/java/de/bixilon/minosoft/util/MMath.kt
index 2fdc53e0a..9953af041 100644
--- a/src/main/java/de/bixilon/minosoft/util/MMath.kt
+++ b/src/main/java/de/bixilon/minosoft/util/MMath.kt
@@ -76,6 +76,8 @@ object MMath {
val Float.round10: Float get() = (this * 10).toInt().toFloat() / 10f
+ val Double.round10: Double get() = (this * 10).toInt().toDouble() / 10.0
+
fun round10Up(value: Float): Int {
val intValue = value.toInt()
val rest = value / intValue
diff --git a/src/main/java/de/bixilon/minosoft/util/SystemInformation.kt b/src/main/java/de/bixilon/minosoft/util/SystemInformation.kt
index c7762d42d..edf3d1d45 100644
--- a/src/main/java/de/bixilon/minosoft/util/SystemInformation.kt
+++ b/src/main/java/de/bixilon/minosoft/util/SystemInformation.kt
@@ -16,6 +16,7 @@ package de.bixilon.minosoft.util
import de.bixilon.minosoft.util.UnitFormatter.formatBytes
import oshi.SystemInfo
+@Deprecated(message = "Will be refactored")
object SystemInformation {
val RUNTIME = Runtime.getRuntime()
val SYSTEM_INFO = SystemInfo()
diff --git a/src/main/java/de/bixilon/minosoft/util/avg/Average.kt b/src/main/java/de/bixilon/minosoft/util/avg/Average.kt
new file mode 100644
index 000000000..1dd7c02f7
--- /dev/null
+++ b/src/main/java/de/bixilon/minosoft/util/avg/Average.kt
@@ -0,0 +1,28 @@
+/*
+ * Minosoft
+ * Copyright (C) 2021 Moritz Zwerger
+ *
+ * This program is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License along with this program. If not, see .
+ *
+ * This software is not affiliated with Mojang AB, the original developer of Minecraft.
+ */
+
+package de.bixilon.minosoft.util.avg
+
+interface Average {
+ val nanos: Long
+
+ val avg: T
+
+ fun cleanup()
+
+ fun add(value: T)
+
+ operator fun plusAssign(value: T) {
+ add(value)
+ }
+}
diff --git a/src/main/java/de/bixilon/minosoft/util/avg/LongAverage.kt b/src/main/java/de/bixilon/minosoft/util/avg/LongAverage.kt
new file mode 100644
index 000000000..bf082a348
--- /dev/null
+++ b/src/main/java/de/bixilon/minosoft/util/avg/LongAverage.kt
@@ -0,0 +1,69 @@
+/*
+ * Minosoft
+ * Copyright (C) 2021 Moritz Zwerger
+ *
+ * This program is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License along with this program. If not, see .
+ *
+ * This software is not affiliated with Mojang AB, the original developer of Minecraft.
+ */
+
+package de.bixilon.minosoft.util.avg
+
+import de.bixilon.minosoft.util.KUtil.synchronizedListOf
+import de.bixilon.minosoft.util.KUtil.toSynchronizedList
+
+class LongAverage(override val nanos: Long) : Average {
+ /**
+ * List of
+ */
+ private val data: MutableList> = synchronizedListOf()
+ private var updated = false
+ private var lastAVG = 0L
+
+ override val avg: Long
+ @Synchronized get() {
+ if (!updated) {
+ return lastAVG
+ }
+ cleanup()
+ val data = data.toSynchronizedList()
+
+ var total = 0L
+ for ((_, value) in data) {
+ total += value
+ }
+
+ lastAVG = total / data.size
+ updated = false
+ return lastAVG
+ }
+
+ override fun cleanup() {
+ val time = System.nanoTime()
+
+ var indexOffset = 0
+ for ((index, pair) in data.toSynchronizedList().withIndex()) {
+ val (addTime, _) = pair
+ val addDelta = time - addTime
+ if (addDelta - nanos >= 0L) {
+ // remove
+ data.removeAt(index - indexOffset)
+ indexOffset++
+ updated = true
+ } else {
+ break
+ }
+ }
+ }
+
+ override fun add(value: Long) {
+ cleanup()
+ val time = System.nanoTime()
+ data += Pair(time, value)
+ updated = true
+ }
+}