Skip to content
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
4 changes: 4 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -10,3 +10,7 @@ catalog pin and are validated against that exact supported lobby catalog revisio
NPC bounce distance is an approximate travel distance in blocks. Use
`/scene npc <id> collision distance <blocks>` with a value from 0 through 20; the resulting travel
can vary with the runtime collision environment.

Scene-editor feedback uses the general system-message category because it describes editor
operations rather than an in-game story. Info, success, warning and error remain independent
levels that control visual emphasis without replacing the category label.
1 change: 1 addition & 0 deletions paper/build.gradle.kts
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@ repositories { maven("https://repo.papermc.io/repository/maven-public/") }

dependencies {
implementation(project(":common"))
implementation("gg.grounds:library-i18n:0.4.0")
compileOnly("de.eintosti:buildsystem-api:4.0.0")

testImplementation("org.mockbukkit.mockbukkit:mockbukkit-v26.1.2:4.115.0")
Expand Down
Original file line number Diff line number Diff line change
@@ -1,13 +1,24 @@
package gg.grounds.scene.editor.paper

import gg.grounds.i18n.Translations
import gg.grounds.scene.editor.paper.command.SceneCommandFeedback
import net.kyori.adventure.text.Component
import org.bukkit.command.CommandSender

class AdventureSceneFeedback : SceneCommandFeedback {
override fun info(sender: CommandSender, message: String) =
sender.sendMessage(Component.text(message))
private val messages =
Translations.forBundle("gg.grounds.scene.editor.messages", javaClass.classLoader)

override fun error(sender: CommandSender, message: String) =
sender.sendMessage(Component.text(message))
override fun send(
sender: CommandSender,
message: SceneMessage,
vararg args: Pair<String, Any>,
) {
val localizedArgs =
args
.map { (key, value) ->
key to if (value is SceneMessage) messages.render(value, sender) else value
}
.toTypedArray()
messages.send(sender, message, *localizedArgs)
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,6 @@ import gg.grounds.scene.editor.paper.preview.PaperPreviewAdapter
import gg.grounds.scene.editor.session.EditorSessionService
import gg.grounds.scene.editor.session.SessionCloseResult
import gg.grounds.scene.editor.session.SessionCloseSnapshot
import net.kyori.adventure.text.Component
import org.bukkit.Server
import org.bukkit.World
import org.bukkit.event.EventHandler
Expand All @@ -18,6 +17,7 @@ class PaperWorldLifecycleListener(
private val sessions: EditorSessionService,
private val previews: PaperPreviewAdapter,
private val beforeWorldClose: (World) -> Unit = {},
private val feedback: AdventureSceneFeedback = AdventureSceneFeedback(),
) : Listener {
@EventHandler(priority = EventPriority.MONITOR, ignoreCancelled = true)
fun onWorldUnload(event: WorldUnloadEvent) {
Expand All @@ -38,9 +38,7 @@ class PaperWorldLifecycleListener(
"Closing dirty scene editor session for world ${snapshot.worldId} at generation ${snapshot.generation}"
)
snapshot.editorPlayers.forEach { playerId ->
server
.getPlayer(playerId)
?.sendMessage(Component.text("Scene editor closed with unsaved changes."))
server.getPlayer(playerId)?.let { feedback.send(it, SceneMessage.DIRTY_CLOSE) }
}
}
}
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,86 @@
package gg.grounds.scene.editor.paper

import gg.grounds.i18n.SystemLevel
import gg.grounds.i18n.SystemMessageKey

enum class SceneMessage(
override val id: String,
override val level: SystemLevel,
) : SystemMessageKey {
IO_FAILURE("error.io-failure", SystemLevel.ERROR),
NO_ACTIONS("scene.no-actions", SystemLevel.INFO),
UNKNOWN_INCOMPLETE("command.unknown-incomplete", SystemLevel.ERROR),
NO_PERMISSION("command.no-permission", SystemLevel.ERROR),
CATALOG_STATUS("command.catalog-status", SystemLevel.INFO),
PLAYER_WORLD_REQUIRED("command.player-world-required", SystemLevel.ERROR),
BUILD_WORLD_REQUIRED("command.build-world-required", SystemLevel.ERROR),
HELP("command.help", SystemLevel.INFO),
UNKNOWN("command.unknown", SystemLevel.ERROR),
TOOL_UNAVAILABLE("tool.unavailable", SystemLevel.ERROR),
TOOL_NAME("tool.name", SystemLevel.INFO),
TOOL_ADDED("tool.added", SystemLevel.SUCCESS),
TOOL_DROPPED("tool.dropped", SystemLevel.WARNING),
NO_SOURCE("scene.no-source", SystemLevel.INFO),
CANONICAL_OPEN_FAILED("scene.canonical-open-failed", SystemLevel.ERROR),
INVALID_SOURCE("scene.invalid-source", SystemLevel.ERROR),
REJECTED_SOURCE("scene.rejected-source", SystemLevel.ERROR),
OPEN_FAILED("scene.open-failed", SystemLevel.ERROR),
OPENING("scene.opening", SystemLevel.INFO),
INVALID_SCENE_ID("scene.invalid-id", SystemLevel.ERROR),
WORLD_UNAVAILABLE("scene.world-unavailable", SystemLevel.ERROR),
CREATE_FAILED("scene.create-failed", SystemLevel.ERROR),
READY("scene.ready", SystemLevel.SUCCESS),
ALREADY_OPEN("scene.already-open", SystemLevel.ERROR),
CANONICAL_CREATE_FAILED("scene.canonical-create-failed", SystemLevel.ERROR),
MEMORY_CREATE_FAILED("scene.memory-create-failed", SystemLevel.ERROR),
NO_SCENE_CREATE("scene.none-create", SystemLevel.INFO),
INFO("scene.info", SystemLevel.INFO),
NO_SCENE("scene.none", SystemLevel.INFO),
VALIDATION_PASSED("scene.validation-passed", SystemLevel.SUCCESS),
VALIDATION_PROBLEM("scene.validation-problem", SystemLevel.ERROR),
SAVE_FAILED("scene.save-failed", SystemLevel.ERROR),
SAVED("scene.saved", SystemLevel.SUCCESS),
SAVING("scene.saving", SystemLevel.INFO),
HISTORY("history.status", SystemLevel.INFO),
POSITIVE_STEPS("history.positive-steps", SystemLevel.ERROR),
HISTORY_APPLIED("history.applied", SystemLevel.SUCCESS),
HISTORY_NONE("history.none", SystemLevel.INFO),
ELEMENT_PAGE("element.page", SystemLevel.INFO),
NO_ELEMENTS("element.none", SystemLevel.INFO),
SELECTED("element.selected", SystemLevel.SUCCESS),
LEASED_BY("element.leased-by", SystemLevel.ERROR),
ELEMENT_NOT_FOUND("element.not-found", SystemLevel.ERROR),
INVALID_VALUE("element.invalid-value", SystemLevel.ERROR),
MUTATION_APPLIED("element.mutation-applied", SystemLevel.SUCCESS),
EDIT_REJECTED("element.edit-rejected", SystemLevel.ERROR),
LEASE_RELEASE_FORBIDDEN("lease.release-forbidden", SystemLevel.ERROR),
LEASE_RELEASED("lease.released", SystemLevel.SUCCESS),
NO_ACTIVE_LEASE("lease.none", SystemLevel.INFO),
LEASE_STATUS("lease.status", SystemLevel.INFO),
LEASE_AVAILABLE("lease.available", SystemLevel.INFO),
ELEMENT_UNAVAILABLE("lease.element-unavailable", SystemLevel.ERROR),
LEASE_OVERRIDDEN("lease.overridden", SystemLevel.SUCCESS),
SAVE_IN_PROGRESS("reload.save-in-progress", SystemLevel.WARNING),
RELOAD_FAILED("reload.failed", SystemLevel.ERROR),
RELOADED("reload.done", SystemLevel.SUCCESS),
DISCARDED_RELOADED("reload.discarded", SystemLevel.SUCCESS),
DISCARD_CONFIRMATION("reload.confirmation", SystemLevel.WARNING),
STALE_RELOAD("reload.stale", SystemLevel.ERROR),
LOADING("reload.loading", SystemLevel.INFO),
EXPORT_FAILED("recovery.export-failed", SystemLevel.ERROR),
EXPORT_WRITTEN("recovery.export-written", SystemLevel.SUCCESS),
LITERAL_CONFIRMATION("recovery.literal-confirmation", SystemLevel.WARNING),
NO_INVALID_SOURCE("recovery.no-invalid-source", SystemLevel.ERROR),
RECOVERY_FAILED("recovery.failed", SystemLevel.ERROR),
RECOVERED("recovery.done", SystemLevel.SUCCESS),
RECOVERING("recovery.in-progress", SystemLevel.INFO),
MISSING_ELEMENT_ID("element.missing-id", SystemLevel.ERROR),
INVALID_ELEMENT_ID("element.invalid-id", SystemLevel.ERROR),
DIRTY_CLOSE("lifecycle.dirty-close", SystemLevel.WARNING),
USAGE_CREATE("usage.create", SystemLevel.WARNING),
USAGE_ELEMENT("usage.element", SystemLevel.WARNING),
USAGE_INVALID_ELEMENT("usage.invalid-element", SystemLevel.WARNING),
USAGE_LEASE("usage.lease", SystemLevel.WARNING),
USAGE_RECOVERY("usage.recovery", SystemLevel.WARNING),
USAGE_RECOVER_CREATE("usage.recover-create", SystemLevel.WARNING),
}
Loading