@ -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
|
||||
|
||||
|
@ -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();
|
||||
|
@ -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<Component>? = null,
|
||||
var descriptionSuppliers: MutableList<ComponentSupplier>? = null,
|
||||
var itemIcon: Item? = null,
|
||||
var skinIcon: SkinElement? = null,
|
||||
var skinIcon: AbstractSkinElement? = null,
|
||||
var iconText: Component? = null,
|
||||
) {
|
||||
private val items = ArrayList<Pair<Ingredient, Int>>()
|
||||
@ -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() }
|
||||
|
@ -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")
|
||||
|
@ -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)
|
||||
}
|
||||
}
|
||||
}
|
@ -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)
|
||||
}
|
||||
}
|
||||
}
|
@ -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++}"))
|
||||
}
|
||||
}
|
||||
|
@ -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)
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -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)
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
@ -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
|
||||
}
|
||||
}
|
||||
}
|
@ -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) {
|
||||
|
@ -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<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() {
|
||||
ticks++
|
||||
|
||||
@ -67,4 +78,8 @@ class TimerQueue {
|
||||
ticks = 0
|
||||
list.clear()
|
||||
}
|
||||
|
||||
companion object {
|
||||
private val LOGGER = LogManager.getLogger()
|
||||
}
|
||||
}
|
||||
|
@ -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
|
||||
|
After Width: | Height: | Size: 383 B |
After Width: | Height: | Size: 408 B |
After Width: | Height: | Size: 407 B |
After Width: | Height: | Size: 427 B |
After Width: | Height: | Size: 376 B |
After Width: | Height: | Size: 411 B |
After Width: | Height: | Size: 375 B |
After Width: | Height: | Size: 399 B |
After Width: | Height: | Size: 402 B |
After Width: | Height: | Size: 387 B |
After Width: | Height: | Size: 383 B |
After Width: | Height: | Size: 383 B |
After Width: | Height: | Size: 382 B |
After Width: | Height: | Size: 399 B |
After Width: | Height: | Size: 395 B |
After Width: | Height: | Size: 385 B |
After Width: | Height: | Size: 407 B |
After Width: | Height: | Size: 372 B |
After Width: | Height: | Size: 370 B |
After Width: | Height: | Size: 386 B |
After Width: | Height: | Size: 384 B |
After Width: | Height: | Size: 377 B |
After Width: | Height: | Size: 414 B |
After Width: | Height: | Size: 376 B |
After Width: | Height: | Size: 399 B |
Before Width: | Height: | Size: 2.5 KiB |