@ -1,6 +1,6 @@
|
|||||||
# Sets default memory used for gradle commands. Can be overridden by user or command line properties.
|
# Sets default memory used for gradle commands. Can be overridden by user or command line properties.
|
||||||
# This is required to provide enough memory for the Minecraft decompilation process.
|
# This is required to provide enough memory for the Minecraft decompilation process.
|
||||||
org.gradle.jvmargs=-Xmx3G -XX:+UseParallelGC
|
org.gradle.jvmargs=-Xmx3G
|
||||||
org.gradle.daemon=true
|
org.gradle.daemon=true
|
||||||
kotlin.stdlib.default.dependency=false
|
kotlin.stdlib.default.dependency=false
|
||||||
|
|
||||||
|
@ -31,6 +31,7 @@ import ru.dbotthepony.mc.otm.client.ClientTickHandlerKt;
|
|||||||
import ru.dbotthepony.mc.otm.client.MatteryGUI;
|
import ru.dbotthepony.mc.otm.client.MatteryGUI;
|
||||||
import ru.dbotthepony.mc.otm.client.model.GravitationStabilizerModel;
|
import ru.dbotthepony.mc.otm.client.model.GravitationStabilizerModel;
|
||||||
import ru.dbotthepony.mc.otm.client.model.TritaniumArmorModel;
|
import ru.dbotthepony.mc.otm.client.model.TritaniumArmorModel;
|
||||||
|
import ru.dbotthepony.mc.otm.client.render.WidgetAtlasHolder;
|
||||||
import ru.dbotthepony.mc.otm.compat.mekanism.QIOKt;
|
import ru.dbotthepony.mc.otm.compat.mekanism.QIOKt;
|
||||||
import ru.dbotthepony.mc.otm.compat.mekanism.TooltipsKt;
|
import ru.dbotthepony.mc.otm.compat.mekanism.TooltipsKt;
|
||||||
import ru.dbotthepony.mc.otm.core.ImpreciseFraction;
|
import ru.dbotthepony.mc.otm.core.ImpreciseFraction;
|
||||||
@ -102,6 +103,7 @@ public final class OverdriveThatMatters {
|
|||||||
modBus.addListener(EventPriority.NORMAL, AndroidAbilityKeyMapping.INSTANCE::register);
|
modBus.addListener(EventPriority.NORMAL, AndroidAbilityKeyMapping.INSTANCE::register);
|
||||||
modBus.addListener(EventPriority.NORMAL, TritaniumArmorModel::register);
|
modBus.addListener(EventPriority.NORMAL, TritaniumArmorModel::register);
|
||||||
modBus.addListener(EventPriority.NORMAL, GravitationStabilizerModel::register);
|
modBus.addListener(EventPriority.NORMAL, GravitationStabilizerModel::register);
|
||||||
|
modBus.addListener(EventPriority.NORMAL, WidgetAtlasHolder::register);
|
||||||
});
|
});
|
||||||
|
|
||||||
ClientConfig.INSTANCE.register();
|
ClientConfig.INSTANCE.register();
|
||||||
|
@ -7,6 +7,7 @@ import com.google.gson.JsonElement
|
|||||||
import com.google.gson.JsonObject
|
import com.google.gson.JsonObject
|
||||||
import com.google.gson.JsonPrimitive
|
import com.google.gson.JsonPrimitive
|
||||||
import com.google.gson.JsonSyntaxException
|
import com.google.gson.JsonSyntaxException
|
||||||
|
import com.google.gson.internal.bind.TypeAdapters
|
||||||
import net.minecraft.network.FriendlyByteBuf
|
import net.minecraft.network.FriendlyByteBuf
|
||||||
import net.minecraft.network.chat.Component
|
import net.minecraft.network.chat.Component
|
||||||
import net.minecraft.network.chat.ComponentContents
|
import net.minecraft.network.chat.ComponentContents
|
||||||
@ -20,6 +21,7 @@ import net.minecraft.world.item.Items
|
|||||||
import net.minecraft.world.item.crafting.Ingredient
|
import net.minecraft.world.item.crafting.Ingredient
|
||||||
import net.minecraft.world.level.ItemLike
|
import net.minecraft.world.level.ItemLike
|
||||||
import net.minecraftforge.registries.ForgeRegistries
|
import net.minecraftforge.registries.ForgeRegistries
|
||||||
|
import ru.dbotthepony.mc.otm.client.render.AbstractSkinElement
|
||||||
import ru.dbotthepony.mc.otm.client.render.SkinElement
|
import ru.dbotthepony.mc.otm.client.render.SkinElement
|
||||||
import ru.dbotthepony.mc.otm.core.ListSet
|
import ru.dbotthepony.mc.otm.core.ListSet
|
||||||
import ru.dbotthepony.mc.otm.core.TranslatableComponent
|
import ru.dbotthepony.mc.otm.core.TranslatableComponent
|
||||||
@ -28,6 +30,7 @@ import ru.dbotthepony.mc.otm.core.registryName
|
|||||||
import ru.dbotthepony.mc.otm.core.set
|
import ru.dbotthepony.mc.otm.core.set
|
||||||
import ru.dbotthepony.mc.otm.core.toImmutableList
|
import ru.dbotthepony.mc.otm.core.toImmutableList
|
||||||
import ru.dbotthepony.mc.otm.data.stream
|
import ru.dbotthepony.mc.otm.data.stream
|
||||||
|
import ru.dbotthepony.mc.otm.isClient
|
||||||
import ru.dbotthepony.mc.otm.registry.MRegistry
|
import ru.dbotthepony.mc.otm.registry.MRegistry
|
||||||
import java.util.LinkedList
|
import java.util.LinkedList
|
||||||
import java.util.stream.Stream
|
import java.util.stream.Stream
|
||||||
@ -88,16 +91,22 @@ class AndroidResearchType(
|
|||||||
val experienceLevels: Int = 0,
|
val experienceLevels: Int = 0,
|
||||||
private val customName: Component? = null,
|
private val customName: Component? = null,
|
||||||
|
|
||||||
// why pack these into research itself?
|
// ok
|
||||||
// because Minecraft itself does this
|
val skinIcon: JsonElement? = null,
|
||||||
// check out advancements
|
|
||||||
val skinIcon: SkinElement? = null,
|
|
||||||
val itemIcon: Item? = null,
|
val itemIcon: Item? = null,
|
||||||
iconText: Component? = null,
|
iconText: Component? = null,
|
||||||
) {
|
) {
|
||||||
private val iconTextValue = iconText?.copy()
|
private val iconTextValue = iconText?.copy()
|
||||||
val iconText get() = iconTextValue?.copy()
|
val iconText get() = iconTextValue?.copy()
|
||||||
|
|
||||||
|
val resolvedSkinIcon by lazy {
|
||||||
|
check(isClient) { "Invalid realm" }
|
||||||
|
if (skinIcon != null)
|
||||||
|
AbstractSkinElement.fromJson(skinIcon)
|
||||||
|
else
|
||||||
|
null
|
||||||
|
}
|
||||||
|
|
||||||
data class Reference(
|
data class Reference(
|
||||||
val id: ResourceLocation,
|
val id: ResourceLocation,
|
||||||
val isRigid: Boolean
|
val isRigid: Boolean
|
||||||
@ -471,7 +480,7 @@ class AndroidResearchType(
|
|||||||
it["experience"] = JsonPrimitive(experienceLevels)
|
it["experience"] = JsonPrimitive(experienceLevels)
|
||||||
|
|
||||||
if (skinIcon != null) {
|
if (skinIcon != null) {
|
||||||
it["skin_icon"] = skinIcon.toJson()
|
it["skin_icon"] = skinIcon
|
||||||
}
|
}
|
||||||
|
|
||||||
if (itemIcon != null) {
|
if (itemIcon != null) {
|
||||||
@ -511,7 +520,7 @@ class AndroidResearchType(
|
|||||||
if (iconTextValue != null) buff.writeComponent(iconTextValue)
|
if (iconTextValue != null) buff.writeComponent(iconTextValue)
|
||||||
|
|
||||||
buff.writeBoolean(skinIcon != null)
|
buff.writeBoolean(skinIcon != null)
|
||||||
skinIcon?.toNetwork(buff)
|
if (skinIcon != null) buff.writeUtf(skinIcon.toString())
|
||||||
|
|
||||||
buff.writeBoolean(itemIcon != null)
|
buff.writeBoolean(itemIcon != null)
|
||||||
if (itemIcon != null) buff.writeUtf(itemIcon.registryName!!.toString())
|
if (itemIcon != null) buff.writeUtf(itemIcon.registryName!!.toString())
|
||||||
@ -541,7 +550,7 @@ class AndroidResearchType(
|
|||||||
}
|
}
|
||||||
|
|
||||||
val skinIcon = if (buff.readBoolean()) {
|
val skinIcon = if (buff.readBoolean()) {
|
||||||
SkinElement.fromNetwork(buff)
|
TypeAdapters.JSON_ELEMENT.fromJson(buff.readUtf())
|
||||||
} else {
|
} else {
|
||||||
null
|
null
|
||||||
}
|
}
|
||||||
@ -582,7 +591,7 @@ class AndroidResearchType(
|
|||||||
val experience = value["experience"]?.asInt ?: 0
|
val experience = value["experience"]?.asInt ?: 0
|
||||||
val customName = value["custom_name"]?.let(Component.Serializer::fromJson)
|
val customName = value["custom_name"]?.let(Component.Serializer::fromJson)
|
||||||
val iconText = value["icon_text"]?.let(Component.Serializer::fromJson)
|
val iconText = value["icon_text"]?.let(Component.Serializer::fromJson)
|
||||||
val skinIcon = value["skin_icon"]?.let(SkinElement.Companion::fromJson)
|
val skinIcon = value["skin_icon"]
|
||||||
val itemIcon = value["item_icon"]?.let { ForgeRegistries.ITEMS.getValue(ResourceLocation(it.asString)).let { if (it == Items.AIR) null else it } }
|
val itemIcon = value["item_icon"]?.let { ForgeRegistries.ITEMS.getValue(ResourceLocation(it.asString)).let { if (it == Items.AIR) null else it } }
|
||||||
|
|
||||||
return AndroidResearchType(
|
return AndroidResearchType(
|
||||||
@ -615,7 +624,7 @@ class AndroidResearchType(
|
|||||||
var description: MutableList<Component>? = null,
|
var description: MutableList<Component>? = null,
|
||||||
var descriptionSuppliers: MutableList<ComponentSupplier>? = null,
|
var descriptionSuppliers: MutableList<ComponentSupplier>? = null,
|
||||||
var itemIcon: Item? = null,
|
var itemIcon: Item? = null,
|
||||||
var skinIcon: SkinElement? = null,
|
var skinIcon: AbstractSkinElement? = null,
|
||||||
var iconText: Component? = null,
|
var iconText: Component? = null,
|
||||||
) {
|
) {
|
||||||
private val items = ArrayList<Pair<Ingredient, Int>>()
|
private val items = ArrayList<Pair<Ingredient, Int>>()
|
||||||
@ -629,7 +638,7 @@ class AndroidResearchType(
|
|||||||
return this
|
return this
|
||||||
}
|
}
|
||||||
|
|
||||||
fun withIcon(icon: SkinElement? = null): Builder {
|
fun withIcon(icon: AbstractSkinElement? = null): Builder {
|
||||||
this.skinIcon = icon
|
this.skinIcon = icon
|
||||||
this.itemIcon = null
|
this.itemIcon = null
|
||||||
return this
|
return this
|
||||||
@ -840,7 +849,7 @@ class AndroidResearchType(
|
|||||||
descriptionSuppliers = descriptionSuppliers ?: listOf(),
|
descriptionSuppliers = descriptionSuppliers ?: listOf(),
|
||||||
experienceLevels = experience,
|
experienceLevels = experience,
|
||||||
customName = customName,
|
customName = customName,
|
||||||
skinIcon = skinIcon,
|
skinIcon = skinIcon?.toJson(),
|
||||||
itemIcon = itemIcon,
|
itemIcon = itemIcon,
|
||||||
iconText = iconText
|
iconText = iconText
|
||||||
).also { if (validate) it.validate() }
|
).also { if (validate) it.validate() }
|
||||||
|
@ -25,6 +25,16 @@ fun onceClientPre(ticker: ITickable) {
|
|||||||
preTickList.add(ticker, LOGGED_IN, "Not logged in")
|
preTickList.add(ticker, LOGGED_IN, "Not logged in")
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fun onceClient(inTicks: Int, ticker: Runnable) {
|
||||||
|
check(isClient) { "Illegal side" }
|
||||||
|
postTimerList.add(inTicks, ticker, LOGGED_IN, "Not logged in")
|
||||||
|
}
|
||||||
|
|
||||||
|
fun onceClientPre(inTicks: Int, ticker: Runnable) {
|
||||||
|
check(isClient) { "Illegal side" }
|
||||||
|
preTimerList.add(inTicks, ticker, LOGGED_IN, "Not logged in")
|
||||||
|
}
|
||||||
|
|
||||||
fun tickClient(ticker: IConditionalTickable) {
|
fun tickClient(ticker: IConditionalTickable) {
|
||||||
check(isClient) { "Illegal side" }
|
check(isClient) { "Illegal side" }
|
||||||
postTickList.add(ticker, LOGGED_IN, "Not logged in")
|
postTickList.add(ticker, LOGGED_IN, "Not logged in")
|
||||||
|
@ -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
|
import ru.dbotthepony.mc.otm.OverdriveThatMatters
|
||||||
|
|
||||||
object ResearchIcons {
|
object ResearchIcons {
|
||||||
val ICONS = ResourceLocation(OverdriveThatMatters.MOD_ID, "textures/gui/android_upgrades.png")
|
val ICON_TRANSFER: AbstractSkinElement
|
||||||
val ICON_TRANSFER: SkinElement
|
val ICON_ATTACK_BOOST: AbstractSkinElement
|
||||||
val ICON_ATTACK_BOOST: SkinElement
|
val ICON_PLASMA_SHIELD_BOOST: AbstractSkinElement
|
||||||
val ICON_PLASMA_SHIELD_BOOST: SkinElement
|
val ICON_CLOAK: AbstractSkinElement
|
||||||
val ICON_CLOAK: SkinElement
|
val ICON_GRAVITATIONAL_STABILIZER: AbstractSkinElement
|
||||||
val ICON_GRAVITATIONAL_STABILIZER: SkinElement
|
val ICON_AIR_BAGS: AbstractSkinElement
|
||||||
val ICON_AIR_BAGS: SkinElement
|
val ICON_JUMP_BOOST: AbstractSkinElement
|
||||||
val ICON_JUMP_BOOST: SkinElement
|
|
||||||
|
|
||||||
val ICON_FEATHER_FALLING: SkinElement
|
val ICON_FEATHER_FALLING: AbstractSkinElement
|
||||||
val ICON_ITEM_MAGNET: SkinElement
|
val ICON_ITEM_MAGNET: AbstractSkinElement
|
||||||
val ICON_ARROW: SkinElement
|
val ICON_ARROW: AbstractSkinElement
|
||||||
val ICON_ARMOR: SkinElement
|
val ICON_ARMOR: AbstractSkinElement
|
||||||
val ICON_NANOBOTS: SkinElement
|
val ICON_NANOBOTS: AbstractSkinElement
|
||||||
val ICON_NIGHT_VISION: SkinElement
|
val ICON_NIGHT_VISION: AbstractSkinElement
|
||||||
val ICON_OXYGEN_SUPPLY: SkinElement
|
val ICON_OXYGEN_SUPPLY: AbstractSkinElement
|
||||||
|
|
||||||
val ICON_PLASMA_SHIELD: SkinElement
|
val ICON_PLASMA_SHIELD: AbstractSkinElement
|
||||||
val ICON_SHOCKWAVE: SkinElement
|
val ICON_SHOCKWAVE: AbstractSkinElement
|
||||||
val ICON_LIMB_OVERCLOCKING: SkinElement
|
val ICON_LIMB_OVERCLOCKING: AbstractSkinElement
|
||||||
val ICON_STEP_ASSIST: SkinElement
|
val ICON_STEP_ASSIST: AbstractSkinElement
|
||||||
val ICON_ENDER_TELEPORT: SkinElement
|
val ICON_ENDER_TELEPORT: AbstractSkinElement
|
||||||
val ICON_WIRELESS_CHARGING: SkinElement
|
val ICON_WIRELESS_CHARGING: AbstractSkinElement
|
||||||
val ICON_UNKNOWN: SkinElement
|
val ICON_UNKNOWN: AbstractSkinElement
|
||||||
|
|
||||||
val ICON_EXTENDED_REACH: SkinElement
|
val ICON_EXTENDED_REACH: AbstractSkinElement
|
||||||
val ICON_PHANTOM_ATTRACTOR: SkinElement
|
val ICON_PHANTOM_ATTRACTOR: AbstractSkinElement
|
||||||
|
|
||||||
val KOT = ResourceLocation(OverdriveThatMatters.MOD_ID, "textures/block/ph_kitty.png").element(0f, 0f, 32f, 32f, 32f, 32f)
|
val KOT = ResourceLocation(OverdriveThatMatters.MOD_ID, "textures/block/ph_kitty.png").element(0f, 0f, 32f, 32f, 32f, 32f)
|
||||||
|
|
||||||
init {
|
init {
|
||||||
val grid = SkinGrid(ICONS, 18f, 18f, 7, 7)
|
var i = 0
|
||||||
|
|
||||||
ICON_TRANSFER = grid.next()
|
ICON_TRANSFER = AtlasSkinElement(ResourceLocation(OverdriveThatMatters.MOD_ID, "android_stuff-${i++}"))
|
||||||
ICON_ATTACK_BOOST = grid.next()
|
ICON_ATTACK_BOOST = AtlasSkinElement(ResourceLocation(OverdriveThatMatters.MOD_ID, "android_stuff-${i++}"))
|
||||||
ICON_PLASMA_SHIELD_BOOST = grid.next()
|
ICON_PLASMA_SHIELD_BOOST = AtlasSkinElement(ResourceLocation(OverdriveThatMatters.MOD_ID, "android_stuff-${i++}"))
|
||||||
ICON_CLOAK = grid.next()
|
ICON_CLOAK = AtlasSkinElement(ResourceLocation(OverdriveThatMatters.MOD_ID, "android_stuff-${i++}"))
|
||||||
ICON_GRAVITATIONAL_STABILIZER = grid.next()
|
ICON_GRAVITATIONAL_STABILIZER = AtlasSkinElement(ResourceLocation(OverdriveThatMatters.MOD_ID, "android_stuff-${i++}"))
|
||||||
ICON_AIR_BAGS = grid.next()
|
ICON_AIR_BAGS = AtlasSkinElement(ResourceLocation(OverdriveThatMatters.MOD_ID, "android_stuff-${i++}"))
|
||||||
ICON_JUMP_BOOST = grid.next()
|
ICON_JUMP_BOOST = AtlasSkinElement(ResourceLocation(OverdriveThatMatters.MOD_ID, "android_stuff-${i++}"))
|
||||||
|
ICON_FEATHER_FALLING = AtlasSkinElement(ResourceLocation(OverdriveThatMatters.MOD_ID, "android_stuff-${i++}"))
|
||||||
ICON_FEATHER_FALLING = grid.next()
|
ICON_ITEM_MAGNET = AtlasSkinElement(ResourceLocation(OverdriveThatMatters.MOD_ID, "android_stuff-${i++}"))
|
||||||
ICON_ITEM_MAGNET = grid.next()
|
ICON_ARROW = AtlasSkinElement(ResourceLocation(OverdriveThatMatters.MOD_ID, "android_stuff-${i++}"))
|
||||||
ICON_ARROW = grid.next()
|
ICON_ARMOR = AtlasSkinElement(ResourceLocation(OverdriveThatMatters.MOD_ID, "android_stuff-${i++}"))
|
||||||
ICON_ARMOR = grid.next()
|
ICON_NANOBOTS = AtlasSkinElement(ResourceLocation(OverdriveThatMatters.MOD_ID, "android_stuff-${i++}"))
|
||||||
ICON_NANOBOTS = grid.next()
|
ICON_NIGHT_VISION = AtlasSkinElement(ResourceLocation(OverdriveThatMatters.MOD_ID, "android_stuff-${i++}"))
|
||||||
ICON_NIGHT_VISION = grid.next()
|
ICON_OXYGEN_SUPPLY = AtlasSkinElement(ResourceLocation(OverdriveThatMatters.MOD_ID, "android_stuff-${i++}"))
|
||||||
ICON_OXYGEN_SUPPLY = grid.next()
|
ICON_PLASMA_SHIELD = AtlasSkinElement(ResourceLocation(OverdriveThatMatters.MOD_ID, "android_stuff-${i++}"))
|
||||||
|
ICON_SHOCKWAVE = AtlasSkinElement(ResourceLocation(OverdriveThatMatters.MOD_ID, "android_stuff-${i++}"))
|
||||||
ICON_PLASMA_SHIELD = grid.next()
|
ICON_LIMB_OVERCLOCKING = AtlasSkinElement(ResourceLocation(OverdriveThatMatters.MOD_ID, "android_stuff-${i++}"))
|
||||||
ICON_SHOCKWAVE = grid.next()
|
ICON_STEP_ASSIST = AtlasSkinElement(ResourceLocation(OverdriveThatMatters.MOD_ID, "android_stuff-${i++}"))
|
||||||
ICON_LIMB_OVERCLOCKING = grid.next()
|
ICON_ENDER_TELEPORT = AtlasSkinElement(ResourceLocation(OverdriveThatMatters.MOD_ID, "android_stuff-${i++}"))
|
||||||
ICON_STEP_ASSIST = grid.next()
|
ICON_WIRELESS_CHARGING = AtlasSkinElement(ResourceLocation(OverdriveThatMatters.MOD_ID, "android_stuff-${i++}"))
|
||||||
ICON_ENDER_TELEPORT = grid.next()
|
ICON_UNKNOWN = AtlasSkinElement(ResourceLocation(OverdriveThatMatters.MOD_ID, "android_stuff-${i++}"))
|
||||||
ICON_WIRELESS_CHARGING = grid.next()
|
ICON_EXTENDED_REACH = AtlasSkinElement(ResourceLocation(OverdriveThatMatters.MOD_ID, "android_stuff-${i++}"))
|
||||||
ICON_UNKNOWN = grid.next()
|
ICON_PHANTOM_ATTRACTOR = AtlasSkinElement(ResourceLocation(OverdriveThatMatters.MOD_ID, "android_stuff-${i++}"))
|
||||||
|
|
||||||
ICON_EXTENDED_REACH = grid.next()
|
|
||||||
ICON_PHANTOM_ATTRACTOR = grid.next()
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -12,11 +12,8 @@ import com.google.gson.TypeAdapter
|
|||||||
import com.google.gson.internal.bind.TypeAdapters
|
import com.google.gson.internal.bind.TypeAdapters
|
||||||
import com.google.gson.stream.JsonReader
|
import com.google.gson.stream.JsonReader
|
||||||
import com.google.gson.stream.JsonWriter
|
import com.google.gson.stream.JsonWriter
|
||||||
import com.mojang.blaze3d.systems.RenderSystem
|
|
||||||
import com.mojang.blaze3d.vertex.PoseStack
|
|
||||||
import net.minecraft.network.FriendlyByteBuf
|
import net.minecraft.network.FriendlyByteBuf
|
||||||
import net.minecraft.resources.ResourceLocation
|
import net.minecraft.resources.ResourceLocation
|
||||||
import ru.dbotthepony.mc.otm.client.screen.panels.DockProperty
|
|
||||||
import ru.dbotthepony.mc.otm.core.set
|
import ru.dbotthepony.mc.otm.core.set
|
||||||
import java.lang.reflect.Type
|
import java.lang.reflect.Type
|
||||||
|
|
||||||
@ -54,16 +51,16 @@ fun ResourceLocation.vLine(
|
|||||||
|
|
||||||
@Suppress("unused")
|
@Suppress("unused")
|
||||||
data class SkinElement @JvmOverloads constructor(
|
data class SkinElement @JvmOverloads constructor(
|
||||||
val texture: ResourceLocation,
|
override val texture: ResourceLocation,
|
||||||
val x: Float,
|
override val x: Float,
|
||||||
val y: Float,
|
override val y: Float,
|
||||||
val width: Float,
|
override val width: Float,
|
||||||
val height: Float,
|
override val height: Float,
|
||||||
val imageWidth: Float = 256f,
|
val imageWidth: Float = 256f,
|
||||||
val imageHeight: Float = 256f,
|
val imageHeight: Float = 256f,
|
||||||
val winding: UVWindingOrder = UVWindingOrder.NORMAL
|
override val winding: UVWindingOrder = UVWindingOrder.NORMAL,
|
||||||
) {
|
) : AbstractSkinElement() {
|
||||||
fun toJson(): JsonObject {
|
override fun toJson(): JsonObject {
|
||||||
return JsonObject().also {
|
return JsonObject().also {
|
||||||
it["texture"] = JsonPrimitive(texture.toString())
|
it["texture"] = JsonPrimitive(texture.toString())
|
||||||
it["x"] = JsonPrimitive(x)
|
it["x"] = JsonPrimitive(x)
|
||||||
@ -76,7 +73,7 @@ data class SkinElement @JvmOverloads constructor(
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fun toNetwork(buff: FriendlyByteBuf) {
|
override fun toNetwork(buff: FriendlyByteBuf) {
|
||||||
buff.writeUtf(texture.toString())
|
buff.writeUtf(texture.toString())
|
||||||
buff.writeFloat(x)
|
buff.writeFloat(x)
|
||||||
buff.writeFloat(y)
|
buff.writeFloat(y)
|
||||||
@ -149,250 +146,8 @@ data class SkinElement @JvmOverloads constructor(
|
|||||||
require(imageHeight > 0f) { "Invalid image height $imageHeight" }
|
require(imageHeight > 0f) { "Invalid image height $imageHeight" }
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
override val u0 = this.x / imageWidth
|
||||||
* See [ru.dbotthepony.mc.otm.client.render.clearDepth]
|
override val v0 = this.y / imageHeight
|
||||||
*/
|
override val u1 = (this.x + width) / imageWidth
|
||||||
fun clearDepth(
|
override val v1 = (this.y + height) / imageHeight
|
||||||
stack: PoseStack,
|
|
||||||
x: Float = 0f,
|
|
||||||
y: Float = 0f,
|
|
||||||
width: Float = this.width,
|
|
||||||
height: Float = this.height,
|
|
||||||
) = ru.dbotthepony.mc.otm.client.render.clearDepth(stack, x, y, width, height)
|
|
||||||
|
|
||||||
@JvmOverloads
|
|
||||||
fun render(
|
|
||||||
stack: PoseStack,
|
|
||||||
x: Float = 0f,
|
|
||||||
y: Float = 0f,
|
|
||||||
width: Float = this.width,
|
|
||||||
height: Float = this.height,
|
|
||||||
winding: UVWindingOrder = this.winding
|
|
||||||
) {
|
|
||||||
RenderSystem.setShaderTexture(0, texture)
|
|
||||||
RenderSystem.enableBlend()
|
|
||||||
RenderSystem.defaultBlendFunc()
|
|
||||||
|
|
||||||
renderRaw(stack, x, y, width, height, winding)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@JvmOverloads
|
|
||||||
fun render(
|
|
||||||
stack: PoseStack,
|
|
||||||
x: Double,
|
|
||||||
y: Double = 0.0,
|
|
||||||
width: Double = this.width.toDouble(),
|
|
||||||
height: Double = this.height.toDouble(),
|
|
||||||
winding: UVWindingOrder = this.winding
|
|
||||||
) = render(stack, x.toFloat(), y.toFloat(), width.toFloat(), height.toFloat(), winding)
|
|
||||||
|
|
||||||
@JvmOverloads
|
|
||||||
fun renderPartial(
|
|
||||||
stack: PoseStack,
|
|
||||||
x: Float = 0f,
|
|
||||||
y: Float = 0f,
|
|
||||||
width: Float = this.width,
|
|
||||||
height: Float = this.height,
|
|
||||||
winding: UVWindingOrder = this.winding
|
|
||||||
) {
|
|
||||||
RenderSystem.setShaderTexture(0, texture)
|
|
||||||
RenderSystem.enableBlend()
|
|
||||||
RenderSystem.defaultBlendFunc()
|
|
||||||
|
|
||||||
renderRawPartial(stack, x, y, width, height, winding)
|
|
||||||
}
|
|
||||||
|
|
||||||
@JvmOverloads
|
|
||||||
fun renderPartial(
|
|
||||||
stack: PoseStack,
|
|
||||||
x: Double,
|
|
||||||
y: Double = 0.0,
|
|
||||||
width: Double = this.width.toDouble(),
|
|
||||||
height: Double = this.height.toDouble(),
|
|
||||||
winding: UVWindingOrder = this.winding
|
|
||||||
) = renderPartial(stack, x.toFloat(), y.toFloat(), width.toFloat(), height.toFloat(), winding)
|
|
||||||
|
|
||||||
@JvmOverloads
|
|
||||||
fun renderWidth(
|
|
||||||
stack: PoseStack,
|
|
||||||
x: Float = 0f,
|
|
||||||
y: Float = 0f,
|
|
||||||
width: Float = this.width,
|
|
||||||
winding: UVWindingOrder = this.winding
|
|
||||||
) {
|
|
||||||
render(stack, x, y, width = width, winding = winding)
|
|
||||||
}
|
|
||||||
|
|
||||||
@JvmOverloads
|
|
||||||
fun renderWidth(
|
|
||||||
stack: PoseStack,
|
|
||||||
x: Double,
|
|
||||||
y: Double = 0.0,
|
|
||||||
width: Double = this.width.toDouble(),
|
|
||||||
winding: UVWindingOrder = this.winding,
|
|
||||||
) = renderWidth(stack, x.toFloat(), y.toFloat(), width.toFloat(), winding)
|
|
||||||
|
|
||||||
@JvmOverloads
|
|
||||||
fun renderHeight(
|
|
||||||
stack: PoseStack,
|
|
||||||
x: Float = 0f,
|
|
||||||
y: Float = 0f,
|
|
||||||
height: Float = this.height,
|
|
||||||
winding: UVWindingOrder = this.winding,
|
|
||||||
) {
|
|
||||||
render(stack, x, y, height = height, winding = winding)
|
|
||||||
}
|
|
||||||
|
|
||||||
@JvmOverloads
|
|
||||||
fun renderHeight(
|
|
||||||
stack: PoseStack,
|
|
||||||
x: Double,
|
|
||||||
y: Double = 0.0,
|
|
||||||
height: Double = this.height.toDouble(),
|
|
||||||
winding: UVWindingOrder = this.winding,
|
|
||||||
) = renderHeight(stack, x.toFloat(), y.toFloat(), height.toFloat(), winding)
|
|
||||||
|
|
||||||
val u0 = this.x / imageWidth
|
|
||||||
val v0 = this.y / imageHeight
|
|
||||||
val u1 = (this.x + width) / imageWidth
|
|
||||||
val v1 = (this.y + height) / imageHeight
|
|
||||||
|
|
||||||
@JvmOverloads
|
|
||||||
fun renderRaw(
|
|
||||||
stack: PoseStack,
|
|
||||||
x: Float = 0f,
|
|
||||||
y: Float = 0f,
|
|
||||||
width: Float = this.width,
|
|
||||||
height: Float = this.height,
|
|
||||||
winding: UVWindingOrder = UVWindingOrder.NORMAL
|
|
||||||
) {
|
|
||||||
val winded = winding.translate(u0, v0, u1, v1)
|
|
||||||
|
|
||||||
drawTexturedRect(
|
|
||||||
stack,
|
|
||||||
x,
|
|
||||||
y,
|
|
||||||
width,
|
|
||||||
height,
|
|
||||||
winded,
|
|
||||||
)
|
|
||||||
}
|
|
||||||
|
|
||||||
@JvmOverloads
|
|
||||||
fun renderRaw(
|
|
||||||
stack: PoseStack,
|
|
||||||
x: Double,
|
|
||||||
y: Double = 0.0,
|
|
||||||
width: Double = this.width.toDouble(),
|
|
||||||
height: Double = this.height.toDouble(),
|
|
||||||
winding: UVWindingOrder = UVWindingOrder.NORMAL
|
|
||||||
) = renderRaw(stack, x.toFloat(), y.toFloat(), width.toFloat(), height.toFloat(), winding)
|
|
||||||
|
|
||||||
@JvmOverloads
|
|
||||||
fun renderRawPartial(
|
|
||||||
stack: PoseStack,
|
|
||||||
x: Float = 0f,
|
|
||||||
y: Float = 0f,
|
|
||||||
width: Float = this.width,
|
|
||||||
height: Float = this.height,
|
|
||||||
winding: UVWindingOrder = UVWindingOrder.NORMAL
|
|
||||||
) {
|
|
||||||
val u1 = (this.x + width) / imageWidth
|
|
||||||
val v1 = (this.y + height) / imageHeight
|
|
||||||
|
|
||||||
val winded = winding.translate(u0, v0, u1, v1)
|
|
||||||
|
|
||||||
drawTexturedRect(
|
|
||||||
stack,
|
|
||||||
x,
|
|
||||||
y,
|
|
||||||
width,
|
|
||||||
height,
|
|
||||||
winded,
|
|
||||||
)
|
|
||||||
}
|
|
||||||
|
|
||||||
@JvmOverloads
|
|
||||||
fun renderRawPartial(
|
|
||||||
stack: PoseStack,
|
|
||||||
x: Double,
|
|
||||||
y: Double = 0.0,
|
|
||||||
width: Double = this.width.toDouble(),
|
|
||||||
height: Double = this.height.toDouble(),
|
|
||||||
winding: UVWindingOrder = UVWindingOrder.NORMAL
|
|
||||||
) = renderRawPartial(stack, x.toFloat(), y.toFloat(), width.toFloat(), height.toFloat(), winding)
|
|
||||||
}
|
|
||||||
|
|
||||||
data class StretchingRectangleElement(
|
|
||||||
val topLeft: SkinElement,
|
|
||||||
val topRight: SkinElement,
|
|
||||||
val bottomLeft: SkinElement,
|
|
||||||
val bottomRight: SkinElement,
|
|
||||||
val left: SkinElement,
|
|
||||||
val right: SkinElement,
|
|
||||||
val top: SkinElement,
|
|
||||||
val bottom: SkinElement,
|
|
||||||
val middle: SkinElement,
|
|
||||||
val padding: DockProperty = DockProperty.EMPTY
|
|
||||||
) {
|
|
||||||
fun render(
|
|
||||||
stack: PoseStack,
|
|
||||||
x: Float = 0f,
|
|
||||||
y: Float = 0f,
|
|
||||||
width: Float,
|
|
||||||
height: Float,
|
|
||||||
) {
|
|
||||||
val bgWidth = width - topLeft.width.coerceAtMost(bottomLeft.width) - topRight.width.coerceAtMost(bottomRight.width) - padding.left - padding.right
|
|
||||||
val bgHeight = height - topLeft.height.coerceAtMost(bottomLeft.height) - topRight.height.coerceAtMost(bottomRight.height) - padding.top - padding.bottom
|
|
||||||
|
|
||||||
if (bgWidth > 0 && bgHeight > 0) {
|
|
||||||
middle.render(stack, x + topLeft.width + padding.left, y + topLeft.height + padding.top, bgWidth, bgHeight)
|
|
||||||
}
|
|
||||||
|
|
||||||
top.render(stack, x + topLeft.width, y, width = width - topLeft.width - topRight.width)
|
|
||||||
bottom.render(stack, x + bottomLeft.width, y + height - bottom.height, width = width - bottomLeft.width - bottomRight.width)
|
|
||||||
|
|
||||||
left.render(stack, x, y + topLeft.height, height = height - topLeft.height - bottomLeft.height)
|
|
||||||
right.render(stack, x + width - right.width, y + topRight.height, height = height - topRight.height - bottomRight.height)
|
|
||||||
|
|
||||||
topLeft.render(stack, x, y)
|
|
||||||
topRight.render(stack, x + width - topRight.width, y)
|
|
||||||
|
|
||||||
bottomLeft.render(stack, x, y + height - bottomLeft.height)
|
|
||||||
bottomRight.render(stack, x + width - bottomRight.width, y + height - bottomLeft.height)
|
|
||||||
}
|
|
||||||
|
|
||||||
companion object {
|
|
||||||
fun square(
|
|
||||||
texture: ResourceLocation,
|
|
||||||
x: Float,
|
|
||||||
y: Float,
|
|
||||||
cornerWidth: Float,
|
|
||||||
cornerHeight: Float,
|
|
||||||
width: Float,
|
|
||||||
height: Float,
|
|
||||||
sideThickness: Float,
|
|
||||||
imageWidth: Float = 256f,
|
|
||||||
imageHeight: Float = 256f,
|
|
||||||
): StretchingRectangleElement {
|
|
||||||
val innerThickness = sideThickness.coerceAtLeast(cornerWidth).coerceAtLeast(cornerHeight)
|
|
||||||
val padding = sideThickness - innerThickness
|
|
||||||
|
|
||||||
return StretchingRectangleElement(
|
|
||||||
topLeft = texture.element(x, y, cornerWidth, cornerHeight, imageWidth, imageHeight),
|
|
||||||
topRight = texture.element(x + width - cornerWidth, y, cornerWidth, cornerHeight, imageWidth, imageHeight),
|
|
||||||
bottomLeft = texture.element(x, y + height - cornerHeight, cornerWidth, cornerHeight, imageWidth, imageHeight),
|
|
||||||
bottomRight = texture.element(x + width - cornerWidth, y + height - cornerHeight, cornerWidth, cornerHeight, imageWidth, imageHeight),
|
|
||||||
|
|
||||||
top = texture.element(x + cornerWidth, y, width - cornerWidth * 2f, sideThickness, imageWidth, imageHeight),
|
|
||||||
bottom = texture.element(x + cornerWidth, y + height - sideThickness, width - cornerWidth * 2f, sideThickness, imageWidth, imageHeight),
|
|
||||||
left = texture.element(x, y, sideThickness, height - cornerHeight * 2f, imageWidth, imageHeight),
|
|
||||||
right = texture.element(x, y + width - sideThickness, sideThickness, height - cornerHeight * 2f, imageWidth, imageHeight),
|
|
||||||
|
|
||||||
middle = texture.element(x + innerThickness, y + innerThickness, width - innerThickness * 2f, height - innerThickness * 2f, imageWidth, imageHeight),
|
|
||||||
padding = DockProperty(padding, padding, padding, padding)
|
|
||||||
)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
|
@ -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()
|
AndroidStationScreen.CAN_NOT_BE_RESEARCHED.setSystemColor()
|
||||||
}
|
}
|
||||||
|
|
||||||
val icon = node.type.skinIcon
|
val icon = node.type.resolvedSkinIcon
|
||||||
val itemIcon = node.type.itemIcon
|
val itemIcon = node.type.itemIcon
|
||||||
|
|
||||||
if (icon != null) {
|
if (icon != null) {
|
||||||
|
@ -1,5 +1,7 @@
|
|||||||
package ru.dbotthepony.mc.otm.core
|
package ru.dbotthepony.mc.otm.core
|
||||||
|
|
||||||
|
import org.apache.logging.log4j.LogManager
|
||||||
|
|
||||||
class TimerQueue {
|
class TimerQueue {
|
||||||
private var ticks = 0
|
private var ticks = 0
|
||||||
private val list = ArrayDeque<Timer>()
|
private val list = ArrayDeque<Timer>()
|
||||||
@ -48,6 +50,15 @@ class TimerQueue {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fun add(timerTicks: Int, ticker: Runnable, condition: Boolean, reason: String): Timer? {
|
||||||
|
if (!condition) {
|
||||||
|
LOGGER.error("Refusing to add timer $ticker in $timerTicks ticks because we $reason", IllegalStateException(reason))
|
||||||
|
return null
|
||||||
|
}
|
||||||
|
|
||||||
|
return Timer(timerTicks, ticker)
|
||||||
|
}
|
||||||
|
|
||||||
fun tick() {
|
fun tick() {
|
||||||
ticks++
|
ticks++
|
||||||
|
|
||||||
@ -67,4 +78,8 @@ class TimerQueue {
|
|||||||
ticks = 0
|
ticks = 0
|
||||||
list.clear()
|
list.clear()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
companion object {
|
||||||
|
private val LOGGER = LogManager.getLogger()
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@ -45,3 +45,5 @@ protected net.minecraft.client.gui.screens.inventory.AbstractContainerScreen m_9
|
|||||||
protected net.minecraft.client.gui.screens.inventory.AbstractContainerScreen m_97818_()V # recalculateQuickCraftRemaining
|
protected net.minecraft.client.gui.screens.inventory.AbstractContainerScreen m_97818_()V # recalculateQuickCraftRemaining
|
||||||
protected net.minecraft.client.gui.screens.inventory.AbstractContainerScreen m_97744_(DD)Lnet/minecraft/world/inventory/Slot; # findSlot
|
protected net.minecraft.client.gui.screens.inventory.AbstractContainerScreen m_97744_(DD)Lnet/minecraft/world/inventory/Slot; # findSlot
|
||||||
protected net.minecraft.client.gui.screens.inventory.AbstractContainerScreen m_97782_(Lnet/minecraft/world/item/ItemStack;IILjava/lang/String;)V # renderFloatingItem
|
protected net.minecraft.client.gui.screens.inventory.AbstractContainerScreen m_97782_(Lnet/minecraft/world/item/ItemStack;IILjava/lang/String;)V # renderFloatingItem
|
||||||
|
|
||||||
|
protected net.minecraft.client.resources.TextureAtlasHolder f_118884_ # textureAtlas
|
||||||
|
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 |