@@ -19,6 +19,7 @@ package com.lambda.module.modules.render
1919
2020import com.lambda.Lambda.mc
2121import com.lambda.config.settings.complex.Bind
22+ import com.lambda.interaction.material.container.containers.EnderChestContainer
2223import com.lambda.module.Module
2324import com.lambda.module.tag.ModuleTag
2425import com.lambda.util.KeyCode
@@ -32,6 +33,7 @@ import net.minecraft.client.gui.tooltip.TooltipComponent
3233import net.minecraft.client.render.RenderLayer
3334import net.minecraft.item.BlockItem
3435import net.minecraft.item.ItemStack
36+ import net.minecraft.item.Items
3537import net.minecraft.item.tooltip.TooltipData
3638import net.minecraft.util.DyeColor
3739import net.minecraft.util.Identifier
@@ -80,6 +82,18 @@ object ContainerPreview : Module(
8082 private fun getTooltipWidth (): Int = PADDING + COLS * SLOT_SIZE + PADDING
8183 private fun getTooltipHeight (): Int = TITLE_HEIGHT + ROWS * SLOT_SIZE + PADDING
8284
85+ /* *
86+ * Check if mouse is over the locked tooltip area (for click blocking)
87+ */
88+ @JvmStatic
89+ fun isMouseOverLockedTooltip (mouseX : Int , mouseY : Int ): Boolean {
90+ if (! isLocked) return false
91+ val width = getTooltipWidth()
92+ val height = getTooltipHeight()
93+ return mouseX >= lockedX && mouseX < lockedX + width &&
94+ mouseY >= lockedY && mouseY < lockedY + height
95+ }
96+
8397 /* *
8498 * Calculate text color based on background luminance.
8599 * Returns dark text for light backgrounds and white text for dark backgrounds.
@@ -97,7 +111,7 @@ object ContainerPreview : Module(
97111 }
98112
99113 @JvmStatic
100- fun renderShulkerTooltip (context : DrawContext , textRenderer : TextRenderer , component : ShulkerComponent , mouseX : Int , mouseY : Int ) {
114+ fun renderShulkerTooltip (context : DrawContext , textRenderer : TextRenderer , component : ContainerComponent , mouseX : Int , mouseY : Int ) {
101115 // Calculate tooltip position
102116 val width = getTooltipWidth()
103117 val height = getTooltipHeight()
@@ -144,33 +158,28 @@ object ContainerPreview : Module(
144158 }
145159
146160 private fun renderTooltipForStack (context : DrawContext , textRenderer : TextRenderer , stack : ItemStack , x : Int , y : Int , allowHover : Boolean ) {
147- val contents = stack.shulkerBoxContents
161+ val contents = getContainerContents( stack)
148162 val width = getTooltipWidth()
149163 val height = getTooltipHeight()
150164
151165 val matrices = context.matrices
152166 matrices.push()
153167 matrices.translate(0f , 0f , 400f )
154168
155- // Get shulker box color
156- val color = getShulkerColor(stack)
157- val tintColor = if (colorTint && color != null ) {
158- color.entityColor
159- } else {
160- 0xFFFFFFFF .toInt()
161- }
169+ // Get container color (shulker box color or purple for ender chest)
170+ val tintColor = getContainerTintColor(stack)
162171
163172 // Draw background with color tint
164173 drawBackground(context, x, y, width, height, tintColor)
165174
166- // Draw title (shulker box name) with appropriate text color
175+ // Draw title (container name) with appropriate text color
167176 val name = stack.name
168177 val textColor = getTextColor(tintColor)
169178 context.drawText(textRenderer, name, x + PADDING , y + 4 , textColor, false )
170179
171- // Draw items
172- val startX = x + PADDING + 1
173- val startY = y + TITLE_HEIGHT
180+ // Slots start at padding offset, items are centered in 18px slots (1px padding on each side)
181+ val slotsStartX = x + PADDING
182+ val slotsStartY = y + TITLE_HEIGHT
174183
175184 // Get actual mouse position for hover detection
176185 val actualMouseX = (mc.mouse.x * mc.window.scaledWidth / mc.window.width).toInt()
@@ -183,19 +192,25 @@ object ContainerPreview : Module(
183192 for ((index, item) in contents.withIndex()) {
184193 if (index >= COLS * ROWS ) break
185194
186- val slotX = index % COLS
187- val slotY = index / COLS
195+ val slotCol = index % COLS
196+ val slotRow = index / COLS
197+
198+ // Slot bounds (full 18x18 area for hover detection)
199+ val slotX = slotsStartX + slotCol * SLOT_SIZE
200+ val slotY = slotsStartY + slotRow * SLOT_SIZE
188201
189- val itemX = startX + slotX * SLOT_SIZE
190- val itemY = startY + slotY * SLOT_SIZE
202+ // Item position (centered in slot with 1px offset)
203+ val itemX = slotX + 1
204+ val itemY = slotY + 1
191205
192206 // Check if this slot is hovered (only when locked/allowHover)
207+ // Use full slot size (18x18) for hover detection to avoid dead zones
193208 if (allowHover) {
194- val isHovered = actualMouseX >= itemX && actualMouseX < itemX + 16 &&
195- actualMouseY >= itemY && actualMouseY < itemY + 16
209+ val isHovered = actualMouseX >= slotX && actualMouseX < slotX + SLOT_SIZE &&
210+ actualMouseY >= slotY && actualMouseY < slotY + SLOT_SIZE
196211
197212 if (isHovered && ! item.isEmpty) {
198- // Draw highlight
213+ // Draw highlight on the item area (16x16)
199214 context.fill(itemX, itemY, itemX + 16 , itemY + 16 , 0x80FFFFFF .toInt())
200215 hoveredStack = item
201216 hoveredSlotX = actualMouseX
@@ -215,17 +230,52 @@ object ContainerPreview : Module(
215230 if (hoveredStack != null && allowHover) {
216231 matrices.push()
217232 matrices.translate(0f , 0f , 500f ) // Higher Z than the main tooltip
218- // Set flag to prevent recursive mixin interception
219- isRenderingSubTooltip = true
220- try {
221- context.drawItemTooltip(textRenderer, hoveredStack, hoveredSlotX, hoveredSlotY)
222- } finally {
223- isRenderingSubTooltip = false
233+
234+ // Check if hovered item is also a previewable container (shulker in echest)
235+ if (isPreviewableContainer(hoveredStack)) {
236+ // Render nested container preview recursively
237+ val nestedWidth = getTooltipWidth()
238+ val nestedHeight = getTooltipHeight()
239+ val nestedX = calculateTooltipX(hoveredSlotX, nestedWidth)
240+ val nestedY = calculateTooltipY(hoveredSlotY, nestedHeight)
241+ renderTooltipForStack(context, textRenderer, hoveredStack, nestedX, nestedY, false )
242+ } else {
243+ // Regular item tooltip - use mixin bypass flag
244+ isRenderingSubTooltip = true
245+ try {
246+ context.drawItemTooltip(textRenderer, hoveredStack, hoveredSlotX, hoveredSlotY)
247+ } finally {
248+ isRenderingSubTooltip = false
249+ }
224250 }
225251 matrices.pop()
226252 }
227253 }
228254
255+ private fun getContainerContents (stack : ItemStack ): List <ItemStack > {
256+ return when {
257+ isShulkerBox(stack) -> stack.shulkerBoxContents
258+ isEnderChest(stack) -> EnderChestContainer .stacks
259+ else -> emptyList()
260+ }
261+ }
262+
263+ private fun getContainerTintColor (stack : ItemStack ): Int {
264+ if (! colorTint) return 0xFFFFFFFF .toInt()
265+
266+ return when {
267+ isShulkerBox(stack) -> {
268+ val color = getShulkerColor(stack)
269+ color?.entityColor ? : 0xFFFFFFFF .toInt()
270+ }
271+ isEnderChest(stack) -> {
272+ // Ender chest purple/dark tint
273+ 0xFF1E1E2E .toInt()
274+ }
275+ else -> 0xFFFFFFFF .toInt()
276+ }
277+ }
278+
229279 private fun calculateTooltipX (mouseX : Int , width : Int ): Int {
230280 val screenWidth = mc.window.scaledWidth
231281 var x = mouseX + 12
@@ -309,13 +359,31 @@ object ContainerPreview : Module(
309359 return stack.item in shulkerBoxes
310360 }
311361
312- class ShulkerComponent (val stack : ItemStack ) : TooltipData, TooltipComponent {
362+ @JvmStatic
363+ fun isEnderChest (stack : ItemStack ): Boolean {
364+ return stack.item == Items .ENDER_CHEST && EnderChestContainer .stacks.isNotEmpty()
365+ }
366+
367+ @JvmStatic
368+ fun isPreviewableContainer (stack : ItemStack ): Boolean {
369+ return isShulkerBox(stack) || isEnderChest(stack)
370+ }
371+
372+ open class ContainerComponent (val stack : ItemStack ) : TooltipData, TooltipComponent {
313373 val contents: List <ItemStack >
314- get() = stack.shulkerBoxContents
374+ get() = when {
375+ isShulkerBox(stack) -> stack.shulkerBoxContents
376+ isEnderChest(stack) -> EnderChestContainer .stacks
377+ else -> emptyList()
378+ }
315379
316380 // These methods are not used since we render the tooltip ourselves
317381 override fun drawItems (textRenderer : TextRenderer , x : Int , y : Int , width : Int , height : Int , context : DrawContext ) {}
318382 override fun getHeight (textRenderer : TextRenderer ): Int = 0
319383 override fun getWidth (textRenderer : TextRenderer ): Int = 0
320384 }
385+
386+ // Keep for backwards compatibility
387+ @Deprecated(" Use ContainerComponent instead" , ReplaceWith (" ContainerComponent" ))
388+ class ShulkerComponent (stack : ItemStack ) : ContainerComponent(stack)
321389}
0 commit comments