Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat: add simple frontend for in-game preview, closes #178 #217

Merged
merged 1 commit into from
Oct 19, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 2 additions & 4 deletions src/commonMain/kotlin/net/kyori/adventure/webui/Constants.kt
Original file line number Diff line number Diff line change
Expand Up @@ -42,10 +42,8 @@ public const val PARAM_EDITOR_TOKEN: String = "token"
/** Path for getting a short link for a MiniMessage input. */
public const val URL_MINI_SHORTEN: String = "/mini-shorten"

/** Path for getting a hostname for an in-game MiniMessage motd preview. */
public const val URL_SETUP_MOTD_PREVIEW: String = "/setup-motd-preview"
/** Path for getting a hostname for an in-game MiniMessage kick preview. */
public const val URL_SETUP_KICK_PREVIEW: String = "/setup-kick-preview"
/** Path for getting a hostname for an in-game MiniMessage preview. */
public const val URL_IN_GAME_PREVIEW: String = "/in-game-preview"

/** Path for getting the configuration of this WebUI instance */
public const val URL_BUILD_INFO: String = "/build"
Original file line number Diff line number Diff line change
Expand Up @@ -28,3 +28,9 @@ public data class Combined(
public val background: String? = null,
public val mode: String? = null
)

@Serializable
public data class InGamePreview(
public val miniMessage: String? = null,
public val key: String? = null
)
3 changes: 3 additions & 0 deletions src/commonMain/resources/web/index.html
Original file line number Diff line number Diff line change
Expand Up @@ -61,6 +61,9 @@ <h1 class="title mc-font">MiniMessage Viewer</h1>
<button class="button" id="copy-button" aria-label="Copy input" title="Copy input">
<span class="icon is-small"><i class="fas fa-copy"></i></span>
</button>
<button class="button" id="in-game-preview-button" aria-label="Try in-game" title="Try in-game">
<span class="icon is-small"><i class="fas fa-gamepad"></i></span>
</button>
<div class="dropdown share-dropdown">
<div class="dropdown-trigger">
<button class="button" aria-haspopup="true" aria-controls="share-dropdown-menu">
Expand Down
16 changes: 16 additions & 0 deletions src/jsMain/kotlin/net/kyori/adventure/webui/js/Main.kt
Original file line number Diff line number Diff line change
Expand Up @@ -17,13 +17,15 @@ import net.kyori.adventure.webui.URL_API
import net.kyori.adventure.webui.URL_EDITOR
import net.kyori.adventure.webui.URL_EDITOR_INPUT
import net.kyori.adventure.webui.URL_EDITOR_OUTPUT
import net.kyori.adventure.webui.URL_IN_GAME_PREVIEW
import net.kyori.adventure.webui.URL_MINI_TO_HTML
import net.kyori.adventure.webui.URL_MINI_TO_JSON
import net.kyori.adventure.webui.URL_MINI_TO_TREE
import net.kyori.adventure.webui.editor.EditorInput
import net.kyori.adventure.webui.tryDecodeFromString
import net.kyori.adventure.webui.websocket.Call
import net.kyori.adventure.webui.websocket.Combined
import net.kyori.adventure.webui.websocket.InGamePreview
import net.kyori.adventure.webui.websocket.Packet
import net.kyori.adventure.webui.websocket.Placeholders
import net.kyori.adventure.webui.websocket.Response
Expand Down Expand Up @@ -323,6 +325,20 @@ public fun mainLoaded() {
}
)

var inGamePreviewKey = (1..8).map { "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789".random() }.joinToString("")
document.getElementById("in-game-preview-button")!!.addEventListener(
"click",
{
window.postPacket(
"$URL_API$URL_IN_GAME_PREVIEW",
InGamePreview(miniMessage = input.value, key = inGamePreviewKey)
)
.then { response -> response.text() }
.then { text -> window.navigator.clipboard.writeText(text) }
.then { bulmaToast.toast("Minecraft Server Hostname copied to clipboard!") }
}
)

// EDITOR

