diff --git a/gradle.properties b/gradle.properties index afaef7038..e80d6a0ff 100644 --- a/gradle.properties +++ b/gradle.properties @@ -1,6 +1,6 @@ # 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. -org.gradle.jvmargs=-Xmx3G -XX:+UseParallelGC +org.gradle.jvmargs=-Xmx3G org.gradle.daemon=true kotlin.stdlib.default.dependency=false diff --git a/src/main/java/ru/dbotthepony/mc/otm/OverdriveThatMatters.java b/src/main/java/ru/dbotthepony/mc/otm/OverdriveThatMatters.java index 2b4ddfdc7..83b9209de 100644 --- a/src/main/java/ru/dbotthepony/mc/otm/OverdriveThatMatters.java +++ b/src/main/java/ru/dbotthepony/mc/otm/OverdriveThatMatters.java @@ -31,6 +31,7 @@ import ru.dbotthepony.mc.otm.client.ClientTickHandlerKt; import ru.dbotthepony.mc.otm.client.MatteryGUI; import ru.dbotthepony.mc.otm.client.model.GravitationStabilizerModel; 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.TooltipsKt; 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, TritaniumArmorModel::register); modBus.addListener(EventPriority.NORMAL, GravitationStabilizerModel::register); + modBus.addListener(EventPriority.NORMAL, WidgetAtlasHolder::register); }); ClientConfig.INSTANCE.register(); diff --git a/src/main/kotlin/ru/dbotthepony/mc/otm/android/AndroidResearchType.kt b/src/main/kotlin/ru/dbotthepony/mc/otm/android/AndroidResearchType.kt index 10d6afeca..75a8b9342 100644 --- a/src/main/kotlin/ru/dbotthepony/mc/otm/android/AndroidResearchType.kt +++ b/src/main/kotlin/ru/dbotthepony/mc/otm/android/AndroidResearchType.kt @@ -7,6 +7,7 @@ import com.google.gson.JsonElement import com.google.gson.JsonObject import com.google.gson.JsonPrimitive import com.google.gson.JsonSyntaxException +import com.google.gson.internal.bind.TypeAdapters import net.minecraft.network.FriendlyByteBuf import net.minecraft.network.chat.Component 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.level.ItemLike 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.core.ListSet 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.toImmutableList import ru.dbotthepony.mc.otm.data.stream +import ru.dbotthepony.mc.otm.isClient import ru.dbotthepony.mc.otm.registry.MRegistry import java.util.LinkedList import java.util.stream.Stream @@ -88,16 +91,22 @@ class AndroidResearchType( val experienceLevels: Int = 0, private val customName: Component? = null, - // why pack these into research itself? - // because Minecraft itself does this - // check out advancements - val skinIcon: SkinElement? = null, + // ok + val skinIcon: JsonElement? = null, val itemIcon: Item? = null, iconText: Component? = null, ) { private val iconTextValue = iconText?.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( val id: ResourceLocation, val isRigid: Boolean @@ -471,7 +480,7 @@ class AndroidResearchType( it["experience"] = JsonPrimitive(experienceLevels) if (skinIcon != null) { - it["skin_icon"] = skinIcon.toJson() + it["skin_icon"] = skinIcon } if (itemIcon != null) { @@ -511,7 +520,7 @@ class AndroidResearchType( if (iconTextValue != null) buff.writeComponent(iconTextValue) buff.writeBoolean(skinIcon != null) - skinIcon?.toNetwork(buff) + if (skinIcon != null) buff.writeUtf(skinIcon.toString()) buff.writeBoolean(itemIcon != null) if (itemIcon != null) buff.writeUtf(itemIcon.registryName!!.toString()) @@ -541,7 +550,7 @@ class AndroidResearchType( } val skinIcon = if (buff.readBoolean()) { - SkinElement.fromNetwork(buff) + TypeAdapters.JSON_ELEMENT.fromJson(buff.readUtf()) } else { null } @@ -582,7 +591,7 @@ class AndroidResearchType( val experience = value["experience"]?.asInt ?: 0 val customName = value["custom_name"]?.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 } } return AndroidResearchType( @@ -615,7 +624,7 @@ class AndroidResearchType( var description: MutableList? = null, var descriptionSuppliers: MutableList? = null, var itemIcon: Item? = null, - var skinIcon: SkinElement? = null, + var skinIcon: AbstractSkinElement? = null, var iconText: Component? = null, ) { private val items = ArrayList>() @@ -629,7 +638,7 @@ class AndroidResearchType( return this } - fun withIcon(icon: SkinElement? = null): Builder { + fun withIcon(icon: AbstractSkinElement? = null): Builder { this.skinIcon = icon this.itemIcon = null return this @@ -840,7 +849,7 @@ class AndroidResearchType( descriptionSuppliers = descriptionSuppliers ?: listOf(), experienceLevels = experience, customName = customName, - skinIcon = skinIcon, + skinIcon = skinIcon?.toJson(), itemIcon = itemIcon, iconText = iconText ).also { if (validate) it.validate() } diff --git a/src/main/kotlin/ru/dbotthepony/mc/otm/client/ClientTickHandler.kt b/src/main/kotlin/ru/dbotthepony/mc/otm/client/ClientTickHandler.kt index f443f7539..d3eb21b76 100644 --- a/src/main/kotlin/ru/dbotthepony/mc/otm/client/ClientTickHandler.kt +++ b/src/main/kotlin/ru/dbotthepony/mc/otm/client/ClientTickHandler.kt @@ -25,6 +25,16 @@ fun onceClientPre(ticker: ITickable) { 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) { check(isClient) { "Illegal side" } postTickList.add(ticker, LOGGED_IN, "Not logged in") diff --git a/src/main/kotlin/ru/dbotthepony/mc/otm/client/render/AbstractSkinElement.kt b/src/main/kotlin/ru/dbotthepony/mc/otm/client/render/AbstractSkinElement.kt new file mode 100644 index 000000000..6b349f0d0 --- /dev/null +++ b/src/main/kotlin/ru/dbotthepony/mc/otm/client/render/AbstractSkinElement.kt @@ -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(), JsonSerializer, JsonDeserializer { + 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) + } + } +} diff --git a/src/main/kotlin/ru/dbotthepony/mc/otm/client/render/AtlasSkinElement.kt b/src/main/kotlin/ru/dbotthepony/mc/otm/client/render/AtlasSkinElement.kt new file mode 100644 index 000000000..671c8aa31 --- /dev/null +++ b/src/main/kotlin/ru/dbotthepony/mc/otm/client/render/AtlasSkinElement.kt @@ -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(), JsonSerializer, JsonDeserializer { + private val skinElementCache = HashMap() + + val keys: Stream 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) + } + } +} diff --git a/src/main/kotlin/ru/dbotthepony/mc/otm/client/render/ResearchIcons.kt b/src/main/kotlin/ru/dbotthepony/mc/otm/client/render/ResearchIcons.kt index 0ead968cb..e31000426 100644 --- a/src/main/kotlin/ru/dbotthepony/mc/otm/client/render/ResearchIcons.kt +++ b/src/main/kotlin/ru/dbotthepony/mc/otm/client/render/ResearchIcons.kt @@ -4,64 +4,60 @@ import net.minecraft.resources.ResourceLocation import ru.dbotthepony.mc.otm.OverdriveThatMatters object ResearchIcons { - val ICONS = ResourceLocation(OverdriveThatMatters.MOD_ID, "textures/gui/android_upgrades.png") - val ICON_TRANSFER: SkinElement - val ICON_ATTACK_BOOST: SkinElement - val ICON_PLASMA_SHIELD_BOOST: SkinElement - val ICON_CLOAK: SkinElement - val ICON_GRAVITATIONAL_STABILIZER: SkinElement - val ICON_AIR_BAGS: SkinElement - val ICON_JUMP_BOOST: SkinElement + val ICON_TRANSFER: AbstractSkinElement + val ICON_ATTACK_BOOST: AbstractSkinElement + val ICON_PLASMA_SHIELD_BOOST: AbstractSkinElement + val ICON_CLOAK: AbstractSkinElement + val ICON_GRAVITATIONAL_STABILIZER: AbstractSkinElement + val ICON_AIR_BAGS: AbstractSkinElement + val ICON_JUMP_BOOST: AbstractSkinElement - val ICON_FEATHER_FALLING: SkinElement - val ICON_ITEM_MAGNET: SkinElement - val ICON_ARROW: SkinElement - val ICON_ARMOR: SkinElement - val ICON_NANOBOTS: SkinElement - val ICON_NIGHT_VISION: SkinElement - val ICON_OXYGEN_SUPPLY: SkinElement + val ICON_FEATHER_FALLING: AbstractSkinElement + val ICON_ITEM_MAGNET: AbstractSkinElement + val ICON_ARROW: AbstractSkinElement + val ICON_ARMOR: AbstractSkinElement + val ICON_NANOBOTS: AbstractSkinElement + val ICON_NIGHT_VISION: AbstractSkinElement + val ICON_OXYGEN_SUPPLY: AbstractSkinElement - val ICON_PLASMA_SHIELD: SkinElement - val ICON_SHOCKWAVE: SkinElement - val ICON_LIMB_OVERCLOCKING: SkinElement - val ICON_STEP_ASSIST: SkinElement - val ICON_ENDER_TELEPORT: SkinElement - val ICON_WIRELESS_CHARGING: SkinElement - val ICON_UNKNOWN: SkinElement + val ICON_PLASMA_SHIELD: AbstractSkinElement + val ICON_SHOCKWAVE: AbstractSkinElement + val ICON_LIMB_OVERCLOCKING: AbstractSkinElement + val ICON_STEP_ASSIST: AbstractSkinElement + val ICON_ENDER_TELEPORT: AbstractSkinElement + val ICON_WIRELESS_CHARGING: AbstractSkinElement + val ICON_UNKNOWN: AbstractSkinElement - val ICON_EXTENDED_REACH: SkinElement - val ICON_PHANTOM_ATTRACTOR: SkinElement + val ICON_EXTENDED_REACH: AbstractSkinElement + val ICON_PHANTOM_ATTRACTOR: AbstractSkinElement val KOT = ResourceLocation(OverdriveThatMatters.MOD_ID, "textures/block/ph_kitty.png").element(0f, 0f, 32f, 32f, 32f, 32f) init { - val grid = SkinGrid(ICONS, 18f, 18f, 7, 7) + var i = 0 - ICON_TRANSFER = grid.next() - ICON_ATTACK_BOOST = grid.next() - ICON_PLASMA_SHIELD_BOOST = grid.next() - ICON_CLOAK = grid.next() - ICON_GRAVITATIONAL_STABILIZER = grid.next() - ICON_AIR_BAGS = grid.next() - ICON_JUMP_BOOST = grid.next() - - ICON_FEATHER_FALLING = grid.next() - ICON_ITEM_MAGNET = grid.next() - ICON_ARROW = grid.next() - ICON_ARMOR = grid.next() - ICON_NANOBOTS = grid.next() - ICON_NIGHT_VISION = grid.next() - ICON_OXYGEN_SUPPLY = grid.next() - - ICON_PLASMA_SHIELD = grid.next() - ICON_SHOCKWAVE = grid.next() - ICON_LIMB_OVERCLOCKING = grid.next() - ICON_STEP_ASSIST = grid.next() - ICON_ENDER_TELEPORT = grid.next() - ICON_WIRELESS_CHARGING = grid.next() - ICON_UNKNOWN = grid.next() - - ICON_EXTENDED_REACH = grid.next() - ICON_PHANTOM_ATTRACTOR = grid.next() + ICON_TRANSFER = AtlasSkinElement(ResourceLocation(OverdriveThatMatters.MOD_ID, "android_stuff-${i++}")) + ICON_ATTACK_BOOST = AtlasSkinElement(ResourceLocation(OverdriveThatMatters.MOD_ID, "android_stuff-${i++}")) + ICON_PLASMA_SHIELD_BOOST = AtlasSkinElement(ResourceLocation(OverdriveThatMatters.MOD_ID, "android_stuff-${i++}")) + ICON_CLOAK = AtlasSkinElement(ResourceLocation(OverdriveThatMatters.MOD_ID, "android_stuff-${i++}")) + ICON_GRAVITATIONAL_STABILIZER = AtlasSkinElement(ResourceLocation(OverdriveThatMatters.MOD_ID, "android_stuff-${i++}")) + ICON_AIR_BAGS = AtlasSkinElement(ResourceLocation(OverdriveThatMatters.MOD_ID, "android_stuff-${i++}")) + ICON_JUMP_BOOST = AtlasSkinElement(ResourceLocation(OverdriveThatMatters.MOD_ID, "android_stuff-${i++}")) + ICON_FEATHER_FALLING = AtlasSkinElement(ResourceLocation(OverdriveThatMatters.MOD_ID, "android_stuff-${i++}")) + ICON_ITEM_MAGNET = AtlasSkinElement(ResourceLocation(OverdriveThatMatters.MOD_ID, "android_stuff-${i++}")) + ICON_ARROW = AtlasSkinElement(ResourceLocation(OverdriveThatMatters.MOD_ID, "android_stuff-${i++}")) + ICON_ARMOR = AtlasSkinElement(ResourceLocation(OverdriveThatMatters.MOD_ID, "android_stuff-${i++}")) + ICON_NANOBOTS = AtlasSkinElement(ResourceLocation(OverdriveThatMatters.MOD_ID, "android_stuff-${i++}")) + ICON_NIGHT_VISION = AtlasSkinElement(ResourceLocation(OverdriveThatMatters.MOD_ID, "android_stuff-${i++}")) + ICON_OXYGEN_SUPPLY = AtlasSkinElement(ResourceLocation(OverdriveThatMatters.MOD_ID, "android_stuff-${i++}")) + ICON_PLASMA_SHIELD = AtlasSkinElement(ResourceLocation(OverdriveThatMatters.MOD_ID, "android_stuff-${i++}")) + ICON_SHOCKWAVE = AtlasSkinElement(ResourceLocation(OverdriveThatMatters.MOD_ID, "android_stuff-${i++}")) + ICON_LIMB_OVERCLOCKING = AtlasSkinElement(ResourceLocation(OverdriveThatMatters.MOD_ID, "android_stuff-${i++}")) + ICON_STEP_ASSIST = AtlasSkinElement(ResourceLocation(OverdriveThatMatters.MOD_ID, "android_stuff-${i++}")) + ICON_ENDER_TELEPORT = AtlasSkinElement(ResourceLocation(OverdriveThatMatters.MOD_ID, "android_stuff-${i++}")) + ICON_WIRELESS_CHARGING = AtlasSkinElement(ResourceLocation(OverdriveThatMatters.MOD_ID, "android_stuff-${i++}")) + ICON_UNKNOWN = AtlasSkinElement(ResourceLocation(OverdriveThatMatters.MOD_ID, "android_stuff-${i++}")) + ICON_EXTENDED_REACH = AtlasSkinElement(ResourceLocation(OverdriveThatMatters.MOD_ID, "android_stuff-${i++}")) + ICON_PHANTOM_ATTRACTOR = AtlasSkinElement(ResourceLocation(OverdriveThatMatters.MOD_ID, "android_stuff-${i++}")) } } diff --git a/src/main/kotlin/ru/dbotthepony/mc/otm/client/render/SkinElement.kt b/src/main/kotlin/ru/dbotthepony/mc/otm/client/render/SkinElement.kt index 526f76608..8f9a39c81 100644 --- a/src/main/kotlin/ru/dbotthepony/mc/otm/client/render/SkinElement.kt +++ b/src/main/kotlin/ru/dbotthepony/mc/otm/client/render/SkinElement.kt @@ -12,11 +12,8 @@ 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.client.screen.panels.DockProperty import ru.dbotthepony.mc.otm.core.set import java.lang.reflect.Type @@ -54,16 +51,16 @@ fun ResourceLocation.vLine( @Suppress("unused") data class SkinElement @JvmOverloads constructor( - val texture: ResourceLocation, - val x: Float, - val y: Float, - val width: Float, - val height: Float, + override val texture: ResourceLocation, + override val x: Float, + override val y: Float, + override val width: Float, + override val height: Float, val imageWidth: Float = 256f, val imageHeight: Float = 256f, - val winding: UVWindingOrder = UVWindingOrder.NORMAL -) { - fun toJson(): JsonObject { + override val winding: UVWindingOrder = UVWindingOrder.NORMAL, +) : AbstractSkinElement() { + override fun toJson(): JsonObject { return JsonObject().also { it["texture"] = JsonPrimitive(texture.toString()) 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.writeFloat(x) buff.writeFloat(y) @@ -149,250 +146,8 @@ data class SkinElement @JvmOverloads constructor( require(imageHeight > 0f) { "Invalid image height $imageHeight" } } - /** - * 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) - - 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) + override val u0 = this.x / imageWidth + override val v0 = this.y / imageHeight + override val u1 = (this.x + width) / imageWidth + override val v1 = (this.y + height) / imageHeight } - -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) - ) - } - } -} - diff --git a/src/main/kotlin/ru/dbotthepony/mc/otm/client/render/StretchingRectangleElement.kt b/src/main/kotlin/ru/dbotthepony/mc/otm/client/render/StretchingRectangleElement.kt new file mode 100644 index 000000000..8fe0010fb --- /dev/null +++ b/src/main/kotlin/ru/dbotthepony/mc/otm/client/render/StretchingRectangleElement.kt @@ -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) + ) + } + } +} diff --git a/src/main/kotlin/ru/dbotthepony/mc/otm/client/render/WidgetAtlasHolder.kt b/src/main/kotlin/ru/dbotthepony/mc/otm/client/render/WidgetAtlasHolder.kt new file mode 100644 index 000000000..0b858629a --- /dev/null +++ b/src/main/kotlin/ru/dbotthepony/mc/otm/client/render/WidgetAtlasHolder.kt @@ -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() + private var profileManager by Delegates.notNull() + + 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 { + 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 + } + } +} diff --git a/src/main/kotlin/ru/dbotthepony/mc/otm/client/screen/AndroidStationScreen.kt b/src/main/kotlin/ru/dbotthepony/mc/otm/client/screen/AndroidStationScreen.kt index f51d30da0..db5eb82c4 100644 --- a/src/main/kotlin/ru/dbotthepony/mc/otm/client/screen/AndroidStationScreen.kt +++ b/src/main/kotlin/ru/dbotthepony/mc/otm/client/screen/AndroidStationScreen.kt @@ -303,7 +303,7 @@ private class AndroidResearchButton( AndroidStationScreen.CAN_NOT_BE_RESEARCHED.setSystemColor() } - val icon = node.type.skinIcon + val icon = node.type.resolvedSkinIcon val itemIcon = node.type.itemIcon if (icon != null) { diff --git a/src/main/kotlin/ru/dbotthepony/mc/otm/core/TimerQueue.kt b/src/main/kotlin/ru/dbotthepony/mc/otm/core/TimerQueue.kt index 40e5ec0e7..35604a00a 100644 --- a/src/main/kotlin/ru/dbotthepony/mc/otm/core/TimerQueue.kt +++ b/src/main/kotlin/ru/dbotthepony/mc/otm/core/TimerQueue.kt @@ -1,5 +1,7 @@ package ru.dbotthepony.mc.otm.core +import org.apache.logging.log4j.LogManager + class TimerQueue { private var ticks = 0 private val list = ArrayDeque() @@ -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() { ticks++ @@ -67,4 +78,8 @@ class TimerQueue { ticks = 0 list.clear() } + + companion object { + private val LOGGER = LogManager.getLogger() + } } diff --git a/src/main/resources/META-INF/accesstransformer.cfg b/src/main/resources/META-INF/accesstransformer.cfg index 61f82a3ce..6d2453c24 100644 --- a/src/main/resources/META-INF/accesstransformer.cfg +++ b/src/main/resources/META-INF/accesstransformer.cfg @@ -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_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.resources.TextureAtlasHolder f_118884_ # textureAtlas diff --git a/src/main/resources/assets/overdrive_that_matters/textures/gui/android_stuff-0.png b/src/main/resources/assets/overdrive_that_matters/textures/gui/android_stuff-0.png new file mode 100644 index 000000000..d94769ae2 Binary files /dev/null and b/src/main/resources/assets/overdrive_that_matters/textures/gui/android_stuff-0.png differ diff --git a/src/main/resources/assets/overdrive_that_matters/textures/gui/android_stuff-1.png b/src/main/resources/assets/overdrive_that_matters/textures/gui/android_stuff-1.png new file mode 100644 index 000000000..256ccde1d Binary files /dev/null and b/src/main/resources/assets/overdrive_that_matters/textures/gui/android_stuff-1.png differ diff --git a/src/main/resources/assets/overdrive_that_matters/textures/gui/android_stuff-10.png b/src/main/resources/assets/overdrive_that_matters/textures/gui/android_stuff-10.png new file mode 100644 index 000000000..4d127e4d6 Binary files /dev/null and b/src/main/resources/assets/overdrive_that_matters/textures/gui/android_stuff-10.png differ diff --git a/src/main/resources/assets/overdrive_that_matters/textures/gui/android_stuff-11.png b/src/main/resources/assets/overdrive_that_matters/textures/gui/android_stuff-11.png new file mode 100644 index 000000000..48e4b0d38 Binary files /dev/null and b/src/main/resources/assets/overdrive_that_matters/textures/gui/android_stuff-11.png differ diff --git a/src/main/resources/assets/overdrive_that_matters/textures/gui/android_stuff-12.png b/src/main/resources/assets/overdrive_that_matters/textures/gui/android_stuff-12.png new file mode 100644 index 000000000..97ef5abe5 Binary files /dev/null and b/src/main/resources/assets/overdrive_that_matters/textures/gui/android_stuff-12.png differ diff --git a/src/main/resources/assets/overdrive_that_matters/textures/gui/android_stuff-13.png b/src/main/resources/assets/overdrive_that_matters/textures/gui/android_stuff-13.png new file mode 100644 index 000000000..ca7c89649 Binary files /dev/null and b/src/main/resources/assets/overdrive_that_matters/textures/gui/android_stuff-13.png differ diff --git a/src/main/resources/assets/overdrive_that_matters/textures/gui/android_stuff-14.png b/src/main/resources/assets/overdrive_that_matters/textures/gui/android_stuff-14.png new file mode 100644 index 000000000..4b56feda2 Binary files /dev/null and b/src/main/resources/assets/overdrive_that_matters/textures/gui/android_stuff-14.png differ diff --git a/src/main/resources/assets/overdrive_that_matters/textures/gui/android_stuff-15.png b/src/main/resources/assets/overdrive_that_matters/textures/gui/android_stuff-15.png new file mode 100644 index 000000000..69cdf547d Binary files /dev/null and b/src/main/resources/assets/overdrive_that_matters/textures/gui/android_stuff-15.png differ diff --git a/src/main/resources/assets/overdrive_that_matters/textures/gui/android_stuff-16.png b/src/main/resources/assets/overdrive_that_matters/textures/gui/android_stuff-16.png new file mode 100644 index 000000000..446c17f7d Binary files /dev/null and b/src/main/resources/assets/overdrive_that_matters/textures/gui/android_stuff-16.png differ diff --git a/src/main/resources/assets/overdrive_that_matters/textures/gui/android_stuff-17.png b/src/main/resources/assets/overdrive_that_matters/textures/gui/android_stuff-17.png new file mode 100644 index 000000000..38728ee3f Binary files /dev/null and b/src/main/resources/assets/overdrive_that_matters/textures/gui/android_stuff-17.png differ diff --git a/src/main/resources/assets/overdrive_that_matters/textures/gui/android_stuff-18.png b/src/main/resources/assets/overdrive_that_matters/textures/gui/android_stuff-18.png new file mode 100644 index 000000000..f4560d6cd Binary files /dev/null and b/src/main/resources/assets/overdrive_that_matters/textures/gui/android_stuff-18.png differ diff --git a/src/main/resources/assets/overdrive_that_matters/textures/gui/android_stuff-19.png b/src/main/resources/assets/overdrive_that_matters/textures/gui/android_stuff-19.png new file mode 100644 index 000000000..421e5fc94 Binary files /dev/null and b/src/main/resources/assets/overdrive_that_matters/textures/gui/android_stuff-19.png differ diff --git a/src/main/resources/assets/overdrive_that_matters/textures/gui/android_stuff-2.png b/src/main/resources/assets/overdrive_that_matters/textures/gui/android_stuff-2.png new file mode 100644 index 000000000..fa4be6283 Binary files /dev/null and b/src/main/resources/assets/overdrive_that_matters/textures/gui/android_stuff-2.png differ diff --git a/src/main/resources/assets/overdrive_that_matters/textures/gui/android_stuff-20.png b/src/main/resources/assets/overdrive_that_matters/textures/gui/android_stuff-20.png new file mode 100644 index 000000000..78067b180 Binary files /dev/null and b/src/main/resources/assets/overdrive_that_matters/textures/gui/android_stuff-20.png differ diff --git a/src/main/resources/assets/overdrive_that_matters/textures/gui/android_stuff-21.png b/src/main/resources/assets/overdrive_that_matters/textures/gui/android_stuff-21.png new file mode 100644 index 000000000..cc9d32fe3 Binary files /dev/null and b/src/main/resources/assets/overdrive_that_matters/textures/gui/android_stuff-21.png differ diff --git a/src/main/resources/assets/overdrive_that_matters/textures/gui/android_stuff-22.png b/src/main/resources/assets/overdrive_that_matters/textures/gui/android_stuff-22.png new file mode 100644 index 000000000..ea6ae2a55 Binary files /dev/null and b/src/main/resources/assets/overdrive_that_matters/textures/gui/android_stuff-22.png differ diff --git a/src/main/resources/assets/overdrive_that_matters/textures/gui/android_stuff-23.png b/src/main/resources/assets/overdrive_that_matters/textures/gui/android_stuff-23.png new file mode 100644 index 000000000..b29a0723b Binary files /dev/null and b/src/main/resources/assets/overdrive_that_matters/textures/gui/android_stuff-23.png differ diff --git a/src/main/resources/assets/overdrive_that_matters/textures/gui/android_stuff-24.png b/src/main/resources/assets/overdrive_that_matters/textures/gui/android_stuff-24.png new file mode 100644 index 000000000..05b214cad Binary files /dev/null and b/src/main/resources/assets/overdrive_that_matters/textures/gui/android_stuff-24.png differ diff --git a/src/main/resources/assets/overdrive_that_matters/textures/gui/android_stuff-3.png b/src/main/resources/assets/overdrive_that_matters/textures/gui/android_stuff-3.png new file mode 100644 index 000000000..10646c9ed Binary files /dev/null and b/src/main/resources/assets/overdrive_that_matters/textures/gui/android_stuff-3.png differ diff --git a/src/main/resources/assets/overdrive_that_matters/textures/gui/android_stuff-4.png b/src/main/resources/assets/overdrive_that_matters/textures/gui/android_stuff-4.png new file mode 100644 index 000000000..ecfeb4a92 Binary files /dev/null and b/src/main/resources/assets/overdrive_that_matters/textures/gui/android_stuff-4.png differ diff --git a/src/main/resources/assets/overdrive_that_matters/textures/gui/android_stuff-5.png b/src/main/resources/assets/overdrive_that_matters/textures/gui/android_stuff-5.png new file mode 100644 index 000000000..cfa7c2368 Binary files /dev/null and b/src/main/resources/assets/overdrive_that_matters/textures/gui/android_stuff-5.png differ diff --git a/src/main/resources/assets/overdrive_that_matters/textures/gui/android_stuff-6.png b/src/main/resources/assets/overdrive_that_matters/textures/gui/android_stuff-6.png new file mode 100644 index 000000000..38e4c7f10 Binary files /dev/null and b/src/main/resources/assets/overdrive_that_matters/textures/gui/android_stuff-6.png differ diff --git a/src/main/resources/assets/overdrive_that_matters/textures/gui/android_stuff-7.png b/src/main/resources/assets/overdrive_that_matters/textures/gui/android_stuff-7.png new file mode 100644 index 000000000..5b6b03cf6 Binary files /dev/null and b/src/main/resources/assets/overdrive_that_matters/textures/gui/android_stuff-7.png differ diff --git a/src/main/resources/assets/overdrive_that_matters/textures/gui/android_stuff-8.png b/src/main/resources/assets/overdrive_that_matters/textures/gui/android_stuff-8.png new file mode 100644 index 000000000..e2dcc9d85 Binary files /dev/null and b/src/main/resources/assets/overdrive_that_matters/textures/gui/android_stuff-8.png differ diff --git a/src/main/resources/assets/overdrive_that_matters/textures/gui/android_stuff-9.png b/src/main/resources/assets/overdrive_that_matters/textures/gui/android_stuff-9.png new file mode 100644 index 000000000..a18a56c74 Binary files /dev/null and b/src/main/resources/assets/overdrive_that_matters/textures/gui/android_stuff-9.png differ diff --git a/src/main/resources/assets/overdrive_that_matters/textures/gui/android_upgrades.png b/src/main/resources/assets/overdrive_that_matters/textures/gui/android_upgrades.png deleted file mode 100644 index ce32f5677..000000000 Binary files a/src/main/resources/assets/overdrive_that_matters/textures/gui/android_upgrades.png and /dev/null differ