mirror of
https://gitlab.bixilon.de/bixilon/minosoft.git
synced 2025-09-18 11:54:59 -04:00
rendering: screenshot saver, auto add missing hotkeys to config
This commit is contained in:
parent
42d9c9b592
commit
2b0f7a0c13
@ -22,7 +22,7 @@ public class StaticConfiguration {
|
|||||||
public static final boolean DEBUG_MODE = true; // if true, additional checks will be made to validate data, ... Decreases performance
|
public static final boolean DEBUG_MODE = true; // if true, additional checks will be made to validate data, ... Decreases performance
|
||||||
public static final boolean BIOME_DEBUG_MODE = false; // colors all biomes according to the biome hashCode
|
public static final boolean BIOME_DEBUG_MODE = false; // colors all biomes according to the biome hashCode
|
||||||
public static final boolean DEBUG_SLOW_LOADING = false; // if true, many Thread.sleep will be executed and the start will be delayed (by a lot)
|
public static final boolean DEBUG_SLOW_LOADING = false; // if true, many Thread.sleep will be executed and the start will be delayed (by a lot)
|
||||||
public static final boolean SHOW_LOG_MESSAGES_IN_CHAT = false; // prints all console messages in the chat box
|
public static final boolean SHOW_LOG_MESSAGES_IN_CHAT = true; // prints all console messages in the chat box
|
||||||
public static String CONFIG_FILENAME = "minosoft.json"; // Filename of minosoft's base configuration (located in AppData/Minosoft/config)
|
public static String CONFIG_FILENAME = "minosoft.json"; // Filename of minosoft's base configuration (located in AppData/Minosoft/config)
|
||||||
public static boolean SKIP_MOJANG_AUTHENTICATION; // disables all connections to mojang
|
public static boolean SKIP_MOJANG_AUTHENTICATION; // disables all connections to mojang
|
||||||
public static boolean COLORED_LOG = true; // the log should be colored with ANSI (does not affect base components)
|
public static boolean COLORED_LOG = true; // the log should be colored with ANSI (does not affect base components)
|
||||||
|
@ -13,28 +13,49 @@
|
|||||||
|
|
||||||
package de.bixilon.minosoft.config.config.game.controls
|
package de.bixilon.minosoft.config.config.game.controls
|
||||||
|
|
||||||
import de.bixilon.minosoft.config.config.game.controls.KeyBindingsNames.DEBUG_CLEAR_CHUNK_CACHE
|
import de.bixilon.minosoft.config.config.game.controls.KeyBindingsNames.DEFAULT_KEY_BINDINGS
|
||||||
import de.bixilon.minosoft.config.config.game.controls.KeyBindingsNames.DEBUG_MOUSE_CATCH
|
|
||||||
import de.bixilon.minosoft.config.config.game.controls.KeyBindingsNames.DEBUG_POLYGEN
|
|
||||||
import de.bixilon.minosoft.config.config.game.controls.KeyBindingsNames.DEBUG_SCREEN
|
|
||||||
import de.bixilon.minosoft.config.config.game.controls.KeyBindingsNames.MOVE_BACKWARDS
|
|
||||||
import de.bixilon.minosoft.config.config.game.controls.KeyBindingsNames.MOVE_FLY_DOWN
|
|
||||||
import de.bixilon.minosoft.config.config.game.controls.KeyBindingsNames.MOVE_FLY_UP
|
|
||||||
import de.bixilon.minosoft.config.config.game.controls.KeyBindingsNames.MOVE_FORWARD
|
|
||||||
import de.bixilon.minosoft.config.config.game.controls.KeyBindingsNames.MOVE_LEFT
|
|
||||||
import de.bixilon.minosoft.config.config.game.controls.KeyBindingsNames.MOVE_RIGHT
|
|
||||||
import de.bixilon.minosoft.config.config.game.controls.KeyBindingsNames.MOVE_SPRINT
|
|
||||||
import de.bixilon.minosoft.config.config.game.controls.KeyBindingsNames.QUIT_RENDERING
|
|
||||||
import de.bixilon.minosoft.config.config.game.controls.KeyBindingsNames.WHEN_IN_GAME
|
|
||||||
import de.bixilon.minosoft.config.config.game.controls.KeyBindingsNames.WHEN_PLAYER_IS_FLYING
|
|
||||||
import de.bixilon.minosoft.config.config.game.controls.KeyBindingsNames.ZOOM
|
|
||||||
import de.bixilon.minosoft.config.key.KeyAction
|
import de.bixilon.minosoft.config.key.KeyAction
|
||||||
import de.bixilon.minosoft.config.key.KeyBinding
|
import de.bixilon.minosoft.config.key.KeyBinding
|
||||||
import de.bixilon.minosoft.config.key.KeyCodes
|
import de.bixilon.minosoft.config.key.KeyCodes
|
||||||
import de.bixilon.minosoft.data.mappings.ResourceLocation
|
import de.bixilon.minosoft.data.mappings.ResourceLocation
|
||||||
|
|
||||||
data class KeyBindingsGameConfig(
|
data class KeyBindingsGameConfig(
|
||||||
val entries: MutableMap<ResourceLocation, KeyBinding> = mutableMapOf(
|
val entries: MutableMap<ResourceLocation, KeyBinding> = mutableMapOf(),
|
||||||
|
) {
|
||||||
|
init {
|
||||||
|
for ((resourceLocation, keyBinding) in DEFAULT_KEY_BINDINGS) {
|
||||||
|
if (!entries.containsKey(resourceLocation)) {
|
||||||
|
// add key binding
|
||||||
|
entries[resourceLocation] = KeyBinding(keyBinding)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
object KeyBindingsNames {
|
||||||
|
val MOVE_FORWARD = ResourceLocation("minosoft:move_forward")
|
||||||
|
val MOVE_BACKWARDS = ResourceLocation("minosoft:move_backwards")
|
||||||
|
val MOVE_LEFT = ResourceLocation("minosoft:move_left")
|
||||||
|
val MOVE_RIGHT = ResourceLocation("minosoft:move_right")
|
||||||
|
val MOVE_SPRINT = ResourceLocation("minosoft:move_sprint")
|
||||||
|
val MOVE_FLY_UP = ResourceLocation("minosoft:move_fly_up")
|
||||||
|
val MOVE_FLY_DOWN = ResourceLocation("minosoft:move_fly_down")
|
||||||
|
|
||||||
|
val ZOOM = ResourceLocation("minosoft:zoom")
|
||||||
|
|
||||||
|
val QUIT_RENDERING = ResourceLocation("minosoft:quit_rendering")
|
||||||
|
|
||||||
|
val DEBUG_SCREEN = ResourceLocation("minosoft:debug_screen")
|
||||||
|
val DEBUG_CLEAR_CHUNK_CACHE = ResourceLocation("minosoft:debug_clear_chunk_cache")
|
||||||
|
val DEBUG_POLYGEN = ResourceLocation("minosoft:debug_polygen")
|
||||||
|
val DEBUG_MOUSE_CATCH = ResourceLocation("minosoft:debug_mouse_catch")
|
||||||
|
|
||||||
|
val WHEN_IN_GAME = ResourceLocation("minosoft:in_game")
|
||||||
|
val WHEN_PLAYER_IS_FLYING = ResourceLocation("minosoft:is_flying")
|
||||||
|
|
||||||
|
val TAKE_SCREENSHOT = ResourceLocation("minosoft:take_screenshot")
|
||||||
|
|
||||||
|
val DEFAULT_KEY_BINDINGS: Map<ResourceLocation, KeyBinding> = mapOf(
|
||||||
MOVE_FORWARD to KeyBinding(
|
MOVE_FORWARD to KeyBinding(
|
||||||
mutableMapOf(
|
mutableMapOf(
|
||||||
KeyAction.CHANGE to mutableSetOf(KeyCodes.KEY_W)
|
KeyAction.CHANGE to mutableSetOf(KeyCodes.KEY_W)
|
||||||
@ -116,27 +137,11 @@ data class KeyBindingsGameConfig(
|
|||||||
),
|
),
|
||||||
mutableSetOf(mutableSetOf(WHEN_IN_GAME))
|
mutableSetOf(mutableSetOf(WHEN_IN_GAME))
|
||||||
),
|
),
|
||||||
|
TAKE_SCREENSHOT to KeyBinding(
|
||||||
|
mutableMapOf(
|
||||||
|
KeyAction.RELEASE to mutableSetOf(KeyCodes.KEY_F2)
|
||||||
|
),
|
||||||
|
mutableSetOf()
|
||||||
),
|
),
|
||||||
)
|
)
|
||||||
|
|
||||||
object KeyBindingsNames {
|
|
||||||
val MOVE_FORWARD = ResourceLocation("minosoft:move_forward")
|
|
||||||
val MOVE_BACKWARDS = ResourceLocation("minosoft:move_backwards")
|
|
||||||
val MOVE_LEFT = ResourceLocation("minosoft:move_left")
|
|
||||||
val MOVE_RIGHT = ResourceLocation("minosoft:move_right")
|
|
||||||
val MOVE_SPRINT = ResourceLocation("minosoft:move_sprint")
|
|
||||||
val MOVE_FLY_UP = ResourceLocation("minosoft:move_fly_up")
|
|
||||||
val MOVE_FLY_DOWN = ResourceLocation("minosoft:move_fly_down")
|
|
||||||
|
|
||||||
val ZOOM = ResourceLocation("minosoft:zoom")
|
|
||||||
|
|
||||||
val QUIT_RENDERING = ResourceLocation("minosoft:quit_rendering")
|
|
||||||
|
|
||||||
val DEBUG_SCREEN = ResourceLocation("minosoft:debug_screen")
|
|
||||||
val DEBUG_CLEAR_CHUNK_CACHE = ResourceLocation("minosoft:debug_clear_chunk_cache")
|
|
||||||
val DEBUG_POLYGEN = ResourceLocation("minosoft:debug_polygen")
|
|
||||||
val DEBUG_MOUSE_CATCH = ResourceLocation("minosoft:debug_mouse_catch")
|
|
||||||
|
|
||||||
val WHEN_IN_GAME = ResourceLocation("minosoft:in_game")
|
|
||||||
val WHEN_PLAYER_IS_FLYING = ResourceLocation("minosoft:is_flying")
|
|
||||||
}
|
}
|
||||||
|
@ -18,4 +18,6 @@ import de.bixilon.minosoft.data.mappings.ResourceLocation
|
|||||||
class KeyBinding(
|
class KeyBinding(
|
||||||
val action: MutableMap<KeyAction, MutableSet<KeyCodes>>,
|
val action: MutableMap<KeyAction, MutableSet<KeyCodes>>,
|
||||||
val `when`: MutableSet<MutableSet<ResourceLocation>>,
|
val `when`: MutableSet<MutableSet<ResourceLocation>>,
|
||||||
)
|
) {
|
||||||
|
constructor(keyBinding: KeyBinding) : this(keyBinding.action.toMutableMap(), keyBinding.`when`.toMutableSet()) // ToDo: Deep copy
|
||||||
|
}
|
||||||
|
@ -28,4 +28,6 @@ object RenderConstants {
|
|||||||
val LILY_PAD_BLOCK_COLOR = RGBColor("#208030")
|
val LILY_PAD_BLOCK_COLOR = RGBColor("#208030")
|
||||||
|
|
||||||
const val COLORMAP_SIZE = 255
|
const val COLORMAP_SIZE = 255
|
||||||
|
|
||||||
|
const val DEBUG_MESSAGES_PREFIX = "§f[§e§lDEBUG§f] §9"
|
||||||
}
|
}
|
||||||
|
@ -24,6 +24,7 @@ import de.bixilon.minosoft.data.text.RGBColor
|
|||||||
import de.bixilon.minosoft.gui.rendering.chunk.WorldRenderer
|
import de.bixilon.minosoft.gui.rendering.chunk.WorldRenderer
|
||||||
import de.bixilon.minosoft.gui.rendering.hud.HUDRenderer
|
import de.bixilon.minosoft.gui.rendering.hud.HUDRenderer
|
||||||
import de.bixilon.minosoft.gui.rendering.hud.elements.RenderStats
|
import de.bixilon.minosoft.gui.rendering.hud.elements.RenderStats
|
||||||
|
import de.bixilon.minosoft.gui.rendering.util.ScreenshotTaker
|
||||||
import de.bixilon.minosoft.modding.event.EventInvokerCallback
|
import de.bixilon.minosoft.modding.event.EventInvokerCallback
|
||||||
import de.bixilon.minosoft.modding.event.events.ConnectionStateChangeEvent
|
import de.bixilon.minosoft.modding.event.events.ConnectionStateChangeEvent
|
||||||
import de.bixilon.minosoft.modding.event.events.PacketReceiveEvent
|
import de.bixilon.minosoft.modding.event.events.PacketReceiveEvent
|
||||||
@ -40,7 +41,7 @@ import org.lwjgl.system.MemoryStack
|
|||||||
import org.lwjgl.system.MemoryUtil
|
import org.lwjgl.system.MemoryUtil
|
||||||
import java.util.concurrent.ConcurrentLinkedQueue
|
import java.util.concurrent.ConcurrentLinkedQueue
|
||||||
|
|
||||||
class RenderWindow(private val connection: Connection, val rendering: Rendering) {
|
class RenderWindow(val connection: Connection, val rendering: Rendering) {
|
||||||
private val keyBindingCallbacks: MutableMap<ResourceLocation, Pair<KeyBinding, MutableSet<((keyCode: KeyCodes, keyEvent: KeyAction) -> Unit)>>> = mutableMapOf()
|
private val keyBindingCallbacks: MutableMap<ResourceLocation, Pair<KeyBinding, MutableSet<((keyCode: KeyCodes, keyEvent: KeyAction) -> Unit)>>> = mutableMapOf()
|
||||||
private val keysDown: MutableSet<KeyCodes> = mutableSetOf()
|
private val keysDown: MutableSet<KeyCodes> = mutableSetOf()
|
||||||
private val keyBindingDown: MutableSet<KeyBinding> = mutableSetOf()
|
private val keyBindingDown: MutableSet<KeyBinding> = mutableSetOf()
|
||||||
@ -59,6 +60,7 @@ class RenderWindow(private val connection: Connection, val rendering: Rendering)
|
|||||||
private var polygonEnabled = false
|
private var polygonEnabled = false
|
||||||
private var mouseCatch = !StaticConfiguration.DEBUG_MODE
|
private var mouseCatch = !StaticConfiguration.DEBUG_MODE
|
||||||
|
|
||||||
|
private val screenshotTaker = ScreenshotTaker(this)
|
||||||
val tintColorCalculator = TintColorCalculator()
|
val tintColorCalculator = TintColorCalculator()
|
||||||
|
|
||||||
// all renderers
|
// all renderers
|
||||||
@ -259,27 +261,8 @@ class RenderWindow(private val connection: Connection, val rendering: Rendering)
|
|||||||
}
|
}
|
||||||
})
|
})
|
||||||
|
|
||||||
registerKeyCallback(KeyBindingsNames.DEBUG_POLYGEN) { _: KeyCodes, _: KeyAction ->
|
|
||||||
polygonEnabled = !polygonEnabled
|
registerGlobalKeyCombinations()
|
||||||
glPolygonMode(GL_FRONT_AND_BACK, if (polygonEnabled) {
|
|
||||||
GL_LINE
|
|
||||||
} else {
|
|
||||||
GL_FILL
|
|
||||||
})
|
|
||||||
connection.sender.sendFakeChatMessage("§f[§e§lDEBUG§f] §9Toggled polygen mode!")
|
|
||||||
}
|
|
||||||
registerKeyCallback(KeyBindingsNames.DEBUG_MOUSE_CATCH) { _: KeyCodes, _: KeyAction ->
|
|
||||||
mouseCatch = !mouseCatch
|
|
||||||
if (mouseCatch) {
|
|
||||||
glfwSetInputMode(windowId, GLFW_CURSOR, GLFW_CURSOR_DISABLED)
|
|
||||||
} else {
|
|
||||||
glfwSetInputMode(windowId, GLFW_CURSOR, GLFW_CURSOR_NORMAL)
|
|
||||||
}
|
|
||||||
connection.sender.sendFakeChatMessage("§f[§e§lDEBUG§f] §9Toggled mouse catch!")
|
|
||||||
}
|
|
||||||
registerKeyCallback(KeyBindingsNames.QUIT_RENDERING) { _: KeyCodes, _: KeyAction ->
|
|
||||||
glfwSetWindowShouldClose(windowId, true)
|
|
||||||
}
|
|
||||||
|
|
||||||
hudRenderer.screenChangeResizeCallback(screenWidth, screenHeight)
|
hudRenderer.screenChangeResizeCallback(screenWidth, screenHeight)
|
||||||
|
|
||||||
@ -296,6 +279,33 @@ class RenderWindow(private val connection: Connection, val rendering: Rendering)
|
|||||||
glfwShowWindow(windowId)
|
glfwShowWindow(windowId)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private fun registerGlobalKeyCombinations() {
|
||||||
|
registerKeyCallback(KeyBindingsNames.DEBUG_POLYGEN) { _: KeyCodes, _: KeyAction ->
|
||||||
|
polygonEnabled = !polygonEnabled
|
||||||
|
glPolygonMode(GL_FRONT_AND_BACK, if (polygonEnabled) {
|
||||||
|
GL_LINE
|
||||||
|
} else {
|
||||||
|
GL_FILL
|
||||||
|
})
|
||||||
|
sendDebugMessage("Toggled polygen mode!")
|
||||||
|
}
|
||||||
|
registerKeyCallback(KeyBindingsNames.DEBUG_MOUSE_CATCH) { _: KeyCodes, _: KeyAction ->
|
||||||
|
mouseCatch = !mouseCatch
|
||||||
|
if (mouseCatch) {
|
||||||
|
glfwSetInputMode(windowId, GLFW_CURSOR, GLFW_CURSOR_DISABLED)
|
||||||
|
} else {
|
||||||
|
glfwSetInputMode(windowId, GLFW_CURSOR, GLFW_CURSOR_NORMAL)
|
||||||
|
}
|
||||||
|
sendDebugMessage("Toggled mouse catch!")
|
||||||
|
}
|
||||||
|
registerKeyCallback(KeyBindingsNames.QUIT_RENDERING) { _: KeyCodes, _: KeyAction ->
|
||||||
|
glfwSetWindowShouldClose(windowId, true)
|
||||||
|
}
|
||||||
|
registerKeyCallback(KeyBindingsNames.TAKE_SCREENSHOT) { _: KeyCodes, _: KeyAction ->
|
||||||
|
screenshotTaker.takeScreenshot()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
fun startRenderLoop() {
|
fun startRenderLoop() {
|
||||||
while (!glfwWindowShouldClose(windowId)) {
|
while (!glfwWindowShouldClose(windowId)) {
|
||||||
if (renderingStatus == RenderingStates.PAUSED) {
|
if (renderingStatus == RenderingStates.PAUSED) {
|
||||||
@ -382,4 +392,8 @@ class RenderWindow(private val connection: Connection, val rendering: Rendering)
|
|||||||
fun setSkyColor(color: RGBColor) {
|
fun setSkyColor(color: RGBColor) {
|
||||||
glClearColor(color.floatRed, color.floatGreen, color.floatBlue, 1.0f)
|
glClearColor(color.floatRed, color.floatGreen, color.floatBlue, 1.0f)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fun sendDebugMessage(message: String) {
|
||||||
|
connection.sender.sendFakeChatMessage(RenderConstants.DEBUG_MESSAGES_PREFIX + message)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@ -0,0 +1,71 @@
|
|||||||
|
/*
|
||||||
|
* 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 <https://www.gnu.org/licenses/>.
|
||||||
|
*
|
||||||
|
* This software is not affiliated with Mojang AB, the original developer of Minecraft.
|
||||||
|
*/
|
||||||
|
|
||||||
|
package de.bixilon.minosoft.gui.rendering.util
|
||||||
|
|
||||||
|
import de.bixilon.minosoft.config.StaticConfiguration
|
||||||
|
import de.bixilon.minosoft.gui.rendering.RenderWindow
|
||||||
|
import de.bixilon.minosoft.util.Util
|
||||||
|
import de.matthiasmann.twl.utils.PNGDecoder
|
||||||
|
import org.lwjgl.BufferUtils
|
||||||
|
import org.lwjgl.opengl.GL11.*
|
||||||
|
import java.awt.image.BufferedImage
|
||||||
|
import java.io.File
|
||||||
|
import java.nio.ByteBuffer
|
||||||
|
import java.text.SimpleDateFormat
|
||||||
|
import javax.imageio.ImageIO
|
||||||
|
|
||||||
|
|
||||||
|
class ScreenshotTaker(
|
||||||
|
private val renderWindow: RenderWindow,
|
||||||
|
) {
|
||||||
|
fun takeScreenshot() {
|
||||||
|
try {
|
||||||
|
val basePath = "${StaticConfiguration.HOME_DIRECTORY}/screenshots/${renderWindow.connection.address.hostname}/${DATE_FORMATTER.format(System.currentTimeMillis())}"
|
||||||
|
Util.createParentFolderIfNotExist(basePath)
|
||||||
|
var path = "$basePath.png"
|
||||||
|
var i = 1
|
||||||
|
while (File(path).exists()) {
|
||||||
|
path = "${basePath}_${i++}.png"
|
||||||
|
}
|
||||||
|
|
||||||
|
val width = renderWindow.screenWidth
|
||||||
|
val height = renderWindow.screenHeight
|
||||||
|
val buffer: ByteBuffer = BufferUtils.createByteBuffer(width * height * PNGDecoder.Format.RGBA.numComponents)
|
||||||
|
glReadPixels(0, 0, width, height, GL_RGBA, GL_UNSIGNED_BYTE, buffer)
|
||||||
|
|
||||||
|
val bufferedImage = BufferedImage(width, height, BufferedImage.TYPE_INT_RGB)
|
||||||
|
|
||||||
|
for (x in 0 until width) {
|
||||||
|
for (y in 0 until height) {
|
||||||
|
val index: Int = (x + width * y) * 4
|
||||||
|
val red: Int = buffer[index].toInt() and 0xFF
|
||||||
|
val green: Int = buffer[index + 1].toInt() and 0xFF
|
||||||
|
val blue: Int = buffer[index + 2].toInt() and 0xFF
|
||||||
|
bufferedImage.setRGB(x, height - (y + 1), 0xFF shl 24 or (red shl 16) or (green shl 8) or blue)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
ImageIO.write(bufferedImage, "png", File(path))
|
||||||
|
|
||||||
|
renderWindow.sendDebugMessage("§aScreenshot saved to §f$path")
|
||||||
|
} catch (exception: Exception) {
|
||||||
|
exception.printStackTrace()
|
||||||
|
renderWindow.sendDebugMessage("§cFailed to make a screenshot!")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
companion object {
|
||||||
|
private val DATE_FORMATTER = SimpleDateFormat("yyyy-MM-dd_HH.mm.ss")
|
||||||
|
}
|
||||||
|
}
|
@ -28,9 +28,6 @@ class PacketUpdateLight : ClientboundPacket() {
|
|||||||
override fun read(buffer: InByteBuffer): Boolean {
|
override fun read(buffer: InByteBuffer): Boolean {
|
||||||
position = ChunkPosition(buffer.readVarInt(), buffer.readVarInt())
|
position = ChunkPosition(buffer.readVarInt(), buffer.readVarInt())
|
||||||
|
|
||||||
if (position == ChunkPosition(-6, 20)) {
|
|
||||||
Log.debug("")
|
|
||||||
}
|
|
||||||
if (buffer.versionId >= ProtocolVersions.V_1_16_PRE3) {
|
if (buffer.versionId >= ProtocolVersions.V_1_16_PRE3) {
|
||||||
val trustEdges = buffer.readBoolean()
|
val trustEdges = buffer.readBoolean()
|
||||||
}
|
}
|
||||||
|
Loading…
x
Reference in New Issue
Block a user