Initial commit

This commit is contained in:
Bixilon 2022-11-12 20:15:02 +01:00
commit 04c3129717
No known key found for this signature in database
GPG Key ID: 5CAD791931B09AC4
9 changed files with 417 additions and 0 deletions

View File

@ -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()
}
}
}
}
}

View 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)
}
}

View File

@ -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
}
}

View File

@ -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)
}
}

View File

@ -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
}
}

View File

@ -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
}
}

View File

@ -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()
}
}

View File

@ -0,0 +1,3 @@
package de.bixilon.pixlyzer.physics.tests
annotation class PhysicsTest(val id: String)

View File

@ -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
}
}