Skip to content

Commit 9411825

Browse files
committed
feat: storage esp
1 parent fe004bd commit 9411825

File tree

2 files changed

+175
-0
lines changed

2 files changed

+175
-0
lines changed
Lines changed: 173 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,173 @@
1+
/*
2+
* Copyright 2025 Lambda
3+
*
4+
* This program is free software: you can redistribute it and/or modify
5+
* it under the terms of the GNU General Public License as published by
6+
* the Free Software Foundation, either version 3 of the License, or
7+
* (at your option) any later version.
8+
*
9+
* This program is distributed in the hope that it will be useful,
10+
* but WITHOUT ANY WARRANTY; without even the implied warranty of
11+
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12+
* GNU General Public License for more details.
13+
*
14+
* You should have received a copy of the GNU General Public License
15+
* along with this program. If not, see <http://www.gnu.org/licenses/>.
16+
*/
17+
18+
package com.lambda.module.modules.render
19+
20+
import com.lambda.context.SafeContext
21+
import com.lambda.event.events.RenderEvent
22+
import com.lambda.event.listener.SafeListener.Companion.listen
23+
import com.lambda.graphics.renderer.esp.DirectionMask
24+
import com.lambda.graphics.renderer.esp.DirectionMask.buildSideMesh
25+
import com.lambda.graphics.renderer.esp.builders.buildFilled
26+
import com.lambda.graphics.renderer.esp.builders.buildFilledMesh
27+
import com.lambda.graphics.renderer.esp.builders.buildOutline
28+
import com.lambda.graphics.renderer.esp.builders.buildOutlineMesh
29+
import com.lambda.graphics.renderer.esp.impl.StaticESPRenderer
30+
import com.lambda.module.Module
31+
import com.lambda.module.tag.ModuleTag
32+
import com.lambda.threading.runSafe
33+
import com.lambda.util.extension.blockColor
34+
import com.lambda.util.extension.blockFilledMesh
35+
import com.lambda.util.extension.blockOutlineMesh
36+
import com.lambda.util.math.setAlpha
37+
import com.lambda.util.world.blockEntitySearch
38+
import com.lambda.util.world.entitySearch
39+
import net.minecraft.block.entity.BarrelBlockEntity
40+
import net.minecraft.block.entity.BlastFurnaceBlockEntity
41+
import net.minecraft.block.entity.BlockEntity
42+
import net.minecraft.block.entity.BrewingStandBlockEntity
43+
import net.minecraft.block.entity.ChestBlockEntity
44+
import net.minecraft.block.entity.DispenserBlockEntity
45+
import net.minecraft.block.entity.EnderChestBlockEntity
46+
import net.minecraft.block.entity.FurnaceBlockEntity
47+
import net.minecraft.block.entity.HopperBlockEntity
48+
import net.minecraft.block.entity.ShulkerBoxBlockEntity
49+
import net.minecraft.block.entity.SmokerBlockEntity
50+
import net.minecraft.entity.Entity
51+
import net.minecraft.entity.decoration.ItemFrameEntity
52+
import net.minecraft.entity.vehicle.AbstractMinecartEntity
53+
import net.minecraft.util.math.BlockPos
54+
import java.awt.Color
55+
56+
object StorageESP : Module(
57+
name = "StorageESP",
58+
description = "Render storage blocks/entities",
59+
defaultTags = setOf(ModuleTag.RENDER),
60+
) {
61+
private val page by setting("Page", Page.Render)
62+
63+
/* General settings */
64+
private val distance by setting("Distance", 64.0, 10.0..256.0, 1.0, "Maximum distance for rendering") { page == Page.General }
65+
66+
/* Render settings */
67+
private var drawFaces: Boolean by setting("Draw Faces", true, "Draw faces of blocks") { page == Page.Render }.apply { onValueSet { _, to -> if (!to) drawOutlines = true } }
68+
private var drawOutlines: Boolean by setting("Draw Outlines", true, "Draw outlines of blocks") { page == Page.Render }.apply { onValueSet { _, to -> if (!to) drawFaces = true } }
69+
private val outlineMode by setting("Outline Mode", DirectionMask.OutlineMode.AND, "Outline mode") { page == Page.Render }
70+
private val mesh by setting("Mesh", true, "Connect similar adjacent blocks")
71+
72+
/* Color settings */
73+
private val useBlockColor by setting("Use Block Color", true, "Use the color of the block instead") { page == Page.Color }
74+
private val alpha by setting("Alpha", 0.3, 0.1..1.0, 0.05) { page == Page.Color }
75+
76+
// TODO:
77+
// Once we have map setting we can do this:
78+
// val blockColors by setting("Block Colors", mapOf<String, Color>()) { page == Page.Color && !useBlockColor }
79+
// val renders by setting("Block Colors", mapOf<String, Color>()) { page == Page.Color && !useBlockColor }
80+
//
81+
// TODO: Create enum of MapColors
82+
83+
// I used this to extract the colors as rgb format
84+
//> function extract(color) {
85+
// ... console.log((color >> 16) & 0xFF)
86+
// ... console.log((color >> 8) & 0xFF)
87+
// ... console.log(color & 0xFF)
88+
// ... }
89+
90+
private val barrelColor by setting("Barrel Color", Color(143, 119, 72)) { page == Page.Color && !useBlockColor }
91+
private val blastFurnaceColor by setting("Blast Furnace Color", Color(153, 153, 153)) { page == Page.Color && !useBlockColor }
92+
private val brewingStandColor by setting("Brewing Stand Color", Color(167, 167, 167))
93+
private val chestColor by setting("Chest Color", Color(216, 127, 51)) { page == Page.Color && !useBlockColor }
94+
private val dispenserColor by setting("Dispenser Color", Color(153, 153, 153)) { page == Page.Color && !useBlockColor }
95+
private val enderChestColor by setting("Ender Chest Color", Color(127, 63, 178)) { page == Page.Color && !useBlockColor }
96+
private val furnaceColor by setting("Furnace Color", Color(153, 153, 153)) { page == Page.Color && !useBlockColor }
97+
private val hopperColor by setting("Hopper Color", Color(76, 76, 76)) { page == Page.Color && !useBlockColor }
98+
private val smokerColor by setting("Smoker Color", Color(112, 112, 112)) { page == Page.Color && !useBlockColor }
99+
private val shulkerColor by setting("Shulker Color", Color(178, 76, 216)) { page == Page.Color && !useBlockColor }
100+
private val itemFrameColor by setting("Item Frame Color", Color(216, 127, 51)) { page == Page.Color && !useBlockColor }
101+
private val cartColor by setting("Cart Color", Color(102, 127, 51)) { page == Page.Color && !useBlockColor }
102+
103+
init {
104+
listen<RenderEvent.StaticESP> { event ->
105+
blockEntitySearch<BlockEntity>(range = distance)
106+
.forEach { event.renderer.build(it, it.pos, buildMesh(it.pos)) }
107+
108+
(entitySearch<AbstractMinecartEntity>(range = distance) +
109+
entitySearch<ItemFrameEntity>(range = distance))
110+
.forEach { event.renderer.build(it, DirectionMask.ALL) }
111+
}
112+
}
113+
114+
private fun SafeContext.buildMesh(position: BlockPos) =
115+
if (mesh) buildSideMesh(position) {
116+
val block = world.getBlockEntity(it) ?: return@buildSideMesh false
117+
118+
getBlockEntityColor(block) != null &&
119+
block.cachedState.isFullCube(world, it)
120+
}
121+
else DirectionMask.ALL
122+
123+
private fun StaticESPRenderer.build(
124+
block: BlockEntity,
125+
pos: BlockPos,
126+
sides: Int,
127+
) = runSafe {
128+
val color = if (useBlockColor) blockColor(block.cachedState, pos) else getBlockEntityColor(block) ?: return@runSafe
129+
val filledMesh = blockFilledMesh(block.cachedState, pos)
130+
val outlineMesh = blockOutlineMesh(block.cachedState, pos)
131+
132+
if (drawFaces) buildFilledMesh(filledMesh, color.setAlpha(alpha), sides)
133+
if (drawOutlines) buildOutlineMesh(outlineMesh, color, sides, outlineMode)
134+
}
135+
136+
private fun StaticESPRenderer.build(
137+
entity: Entity,
138+
sides: Int,
139+
) = runSafe {
140+
val color = getEntityColor(entity) ?: return@runSafe
141+
142+
if (drawFaces) buildFilled(entity.boundingBox, color.setAlpha(alpha), sides)
143+
if (drawOutlines) buildOutline(entity.boundingBox, color, sides, outlineMode)
144+
}
145+
146+
private fun getBlockEntityColor(block: BlockEntity?) =
147+
when (block) {
148+
is BarrelBlockEntity -> barrelColor
149+
is BlastFurnaceBlockEntity -> blastFurnaceColor
150+
is BrewingStandBlockEntity -> brewingStandColor
151+
is ChestBlockEntity -> chestColor
152+
is DispenserBlockEntity -> dispenserColor
153+
is EnderChestBlockEntity -> enderChestColor
154+
is FurnaceBlockEntity -> furnaceColor
155+
is HopperBlockEntity -> hopperColor
156+
is SmokerBlockEntity -> smokerColor
157+
is ShulkerBoxBlockEntity -> shulkerColor
158+
else -> null
159+
}
160+
161+
private fun getEntityColor(entity: Entity?) =
162+
when (entity) {
163+
is AbstractMinecartEntity -> cartColor
164+
is ItemFrameEntity -> itemFrameColor
165+
else -> null
166+
}
167+
168+
private enum class Page {
169+
General,
170+
Render,
171+
Color
172+
}
173+
}

common/src/main/kotlin/com/lambda/util/extension/World.kt

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,7 @@ import com.lambda.util.world.*
2424
import net.minecraft.block.Block
2525
import net.minecraft.block.BlockState
2626
import net.minecraft.block.Blocks
27+
import net.minecraft.block.entity.BlockEntity
2728
import net.minecraft.datafixer.DataFixTypes
2829
import net.minecraft.fluid.FluidState
2930
import net.minecraft.fluid.Fluids
@@ -68,6 +69,7 @@ fun World.getFluidState(x: Int, y: Int, z: Int): FluidState {
6869
}
6970

7071
fun World.getBlockState(vec: FastVector): BlockState = getBlockState(vec.x, vec.y, vec.z)
72+
fun World.getBlockEntity(vec: FastVector) = getBlockEntity(vec.toBlockPos())
7173
fun World.getFluidState(vec: FastVector): FluidState = getFluidState(vec.x, vec.y, vec.z)
7274

7375
private fun positionFromIndex(width: Int, length: Int, index: Int): FastVector {

0 commit comments

Comments
 (0)