Add back research icons

This commit is contained in:
DBotThePony 2022-09-23 17:37:03 +07:00
parent feb0c4d551
commit c619bf4787
Signed by: DBot
GPG Key ID: DCC23B5715498507
4 changed files with 141 additions and 25 deletions

View File

@ -329,10 +329,6 @@ class AndroidResearch(val type: AndroidResearchType, val capability: MatteryPlay
*/
val screenTooltipHeader: Component get() = type.displayName
val skinIcon: SkinElement? get() = null
val stackIcon: ItemStack? get() = null
val iconText: Component? get() = null
override fun serializeNBT(): CompoundTag {
return CompoundTag().also {
it["researched"] = isResearched

View File

@ -12,10 +12,14 @@ import net.minecraft.network.chat.ComponentContents
import net.minecraft.network.chat.MutableComponent
import net.minecraft.network.chat.contents.TranslatableContents
import net.minecraft.resources.ResourceLocation
import net.minecraft.world.item.Item
import net.minecraft.world.item.ItemStack
import net.minecraft.world.item.Items
import net.minecraftforge.registries.ForgeRegistries
import ru.dbotthepony.mc.otm.client.render.SkinElement
import ru.dbotthepony.mc.otm.core.ListSet
import ru.dbotthepony.mc.otm.core.TranslatableComponent
import ru.dbotthepony.mc.otm.core.registryName
import ru.dbotthepony.mc.otm.core.set
import ru.dbotthepony.mc.otm.core.stream
import ru.dbotthepony.mc.otm.core.toImmutableList
@ -79,14 +83,14 @@ 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,
stackIcon: ItemStack? = null,
val itemIcon: Item? = null,
iconText: Component? = null,
) {
private val stackIconValue = stackIcon?.copy()
private val iconTextValue = iconText?.copy()
val stackIcon get() = stackIconValue?.copy()
val iconText get() = iconTextValue?.copy()
data class Reference(
@ -435,19 +439,23 @@ class AndroidResearchType(
it["prerequisites"] = JsonArray().also { for (value in prerequisites) it.add(value.toJson()) }
it["blocked_by"] = JsonArray().also { for (value in blockedBy) it.add(value.toJson()) }
it["required_items"] = JsonArray().also { for (item in itemCollection) it.add(ItemStackCodec.serialize(item)) }
it["feature_result"] = JsonArray().also { for (feature in features) it.add(feature.toJson()) }
it["description"] = JsonArray().also { for (line in descriptionLines) it.add(Component.Serializer.toJsonTree(line)) }
it["experience"] = JsonPrimitive(experienceLevels)
if (skinIcon != null) {
it["skin_icon"] = skinIcon.toJson()
}
if (itemIcon != null) {
it["item_icon"] = JsonPrimitive(itemIcon.registryName!!.toString())
}
if (iconTextValue != null) {
it["icon_text"] = Component.Serializer.toJsonTree(iconTextValue)
}
if (customName != null) {
it["custom_name"] = Component.Serializer.toJsonTree(customName)
}
@ -470,10 +478,16 @@ class AndroidResearchType(
buff.writeVarInt(experienceLevels)
buff.writeBoolean(customName != null)
if (customName != null) buff.writeComponent(customName)
if (customName != null) {
buff.writeComponent(customName)
}
buff.writeBoolean(iconTextValue != null)
if (iconTextValue != null) buff.writeComponent(iconTextValue)
buff.writeBoolean(skinIcon != null)
skinIcon?.toNetwork(buff)
buff.writeBoolean(itemIcon != null)
if (itemIcon != null) buff.writeUtf(itemIcon.registryName!!.toString())
}
companion object {
@ -486,12 +500,30 @@ class AndroidResearchType(
val descriptionLines = buff.readCollection({ LinkedList() }, FriendlyByteBuf::readComponent)
val experienceLevels = buff.readVarInt()
val customName: Component? = if (buff.readBoolean()) {
val customName = if (buff.readBoolean()) {
buff.readComponent()
} else {
null
}
val iconTextValue = if (buff.readBoolean()) {
buff.readComponent()
} else {
null
}
val skinIcon = if (buff.readBoolean()) {
SkinElement.fromNetwork(buff)
} else {
null
}
val itemIcon = if (buff.readBoolean()) {
ForgeRegistries.ITEMS.getValue(ResourceLocation(buff.readUtf()))?.let { if (it == Items.AIR) null else it }
} else {
null
}
return AndroidResearchType(
id = id,
prerequisites = prerequisites,
@ -500,7 +532,10 @@ class AndroidResearchType(
features = features,
descriptionLines = descriptionLines,
experienceLevels = experienceLevels,
customName = customName
customName = customName,
iconText = iconTextValue,
skinIcon = skinIcon,
itemIcon = itemIcon,
)
}
@ -516,6 +551,9 @@ class AndroidResearchType(
val description = value["description"] as JsonArray? ?: JsonArray()
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 itemIcon = value["item_icon"]?.let { ForgeRegistries.ITEMS.getValue(ResourceLocation(it.asString)).let { if (it == Items.AIR) null else it } }
return AndroidResearchType(
id = id,
@ -525,7 +563,10 @@ class AndroidResearchType(
items = items.stream().map { ItemStackCodec.deserialize(it) }.filter { !it.isEmpty }.toList(),
descriptionLines = description.stream().map { Component.Serializer.fromJson(it) }.toList() as List<MutableComponent>,
experienceLevels = experience,
customName = customName
customName = customName,
iconText = iconText,
skinIcon = skinIcon,
itemIcon = itemIcon,
)
}
}
@ -536,6 +577,7 @@ class AndroidResearchType(
var experience: Int = 0,
var customName: Component? = null,
var description: MutableList<Component>? = null,
var itemIcon: Item? = null,
var skinIcon: SkinElement? = null,
var iconText: Component? = null,
) {
@ -545,15 +587,26 @@ class AndroidResearchType(
private val features = ArrayList<FeatureReference>()
fun withIconText(icon: Component?): Builder {
fun withIconText(icon: Component? = null): Builder {
this.iconText = icon
return this
}
fun withIconText() = withIconText(null)
fun withIcon(icon: SkinElement): Builder {
fun withIcon(icon: SkinElement? = null): Builder {
this.skinIcon = icon
this.itemIcon = null
return this
}
fun withIcon(icon: Item? = null): Builder {
this.itemIcon = icon
this.skinIcon = null
return this
}
fun withIcon(): Builder {
this.itemIcon = null
this.skinIcon = null
return this
}
@ -636,7 +689,10 @@ class AndroidResearchType(
features = features,
descriptionLines = description ?: listOf(),
experienceLevels = experience,
customName = customName
customName = customName,
skinIcon = skinIcon,
itemIcon = itemIcon,
iconText = iconText
).also { if (validate) it.validate() }
}
}

View File

@ -14,6 +14,7 @@ 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
@ -129,7 +130,31 @@ data class SkinElement @JvmOverloads constructor(
}
}
fun toNetwork(buff: FriendlyByteBuf) {
buff.writeUtf(texture.toString())
buff.writeFloat(x)
buff.writeFloat(y)
buff.writeFloat(width)
buff.writeFloat(height)
buff.writeFloat(imageWidth)
buff.writeFloat(imageHeight)
buff.writeEnum(winding)
}
companion object : TypeAdapter<SkinElement>(), JsonSerializer<SkinElement>, JsonDeserializer<SkinElement> {
fun fromNetwork(buff: FriendlyByteBuf): SkinElement {
val texture = ResourceLocation(buff.readUtf())
val x = buff.readFloat()
val y = buff.readFloat()
val width = buff.readFloat()
val height = buff.readFloat()
val imageWidth = buff.readFloat()
val imageHeight = buff.readFloat()
val winding = buff.readEnum(UVWindingOrder::class.java)
return SkinElement(texture, x, y, width, height, imageWidth, imageHeight, winding)
}
fun fromJson(value: JsonObject): SkinElement {
val texture = value["texture"]?.asString ?: throw JsonSyntaxException("Missing texture element")
val x = value["x"]?.asFloat ?: throw JsonSyntaxException("Missing x element")
@ -143,6 +168,10 @@ data class SkinElement @JvmOverloads constructor(
return SkinElement(ResourceLocation(texture), x, y, width, height, imageWidth, imageHeight, UVWindingOrder.valueOf(winding))
}
fun fromJson(value: JsonElement): SkinElement {
return fromJson(value as? JsonObject ?: throw JsonSyntaxException("Expected JsonObject, got ${value::class.qualifiedName}"))
}
override fun write(out: JsonWriter, value: SkinElement) {
TypeAdapters.JSON_ELEMENT.write(out, value.toJson())
}

View File

@ -1,6 +1,7 @@
package ru.dbotthepony.mc.otm.client.screen
import com.mojang.blaze3d.platform.InputConstants
import com.mojang.blaze3d.systems.RenderSystem
import com.mojang.blaze3d.vertex.PoseStack
import it.unimi.dsi.fastutil.ints.Int2FloatAVLTreeMap
import it.unimi.dsi.fastutil.ints.Int2ObjectAVLTreeMap
@ -9,6 +10,8 @@ import net.minecraft.ChatFormatting
import net.minecraft.client.Minecraft
import net.minecraft.network.chat.Component
import net.minecraft.world.entity.player.Inventory
import net.minecraft.world.item.ItemStack
import org.lwjgl.opengl.GL11
import ru.dbotthepony.mc.otm.core.TranslatableComponent
import ru.dbotthepony.mc.otm.android.AndroidResearch
import ru.dbotthepony.mc.otm.android.AndroidResearchManager
@ -300,10 +303,42 @@ private class AndroidResearchButton(
AndroidStationScreen.CAN_NOT_BE_RESEARCHED.setSystemColor()
}
val icon = node.skinIcon
val icon = node.type.skinIcon
val itemIcon = node.type.itemIcon
if (icon != null) {
icon.render(stack, 0f, 0f, width, height)
} else if (itemIcon != null) {
val itemstack = ItemStack(itemIcon, 1)
val systemPoseStack = RenderSystem.getModelViewStack()
systemPoseStack.pushPose()
systemPoseStack.translate((absoluteX + 1f).toDouble(), (absoluteY + 1f).toDouble(), 0.0)
RenderSystem.applyModelViewMatrix()
RenderSystem.depthFunc(GL11.GL_LESS)
// Thanks Mojang
// Very cool
// (for int x, int y, which are then cast into doubles anyway)
screen.itemRenderer.blitOffset = 1f // Z pos
screen.itemRenderer.renderAndDecorateItem(
requireNotNull(minecraft.player) { "yo, dude, what the fuck" },
itemstack,
0,
0,
(absoluteX + absoluteY * 1000f).toInt()
)
RenderSystem.depthFunc(GL11.GL_ALWAYS)
screen.itemRenderer.renderGuiItemDecorations(screen.font, itemstack, 0, 0, null)
screen.itemRenderer.blitOffset = 0f
// too big accumulations can lead to Z near clipping issues
systemPoseStack.popPose()
RenderSystem.applyModelViewMatrix()
clearDepth(stack)
} else {
drawRect(stack, 0f, 0f, width, height)
}
@ -318,7 +353,7 @@ private class AndroidResearchButton(
Widgets18.FORWARD_SLASH.render(stack)
}
val text = node.iconText
val text = node.type.iconText
if (text != null) {
font.drawShadow(stack, text, width - font.width(text), height - font.lineHeight, -0x1)