// BURGER MENU
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -26,12 +26,11 @@ import net.kyori.adventure.webui.Serializers
import net.kyori.adventure.webui.URL_API
import net.kyori.adventure.webui.URL_BUILD_INFO
import net.kyori.adventure.webui.URL_EDITOR
import net.kyori.adventure.webui.URL_IN_GAME_PREVIEW
import net.kyori.adventure.webui.URL_MINI_SHORTEN
import net.kyori.adventure.webui.URL_MINI_TO_HTML
import net.kyori.adventure.webui.URL_MINI_TO_JSON
import net.kyori.adventure.webui.URL_MINI_TO_TREE
import net.kyori.adventure.webui.URL_SETUP_KICK_PREVIEW
import net.kyori.adventure.webui.URL_SETUP_MOTD_PREVIEW
import net.kyori.adventure.webui.jvm.appendComponent
import net.kyori.adventure.webui.jvm.getConfigString
import net.kyori.adventure.webui.jvm.minimessage.editor.installEditor
Expand All @@ -49,6 +48,7 @@ import net.kyori.adventure.webui.jvm.minimessage.storage.BytebinStorage
import net.kyori.adventure.webui.tryDecodeFromString
import net.kyori.adventure.webui.websocket.Call
import net.kyori.adventure.webui.websocket.Combined
import net.kyori.adventure.webui.websocket.InGamePreview
import net.kyori.adventure.webui.websocket.Packet
import net.kyori.adventure.webui.websocket.ParseResult
import net.kyori.adventure.webui.websocket.Placeholders
Expand Down Expand Up @@ -205,16 +205,14 @@ public fun Application.miniMessage() {
}
}

post(URL_SETUP_MOTD_PREVIEW) {
val input = call.receiveText()
val hostname = previewManager.initializeMotdPreview(input)
call.respondText(hostname)
}

post(URL_SETUP_KICK_PREVIEW) {
val input = call.receiveText()
val hostname = previewManager.initializeKickPreview(input)
call.respondText(hostname)
post(URL_IN_GAME_PREVIEW) {
val request = Serializers.json.tryDecodeFromString<InGamePreview>(call.receiveText())
if (request != null && request.miniMessage != null && request.key != null) {
val hostname = previewManager.initializePreview(request.miniMessage, request.key)
call.respondText(hostname)
} else {
call.response.status(HttpStatusCode.BadRequest)
}
}

get(URL_BUILD_INFO) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -36,8 +36,7 @@ public class ServerStatusPreviewManager(
private val managerJob = SupervisorJob(application.coroutineContext.job)
override val coroutineContext: CoroutineContext = application.coroutineContext + managerJob

private val motdPreviews = Cache.Builder<String, String>().expireAfterAccess(1.hours).build()
private val kickPreviews = Cache.Builder<String, String>().expireAfterAccess(1.hours).build()
private val previews = Cache.Builder<String, String>().expireAfterAccess(1.hours).build()

init {
launch {
Expand Down Expand Up @@ -110,32 +109,18 @@ public class ServerStatusPreviewManager(
}

private fun lookupKickMessage(serverAddress: String): String {
return kickPreviews.get(serverAddress.split(".")[0]) ?: "<red>You cant join here!"
return previews.get(serverAddress.split(".")[0]) ?: "<red>You cant join here!"
}

private fun lookupMotd(serverAddress: String): String {
return motdPreviews.get(serverAddress.split(".")[0]) ?: "<rainbow>MiniMessage is cool!"
return previews.get(serverAddress.split(".")[0]) ?: "<rainbow>MiniMessage is cool!"
}

public fun initializeKickPreview(input: String): String {
val key = generateRandomString()
kickPreviews.put(key, input)
public fun initializePreview(input: String, key: String): String {
previews.put(key, input)
return "$key.webui.advntr.dev"
}

public fun initializeMotdPreview(input: String): String {
val key = generateRandomString()
motdPreviews.put(key, input)
return "$key.webui.advntr.dev"
}

private fun generateRandomString(length: Int = 8): String {
val allowedChars = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789"
return (1..length)
.map { allowedChars.random() }
.joinToString("")
}

private suspend fun ByteWriteChannel.writeMcPacket(packetId: Int, consumer: (packet: DataOutputStream) -> Unit) {
val stream = ByteArrayOutputStream()
val packet = DataOutputStream(stream)
Expand Down