diff options
Diffstat (limited to 'src/main/kotlin')
-rw-r--r-- | src/main/kotlin/commands/rome.kt | 1 | ||||
-rw-r--r-- | src/main/kotlin/events/CustomItemModelEvent.kt | 21 | ||||
-rw-r--r-- | src/main/kotlin/events/EntityRenderTintEvent.kt | 66 | ||||
-rw-r--r-- | src/main/kotlin/features/debug/PowerUserTools.kt | 22 | ||||
-rw-r--r-- | src/main/kotlin/features/events/anniversity/CenturyRaffleFeatures.kt | 63 | ||||
-rw-r--r-- | src/main/kotlin/util/MC.kt | 4 | ||||
-rw-r--r-- | src/main/kotlin/util/mc/IntrospectableItemModelManager.kt | 7 | ||||
-rw-r--r-- | src/main/kotlin/util/render/TintedOverlayTexture.kt | 44 | ||||
-rw-r--r-- | src/main/kotlin/util/skyblock/SkyBlockItems.kt | 5 |
9 files changed, 227 insertions, 6 deletions
diff --git a/src/main/kotlin/commands/rome.kt b/src/main/kotlin/commands/rome.kt index 13acb3c..5412792 100644 --- a/src/main/kotlin/commands/rome.kt +++ b/src/main/kotlin/commands/rome.kt @@ -254,6 +254,7 @@ fun firmamentCommand() = literal("firmament") { val player = MC.player ?: return@thenExecute player.world.getOtherEntities(player, player.boundingBox.expand(12.0)) .forEach(PowerUserTools::showEntity) + PowerUserTools.showEntity(player) } } thenLiteral("callUrsa") { diff --git a/src/main/kotlin/events/CustomItemModelEvent.kt b/src/main/kotlin/events/CustomItemModelEvent.kt index e7b6eb8..21ee326 100644 --- a/src/main/kotlin/events/CustomItemModelEvent.kt +++ b/src/main/kotlin/events/CustomItemModelEvent.kt @@ -5,28 +5,39 @@ import kotlin.jvm.optionals.getOrNull import net.minecraft.item.ItemStack import net.minecraft.util.Identifier import moe.nea.firmament.util.collections.WeakCache +import moe.nea.firmament.util.mc.IntrospectableItemModelManager // TODO: assert an order on these events data class CustomItemModelEvent( val itemStack: ItemStack, + val itemModelManager: IntrospectableItemModelManager, var overrideModel: Identifier? = null, ) : FirmamentEvent() { companion object : FirmamentEventBus<CustomItemModelEvent>() { val cache = WeakCache.memoize("ItemModelIdentifier", ::getModelIdentifier0) @JvmStatic - fun getModelIdentifier(itemStack: ItemStack?): Identifier? { + fun getModelIdentifier(itemStack: ItemStack?, itemModelManager: IntrospectableItemModelManager): Identifier? { if (itemStack == null) return null - return cache.invoke(itemStack).getOrNull() + return cache.invoke(itemStack, itemModelManager).getOrNull() } - fun getModelIdentifier0(itemStack: ItemStack): Optional<Identifier> { + fun getModelIdentifier0( + itemStack: ItemStack, + itemModelManager: IntrospectableItemModelManager + ): Optional<Identifier> { // TODO: add an error / warning if the model does not exist - return Optional.ofNullable(publish(CustomItemModelEvent(itemStack)).overrideModel) + return Optional.ofNullable(publish(CustomItemModelEvent(itemStack, itemModelManager)).overrideModel) } } fun overrideIfExists(overrideModel: Identifier) { - this.overrideModel = overrideModel + if (itemModelManager.hasModel_firmament(overrideModel)) + this.overrideModel = overrideModel + } + + fun overrideIfEmpty(identifier: Identifier) { + if (overrideModel == null) + overrideModel = identifier } } diff --git a/src/main/kotlin/events/EntityRenderTintEvent.kt b/src/main/kotlin/events/EntityRenderTintEvent.kt new file mode 100644 index 0000000..29b888b --- /dev/null +++ b/src/main/kotlin/events/EntityRenderTintEvent.kt @@ -0,0 +1,66 @@ +package moe.nea.firmament.events + +import net.minecraft.client.render.GameRenderer +import net.minecraft.client.render.OverlayTexture +import net.minecraft.client.render.entity.state.EntityRenderState +import net.minecraft.entity.Entity +import net.minecraft.entity.LivingEntity +import moe.nea.firmament.util.render.TintedOverlayTexture + +/** + * Change the tint color of a [LivingEntity] + */ +class EntityRenderTintEvent( + val entity: Entity, + val renderState: HasTintRenderState +) : FirmamentEvent.Cancellable() { + init { + if (entity !is LivingEntity) { + cancel() + } + } + + companion object : FirmamentEventBus<EntityRenderTintEvent>() { + /** + * Static variable containing an override for [GameRenderer.getOverlayTexture]. Should be only set briefly. + * + * This variable only affects render layers that naturally make use of the overlay texture, have proper overlay UVs set (`overlay u != 0`), and have a shader that makes use of the overlay (does not have the `NO_OVERLAY` flag set in its json definition). + * + * Currently supported layers: [net.minecraft.client.render.entity.equipment.EquipmentRenderer], [net.minecraft.client.render.entity.model.PlayerEntityModel], as well as some others naturally. + * + * @see moe.nea.firmament.mixins.render.entitytints.ReplaceOverlayTexture + * @see TintedOverlayTexture + */ + @JvmField + var overlayOverride: OverlayTexture? = null + } + + @Suppress("PropertyName", "FunctionName") + interface HasTintRenderState { + /** + * Multiplicative tint applied before the overlay. + */ + var tint_firmament: Int + + /** + * Must be set for [tint_firmament] to have any effect. + */ + var hasTintOverride_firmament: Boolean + + // TODO: allow for more specific selection of which layers get tinted + /** + * Specify a [TintedOverlayTexture] to be used. This does not apply to render layers not using the overlay texture. + * @see overlayOverride + */ + var overlayTexture_firmament: TintedOverlayTexture? + fun reset_firmament() + + companion object { + @JvmStatic + fun cast(state: EntityRenderState): HasTintRenderState { + return state as HasTintRenderState + } + } + } + +} diff --git a/src/main/kotlin/features/debug/PowerUserTools.kt b/src/main/kotlin/features/debug/PowerUserTools.kt index 225bc13..8be5d5d 100644 --- a/src/main/kotlin/features/debug/PowerUserTools.kt +++ b/src/main/kotlin/features/debug/PowerUserTools.kt @@ -1,22 +1,31 @@ package moe.nea.firmament.features.debug +import com.mojang.serialization.Codec +import com.mojang.serialization.DynamicOps import com.mojang.serialization.JsonOps +import com.mojang.serialization.codecs.RecordCodecBuilder import kotlin.jvm.optionals.getOrNull import net.minecraft.block.SkullBlock import net.minecraft.block.entity.SkullBlockEntity import net.minecraft.component.DataComponentTypes import net.minecraft.component.type.ProfileComponent import net.minecraft.entity.Entity +import net.minecraft.entity.EntityType import net.minecraft.entity.LivingEntity import net.minecraft.item.ItemStack import net.minecraft.item.Items +import net.minecraft.nbt.NbtCompound import net.minecraft.nbt.NbtOps +import net.minecraft.nbt.NbtString +import net.minecraft.predicate.NbtPredicate import net.minecraft.text.Text import net.minecraft.text.TextCodecs import net.minecraft.util.Identifier import net.minecraft.util.hit.BlockHitResult import net.minecraft.util.hit.EntityHitResult import net.minecraft.util.hit.HitResult +import net.minecraft.util.math.Position +import net.minecraft.util.math.Vec3d import moe.nea.firmament.annotations.Subscribe import moe.nea.firmament.events.CustomItemModelEvent import moe.nea.firmament.events.HandledScreenKeyPressedEvent @@ -30,6 +39,8 @@ import moe.nea.firmament.mixins.accessor.AccessorHandledScreen import moe.nea.firmament.util.ClipboardUtils import moe.nea.firmament.util.MC import moe.nea.firmament.util.focusedItemStack +import moe.nea.firmament.util.mc.IntrospectableItemModelManager +import moe.nea.firmament.util.mc.SNbtFormatter import moe.nea.firmament.util.mc.SNbtFormatter.Companion.toPrettyString import moe.nea.firmament.util.mc.displayNameAccordingToNbt import moe.nea.firmament.util.mc.loreAccordingToNbt @@ -87,6 +98,11 @@ object PowerUserTools : FirmamentFeature { } fun showEntity(target: Entity) { + val nbt = NbtPredicate.entityToNbt(target) + nbt.remove("Inventory") + nbt.put("StyledName", TextCodecs.CODEC.encodeStart(NbtOps.INSTANCE, target.styledDisplayName).orThrow) + println(SNbtFormatter.prettify(nbt)) + ClipboardUtils.setTextContent(SNbtFormatter.prettify(nbt)) MC.sendChat(Text.translatable("firmament.poweruser.entity.type", target.type)) MC.sendChat(Text.translatable("firmament.poweruser.entity.name", target.name)) MC.sendChat(Text.stringifiedTranslatable("firmament.poweruser.entity.position", target.pos)) @@ -119,7 +135,11 @@ object PowerUserTools : FirmamentFeature { lastCopiedStack = Pair(item, Text.stringifiedTranslatable("firmament.tooltip.copied.skyblockid", sbId.neuItem)) } else if (it.matches(TConfig.copyTexturePackId)) { - val model = CustomItemModelEvent.getModelIdentifier(item) // TODO: remove global texture overrides, maybe + val model = CustomItemModelEvent.getModelIdentifier0(item, object : IntrospectableItemModelManager { + override fun hasModel_firmament(identifier: Identifier): Boolean { + return true + } + }).getOrNull() // TODO: remove global texture overrides, maybe if (model == null) { lastCopiedStack = Pair(item, Text.translatable("firmament.tooltip.copied.modelid.fail")) return diff --git a/src/main/kotlin/features/events/anniversity/CenturyRaffleFeatures.kt b/src/main/kotlin/features/events/anniversity/CenturyRaffleFeatures.kt new file mode 100644 index 0000000..9935051 --- /dev/null +++ b/src/main/kotlin/features/events/anniversity/CenturyRaffleFeatures.kt @@ -0,0 +1,63 @@ +package moe.nea.firmament.features.events.anniversity + +import java.util.Optional +import me.shedaniel.math.Color +import kotlin.jvm.optionals.getOrNull +import net.minecraft.entity.player.PlayerEntity +import net.minecraft.text.Style +import net.minecraft.util.Formatting +import moe.nea.firmament.annotations.Subscribe +import moe.nea.firmament.events.EntityRenderTintEvent +import moe.nea.firmament.gui.config.ManagedConfig +import moe.nea.firmament.util.MC +import moe.nea.firmament.util.SkyblockId +import moe.nea.firmament.util.render.TintedOverlayTexture +import moe.nea.firmament.util.skyBlockId +import moe.nea.firmament.util.skyblock.SkyBlockItems + +object CenturyRaffleFeatures { + object TConfig : ManagedConfig("centuryraffle", Category.EVENTS) { + val highlightPlayersForSlice by toggle("highlight-cake-players") { true } +// val highlightAllPlayers by toggle("highlight-all-cake-players") { true } + } + + val cakeIcon = "⛃" + + val cakeColors = listOf( + CakeTeam(SkyBlockItems.SLICE_OF_BLUEBERRY_CAKE, Formatting.BLUE), + CakeTeam(SkyBlockItems.SLICE_OF_CHEESECAKE, Formatting.YELLOW), + CakeTeam(SkyBlockItems.SLICE_OF_GREEN_VELVET_CAKE, Formatting.GREEN), + CakeTeam(SkyBlockItems.SLICE_OF_RED_VELVET_CAKE, Formatting.RED), + CakeTeam(SkyBlockItems.SLICE_OF_STRAWBERRY_SHORTCAKE, Formatting.LIGHT_PURPLE), + ) + + data class CakeTeam( + val id: SkyblockId, + val formatting: Formatting, + ) { + val searchedTextRgb = formatting.colorValue!! + val brightenedRgb = Color.ofOpaque(searchedTextRgb)//.brighter(2.0) + val tintOverlay by lazy { + TintedOverlayTexture().setColor(brightenedRgb) + } + } + + val sliceToColor = cakeColors.associateBy { it.id } + + @Subscribe + fun onEntityRender(event: EntityRenderTintEvent) { + if (!TConfig.highlightPlayersForSlice) return + val requestedCakeTeam = sliceToColor[MC.stackInHand?.skyBlockId] ?: return + // TODO: cache the requested color + val player = event.entity as? PlayerEntity ?: return + val cakeColor: Style = player.styledDisplayName.visit( + { style, text -> + if (text == cakeIcon) Optional.of(style) + else Optional.empty() + }, Style.EMPTY).getOrNull() ?: return + if (cakeColor.color?.rgb == requestedCakeTeam.searchedTextRgb) { + event.renderState.overlayTexture_firmament = requestedCakeTeam.tintOverlay + } + } + +} diff --git a/src/main/kotlin/util/MC.kt b/src/main/kotlin/util/MC.kt index 215d2a8..ca3742d 100644 --- a/src/main/kotlin/util/MC.kt +++ b/src/main/kotlin/util/MC.kt @@ -7,11 +7,13 @@ import net.minecraft.client.gui.hud.InGameHud import net.minecraft.client.gui.screen.Screen import net.minecraft.client.gui.screen.ingame.HandledScreen import net.minecraft.client.network.ClientPlayerEntity +import net.minecraft.client.render.GameRenderer import net.minecraft.client.render.WorldRenderer import net.minecraft.client.render.item.ItemRenderer import net.minecraft.client.world.ClientWorld import net.minecraft.entity.Entity import net.minecraft.item.Item +import net.minecraft.item.ItemStack import net.minecraft.network.packet.c2s.play.CommandExecutionC2SPacket import net.minecraft.registry.BuiltinRegistries import net.minecraft.registry.RegistryKeys @@ -85,6 +87,7 @@ object MC { inline val resourceManager get() = (instance.resourceManager as ReloadableResourceManagerImpl) inline val itemRenderer: ItemRenderer get() = instance.itemRenderer inline val worldRenderer: WorldRenderer get() = instance.worldRenderer + inline val gameRenderer: GameRenderer get() = instance.gameRenderer inline val networkHandler get() = player?.networkHandler inline val instance get() = MinecraftClient.getInstance() inline val keyboard get() = instance.keyboard @@ -96,6 +99,7 @@ object MC { inline val soundManager get() = instance.soundManager inline val player: ClientPlayerEntity? get() = TestUtil.unlessTesting { instance.player } inline val camera: Entity? get() = instance.cameraEntity + inline val stackInHand: ItemStack? get() = player?.inventory?.mainHandStack inline val guiAtlasManager get() = instance.guiAtlasManager inline val world: ClientWorld? get() = TestUtil.unlessTesting { instance.world } inline val playerName: String? get() = player?.name?.unformattedString diff --git a/src/main/kotlin/util/mc/IntrospectableItemModelManager.kt b/src/main/kotlin/util/mc/IntrospectableItemModelManager.kt new file mode 100644 index 0000000..e546fd3 --- /dev/null +++ b/src/main/kotlin/util/mc/IntrospectableItemModelManager.kt @@ -0,0 +1,7 @@ +package moe.nea.firmament.util.mc + +import net.minecraft.util.Identifier + +interface IntrospectableItemModelManager { + fun hasModel_firmament(identifier: Identifier): Boolean +} diff --git a/src/main/kotlin/util/render/TintedOverlayTexture.kt b/src/main/kotlin/util/render/TintedOverlayTexture.kt new file mode 100644 index 0000000..a02eccc --- /dev/null +++ b/src/main/kotlin/util/render/TintedOverlayTexture.kt @@ -0,0 +1,44 @@ +package moe.nea.firmament.util.render + +import com.mojang.blaze3d.platform.GlConst +import com.mojang.blaze3d.systems.RenderSystem +import me.shedaniel.math.Color +import net.minecraft.client.render.OverlayTexture +import net.minecraft.util.math.ColorHelper +import moe.nea.firmament.util.ErrorUtil + +class TintedOverlayTexture : OverlayTexture() { + companion object { + val size = 16 + } + + private var lastColor: Color? = null + fun setColor(color: Color): TintedOverlayTexture { + val image = ErrorUtil.notNullOr(texture.image, "Disposed TintedOverlayTexture written to") { return this } + if (color == lastColor) return this + lastColor = color + + for (i in 0..<size) { + for (j in 0..<size) { + if (i < 8) { + image.setColorArgb(j, i, 0xB2FF0000.toInt()) + } else { + val k = ((1F - j / 15F * 0.75F) * 255F).toInt() + image.setColorArgb(j, i, ColorHelper.withAlpha(k, color.color)) + } + } + } + + RenderSystem.activeTexture(GlConst.GL_TEXTURE1) + texture.bindTexture() + texture.setFilter(false, false) + texture.setClamp(true) + image.upload(0, + 0, 0, + 0, 0, + image.width, image.height, + false) + RenderSystem.activeTexture(GlConst.GL_TEXTURE0) + return this + } +} diff --git a/src/main/kotlin/util/skyblock/SkyBlockItems.kt b/src/main/kotlin/util/skyblock/SkyBlockItems.kt index cfd8429..ca2b17b 100644 --- a/src/main/kotlin/util/skyblock/SkyBlockItems.kt +++ b/src/main/kotlin/util/skyblock/SkyBlockItems.kt @@ -8,4 +8,9 @@ object SkyBlockItems { val DIAMOND = SkyblockId("DIAMOND") val ANCESTRAL_SPADE = SkyblockId("ANCESTRAL_SPADE") val REFORGE_ANVIL = SkyblockId("REFORGE_ANVIL") + val SLICE_OF_BLUEBERRY_CAKE = SkyblockId("SLICE_OF_BLUEBERRY_CAKE") + val SLICE_OF_CHEESECAKE = SkyblockId("SLICE_OF_CHEESECAKE") + val SLICE_OF_GREEN_VELVET_CAKE = SkyblockId("SLICE_OF_GREEN_VELVET_CAKE") + val SLICE_OF_RED_VELVET_CAKE = SkyblockId("SLICE_OF_RED_VELVET_CAKE") + val SLICE_OF_STRAWBERRY_SHORTCAKE = SkyblockId("SLICE_OF_STRAWBERRY_SHORTCAKE") } |