Skip to content
This repository was archived by the owner on Nov 28, 2025. It is now read-only.
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
33 changes: 29 additions & 4 deletions src/main/kotlin/Main.kt
Original file line number Diff line number Diff line change
@@ -1,14 +1,24 @@
import io.github.dockyardmc.DockyardServer
import io.github.dockyardmc.commands.Commands
import io.github.dockyardmc.entity.EntityManager.despawnEntity
import io.github.dockyardmc.entity.EntityManager.spawnEntity
import io.github.dockyardmc.entity.ItemDropEntity
import io.github.dockyardmc.events.Events
import io.github.dockyardmc.events.PlayerJoinEvent
import io.github.dockyardmc.events.PlayerRightClickWithItemEvent
import io.github.dockyardmc.inventory.give
import io.github.dockyardmc.item.ItemStack
import io.github.dockyardmc.maths.randomFloat
import io.github.dockyardmc.maths.vectors.Vector3d
import io.github.dockyardmc.maths.vectors.Vector3f
import io.github.dockyardmc.maths.velocity.VelocitySimulation
import io.github.dockyardmc.player.systems.GameMode
import io.github.dockyardmc.registry.Items
import io.github.dockyardmc.ui.TestScreen
import io.github.dockyardmc.registry.registries.ItemRegistry
import io.github.dockyardmc.scheduler.runLaterAsync
import io.github.dockyardmc.scheduler.runnables.ticks
import io.github.dockyardmc.utils.DebugSidebar
import kotlin.time.Duration.Companion.seconds

fun main() {
val server = DockyardServer {
Expand All @@ -30,11 +40,26 @@ fun main() {
event.player.setVelocity(Vector3d(0, 20.5, 0))
}

Commands.add("/ui") {
Commands.add("/test") {
execute { ctx ->
val player = ctx.getPlayerOrThrow()
val screen = TestScreen()
screen.open(player)
player.world.scheduler.repeat(5, 1.ticks) {
repeat(3) {
val physics = VelocitySimulation(player.location.add(0.0, 0.5, 0.0), Vector3f(randomFloat(-0.50f, 0.50f), 0.5f, randomFloat(-0.50f, 0.50f)), true)
val entity = player.world.spawnEntity(ItemDropEntity(player.location, ItemStack(ItemRegistry.items.values.random()))) as ItemDropEntity

physics.onTick.subscribe { location ->
entity.teleport(location)
}

physics.start()

runLaterAsync(5.seconds) {
physics.dispose()
player.world.despawnEntity(entity)
}
}
}
}
}

Expand Down
1 change: 1 addition & 0 deletions src/main/kotlin/io/github/dockyardmc/entity/Entity.kt
Original file line number Diff line number Diff line change
Expand Up @@ -70,6 +70,7 @@ abstract class Entity(open var location: Location, open var world: World) : Disp
val hasNoGravity: Bindable<Boolean> = bindablePool.provideBindable(true)
val isSilent: Bindable<Boolean> = bindablePool.provideBindable(false)
val stuckArrows: Bindable<Int> = bindablePool.provideBindable(0)
var gravityTickCount = 0

val potionEffects: BindableMap<PotionEffect, AppliedPotionEffect> = bindablePool.provideBindableMap()
val isInvisible: Bindable<Boolean> = bindablePool.provideBindable(false)
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
package io.github.dockyardmc.entity.handlers

import io.github.dockyardmc.entity.Entity

class EntityMovementHandler(override val entity: Entity) : TickableEntityHandler {

override fun tick() {
entity.gravityTickCount = if (entity.isOnGround) 0 else entity.gravityTickCount + 1
}
}
2 changes: 1 addition & 1 deletion src/main/kotlin/io/github/dockyardmc/location/Location.kt
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@ import io.github.dockyardmc.world.chunk.Chunk
import io.netty.buffer.ByteBuf
import kotlin.math.*

class Location(
data class Location(
var x: Double,
var y: Double,
var z: Double,
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,101 @@
package io.github.dockyardmc.maths.velocity

import cz.lukynka.bindables.BindableDispatcher
import io.github.dockyardmc.location.Location
import io.github.dockyardmc.maths.vectors.Vector3f
import io.github.dockyardmc.scheduler.runnables.ticks
import io.github.dockyardmc.utils.Disposable
import io.github.dockyardmc.world.World

class VelocitySimulation(
startLocation: Location,
initialVelocity: Vector3f,
val handlesCollision: Boolean = false,
val floorBouncinessFactor: Float = 0.4f,

) : Disposable {

private val gravity: Vector3f = Vector3f(0f, -0.05f, 0f)
private val airFriction: Vector3f = Vector3f(0.98f)
private val groundFriction: Vector3f = Vector3f(0.1f, 0.98f, 0.1f)

private var currentLocation: Location = startLocation
private var currentVelocity: Vector3f = initialVelocity

val onTick: BindableDispatcher<Location> = BindableDispatcher()
private var running: Boolean = false

private val schedulerTask = startLocation.world.scheduler.runRepeating(1.ticks) {
if (!running) return@runRepeating

var friction = airFriction
if (currentLocation.subtract(0.0, 0.05, 0.0).block.registryBlock.isSolid) {
friction = groundFriction
}

currentVelocity = currentVelocity + gravity
currentVelocity = currentVelocity * friction

val newLocXOnly = newLocation(currentVelocity.x, 0f, 0f, currentLocation.yaw, currentLocation.pitch, currentLocation.world)
val newLocYOnly = newLocation(0f, currentVelocity.y, 0f, currentLocation.yaw, currentLocation.pitch, currentLocation.world)
val newLocZOnly = newLocation(0f, 0f, currentVelocity.z, currentLocation.yaw, currentLocation.pitch, currentLocation.world)

if (newLocXOnly.block.registryBlock.isSolid) {
currentVelocity.x = 0f
}
if (newLocYOnly.block.registryBlock.isSolid) {
currentVelocity.y = if (floorBouncinessFactor == -1f) 0f else (currentVelocity.y * -1) - 0.4f
}
if (newLocZOnly.block.registryBlock.isSolid) {
currentVelocity.z = 0f
}

val newLocFull = newLocation(currentVelocity.x, currentVelocity.y, currentVelocity.z, currentLocation.yaw, currentLocation.pitch, currentLocation.world)
if (handlesCollision && newLocFull.block.registryBlock.isSolid) {
currentVelocity = Vector3f(0f, 0f, 0f)
return@runRepeating
}

if (!handlesCollision || !newLocFull.block.registryBlock.isSolid) {
currentLocation = Location(
currentLocation.x + currentVelocity.x,
currentLocation.y + currentVelocity.y,
currentLocation.z + currentVelocity.z,
currentLocation.yaw,
currentLocation.pitch,
currentLocation.world
)
}

if (currentVelocity.isZero) {
dispose()
return@runRepeating
}

onTick.dispatch(currentLocation)
}

fun start() {
running = true
}

fun stop() {
running = false
}

override fun dispose() {
schedulerTask.cancel()
onTick.dispose()
}

private fun newLocation(newX: Float, newY: Float, newZ: Float, yaw: Float, pitch: Float, world: World): Location {
return Location(
currentLocation.x + newX,
currentLocation.y + newY,
currentLocation.z + newZ,
yaw,
pitch,
world
)
}
}
Loading