### Build and Test Commands for Bukkit Kotlin Serialization Source: https://github.com/typst-io/bukkit-kotlin-serialization/blob/master/CLAUDE.md Provides common Gradle commands for building, testing, and publishing the bukkit-kotlin-serialization project. Includes commands for building the shadow JAR, running all tests, specific test classes, or specific test methods. ```bash # Build the project (includes shadowJar) ./gradlew build # Run tests ./gradlew test # Run a single test class ./gradlew test --tests "io.typst.bukkit.kotlin.serialization.expression.EvaluatorTest" # Run a specific test method ./gradlew test --tests "io.typst.bukkit.kotlin.serialization.expression.EvaluatorTest.evaluate" # Build shadow JAR only ./gradlew shadowJar # Publish to Maven Central staging (requires credentials) ./gradlew publish ``` -------------------------------- ### Plugin Integration Utilities in Kotlin Source: https://github.com/typst-io/bukkit-kotlin-serialization/blob/master/CLAUDE.md Provides convenient extension properties and functions for Bukkit plugin developers to easily handle configuration files in JSON and YAML formats. Includes methods for reading and creating configuration files. ```kotlin import org.bukkit.plugin.java.JavaPlugin import java.io.File // Extension properties for config file paths val JavaPlugin.configJsonFile: File get() = File(dataFolder, "config.json") val JavaPlugin.configYamlFile: File get() = File(dataFolder, "config.yml") // Preconfigured serialization formats (assuming bukkitPluginJson and bukkitPluginYaml are defined elsewhere) // val bukkitPluginJson = ... // val bukkitPluginYaml = ... // Helper to read config or create with defaults inline fun JavaPlugin.readConfigOrCreate(file: File, default: T): T { if (!file.exists()) { // Use appropriate serializer (e.g., bukkitPluginJson or bukkitPluginYaml) // Example using JSON: // bukkitPluginJson.encodeToFile(this, file, default) // return default } // Use appropriate serializer to read the file // Example using JSON: // return bukkitPluginJson.decodeFromFile(this, file) return default // Placeholder } ``` -------------------------------- ### Mathematical Expression Evaluator Source: https://github.com/typst-io/bukkit-kotlin-serialization/blob/master/CLAUDE.md Evaluates the Abstract Syntax Tree (AST) generated by the parser. It supports variable substitution and calculates the result of the mathematical expression. ```kotlin import io.vavr.control.Either // Assuming Expression ADT (Literal, Variable, Unary, Binary) and Operator types are defined class Evaluator(private val variables: Map = emptyMap()) { fun evaluate(expression: Expression): Either { return try { Either.right(evaluateExpression(expression)) } catch (e: Exception) { Either.left(e.message ?: "Unknown evaluation error") } } private fun evaluateExpression(expr: Expression): Double = when (expr) { is Literal -> expr.value is Variable -> { variables[expr.name] ?: throw IllegalArgumentException("Undefined variable: ${expr.name}") } is Unary -> { val operandValue = evaluateExpression(expr.operand) when (expr.op) { UnaryOpType.PLUS -> operandValue UnaryOpType.MINUS -> -operandValue } } is Binary -> { val leftValue = evaluateExpression(expr.left) val rightValue = evaluateExpression(expr.right) when (expr.op) { BinaryOpType.ADD -> leftValue + rightValue BinaryOpType.SUBTRACT -> leftValue - rightValue BinaryOpType.MULTIPLY -> leftValue * rightValue BinaryOpType.DIVIDE -> { if (rightValue == 0.0) throw ArithmeticException("Division by zero") leftValue / rightValue } BinaryOpType.POWER -> kotlin.math.pow(leftValue, rightValue) } } } } ``` -------------------------------- ### Manual ConfigurationSerializable Handling with Kotlin Source: https://context7.com/typst-io/bukkit-kotlin-serialization/llms.txt Provides a method for manually serializing and deserializing Bukkit's `ConfigurationSerializable` objects using `BukkitConfigSerializableSerializer`. This is useful when working directly with the Map-based representation or when custom handling is required. The example shows converting an `ItemStack` to a Map and back. ```kotlin import io.typst.bukkit.kotlin.serialization.BukkitConfigSerializableSerializer import org.bukkit.inventory.ItemStack import org.bukkit.Material val itemStack = ItemStack(Material.DIAMOND_SWORD) // Convert to Map format val map: Map = BukkitConfigSerializableSerializer.serialize(itemStack) println(map) // Output: {==: ItemStack, type: DIAMOND_SWORD, amount: 1, ...} // Deserialize from Map val restored = BukkitConfigSerializableSerializer.deserializeObject(map) println(restored is ItemStack) // true ``` -------------------------------- ### Mathematical Expression Parser (Pratt Parser) Source: https://github.com/typst-io/bukkit-kotlin-serialization/blob/master/CLAUDE.md Implements a Pratt parser for constructing an Abstract Syntax Tree (AST) from a sequence of tokens. It handles operator precedence and associativity to correctly parse mathematical expressions. ```kotlin import io.vavr.control.Either // Assuming Expression ADT (Literal, Variable, Unary, Binary) and Operator types are defined // data class Literal(val value: Double) : Expression // data class Variable(val name: String) : Expression // data class Unary(val op: UnaryOpType, val operand: Expression) : Expression // data class Binary(val op: BinaryOpType, val left: Expression, val right: Expression) : Expression // enum class UnaryOpType { PLUS, MINUS } // enum class BinaryOpType { ADD, SUBTRACT, MULTIPLY, DIVIDE, POWER } class Parser(private val tokens: List) { private var currentTokenIndex = 0 fun parse(): Either { return try { val expression = parseExpression(0) if (currentToken().type != TokenType.EOF) { Either.left("Unexpected token at end: ${currentToken().value}") } else { Either.right(expression) } } catch (e: Exception) { Either.left(e.message ?: "Unknown parsing error") } } private fun parseExpression(precedence: Int): Expression { var left = parsePrimary() while (true) { val currentPrecedence = currentToken().getBinaryOperatorPrecedence() // Extension function on Token if (currentPrecedence == -1 || currentPrecedence < precedence) { break } val operator = currentToken().value advanceToken() val right = parseExpression(currentPrecedence + (if (currentToken().isLeftAssociative()) 0 else 1)) // Handle associativity left = Binary(BinaryOpType.valueOf(operator.uppercase()), left, right) // Simplified mapping } return left } private fun parsePrimary(): Expression { val token = currentToken() return when (token.type) { TokenType.NUMBER -> { advanceToken() Literal(token.value.toDouble()) } TokenType.IDENTIFIER -> { advanceToken() Variable(token.value) } TokenType.PARENTHESIS -> { if (token.value == "(") { advanceToken() val expr = parseExpression(0) if (currentToken().value != ")") { throw IllegalArgumentException("Expected ')' but found ${currentToken().value}") } advanceToken() expr } else { throw IllegalArgumentException("Unexpected closing parenthesis") } } else -> throw IllegalArgumentException("Unexpected token type: ${token.type}") } } private fun currentToken(): Token = tokens.getOrElse(currentTokenIndex) { tokens.last() } // Handle EOF private fun advanceToken() { currentTokenIndex++ } } // Dummy extension functions for illustration fun Token.getBinaryOperatorPrecedence(): Int = when(this.value) { "+", "-" -> 1 "*", "/" -> 2 "^" -> 3 else -> -1 } fun Token.isLeftAssociative(): Boolean = when(this.value) { "+", "-", "*", "/" -> true "^" -> false else -> true } ``` -------------------------------- ### Kotlin Range Serializers Source: https://github.com/typst-io/bukkit-kotlin-serialization/blob/master/CLAUDE.md Provides kotlinx.serialization serializers for Kotlin's IntRange and LongRange types. These allow for the serialization and deserialization of ranges to/from formats like JSON and YAML. ```kotlin import kotlinx.serialization.* import kotlinx.serialization.descriptors.* import kotlinx.serialization.encoding.* // Serializer for IntRange object IntRangeSerializer : KSerializer { override val descriptor: SerialDescriptor = buildClassSerialDescriptor("IntRange") { element("start", Long.serializer().descriptor) element("endInclusive", Long.serializer().descriptor) } override fun serialize(encoder: Encoder, value: IntRange) { encoder.encodeStructure(descriptor) { encodeLongElement(descriptor, 0, value.start.toLong()) encodeLongElement(descriptor, 1, value.endInclusive.toLong()) } } override fun deserialize(decoder: Decoder): IntRange { return decoder.decodeStructure(descriptor) { var start = 0 var endInclusive = 0 while (true) { when (val index = decodeElementIndex(descriptor)) { 0 -> start = decodeLongElement(descriptor, index).toInt() 1 -> endInclusive = decodeLongElement(descriptor, index).toInt() CompositeDecoder.DECODE_DONE -> break else -> throw SerializationException("Unknown element index: $index") } } start..endInclusive } } } // Serializer for LongRange (similar structure to IntRangeSerializer) object LongRangeSerializer : KSerializer { override val descriptor: SerialDescriptor = buildClassSerialDescriptor("LongRange") { element("start", Long.serializer().descriptor) element("endInclusive", Long.serializer().descriptor) } override fun serialize(encoder: Encoder, value: LongRange) { encoder.encodeStructure(descriptor) { encodeLongElement(descriptor, 0, value.start) encodeLongElement(descriptor, 1, value.endInclusive) } } override fun deserialize(decoder: Decoder): LongRange { return decoder.decodeStructure(descriptor) { var start = 0L var endInclusive = 0L while (true) { when (val index = decodeElementIndex(descriptor)) { 0 -> start = decodeLongElement(descriptor, index) 1 -> endInclusive = decodeLongElement(descriptor, index) CompositeDecoder.DECODE_DONE -> break else -> throw SerializationException("Unknown element index: $index") } } start..endInclusive } } } ``` -------------------------------- ### Mathematical Expression Lexer Source: https://github.com/typst-io/bukkit-kotlin-serialization/blob/master/CLAUDE.md The lexer component of the expression system responsible for tokenizing mathematical expressions. It breaks down input strings into a sequence of tokens representing numbers, operators, parentheses, and identifiers. ```kotlin import java.util.regex.Pattern // Enum for token types enum class TokenType { NUMBER, OPERATOR, PARENTHESIS, IDENTIFIER, EOF } // Data class for tokens data class Token(val type: TokenType, val value: String, val position: Int) class Lexer(private val input: String) { private var position = 0 fun tokenize(): List { val tokens = mutableListOf() while (position < input.length) { when { input[position].isWhitespace() -> position++ input[position].isDigit() -> tokens.add(readNumber()) input[position] == '(' || input[position] == ')' -> tokens.add(readParenthesis()) input[position].isLetter() -> tokens.add(readIdentifierOrOperator()) else -> throw IllegalArgumentException("Unexpected character at position $position: ${input[position]}") } } tokens.add(Token(TokenType.EOF, "", position)) return tokens } private fun readNumber(): Token { val start = position while (position < input.length && input[position].isDigit()) { position++ } return Token(TokenType.NUMBER, input.substring(start, position), start) } private fun readParenthesis(): Token { val char = input[position] position++ return Token(TokenType.PARENTHESIS, char.toString(), position - 1) } private fun readIdentifierOrOperator(): Token { val start = position while (position < input.length && (input[position].isLetterOrDigit())) { position++ } val value = input.substring(start, position) // Simplified: Check if it's a known operator or assume identifier return Token(TokenType.IDENTIFIER, value, start) } // ... potentially more robust operator handling ... } ``` -------------------------------- ### WorldLocation Serializable Wrapper Source: https://github.com/typst-io/bukkit-kotlin-serialization/blob/master/CLAUDE.md A serializable wrapper for Bukkit's Location object that includes the world name. This allows Location objects to be directly serialized and deserialized, preserving world context. ```kotlin import org.bukkit.Bukkit import org.bukkit.Location import kotlinx.serialization.* @Serializable data class WorldLocation( val worldName: String, val x: Double, val y: Double, val z: Double, val yaw: Float = 0f, val pitch: Float = 0f ) { fun toLocation(): Location { val world = Bukkit.getWorld(worldName) ?: throw IllegalStateException("World '$worldName' not found.") return Location(world, x, y, z, yaw, pitch) } companion object { fun fromLocation(location: Location): WorldLocation { return WorldLocation( worldName = location.world?.name ?: throw IllegalStateException("Location has no world."), x = location.x, y = location.y, z = location.z, yaw = location.yaw, pitch = location.pitch ) } } } ``` -------------------------------- ### BukkitConfigSerializableSerializer Core Logic Source: https://github.com/typst-io/bukkit-kotlin-serialization/blob/master/CLAUDE.md Demonstrates the core serializer for Bukkit's ConfigurationSerializable types, handling conversion between Bukkit's Map format and kotlinx.serialization formats (JSON and YAML). It recursively deserializes nested objects. ```kotlin class BukkitConfigSerializableSerializer : KSerializer { // ... implementation details ... override fun serialize(encoder: Encoder, value: T) { val map = ConfigurationSerialization.serialize(value) val outputKind = encoder.serializersModule.get(value::class) as? BukkitConfigSerializableSerializer<*> ?: BukkitConfigSerializableSerializer() val jsonEncoder = encoder as? JsonEncoder if (jsonEncoder != null) { val jsonMap = mapToJson(map) encoder.encodeSerializableValue(JsonElementSerializer, JsonObject(jsonMap)) } else { val yamlMap = mapToYaml(map) encoder.encodeSerializableValue(YamlElementSerializer, YamlDocument(yamlMap)) } } override fun deserialize(decoder: Decoder): T { val map: Map val jsonDecoder = decoder as? JsonDecoder if (jsonDecoder != null) { val jsonElement = jsonDecoder.decodeJsonElement() map = jsonToMap(jsonElement) } else { val yamlDocument = decoder.decodeSerializableValue(YamlDocument.serializer()) map = yamlToMap(yamlDocument) } val typeKey = map[ConfigurationSerialization.SERIALIZED_TYPE_KEY] as? String if (typeKey == null) { throw SerializationException("Missing $ConfigurationSerialization.SERIALIZED_TYPE_KEY in serialized data.") } val clazz = Bukkit.getUnsafeConfigurationSerializer().get(typeKey) ?: throw SerializationException("Unknown ConfigurationSerializable type: $typeKey") @Suppress("UNCHECKED_CAST") return deserializeObject(clazz, map) as T } private fun deserializeObject(clazz: Class<*>, map: Map): Any { val processedMap = map.entries.associate { (key, value) -> if (value is Map<*, *>) { key to deserializeObject(clazz, value as Map) } else { key to value } } return ConfigurationSerialization.deserialize(mapOf(ConfigurationSerialization.SERIALIZED_TYPE_KEY to clazz.name) + processedMap) } // Helper methods for JSON and YAML conversion (mapToJson, jsonToMap, mapToYaml, yamlToMap) omitted for brevity } ``` -------------------------------- ### Java Time Serializers for kotlinx.serialization Source: https://github.com/typst-io/bukkit-kotlin-serialization/blob/master/CLAUDE.md Provides serializers for various Java Time API classes including Duration, LocalDate, LocalDateTime, LocalTime, and Period. These enable seamless serialization and deserialization of time-based data. ```kotlin import kotlinx.serialization.* import kotlinx.serialization.descriptors.* import kotlinx.serialization.encoding.* import java.time.* // DurationSerializer object DurationSerializer : KSerializer { override val descriptor: SerialDescriptor = PrimitiveSerialDescriptor("Duration", PrimitiveKind.LONG) // Simplified for example override fun serialize(encoder: Encoder, value: Duration) { encoder.encodeLong(value.toMillis()) // Example: serialize as milliseconds } override fun deserialize(decoder: Decoder): Duration { val millis = decoder.decodeLong() return Duration.ofMillis(millis) } } // LocalDateSerializer (similar structure) object LocalDateSerializer : KSerializer { override val descriptor: SerialDescriptor = PrimitiveSerialDescriptor("LocalDate", PrimitiveKind.STRING) // Example: serialize as ISO string override fun serialize(encoder: Encoder, value: LocalDate) { encoder.encodeString(value.toString()) } override fun deserialize(decoder: Decoder): LocalDate { return LocalDate.parse(decoder.decodeString()) } } // LocalDateTimeSerializer (similar structure) object LocalDateTimeSerializer : KSerializer { override val descriptor: SerialDescriptor = PrimitiveSerialDescriptor("LocalDateTime", PrimitiveKind.STRING) override fun serialize(encoder: Encoder, value: LocalDateTime) { encoder.encodeString(value.toString()) } override fun deserialize(decoder: Decoder): LocalDateTime { return LocalDateTime.parse(decoder.decodeString()) } } // LocalTimeSerializer (similar structure) object LocalTimeSerializer : KSerializer { override val descriptor: SerialDescriptor = PrimitiveSerialDescriptor("LocalTime", PrimitiveKind.STRING) override fun serialize(encoder: Encoder, value: LocalTime) { encoder.encodeString(value.toString()) } override fun deserialize(decoder: Decoder): LocalTime { return LocalTime.parse(decoder.decodeString()) } } // PeriodSerializer (similar structure) object PeriodSerializer : KSerializer { override val descriptor: SerialDescriptor = buildClassSerialDescriptor("Period") { // Example: custom structure element("years", Int.serializer().descriptor) element("months", Int.serializer().descriptor) element("days", Int.serializer().descriptor) } override fun serialize(encoder: Encoder, value: Period) { encoder.encodeStructure(descriptor) { encodeIntElement(descriptor, 0, value.years) encodeIntElement(descriptor, 1, value.months) encodeIntElement(descriptor, 2, value.days) } } override fun deserialize(decoder: Decoder): Period { var years = 0 var months = 0 var days = 0 decoder.decodeStructure(descriptor).apply { while (true) { when (val index = decodeElementIndex(descriptor)) { 0 -> years = decodeIntElement(descriptor, index) 1 -> months = decodeIntElement(descriptor, index) 2 -> days = decodeIntElement(descriptor, index) CompositeDecoder.DECODE_DONE -> break else -> throw SerializationException("Unknown element index: $index") } } } return Period.of(years, months, days) } } ``` -------------------------------- ### Plugin Configuration Handling with Kotlin Source: https://context7.com/typst-io/bukkit-kotlin-serialization/llms.txt Illustrates automatic plugin configuration loading and creation using the library. It defines a serializable data class for the configuration and uses `readConfigOrCreate` to either load an existing JSON/YAML configuration file or create a new one with default values. This simplifies configuration management in Bukkit plugins. ```kotlin import io.typst.bukkit.kotlin.serialization.* import kotlinx.serialization.Serializable import org.bukkit.plugin.java.JavaPlugin @Serializable data class PluginConfig( val maxPlayers: Int = 100, val spawnRadius: Double = 50.0, val enablePvP: Boolean = true, val worlds: List = listOf("world", "world_nether", "world_the_end") ) class MyPlugin : JavaPlugin() { lateinit var config: PluginConfig override fun onEnable() { // Reads config.json or creates it with defaults config = readConfigOrCreate( defaultValue = { PluginConfig() }, jsonOrYaml = true // true for JSON, false for YAML ) logger.info("Max players: ${config.maxPlayers}") logger.info("Spawn radius: ${config.spawnRadius}") } } ``` -------------------------------- ### Lexer and Parser for Mathematical Expressions Source: https://context7.com/typst-io/bukkit-kotlin-serialization/llms.txt Provides a Lexer to tokenize mathematical expressions into a sequence of meaningful tokens and a Parser to transform these tokens into an Abstract Syntax Tree (AST). The AST can then be evaluated. This is useful for understanding the structure of expressions and for custom expression processing. ```kotlin import io.typst.bukkit.kotlin.serialization.expression.* // Tokenize expression val tokens = Lexer.lexAll("3 + 4 * (2 - 1)") if (tokens.isRight) { tokens.get().forEach { token -> println("${token.tokenType}: ${token.lexeme}") } // Output: // NUMBER: 3 // OPERATOR: + // NUMBER: 4 // OPERATOR: * // LEFT_PAREN: ( // NUMBER: 2 // OPERATOR: - // NUMBER: 1 // RIGHT_PAREN: ) // EOF: } // Parse to AST val ast = tokens.flatMap { Parser.parse(it) } if (ast.isRight) { println(ast.get()) // Output: Binary(PLUS, Literal(3.0), Binary(MULTIPLY, Literal(4.0), Binary(MINUS, Literal(2.0), Literal(1.0)))) } // Evaluate the parsed AST val result = ast.flatMap { it.evaluate(emptyMap()) } if (result.isRight) { println(result.get()) // 7.0 } ``` -------------------------------- ### Add Bukkit Kotlin Serialization Dependency (Gradle) Source: https://github.com/typst-io/bukkit-kotlin-serialization/blob/master/README.md This snippet shows how to add the bukkit-kotlin-serialization library to your Gradle project. It includes the necessary repository and dependency declarations for implementation. ```gradle repositories { mavenCentral() } dependencies { implementation('io.typst:bukkit-kotlin-serialization:3.2.0') } ``` -------------------------------- ### Build Expression AST Programmatically Source: https://context7.com/typst-io/bukkit-kotlin-serialization/llms.txt Allows for the programmatic construction of an Abstract Syntax Tree (AST) for mathematical expressions. This enables complex expression generation and manipulation before evaluation. The `evaluate` method on the `Expression` object handles the calculation based on the provided environment. ```kotlin import io.typst.bukkit.kotlin.serialization.expression.* // Build: (10 + x) * 2 val expr = Expression.Binary( op = BinaryOpType.MULTIPLY, left = Expression.Binary( op = BinaryOpType.PLUS, left = Expression.Literal(10.0), right = Expression.Variable("x") ), right = Expression.Literal(2.0) ) // Evaluate val result = expr.evaluate(mapOf("x" to 5.0)) if (result.isRight) { println(result.get()) // 30.0 ((10 + 5) * 2) } ``` -------------------------------- ### Serialize ConfigurationSerializable to YAML with Kotlin Source: https://context7.com/typst-io/bukkit-kotlin-serialization/llms.txt Shows how to serialize Bukkit's ConfigurationSerializable objects, specifically a Vector, to YAML format using the library. This is useful for managing plugin configurations in a human-readable format. The code includes serialization and deserialization of a custom data class. ```kotlin import io.typst.bukkit.kotlin.serialization.* import kotlinx.serialization.Serializable import kotlinx.serialization.encodeToString import org.bukkit.util.Vector @Serializable data class SpawnPoint( val name: String, val position: VectorSerializable, val enabled: Boolean = true ) val spawn = SpawnPoint( name = "MainSpawn", position = Vector(100.0, 64.0, 200.0) ) // Serialize to YAML val yaml = bukkitPluginYaml.encodeToString(spawn) println(yaml) // Output: // name: MainSpawn // position: 100.0,64.0,200.0 // enabled: true // Deserialize from YAML val restored: SpawnPoint = bukkitPluginYaml.decodeFromString(yaml) ``` -------------------------------- ### Serialize and Deserialize Bukkit Objects with Kotlin Serialization Source: https://github.com/typst-io/bukkit-kotlin-serialization/blob/master/README.md This Kotlin code demonstrates how to use the bukkit-kotlin-serialization library with kotlinx.serialization to serialize and deserialize Bukkit objects. It defines a serializable data class 'MyConfig' that includes an ItemStackSerializable field and shows how to read configuration from a JSON file on plugin enable and write it back on plugin disable. ```kotlin import io.typst.bukkit.kotlin.serialization.ItemStackSerializable import kotlinx.serialization.Serializable import kotlinx.serialization.decodeFromString import kotlinx.serialization.encodeToString import kotlinx.serialization.json.Json import org.bukkit.plugin.java.JavaPlugin import java.io.File @Serializable data class MyConfig( val name: String, // typealias ItemStackSerializable = @Serializable(ItemStackSerializer::class) ItemStack val item: ItemStackSerializable? ) class MyPlugin : JavaPlugin() { var myConfig: MyConfig = MyConfig("", null) val configJson: Json = Json { prettyPrint = true; encodeDefaults = true } override fun onEnable(): Unit { this.myConfig = configJson.decodeFromString(File(dataFolder, "config.json").readText()) // or Json.decodeFromString } override fun onDisable(): Unit { File(dataFolder, "config.json").writeText(configJson.encodeToString(this.myConfig)) // or Json.encodeToString } } ``` -------------------------------- ### Serialize WorldLocation to JSON with Kotlin Source: https://context7.com/typst-io/bukkit-kotlin-serialization/llms.txt Demonstrates serializing Bukkit's Location object, enhanced as `WorldLocation`, to JSON. The `WorldLocation` class provides methods to convert between Bukkit's `Location` and a serializable format. This snippet covers conversion, serialization, and deserialization back to a Bukkit `Location`. ```kotlin import io.typst.bukkit.kotlin.serialization.location.WorldLocation import kotlinx.serialization.Serializable import kotlinx.serialization.encodeToString import org.bukkit.Bukkit import org.bukkit.Location @Serializable data class Waypoint( val name: String, val location: WorldLocation, val description: String ) // Convert Bukkit Location to serializable WorldLocation val bukkitLoc = Location(Bukkit.getWorld("world"), 100.0, 64.0, 200.0, 90f, 0f) val worldLoc = WorldLocation.fromBukkit(bukkitLoc) val waypoint = Waypoint( name = "Castle", location = worldLoc, description = "Main castle entrance" ) // Serialize val json = bukkitPluginJson.encodeToString(waypoint) println(json) // Output: {"name":"Castle","location":{"world":"world","x":100.0,"y":64.0,"z":200.0,"yaw":90.0,"pitch":0.0},...} // Deserialize and convert back to Bukkit Location val restored: Waypoint = bukkitPluginJson.decodeFromString(json) val restoredLoc: Location = restored.location.toBukkitLocation() ``` -------------------------------- ### Complex Mathematical Expression Evaluation Source: https://context7.com/typst-io/bukkit-kotlin-serialization/llms.txt Demonstrates the evaluation of more complex mathematical expressions, including those involving nested parentheses, unary operators, and player-specific game mechanics like damage calculation with armor and defense. It highlights the flexibility of the `evaluate` function for real-world scenarios. ```kotlin import io.typst.bukkit.kotlin.serialization.expression.* // Player damage calculation with armor val damageFormula = "(baseDamage * critMultiplier - enemyDefense) * (1 - armorReduction)" val env = mapOf( "baseDamage" to 50.0, "critMultiplier" to 2.0, "enemyDefense" to 20.0, "armorReduction" to 0.3 ) val finalDamage = evaluate(damageFormula, env) if (finalDamage.isRight) { println("Final damage: ${finalDamage.get()}") // 56.0 } // Nested expressions with unary operators val complexExpr = "-(10 + -5) * 2" val result = evaluate(complexExpr, emptyMap()) if (result.isRight) { println(result.get()) // -10.0 } ``` -------------------------------- ### Serialize ItemStack to JSON with Kotlin Source: https://context7.com/typst-io/bukkit-kotlin-serialization/llms.txt Demonstrates serializing a Bukkit ItemStack to JSON using the library's custom serializer. It requires importing the necessary serialization and Bukkit classes. The output is a JSON string representing the ItemStack, which can be deserialized back into a data class. ```kotlin import io.typst.bukkit.kotlin.serialization.* import kotlinx.serialization.Serializable import kotlinx.serialization.encodeToString import org.bukkit.Material import org.bukkit.inventory.ItemStack @Serializable data class PlayerInventory( val helmet: ItemStackSerializable?, val chestplate: ItemStackSerializable?, val weapon: ItemStackSerializable ) // Create inventory with items val inventory = PlayerInventory( helmet = ItemStack(Material.DIAMOND_HELMET), chestplate = ItemStack(Material.DIAMOND_CHESTPLATE), weapon = ItemStack(Material.DIAMOND_SWORD) ) // Serialize to JSON val json = bukkitPluginJson.encodeToString(inventory) println(json) // Output: {"helmet":{"==":"ItemStack","type":"DIAMOND_HELMET",...},...} // Deserialize from JSON val restored: PlayerInventory = bukkitPluginJson.decodeFromString(json) ``` -------------------------------- ### Evaluate Mathematical Expressions with Variables Source: https://context7.com/typst-io/bukkit-kotlin-serialization/llms.txt Evaluates mathematical expressions, supporting basic arithmetic operations, operator precedence, and variables. It returns either a Double result on success or an error message (String) on failure, such as division by zero or unknown variables. This is useful for dynamic calculations within the plugin. ```kotlin import io.typst.bukkit.kotlin.serialization.expression.* import io.vavr.control.Either // Parse and evaluate simple expression val result1 = evaluate("2 + 3 * 4", emptyMap()) if (result1.isRight) { println(result1.get()) // 14.0 } // Evaluate with variables val variables = mapOf( "health" to 100.0, "damage" to 25.0, "defense" to 10.0 ) val result2 = evaluate("health - (damage - defense)", variables) if (result2.isRight) { println(result2.get()) // 85.0 (100 - (25 - 10)) } // Handle errors val result3 = evaluate("health / 0", mapOf("health" to 100.0)) if (result3.isLeft) { val failure = result3.left println(failure.message) // "Division by zero" } // Missing variable error val result4 = evaluate("x + y", mapOf("x" to 5.0)) if (result4.isLeft) { println(result4.left.message) // "Unknown variable: y in env: {x=5.0}" } ``` -------------------------------- ### Java Time Duration, Period, and LocalDateTime Serialization Source: https://context7.com/typst-io/bukkit-kotlin-serialization/llms.txt Enables serialization and deserialization of Java Time objects like Duration, Period, and LocalDate to and from JSON. It utilizes custom serializers (DurationAsString, LocalDateSerializer, PeriodSerializer) provided by the library. This is useful for scheduling events or managing cooldowns. ```kotlin import io.typst.bukkit.kotlin.serialization.time.* import kotlinx.serialization.Serializable import kotlinx.serialization.encodeToString import java.time.* @Serializable data class Event( val name: String, val startTime: DurationAsString, val date: @Serializable(LocalDateSerializer::class) LocalDate, val cooldown: @Serializable(PeriodSerializer::class) Period ) val event = Event( name = "Weekly Boss Fight", startTime = Duration.ofHours(2).plusMinutes(30), date = LocalDate.of(2025, 11, 28), cooldown = Period.ofDays(7) ) // Serialize val json = bukkitPluginJson.encodeToString(event) println(json) // Output: {"name":"Weekly Boss Fight","startTime":"PT2H30M","date":"2025-11-28","cooldown":"P7D"} // Deserialize val restored: Event = bukkitPluginJson.decodeFromString(json) println(restored.startTime.toMinutes()) // 150 ``` -------------------------------- ### Kotlin IntRange and LongRange Serialization Source: https://context7.com/typst-io/bukkit-kotlin-serialization/llms.txt Serializes Kotlin's IntRange and LongRange types to and from JSON string representations. This allows for easy persistence and transfer of range data. It depends on kotlinx.serialization and the custom IntRangeAsString serializer. ```kotlin import io.typst.bukkit.kotlin.serialization.ktstd.IntRangeAsString import kotlinx.serialization.Serializable import kotlinx.serialization.encodeToString @Serializable data class LevelRequirements( val allowedLevels: IntRangeAsString, val experienceRange: IntRangeAsString ) val requirements = LevelRequirements( allowedLevels = 10..50, experienceRange = 1000..5000 ) // Serialize to JSON val json = bukkitPluginJson.encodeToString(requirements) println(json) // Output: {"allowedLevels":"[10, 50]","experienceRange":"[1000, 5000]"} // Deserialize val restored: LevelRequirements = bukkitPluginJson.decodeFromString(json) println(restored.allowedLevels) // 10..50 ``` -------------------------------- ### Serialize Vector with Kotlin Serialization Source: https://context7.com/typst-io/bukkit-kotlin-serialization/llms.txt Serializes and deserializes Bukkit Vectors using Kotlinx.serialization. Requires `VectorSerializable` from the library. Vectors are stored as "x,y,z" strings in the serialized output. ```kotlin import io.typst.bukkit.kotlin.serialization.VectorSerializable import kotlinx.serialization.Serializable import kotlinx.serialization.encodeToString import org.bukkit.util.Vector @Serializable data class Projectile( val velocity: VectorSerializable, val startPosition: VectorSerializable, val damage: Double ) val projectile = Projectile( velocity = Vector(1.5, 0.5, 0.0), startPosition = Vector(100.0, 64.0, 200.0), damage = 10.0 ) // Serialize (vectors stored as "x,y,z" strings) val json = bukkitPluginJson.encodeToString(projectile) println(json) // Output: {"velocity":"1.5,0.5,0.0","startPosition":"100.0,64.0,200.0","damage":10.0} val restored: Projectile = bukkitPluginJson.decodeFromString(json) val restoredVelocity = restored.velocity println(restoredVelocity.length()) // Vector magnitude ``` -------------------------------- ### Serialize UUID with Kotlin Serialization Source: https://context7.com/typst-io/bukkit-kotlin-serialization/llms.txt Serializes and deserializes Minecraft UUIDs using Kotlinx.serialization. Requires `UUIDSerializable` from the library and `kotlinx.serialization`. Handles UUIDs as strings in JSON output. ```kotlin import io.typst.bukkit.kotlin.serialization.UUIDSerializable import kotlinx.serialization.Serializable import kotlinx.serialization.encodeToString import java.util.UUID @Serializable data class PlayerData( val playerId: UUIDSerializable, val username: String, val coins: Int ) val player = PlayerData( playerId = UUID.randomUUID(), username = "Steve", coins = 1000 ) val json = bukkitPluginJson.encodeToString(player) println(json) // Output: {"playerId":"a1b2c3d4-e5f6-7890-abcd-ef1234567890","username":"Steve","coins":1000} val restored: PlayerData = bukkitPluginJson.decodeFromString(json) ``` === COMPLETE CONTENT === This response contains all available snippets from this library. No additional content exists. Do not make further requests.