Atlas variant for skin element

Fixes #99
This commit is contained in:
DBotThePony 2022-10-06 23:41:08 +07:00
parent 92ae0408e8
commit f99ed19d9c
Signed by: DBot
GPG Key ID: DCC23B5715498507
39 changed files with 719 additions and 322 deletions

View File

@ -1,6 +1,6 @@
# Sets default memory used for gradle commands. Can be overridden by user or command line properties. # Sets default memory used for gradle commands. Can be overridden by user or command line properties.
# This is required to provide enough memory for the Minecraft decompilation process. # This is required to provide enough memory for the Minecraft decompilation process.
org.gradle.jvmargs=-Xmx3G -XX:+UseParallelGC org.gradle.jvmargs=-Xmx3G
org.gradle.daemon=true org.gradle.daemon=true
kotlin.stdlib.default.dependency=false kotlin.stdlib.default.dependency=false

View File

@ -31,6 +31,7 @@ import ru.dbotthepony.mc.otm.client.ClientTickHandlerKt;
import ru.dbotthepony.mc.otm.client.MatteryGUI; import ru.dbotthepony.mc.otm.client.MatteryGUI;
import ru.dbotthepony.mc.otm.client.model.GravitationStabilizerModel; import ru.dbotthepony.mc.otm.client.model.GravitationStabilizerModel;
import ru.dbotthepony.mc.otm.client.model.TritaniumArmorModel; import ru.dbotthepony.mc.otm.client.model.TritaniumArmorModel;
import ru.dbotthepony.mc.otm.client.render.WidgetAtlasHolder;
import ru.dbotthepony.mc.otm.compat.mekanism.QIOKt; import ru.dbotthepony.mc.otm.compat.mekanism.QIOKt;
import ru.dbotthepony.mc.otm.compat.mekanism.TooltipsKt; import ru.dbotthepony.mc.otm.compat.mekanism.TooltipsKt;
import ru.dbotthepony.mc.otm.core.ImpreciseFraction; import ru.dbotthepony.mc.otm.core.ImpreciseFraction;
@ -102,6 +103,7 @@ public final class OverdriveThatMatters {
modBus.addListener(EventPriority.NORMAL, AndroidAbilityKeyMapping.INSTANCE::register); modBus.addListener(EventPriority.NORMAL, AndroidAbilityKeyMapping.INSTANCE::register);
modBus.addListener(EventPriority.NORMAL, TritaniumArmorModel::register); modBus.addListener(EventPriority.NORMAL, TritaniumArmorModel::register);
modBus.addListener(EventPriority.NORMAL, GravitationStabilizerModel::register); modBus.addListener(EventPriority.NORMAL, GravitationStabilizerModel::register);
modBus.addListener(EventPriority.NORMAL, WidgetAtlasHolder::register);
}); });
ClientConfig.INSTANCE.register(); ClientConfig.INSTANCE.register();

View File

