Skip to content

Commit

Permalink
🔖 Release 1.0.3
Browse files Browse the repository at this point in the history
Added schematic support
  • Loading branch information
KodingDev authored Jul 23, 2020
2 parents 3725d59 + e36880d commit bb98cc5
Show file tree
Hide file tree
Showing 20 changed files with 563 additions and 67 deletions.
2 changes: 1 addition & 1 deletion build.gradle
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@ ext {
}

group 'dev.zerite.craftlib'
version '0.1.2'
version '0.1.3'

subprojects {
apply plugin: 'java'
Expand Down
1 change: 1 addition & 0 deletions craftlib-commons/build.gradle
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
description = 'Miscellaneous utilities which are shared between modules'
Original file line number Diff line number Diff line change
@@ -1,23 +1,23 @@
package dev.zerite.craftlib.protocol.data.world
package dev.zerite.craftlib.commons.io

/**
* Stores an array of bytes, with each storing two integer values spanning
* 4 bits.
*
* @author Koding
* @since 0.1.0-SNAPSHOT
* @since 0.1.3
*/
data class ByteNibbleArray(var data: ByteArray) {
data class ByteNibbleArray @JvmOverloads constructor(var data: ByteArray, var flipped: Boolean = false) {

/**
* Gets a nibble byte from the array with the given index.
*
* @param index The index of the nibble byte.
* @author Koding
* @since 0.1.0-SNAPSHOT
* @since 0.1.3
*/
operator fun get(index: Int) =
data[index / 2].toInt() ushr (if (index % 2 == 0) 0 else 4) and 0x0F
data[index / 2].toInt() ushr (if (index % 2 == if (flipped) 1 else 0) 0 else 4) and 0x0F

/**
* Gets a nibble byte from the array, otherwise falling back
Expand All @@ -27,7 +27,7 @@ data class ByteNibbleArray(var data: ByteArray) {
* @param default The fallback value if the index is out of bounds.
*
* @author Koding
* @since 0.1.0-SNAPSHOT
* @since 0.1.3
*/
operator fun get(index: Int, default: Int) =
if (index < 0 || (index / 2) >= data.size || data.isEmpty()) default else this[index]
Expand All @@ -39,11 +39,11 @@ data class ByteNibbleArray(var data: ByteArray) {
* @param value The value which we are setting.
*
* @author Koding
* @since 0.1.0-SNAPSHOT
* @since 0.1.3
*/
operator fun set(index: Int, value: Int) {
val i = index shr 1
if (index and 1 == 0) data[i] = ((data[i].toInt() and 240) or (value and 15)).toByte()
if (index and 1 == if (flipped) 1 else 0) data[i] = ((data[i].toInt() and 240) or (value and 15)).toByte()
else data[i] = ((data[i].toInt() and 15) or ((value and 15) shl 4)).toByte()
}

Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,40 @@
package dev.zerite.craftlib.commons.world

/**
* Stores information about a single block in the world
*
* @author Koding
* @since 0.1.0-SNAPSHOT
*/
data class Block(
val id: Int,
val metadata: Int,
val blockLight: Int = 0,
val skyLight: Int = 0
) {

companion object {
/**
* Constant value for an air block.
*/
@JvmField
val AIR = Block(0, 0)
}

/**
* The location of this block.
*/
lateinit var location: BlockLocation
}

/**
* Vector for storing a 3D block location.
*
* @author Koding
* @since 0.1.0-SNAPSHOT
*/
data class BlockLocation(
val x: Int,
val y: Int,
val z: Int
)
34 changes: 34 additions & 0 deletions craftlib-nbt/src/main/kotlin/dev/zerite/craftlib/nbt/DSL.kt
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,8 @@
package dev.zerite.craftlib.nbt

import dev.zerite.craftlib.nbt.impl.*
import java.io.InputStream
import java.io.OutputStream

/**
* Builds a compound tag.
Expand Down Expand Up @@ -151,3 +153,35 @@ val Any?.asTag: NBTTag
is LongArray -> LongArrayTag(this)
else -> error("Don't know how to convert $this into a NBT tag")
}

/**
* Writes a NBT tag to the provided output stream.
*
* @param stream The stream to write to.
* @param compressed Whether the tag we are writing should be compressed.
*
* @author Koding
* @since 0.1.3
*/
suspend fun NBTTag.write(stream: OutputStream, compressed: Boolean = false) =
if (compressed) NBTIO.writeCompressed(this, stream)
else NBTIO.write(this, stream)

/**
* Reads a NBT tag from this input stream.
*
* @param compressed Whether this tag we are reading is compressed.
* @author Koding
* @since 0.1.3
*/
suspend fun InputStream.readTag(compressed: Boolean = false) =
if (compressed) NBTIO.readCompressed(this)
else NBTIO.read(this)

/**
* Converts a NBT tag into a named NBT tag.
*
* @author Koding
* @since 0.1.3
*/
fun <T : NBTTag> T.named(name: String) = named(name, this)
2 changes: 2 additions & 0 deletions craftlib-protocol/build.gradle
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,8 @@ dependencies {
api "org.jetbrains.kotlinx:kotlinx-coroutines-jdk8:$coroutinesVersion"
api "org.jetbrains.kotlin:kotlin-reflect:$kotlinVersion"
api 'io.netty:netty-all:4.1.51.Final'

api project(':craftlib-chat')
api project(':craftlib-nbt')
api project(':craftlib-commons')
}
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
package dev.zerite.craftlib.protocol

import com.google.gson.reflect.TypeToken
import dev.zerite.craftlib.protocol.connection.NettyConnection
import dev.zerite.craftlib.protocol.version.ProtocolVersion

Expand All @@ -13,6 +14,12 @@ import dev.zerite.craftlib.protocol.version.ProtocolVersion
@Suppress("UNUSED")
interface PacketIO<T : Packet> {

/**
* Retrieves the class for the packet generic.
*/
val type: Class<in T>
get() = (object : TypeToken<T>() {}).rawType

/**
* Reads a packet from the provided protocol buffer into an object.
*
Expand Down
Original file line number Diff line number Diff line change
@@ -1,5 +1,8 @@
package dev.zerite.craftlib.protocol.data.world

import dev.zerite.craftlib.commons.world.Block
import dev.zerite.craftlib.commons.world.BlockLocation

/**
* Stores a chunk's full data, including the block information and
* lighting data.
Expand Down Expand Up @@ -69,36 +72,6 @@ data class Chunk(internal var blocks: Array<Block?> = arrayOfNulls(DESIRED_BLOCK
override fun hashCode() = blocks.contentHashCode()
}

/**
* Stores information about a single block in the world
*
* @author Koding
* @since 0.1.0-SNAPSHOT
*/
data class Block(
val id: Int,
val metadata: Int,
val blockLight: Int,
val skyLight: Int
) {
/**
* The location of this block.
*/
lateinit var location: BlockLocation
}

/**
* Vector for storing a 3D block location.
*
* @author Koding
* @since 0.1.0-SNAPSHOT
*/
data class BlockLocation(
val x: Int,
val y: Int,
val z: Int
)

/**
* Stores information about a chunk.
*
Expand Down
Original file line number Diff line number Diff line change
@@ -1,5 +1,8 @@
package dev.zerite.craftlib.protocol.data.world

import dev.zerite.craftlib.commons.io.ByteNibbleArray
import dev.zerite.craftlib.commons.world.Block
import dev.zerite.craftlib.commons.world.BlockLocation
import dev.zerite.craftlib.protocol.util.ext.toByteArray
import dev.zerite.craftlib.protocol.util.ext.toShortArray
import dev.zerite.craftlib.protocol.util.ext.trim
Expand All @@ -11,7 +14,12 @@ import dev.zerite.craftlib.protocol.util.ext.trim
* @author Koding
* @since 0.1.0-SNAPSHOT
*/
data class ChunkColumn(val x: Int, val z: Int, val chunks: Array<Chunk>, private var biomes: ByteArray) {
data class ChunkColumn @JvmOverloads constructor(
val x: Int,
val z: Int,
val chunks: Array<Chunk> = Array(16) { Chunk() },
var biomes: ByteArray = ByteArray(16 * 16) { 0 }
) {

companion object {
/**
Expand Down Expand Up @@ -402,6 +410,22 @@ data class ChunkColumn(val x: Int, val z: Int, val chunks: Array<Chunk>, private
return this[chunkY][x, y - chunkY * 16, z]
}

/**
* Gets a block in this chunk column and return it.
*
* @param x The x coordinate in this chunk. Max 16.
* @param y The y coordinate in this chunk. Max 256.
* @param z The z coordinate in this chunk. Max 16.
* @param block The new block at this coordinate.
*
* @author Koding
* @since 0.1.0-SNAPSHOT
*/
operator fun set(x: Int, y: Int, z: Int, block: Block) {
val chunkY = y / 16
this[chunkY][x, y - chunkY * 16, z] = block
}

/**
* Gets the biome at the specific coordinate within the chunk.
*
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,51 @@
package dev.zerite.craftlib.protocol.data.world

import dev.zerite.craftlib.commons.world.Block

/**
* Simple utility class which allows you to set any coordinate in a world with
* a block and automatically update the chunks map.
*
* @author Koding
* @since 0.1.3
*/
@Suppress("UNUSED")
class World @JvmOverloads constructor(var chunks: MutableMap<Pair<Int, Int>, ChunkColumn> = hashMapOf()) {

/**
* Sets a block a the given position in the world.
*
* @param x The x position to set the block at.
* @param y The y position to set the block at.
* @param z The z position to set the block at.
* @param block The new block for the position to have set.
*
* @author Koding
* @since 0.1.3
*/
operator fun set(x: Int, y: Int, z: Int, block: Block) {
val chunkX = x shr 4
val chunkZ = z shr 4
val column = chunks.getOrPut(chunkX to chunkZ) { ChunkColumn(chunkX, chunkZ) }
column[x and 0xF, y, z and 0xF] = block
}

/**
* Gets a block at the given position or null if there
* is no block present.
*
* @param x The x position to set the block at.
* @param y The y position to set the block at.
* @param z The z position to set the block at.
*
* @author Koding
* @since 0.1.3
*/
operator fun get(x: Int, y: Int, z: Int): Block? {
val chunkX = x shr 4
val chunkZ = z shr 4
val column = chunks[chunkX to chunkZ] ?: return null
return column[x and 0xF, y, z and 0xF]
}

}
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
@file:JvmName("ArrayUtil")

package dev.zerite.craftlib.protocol.util.ext

import io.netty.buffer.Unpooled
Expand Down
Original file line number Diff line number Diff line change
@@ -1,7 +1,6 @@
package dev.zerite.craftlib.protocol.version

import dev.zerite.craftlib.protocol.PacketIO
import kotlin.reflect.jvm.javaType

/**
* Stores details about packet mappings for a specific connection state.
Expand Down Expand Up @@ -138,29 +137,14 @@ data class ProtocolState(val name: String, val id: Any) {
* @since 0.1.0-SNAPSHOT
*/
@ProtocolStateDSL
operator fun PacketIO<*>.invoke(block: IdListBuilder.() -> Unit) =
operator fun PacketIO<*>.invoke(block: IdListBuilder.() -> Unit) {
val packetType = type
runForAllProtocols(IdListBuilder().apply(block).ids.toTypedArray()) { version, id ->
val data = PacketData(id, this)
val type = javaClass.typeParameter ?: return@runForAllProtocols

classToData.getOrPut(version) { hashMapOf() }[type] = data
classToData.getOrPut(version) { hashMapOf() }[packetType] = data
idToData.getOrPut(version) { hashMapOf() }[id] = data
}

/**
* Finds the first type parameter for a class.
*/
val Class<*>.typeParameter: Class<*>?
get() = try {
kotlin.supertypes.firstOrNull()
?.arguments?.firstOrNull()
?.type?.javaType?.typeName
?.let {
Class.forName(it)
} ?: error("Failed to get packet class!")
} catch (e: Throwable) {
error("Failed to get packet class!")
}
}


/**
Expand Down
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
package dev.zerite.craftlib.protocol.packet.play.server.world

import dev.zerite.craftlib.protocol.data.world.Block
import dev.zerite.craftlib.commons.world.Block
import dev.zerite.craftlib.protocol.data.world.Chunk
import dev.zerite.craftlib.protocol.data.world.ChunkColumn
import dev.zerite.craftlib.protocol.packet.PacketTest
Expand Down
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
package dev.zerite.craftlib.protocol.packet.play.server.world

import dev.zerite.craftlib.protocol.data.world.Block
import dev.zerite.craftlib.commons.world.Block
import dev.zerite.craftlib.protocol.data.world.Chunk
import dev.zerite.craftlib.protocol.data.world.ChunkColumn
import dev.zerite.craftlib.protocol.packet.PacketTest
Expand Down
Loading

0 comments on commit bb98cc5

Please sign in to comment.