mirror of
https://gitlab.bixilon.de/bixilon/pixlyzer-physics.git
synced 2025-09-20 10:14:17 -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