{siteConfig.tagline}
16 |= 28 | """((?:\\[{}]|\{}|[^{}])+)|\{([a-zA-Z_][a-zA-Z0-9_]*)+}""" 29 | .toRegex() 30 | .findAll(string) 31 | .map { match -> 32 | val commonStrMatch = match.groupValues[1] 33 | if (commonStrMatch.isNotEmpty()) { 34 | Quote(commonStrMatch, false) 35 | } else { 36 | Quote(match.groupValues[2], true, match.value) 37 | } 38 | } 39 | .toList() 40 | -------------------------------------------------------------------------------- /andesite-protocol/andesite-protocol-java/andesite-protocol-java-v756/src/commonMain/kotlin/PlayerPositionAndRotationPacket.kt: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2022 Gabrielle Guimarães de Oliveira 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | package andesite.protocol.java.v756 18 | 19 | import andesite.protocol.ProtocolPacket 20 | import andesite.protocol.java.JavaPacket 21 | import andesite.world.Location 22 | import kotlinx.serialization.SerialName 23 | import kotlinx.serialization.Serializable 24 | 25 | @Serializable 26 | @SerialName("PlayerPositionAndRotationPacket") 27 | @ProtocolPacket(0x12) 28 | public data class PlayerPositionAndRotationPacket( 29 | val x: Double, 30 | val feetY: Double, 31 | val z: Double, 32 | val yaw: Float, 33 | val onGround: Boolean, 34 | ) : JavaPacket, PositionMutatorPacket { 35 | override fun applyTo(location: Location): Location { 36 | return location.copy(x = x, y = feetY, z = z, yaw = yaw, pitch = 0.0f) 37 | } 38 | } 39 | -------------------------------------------------------------------------------- /andesite-protocol/andesite-protocol-java/andesite-protocol-java-v756/src/jvmMain/resources/v756/biomes/end_midlands.json: -------------------------------------------------------------------------------- 1 | { 2 | "scale": 0.2, 3 | "effects": { 4 | "mood_sound": { 5 | "sound": "minecraft:ambient.cave", 6 | "tick_delay": 6000, 7 | "block_search_extent": 8, 8 | "offset": 2.0 9 | }, 10 | "sky_color": 0, 11 | "fog_color": 10518688, 12 | "water_color": 4159204, 13 | "water_fog_color": 329011 14 | }, 15 | "surface_builder": { 16 | "config": { 17 | "top_material": { 18 | "Name": "minecraft:end_stone" 19 | }, 20 | "under_material": { 21 | "Name": "minecraft:end_stone" 22 | }, 23 | "underwater_material": { 24 | "Name": "minecraft:end_stone" 25 | } 26 | }, 27 | "type": "minecraft:default" 28 | }, 29 | "carvers": {}, 30 | "features": [], 31 | "starts": [ 32 | { 33 | "config": {}, 34 | "type": "minecraft:endcity" 35 | } 36 | ], 37 | "spawners": { 38 | "monster": [ 39 | { 40 | "type": "minecraft:enderman", 41 | "weight": 10, 42 | "minCount": 4, 43 | "maxCount": 4 44 | } 45 | ], 46 | "creature": [], 47 | "ambient": [], 48 | "underground_water_creature": [], 49 | "water_creature": [], 50 | "water_ambient": [], 51 | "misc": [] 52 | }, 53 | "spawn_costs": {}, 54 | "player_spawn_friendly": false, 55 | "precipitation": "none", 56 | "temperature": 0.5, 57 | "downfall": 0.5, 58 | "category": "the_end", 59 | "depth": 0.1 60 | } -------------------------------------------------------------------------------- /docs/docs/misc/chat.md: -------------------------------------------------------------------------------- 1 | --- 2 | sidebar_position: 1 3 | --- 4 | 5 | # Chat 6 | 7 | The [Chat](https://github.com/gabrielleeg1/andesite/blob/main/andesite-protocol/andesite-protocol-common/src/commonMain/kotlin/misc/Chat.kt) is a wrapper for the Minecraft text components. 8 | 9 | ## Simple chat 10 | 11 | You can instantiate a simple chat with the `Chat.of()` function: 12 | 13 | ```kotlin title="main.kt" 14 | Chat.of("&aI &bcan &cuse &dcolors!") 15 | ``` 16 | 17 | :::tip 18 | It is supported all bukkit color codes with the `&` prefix. You can look [here](https://wiki.vg/Chat#Colors) for the full list of color codes. 19 | ::: 20 | 21 | 22 | ## Placeholder chat 23 | 24 | You can use chat with placeholders to make the chat more customized like: 25 | 26 | ```kotlin title="main.kt" 27 | Chat.build("{player} joined the server") { 28 | val player by placeholder(player.username) { 29 | hoverEvent = ShowText("@${player.username}") 30 | 31 | hex("32a852") // you can use `yellow()` or `hex()` to set the color of the text. 32 | } 33 | } 34 | ``` 35 | 36 | :::tip 37 | You can set up click events too, the complete list of events are: 38 | 39 | - Hover 40 | * Show text 41 | 42 | - Click 43 | * Open url 44 | * Run command 45 | * Suggest command 46 | * Change page (of book) 47 | * Copy to clipboard 48 | ::: 49 | 50 | ## Mordant 51 | 52 | You can transform the `Chat` into text to print into a colored terminal using `.mordant()` function like: 53 | 54 | ```kotlin title="main.kt" 55 | println(Chat.of("&aI &bcan &cuse &dcolors!").mordant()) 56 | ``` 57 | -------------------------------------------------------------------------------- /andesite-world/andesite-world-common/src/commonMain/kotlin/block/Block.kt: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2021 Gabrielle Guimarães de Oliveira 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | package andesite.world.block 18 | 19 | import andesite.protocol.misc.Identifier 20 | import kotlinx.serialization.json.JsonObject 21 | import kotlinx.serialization.json.buildJsonObject 22 | import net.benwoodworth.knbt.NbtCompound 23 | import net.benwoodworth.knbt.NbtString 24 | import net.benwoodworth.knbt.buildNbtCompound 25 | 26 | public data class Block( 27 | val id: Identifier, 28 | val properties: JsonObject = buildJsonObject { }, 29 | ) { 30 | val isAir: Boolean get() = id.equals("minecraft:air") 31 | } 32 | 33 | public fun NbtCompound.toBlock(): Block { 34 | val id = get("Name") as NbtString? ?: NbtString("minecraft:air") 35 | val properties = get("Properties") as NbtCompound? ?: buildNbtCompound { } 36 | 37 | return Block(Identifier(id.value), properties.toJsonObject()) 38 | } 39 | -------------------------------------------------------------------------------- /andesite-shared/src/jvmMain/kotlin/ThreadLocalProperty.kt: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2022 Gabrielle Guimarães de Oliveira 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | package andesite.shared 18 | 19 | import kotlin.properties.ReadWriteProperty 20 | import kotlin.reflect.KProperty 21 | 22 | /** 23 | * Represents a value-initialized thread local property delegate. 24 | * 25 | * @param value the initial value of the property 26 | */ 27 | public actual class ThreadLocalProperty internal actual constructor(value: A) : 28 | ReadWriteProperty{ 29 | private val _value: ThreadLocal = ThreadLocal.withInitial { value } 30 | 31 | public actual var value: A 32 | get(): A = _value.get() 33 | set(value) = _value.set(value) 34 | 35 | override fun getValue(thisRef: Any?, property: KProperty<*>): A { 36 | return value 37 | } 38 | 39 | override fun setValue(thisRef: Any?, property: KProperty<*>, value: A) { 40 | this.value = value 41 | } 42 | } 43 | -------------------------------------------------------------------------------- /andesite-server/andesite-server-common/src/jvmMain/kotlin/server/broadcast.kt: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2022 Gabrielle Guimarães de Oliveira 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | package andesite.server 18 | 19 | import andesite.protocol.misc.Chat 20 | import andesite.protocol.misc.ChatBuilder 21 | import andesite.protocol.misc.mordant 22 | 23 | /** 24 | * Broadcasts the [chat] to all connected clients. 25 | * 26 | * @param chat the [Chat] component to broadcast 27 | */ 28 | public suspend fun MinecraftServer.broadcast(chat: Chat) { 29 | logger.info(chat.mordant()) 30 | 31 | players.forEach { player -> 32 | player.sendMessage(chat) 33 | } 34 | } 35 | 36 | /** 37 | * Broadcasts the [text] to all connected clients. 38 | * 39 | * @param text the base text 40 | * @param builder the builder function for the full-featured component 41 | */ 42 | public suspend fun MinecraftServer.broadcast(text: String, builder: ChatBuilder.() -> Unit = {}) { 43 | broadcast(Chat.build(text, builder)) 44 | } 45 | -------------------------------------------------------------------------------- /andesite-shared/src/commonMain/kotlin/AndesiteProperties.kt: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2022 Gabrielle Guimarães de Oliveira 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | package andesite.shared 18 | 19 | /** Andesite property delegates. */ 20 | public object AndesiteProperties { 21 | /** 22 | * Creates a new [NullableThreadLocalProperty]. 23 | * 24 | * @return a new [NullableThreadLocalProperty] 25 | */ 26 | public fun threadLocal(): NullableThreadLocalProperty = NullableThreadLocalProperty() 27 | 28 | /** 29 | * Creates a new [ThreadLocalProperty] with the given [value]. 30 | * 31 | * @param value the value to be set initially 32 | * @return a new [ThreadLocalProperty] 33 | */ 34 | public fun threadLocal(value: A): ThreadLocalProperty = ThreadLocalProperty(value) 35 | 36 | /** 37 | * Creates a new [BuilderProperty]. 38 | * 39 | * @return a new [BuilderProperty] 40 | */ 41 | public fun builder(): BuilderProperty = BuilderProperty() 42 | } 43 | -------------------------------------------------------------------------------- /settings.gradle.kts: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2021 Gabrielle Guimarães de Oliveira 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | rootProject.name = "andesite" 18 | 19 | enableFeaturePreview("TYPESAFE_PROJECT_ACCESSORS") 20 | 21 | include("andesite-shared") 22 | include("andesite-world:andesite-world-common") 23 | include("andesite-world:andesite-world-anvil") 24 | include("andesite-world:andesite-world-slime") 25 | include("andesite-protocol:andesite-protocol-common") 26 | include("andesite-protocol:andesite-protocol-java") 27 | include("andesite-protocol:andesite-protocol-java:andesite-protocol-java-v756") 28 | include("andesite-protocol:andesite-protocol-bedrock") 29 | include("andesite-protocol:andesite-protocol-bedrock:andesite-protocol-bedrock-v465") 30 | include("andesite-item:andesite-item-generator") 31 | include("andesite-item") 32 | include("andesite-komanda") 33 | include("andesite-server:andesite-server-common") 34 | include("andesite-server:andesite-server-bedrock") 35 | include("andesite-server:andesite-server-java") 36 | -------------------------------------------------------------------------------- /andesite-server/andesite-server-java/src/jvmMain/kotlin/game/handle_disconnect.kt: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2023 Gabrielle Guimarães de Oliveira 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | package andesite.java.game 18 | 19 | import andesite.java.player.Session 20 | import andesite.java.server.JavaMinecraftServer 21 | import andesite.player.JavaPlayer 22 | import andesite.player.PlayerQuitEvent 23 | import io.ktor.network.sockets.awaitClosed 24 | import io.ktor.utils.io.CancellationException 25 | import kotlinx.coroutines.CoroutineScope 26 | import kotlinx.coroutines.cancel 27 | import org.apache.logging.log4j.kotlin.logger 28 | 29 | private val logger = logger("andesite.java.game.Disconnect") 30 | 31 | internal suspend fun JavaMinecraftServer.handleDisconnect( 32 | scope: CoroutineScope, 33 | session: Session, 34 | player: JavaPlayer, 35 | ) { 36 | session.socket.awaitClosed() 37 | 38 | removePlayer(player) 39 | publish(PlayerQuitEvent(player)) 40 | 41 | scope.cancel(CancellationException("Player disconnected")) 42 | } 43 | -------------------------------------------------------------------------------- /andesite-server/andesite-server-java/src/jvmMain/kotlin/game/handle_chat.kt: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2022 Gabrielle Guimarães de Oliveira 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | package andesite.java.game 18 | 19 | import andesite.java.player.Session 20 | import andesite.java.server.JavaMinecraftServer 21 | import andesite.player.JavaPlayer 22 | import andesite.player.PlayerChatEvent 23 | import andesite.protocol.java.v756.ServerChatMessagePacket 24 | import andesite.protocol.misc.Chat 25 | import kotlinx.coroutines.flow.collect 26 | import kotlinx.coroutines.flow.filterIsInstance 27 | import kotlinx.coroutines.flow.onEach 28 | import org.apache.logging.log4j.kotlin.logger 29 | 30 | private val logger = logger("andesite.java.game.Chat") 31 | 32 | internal suspend fun JavaMinecraftServer.handleChat(session: Session, player: JavaPlayer) { 33 | session.inboundPacketFlow 34 | .filterIsInstance () 35 | .onEach { packet -> 36 | publish(PlayerChatEvent(Chat.of(packet.message), player)) 37 | } 38 | .collect() 39 | } 40 | -------------------------------------------------------------------------------- /andesite-komanda/src/commonMain/kotlin/ExecutionScope.kt: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2022 Gabrielle Guimarães de Oliveira 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | package andesite.komanda 18 | 19 | import andesite.protocol.misc.Chat 20 | import andesite.protocol.misc.ChatBuilder 21 | 22 | public interface ExecutionScope { 23 | public val arguments: Arguments 24 | public val sender: S 25 | 26 | public fun Parameter.value(): A { 27 | return arguments.get(name, type) 28 | } 29 | 30 | public fun Parameter.orDefault(orDefault: () -> A): A { 31 | return arguments.getOrNull(name, type) ?: orDefault() 32 | } 33 | 34 | public suspend fun sendMessage(chat: Chat) 35 | 36 | public suspend fun sendMessage(text: String, builder: ChatBuilder.() -> Unit = {}) { 37 | sendMessage(Chat.build(text, builder)) 38 | } 39 | 40 | public suspend fun failwith(chat: Chat) 41 | 42 | public suspend fun failwith(text: String, builder: ChatBuilder.() -> Unit = {}) { 43 | failwith(Chat.build(text, builder)) 44 | } 45 | } 46 | -------------------------------------------------------------------------------- /andesite-protocol/README.md: -------------------------------------------------------------------------------- 1 | ## andesite-protocol 2 | 3 | ### Installation 4 | 5 | You can use the gradle groovy with the following code: 6 | 7 | ```groovy 8 | repositories { 9 | mavenCentral() 10 | } 11 | 12 | dependencies { 13 | implementation 'me.gabrielleeg1:andesite-protocol-java-v756:{latest_version}' // Example for version v756 protocol 14 | implementation 'me.gabrielleeg1:andesite-protocol-java-v756-jvm:{latest_version}' 15 | } 16 | ``` 17 | 18 | Or either with kotlin gradle dsl: 19 | 20 | ```kt 21 | repositories { 22 | mavenCentral() 23 | } 24 | 25 | dependencies { 26 | implementation("me.gabrielleeg1:andesite-protocol-java-v756:{latest_version}") // Example for version v756 protocol 27 | implementation("me.gabrielleeg1:andesite-protocol-java-v756-jvm:{latest_version}") 28 | } 29 | ``` 30 | 31 | ### Samples 32 | 33 | Samples to use with andesite 34 | 35 | #### Java protocol 36 | 37 | This is a simple example of using `andesite:protocol`: 38 | 39 | - PS: The example is for [v756 protocol](https://wiki.vg/index.php?title=Protocol&oldid=16918) 40 | 41 | ```kt 42 | @ProtocolPacket(0x00) 43 | @Serializable 44 | data class HandshakePacket( 45 | val protocolVersion: VarInt, 46 | val serverAddress: String, 47 | val serverPort: UShort, 48 | val nextState: NextState, 49 | ) 50 | 51 | @ProtocolEnum 52 | @ProtocolVariant(Variant.VarInt) 53 | @Serializable 54 | enum class NextState { 55 | @ProtocolValue(1) 56 | Status, 57 | 58 | @ProtocolValue(2) 59 | Login; 60 | } 61 | 62 | val codec = MinecraftCodec.v756 { json = Json; nbt = SerializersModule { contextual(UuidSerializer) } } 63 | val packet = codec.decodeFromByteArray(bytes) 64 | 65 | println(packet) 66 | ``` 67 | -------------------------------------------------------------------------------- /andesite-protocol/andesite-protocol-java/andesite-protocol-java-v756/src/jvmMain/resources/v756/biomes/the_end.json: -------------------------------------------------------------------------------- 1 | { 2 | "scale": 0.2, 3 | "effects": { 4 | "mood_sound": { 5 | "sound": "minecraft:ambient.cave", 6 | "tick_delay": 6000, 7 | "block_search_extent": 8, 8 | "offset": 2.0 9 | }, 10 | "sky_color": 0, 11 | "fog_color": 10518688, 12 | "water_color": 4159204, 13 | "water_fog_color": 329011 14 | }, 15 | "surface_builder": { 16 | "config": { 17 | "top_material": { 18 | "Name": "minecraft:end_stone" 19 | }, 20 | "under_material": { 21 | "Name": "minecraft:end_stone" 22 | }, 23 | "underwater_material": { 24 | "Name": "minecraft:end_stone" 25 | } 26 | }, 27 | "type": "minecraft:default" 28 | }, 29 | "carvers": {}, 30 | "features": [ 31 | [], 32 | [], 33 | [], 34 | [], 35 | [ 36 | { 37 | "config": { 38 | "crystal_invulnerable": false, 39 | "spikes": [] 40 | }, 41 | "type": "minecraft:end_spike" 42 | } 43 | ] 44 | ], 45 | "starts": [], 46 | "spawners": { 47 | "monster": [ 48 | { 49 | "type": "minecraft:enderman", 50 | "weight": 10, 51 | "minCount": 4, 52 | "maxCount": 4 53 | } 54 | ], 55 | "creature": [], 56 | "ambient": [], 57 | "underground_water_creature": [], 58 | "water_creature": [], 59 | "water_ambient": [], 60 | "misc": [] 61 | }, 62 | "spawn_costs": {}, 63 | "player_spawn_friendly": false, 64 | "precipitation": "none", 65 | "temperature": 0.5, 66 | "downfall": 0.5, 67 | "category": "the_end", 68 | "depth": 0.1 69 | } -------------------------------------------------------------------------------- /andesite-server/andesite-server-java/src/jvmMain/kotlin/game/handle_move.kt: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2022 Gabrielle Guimarães de Oliveira 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | package andesite.java.game 18 | 19 | import andesite.java.player.Session 20 | import andesite.java.server.JavaMinecraftServer 21 | import andesite.player.JavaPlayer 22 | import andesite.player.PlayerMoveEvent 23 | import andesite.protocol.java.v756.PositionMutatorPacket 24 | import andesite.shared.AndesiteInternalAPI 25 | import kotlinx.coroutines.flow.collect 26 | import kotlinx.coroutines.flow.filterIsInstance 27 | import kotlinx.coroutines.flow.onEach 28 | 29 | @OptIn(AndesiteInternalAPI::class) 30 | internal suspend fun JavaMinecraftServer.handleMove(session: Session, player: JavaPlayer) { 31 | session.inboundPacketFlow 32 | .filterIsInstance () 33 | .onEach { packet -> 34 | val oldLocation = player.location 35 | val newLocation = packet.applyTo(oldLocation) 36 | player.location = newLocation 37 | 38 | publish(PlayerMoveEvent(oldLocation, newLocation, player)) 39 | } 40 | .collect() 41 | } 42 | -------------------------------------------------------------------------------- /andesite-protocol/andesite-protocol-common/src/commonMain/kotlin/math/vecs.kt: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2021 Gabrielle Guimarães de Oliveira 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | package andesite.protocol.math 18 | 19 | /** 20 | * Vector used for 3D math using integer coordinates. 21 | * 22 | * @property x X coordinate 23 | * @property y Y coordinate 24 | * @property z Z coordinate 25 | */ 26 | public data class Vector3i(val x: Int, val y: Int, val z: Int) 27 | 28 | /** 29 | * Vector used for 2D math using integer coordinates. 30 | * 31 | * @property x X coordinate 32 | * @property y Y coordinate 33 | */ 34 | public data class Vector2i(val x: Int, val y: Int) 35 | 36 | /** 37 | * Vector used for 3D math using float coordinates. 38 | * 39 | * @property x X coordinate 40 | * @property y Y coordinate 41 | * @property z Z coordinate 42 | */ 43 | public data class Vector3f(val x: Float, val y: Float, val z: Float) 44 | 45 | /** 46 | * Vector used for 2D math using float coordinates. 47 | * 48 | * @property x X coordinate 49 | * @property y Y coordinate 50 | */ 51 | public data class Vector2f(val x: Float, val y: Float) 52 | -------------------------------------------------------------------------------- /andesite-protocol/andesite-protocol-java/src/commonMain/kotlin/data/DimensionCodec.kt: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2022 Gabrielle Guimarães de Oliveira 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | package andesite.protocol.java.data 18 | 19 | import andesite.protocol.misc.Identifier 20 | import kotlinx.serialization.SerialName 21 | import kotlinx.serialization.Serializable 22 | 23 | @Serializable 24 | @SerialName("DimensionCodec") 25 | public data class DimensionCodec( 26 | @SerialName("minecraft:dimension_type") 27 | val dimension: Registry , 28 | 29 | @SerialName("minecraft:worldgen/biome") 30 | val worldgen: Registry , 31 | ) { 32 | init { 33 | require(dimension.kind == "minecraft:dimension_type") 34 | require(worldgen.kind == "minecraft:worldgen/biome") 35 | } 36 | } 37 | 38 | @Serializable 39 | @SerialName("Registry") 40 | public data class Registry ( 41 | @SerialName("type") val kind: String, 42 | val value: List >, 43 | ) { 44 | @Serializable 45 | @SerialName("Registry.Entry") 46 | public data class Entry (val name: Identifier, val id: Int, val element: T) 47 | } 48 | -------------------------------------------------------------------------------- /andesite-shared/src/commonMain/kotlin/BuilderProperty.kt: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2022 Gabrielle Guimarães de Oliveira 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | package andesite.shared 18 | 19 | import kotlin.properties.ReadWriteProperty 20 | import kotlin.reflect.KProperty 21 | 22 | /** Represents a property delegate to be used in builder classes. */ 23 | public class BuilderProperty : ReadWriteProperty { 24 | private var value: T? = null 25 | 26 | override fun getValue(thisRef: Any?, property: KProperty<*>): T { 27 | return value ?: throw BuilderInitializationException( 28 | message = "Property ${property.name} should be initialized before build.", 29 | ) 30 | } 31 | 32 | override fun setValue(thisRef: Any?, property: KProperty<*>, value: T) { 33 | this.value = value 34 | } 35 | } 36 | 37 | public class BuilderInitializationException(override val message: String) : RuntimeException() 38 | 39 | public fun R.runIfInitialized(property: () -> A, f: R.(A) -> Unit) { 40 | try { 41 | f(property()) 42 | } catch (_: BuilderInitializationException) { 43 | // nothing 44 | } 45 | } 46 | -------------------------------------------------------------------------------- /andesite-protocol/andesite-protocol-java/src/commonMain/kotlin/handshake/HandshakePacket.kt: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2021 Gabrielle Guimarães de Oliveira 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | package andesite.protocol.java.handshake 18 | 19 | import andesite.protocol.ProtocolEnum 20 | import andesite.protocol.ProtocolPacket 21 | import andesite.protocol.ProtocolValue 22 | import andesite.protocol.ProtocolVariant 23 | import andesite.protocol.Variant 24 | import andesite.protocol.java.JavaPacket 25 | import andesite.protocol.types.VarInt 26 | import kotlinx.serialization.SerialName 27 | import kotlinx.serialization.Serializable 28 | 29 | @Serializable 30 | @SerialName("HandshakePacket") 31 | @ProtocolPacket(0x00) 32 | public data class HandshakePacket( 33 | val protocolVersion: VarInt, 34 | val serverAddress: String, 35 | val serverPort: UShort, 36 | val nextState: NextState, 37 | ) : JavaPacket 38 | 39 | @Serializable 40 | @SerialName("NextState") 41 | @ProtocolEnum 42 | @ProtocolVariant(kind = Variant.VarInt) 43 | public enum class NextState { 44 | @ProtocolValue(1) 45 | Status, 46 | 47 | @ProtocolValue(2) 48 | Login, 49 | } 50 | -------------------------------------------------------------------------------- /andesite-server/andesite-server-java/src/jvmMain/kotlin/game/handle_keep_alive.kt: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2022 Gabrielle Guimarães de Oliveira 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | @file:OptIn(ExperimentalTime::class) 18 | 19 | package andesite.java.game 20 | 21 | import andesite.java.player.Session 22 | import andesite.java.player.sendPacket 23 | import andesite.protocol.currentTimeMillis 24 | import andesite.protocol.java.v756.KeepAlivePacket 25 | import kotlinx.coroutines.Dispatchers 26 | import kotlinx.coroutines.delay 27 | import kotlinx.coroutines.withContext 28 | import org.apache.logging.log4j.kotlin.logger 29 | import kotlin.time.Duration.Companion.milliseconds 30 | import kotlin.time.ExperimentalTime 31 | 32 | private val logger = logger("andesite.java.game.KeepAlive") 33 | 34 | internal suspend fun handleKeepAlive(session: Session) { 35 | while (true) { 36 | delay(500.milliseconds) 37 | 38 | try { 39 | session.sendPacket(KeepAlivePacket(currentTimeMillis())) 40 | } catch (error: Throwable) { 41 | withContext(Dispatchers.IO) { 42 | session.socket.close() 43 | } 44 | 45 | break 46 | } 47 | } 48 | } 49 | -------------------------------------------------------------------------------- /andesite-protocol/andesite-protocol-java/src/commonMain/kotlin/handshake/ResponsePacket.kt: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2021 Gabrielle Guimarães de Oliveira 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | package andesite.protocol.java.handshake 18 | 19 | import andesite.protocol.ProtocolJson 20 | import andesite.protocol.ProtocolPacket 21 | import andesite.protocol.java.JavaPacket 22 | import andesite.protocol.misc.Chat 23 | import kotlinx.serialization.SerialName 24 | import kotlinx.serialization.Serializable 25 | 26 | @Serializable 27 | public data class Response( 28 | val version: Version, 29 | val players: Players, 30 | val description: Chat, 31 | val favicon: String? = null, 32 | ) 33 | 34 | @Serializable 35 | public data class Version( 36 | val name: String, 37 | val protocol: Int, 38 | ) 39 | 40 | @Serializable 41 | public data class Players( 42 | val max: Int, 43 | val online: Int, 44 | val sample: List = emptyList(), 45 | ) 46 | 47 | @Serializable 48 | public data class Sample(val name: String, val id: String) 49 | 50 | @Serializable 51 | @SerialName("ResponsePacket") 52 | @ProtocolPacket(0x00) 53 | public data class ResponsePacket(@ProtocolJson val response: Response) : JavaPacket 54 | -------------------------------------------------------------------------------- /andesite-protocol/andesite-protocol-bedrock/src/commonMain/kotlin/PlayStatusPacket.kt: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2022 Gabrielle Guimarães de Oliveira 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | package andesite.protocol.bedrock 18 | 19 | import andesite.protocol.ProtocolEnum 20 | import andesite.protocol.ProtocolPacket 21 | import andesite.protocol.ProtocolValue 22 | import andesite.protocol.ProtocolVariant 23 | import andesite.protocol.Variant 24 | import kotlinx.serialization.SerialName 25 | import kotlinx.serialization.Serializable 26 | 27 | @Serializable 28 | @SerialName("PlayStatusPacket") 29 | @ProtocolPacket(0x02) 30 | public data class PlayStatusPacket(val status: PlayStatus) : BedrockPacket 31 | 32 | @Serializable 33 | @SerialName("PlayStatus") 34 | @ProtocolEnum 35 | @ProtocolVariant(Variant.Int) 36 | public enum class PlayStatus { 37 | @ProtocolValue(0) 38 | LoginSuccess, 39 | 40 | @ProtocolValue(1) 41 | FailedClient, 42 | 43 | @ProtocolValue(2) 44 | FailedServer, 45 | 46 | @ProtocolValue(3) 47 | PlayerSpawn, 48 | 49 | @ProtocolValue(4) 50 | FailedInvalidTenant, 51 | 52 | @ProtocolValue(5) 53 | FailedVanillaEdu, 54 | 55 | @ProtocolValue(6) 56 | FailedEduVanilla, 57 | 58 | @ProtocolValue(7) 59 | FailedServerFull, 60 | } 61 | -------------------------------------------------------------------------------- /andesite-protocol/andesite-protocol-java/andesite-protocol-java-v756/src/commonMain/kotlin/_codec.kt: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2022 Gabrielle Guimarães de Oliveira 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | package andesite.protocol.java.v756 18 | 19 | import andesite.protocol.serialization.CodecBuilder 20 | import andesite.protocol.serialization.DefaultProtocolConfiguration 21 | import andesite.protocol.serialization.MinecraftCodec 22 | import andesite.protocol.serialization.MinecraftCodec.Versions 23 | import andesite.protocol.serialization.ProtocolConfiguration 24 | 25 | public fun Versions.v756( 26 | from: ProtocolConfiguration = DefaultProtocolConfiguration, 27 | builder: CodecBuilder, 28 | ): MinecraftCodec { 29 | return MinecraftCodec(from) { 30 | protocolVersion = 756 31 | packetRegistry = createPacketRegistry { 32 | register () 33 | register () 34 | register () 35 | register () 36 | register () 37 | register () 38 | register () 39 | register () 40 | register () 41 | } 42 | 43 | builder() 44 | } 45 | } 46 | -------------------------------------------------------------------------------- /andesite-protocol/andesite-protocol-common/src/commonMain/kotlin/misc/Uuid.kt: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2022 Gabrielle Guimarães de Oliveira 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | package andesite.protocol.misc 18 | 19 | import kotlinx.serialization.KSerializer 20 | import kotlinx.serialization.Serializable 21 | import kotlinx.serialization.descriptors.SerialDescriptor 22 | import kotlinx.serialization.descriptors.buildClassSerialDescriptor 23 | import kotlinx.serialization.descriptors.element 24 | import kotlinx.serialization.encoding.Decoder 25 | import kotlinx.serialization.encoding.Encoder 26 | 27 | public typealias Uuid = @Serializable(UuidSerializer::class) com.benasher44.uuid.Uuid 28 | 29 | public object UuidSerializer : KSerializer { 30 | override val descriptor: SerialDescriptor = 31 | buildClassSerialDescriptor("Uuid") { 32 | element ("mostSignificantBits") 33 | element ("leastSignificantBits") 34 | } 35 | 36 | override fun serialize(encoder: Encoder, value: Uuid) { 37 | encoder.encodeLong(value.mostSignificantBits) 38 | encoder.encodeLong(value.leastSignificantBits) 39 | } 40 | 41 | override fun deserialize(decoder: Decoder): Uuid { 42 | return Uuid(decoder.decodeLong(), decoder.decodeLong()) 43 | } 44 | } 45 | -------------------------------------------------------------------------------- /.github/ISSUE_TEMPLATE/bug_report.yml: -------------------------------------------------------------------------------- 1 | name: 🐞 Bug report 2 | description: Something isn't working 3 | title: "[BUG] " 4 | labels: [ "type: bug" ] 5 | body: 6 | - type: dropdown 7 | attributes: 8 | label: Is there an existing issue for this? 9 | description: Please search to see if an issue already exists for the bug you encountered. 10 | options: 11 | - 'Yes' 12 | - 'No' 13 | - type: textarea 14 | attributes: 15 | label: 🐛 Describe the bug 16 | description: A concise description of what you're experiencing. 17 | validations: 18 | required: false 19 | - type: textarea 20 | attributes: 21 | label: ✔️ Expected behavior 22 | description: What's you expected to happen. 23 | validations: 24 | required: false 25 | - type: textarea 26 | attributes: 27 | label: 👣 Steps to Reproduce 28 | description: Steps to reproduce the bug. 29 | placeholder: | 30 | 1. In this environment... 31 | 2. With this config... 32 | 3. Run '...' 33 | 4. See error... 34 | validations: 35 | required: false 36 | - type: input 37 | attributes: 38 | label: 💻 Platform 39 | description: On which platform did the bug occur? 40 | placeholder: "e.g. All, Linux" 41 | - type: input 42 | id: environment 43 | attributes: 44 | label: ⭐ Environment 45 | description: Which is your Andesite version. 46 | placeholder: "e.g. 1.0-SNAPSHOT" 47 | validations: 48 | required: true 49 | - type: textarea 50 | attributes: 51 | label: ✍️ Additional context 52 | description: | 53 | Links? References? Anything that will give us more context about the issue you are encountering! 54 | Tip: You can attach images or log files by clicking this area to highlight it and then dragging files in. 55 | validations: 56 | required: false 57 | -------------------------------------------------------------------------------- /andesite-protocol/andesite-protocol-java/andesite-protocol-java-v756/src/commonMain/kotlin/ChatMessagePacket.kt: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2022 Gabrielle Guimarães de Oliveira 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | package andesite.protocol.java.v756 18 | 19 | import andesite.protocol.ProtocolEnum 20 | import andesite.protocol.ProtocolJson 21 | import andesite.protocol.ProtocolPacket 22 | import andesite.protocol.ProtocolValue 23 | import andesite.protocol.ProtocolVariant 24 | import andesite.protocol.Variant 25 | import andesite.protocol.java.JavaPacket 26 | import andesite.protocol.misc.Chat 27 | import andesite.protocol.misc.Uuid 28 | import kotlinx.serialization.Contextual 29 | import kotlinx.serialization.SerialName 30 | import kotlinx.serialization.Serializable 31 | 32 | @Serializable 33 | @SerialName("ChatMessagePacket") 34 | @ProtocolPacket(0x0F) 35 | public data class ChatMessagePacket( 36 | @ProtocolJson 37 | val data: Chat, 38 | val position: ChatPosition, 39 | @Contextual 40 | val sender: Uuid, 41 | ) : JavaPacket 42 | 43 | @Serializable 44 | @ProtocolEnum 45 | @SerialName("ChatPosition") 46 | @ProtocolVariant(Variant.Byte) 47 | public enum class ChatPosition { 48 | @ProtocolValue(0) 49 | Chat, 50 | 51 | @ProtocolValue(1) 52 | SystemMessage, 53 | 54 | @ProtocolValue(2) 55 | ActionBar, 56 | } 57 | -------------------------------------------------------------------------------- /andesite-komanda/src/commonMain/kotlin/FallbackBuilder.kt: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2022 Gabrielle Guimarães de Oliveira 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | package andesite.komanda 18 | 19 | import andesite.komanda.parsing.PathNode 20 | import andesite.komanda.parsing.PatternExpr 21 | import kotlin.reflect.KClass 22 | 23 | public class FallbackBuilder(private val name: String) { 24 | private val exceptionHandlers: MutableSet = mutableSetOf() 25 | private val executionHandlers: MutableMap , Execution<*>> = mutableMapOf() 26 | 27 | public fun onFailure(handler: ExceptionHandler) { 28 | exceptionHandlers += handler 29 | } 30 | 31 | public inline fun onExecution(noinline handler: Execution ) { 32 | onExecution(S::class, handler) 33 | } 34 | 35 | public fun onAnyExecution(handler: Execution) { 36 | onExecution(Any::class, handler) 37 | } 38 | 39 | public fun onExecution(type: KClass, handler: Execution) { 40 | @Suppress("UNCHECKED_CAST") 41 | executionHandlers[type] = handler as Execution<*> 42 | } 43 | 44 | public fun build(): Pattern { 45 | return Pattern( 46 | expr = PatternExpr(PathNode(name)), 47 | parameters = emptyMap(), 48 | exceptionHandlers, 49 | executionHandlers, 50 | ) 51 | } 52 | } 53 | -------------------------------------------------------------------------------- /andesite-server/andesite-server-common/src/jvmMain/kotlin/command/MinecraftKomandaRoot.kt: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2022 Gabrielle Guimarães de Oliveira 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | package andesite.command 18 | 19 | import andesite.komanda.AbstractKomandaRoot 20 | import andesite.komanda.Arguments 21 | import andesite.komanda.ExecutionScope 22 | import andesite.player.MinecraftPlayer 23 | import andesite.protocol.misc.Chat 24 | import andesite.server.Messageable 25 | 26 | public class MinecraftKomandaRoot : AbstractKomandaRoot( 27 | { 28 | alias ("int") 29 | alias ("double") 30 | alias ("float") 31 | alias ("byte") 32 | alias ("short") 33 | 34 | onFailure { failure -> 35 | when (failure.cause) { 36 | null -> sendMessage(failure.chat) 37 | else -> sendMessage( 38 | "&cAn internal error occurred," + 39 | " please contact the server administration", 40 | ) 41 | } 42 | } 43 | 44 | acceptTargets { 45 | put(MinecraftPlayer::class, Chat.of("&cThe executor must be a player")) 46 | } 47 | }, 48 | ) { 49 | override fun createExecutionScope( 50 | sender: Messageable, 51 | arguments: Arguments, 52 | ): ExecutionScope { 53 | return MinecraftExecutionScope(arguments, sender) 54 | } 55 | } 56 | -------------------------------------------------------------------------------- /andesite-server/andesite-server-common/src/jvmMain/kotlin/player/MinecraftPlayer.kt: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2021 Gabrielle Guimarães de Oliveira 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | package andesite.player 18 | 19 | import andesite.event.EventHolder 20 | import andesite.protocol.java.JavaPacket 21 | import andesite.protocol.misc.Uuid 22 | import andesite.server.Messageable 23 | import andesite.shared.AndesiteInternalAPI 24 | import andesite.world.Location 25 | import kotlinx.serialization.SerializationStrategy 26 | import kotlinx.serialization.serializer 27 | import org.apache.logging.log4j.kotlin.Logging 28 | 29 | /** Represents a generic Minecraft player. */ 30 | public sealed interface MinecraftPlayer : EventHolder , Logging, Messageable { 31 | public val id: Uuid 32 | public val protocol: Int 33 | public val username: String 34 | public var location: Location 35 | @AndesiteInternalAPI set 36 | } 37 | 38 | /** Represents a Java Edition Minecraft player. */ 39 | public interface JavaPlayer : MinecraftPlayer { 40 | public suspend fun sendPacket(serializer: SerializationStrategy, packet: A) 41 | } 42 | 43 | public suspend inline fun JavaPlayer.sendPacket(packet: A) { 44 | sendPacket(serializer(), packet) 45 | } 46 | 47 | /** Represents a Bedrock Edition Minecraft player. */ 48 | public interface BedrockPlayer : MinecraftPlayer 49 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # andesite 2 | 3 |  4 |  5 |  6 |  7 | 8 | Simple library for building [Minecraft Protocol](https://wiki.vg/Main_Page) for Minecraft Java Edition and Bedrock 9 | Edition. 10 | 11 | ### User guide 12 | 13 | The full documentation is [here](https://andesite.devgabi.me) 14 | 15 | ### Protocol versions 16 | 17 | The following versions of Minecraft are supported: 18 | 19 | - [Java](andesite-protocol/andesite-protocol-java) 20 | - [v756](andesite-protocol/andesite-protocol-java/andesite-protocol-java-v756) 21 | 22 | - [Bedrock](andesite-protocol/andesite-protocol-bedrock) 23 | - [v465](andesite-protocol/andesite-protocol-bedrock/andesite-protocol-bedrock-v465) (TODO) 24 | 25 | ### World versions 26 | 27 | The following versions of Minecraft world format are supported: 28 | 29 | - [Anvil](andesite-world/andesite-world-anvil) 30 | - [Slime](andesite-world/andesite-world-slime) 31 | 32 | ### Licensing 33 | 34 | This project is using the [Apache 2 License](LICENSE). 35 | 36 | ``` 37 | Copyright 2022 Gabrielle Guimarães de Oliveira 38 | 39 | Licensed under the Apache License, Version 2.0 (the "License"); 40 | you may not use this file except in compliance with the License. 41 | You may obtain a copy of the License at 42 | 43 | http://www.apache.org/licenses/LICENSE-2.0 44 | 45 | Unless required by applicable law or agreed to in writing, software 46 | distributed under the License is distributed on an "AS IS" BASIS, 47 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 48 | See the License for the specific language governing permissions and 49 | limitations under the License. 50 | ``` 51 | -------------------------------------------------------------------------------- /andesite-protocol/andesite-protocol-common/src/commonMain/kotlin/serialization/decoder.kt: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2022 Gabrielle Guimarães de Oliveira 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | package andesite.protocol.serialization 18 | 19 | import kotlinx.serialization.builtins.ByteArraySerializer 20 | import kotlinx.serialization.builtins.DoubleArraySerializer 21 | import kotlinx.serialization.builtins.FloatArraySerializer 22 | import kotlinx.serialization.builtins.IntArraySerializer 23 | import kotlinx.serialization.builtins.ListSerializer 24 | import kotlinx.serialization.builtins.LongArraySerializer 25 | import kotlinx.serialization.serializer 26 | 27 | public fun ProtocolDecoder.decodeLongArray(): LongArray { 28 | return decodeSerializableValue(LongArraySerializer()) 29 | } 30 | 31 | public fun ProtocolDecoder.decodeIntArray(): IntArray { 32 | return decodeSerializableValue(IntArraySerializer()) 33 | } 34 | 35 | public fun ProtocolDecoder.decodeFloatArray(): FloatArray { 36 | return decodeSerializableValue(FloatArraySerializer()) 37 | } 38 | 39 | public fun ProtocolDecoder.decodeDoubleArray(): DoubleArray { 40 | return decodeSerializableValue(DoubleArraySerializer()) 41 | } 42 | 43 | public fun ProtocolDecoder.decodeByteArray(): ByteArray { 44 | return decodeSerializableValue(ByteArraySerializer()) 45 | } 46 | 47 | public inline fun ProtocolDecoder.decodeList(): List { 48 | return decodeSerializableValue(ListSerializer(serializer())) 49 | } 50 | -------------------------------------------------------------------------------- /andesite-protocol/andesite-protocol-common/src/commonMain/kotlin/serialization/encoder.kt: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2022 Gabrielle Guimarães de Oliveira 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | package andesite.protocol.serialization 18 | 19 | import kotlinx.serialization.builtins.ByteArraySerializer 20 | import kotlinx.serialization.builtins.DoubleArraySerializer 21 | import kotlinx.serialization.builtins.FloatArraySerializer 22 | import kotlinx.serialization.builtins.IntArraySerializer 23 | import kotlinx.serialization.builtins.ListSerializer 24 | import kotlinx.serialization.builtins.LongArraySerializer 25 | import kotlinx.serialization.serializer 26 | 27 | public fun ProtocolEncoder.encodeLongArray(array: LongArray) { 28 | encodeSerializableValue(LongArraySerializer(), array) 29 | } 30 | 31 | public fun ProtocolEncoder.encodeIntArray(array: IntArray) { 32 | encodeSerializableValue(IntArraySerializer(), array) 33 | } 34 | 35 | public fun ProtocolEncoder.encodeFloatArray(array: FloatArray) { 36 | encodeSerializableValue(FloatArraySerializer(), array) 37 | } 38 | 39 | public fun ProtocolEncoder.encodeDoubleArray(array: DoubleArray) { 40 | encodeSerializableValue(DoubleArraySerializer(), array) 41 | } 42 | 43 | public fun ProtocolEncoder.encodeByteArray(array: ByteArray) { 44 | encodeSerializableValue(ByteArraySerializer(), array) 45 | } 46 | 47 | public inline fun ProtocolEncoder.encodeList(list: List ) { 48 | encodeSerializableValue(ListSerializer(serializer()), list) 49 | } 50 | -------------------------------------------------------------------------------- /andesite-protocol/andesite-protocol-common/src/commonMain/kotlin/misc/mordant.kt: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2022 Gabrielle Guimarães de Oliveira 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | package andesite.protocol.misc 18 | 19 | import com.github.ajalt.mordant.rendering.TextStyle 20 | 21 | /** 22 | * Converts a [Chat] component into a [String] that have color information using Mordant. 23 | * 24 | * @receiver the [Chat] component to be converted 25 | * @return the [String] with color information 26 | */ 27 | public fun Chat.mordant(): String { 28 | return flatten().joinToString("") { chat -> 29 | val text = when (chat.obfuscated) { 30 | true -> chat.text.map { ' ' }.toCharArray().concatToString() 31 | false -> chat.text 32 | } 33 | 34 | val style = TextStyle( 35 | color = when (val color = chat.color) { 36 | Color.White -> null 37 | else -> color.style.color 38 | }, 39 | bold = chat.bold, 40 | italic = chat.italic, 41 | underline = chat.underlined, 42 | strikethrough = chat.strikethrough, 43 | ) 44 | 45 | style(text) 46 | } 47 | } 48 | 49 | /** 50 | * Converts a [Chat] component with many [Chat.extra] children into a [List] of [Chat]. 51 | * 52 | * @receiver the [Chat] component to be converted 53 | * @return the [List] of [Chat] 54 | */ 55 | public fun Chat.flatten(): List { 56 | if (extra.isNullOrEmpty()) return listOf(this) 57 | 58 | return extra.fold(listOf(this)) { a, b -> 59 | a + b.flatten() 60 | } 61 | } 62 | -------------------------------------------------------------------------------- /andesite-protocol/andesite-protocol-java/src/commonMain/kotlin/data/Dimension.kt: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2022 Gabrielle Guimarães de Oliveira 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | package andesite.protocol.java.data 18 | 19 | import andesite.protocol.misc.Identifier 20 | import kotlinx.serialization.SerialName 21 | import kotlinx.serialization.Serializable 22 | 23 | @Serializable 24 | @SerialName("Dimension") 25 | public data class Dimension( 26 | val effects: Identifier, 27 | val infiniburn: Identifier, 28 | val natural: Boolean, 29 | 30 | @SerialName("piglin_safe") 31 | val piglinSafe: Boolean, 32 | 33 | @SerialName("ambient_light") 34 | val ambientLight: Float, 35 | 36 | @SerialName("fixed_time") 37 | val fixedTime: Long? = null, 38 | 39 | @SerialName("respawn_anchor_works") 40 | val respawnAnchorWorks: Boolean, 41 | 42 | @SerialName("has_skylight") 43 | val hasSkylight: Boolean, 44 | 45 | @SerialName("has_raids") 46 | val hasRaids: Boolean, 47 | 48 | @SerialName("has_ceiling") 49 | val hasCeiling: Boolean, 50 | 51 | @SerialName("bed_works") 52 | val bedWorks: Boolean, 53 | 54 | @SerialName("min_y") 55 | val minY: Int, 56 | 57 | @SerialName("height") 58 | val height: Int, 59 | 60 | @SerialName("logical_height") 61 | val logicalHeight: Short, 62 | 63 | @SerialName("coordinate_scale") 64 | val coordinateScale: Float, 65 | 66 | @SerialName("ultrawarm") 67 | val ultrawarm: Boolean, 68 | ) { 69 | init { 70 | require(ambientLight in 0f..1f) { "ambientLight must be between 0 and 1" } 71 | } 72 | } 73 | -------------------------------------------------------------------------------- /andesite-server/andesite-server-common/src/jvmMain/kotlin/event/EventHolder.kt: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2022 Gabrielle Guimarães de Oliveira 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | package andesite.event 18 | 19 | import kotlinx.coroutines.CoroutineName 20 | import kotlinx.coroutines.CoroutineScope 21 | import kotlinx.coroutines.flow.Flow 22 | import kotlinx.coroutines.flow.collect 23 | import kotlinx.coroutines.flow.filterIsInstance 24 | import kotlinx.coroutines.flow.onEach 25 | import kotlinx.coroutines.launch 26 | import kotlin.coroutines.CoroutineContext 27 | import kotlin.coroutines.EmptyCoroutineContext 28 | 29 | /** Holds an event bus that can be used to listen [E] events. */ 30 | public interface EventHolder : CoroutineScope { 31 | /** 32 | * The event bus for [E]. 33 | * 34 | * @return the event bus for [E] 35 | */ 36 | public fun eventFlow(): Flow 37 | } 38 | 39 | /** 40 | * Listen events on a [EventHolder]. 41 | * 42 | * @param E the type of the [MinecraftEvent] to listen for. 43 | * @param context the [CoroutineContext] to use for the coroutine. 44 | * @param handle the function to execute when an event of type [E] is received. 45 | */ 46 | public inline fun EventHolder .on( 47 | context: CoroutineContext = EmptyCoroutineContext, 48 | noinline handle: suspend E.() -> Unit, 49 | ) { 50 | launch(context + CoroutineName("listen/${E::class.simpleName}")) { 51 | eventFlow() 52 | .filterIsInstance () 53 | .onEach { handle(it) } 54 | .collect() 55 | } 56 | } 57 | -------------------------------------------------------------------------------- /andesite-server/andesite-server-java/src/jvmMain/kotlin/game/handle_chunks.kt: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2022 Gabrielle Guimarães de Oliveira 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | package andesite.java.game 18 | 19 | import andesite.event.on 20 | import andesite.java.convertChunk 21 | import andesite.java.player.Session 22 | import andesite.java.player.sendPacket 23 | import andesite.java.server.JavaMinecraftServer 24 | import andesite.player.JavaPlayer 25 | import andesite.player.PlayerMoveEvent 26 | import andesite.protocol.java.v756.PlayerPositionAndLookPacket 27 | import andesite.protocol.types.VarInt 28 | import org.apache.logging.log4j.kotlin.logger 29 | 30 | private val logger = logger("andesite.java.game.Chunk") 31 | 32 | internal suspend fun JavaMinecraftServer.handleChunks(session: Session, player: JavaPlayer) { 33 | // Load new chunks 34 | player.on { 35 | val chunk = player.location.world.getChunkAt( 36 | player.location.x.toInt(), 37 | player.location.z.toInt(), 38 | ) 39 | if (chunk != null) { 40 | session.sendPacket(convertChunk(chunk)) 41 | } 42 | 43 | if (newLocation.y < 0) { 44 | session.sendPacket( 45 | PlayerPositionAndLookPacket( 46 | x = 0.0, 47 | y = 50.0, // TODO: Implement better solution from falling in the void 48 | z = 0.0, 49 | yaw = 0f, 50 | pitch = 0f, 51 | flags = 0x1D, // Only Y position isn't relative 52 | teleportId = VarInt(0), 53 | dismountVehicle = false, 54 | ), 55 | ) 56 | } 57 | } 58 | } 59 | -------------------------------------------------------------------------------- /andesite-komanda/src/commonMain/kotlin/Command.kt: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2022 Gabrielle Guimarães de Oliveira 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | package andesite.komanda 18 | 19 | import andesite.komanda.parsing.parsePatternNode 20 | import andesite.protocol.misc.Chat 21 | import andesite.protocol.misc.ChatListBuilder 22 | 23 | public data class Command( 24 | val fallback: Pattern?, 25 | val name: String, 26 | val usage: List , 27 | val aliases: Set , 28 | val permissions: Set , 29 | val children: Set , 30 | ) 31 | 32 | public class CommandBuilder(private val name: String) { 33 | public var permissions: List = listOf() 34 | public var aliases: List = listOf() 35 | public var usage: List = listOf() 36 | 37 | private var fallback: Pattern? = null 38 | private val children: MutableSet = mutableSetOf() 39 | 40 | public fun fallback(builder: FallbackBuilder.() -> Unit) { 41 | fallback = FallbackBuilder(name).apply(builder).build() 42 | } 43 | 44 | public fun usage(builder: ChatListBuilder.() -> Unit) { 45 | usage = Chat.many(builder) 46 | } 47 | 48 | public fun pattern(text: String, builder: PatternBuilder.() -> Unit) { 49 | children += PatternBuilder(parsePatternNode(text)).apply(builder).build() 50 | } 51 | 52 | public fun pattern(builder: PatternBuilder.() -> Unit) { 53 | children += PatternBuilder().apply(builder).build() 54 | } 55 | 56 | public fun build(): Command { 57 | return Command(fallback, name, usage, aliases.toSet(), permissions.toSet(), children) 58 | } 59 | } 60 | -------------------------------------------------------------------------------- /.github/ISSUE_TEMPLATE/feature_request.yml: -------------------------------------------------------------------------------- 1 | name: 🚀 Feature Request 2 | description: I have a suggestion (and may want to implement it 🙂)! 3 | title: "[FR] " 4 | labels: [ "type: feature" ] 5 | body: 6 | - type: dropdown 7 | attributes: 8 | label: First, a few things... 9 | description: This will help us better interpret your request. 10 | options: 11 | - Is your feature request related to a problem? 12 | - Will this feature just help you or is it something everyone needs? 13 | - Have you tried to implement or *draft* this feature? 14 | - Is your feature a breaking change? 15 | - type: textarea 16 | attributes: 17 | label: 😄 Describe the solution you'd like 18 | description: A clear and concise description of what you want to happen. Add any considered drawbacks. 19 | validations: 20 | required: false 21 | - type: textarea 22 | attributes: 23 | label: 🧠 Describe alternatives you've considered 24 | description: A clear and concise description of any alternative solutions or features you've considered. 25 | validations: 26 | required: false 27 | - type: textarea 28 | attributes: 29 | label: 🤚 Drawbacks 30 | description: If this feature is a breaking change or what drawbacks does it have? 31 | validations: 32 | required: false 33 | - type: input 34 | attributes: 35 | label: 💻 Platform 36 | description: On which platforms do you want this feature to be applied? 37 | placeholder: "e.g. All, Linux" 38 | 39 | - type: input 40 | id: environment 41 | attributes: 42 | label: ⭐ Environment 43 | description: What is your current Andesite version? Maybe this feature already exists and you don't know 44 | placeholder: "e.g. 1.0-SNAPSHOT" 45 | validations: 46 | required: true 47 | - type: textarea 48 | attributes: 49 | label: ✍️ Additional context 50 | description: | 51 | Links? References? Anything that will give us more context about the issue you are encountering! 52 | Tip: You can attach images or log files by clicking this area to highlight it and then dragging files in. 53 | validations: 54 | required: false 55 | -------------------------------------------------------------------------------- /andesite-world/andesite-world-common/src/commonMain/kotlin/Location.kt: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2021 Gabrielle Guimarães de Oliveira 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | package andesite.world 18 | 19 | /** 20 | * Represents a generic Minecraft location. 21 | * 22 | * @param x the x coordinate 23 | * @param y the y coordinate 24 | * @param z the z coordinate 25 | * @param yaw the yaw 26 | * @param pitch the pitch 27 | * @param world the world 28 | */ 29 | public data class Location( 30 | val x: Double, 31 | val y: Double, 32 | val z: Double, 33 | val yaw: Float, 34 | val pitch: Float, 35 | val world: World, 36 | ) { 37 | public operator fun div(other: Location): Location { 38 | return Location( 39 | x / other.x, 40 | y / other.y, 41 | z / other.z, 42 | yaw / other.yaw, 43 | pitch / other.pitch, 44 | world, 45 | ) 46 | } 47 | 48 | public operator fun times(other: Location): Location { 49 | return Location( 50 | x * other.x, 51 | y * other.y, 52 | z * other.z, 53 | yaw * other.yaw, 54 | pitch * other.pitch, 55 | world, 56 | ) 57 | } 58 | 59 | public operator fun minus(other: Location): Location { 60 | return Location( 61 | x - other.x, 62 | y - other.y, 63 | z - other.z, 64 | yaw - other.yaw, 65 | pitch - other.pitch, 66 | world, 67 | ) 68 | } 69 | 70 | public operator fun plus(other: Location): Location { 71 | return Location( 72 | x + other.x, 73 | y + other.y, 74 | z + other.z, 75 | yaw + other.yaw, 76 | pitch + other.pitch, 77 | world, 78 | ) 79 | } 80 | } 81 | -------------------------------------------------------------------------------- /andesite-server/andesite-server-java/src/jvmMain/kotlin/player/JavaPlayerImpl.kt: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2021 Gabrielle Guimarães de Oliveira 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | package andesite.java.player 18 | 19 | import andesite.player.JavaPlayer 20 | import andesite.player.PlayerEvent 21 | import andesite.protocol.java.JavaPacket 22 | import andesite.protocol.java.v756.ChatMessagePacket 23 | import andesite.protocol.java.v756.ChatPosition 24 | import andesite.protocol.misc.Chat 25 | import andesite.protocol.misc.Uuid 26 | import andesite.server.MinecraftServer 27 | import andesite.world.Location 28 | import com.benasher44.uuid.uuid4 29 | import kotlinx.coroutines.CoroutineScope 30 | import kotlinx.coroutines.flow.Flow 31 | import kotlinx.coroutines.flow.filter 32 | import kotlinx.coroutines.flow.filterIsInstance 33 | import kotlinx.serialization.SerializationStrategy 34 | 35 | internal class JavaPlayerImpl( 36 | override val id: Uuid, 37 | override val protocol: Int, 38 | override val username: String, 39 | override var location: Location, 40 | val session: Session, 41 | val server: MinecraftServer, 42 | ) : JavaPlayer, CoroutineScope by session { 43 | override fun eventFlow(): Flow { 44 | return server 45 | .eventFlow() 46 | .filterIsInstance () 47 | .filter { it.player == this } 48 | } 49 | 50 | override suspend fun sendMessage(chat: Chat) { 51 | session.sendPacket(ChatMessagePacket(chat, ChatPosition.Chat, uuid4())) 52 | } 53 | 54 | override suspend fun sendPacket( 55 | serializer: SerializationStrategy, 56 | packet: A, 57 | ) { 58 | session.sendPacket(serializer, packet) 59 | } 60 | } 61 | -------------------------------------------------------------------------------- /andesite-komanda/src/commonMain/kotlin/Parameters.kt: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2022 Gabrielle Guimarães de Oliveira 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | package andesite.komanda 18 | 19 | import kotlin.reflect.KClass 20 | 21 | public typealias Parameters = Map > 22 | 23 | public class ParametersBuilder { 24 | private var parameters: MutableSet > = mutableSetOf() 25 | 26 | public fun add(parameter: Parameter) { 27 | parameters += parameter 28 | } 29 | 30 | public fun creating(type: KClass): ParameterBuilder { 31 | return ParameterBuilder(type, this) 32 | } 33 | 34 | public inline fun creating(): ParameterBuilder { 35 | return creating(A::class) 36 | } 37 | 38 | public fun byte(): ParameterBuilder = creating ().executes { it.toByte() } 39 | 40 | public fun uByte(): ParameterBuilder = creating ().executes { it.toUByte() } 41 | 42 | public fun short(): ParameterBuilder = creating ().executes { it.toShort() } 43 | 44 | public fun uShort(): ParameterBuilder = creating ().executes { it.toUShort() } 45 | 46 | public fun int(): ParameterBuilder = creating ().executes { it.toInt() } 47 | 48 | public fun uInt(): ParameterBuilder = creating ().executes { it.toUInt() } 49 | 50 | public fun long(): ParameterBuilder = creating ().executes { it.toLong() } 51 | 52 | public fun uLong(): ParameterBuilder = creating ().executes { it.toULong() } 53 | 54 | public fun string(): ParameterBuilder = creating ().executes { it } 55 | 56 | public fun build(): Set > { 57 | return parameters.toSet() 58 | } 59 | } 60 | -------------------------------------------------------------------------------- /andesite-komanda/src/jvmTest/kotlin/DispatchTest.kt: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2022 Gabrielle Guimarães de Oliveira 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | package andesite.komanda 18 | 19 | import andesite.protocol.misc.Chat 20 | import andesite.protocol.misc.mordant 21 | import kotlinx.coroutines.runBlocking 22 | import org.junit.jupiter.api.Test 23 | 24 | class DispatchTest { 25 | @Test 26 | fun `test dispatch`(): Unit = runBlocking { 27 | val root = TestKomandaRoot() 28 | 29 | root.command("hello") { 30 | fallback { 31 | onExecution { 32 | sendMessage("Hello from fallback, $arguments!") 33 | } 34 | } 35 | 36 | pattern("to [message]") { 37 | val target by parameters.string() 38 | val message by parameters.string().nullable() 39 | 40 | onExecution { 41 | sendMessage("Hello from pattern, target=$target, message=$message") 42 | } 43 | } 44 | } 45 | 46 | root.dispatch("hello to 'carlos'", "Gabi") 47 | // root.dispatch("hello 'world'", "Gabi") 48 | // root.dispatch("hello target:'world'", "Gabi") 49 | // root.dispatch("hello target='world'", "Gabi") 50 | // root.dispatch("hello target= 'world'", "Gabi") 51 | } 52 | } 53 | 54 | class TestExecutionScope (override val sender: S, override val arguments: Arguments) : 55 | ExecutionScope{ 56 | override suspend fun sendMessage(chat: Chat) { 57 | println("message: ${chat.mordant()}") 58 | } 59 | 60 | override suspend fun failwith(chat: Chat) { 61 | println("fail: ${chat.mordant()}") 62 | } 63 | } 64 | 65 | class TestKomandaRoot : AbstractKomandaRoot() { 66 | override fun createExecutionScope(sender: String, arguments: Arguments) = 67 | TestExecutionScope(sender, arguments) 68 | } 69 | -------------------------------------------------------------------------------- /andesite-server/andesite-server-common/src/jvmMain/kotlin/server/MinecraftServer.kt: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2022 Gabrielle Guimarães de Oliveira 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | package andesite.server 18 | 19 | import andesite.event.EventHolder 20 | import andesite.event.MinecraftEvent 21 | import andesite.komanda.KomandaRoot 22 | import andesite.player.MinecraftPlayer 23 | import andesite.protocol.serialization.MinecraftCodec 24 | import andesite.world.Location 25 | import andesite.world.block.BlockRegistry 26 | import kotlinx.coroutines.CoroutineScope 27 | import kotlinx.serialization.json.Json 28 | import net.benwoodworth.knbt.Nbt 29 | import org.apache.logging.log4j.kotlin.Logging 30 | 31 | /** Represents a generic Minecraft server. */ 32 | public interface MinecraftServer : 33 | CoroutineScope, 34 | EventHolder , 35 | Logging, 36 | KomandaRoot { 37 | public val codec: MinecraftCodec 38 | public val protocolVersion: Int 39 | public val minecraftVersion: String 40 | public val players: List 41 | public val motd: Motd 42 | public val spawn: Location 43 | public val blockRegistry: BlockRegistry 44 | public val nbt: Nbt 45 | public val json: Json 46 | 47 | /** 48 | * Publish events to [MinecraftServer] 49 | * 50 | * @param event the event to publish 51 | */ 52 | public suspend fun publish(event: MinecraftEvent) 53 | 54 | /** Listen to connections */ 55 | public fun listen() 56 | } 57 | 58 | /** The builder class for [MinecraftServer]. */ 59 | public interface MinecraftServerBuilder { 60 | public var hostname: String 61 | public var port: Int 62 | public var spawn: Location 63 | public var blockRegistry: BlockRegistry 64 | public var codec: MinecraftCodec 65 | 66 | public fun motd(builder: MotdBuilder.() -> Unit) 67 | } 68 | -------------------------------------------------------------------------------- /andesite-komanda/src/commonMain/kotlin/Arguments.kt: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2022 Gabrielle Guimarães de Oliveira 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | package andesite.komanda 18 | 19 | import andesite.komanda.errors.ArgumentNotFoundException 20 | import andesite.komanda.errors.ArgumentNotTypecheckException 21 | import kotlin.properties.ReadOnlyProperty 22 | import kotlin.reflect.KClass 23 | import kotlin.reflect.KProperty 24 | 25 | public class Arguments( 26 | private val map: Map , 27 | private val toString: String = map.toString(), 28 | ) { 29 | public val size: Int get() = map.size 30 | 31 | public infix fun compose(other: Arguments): Arguments { 32 | return Arguments(map = map + other.map) 33 | } 34 | 35 | public fun get(name: String, type: KClass): A { 36 | return getOrNull(name, type) ?: throw ArgumentNotFoundException(name) 37 | } 38 | 39 | public fun getOrNull(name: String, type: KClass): A? { 40 | val argument = map[name] ?: return null 41 | if (!type.isInstance(argument)) throw ArgumentNotTypecheckException(name, type, argument::class) 42 | 43 | @Suppress("UNCHECKED_CAST") 44 | return argument as A 45 | } 46 | 47 | public inline fun orDefault(value: A): ReadOnlyProperty { 48 | return ReadOnlyProperty { _, property -> 49 | getOrNull(property.name, A::class) ?: value 50 | } 51 | } 52 | 53 | public inline operator fun getValue(thisRef: Any?, property: KProperty<*>): A { 54 | return get(property.name, A::class) 55 | } 56 | 57 | public fun toStringList(): List { 58 | return map.values.mapNotNull { it.toString() } 59 | } 60 | 61 | override fun toString(): String = toString 62 | 63 | public companion object { 64 | public fun empty(): Arguments = Arguments(mapOf()) 65 | } 66 | } 67 | -------------------------------------------------------------------------------- /gradle/libs.versions.toml: -------------------------------------------------------------------------------- 1 | [versions] 2 | ktx-coroutines = "1.6.4" 3 | ktx-serialization = "1.4.0-RC" 4 | ktx-datetime = "0.3.1" 5 | ktx-atomicfu = "0.17.2" 6 | kt = "1.7.0" 7 | ktor = "2.0.3" 8 | knbt = "0.11.2" 9 | uuid = "0.3.1" 10 | mordant = "2.0.0-beta4" 11 | log4j-core = "2.17.2" 12 | log4j-kotlin = "1.1.0" 13 | okio = "3.0.0" 14 | betterParse = "0.4.4" 15 | 16 | # Libraries 17 | [libraries.kt-reflect] 18 | module = "org.jetbrains.kotlin:kotlin-reflect" 19 | version.ref = "kt" 20 | 21 | [libraries.kt-test-common] 22 | module = "org.jetbrains.kotlin:kotlin-test-common" 23 | version.ref = "kt" 24 | 25 | [libraries.kt-test-junit] 26 | module = "org.jetbrains.kotlin:kotlin-test-junit5" 27 | version.ref = "kt" 28 | 29 | [libraries.kt-test-annotations-common] 30 | module = "org.jetbrains.kotlin:kotlin-test-annotations-common" 31 | version.ref = "kt" 32 | 33 | [libraries.ktx-atomicfu] 34 | module = "org.jetbrains.kotlinx:atomicfu" 35 | version.ref = "ktx-atomicfu" 36 | 37 | [libraries.ktx-datetime] 38 | module = "org.jetbrains.kotlinx:kotlinx-datetime" 39 | version.ref = "ktx-datetime" 40 | 41 | [libraries.ktx-serialization-json] 42 | module = "org.jetbrains.kotlinx:kotlinx-serialization-json" 43 | version.ref = "ktx-serialization" 44 | 45 | [libraries.ktx-coroutines-core] 46 | module = "org.jetbrains.kotlinx:kotlinx-coroutines-core" 47 | version.ref = "ktx-coroutines" 48 | 49 | [libraries.ktx-coroutines-jdk8] 50 | module = "org.jetbrains.kotlinx:kotlinx-coroutines-jdk8" 51 | version.ref = "ktx-coroutines" 52 | 53 | [libraries.mordant] 54 | module = "com.github.ajalt.mordant:mordant" 55 | version.ref = "mordant" 56 | 57 | [libraries.log4j-api] 58 | module = "org.apache.logging.log4j:log4j-api" 59 | version.ref = "log4j-core" 60 | 61 | [libraries.log4j-core] 62 | module = "org.apache.logging.log4j:log4j-core" 63 | version.ref = "log4j-core" 64 | 65 | [libraries.log4j-kotlin] 66 | module = "org.apache.logging.log4j:log4j-api-kotlin" 67 | version.ref = "log4j-kotlin" 68 | 69 | [libraries.okio] 70 | module = "com.squareup.okio:okio" 71 | version.ref = "okio" 72 | 73 | [libraries.ktor-network] 74 | module = "io.ktor:ktor-network" 75 | version.ref = "ktor" 76 | 77 | [libraries.knbt] 78 | module = "net.benwoodworth.knbt:knbt" 79 | version.ref = "knbt" 80 | 81 | [libraries.uuid] 82 | module = "com.benasher44:uuid" 83 | version.ref = "uuid" 84 | 85 | [libraries.betterParse] 86 | module = "com.github.h0tk3y.betterParse:better-parse" 87 | version.ref = "betterParse" 88 | --------------------------------------------------------------------------------