mirror of
https://gitlab.bixilon.de/bixilon/minosoft.git
synced 2025-09-13 17:37:58 -04:00
yggdrasil implementation, player data: read player properties correct
This commit is contained in:
parent
b55d24ca89
commit
d0307e9fb2
5
pom.xml
5
pom.xml
@ -444,5 +444,10 @@
|
|||||||
<artifactId>reflections</artifactId>
|
<artifactId>reflections</artifactId>
|
||||||
<version>0.10.2</version>
|
<version>0.10.2</version>
|
||||||
</dependency>
|
</dependency>
|
||||||
|
<dependency>
|
||||||
|
<groupId>com.github.luben</groupId>
|
||||||
|
<artifactId>zstd-jni</artifactId>
|
||||||
|
<version>1.5.0-4</version>
|
||||||
|
</dependency>
|
||||||
</dependencies>
|
</dependencies>
|
||||||
</project>
|
</project>
|
||||||
|
@ -122,6 +122,8 @@ object Minosoft {
|
|||||||
|
|
||||||
Util.forceClassInit(Eros::class.java)
|
Util.forceClassInit(Eros::class.java)
|
||||||
}
|
}
|
||||||
|
taskWorker += Task(identifier = StartupTasks.LOAD_YGGDRASIL, executor = { YggdrasilUtil.load() })
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
taskWorker.work(START_UP_LATCH)
|
taskWorker.work(START_UP_LATCH)
|
||||||
|
@ -19,7 +19,7 @@ import de.bixilon.minosoft.data.entities.Poses
|
|||||||
import de.bixilon.minosoft.data.entities.entities.EntityMetaDataFunction
|
import de.bixilon.minosoft.data.entities.entities.EntityMetaDataFunction
|
||||||
import de.bixilon.minosoft.data.entities.entities.LivingEntity
|
import de.bixilon.minosoft.data.entities.entities.LivingEntity
|
||||||
import de.bixilon.minosoft.data.player.Arms
|
import de.bixilon.minosoft.data.player.Arms
|
||||||
import de.bixilon.minosoft.data.player.PlayerProperty
|
import de.bixilon.minosoft.data.player.properties.PlayerProperties
|
||||||
import de.bixilon.minosoft.data.player.tab.TabListItem
|
import de.bixilon.minosoft.data.player.tab.TabListItem
|
||||||
import de.bixilon.minosoft.data.registries.entities.EntityType
|
import de.bixilon.minosoft.data.registries.entities.EntityType
|
||||||
import de.bixilon.minosoft.data.world.World
|
import de.bixilon.minosoft.data.world.World
|
||||||
@ -35,7 +35,7 @@ abstract class PlayerEntity(
|
|||||||
position: Vec3d = Vec3d.EMPTY,
|
position: Vec3d = Vec3d.EMPTY,
|
||||||
rotation: EntityRotation = EntityRotation(0.0, 0.0),
|
rotation: EntityRotation = EntityRotation(0.0, 0.0),
|
||||||
name: String = "TBA",
|
name: String = "TBA",
|
||||||
properties: Map<String, PlayerProperty> = mapOf(),
|
properties: PlayerProperties = PlayerProperties(),
|
||||||
var tabListItem: TabListItem = TabListItem(name = name, gamemode = Gamemodes.SURVIVAL, properties = properties),
|
var tabListItem: TabListItem = TabListItem(name = name, gamemode = Gamemodes.SURVIVAL, properties = properties),
|
||||||
) : LivingEntity(connection, entityType, position, rotation) {
|
) : LivingEntity(connection, entityType, position, rotation) {
|
||||||
override val dimensions: Vec2
|
override val dimensions: Vec2
|
||||||
|
@ -15,7 +15,7 @@ package de.bixilon.minosoft.data.entities.entities.player
|
|||||||
|
|
||||||
import de.bixilon.minosoft.data.abilities.Gamemodes
|
import de.bixilon.minosoft.data.abilities.Gamemodes
|
||||||
import de.bixilon.minosoft.data.entities.EntityRotation
|
import de.bixilon.minosoft.data.entities.EntityRotation
|
||||||
import de.bixilon.minosoft.data.player.PlayerProperty
|
import de.bixilon.minosoft.data.player.properties.PlayerProperties
|
||||||
import de.bixilon.minosoft.data.player.tab.TabListItem
|
import de.bixilon.minosoft.data.player.tab.TabListItem
|
||||||
import de.bixilon.minosoft.data.registries.ResourceLocation
|
import de.bixilon.minosoft.data.registries.ResourceLocation
|
||||||
import de.bixilon.minosoft.data.registries.entities.EntityFactory
|
import de.bixilon.minosoft.data.registries.entities.EntityFactory
|
||||||
@ -30,7 +30,7 @@ class RemotePlayerEntity(
|
|||||||
position: Vec3d = Vec3d.EMPTY,
|
position: Vec3d = Vec3d.EMPTY,
|
||||||
rotation: EntityRotation = EntityRotation(0.0, 0.0),
|
rotation: EntityRotation = EntityRotation(0.0, 0.0),
|
||||||
name: String = "TBA",
|
name: String = "TBA",
|
||||||
properties: Map<String, PlayerProperty> = mapOf(),
|
properties: PlayerProperties = PlayerProperties(),
|
||||||
tabListItem: TabListItem = TabListItem(name = name, gamemode = Gamemodes.SURVIVAL, properties = properties),
|
tabListItem: TabListItem = TabListItem(name = name, gamemode = Gamemodes.SURVIVAL, properties = properties),
|
||||||
) : PlayerEntity(connection, entityType, position, rotation, name, properties, tabListItem) {
|
) : PlayerEntity(connection, entityType, position, rotation, name, properties, tabListItem) {
|
||||||
|
|
||||||
|
@ -1,26 +0,0 @@
|
|||||||
/*
|
|
||||||
* Minosoft
|
|
||||||
* Copyright (C) 2020 Moritz Zwerger
|
|
||||||
*
|
|
||||||
* This program is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version.
|
|
||||||
*
|
|
||||||
* This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.
|
|
||||||
*
|
|
||||||
* You should have received a copy of the GNU General Public License along with this program. If not, see <https://www.gnu.org/licenses/>.
|
|
||||||
*
|
|
||||||
* This software is not affiliated with Mojang AB, the original developer of Minecraft.
|
|
||||||
*/
|
|
||||||
package de.bixilon.minosoft.data.player
|
|
||||||
|
|
||||||
class PlayerProperty(
|
|
||||||
val key: String,
|
|
||||||
val value: String,
|
|
||||||
val signature: String? = null,
|
|
||||||
) {
|
|
||||||
val isSigned: Boolean
|
|
||||||
get() = signature != null // ToDo check signature
|
|
||||||
|
|
||||||
override fun toString(): String {
|
|
||||||
return "$key: $value"
|
|
||||||
}
|
|
||||||
}
|
|
@ -0,0 +1,7 @@
|
|||||||
|
package de.bixilon.minosoft.data.player.properties
|
||||||
|
|
||||||
|
import de.bixilon.minosoft.data.player.properties.textures.PlayerTextures
|
||||||
|
|
||||||
|
class PlayerProperties(
|
||||||
|
val textures: PlayerTextures? = null,
|
||||||
|
)
|
@ -0,0 +1,29 @@
|
|||||||
|
package de.bixilon.minosoft.data.player.properties.textures
|
||||||
|
|
||||||
|
import de.bixilon.minosoft.util.KUtil.check
|
||||||
|
import java.net.URL
|
||||||
|
|
||||||
|
open class PlayerTexture(
|
||||||
|
val url: URL,
|
||||||
|
) {
|
||||||
|
init {
|
||||||
|
url.check()
|
||||||
|
|
||||||
|
check(urlMatches(url, ALLOWED_DOMAINS) && !urlMatches(url, BLOCKED_DOMAINS)) { "URL hostname is not allowed!" }
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
companion object {
|
||||||
|
private val ALLOWED_DOMAINS = arrayOf(".minecraft.net", ".mojang.com")
|
||||||
|
private val BLOCKED_DOMAINS = arrayOf("bugs.mojang.com", "education.minecraft.net", "feedback.minecraft.net")
|
||||||
|
|
||||||
|
private fun urlMatches(url: URL, domains: Array<String>): Boolean {
|
||||||
|
for (checkURL in domains) {
|
||||||
|
if (url.host.endsWith(checkURL)) {
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,38 @@
|
|||||||
|
package de.bixilon.minosoft.data.player.properties.textures
|
||||||
|
|
||||||
|
import com.fasterxml.jackson.module.kotlin.convertValue
|
||||||
|
import de.bixilon.minosoft.util.KUtil.toLong
|
||||||
|
import de.bixilon.minosoft.util.Util
|
||||||
|
import de.bixilon.minosoft.util.YggdrasilUtil
|
||||||
|
import de.bixilon.minosoft.util.json.Jackson
|
||||||
|
import de.bixilon.minosoft.util.nbt.tag.NBTUtil.compoundCast
|
||||||
|
import java.util.*
|
||||||
|
|
||||||
|
class PlayerTextures(
|
||||||
|
val name: String?,
|
||||||
|
val uuid: UUID?,
|
||||||
|
val date: Date?,
|
||||||
|
val skin: SkinPlayerTexture?,
|
||||||
|
val cape: PlayerTexture?,
|
||||||
|
val elytra: PlayerTexture?,
|
||||||
|
) {
|
||||||
|
|
||||||
|
companion object {
|
||||||
|
fun of(encoded: String, signature: String): PlayerTextures {
|
||||||
|
check(YggdrasilUtil.verify(encoded, signature)) { "Texture signature is invalid!" }
|
||||||
|
|
||||||
|
val json: Map<String, Any> = Jackson.MAPPER.readValue(Base64.getDecoder().decode(encoded), Jackson.JSON_MAP_TYPE)
|
||||||
|
|
||||||
|
// Data also contains `signatureRequired`
|
||||||
|
val textures = json["textures"]?.compoundCast()
|
||||||
|
return PlayerTextures(
|
||||||
|
name = json["profileName"]?.toString(),
|
||||||
|
uuid = json["profileId"]?.toString()?.let { Util.getUUIDFromString(it) },
|
||||||
|
date = json["timestamp"]?.toLong()?.let { Date(it) },
|
||||||
|
skin = textures?.get("SKIN")?.compoundCast()?.let { return@let Jackson.MAPPER.convertValue(it) },
|
||||||
|
cape = textures?.get("CAPE")?.compoundCast()?.let { return@let Jackson.MAPPER.convertValue(it) },
|
||||||
|
elytra = textures?.get("ELYTRA")?.compoundCast()?.let { return@let Jackson.MAPPER.convertValue(it) },
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,9 @@
|
|||||||
|
package de.bixilon.minosoft.data.player.properties.textures
|
||||||
|
|
||||||
|
import de.bixilon.minosoft.data.player.properties.textures.metadata.SkinMetadata
|
||||||
|
import java.net.URL
|
||||||
|
|
||||||
|
class SkinPlayerTexture(
|
||||||
|
url: URL,
|
||||||
|
val metadata: SkinMetadata = SkinMetadata(),
|
||||||
|
) : PlayerTexture(url = url)
|
@ -0,0 +1,5 @@
|
|||||||
|
package de.bixilon.minosoft.data.player.properties.textures.metadata
|
||||||
|
|
||||||
|
data class SkinMetadata(
|
||||||
|
val model: SkinModel = SkinModel.NORMAL,
|
||||||
|
)
|
@ -0,0 +1,7 @@
|
|||||||
|
package de.bixilon.minosoft.data.player.properties.textures.metadata
|
||||||
|
|
||||||
|
enum class SkinModel {
|
||||||
|
SLIM,
|
||||||
|
NORMAL,
|
||||||
|
;
|
||||||
|
}
|
@ -14,7 +14,7 @@
|
|||||||
package de.bixilon.minosoft.data.player.tab
|
package de.bixilon.minosoft.data.player.tab
|
||||||
|
|
||||||
import de.bixilon.minosoft.data.abilities.Gamemodes
|
import de.bixilon.minosoft.data.abilities.Gamemodes
|
||||||
import de.bixilon.minosoft.data.player.PlayerProperty
|
import de.bixilon.minosoft.data.player.properties.PlayerProperties
|
||||||
import de.bixilon.minosoft.data.scoreboard.Team
|
import de.bixilon.minosoft.data.scoreboard.Team
|
||||||
import de.bixilon.minosoft.data.text.ChatComponent
|
import de.bixilon.minosoft.data.text.ChatComponent
|
||||||
import de.bixilon.minosoft.util.KUtil.nullCompare
|
import de.bixilon.minosoft.util.KUtil.nullCompare
|
||||||
@ -24,7 +24,7 @@ data class TabListItem(
|
|||||||
var ping: Int = -1,
|
var ping: Int = -1,
|
||||||
var gamemode: Gamemodes = Gamemodes.SURVIVAL,
|
var gamemode: Gamemodes = Gamemodes.SURVIVAL,
|
||||||
var displayName: ChatComponent = ChatComponent.of(name),
|
var displayName: ChatComponent = ChatComponent.of(name),
|
||||||
var properties: Map<String, PlayerProperty> = mutableMapOf(),
|
var properties: PlayerProperties = PlayerProperties(),
|
||||||
var team: Team? = null,
|
var team: Team? = null,
|
||||||
) : Comparable<TabListItem> {
|
) : Comparable<TabListItem> {
|
||||||
val tabDisplayName: ChatComponent
|
val tabDisplayName: ChatComponent
|
||||||
|
@ -14,7 +14,7 @@
|
|||||||
package de.bixilon.minosoft.data.player.tab
|
package de.bixilon.minosoft.data.player.tab
|
||||||
|
|
||||||
import de.bixilon.minosoft.data.abilities.Gamemodes
|
import de.bixilon.minosoft.data.abilities.Gamemodes
|
||||||
import de.bixilon.minosoft.data.player.PlayerProperty
|
import de.bixilon.minosoft.data.player.properties.PlayerProperties
|
||||||
import de.bixilon.minosoft.data.scoreboard.Team
|
import de.bixilon.minosoft.data.scoreboard.Team
|
||||||
import de.bixilon.minosoft.data.text.ChatComponent
|
import de.bixilon.minosoft.data.text.ChatComponent
|
||||||
|
|
||||||
@ -24,7 +24,7 @@ data class TabListItemData(
|
|||||||
var gamemode: Gamemodes? = null,
|
var gamemode: Gamemodes? = null,
|
||||||
var hasDisplayName: Boolean? = null,
|
var hasDisplayName: Boolean? = null,
|
||||||
var displayName: ChatComponent? = null,
|
var displayName: ChatComponent? = null,
|
||||||
val properties: Map<String, PlayerProperty>? = null,
|
val properties: PlayerProperties? = null,
|
||||||
var remove: Boolean = false, // used for legacy tab list
|
var remove: Boolean = false, // used for legacy tab list
|
||||||
var team: Team? = null,
|
var team: Team? = null,
|
||||||
var removeFromTeam: Boolean = false,
|
var removeFromTeam: Boolean = false,
|
||||||
|
@ -20,6 +20,8 @@ import de.bixilon.minosoft.gui.rendering.util.vec.vec2.Vec2iUtil.toVec2i
|
|||||||
import de.bixilon.minosoft.util.KUtil.mapCast
|
import de.bixilon.minosoft.util.KUtil.mapCast
|
||||||
import de.bixilon.minosoft.util.KUtil.toInt
|
import de.bixilon.minosoft.util.KUtil.toInt
|
||||||
import de.bixilon.minosoft.util.KUtil.toResourceLocation
|
import de.bixilon.minosoft.util.KUtil.toResourceLocation
|
||||||
|
import glm_.vec2.Vec2
|
||||||
|
import glm_.vec2.Vec2i
|
||||||
|
|
||||||
class HUDAtlasManager(private val hudRenderer: HUDRenderer) {
|
class HUDAtlasManager(private val hudRenderer: HUDRenderer) {
|
||||||
private lateinit var elements: Map<ResourceLocation, HUDAtlasElement>
|
private lateinit var elements: Map<ResourceLocation, HUDAtlasElement>
|
||||||
@ -79,8 +81,8 @@ class HUDAtlasManager(private val hudRenderer: HUDRenderer) {
|
|||||||
|
|
||||||
fun postInit() {
|
fun postInit() {
|
||||||
for (element in elements.values) {
|
for (element in elements.values) {
|
||||||
element.uvStart = element.texture.singlePixelSize * element.start
|
element.uvStart = ATLAS_SINGLE_PIXEL_SIZE * element.start
|
||||||
element.uvEnd = element.texture.singlePixelSize * element.end
|
element.uvEnd = ATLAS_SINGLE_PIXEL_SIZE * element.end
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -94,5 +96,8 @@ class HUDAtlasManager(private val hudRenderer: HUDRenderer) {
|
|||||||
|
|
||||||
companion object {
|
companion object {
|
||||||
private val ATLAS_DATA = "minosoft:mapping/atlas.json".toResourceLocation()
|
private val ATLAS_DATA = "minosoft:mapping/atlas.json".toResourceLocation()
|
||||||
|
|
||||||
|
private val ATLAS_SIZE = Vec2i(256, 256)
|
||||||
|
private val ATLAS_SINGLE_PIXEL_SIZE = Vec2(1.0f) / ATLAS_SIZE
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -198,8 +198,8 @@ class OpenGLTextureArray(
|
|||||||
|
|
||||||
|
|
||||||
companion object {
|
companion object {
|
||||||
val TEXTURE_RESOLUTION_ID_MAP = intArrayOf(16, 32, 64, 128, 256, 512, 1024) // A 12x12 texture will be saved in texture id 0 (in 0 are only 16x16 textures). Animated textures get split
|
|
||||||
const val TEXTURE_MAX_RESOLUTION = 1024
|
const val TEXTURE_MAX_RESOLUTION = 1024
|
||||||
|
val TEXTURE_RESOLUTION_ID_MAP = intArrayOf(16, 32, 64, 128, 256, 512, TEXTURE_MAX_RESOLUTION) // A 12x12 texture will be saved in texture id 0 (in 0 are only 16x16 textures). Animated textures get split
|
||||||
const val MAX_MIPMAP_LEVELS = 5
|
const val MAX_MIPMAP_LEVELS = 5
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -16,7 +16,7 @@ import de.bixilon.minosoft.data.entities.EntityRotation
|
|||||||
import de.bixilon.minosoft.data.entities.entities.player.PlayerEntity
|
import de.bixilon.minosoft.data.entities.entities.player.PlayerEntity
|
||||||
import de.bixilon.minosoft.data.entities.entities.player.RemotePlayerEntity
|
import de.bixilon.minosoft.data.entities.entities.player.RemotePlayerEntity
|
||||||
import de.bixilon.minosoft.data.entities.meta.EntityMetaData
|
import de.bixilon.minosoft.data.entities.meta.EntityMetaData
|
||||||
import de.bixilon.minosoft.data.player.PlayerProperty
|
import de.bixilon.minosoft.data.player.properties.PlayerProperties
|
||||||
import de.bixilon.minosoft.modding.event.events.EntitySpawnEvent
|
import de.bixilon.minosoft.modding.event.events.EntitySpawnEvent
|
||||||
import de.bixilon.minosoft.protocol.network.connection.play.PlayConnection
|
import de.bixilon.minosoft.protocol.network.connection.play.PlayConnection
|
||||||
import de.bixilon.minosoft.protocol.packets.s2c.PlayS2CPacket
|
import de.bixilon.minosoft.protocol.packets.s2c.PlayS2CPacket
|
||||||
@ -38,15 +38,11 @@ class PlayerEntitySpawnS2CP(buffer: PlayInByteBuffer) : PlayS2CPacket() {
|
|||||||
entityId = buffer.readVarInt()
|
entityId = buffer.readVarInt()
|
||||||
var name = "TBA"
|
var name = "TBA"
|
||||||
|
|
||||||
val properties: MutableMap<String, PlayerProperty> = mutableMapOf()
|
var properties = PlayerProperties()
|
||||||
if (buffer.versionId < ProtocolVersions.V_14W21A) {
|
if (buffer.versionId < ProtocolVersions.V_14W21A) {
|
||||||
name = buffer.readString()
|
name = buffer.readString()
|
||||||
entityUUID = buffer.readUUIDString()
|
entityUUID = buffer.readUUIDString()
|
||||||
val length = buffer.readVarInt()
|
properties = buffer.readPlayerProperties()
|
||||||
for (i in 0 until length) {
|
|
||||||
val property = PlayerProperty(buffer.readString(), buffer.readString(), buffer.readString())
|
|
||||||
properties[property.key] = property
|
|
||||||
}
|
|
||||||
} else {
|
} else {
|
||||||
entityUUID = buffer.readUUID()
|
entityUUID = buffer.readUUID()
|
||||||
}
|
}
|
||||||
|
@ -14,7 +14,6 @@ package de.bixilon.minosoft.protocol.packets.s2c.play
|
|||||||
|
|
||||||
import de.bixilon.minosoft.data.abilities.Gamemodes
|
import de.bixilon.minosoft.data.abilities.Gamemodes
|
||||||
import de.bixilon.minosoft.data.entities.entities.player.PlayerEntity
|
import de.bixilon.minosoft.data.entities.entities.player.PlayerEntity
|
||||||
import de.bixilon.minosoft.data.player.PlayerProperty
|
|
||||||
import de.bixilon.minosoft.data.player.tab.TabListItem
|
import de.bixilon.minosoft.data.player.tab.TabListItem
|
||||||
import de.bixilon.minosoft.data.player.tab.TabListItemData
|
import de.bixilon.minosoft.data.player.tab.TabListItemData
|
||||||
import de.bixilon.minosoft.modding.event.events.TabListEntryChangeEvent
|
import de.bixilon.minosoft.modding.event.events.TabListEntryChangeEvent
|
||||||
@ -60,15 +59,7 @@ class TabListDataS2CP(buffer: PlayInByteBuffer) : PlayS2CPacket() {
|
|||||||
when (action) {
|
when (action) {
|
||||||
TabListItemActions.ADD -> {
|
TabListItemActions.ADD -> {
|
||||||
val name = buffer.readString()
|
val name = buffer.readString()
|
||||||
val playerProperties: MutableMap<String, PlayerProperty> = mutableMapOf()
|
val properties = buffer.readPlayerProperties()
|
||||||
for (index in 0 until buffer.readVarInt()) {
|
|
||||||
val property = PlayerProperty(
|
|
||||||
buffer.readString(),
|
|
||||||
buffer.readString(),
|
|
||||||
buffer.readOptional { buffer.readString() },
|
|
||||||
)
|
|
||||||
playerProperties[property.key] = property
|
|
||||||
}
|
|
||||||
val gamemode = Gamemodes[buffer.readVarInt()]
|
val gamemode = Gamemodes[buffer.readVarInt()]
|
||||||
val ping = buffer.readVarInt()
|
val ping = buffer.readVarInt()
|
||||||
val hasDisplayName = buffer.readBoolean()
|
val hasDisplayName = buffer.readBoolean()
|
||||||
@ -79,7 +70,7 @@ class TabListDataS2CP(buffer: PlayInByteBuffer) : PlayS2CPacket() {
|
|||||||
}
|
}
|
||||||
data = TabListItemData(
|
data = TabListItemData(
|
||||||
name = name,
|
name = name,
|
||||||
properties = playerProperties,
|
properties = properties,
|
||||||
gamemode = gamemode,
|
gamemode = gamemode,
|
||||||
ping = ping,
|
ping = ping,
|
||||||
hasDisplayName = hasDisplayName,
|
hasDisplayName = hasDisplayName,
|
||||||
|
@ -14,6 +14,8 @@ package de.bixilon.minosoft.protocol.protocol
|
|||||||
|
|
||||||
import de.bixilon.minosoft.data.entities.meta.EntityMetaData
|
import de.bixilon.minosoft.data.entities.meta.EntityMetaData
|
||||||
import de.bixilon.minosoft.data.inventory.ItemStack
|
import de.bixilon.minosoft.data.inventory.ItemStack
|
||||||
|
import de.bixilon.minosoft.data.player.properties.PlayerProperties
|
||||||
|
import de.bixilon.minosoft.data.player.properties.textures.PlayerTextures
|
||||||
import de.bixilon.minosoft.data.registries.biomes.Biome
|
import de.bixilon.minosoft.data.registries.biomes.Biome
|
||||||
import de.bixilon.minosoft.data.registries.particle.ParticleType
|
import de.bixilon.minosoft.data.registries.particle.ParticleType
|
||||||
import de.bixilon.minosoft.data.registries.particle.data.BlockParticleData
|
import de.bixilon.minosoft.data.registries.particle.data.BlockParticleData
|
||||||
@ -214,4 +216,27 @@ class PlayInByteBuffer : InByteBuffer {
|
|||||||
fun readEntityIdArray(length: Int = readVarInt()): Array<Int> {
|
fun readEntityIdArray(length: Int = readVarInt()): Array<Int> {
|
||||||
return readArray(length) { readEntityId() }
|
return readArray(length) { readEntityId() }
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
fun readPlayerProperties(): PlayerProperties {
|
||||||
|
var textures: PlayerTextures? = null
|
||||||
|
for (i in 0 until readVarInt()) {
|
||||||
|
val name = readString()
|
||||||
|
val value = readString()
|
||||||
|
val signature = if (versionId < V_14W21A) {
|
||||||
|
readString()
|
||||||
|
} else {
|
||||||
|
readOptional { readString() }
|
||||||
|
}
|
||||||
|
when (name) {
|
||||||
|
"textures" -> {
|
||||||
|
check(textures == null) { "Textures duplicated" }
|
||||||
|
textures = PlayerTextures.of(value, signature ?: throw IllegalArgumentException("Texture data needs to be signed!"))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return PlayerProperties(
|
||||||
|
textures = textures,
|
||||||
|
)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@ -33,6 +33,7 @@ import glm_.vec4.Vec4t
|
|||||||
import sun.misc.Unsafe
|
import sun.misc.Unsafe
|
||||||
import java.io.*
|
import java.io.*
|
||||||
import java.lang.reflect.Field
|
import java.lang.reflect.Field
|
||||||
|
import java.net.URL
|
||||||
import java.nio.ByteBuffer
|
import java.nio.ByteBuffer
|
||||||
import java.time.Instant
|
import java.time.Instant
|
||||||
import java.util.*
|
import java.util.*
|
||||||
@ -558,4 +559,9 @@ object KUtil {
|
|||||||
|
|
||||||
val Locale.fullName: String
|
val Locale.fullName: String
|
||||||
get() = language + "_" + country.ifEmpty { language.uppercase() }
|
get() = language + "_" + country.ifEmpty { language.uppercase() }
|
||||||
|
|
||||||
|
|
||||||
|
fun URL.check() {
|
||||||
|
check(this.protocol == "http" || this.protocol == "https") { "Url is not a web address" }
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
33
src/main/java/de/bixilon/minosoft/util/YggdrasilUtil.kt
Normal file
33
src/main/java/de/bixilon/minosoft/util/YggdrasilUtil.kt
Normal file
@ -0,0 +1,33 @@
|
|||||||
|
package de.bixilon.minosoft.util
|
||||||
|
|
||||||
|
import de.bixilon.minosoft.Minosoft
|
||||||
|
import de.bixilon.minosoft.util.KUtil.toResourceLocation
|
||||||
|
import java.security.KeyFactory
|
||||||
|
import java.security.PublicKey
|
||||||
|
import java.security.Signature
|
||||||
|
import java.security.spec.X509EncodedKeySpec
|
||||||
|
import java.util.*
|
||||||
|
|
||||||
|
|
||||||
|
object YggdrasilUtil {
|
||||||
|
lateinit var PUBLIC_KEY: PublicKey
|
||||||
|
private set
|
||||||
|
|
||||||
|
fun load() {
|
||||||
|
check(!this::PUBLIC_KEY.isInitialized) { "Already loaded!" }
|
||||||
|
val spec = X509EncodedKeySpec(Minosoft.MINOSOFT_ASSETS_MANAGER["minosoft:mojang/yggdrasil_session_pubkey.der".toResourceLocation()].readAllBytes())
|
||||||
|
val keyFactory: KeyFactory = KeyFactory.getInstance("RSA")
|
||||||
|
PUBLIC_KEY = keyFactory.generatePublic(spec)
|
||||||
|
}
|
||||||
|
|
||||||
|
fun verify(data: ByteArray, signature: ByteArray): Boolean {
|
||||||
|
val signatureInstance = Signature.getInstance("SHA1withRSA")
|
||||||
|
signatureInstance.initVerify(PUBLIC_KEY)
|
||||||
|
signatureInstance.update(data)
|
||||||
|
return signatureInstance.verify(signature)
|
||||||
|
}
|
||||||
|
|
||||||
|
fun verify(data: String, signature: String): Boolean {
|
||||||
|
return verify(data.toByteArray(), Base64.getDecoder().decode(signature))
|
||||||
|
}
|
||||||
|
}
|
@ -2,14 +2,19 @@ package de.bixilon.minosoft.util.json
|
|||||||
|
|
||||||
import com.fasterxml.jackson.core.JsonParser
|
import com.fasterxml.jackson.core.JsonParser
|
||||||
import com.fasterxml.jackson.databind.DeserializationFeature
|
import com.fasterxml.jackson.databind.DeserializationFeature
|
||||||
import com.fasterxml.jackson.databind.ObjectMapper
|
import com.fasterxml.jackson.databind.MapperFeature
|
||||||
import com.fasterxml.jackson.databind.PropertyNamingStrategies
|
import com.fasterxml.jackson.databind.PropertyNamingStrategies
|
||||||
|
import com.fasterxml.jackson.databind.json.JsonMapper
|
||||||
import com.fasterxml.jackson.databind.type.MapType
|
import com.fasterxml.jackson.databind.type.MapType
|
||||||
import com.fasterxml.jackson.module.kotlin.KotlinFeature
|
import com.fasterxml.jackson.module.kotlin.KotlinFeature
|
||||||
import com.fasterxml.jackson.module.kotlin.KotlinModule
|
import com.fasterxml.jackson.module.kotlin.KotlinModule
|
||||||
|
|
||||||
object Jackson {
|
object Jackson {
|
||||||
val MAPPER = ObjectMapper()
|
val MAPPER = JsonMapper.builder()
|
||||||
|
.configure(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES, false)
|
||||||
|
.disable(JsonParser.Feature.AUTO_CLOSE_SOURCE)
|
||||||
|
.enable(MapperFeature.ACCEPT_CASE_INSENSITIVE_ENUMS)
|
||||||
|
.build()
|
||||||
.registerModule(KotlinModule.Builder()
|
.registerModule(KotlinModule.Builder()
|
||||||
.withReflectionCacheSize(512)
|
.withReflectionCacheSize(512)
|
||||||
.configure(KotlinFeature.NullToEmptyCollection, false)
|
.configure(KotlinFeature.NullToEmptyCollection, false)
|
||||||
@ -21,8 +26,6 @@ object Jackson {
|
|||||||
.registerModule(ResourceLocationSerializer)
|
.registerModule(ResourceLocationSerializer)
|
||||||
.registerModule(RGBColorSerializer)
|
.registerModule(RGBColorSerializer)
|
||||||
.registerModule(ChatComponentColorSerializer)
|
.registerModule(ChatComponentColorSerializer)
|
||||||
.configure(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES, false)
|
|
||||||
.disable(JsonParser.Feature.AUTO_CLOSE_SOURCE)
|
|
||||||
.setDefaultMergeable(true)
|
.setDefaultMergeable(true)
|
||||||
|
|
||||||
|
|
||||||
|
@ -13,6 +13,8 @@
|
|||||||
|
|
||||||
package de.bixilon.minosoft.util.nbt.tag
|
package de.bixilon.minosoft.util.nbt.tag
|
||||||
|
|
||||||
|
import de.bixilon.minosoft.util.KUtil.nullCast
|
||||||
|
|
||||||
object NBTUtil {
|
object NBTUtil {
|
||||||
|
|
||||||
fun compound(): MutableMap<String, Any> {
|
fun compound(): MutableMap<String, Any> {
|
||||||
@ -33,11 +35,7 @@ object NBTUtil {
|
|||||||
}
|
}
|
||||||
|
|
||||||
fun Any?.compoundCast(): MutableMap<String, Any>? {
|
fun Any?.compoundCast(): MutableMap<String, Any>? {
|
||||||
try {
|
return this.nullCast()
|
||||||
return this as MutableMap<String, Any>
|
|
||||||
} catch (ignored: ClassCastException) {
|
|
||||||
}
|
|
||||||
return null
|
|
||||||
}
|
}
|
||||||
|
|
||||||
fun Any?.asCompound(): MutableMap<String, Any> {
|
fun Any?.asCompound(): MutableMap<String, Any> {
|
||||||
|
@ -24,5 +24,6 @@ enum class StartupTasks {
|
|||||||
INITIALIZE_JAVAFX,
|
INITIALIZE_JAVAFX,
|
||||||
X_START_ON_FIRST_THREAD_WARNING,
|
X_START_ON_FIRST_THREAD_WARNING,
|
||||||
FILE_WATCHER,
|
FILE_WATCHER,
|
||||||
|
LOAD_YGGDRASIL,
|
||||||
;
|
;
|
||||||
}
|
}
|
||||||
|
Binary file not shown.
Loading…
x
Reference in New Issue
Block a user