mirror of
https://gitlab.bixilon.de/bixilon/pixlyzer-physics.git
synced 2025-09-22 03:47:50 -04:00
Initial commit
This commit is contained in:
commit
04c3129717
@ -0,0 +1,48 @@
|
|||||||
|
package de.bixilon.pixlyzer.physics
|
||||||
|
|
||||||
|
import de.bixilon.pixlyzer.physics.tests.AbstractTest
|
||||||
|
import de.bixilon.pixlyzer.physics.tests.EmptyTest
|
||||||
|
import de.bixilon.pixlyzer.physics.tests.GravityTest
|
||||||
|
import de.bixilon.pixlyzer.physics.tests.PhysicsTest
|
||||||
|
import de.bixilon.pixlyzer.physics.tests.packet.PacketReceiveTest
|
||||||
|
import java.lang.reflect.Method
|
||||||
|
|
||||||
|
object PhysicsExtractor {
|
||||||
|
val tests = listOf<Class<out AbstractTest>>(
|
||||||
|
EmptyTest::class.java,
|
||||||
|
PacketReceiveTest::class.java,
|
||||||
|
GravityTest::class.java,
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
|
fun prepare(clazz: AbstractTest) {
|
||||||
|
clazz.result = mutableMapOf()
|
||||||
|
clazz.world = clazz.createWorld()
|
||||||
|
clazz.player = clazz.createPlayer(clazz.world)
|
||||||
|
}
|
||||||
|
|
||||||
|
fun run(method: Method, clazz: AbstractTest) {
|
||||||
|
prepare(clazz)
|
||||||
|
method.invoke(clazz)
|
||||||
|
println("Result: ${method.name}: ${clazz.result}")
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
fun start() {
|
||||||
|
for (tests in tests) {
|
||||||
|
val instance = tests.getConstructor().newInstance()
|
||||||
|
|
||||||
|
for (method in tests.declaredMethods) {
|
||||||
|
method.isAccessible = true
|
||||||
|
if (!method.isAnnotationPresent(PhysicsTest::class.java)) {
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
try {
|
||||||
|
run(method, instance)
|
||||||
|
} catch (error: Throwable) {
|
||||||
|
error.printStackTrace()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
110
src/main/kotlin/de/bixilon/pixlyzer/physics/PhysicsUtil.kt
Normal file
110
src/main/kotlin/de/bixilon/pixlyzer/physics/PhysicsUtil.kt
Normal file
@ -0,0 +1,110 @@
|
|||||||
|
package de.bixilon.pixlyzer.physics
|
||||||
|
|
||||||
|
import com.google.common.collect.Queues
|
||||||
|
import com.mojang.authlib.GameProfile
|
||||||
|
import de.bixilon.pixlyzer.EntitySpawner.setDimension
|
||||||
|
import de.bixilon.pixlyzer.physics.abstractions.MinecraftPlayer
|
||||||
|
import de.bixilon.pixlyzer.physics.abstractions.MinecraftWorld
|
||||||
|
import net.minecraft.client.MinecraftClient
|
||||||
|
import net.minecraft.client.input.Input
|
||||||
|
import net.minecraft.client.network.ClientPlayNetworkHandler
|
||||||
|
import net.minecraft.client.network.ClientPlayerEntity
|
||||||
|
import net.minecraft.client.network.PlayerListEntry
|
||||||
|
import net.minecraft.client.option.GameOptions
|
||||||
|
import net.minecraft.client.option.SimpleOption
|
||||||
|
import net.minecraft.client.recipebook.ClientRecipeBook
|
||||||
|
import net.minecraft.client.tutorial.TutorialManager
|
||||||
|
import net.minecraft.client.world.ClientChunkManager
|
||||||
|
import net.minecraft.client.world.ClientEntityManager
|
||||||
|
import net.minecraft.client.world.ClientWorld
|
||||||
|
import net.minecraft.entity.Entity
|
||||||
|
import net.minecraft.network.ClientConnection
|
||||||
|
import net.minecraft.network.NetworkSide
|
||||||
|
import net.minecraft.scoreboard.Scoreboard
|
||||||
|
import net.minecraft.stat.StatHandler
|
||||||
|
import net.minecraft.util.math.BlockPos
|
||||||
|
import net.minecraft.util.profiler.DummyProfiler
|
||||||
|
import net.minecraft.util.registry.RegistryEntry
|
||||||
|
import net.minecraft.world.Difficulty
|
||||||
|
import net.minecraft.world.biome.Biome
|
||||||
|
import net.minecraft.world.biome.source.BiomeAccess
|
||||||
|
import net.minecraft.world.border.WorldBorder
|
||||||
|
import net.minecraft.world.dimension.DimensionType
|
||||||
|
import org.objenesis.ObjenesisStd
|
||||||
|
import java.util.*
|
||||||
|
import java.util.function.Supplier
|
||||||
|
|
||||||
|
object PhysicsUtil {
|
||||||
|
private val OBJENESIS = ObjenesisStd()
|
||||||
|
|
||||||
|
fun createChunkManager(native: ClientWorld): ClientChunkManager {
|
||||||
|
val chunkManager = OBJENESIS.newInstance(ClientChunkManager::class.java)
|
||||||
|
chunkManager.world = native
|
||||||
|
chunkManager.chunks = chunkManager.ClientChunkMap(ClientChunkManager.getChunkMapRadius(3))
|
||||||
|
|
||||||
|
|
||||||
|
return chunkManager
|
||||||
|
}
|
||||||
|
|
||||||
|
fun createWorld(): MinecraftWorld {
|
||||||
|
val native = OBJENESIS.newInstance(ClientWorld::class.java)
|
||||||
|
native.chunkManager = createChunkManager(native)
|
||||||
|
|
||||||
|
val properties = ClientWorld.Properties(Difficulty.EASY, false, false)
|
||||||
|
native.properties = properties
|
||||||
|
native.clientWorldProperties = ClientWorld.Properties(properties.difficulty, properties.isHardcore, properties.flatWorld)
|
||||||
|
native.setSpawnPos(BlockPos(0, 0, 0), 0.0f)
|
||||||
|
|
||||||
|
native.scoreboard = Scoreboard()
|
||||||
|
native.border = WorldBorder()
|
||||||
|
native.profiler = Supplier { DummyProfiler.INSTANCE }
|
||||||
|
native.setDimension()
|
||||||
|
native.entityManager = ClientEntityManager(Entity::class.java, native.ClientEntityHandler())
|
||||||
|
|
||||||
|
native.biomeAccess = BiomeAccess(BiomeAccess.Storage { biomeX, biomeY, biomeZ -> return@Storage RegistryEntry.Direct<Biome>(null) }, 0L)
|
||||||
|
|
||||||
|
return MinecraftWorld(native)
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun createNetworkHandler(client: MinecraftClient): ClientPlayNetworkHandler {
|
||||||
|
val handler = OBJENESIS.newInstance(ClientPlayNetworkHandler::class.java)
|
||||||
|
handler.profile = GameProfile(UUID(1L, 1L), "physics")
|
||||||
|
handler.client = client
|
||||||
|
handler.connection = ClientConnection(NetworkSide.CLIENTBOUND)
|
||||||
|
return handler
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun createGameOptions(): GameOptions? {
|
||||||
|
val options = OBJENESIS.newInstance(GameOptions::class.java)
|
||||||
|
options.autoJump = SimpleOption.ofBoolean("", false)
|
||||||
|
|
||||||
|
return options
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun createMinecraftClient(): MinecraftClient {
|
||||||
|
val client = OBJENESIS.newInstance(MinecraftClient::class.java)
|
||||||
|
|
||||||
|
client.tasks = Queues.newConcurrentLinkedQueue()
|
||||||
|
client.thread = Thread.currentThread()
|
||||||
|
client.options = createGameOptions()
|
||||||
|
client.tutorialManager = TutorialManager(client, client.options )
|
||||||
|
|
||||||
|
return client
|
||||||
|
}
|
||||||
|
|
||||||
|
fun createPlayer(world: MinecraftWorld): MinecraftPlayer {
|
||||||
|
val client = createMinecraftClient()
|
||||||
|
val networkHandler = createNetworkHandler(client)
|
||||||
|
val native = ClientPlayerEntity(client, world.level, networkHandler, StatHandler(), ClientRecipeBook(), false, false)
|
||||||
|
|
||||||
|
client.player = native
|
||||||
|
native.playerListEntry = PlayerListEntry(networkHandler.profile, false)
|
||||||
|
native.input = Input()
|
||||||
|
native.shoulderEntityLeft = null
|
||||||
|
native.shoulderEntityRight = null
|
||||||
|
|
||||||
|
client.cameraEntity = native
|
||||||
|
|
||||||
|
return MinecraftPlayer(native)
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,45 @@
|
|||||||
|
package de.bixilon.pixlyzer.physics.abstractions
|
||||||
|
|
||||||
|
import net.minecraft.client.input.Input
|
||||||
|
import net.minecraft.client.network.ClientPlayerEntity
|
||||||
|
import net.minecraft.network.Packet
|
||||||
|
import net.minecraft.network.listener.ClientPlayPacketListener
|
||||||
|
import net.minecraft.util.math.Vec3d
|
||||||
|
|
||||||
|
class MinecraftPlayer(
|
||||||
|
val native: ClientPlayerEntity,
|
||||||
|
) {
|
||||||
|
|
||||||
|
fun handlePacket(packet: Packet<ClientPlayPacketListener>) {
|
||||||
|
packet.apply(native.networkHandler)
|
||||||
|
}
|
||||||
|
|
||||||
|
fun tick(count:Int=1) {
|
||||||
|
for(i in 0 until count) {
|
||||||
|
native.tick()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fun teleport(x: Double, y: Double, z: Double) {
|
||||||
|
native.setPosition(Vec3d(x, y, z))
|
||||||
|
}
|
||||||
|
|
||||||
|
fun setKeys(
|
||||||
|
forwards: Boolean = false,
|
||||||
|
backwards: Boolean = false,
|
||||||
|
right: Boolean = false,
|
||||||
|
left: Boolean = false,
|
||||||
|
jump: Boolean = false,
|
||||||
|
sneak: Boolean = false,
|
||||||
|
) {
|
||||||
|
val input = Input()
|
||||||
|
input.pressingForward = forwards
|
||||||
|
input.pressingBack = backwards
|
||||||
|
input.pressingRight = right
|
||||||
|
input.pressingLeft = left
|
||||||
|
input.jumping = jump
|
||||||
|
input.sneaking = sneak
|
||||||
|
|
||||||
|
native.input = input
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,13 @@
|
|||||||
|
package de.bixilon.pixlyzer.physics.abstractions
|
||||||
|
|
||||||
|
import net.minecraft.block.BlockState
|
||||||
|
import net.minecraft.client.world.ClientWorld
|
||||||
|
import net.minecraft.util.math.BlockPos
|
||||||
|
|
||||||
|
class MinecraftWorld(
|
||||||
|
val level: ClientWorld,
|
||||||
|
) {
|
||||||
|
fun set(x: Int, y: Int, z: Int, value: BlockState?) {
|
||||||
|
level.setBlockState(BlockPos(x, y, z), value)
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,25 @@
|
|||||||
|
package de.bixilon.pixlyzer.physics.tests
|
||||||
|
|
||||||
|
import de.bixilon.kutil.cast.CastUtil.unsafeNull
|
||||||
|
import de.bixilon.pixlyzer.physics.PhysicsUtil
|
||||||
|
import de.bixilon.pixlyzer.physics.abstractions.MinecraftPlayer
|
||||||
|
import de.bixilon.pixlyzer.physics.abstractions.MinecraftWorld
|
||||||
|
|
||||||
|
abstract class AbstractTest {
|
||||||
|
open val skip: Boolean = false
|
||||||
|
var world: MinecraftWorld = unsafeNull()
|
||||||
|
var player: MinecraftPlayer = unsafeNull()
|
||||||
|
var result: MutableMap<String, Any?> = mutableMapOf()
|
||||||
|
|
||||||
|
open fun createWorld(): MinecraftWorld = PhysicsUtil.createWorld()
|
||||||
|
open fun createPlayer(world: MinecraftWorld): MinecraftPlayer = PhysicsUtil.createPlayer(world)
|
||||||
|
|
||||||
|
|
||||||
|
protected fun storeBasic() {
|
||||||
|
result["x"] = player.native.x
|
||||||
|
result["y"] = player.native.y
|
||||||
|
result["z"] = player.native.z
|
||||||
|
result["yaw"] = player.native.yaw
|
||||||
|
result["pitch"] = player.native.pitch
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,19 @@
|
|||||||
|
package de.bixilon.pixlyzer.physics.tests
|
||||||
|
|
||||||
|
class EmptyTest : AbstractTest() {
|
||||||
|
|
||||||
|
@PhysicsTest("initial_position")
|
||||||
|
fun testInitialPosition() {
|
||||||
|
result["x"] = player.native.x
|
||||||
|
result["y"] = player.native.y
|
||||||
|
result["z"] = player.native.z
|
||||||
|
}
|
||||||
|
|
||||||
|
@PhysicsTest("empty_teleport")
|
||||||
|
fun testTeleporting() {
|
||||||
|
player.teleport(123.0, 535.0, 19.0)
|
||||||
|
result["x"] = player.native.x
|
||||||
|
result["y"] = player.native.y
|
||||||
|
result["z"] = player.native.z
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,96 @@
|
|||||||
|
package de.bixilon.pixlyzer.physics.tests
|
||||||
|
|
||||||
|
class GravityTest : AbstractTest() {
|
||||||
|
|
||||||
|
@PhysicsTest("blank_falling_1")
|
||||||
|
fun blankFalling1() {
|
||||||
|
player.teleport(45.00, 178.0, 13.00)
|
||||||
|
player.tick()
|
||||||
|
storeBasic()
|
||||||
|
}
|
||||||
|
|
||||||
|
@PhysicsTest("blank_falling_2")
|
||||||
|
fun blankFalling2() {
|
||||||
|
player.teleport(45.00, 178.0, 13.00)
|
||||||
|
player.tick(2)
|
||||||
|
storeBasic()
|
||||||
|
}
|
||||||
|
|
||||||
|
@PhysicsTest("blank_falling_3")
|
||||||
|
fun blankFalling3() {
|
||||||
|
player.teleport(45.00, 178.0, 13.00)
|
||||||
|
player.tick(3)
|
||||||
|
storeBasic()
|
||||||
|
}
|
||||||
|
|
||||||
|
@PhysicsTest("blank_falling_90")
|
||||||
|
fun blankFalling90() {
|
||||||
|
player.teleport(45.00, 178.0, 13.00)
|
||||||
|
player.tick(90)
|
||||||
|
storeBasic()
|
||||||
|
}
|
||||||
|
|
||||||
|
@PhysicsTest("forwards_falling_1")
|
||||||
|
fun forwardFalling1() {
|
||||||
|
player.teleport(45.00, 178.0, 13.00)
|
||||||
|
player.setKeys(forwards = true)
|
||||||
|
player.tick()
|
||||||
|
storeBasic()
|
||||||
|
}
|
||||||
|
|
||||||
|
@PhysicsTest("forwards_falling_2")
|
||||||
|
fun forwardFalling2() {
|
||||||
|
player.teleport(45.00, 178.0, 13.00)
|
||||||
|
player.setKeys(forwards = true)
|
||||||
|
player.tick(2)
|
||||||
|
storeBasic()
|
||||||
|
}
|
||||||
|
|
||||||
|
@PhysicsTest("forwards_falling_2")
|
||||||
|
fun forwardFalling3() {
|
||||||
|
player.teleport(45.00, 178.0, 13.00)
|
||||||
|
player.setKeys(forwards = true)
|
||||||
|
player.tick(3)
|
||||||
|
storeBasic()
|
||||||
|
}
|
||||||
|
|
||||||
|
@PhysicsTest("forwards_falling_90")
|
||||||
|
fun forwardFalling90() {
|
||||||
|
player.teleport(45.00, 178.0, 13.00)
|
||||||
|
player.setKeys(forwards = true)
|
||||||
|
player.tick(90)
|
||||||
|
storeBasic()
|
||||||
|
}
|
||||||
|
|
||||||
|
@PhysicsTest("backwards_falling_1")
|
||||||
|
fun backwardsFalling1() {
|
||||||
|
player.teleport(45.00, 178.0, 13.00)
|
||||||
|
player.setKeys(backwards = true)
|
||||||
|
player.tick()
|
||||||
|
storeBasic()
|
||||||
|
}
|
||||||
|
|
||||||
|
@PhysicsTest("backwards_falling_2")
|
||||||
|
fun backwardsFalling2() {
|
||||||
|
player.teleport(45.00, 178.0, 13.00)
|
||||||
|
player.setKeys(backwards = true)
|
||||||
|
player.tick(2)
|
||||||
|
storeBasic()
|
||||||
|
}
|
||||||
|
|
||||||
|
@PhysicsTest("backwards_falling_2")
|
||||||
|
fun backwardsFalling3() {
|
||||||
|
player.teleport(45.00, 178.0, 13.00)
|
||||||
|
player.setKeys(backwards = true)
|
||||||
|
player.tick(3)
|
||||||
|
storeBasic()
|
||||||
|
}
|
||||||
|
|
||||||
|
@PhysicsTest("backwards_falling_90")
|
||||||
|
fun backwardsFalling90() {
|
||||||
|
player.teleport(45.00, 178.0, 13.00)
|
||||||
|
player.setKeys(backwards = true)
|
||||||
|
player.tick(90)
|
||||||
|
storeBasic()
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,3 @@
|
|||||||
|
package de.bixilon.pixlyzer.physics.tests
|
||||||
|
|
||||||
|
annotation class PhysicsTest(val id: String)
|
@ -0,0 +1,58 @@
|
|||||||
|
package de.bixilon.pixlyzer.physics.tests.packet
|
||||||
|
|
||||||
|
import de.bixilon.pixlyzer.physics.tests.AbstractTest
|
||||||
|
import de.bixilon.pixlyzer.physics.tests.PhysicsTest
|
||||||
|
import net.minecraft.network.packet.s2c.play.PlayerPositionLookS2CPacket
|
||||||
|
import net.minecraft.network.packet.s2c.play.PlayerPositionLookS2CPacket.Flag
|
||||||
|
|
||||||
|
class PacketReceiveTest : AbstractTest() {
|
||||||
|
|
||||||
|
private fun createPacket(x: Double, xRelative: Boolean, y: Double, yRelative: Boolean, z: Double, zRelative: Boolean, yaw: Float, yawRelative: Boolean, pitch: Float, pitchRelative: Boolean, dismount: Boolean): PlayerPositionLookS2CPacket {
|
||||||
|
val flags: MutableSet<Flag> = mutableSetOf()
|
||||||
|
if (xRelative) {
|
||||||
|
flags += Flag.X
|
||||||
|
}
|
||||||
|
if (yRelative) {
|
||||||
|
flags += Flag.Y
|
||||||
|
}
|
||||||
|
if (zRelative) {
|
||||||
|
flags += Flag.Z
|
||||||
|
}
|
||||||
|
if (yawRelative) {
|
||||||
|
flags += Flag.Y_ROT
|
||||||
|
}
|
||||||
|
if (pitchRelative) {
|
||||||
|
flags += Flag.X_ROT
|
||||||
|
}
|
||||||
|
|
||||||
|
return PlayerPositionLookS2CPacket(x, y, z, yaw, pitch, flags, 0, dismount)
|
||||||
|
}
|
||||||
|
|
||||||
|
@PhysicsTest("receive_empty")
|
||||||
|
fun testEmpty() {
|
||||||
|
val packet = createPacket(0.0, true, 0.0, true, 0.0, true, 0.0f, true, 0.0f, true, false)
|
||||||
|
player.handlePacket(packet)
|
||||||
|
storeBasic()
|
||||||
|
result["mount"] = player.native.jumpingMount != null
|
||||||
|
}
|
||||||
|
|
||||||
|
@PhysicsTest("receive_relative")
|
||||||
|
fun testRelative() {
|
||||||
|
player.teleport(623.0, 71.0, 782.0)
|
||||||
|
val packet = createPacket(14.0, true, 87.0, true, 91.0, true, 9.0f, true, 92.0f, true, false)
|
||||||
|
|
||||||
|
player.handlePacket(packet)
|
||||||
|
storeBasic()
|
||||||
|
result["mount"] = player.native.jumpingMount != null
|
||||||
|
}
|
||||||
|
|
||||||
|
@PhysicsTest("receive_absolute")
|
||||||
|
fun testAbsolut() {
|
||||||
|
player.teleport(623.0, 71.0, 782.0)
|
||||||
|
val packet = createPacket(14.0, false, 87.0, false, 91.0, false, 9.0f, false, 92.0f, false, false)
|
||||||
|
|
||||||
|
player.handlePacket(packet)
|
||||||
|
storeBasic()
|
||||||
|
result["mount"] = player.native.jumpingMount != null
|
||||||
|
}
|
||||||
|
}
|
Loading…
x
Reference in New Issue
Block a user