@ -7,6 +7,7 @@ import com.google.gson.JsonElement
import com.google.gson.JsonObject import com.google.gson.JsonObject
import com.google.gson.JsonPrimitive import com.google.gson.JsonPrimitive
import com.google.gson.JsonSyntaxException import com.google.gson.JsonSyntaxException
import com.google.gson.internal.bind.TypeAdapters
import net.minecraft.network.FriendlyByteBuf import net.minecraft.network.FriendlyByteBuf
import net.minecraft.network.chat.Component import net.minecraft.network.chat.Component
import net.minecraft.network.chat.ComponentContents import net.minecraft.network.chat.ComponentContents
@ -20,6 +21,7 @@ import net.minecraft.world.item.Items
import net.minecraft.world.item.crafting.Ingredient import net.minecraft.world.item.crafting.Ingredient
import net.minecraft.world.level.ItemLike import net.minecraft.world.level.ItemLike
import net.minecraftforge.registries.ForgeRegistries import net.minecraftforge.registries.ForgeRegistries
import ru.dbotthepony.mc.otm.client.render.AbstractSkinElement
import ru.dbotthepony.mc.otm.client.render.SkinElement import ru.dbotthepony.mc.otm.client.render.SkinElement
import ru.dbotthepony.mc.otm.core.ListSet import ru.dbotthepony.mc.otm.core.ListSet
import ru.dbotthepony.mc.otm.core.TranslatableComponent import ru.dbotthepony.mc.otm.core.TranslatableComponent
@ -28,6 +30,7 @@ import ru.dbotthepony.mc.otm.core.registryName
import ru.dbotthepony.mc.otm.core.set import ru.dbotthepony.mc.otm.core.set
import ru.dbotthepony.mc.otm.core.toImmutableList import ru.dbotthepony.mc.otm.core.toImmutableList
import ru.dbotthepony.mc.otm.data.stream import ru.dbotthepony.mc.otm.data.stream
import ru.dbotthepony.mc.otm.isClient
import ru.dbotthepony.mc.otm.registry.MRegistry import ru.dbotthepony.mc.otm.registry.MRegistry
import java.util.LinkedList import java.util.LinkedList
import java.util.stream.Stream import java.util.stream.Stream
@ -88,16 +91,22 @@ class AndroidResearchType(
val experienceLevels: Int = 0, val experienceLevels: Int = 0,
private val customName: Component? = null, private val customName: Component? = null,
// why pack these into research itself? // ok
// because Minecraft itself does this val skinIcon: JsonElement? = null,
// check out advancements
val skinIcon: SkinElement? = null,
val itemIcon: Item? = null, val itemIcon: Item? = null,
iconText: Component? = null, iconText: Component? = null,
) { ) {
private val iconTextValue = iconText?.copy() private val iconTextValue = iconText?.copy()
val iconText get() = iconTextValue?.copy() val iconText get() = iconTextValue?.copy()
val resolvedSkinIcon by lazy {
check(isClient) { "Invalid realm" }
if (skinIcon != null)
AbstractSkinElement.fromJson(skinIcon)
else
null
}
data class Reference( data class Reference(
val id: ResourceLocation, val id: ResourceLocation,
val isRigid: Boolean val isRigid: Boolean
@ -471,7 +480,7 @@ class AndroidResearchType(
it["experience"] = JsonPrimitive(experienceLevels) it["experience"] = JsonPrimitive(experienceLevels)
if (skinIcon != null) { if (skinIcon != null) {
it["skin_icon"] = skinIcon.toJson() it["skin_icon"] = skinIcon
} }
if (itemIcon != null) { if (itemIcon != null) {
@ -511,7 +520,7 @@ class AndroidResearchType(
if (iconTextValue != null) buff.writeComponent(iconTextValue) if (iconTextValue != null) buff.writeComponent(iconTextValue)
buff.writeBoolean(skinIcon != null) buff.writeBoolean(skinIcon != null)
skinIcon?.toNetwork(buff) if (skinIcon != null) buff.writeUtf(skinIcon.toString())
buff.writeBoolean(itemIcon != null) buff.writeBoolean(itemIcon != null)
if (itemIcon != null) buff.writeUtf(itemIcon.registryName!!.toString()) if (itemIcon != null) buff.writeUtf(itemIcon.registryName!!.toString())
@ -541,7 +550,7 @@ class AndroidResearchType(
} }
val skinIcon = if (buff.readBoolean()) { val skinIcon = if (buff.readBoolean()) {
SkinElement.fromNetwork(buff) TypeAdapters.JSON_ELEMENT.fromJson(buff.readUtf())
} else { } else {
null null
} }
@ -582,7 +591,7 @@ class AndroidResearchType(
val experience = value["experience"]?.asInt ?: 0 val experience = value["experience"]?.asInt ?: 0
val customName = value["custom_name"]?.let(Component.Serializer::fromJson) val customName = value["custom_name"]?.let(Component.Serializer::fromJson)
val iconText = value["icon_text"]?.let(Component.Serializer::fromJson) val iconText = value["icon_text"]?.let(Component.Serializer::fromJson)
val skinIcon = value["skin_icon"]?.let(SkinElement.Companion::fromJson) val skinIcon = value["skin_icon"]
val itemIcon = value["item_icon"]?.let { ForgeRegistries.ITEMS.getValue(ResourceLocation(it.asString)).let { if (it == Items.AIR) null else it } } val itemIcon = value["item_icon"]?.let { ForgeRegistries.ITEMS.getValue(ResourceLocation(it.asString)).let { if (it == Items.AIR) null else it } }
return AndroidResearchType( return AndroidResearchType(
@ -615,7 +624,7 @@ class AndroidResearchType(
var description: MutableList<Component>? = null, var description: MutableList<Component>? = null,
var descriptionSuppliers: MutableList<ComponentSupplier>? = null, var descriptionSuppliers: MutableList<ComponentSupplier>? = null,
var itemIcon: Item? = null, var itemIcon: Item? = null,
var skinIcon: SkinElement? = null, var skinIcon: AbstractSkinElement? = null,
var iconText: Component? = null, var iconText: Component? = null,
) { ) {
private val items = ArrayList<Pair<Ingredient, Int>>() private val items = ArrayList<Pair<Ingredient, Int>>()
@ -629,7 +638,7 @@ class AndroidResearchType(
return this return this
} }
fun withIcon(icon: SkinElement? = null): Builder { fun withIcon(icon: AbstractSkinElement? = null): Builder {
this.skinIcon = icon this.skinIcon = icon
this.itemIcon = null this.itemIcon = null
return this return this
@ -840,7 +849,7 @@ class AndroidResearchType(
descriptionSuppliers = descriptionSuppliers ?: listOf(), descriptionSuppliers = descriptionSuppliers ?: listOf(),
experienceLevels = experience, experienceLevels = experience,
customName = customName, customName = customName,
skinIcon = skinIcon, skinIcon = skinIcon?.toJson(),
itemIcon = itemIcon, itemIcon = itemIcon,
iconText = iconText iconText = iconText
).also { if (validate) it.validate() } ).also { if (validate) it.validate() }

View File

@ -25,6 +25,16 @@ fun onceClientPre(ticker: ITickable) {
preTickList.add(ticker, LOGGED_IN, "Not logged in") preTickList.add(ticker, LOGGED_IN, "Not logged in")
} }
fun onceClient(inTicks: Int, ticker: Runnable) {
check(isClient) { "Illegal side" }
postTimerList.add(inTicks, ticker, LOGGED_IN, "Not logged in")
}
fun onceClientPre(inTicks: Int, ticker: Runnable) {
check(isClient) { "Illegal side" }
preTimerList.add(inTicks, ticker, LOGGED_IN, "Not logged in")
}
fun tickClient(ticker: IConditionalTickable) { fun tickClient(ticker: IConditionalTickable) {
check(isClient) { "Illegal side" } check(isClient) { "Illegal side" }
postTickList.add(ticker, LOGGED_IN, "Not logged in") postTickList.add(ticker, LOGGED_IN, "Not logged in")

View File

@ -0,0 +1,255 @@
package ru.dbotthepony.mc.otm.client.render
import com.google.gson.JsonDeserializationContext
import com.google.gson.JsonDeserializer
import com.google.gson.JsonElement
import com.google.gson.JsonObject
import com.google.gson.JsonPrimitive
import com.google.gson.JsonSerializationContext
import com.google.gson.JsonSerializer
import com.google.gson.JsonSyntaxException
import com.google.gson.TypeAdapter
import com.google.gson.internal.bind.TypeAdapters
import com.google.gson.stream.JsonReader
import com.google.gson.stream.JsonWriter
import com.mojang.blaze3d.systems.RenderSystem
import com.mojang.blaze3d.vertex.PoseStack
import net.minecraft.network.FriendlyByteBuf
import net.minecraft.resources.ResourceLocation
import ru.dbotthepony.mc.otm.core.linearInterpolation
import java.lang.reflect.Type
sealed class AbstractSkinElement {
abstract val x: Float
abstract val y: Float
abstract val width: Float
abstract val height: Float
abstract val u0: Float
abstract val v0: Float
abstract val u1: Float
abstract val v1: Float
open val winding: UVWindingOrder get() = UVWindingOrder.NORMAL
abstract val texture: ResourceLocation
/**
* See [ru.dbotthepony.mc.otm.client.render.clearDepth]
*/
fun clearDepth(
stack: PoseStack,
x: Float = 0f,
y: Float = 0f,
width: Float = this.width,
height: Float = this.height,
) = ru.dbotthepony.mc.otm.client.render.clearDepth(stack, x, y, width, height)
@JvmOverloads
fun render(
stack: PoseStack,
x: Float = 0f,
y: Float = 0f,
width: Float = this.width,
height: Float = this.height,
winding: UVWindingOrder = this.winding
) {
RenderSystem.setShaderTexture(0, texture)
RenderSystem.enableBlend()
RenderSystem.defaultBlendFunc()
renderRaw(stack, x, y, width, height, winding)
}
@JvmOverloads
fun render(
stack: PoseStack,
x: Double,
y: Double = 0.0,
width: Double = this.width.toDouble(),
height: Double = this.height.toDouble(),
winding: UVWindingOrder = this.winding
) = render(stack, x.toFloat(), y.toFloat(), width.toFloat(), height.toFloat(), winding)
@JvmOverloads
fun renderPartial(
stack: PoseStack,
x: Float = 0f,
y: Float = 0f,
width: Float = this.width,
height: Float = this.height,
winding: UVWindingOrder = this.winding
) {
RenderSystem.setShaderTexture(0, texture)
RenderSystem.enableBlend()
RenderSystem.defaultBlendFunc()
renderRawPartial(stack, x, y, width, height, winding)
}
@JvmOverloads
fun renderPartial(
stack: PoseStack,
x: Double,
y: Double = 0.0,
width: Double = this.width.toDouble(),
height: Double = this.height.toDouble(),
winding: UVWindingOrder = this.winding
) = renderPartial(stack, x.toFloat(), y.toFloat(), width.toFloat(), height.toFloat(), winding)
@JvmOverloads
fun renderWidth(
stack: PoseStack,
x: Float = 0f,
y: Float = 0f,
width: Float = this.width,
winding: UVWindingOrder = this.winding
) {
render(stack, x, y, width = width, winding = winding)
}
@JvmOverloads
fun renderWidth(
stack: PoseStack,
x: Double,
y: Double = 0.0,
width: Double = this.width.toDouble(),
winding: UVWindingOrder = this.winding
) = renderWidth(stack, x.toFloat(), y.toFloat(), width.toFloat(), winding)
@JvmOverloads
fun renderHeight(
stack: PoseStack,
x: Float = 0f,
y: Float = 0f,
height: Float = this.height,
winding: UVWindingOrder = this.winding
) {
render(stack, x, y, height = height, winding = winding)
}
@JvmOverloads
fun renderHeight(
stack: PoseStack,
x: Double,
y: Double = 0.0,
height: Double = this.height.toDouble(),
winding: UVWindingOrder = this.winding
) = renderHeight(stack, x.toFloat(), y.toFloat(), height.toFloat(), winding)
@JvmOverloads
fun renderRaw(
stack: PoseStack,
x: Float = 0f,
y: Float = 0f,
width: Float = this.width,
height: Float = this.height,
winding: UVWindingOrder = this.winding
) {
val winded = winding.translate(u0, v0, u1, v1)
drawTexturedRect(
stack,
x,
y,
width,
height,
winded,
)
}
@JvmOverloads
fun renderRaw(
stack: PoseStack,
x: Double,
y: Double = 0.0,
width: Double = this.width.toDouble(),
height: Double = this.height.toDouble(),
winding: UVWindingOrder = this.winding
) = renderRaw(stack, x.toFloat(), y.toFloat(), width.toFloat(), height.toFloat(), winding)
@JvmOverloads
fun renderRawPartial(
stack: PoseStack,
x: Float = 0f,
y: Float = 0f,
width: Float = this.width,
height: Float = this.height,
winding: UVWindingOrder = this.winding
) {
val u1 = (u0 + linearInterpolation(width / this.width, 0f, u1 - u0)).coerceAtLeast(0f).coerceAtMost(1f)
val v1 = (v0 + linearInterpolation(height / this.height, 0f, v1 - v0)).coerceAtLeast(0f).coerceAtMost(1f)
val winded = winding.translate(u0, v0, u1, v1)
drawTexturedRect(
stack,
x,
y,
width,
height,
winded,
)
}
@JvmOverloads
fun renderRawPartial(
stack: PoseStack,
x: Double,
y: Double = 0.0,
width: Double = this.width.toDouble(),
height: Double = this.height.toDouble(),
winding: UVWindingOrder = this.winding
) = renderRawPartial(stack, x.toFloat(), y.toFloat(), width.toFloat(), height.toFloat(), winding)
abstract fun toJson(): JsonElement
abstract fun toNetwork(buff: FriendlyByteBuf)
companion object : TypeAdapter<AbstractSkinElement>(), JsonSerializer<AbstractSkinElement>, JsonDeserializer<AbstractSkinElement> {
fun toNetwork(value: AbstractSkinElement, buff: FriendlyByteBuf) {
buff.writeBoolean(value is AtlasSkinElement)
value.toNetwork(buff)
}
fun fromNetwork(buff: FriendlyByteBuf): AbstractSkinElement {
if (buff.readBoolean()) {
return AtlasSkinElement.fromNetwork(buff)
}
return SkinElement.fromNetwork(buff)
}
fun fromJson(json: JsonElement): AbstractSkinElement {
if (json is JsonPrimitive) {
return AtlasSkinElement.fromJson(json)
} else if (json is JsonObject) {
return SkinElement.fromJson(json)
} else {
throw JsonSyntaxException("Unknown element type ${json::class.qualifiedName}")
}
}
override fun write(out: JsonWriter, value: AbstractSkinElement) {
TypeAdapters.JSON_ELEMENT.write(out, value.toJson())
}
override fun read(`in`: JsonReader): AbstractSkinElement {
return fromJson(TypeAdapters.JSON_ELEMENT.read(`in`))
}
override fun serialize(
src: AbstractSkinElement,
typeOfSrc: Type,
context: JsonSerializationContext
): JsonElement {
return src.toJson()
}
override fun deserialize(
json: JsonElement,
typeOfT: Type,
context: JsonDeserializationContext
): AbstractSkinElement {
return fromJson(json)
}
}
}

View File

@ -0,0 +1,148 @@
package ru.dbotthepony.mc.otm.client.render
import com.google.gson.JsonDeserializationContext
import com.google.gson.JsonDeserializer
import com.google.gson.JsonElement
import com.google.gson.JsonPrimitive
import com.google.gson.JsonSerializationContext
import com.google.gson.JsonSerializer
import com.google.gson.TypeAdapter
import com.google.gson.internal.bind.TypeAdapters
import com.google.gson.stream.JsonReader
import com.google.gson.stream.JsonWriter
import net.minecraft.client.renderer.texture.TextureAtlasSprite
import net.minecraft.network.FriendlyByteBuf
import net.minecraft.resources.ResourceLocation
import ru.dbotthepony.mc.otm.client.onceClient
import ru.dbotthepony.mc.otm.isClient
import java.lang.reflect.Type
import java.util.stream.Stream
fun AtlasSkinElement(location: ResourceLocation) = AtlasSkinElement.create(location)
class AtlasSkinElement private constructor(
val location: ResourceLocation,
marker: Any?
) : AbstractSkinElement() {
private var changeset = -1
private var _textureAtlasSprite: TextureAtlasSprite? = null
private val textureAtlasSpriteImpl: TextureAtlasSprite get(): TextureAtlasSprite {
check(isClient) { "Invalid realm" }
val _textureAtlasSprite = _textureAtlasSprite
if (_textureAtlasSprite == null || changeset != WidgetAtlasHolder.INSTANCE.changeset) {
val get = WidgetAtlasHolder.INSTANCE.getSprite(location)
this._textureAtlasSprite = get
changeset = WidgetAtlasHolder.INSTANCE.changeset
return get
}
return _textureAtlasSprite
}
val textureAtlasSprite: TextureAtlasSprite get(): TextureAtlasSprite {
check(isWidgetAtlasAvailable) { "Atlas is not available; either we are not a client, or we are running datagen" }
return textureAtlasSpriteImpl
}
override val x get() = textureAtlasSprite.x.toFloat()
override val y get() = textureAtlasSprite.y.toFloat()
override val width get() = textureAtlasSprite.width.toFloat()
override val height get() = textureAtlasSprite.height.toFloat()
override val u0 get() = textureAtlasSprite.u0
override val v0 get() = textureAtlasSprite.v0
override val u1 get() = textureAtlasSprite.u1
override val v1 get() = textureAtlasSprite.v1
override val texture: ResourceLocation get() = textureAtlasSprite.atlas().location()
override fun equals(other: Any?): Boolean {
if (other is AtlasSkinElement)
return location == other.location
return super.equals(other)
}
override fun hashCode(): Int {
return WidgetAtlasHolder.INSTANCE.hashCode() xor location.hashCode()
}
override fun toString(): String {
return "AtlasSkinElement[$location]"
}
override fun toJson(): JsonElement {
return JsonPrimitive(location.toString())
}
override fun toNetwork(buff: FriendlyByteBuf) {
buff.writeResourceLocation(location)
}
companion object : TypeAdapter<AtlasSkinElement>(), JsonSerializer<AtlasSkinElement>, JsonDeserializer<AtlasSkinElement> {
private val skinElementCache = HashMap<ResourceLocation, AtlasSkinElement>()
val keys: Stream<ResourceLocation> get() = skinElementCache.keys.stream()
private fun queueRebuild() {
WidgetAtlasHolder.INSTANCE.queueRebuild()
}
private fun createImpl(location: ResourceLocation): AtlasSkinElement {
var element = skinElementCache[location]
if (element == null) {
element = AtlasSkinElement(location, null)
skinElementCache[location] = element
if (isWidgetAtlasAvailable) {
queueRebuild()
}
}
return element
}
@JvmStatic
fun create(location: ResourceLocation): AtlasSkinElement {
if (!isWidgetAtlasAvailable) {
return AtlasSkinElement(location, null)
}
return createImpl(location)
}
fun fromNetwork(buff: FriendlyByteBuf): AtlasSkinElement {
return create(buff.readResourceLocation())
}
fun fromJson(element: JsonElement): AtlasSkinElement {
return create(ResourceLocation.tryParse(element.asString) ?: ResourceLocation("missing"))
}
override fun write(out: JsonWriter, value: AtlasSkinElement) {
TypeAdapters.JSON_ELEMENT.write(out, value.toJson())
}
override fun read(`in`: JsonReader): AtlasSkinElement {
return fromJson(TypeAdapters.JSON_ELEMENT.read(`in`))
}
override fun serialize(
src: AtlasSkinElement,
typeOfSrc: Type,
context: JsonSerializationContext
): JsonElement {
return src.toJson()
}
override fun deserialize(
json: JsonElement,
typeOfT: Type,
context: JsonDeserializationContext
): AtlasSkinElement {
return fromJson(json)
}
}
}

View File

@ -4,64 +4,60 @@ import net.minecraft.resources.ResourceLocation
import ru.dbotthepony.mc.otm.OverdriveThatMatters import ru.dbotthepony.mc.otm.OverdriveThatMatters
object ResearchIcons { object ResearchIcons {
val ICONS = ResourceLocation(OverdriveThatMatters.MOD_ID, "textures/gui/android_upgrades.png") val ICON_TRANSFER: AbstractSkinElement
val ICON_TRANSFER: SkinElement val ICON_ATTACK_BOOST: AbstractSkinElement
val ICON_ATTACK_BOOST: SkinElement val ICON_PLASMA_SHIELD_BOOST: AbstractSkinElement
val ICON_PLASMA_SHIELD_BOOST: SkinElement val ICON_CLOAK: AbstractSkinElement
val ICON_CLOAK: SkinElement val ICON_GRAVITATIONAL_STABILIZER: AbstractSkinElement
val ICON_GRAVITATIONAL_STABILIZER: SkinElement val ICON_AIR_BAGS: AbstractSkinElement
val ICON_AIR_BAGS: SkinElement val ICON_JUMP_BOOST: AbstractSkinElement
val ICON_JUMP_BOOST: SkinElement
val ICON_FEATHER_FALLING: SkinElement val ICON_FEATHER_FALLING: AbstractSkinElement
val ICON_ITEM_MAGNET: SkinElement val ICON_ITEM_MAGNET: AbstractSkinElement
val ICON_ARROW: SkinElement val ICON_ARROW: AbstractSkinElement
val ICON_ARMOR: SkinElement val ICON_ARMOR: AbstractSkinElement
val ICON_NANOBOTS: SkinElement val ICON_NANOBOTS: AbstractSkinElement
val ICON_NIGHT_VISION: SkinElement val ICON_NIGHT_VISION: AbstractSkinElement
val ICON_OXYGEN_SUPPLY: SkinElement val ICON_OXYGEN_SUPPLY: AbstractSkinElement
val ICON_PLASMA_SHIELD: SkinElement val ICON_PLASMA_SHIELD: AbstractSkinElement
val ICON_SHOCKWAVE: SkinElement val ICON_SHOCKWAVE: AbstractSkinElement
val ICON_LIMB_OVERCLOCKING: SkinElement val ICON_LIMB_OVERCLOCKING: AbstractSkinElement
val ICON_STEP_ASSIST: SkinElement val ICON_STEP_ASSIST: AbstractSkinElement
val ICON_ENDER_TELEPORT: SkinElement val ICON_ENDER_TELEPORT: AbstractSkinElement
val ICON_WIRELESS_CHARGING: SkinElement val ICON_WIRELESS_CHARGING: AbstractSkinElement
val ICON_UNKNOWN: SkinElement val ICON_UNKNOWN: AbstractSkinElement
val ICON_EXTENDED_REACH: SkinElement val ICON_EXTENDED_REACH: AbstractSkinElement
val ICON_PHANTOM_ATTRACTOR: SkinElement val ICON_PHANTOM_ATTRACTOR: AbstractSkinElement
val KOT = ResourceLocation(OverdriveThatMatters.MOD_ID, "textures/block/ph_kitty.png").element(0f, 0f, 32f, 32f, 32f, 32f) val KOT = ResourceLocation(OverdriveThatMatters.MOD_ID, "textures/block/ph_kitty.png").element(0f, 0f, 32f, 32f, 32f, 32f)
init { init {
val grid = SkinGrid(ICONS, 18f, 18f, 7, 7) var i = 0
ICON_TRANSFER = grid.next() ICON_TRANSFER = AtlasSkinElement(ResourceLocation(OverdriveThatMatters.MOD_ID, "android_stuff-${i++}"))
ICON_ATTACK_BOOST = grid.next() ICON_ATTACK_BOOST = AtlasSkinElement(ResourceLocation(OverdriveThatMatters.MOD_ID, "android_stuff-${i++}"))
ICON_PLASMA_SHIELD_BOOST = grid.next() ICON_PLASMA_SHIELD_BOOST = AtlasSkinElement(ResourceLocation(OverdriveThatMatters.MOD_ID, "android_stuff-${i++}"))
ICON_CLOAK = grid.next() ICON_CLOAK = AtlasSkinElement(ResourceLocation(OverdriveThatMatters.MOD_ID, "android_stuff-${i++}"))
ICON_GRAVITATIONAL_STABILIZER = grid.next() ICON_GRAVITATIONAL_STABILIZER = AtlasSkinElement(ResourceLocation(OverdriveThatMatters.MOD_ID, "android_stuff-${i++}"))
ICON_AIR_BAGS = grid.next() ICON_AIR_BAGS = AtlasSkinElement(ResourceLocation(OverdriveThatMatters.MOD_ID, "android_stuff-${i++}"))
ICON_JUMP_BOOST = grid.next() ICON_JUMP_BOOST = AtlasSkinElement(ResourceLocation(OverdriveThatMatters.MOD_ID, "android_stuff-${i++}"))
ICON_FEATHER_FALLING = AtlasSkinElement(ResourceLocation(OverdriveThatMatters.MOD_ID, "android_stuff-${i++}"))
ICON_FEATHER_FALLING = grid.next() ICON_ITEM_MAGNET = AtlasSkinElement(ResourceLocation(OverdriveThatMatters.MOD_ID, "android_stuff-${i++}"))
ICON_ITEM_MAGNET = grid.next() ICON_ARROW = AtlasSkinElement(ResourceLocation(OverdriveThatMatters.MOD_ID, "android_stuff-${i++}"))
ICON_ARROW = grid.next() ICON_ARMOR = AtlasSkinElement(ResourceLocation(OverdriveThatMatters.MOD_ID, "android_stuff-${i++}"))
ICON_ARMOR = grid.next() ICON_NANOBOTS = AtlasSkinElement(ResourceLocation(OverdriveThatMatters.MOD_ID, "android_stuff-${i++}"))
ICON_NANOBOTS = grid.next() ICON_NIGHT_VISION = AtlasSkinElement(ResourceLocation(OverdriveThatMatters.MOD_ID, "android_stuff-${i++}"))
ICON_NIGHT_VISION = grid.next() ICON_OXYGEN_SUPPLY = AtlasSkinElement(ResourceLocation(OverdriveThatMatters.MOD_ID, "android_stuff-${i++}"))
ICON_OXYGEN_SUPPLY = grid.next() ICON_PLASMA_SHIELD = AtlasSkinElement(ResourceLocation(OverdriveThatMatters.MOD_ID, "android_stuff-${i++}"))
ICON_SHOCKWAVE = AtlasSkinElement(ResourceLocation(OverdriveThatMatters.MOD_ID, "android_stuff-${i++}"))
ICON_PLASMA_SHIELD = grid.next() ICON_LIMB_OVERCLOCKING = AtlasSkinElement(ResourceLocation(OverdriveThatMatters.MOD_ID, "android_stuff-${i++}"))
ICON_SHOCKWAVE = grid.next() ICON_STEP_ASSIST = AtlasSkinElement(ResourceLocation(OverdriveThatMatters.MOD_ID, "android_stuff-${i++}"))
ICON_LIMB_OVERCLOCKING = grid.next() ICON_ENDER_TELEPORT = AtlasSkinElement(ResourceLocation(OverdriveThatMatters.MOD_ID, "android_stuff-${i++}"))
ICON_STEP_ASSIST = grid.next() ICON_WIRELESS_CHARGING = AtlasSkinElement(ResourceLocation(OverdriveThatMatters.MOD_ID, "android_stuff-${i++}"))
ICON_ENDER_TELEPORT = grid.next() ICON_UNKNOWN = AtlasSkinElement(ResourceLocation(OverdriveThatMatters.MOD_ID, "android_stuff-${i++}"))
ICON_WIRELESS_CHARGING = grid.next() ICON_EXTENDED_REACH = AtlasSkinElement(ResourceLocation(OverdriveThatMatters.MOD_ID, "android_stuff-${i++}"))
ICON_UNKNOWN = grid.next() ICON_PHANTOM_ATTRACTOR = AtlasSkinElement(ResourceLocation(OverdriveThatMatters.MOD_ID, "android_stuff-${i++}"))
ICON_EXTENDED_REACH = grid.next()
ICON_PHANTOM_ATTRACTOR = grid.next()
} }
} }

View File

@ -12,11 +12,8 @@ import com.google.gson.TypeAdapter
import com.google.gson.internal.bind.TypeAdapters import com.google.gson.internal.bind.TypeAdapters
import com.google.gson.stream.JsonReader import com.google.gson.stream.JsonReader
import com.google.gson.stream.JsonWriter import com.google.gson.stream.JsonWriter
import com.mojang.blaze3d.systems.RenderSystem
import com.mojang.blaze3d.vertex.PoseStack
import net.minecraft.network.FriendlyByteBuf import net.minecraft.network.FriendlyByteBuf
import net.minecraft.resources.ResourceLocation import net.minecraft.resources.ResourceLocation
import ru.dbotthepony.mc.otm.client.screen.panels.DockProperty
import ru.dbotthepony.mc.otm.core.set import ru.dbotthepony.mc.otm.core.set
import java.lang.reflect.Type import java.lang.reflect.Type
@ -54,16 +51,16 @@ fun ResourceLocation.vLine(
@Suppress("unused") @Suppress("unused")
data class SkinElement @JvmOverloads constructor( data class SkinElement @JvmOverloads constructor(
val texture: ResourceLocation, override val texture: ResourceLocation,
val x: Float, override val x: Float,
val y: Float, override val y: Float,
val width: Float, override val width: Float,
val height: Float, override val height: Float,
val imageWidth: Float = 256f, val imageWidth: Float = 256f,
val imageHeight: Float = 256f, val imageHeight: Float = 256f,
val winding: UVWindingOrder = UVWindingOrder.NORMAL override val winding: UVWindingOrder = UVWindingOrder.NORMAL,
) { ) : AbstractSkinElement() {
fun toJson(): JsonObject { override fun toJson(): JsonObject {
return JsonObject().also { return JsonObject().also {
it["texture"] = JsonPrimitive(texture.toString()) it["texture"] = JsonPrimitive(texture.toString())
it["x"] = JsonPrimitive(x) it["x"] = JsonPrimitive(x)
@ -76,7 +73,7 @@ data class SkinElement @JvmOverloads constructor(
} }
} }
fun toNetwork(buff: FriendlyByteBuf) { override fun toNetwork(buff: FriendlyByteBuf) {
buff.writeUtf(texture.toString()) buff.writeUtf(texture.toString())
buff.writeFloat(x) buff.writeFloat(x)
buff.writeFloat(y) buff.writeFloat(y)
@ -149,250 +146,8 @@ data class SkinElement @JvmOverloads constructor(
require(imageHeight > 0f) { "Invalid image height $imageHeight" } require(imageHeight > 0f) { "Invalid image height $imageHeight" }
} }
/** override val u0 = this.x / imageWidth
* See [ru.dbotthepony.mc.otm.client.render.clearDepth] override val v0 = this.y / imageHeight
*/ override val u1 = (this.x + width) / imageWidth
fun clearDepth( override val v1 = (this.y + height) / imageHeight
stack: PoseStack,
x: Float = 0f,
y: Float = 0f,
width: Float = this.width,
height: Float = this.height,
) = ru.dbotthepony.mc.otm.client.render.clearDepth(stack, x, y, width, height)
@JvmOverloads
fun render(
stack: PoseStack,
x: Float = 0f,
y: Float = 0f,
width: Float = this.width,
height: Float = this.height,
winding: UVWindingOrder = this.winding
) {
RenderSystem.setShaderTexture(0, texture)
RenderSystem.enableBlend()
RenderSystem.defaultBlendFunc()
renderRaw(stack, x, y, width, height, winding)
} }
@JvmOverloads
fun render(
stack: PoseStack,
x: Double,
y: Double = 0.0,
width: Double = this.width.toDouble(),
height: Double = this.height.toDouble(),
winding: UVWindingOrder = this.winding
) = render(stack, x.toFloat(), y.toFloat(), width.toFloat(), height.toFloat(), winding)
@JvmOverloads
fun renderPartial(
stack: PoseStack,
x: Float = 0f,
y: Float = 0f,
width: Float = this.width,
height: Float = this.height,
winding: UVWindingOrder = this.winding
) {
RenderSystem.setShaderTexture(0, texture)
RenderSystem.enableBlend()
RenderSystem.defaultBlendFunc()
renderRawPartial(stack, x, y, width, height, winding)
}
@JvmOverloads
fun renderPartial(
stack: PoseStack,
x: Double,
y: Double = 0.0,
width: Double = this.width.toDouble(),
height: Double = this.height.toDouble(),
winding: UVWindingOrder = this.winding
) = renderPartial(stack, x.toFloat(), y.toFloat(), width.toFloat(), height.toFloat(), winding)
@JvmOverloads
fun renderWidth(
stack: PoseStack,
x: Float = 0f,
y: Float = 0f,
width: Float = this.width,
winding: UVWindingOrder = this.winding
) {
render(stack, x, y, width = width, winding = winding)
}
@JvmOverloads
fun renderWidth(
stack: PoseStack,
x: Double,
y: Double = 0.0,
width: Double = this.width.toDouble(),
winding: UVWindingOrder = this.winding,
) = renderWidth(stack, x.toFloat(), y.toFloat(), width.toFloat(), winding)
@JvmOverloads
fun renderHeight(
stack: PoseStack,
x: Float = 0f,
y: Float = 0f,
height: Float = this.height,
winding: UVWindingOrder = this.winding,
) {
render(stack, x, y, height = height, winding = winding)
}
@JvmOverloads
fun renderHeight(
stack: PoseStack,
x: Double,
y: Double = 0.0,
height: Double = this.height.toDouble(),
winding: UVWindingOrder = this.winding,
) = renderHeight(stack, x.toFloat(), y.toFloat(), height.toFloat(), winding)
val u0 = this.x / imageWidth
val v0 = this.y / imageHeight
val u1 = (this.x + width) / imageWidth
val v1 = (this.y + height) / imageHeight
@JvmOverloads
fun renderRaw(
stack: PoseStack,
x: Float = 0f,
y: Float = 0f,
width: Float = this.width,
height: Float = this.height,
winding: UVWindingOrder = UVWindingOrder.NORMAL
) {
val winded = winding.translate(u0, v0, u1, v1)
drawTexturedRect(
stack,
x,
y,
width,
height,
winded,
)
}
@JvmOverloads
fun renderRaw(
stack: PoseStack,
x: Double,
y: Double = 0.0,
width: Double = this.width.toDouble(),
height: Double = this.height.toDouble(),
winding: UVWindingOrder = UVWindingOrder.NORMAL
) = renderRaw(stack, x.toFloat(), y.toFloat(), width.toFloat(), height.toFloat(), winding)
@JvmOverloads
fun renderRawPartial(
stack: PoseStack,
x: Float = 0f,
y: Float = 0f,
width: Float = this.width,
height: Float = this.height,
winding: UVWindingOrder = UVWindingOrder.NORMAL
) {
val u1 = (this.x + width) / imageWidth
val v1 = (this.y + height) / imageHeight
val winded = winding.translate(u0, v0, u1, v1)
drawTexturedRect(
stack,
x,
y,
width,
height,
winded,
)
}
@JvmOverloads
fun renderRawPartial(
stack: PoseStack,
x: Double,
y: Double = 0.0,
width: Double = this.width.toDouble(),
height: Double = this.height.toDouble(),
winding: UVWindingOrder = UVWindingOrder.NORMAL
) = renderRawPartial(stack, x.toFloat(), y.toFloat(), width.toFloat(), height.toFloat(), winding)
}
data class StretchingRectangleElement(
val topLeft: SkinElement,
val topRight: SkinElement,
val bottomLeft: SkinElement,
val bottomRight: SkinElement,
val left: SkinElement,
val right: SkinElement,
val top: SkinElement,
val bottom: SkinElement,
val middle: SkinElement,
val padding: DockProperty = DockProperty.EMPTY
) {
fun render(
stack: PoseStack,
x: Float = 0f,
y: Float = 0f,
width: Float,
height: Float,
) {
val bgWidth = width - topLeft.width.coerceAtMost(bottomLeft.width) - topRight.width.coerceAtMost(bottomRight.width) - padding.left - padding.right
val bgHeight = height - topLeft.height.coerceAtMost(bottomLeft.height) - topRight.height.coerceAtMost(bottomRight.height) - padding.top - padding.bottom
if (bgWidth > 0 && bgHeight > 0) {
middle.render(stack, x + topLeft.width + padding.left, y + topLeft.height + padding.top, bgWidth, bgHeight)
}
top.render(stack, x + topLeft.width, y, width = width - topLeft.width - topRight.width)
bottom.render(stack, x + bottomLeft.width, y + height - bottom.height, width = width - bottomLeft.width - bottomRight.width)
left.render(stack, x, y + topLeft.height, height = height - topLeft.height - bottomLeft.height)
right.render(stack, x + width - right.width, y + topRight.height, height = height - topRight.height - bottomRight.height)
topLeft.render(stack, x, y)
topRight.render(stack, x + width - topRight.width, y)
bottomLeft.render(stack, x, y + height - bottomLeft.height)
bottomRight.render(stack, x + width - bottomRight.width, y + height - bottomLeft.height)
}
companion object {
fun square(
texture: ResourceLocation,
x: Float,
y: Float,
cornerWidth: Float,
cornerHeight: Float,
width: Float,
height: Float,
sideThickness: Float,
imageWidth: Float = 256f,
imageHeight: Float = 256f,
): StretchingRectangleElement {
val innerThickness = sideThickness.coerceAtLeast(cornerWidth).coerceAtLeast(cornerHeight)
val padding = sideThickness - innerThickness
return StretchingRectangleElement(
topLeft = texture.element(x, y, cornerWidth, cornerHeight, imageWidth, imageHeight),
topRight = texture.element(x + width - cornerWidth, y, cornerWidth, cornerHeight, imageWidth, imageHeight),
bottomLeft = texture.element(x, y + height - cornerHeight, cornerWidth, cornerHeight, imageWidth, imageHeight),
bottomRight = texture.element(x + width - cornerWidth, y + height - cornerHeight, cornerWidth, cornerHeight, imageWidth, imageHeight),
top = texture.element(x + cornerWidth, y, width - cornerWidth * 2f, sideThickness, imageWidth, imageHeight),
bottom = texture.element(x + cornerWidth, y + height - sideThickness, width - cornerWidth * 2f, sideThickness, imageWidth, imageHeight),
left = texture.element(x, y, sideThickness, height - cornerHeight * 2f, imageWidth, imageHeight),
right = texture.element(x, y + width - sideThickness, sideThickness, height - cornerHeight * 2f, imageWidth, imageHeight),
middle = texture.element(x + innerThickness, y + innerThickness, width - innerThickness * 2f, height - innerThickness * 2f, imageWidth, imageHeight),
padding = DockProperty(padding, padding, padding, padding)
)
}
}
}

View File

@ -0,0 +1,127 @@
package ru.dbotthepony.mc.otm.client.render
import com.mojang.blaze3d.vertex.PoseStack
import net.minecraft.resources.ResourceLocation
import ru.dbotthepony.mc.otm.client.screen.panels.DockProperty
data class StretchingRectangleElement(
val topLeft: AbstractSkinElement,
val topRight: AbstractSkinElement,
val bottomLeft: AbstractSkinElement,
val bottomRight: AbstractSkinElement,
val left: AbstractSkinElement,
val right: AbstractSkinElement,
val top: AbstractSkinElement,
val bottom: AbstractSkinElement,
val middle: AbstractSkinElement,
val padding: DockProperty = DockProperty.EMPTY
) {
fun render(
stack: PoseStack,
x: Float = 0f,
y: Float = 0f,
width: Float,
height: Float,
) {
val bgWidth = width - topLeft.width.coerceAtMost(bottomLeft.width) - topRight.width.coerceAtMost(bottomRight.width) - padding.left - padding.right
val bgHeight = height - topLeft.height.coerceAtMost(bottomLeft.height) - topRight.height.coerceAtMost(bottomRight.height) - padding.top - padding.bottom
if (bgWidth > 0 && bgHeight > 0) {
middle.render(stack, x + topLeft.width + padding.left, y + topLeft.height + padding.top, bgWidth, bgHeight)
}
top.render(stack, x + topLeft.width, y, width = width - topLeft.width - topRight.width)
bottom.render(stack, x + bottomLeft.width, y + height - bottom.height, width = width - bottomLeft.width - bottomRight.width)
left.render(stack, x, y + topLeft.height, height = height - topLeft.height - bottomLeft.height)
right.render(stack, x + width - right.width, y + topRight.height, height = height - topRight.height - bottomRight.height)
topLeft.render(stack, x, y)
topRight.render(stack, x + width - topRight.width, y)
bottomLeft.render(stack, x, y + height - bottomLeft.height)
bottomRight.render(stack, x + width - bottomRight.width, y + height - bottomLeft.height)
}
companion object {
fun square(
texture: ResourceLocation,
x: Float,
y: Float,
cornerWidth: Float,
cornerHeight: Float,
width: Float,
height: Float,
sideThickness: Float,
imageWidth: Float = 256f,
imageHeight: Float = 256f,
): StretchingRectangleElement {
val innerThickness = sideThickness.coerceAtLeast(cornerWidth).coerceAtLeast(cornerHeight)
val padding = sideThickness - innerThickness
return StretchingRectangleElement(
topLeft = texture.element(x, y, cornerWidth, cornerHeight, imageWidth, imageHeight),
topRight = texture.element(
x + width - cornerWidth,
y,
cornerWidth,
cornerHeight,
imageWidth,
imageHeight
),
bottomLeft = texture.element(
x,
y + height - cornerHeight,
cornerWidth,
cornerHeight,
imageWidth,
imageHeight
),
bottomRight = texture.element(
x + width - cornerWidth,
y + height - cornerHeight,
cornerWidth,
cornerHeight,
imageWidth,
imageHeight
),
top = texture.element(
x + cornerWidth,
y,
width - cornerWidth * 2f,
sideThickness,
imageWidth,
imageHeight
),
bottom = texture.element(
x + cornerWidth,
y + height - sideThickness,
width - cornerWidth * 2f,
sideThickness,
imageWidth,
imageHeight
),
left = texture.element(x, y, sideThickness, height - cornerHeight * 2f, imageWidth, imageHeight),
right = texture.element(
x,
y + width - sideThickness,
sideThickness,
height - cornerHeight * 2f,
imageWidth,
imageHeight
),
middle = texture.element(
x + innerThickness,
y + innerThickness,
width - innerThickness * 2f,
height - innerThickness * 2f,
imageWidth,
imageHeight
),
padding = DockProperty(padding, padding, padding, padding)
)
}
}
}

View File

@ -0,0 +1,78 @@
package ru.dbotthepony.mc.otm.client.render
import net.minecraft.client.renderer.texture.TextureAtlas
import net.minecraft.client.renderer.texture.TextureAtlasSprite
import net.minecraft.client.renderer.texture.TextureManager
import net.minecraft.client.resources.TextureAtlasHolder
import net.minecraft.resources.ResourceLocation
import net.minecraft.server.packs.resources.ReloadableResourceManager
import net.minecraft.server.packs.resources.ResourceManager
import net.minecraft.util.profiling.ProfilerFiller
import net.minecraftforge.client.event.RegisterClientReloadListenersEvent
import ru.dbotthepony.mc.otm.OverdriveThatMatters
import ru.dbotthepony.mc.otm.client.minecraft
import ru.dbotthepony.mc.otm.client.onceClient
import ru.dbotthepony.mc.otm.registry.WriteOnce
import java.util.stream.Stream
import kotlin.properties.Delegates
var isWidgetAtlasAvailable: Boolean = false
private set
class WidgetAtlasHolder private constructor(manager: TextureManager) : TextureAtlasHolder(manager, LOCATION, "gui") {
var changeset = 0
private set
private var queued = false
private var once = false
private var resourceManager by Delegates.notNull<ResourceManager>()
private var profileManager by Delegates.notNull<ProfilerFiller>()
override fun prepare(p_118891_: ResourceManager, p_118892_: ProfilerFiller): TextureAtlas.Preparations {
once = true
resourceManager = p_118891_
profileManager = p_118892_
return super.prepare(p_118891_, p_118892_)
}
public override fun getSprite(p_118902_: ResourceLocation): TextureAtlasSprite {
if (!once) {
throw IllegalStateException("Trying to get sprite too early")
}
return super.getSprite(p_118902_)
}
fun queueRebuild() {
if (!queued && once) {
queued = true
onceClient(20) {
queued = false
apply(prepare(resourceManager, profileManager), resourceManager, profileManager)
}
}
}
override fun getResourcesToLoad(): Stream<ResourceLocation> {
changeset++
return AtlasSkinElement.keys
}
companion object {
@JvmStatic
val LOCATION = ResourceLocation(OverdriveThatMatters.MOD_ID, "textures/atlas/gui.png")
@JvmStatic
var INSTANCE: WidgetAtlasHolder by WriteOnce()
private set
@JvmStatic
fun register(event: RegisterClientReloadListenersEvent) {
INSTANCE = WidgetAtlasHolder(minecraft.textureManager)
event.registerReloadListener(INSTANCE)
isWidgetAtlasAvailable = true
}
}
}

View File

@ -303,7 +303,7 @@ private class AndroidResearchButton(
AndroidStationScreen.CAN_NOT_BE_RESEARCHED.setSystemColor() AndroidStationScreen.CAN_NOT_BE_RESEARCHED.setSystemColor()
} }
val icon = node.type.skinIcon val icon = node.type.resolvedSkinIcon
val itemIcon = node.type.itemIcon val itemIcon = node.type.itemIcon
if (icon != null) { if (icon != null) {

View File

@ -1,5 +1,7 @@
package ru.dbotthepony.mc.otm.core package ru.dbotthepony.mc.otm.core
import org.apache.logging.log4j.LogManager
class TimerQueue { class TimerQueue {
private var ticks = 0 private var ticks = 0
private val list = ArrayDeque<Timer>() private val list = ArrayDeque<Timer>()
@ -48,6 +50,15 @@ class TimerQueue {
} }
} }
fun add(timerTicks: Int, ticker: Runnable, condition: Boolean, reason: String): Timer? {
if (!condition) {
LOGGER.error("Refusing to add timer $ticker in $timerTicks ticks because we $reason", IllegalStateException(reason))
return null
}
return Timer(timerTicks, ticker)
}
fun tick() { fun tick() {
ticks++ ticks++
@ -67,4 +78,8 @@ class TimerQueue {
ticks = 0 ticks = 0
list.clear() list.clear()
} }
companion object {
private val LOGGER = LogManager.getLogger()
}
} }

View File

@ -45,3 +45,5 @@ protected net.minecraft.client.gui.screens.inventory.AbstractContainerScreen m_9
protected net.minecraft.client.gui.screens.inventory.AbstractContainerScreen m_97818_()V # recalculateQuickCraftRemaining protected net.minecraft.client.gui.screens.inventory.AbstractContainerScreen m_97818_()V # recalculateQuickCraftRemaining
protected net.minecraft.client.gui.screens.inventory.AbstractContainerScreen m_97744_(DD)Lnet/minecraft/world/inventory/Slot; # findSlot protected net.minecraft.client.gui.screens.inventory.AbstractContainerScreen m_97744_(DD)Lnet/minecraft/world/inventory/Slot; # findSlot
protected net.minecraft.client.gui.screens.inventory.AbstractContainerScreen m_97782_(Lnet/minecraft/world/item/ItemStack;IILjava/lang/String;)V # renderFloatingItem protected net.minecraft.client.gui.screens.inventory.AbstractContainerScreen m_97782_(Lnet/minecraft/world/item/ItemStack;IILjava/lang/String;)V # renderFloatingItem
protected net.minecraft.client.resources.TextureAtlasHolder f_118884_ # textureAtlas

Binary file not shown.

After

Width:  |  Height:  |  Size: 383 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 408 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 407 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 427 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 376 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 411 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 375 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 399 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 402 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 387 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 383 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 383 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 382 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 399 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 395 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 385 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 407 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 372 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 370 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 386 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 384 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 377 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 414 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 376 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 399 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 2.5 KiB