Look at some DB stuff
This commit is contained in:
@@ -1,6 +1,6 @@
|
|||||||
package io.dico.parcels2
|
package io.dico.parcels2
|
||||||
|
|
||||||
import io.dico.parcels2.math.Vec2i
|
import io.dico.parcels2.util.Vec2i
|
||||||
import io.dico.parcels2.util.getPlayerName
|
import io.dico.parcels2.util.getPlayerName
|
||||||
import io.dico.parcels2.util.hasBuildAnywhere
|
import io.dico.parcels2.util.hasBuildAnywhere
|
||||||
import io.dico.parcels2.util.isValid
|
import io.dico.parcels2.util.isValid
|
||||||
@@ -8,6 +8,7 @@ import io.dico.parcels2.util.uuid
|
|||||||
import org.bukkit.Bukkit
|
import org.bukkit.Bukkit
|
||||||
import org.bukkit.OfflinePlayer
|
import org.bukkit.OfflinePlayer
|
||||||
import org.bukkit.entity.Player
|
import org.bukkit.entity.Player
|
||||||
|
import org.joda.time.DateTime
|
||||||
import java.util.*
|
import java.util.*
|
||||||
|
|
||||||
interface AddedData {
|
interface AddedData {
|
||||||
@@ -148,12 +149,13 @@ enum class AddedStatus {
|
|||||||
|
|
||||||
@Suppress("UsePropertyAccessSyntax")
|
@Suppress("UsePropertyAccessSyntax")
|
||||||
class ParcelOwner(val uuid: UUID? = null,
|
class ParcelOwner(val uuid: UUID? = null,
|
||||||
name: String? = null) {
|
name: String? = null,
|
||||||
|
val since: DateTime? = null) {
|
||||||
|
|
||||||
companion object {
|
companion object {
|
||||||
fun create(uuid: UUID?, name: String?): ParcelOwner? {
|
fun create(uuid: UUID?, name: String?, time: DateTime? = null): ParcelOwner? {
|
||||||
return uuid?.let { ParcelOwner(uuid, name) }
|
return uuid?.let { ParcelOwner(uuid, name, time) }
|
||||||
?: name?.let { ParcelOwner(uuid, name) }
|
?: name?.let { ParcelOwner(uuid, name, time) }
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -1,11 +1,11 @@
|
|||||||
package io.dico.parcels2
|
package io.dico.parcels2
|
||||||
|
|
||||||
import io.dico.parcels2.math.Vec2i
|
|
||||||
import io.dico.parcels2.math.floor
|
|
||||||
import io.dico.parcels2.storage.SerializableParcel
|
import io.dico.parcels2.storage.SerializableParcel
|
||||||
import io.dico.parcels2.storage.SerializableWorld
|
import io.dico.parcels2.storage.SerializableWorld
|
||||||
import io.dico.parcels2.storage.Storage
|
import io.dico.parcels2.storage.Storage
|
||||||
|
import io.dico.parcels2.util.Vec2i
|
||||||
import io.dico.parcels2.util.doAwait
|
import io.dico.parcels2.util.doAwait
|
||||||
|
import io.dico.parcels2.util.floor
|
||||||
import kotlinx.coroutines.experimental.launch
|
import kotlinx.coroutines.experimental.launch
|
||||||
import org.bukkit.Bukkit
|
import org.bukkit.Bukkit
|
||||||
import org.bukkit.Location
|
import org.bukkit.Location
|
||||||
|
|||||||
@@ -1,9 +1,9 @@
|
|||||||
package io.dico.parcels2
|
package io.dico.parcels2
|
||||||
|
|
||||||
import io.dico.parcels2.math.Vec2i
|
import io.dico.parcels2.util.Vec2i
|
||||||
import io.dico.parcels2.math.clamp
|
import io.dico.parcels2.util.clamp
|
||||||
import io.dico.parcels2.math.even
|
import io.dico.parcels2.util.even
|
||||||
import io.dico.parcels2.math.umod
|
import io.dico.parcels2.util.umod
|
||||||
import org.bukkit.*
|
import org.bukkit.*
|
||||||
import org.bukkit.Bukkit.createBlockData
|
import org.bukkit.Bukkit.createBlockData
|
||||||
import org.bukkit.block.Biome
|
import org.bukkit.block.Biome
|
||||||
|
|||||||
@@ -40,8 +40,9 @@ class ParcelEntityTracker(val worlds: Worlds) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Suppress("RedundantLambdaArrow")
|
||||||
fun swapParcels(parcel1: Parcel, parcel2: Parcel) {
|
fun swapParcels(parcel1: Parcel, parcel2: Parcel) {
|
||||||
map.editLoop {
|
map.editLoop { ->
|
||||||
if (value === parcel1) {
|
if (value === parcel1) {
|
||||||
value = parcel2
|
value = parcel2
|
||||||
} else if (value === parcel2) {
|
} else if (value === parcel2) {
|
||||||
|
|||||||
@@ -110,7 +110,7 @@ class ParcelListeners(val worlds: Worlds, val entityTracker: ParcelEntityTracker
|
|||||||
|
|
||||||
private inline val Long.columnX get() = and(0xFFFF_FFFFL).toInt()
|
private inline val Long.columnX get() = and(0xFFFF_FFFFL).toInt()
|
||||||
private inline val Long.columnZ get() = ushr(32).and(0xFFFF_FFFFL).toInt()
|
private inline val Long.columnZ get() = ushr(32).and(0xFFFF_FFFFL).toInt()
|
||||||
private inline fun TLongCollection.forEachInline(block: (Long) -> Unit) = iterator().let { while (it.hasNext()) block(it.next()) }
|
private inline fun TLongCollection.troveForEach(block: (Long) -> Unit) = iterator().let { while (it.hasNext()) block(it.next()) }
|
||||||
//@formatter:on
|
//@formatter:on
|
||||||
private fun checkPistonMovement(event: BlockPistonEvent, blocks: List<Block>) {
|
private fun checkPistonMovement(event: BlockPistonEvent, blocks: List<Block>) {
|
||||||
val world = worlds.getWorld(event.block.world) ?: return
|
val world = worlds.getWorld(event.block.world) ?: return
|
||||||
@@ -122,7 +122,7 @@ class ParcelListeners(val worlds: Worlds, val entityTracker: ParcelEntityTracker
|
|||||||
it.getRelative(direction).let { columns.add(Column(it.x, it.z)) }
|
it.getRelative(direction).let { columns.add(Column(it.x, it.z)) }
|
||||||
}
|
}
|
||||||
|
|
||||||
columns.forEachInline {
|
columns.troveForEach {
|
||||||
val ppa = world.parcelAt(it.columnX, it.columnZ)
|
val ppa = world.parcelAt(it.columnX, it.columnZ)
|
||||||
if (ppa.isNullOr { hasBlockVisitors }) {
|
if (ppa.isNullOr { hasBlockVisitors }) {
|
||||||
event.isCancelled = true
|
event.isCancelled = true
|
||||||
|
|||||||
@@ -1,5 +1,6 @@
|
|||||||
package io.dico.parcels2.storage
|
package io.dico.parcels2.storage
|
||||||
|
|
||||||
|
import io.dico.parcels2.AddedData
|
||||||
import io.dico.parcels2.Parcel
|
import io.dico.parcels2.Parcel
|
||||||
import io.dico.parcels2.ParcelData
|
import io.dico.parcels2.ParcelData
|
||||||
import io.dico.parcels2.ParcelOwner
|
import io.dico.parcels2.ParcelOwner
|
||||||
@@ -23,6 +24,8 @@ interface Backing {
|
|||||||
*/
|
*/
|
||||||
suspend fun ProducerScope<Pair<Parcel, ParcelData?>>.produceParcelData(parcels: Sequence<Parcel>)
|
suspend fun ProducerScope<Pair<Parcel, ParcelData?>>.produceParcelData(parcels: Sequence<Parcel>)
|
||||||
|
|
||||||
|
suspend fun ProducerScope<Pair<SerializableParcel, ParcelData?>>.produceAllParcelData()
|
||||||
|
|
||||||
suspend fun readParcelData(parcelFor: Parcel): ParcelData?
|
suspend fun readParcelData(parcelFor: Parcel): ParcelData?
|
||||||
|
|
||||||
suspend fun getOwnedParcels(user: ParcelOwner): List<SerializableParcel>
|
suspend fun getOwnedParcels(user: ParcelOwner): List<SerializableParcel>
|
||||||
@@ -40,4 +43,9 @@ interface Backing {
|
|||||||
|
|
||||||
suspend fun setParcelAllowsInteractInputs(parcel: Parcel, value: Boolean)
|
suspend fun setParcelAllowsInteractInputs(parcel: Parcel, value: Boolean)
|
||||||
|
|
||||||
|
|
||||||
|
suspend fun readGlobalPlayerStateData(owner: ParcelOwner): AddedData?
|
||||||
|
|
||||||
|
suspend fun setGlobalPlayerState(owner: ParcelOwner, player: UUID, state: Boolean?)
|
||||||
|
|
||||||
}
|
}
|
||||||
@@ -2,14 +2,14 @@ package io.dico.parcels2.storage
|
|||||||
|
|
||||||
import com.zaxxer.hikari.HikariDataSource
|
import com.zaxxer.hikari.HikariDataSource
|
||||||
import io.dico.parcels2.*
|
import io.dico.parcels2.*
|
||||||
import io.dico.parcels2.math.Vec2i
|
import io.dico.parcels2.util.Vec2i
|
||||||
import io.dico.parcels2.util.synchronized
|
|
||||||
import io.dico.parcels2.util.toByteArray
|
import io.dico.parcels2.util.toByteArray
|
||||||
import io.dico.parcels2.util.toUUID
|
import io.dico.parcels2.util.toUUID
|
||||||
import kotlinx.coroutines.experimental.channels.ProducerScope
|
import kotlinx.coroutines.experimental.channels.ProducerScope
|
||||||
import org.jetbrains.exposed.sql.*
|
import org.jetbrains.exposed.sql.*
|
||||||
import org.jetbrains.exposed.sql.SchemaUtils.create
|
import org.jetbrains.exposed.sql.SchemaUtils.create
|
||||||
import org.jetbrains.exposed.sql.transactions.transaction
|
import org.jetbrains.exposed.sql.transactions.transaction
|
||||||
|
import org.joda.time.DateTime
|
||||||
import java.util.*
|
import java.util.*
|
||||||
import javax.sql.DataSource
|
import javax.sql.DataSource
|
||||||
|
|
||||||
@@ -29,6 +29,7 @@ object ParcelsT : Table("parcels") {
|
|||||||
.references(WorldsT.id)
|
.references(WorldsT.id)
|
||||||
val owner_uuid = binary("owner_uuid", 16).nullable()
|
val owner_uuid = binary("owner_uuid", 16).nullable()
|
||||||
val owner_name = varchar("owner_name", 16).nullable()
|
val owner_name = varchar("owner_name", 16).nullable()
|
||||||
|
val claim_time = datetime("claim_time").nullable()
|
||||||
}
|
}
|
||||||
|
|
||||||
object AddedLocalT : Table("parcels_added_local") {
|
object AddedLocalT : Table("parcels_added_local") {
|
||||||
@@ -148,30 +149,18 @@ class ExposedBacking(private val dataSourceFactory: () -> DataSource) : Backing
|
|||||||
channel.close()
|
channel.close()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
override suspend fun ProducerScope<Pair<SerializableParcel, ParcelData?>>.produceAllParcelData() {
|
||||||
|
ParcelsT.selectAll().forEach { row ->
|
||||||
|
val parcel = rowToSerializableParcel(row) ?: return@forEach
|
||||||
|
val data = rowToParcelData(row)
|
||||||
|
channel.send(parcel to data)
|
||||||
|
}
|
||||||
|
channel.close()
|
||||||
|
}
|
||||||
|
|
||||||
override suspend fun readParcelData(parcelFor: Parcel): ParcelData? = transaction {
|
override suspend fun readParcelData(parcelFor: Parcel): ParcelData? = transaction {
|
||||||
val row = getParcelRow(parcelFor) ?: return@transaction null
|
val row = getParcelRow(parcelFor) ?: return@transaction null
|
||||||
|
rowToParcelData(row)
|
||||||
ParcelDataHolder().apply {
|
|
||||||
|
|
||||||
owner = ParcelOwner.create(
|
|
||||||
uuid = row[ParcelsT.owner_uuid]?.toUUID(),
|
|
||||||
name = row[ParcelsT.owner_name]
|
|
||||||
)
|
|
||||||
|
|
||||||
val parcelId = row[ParcelsT.id]
|
|
||||||
AddedLocalT.select { AddedLocalT.parcel_id eq parcelId }.forEach {
|
|
||||||
val uuid = it[AddedLocalT.player_uuid].toUUID()!!
|
|
||||||
val status = if (it[AddedLocalT.allowed_flag]) AddedStatus.ALLOWED else AddedStatus.BANNED
|
|
||||||
setAddedStatus(uuid, status)
|
|
||||||
}
|
|
||||||
|
|
||||||
ParcelOptionsT.select { ParcelOptionsT.parcel_id eq parcelId }.firstOrNull()?.let {
|
|
||||||
allowInteractInputs = it[ParcelOptionsT.interact_inputs]
|
|
||||||
allowInteractInventory = it[ParcelOptionsT.interact_inventory]
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// TODO order by some new column
|
// TODO order by some new column
|
||||||
@@ -186,16 +175,8 @@ class ExposedBacking(private val dataSourceFactory: () -> DataSource) : Backing
|
|||||||
where = { ParcelsT.owner_name eq name }
|
where = { ParcelsT.owner_name eq name }
|
||||||
}
|
}
|
||||||
|
|
||||||
ParcelsT.select(where)
|
ParcelsT.select(where).orderBy(ParcelsT.claim_time, isAsc = true)
|
||||||
.map { parcelRow ->
|
.mapNotNull(::rowToSerializableParcel)
|
||||||
val worldId = parcelRow[ParcelsT.world_id]
|
|
||||||
val worldRow = WorldsT.select({ WorldsT.id eq worldId }).firstOrNull()
|
|
||||||
?: return@map null
|
|
||||||
|
|
||||||
val world = SerializableWorld(worldRow[WorldsT.name], worldRow[WorldsT.uid].toUUID())
|
|
||||||
SerializableParcel(world, Vec2i(parcelRow[ParcelsT.px], parcelRow[ParcelsT.pz]))
|
|
||||||
}
|
|
||||||
.filterNotNull()
|
|
||||||
.toList()
|
.toList()
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -237,6 +218,7 @@ class ExposedBacking(private val dataSourceFactory: () -> DataSource) : Backing
|
|||||||
override suspend fun setParcelOwner(parcelFor: Parcel, owner: ParcelOwner?) = transaction {
|
override suspend fun setParcelOwner(parcelFor: Parcel, owner: ParcelOwner?) = transaction {
|
||||||
val binaryUuid = owner?.uuid?.toByteArray()
|
val binaryUuid = owner?.uuid?.toByteArray()
|
||||||
val name = owner?.name
|
val name = owner?.name
|
||||||
|
val time = owner?.let { DateTime.now() }
|
||||||
|
|
||||||
val id = if (owner == null)
|
val id = if (owner == null)
|
||||||
getParcelId(parcelFor) ?: return@transaction
|
getParcelId(parcelFor) ?: return@transaction
|
||||||
@@ -246,6 +228,7 @@ class ExposedBacking(private val dataSourceFactory: () -> DataSource) : Backing
|
|||||||
ParcelsT.update({ ParcelsT.id eq id }) {
|
ParcelsT.update({ ParcelsT.id eq id }) {
|
||||||
it[ParcelsT.owner_uuid] = binaryUuid
|
it[ParcelsT.owner_uuid] = binaryUuid
|
||||||
it[ParcelsT.owner_name] = name
|
it[ParcelsT.owner_name] = name
|
||||||
|
it[ParcelsT.claim_time] = time
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -282,6 +265,43 @@ class ExposedBacking(private val dataSourceFactory: () -> DataSource) : Backing
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
override suspend fun readGlobalPlayerStateData(owner: ParcelOwner): AddedData? {
|
||||||
|
TODO("not implemented") //To change body of created functions use File | Settings | File Templates.
|
||||||
|
}
|
||||||
|
|
||||||
|
override suspend fun setGlobalPlayerState(owner: ParcelOwner, player: UUID, state: Boolean?) {
|
||||||
|
TODO("not implemented") //To change body of created functions use File | Settings | File Templates.
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun rowToSerializableParcel(row: ResultRow): SerializableParcel? {
|
||||||
|
val worldId = row[ParcelsT.world_id]
|
||||||
|
val worldRow = WorldsT.select { WorldsT.id eq worldId }.firstOrNull()
|
||||||
|
?: return null
|
||||||
|
|
||||||
|
val world = SerializableWorld(worldRow[WorldsT.name], worldRow[WorldsT.uid].toUUID())
|
||||||
|
return SerializableParcel(world, Vec2i(row[ParcelsT.px], row[ParcelsT.pz]))
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun rowToParcelData(row: ResultRow) = ParcelDataHolder().apply {
|
||||||
|
owner = ParcelOwner.create(
|
||||||
|
uuid = row[ParcelsT.owner_uuid]?.toUUID(),
|
||||||
|
name = row[ParcelsT.owner_name],
|
||||||
|
time = row[ParcelsT.claim_time]
|
||||||
|
)
|
||||||
|
|
||||||
|
val parcelId = row[ParcelsT.id]
|
||||||
|
AddedLocalT.select { AddedLocalT.parcel_id eq parcelId }.forEach {
|
||||||
|
val uuid = it[AddedLocalT.player_uuid].toUUID()!!
|
||||||
|
val status = if (it[AddedLocalT.allowed_flag]) AddedStatus.ALLOWED else AddedStatus.BANNED
|
||||||
|
setAddedStatus(uuid, status)
|
||||||
|
}
|
||||||
|
|
||||||
|
ParcelOptionsT.select { ParcelOptionsT.parcel_id eq parcelId }.firstOrNull()?.let {
|
||||||
|
allowInteractInputs = it[ParcelOptionsT.interact_inputs]
|
||||||
|
allowInteractInventory = it[ParcelOptionsT.interact_inventory]
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@@ -3,7 +3,7 @@ package io.dico.parcels2.storage
|
|||||||
import io.dico.parcels2.Parcel
|
import io.dico.parcels2.Parcel
|
||||||
import io.dico.parcels2.ParcelWorld
|
import io.dico.parcels2.ParcelWorld
|
||||||
import io.dico.parcels2.Worlds
|
import io.dico.parcels2.Worlds
|
||||||
import io.dico.parcels2.math.Vec2i
|
import io.dico.parcels2.util.Vec2i
|
||||||
import org.bukkit.Bukkit
|
import org.bukkit.Bukkit
|
||||||
import org.bukkit.World
|
import org.bukkit.World
|
||||||
import java.util.*
|
import java.util.*
|
||||||
|
|||||||
@@ -1,5 +1,6 @@
|
|||||||
package io.dico.parcels2.storage
|
package io.dico.parcels2.storage
|
||||||
|
|
||||||
|
import io.dico.parcels2.AddedData
|
||||||
import io.dico.parcels2.Parcel
|
import io.dico.parcels2.Parcel
|
||||||
import io.dico.parcels2.ParcelData
|
import io.dico.parcels2.ParcelData
|
||||||
import io.dico.parcels2.ParcelOwner
|
import io.dico.parcels2.ParcelOwner
|
||||||
@@ -25,6 +26,8 @@ interface Storage {
|
|||||||
|
|
||||||
fun readParcelData(parcelsFor: Sequence<Parcel>, channelCapacity: Int): ReceiveChannel<Pair<Parcel, ParcelData?>>
|
fun readParcelData(parcelsFor: Sequence<Parcel>, channelCapacity: Int): ReceiveChannel<Pair<Parcel, ParcelData?>>
|
||||||
|
|
||||||
|
fun readAllParcelData(channelCapacity: Int): ReceiveChannel<Pair<SerializableParcel, ParcelData?>>
|
||||||
|
|
||||||
fun getOwnedParcels(user: ParcelOwner): Deferred<List<SerializableParcel>>
|
fun getOwnedParcels(user: ParcelOwner): Deferred<List<SerializableParcel>>
|
||||||
|
|
||||||
fun getNumParcels(user: ParcelOwner): Deferred<Int>
|
fun getNumParcels(user: ParcelOwner): Deferred<Int>
|
||||||
@@ -40,6 +43,10 @@ interface Storage {
|
|||||||
|
|
||||||
fun setParcelAllowsInteractInputs(parcel: Parcel, value: Boolean): Job
|
fun setParcelAllowsInteractInputs(parcel: Parcel, value: Boolean): Job
|
||||||
|
|
||||||
|
|
||||||
|
fun readGlobalPlayerStateData(owner: ParcelOwner): Deferred<AddedData?>
|
||||||
|
|
||||||
|
fun setGlobalPlayerState(owner: ParcelOwner, player: UUID, state: Boolean?): Job
|
||||||
}
|
}
|
||||||
|
|
||||||
class StorageWithCoroutineBacking internal constructor(val backing: Backing) : Storage {
|
class StorageWithCoroutineBacking internal constructor(val backing: Backing) : Storage {
|
||||||
@@ -66,9 +73,11 @@ class StorageWithCoroutineBacking internal constructor(val backing: Backing) : S
|
|||||||
|
|
||||||
override fun readParcelData(parcelFor: Parcel) = defer { backing.readParcelData(parcelFor) }
|
override fun readParcelData(parcelFor: Parcel) = defer { backing.readParcelData(parcelFor) }
|
||||||
|
|
||||||
override fun readParcelData(parcelsFor: Sequence<Parcel>, channelCapacity: Int) = produce(asyncDispatcher, capacity = channelCapacity) {
|
override fun readParcelData(parcelsFor: Sequence<Parcel>, channelCapacity: Int) =
|
||||||
with(backing) { produceParcelData(parcelsFor) }
|
produce(asyncDispatcher, capacity = channelCapacity) { with(backing) { produceParcelData(parcelsFor) } }
|
||||||
}
|
|
||||||
|
override fun readAllParcelData(channelCapacity: Int): ReceiveChannel<Pair<SerializableParcel, ParcelData?>> =
|
||||||
|
produce(asyncDispatcher, capacity = channelCapacity) { with(backing) { produceAllParcelData() } }
|
||||||
|
|
||||||
override fun getOwnedParcels(user: ParcelOwner) = defer { backing.getOwnedParcels(user) }
|
override fun getOwnedParcels(user: ParcelOwner) = defer { backing.getOwnedParcels(user) }
|
||||||
|
|
||||||
@@ -83,4 +92,9 @@ class StorageWithCoroutineBacking internal constructor(val backing: Backing) : S
|
|||||||
override fun setParcelAllowsInteractInventory(parcel: Parcel, value: Boolean) = job { backing.setParcelAllowsInteractInventory(parcel, value) }
|
override fun setParcelAllowsInteractInventory(parcel: Parcel, value: Boolean) = job { backing.setParcelAllowsInteractInventory(parcel, value) }
|
||||||
|
|
||||||
override fun setParcelAllowsInteractInputs(parcel: Parcel, value: Boolean) = job { backing.setParcelAllowsInteractInputs(parcel, value) }
|
override fun setParcelAllowsInteractInputs(parcel: Parcel, value: Boolean) = job { backing.setParcelAllowsInteractInputs(parcel, value) }
|
||||||
|
|
||||||
|
|
||||||
|
override fun readGlobalPlayerStateData(owner: ParcelOwner): Deferred<AddedData?> = defer { backing.readGlobalPlayerStateData(owner) }
|
||||||
|
|
||||||
|
override fun setGlobalPlayerState(owner: ParcelOwner, player: UUID, state: Boolean?) = job { backing.setGlobalPlayerState(owner, player, state) }
|
||||||
}
|
}
|
||||||
|
|||||||
+1
-1
@@ -1,4 +1,4 @@
|
|||||||
package io.dico.parcels2.math
|
package io.dico.parcels2.util
|
||||||
|
|
||||||
fun Double.floor(): Int {
|
fun Double.floor(): Int {
|
||||||
val down = toInt()
|
val down = toInt()
|
||||||
+1
-1
@@ -1,4 +1,4 @@
|
|||||||
package io.dico.parcels2.math
|
package io.dico.parcels2.util
|
||||||
|
|
||||||
data class Vec2i(
|
data class Vec2i(
|
||||||
val x: Int,
|
val x: Int,
|
||||||
Reference in New Issue
Block a user