Skip to content

Commit ead7fab

Browse files
committed
air place additions. Render State option which renders the unplaced block at lower opacity and a rotation scroll bind to change the direction of the block
1 parent 374e84c commit ead7fab

2 files changed

Lines changed: 126 additions & 37 deletions

File tree

src/main/kotlin/com/lambda/module/modules/world/AirPlace.kt

Lines changed: 124 additions & 30 deletions
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,7 @@
1717

1818
package com.lambda.module.modules.world
1919

20+
import com.lambda.Lambda.mc
2021
import com.lambda.config.AutomationConfig.Companion.setDefaultAutomationConfig
2122
import com.lambda.config.applyEdits
2223
import com.lambda.config.settings.complex.Bind
@@ -29,6 +30,7 @@ import com.lambda.graphics.mc.renderer.TickedRenderer.Companion.tickedRenderer
2930
import com.lambda.interaction.construction.simulation.BuildSimulator.simulate
3031
import com.lambda.interaction.construction.simulation.context.BuildContext
3132
import com.lambda.interaction.construction.verify.TargetState
33+
import com.lambda.interaction.managers.interacting.InteractRequest
3234
import com.lambda.interaction.managers.interacting.InteractRequest.Companion.interactRequest
3335
import com.lambda.interaction.managers.rotating.Rotation.Companion.rotation
3436
import com.lambda.module.Module
@@ -37,33 +39,61 @@ import com.lambda.threading.runSafeAutomated
3739
import com.lambda.util.InputUtils.isSatisfied
3840
import com.lambda.util.KeyCode
3941
import com.lambda.util.NamedEnum
42+
import com.lambda.util.math.setAlpha
43+
import com.lambda.util.math.vec3d
4044
import net.minecraft.block.BlockState
45+
import net.minecraft.fluid.FlowableFluid
4146
import net.minecraft.item.BlockItem
47+
import net.minecraft.item.BucketItem
48+
import net.minecraft.item.DebugStickItem
4249
import net.minecraft.item.ItemPlacementContext
50+
import net.minecraft.state.property.Properties
4351
import net.minecraft.util.Hand
52+
import net.minecraft.util.hit.BlockHitResult
4453
import net.minecraft.util.math.BlockPos
45-
import net.minecraft.util.math.Box
54+
import net.minecraft.util.math.Vec3d
55+
import net.minecraft.util.math.random.Random
4656
import net.minecraft.world.RaycastContext
4757
import org.lwjgl.glfw.GLFW
58+
import java.awt.Color
4859
import java.util.concurrent.ConcurrentLinkedQueue
4960

5061
object AirPlace : Module(
5162
name = "AirPlace",
5263
description = "Allows placing blocks in air",
5364
tag = ModuleTag.WORLD
5465
) {
55-
enum class Group(override val displayName: String) : NamedEnum {
66+
private enum class Group(override val displayName: String) : NamedEnum {
5667
General("General"),
5768
Render("Render")
5869
}
5970

6071
private var distance by setting("Distance", 4.0, 1.0..7.0, 0.01).group(Group.General)
61-
private val scrollBind by setting("Scroll Bind", Bind(KeyCode.Unbound.code, GLFW.GLFW_MOD_CONTROL), "Allows you to hold the ctrl key and scroll to adjust distance").group(Group.General)
72+
private val buckets by setting("Buckets", true, "Enables air placement for buckets filled with fluids").group(Group.General)
73+
private val distanceScrollBind by setting("Distance Scroll Bind", Bind(KeyCode.Unbound.code, GLFW.GLFW_MOD_CONTROL), "Allows you to hold the given key and scroll to adjust distance").group(Group.General)
74+
private val rotationScrollBind by setting("Rotation Scroll Bind", Bind(KeyCode.Unbound.code, GLFW.GLFW_MOD_ALT), "Allows you to hold the given key and scroll to adjust the rotation of the block you're placing").group(Group.General)
75+
76+
private val renderState by setting("Render State", true).group(Group.Render)
77+
private val lineColor by setting("Line Color", Color.WHITE).group(Group.Render)
78+
private val stateAlpha by setting("State Alpha", 0.5, 0.01..1.0, 0.01).group(Group.Render)
6279

6380
private var placementPos: BlockPos? = null
81+
private var backingState: BlockState? = null
6482
private var placementState: BlockState? = null
6583
private val pendingInteractions = ConcurrentLinkedQueue<BuildContext>()
6684

85+
private var request: InteractRequest? = null
86+
private var extraPlaceTicks = 0
87+
88+
private val rotatingProperties = arrayOf(
89+
Properties.ROTATION,
90+
Properties.FACING,
91+
Properties.HORIZONTAL_FACING,
92+
Properties.HORIZONTAL_AXIS,
93+
Properties.AXIS,
94+
Properties.HOPPER_FACING
95+
)
96+
6797
init {
6898
setDefaultAutomationConfig {
6999
applyEdits {
@@ -72,56 +102,120 @@ object AirPlace : Module(
72102
}
73103

74104
listen<TickEvent.Pre> {
105+
if (request?.done == false) {
106+
airPlace()
107+
extraPlaceTicks++
108+
if (extraPlaceTicks > 40) request = null
109+
return@listen
110+
} else {
111+
extraPlaceTicks = 0
112+
request = null
113+
}
114+
75115
val selectedStack = player.inventory.selectedStack
76-
val blockItem = selectedStack.item as? BlockItem ?: run {
77-
placementPos = null
78-
placementState = null
116+
val blockItem = selectedStack.item as? BlockItem
117+
if (blockItem != null) {
118+
val placementContext = ItemPlacementContext(
119+
world,
120+
player, Hand.MAIN_HAND,
121+
selectedStack,
122+
getHitResult()
123+
)
124+
setPosAndState(placementContext.blockPos, blockItem.getPlacementState(placementContext))
79125
return@listen
80126
}
81-
val raycastEnd = player.rotation.vector.multiply(distance).add(player.eyePos)
82-
val raycastContext = RaycastContext(
83-
player.eyePos,
84-
raycastEnd,
85-
RaycastContext.ShapeType.OUTLINE,
86-
RaycastContext.FluidHandling.NONE,
87-
player
88-
)
89-
val placementContext = ItemPlacementContext(
90-
world,
91-
player, Hand.MAIN_HAND,
92-
selectedStack,
93-
world.raycast(raycastContext),
94-
)
95-
placementPos = placementContext.blockPos
96-
placementState = blockItem.getPlacementState(placementContext)
127+
128+
if (buckets) run bucket@{
129+
val item = selectedStack.item
130+
if (item !is BucketItem) return@bucket
131+
val fluid = item.fluid as? FlowableFluid ?: return@bucket
132+
if (item.fluid !is FlowableFluid) return@bucket
133+
placementPos = getHitResult().blockPos
134+
placementState = fluid.defaultState.blockState
135+
}
136+
setPosAndState()
137+
return@listen
97138
}
98139

99140
listen<PlayerEvent.Interact.Block> { if (airPlace()) it.cancel() }
100141
listen<PlayerEvent.Interact.Item> { if (airPlace()) it.cancel() }
101142

102143
tickedRenderer("Air Place Ticked Renderer") { safeContext ->
103144
placementPos?.let { pos ->
104-
val boxes = placementState?.getOutlineShape(safeContext.world, pos)?.boundingBoxes
105-
?: listOf(Box(0.0, 0.0, 0.0, 1.0, 1.0, 1.0))
106-
boxes.forEach { box ->
107-
box(box.offset(pos)) { hideFill() }
145+
placementState?.let { state ->
146+
val boxes = state.getOutlineShape(safeContext.world, pos).boundingBoxes.map { it.offset(pos) }
147+
boxes.forEach { box ->
148+
box(box) {
149+
hideFill()
150+
outlineColor(lineColor)
151+
}
152+
}
153+
if (renderState) {
154+
val model = mc.bakedModelManager.blockModels.getModel(state)
155+
val parts = model.getParts(Random.create())
156+
parts.forEach { part ->
157+
model(
158+
part,
159+
pos = pos.vec3d,
160+
scale = Vec3d(1.0, 1.0, 1.0),
161+
pixelPerfect = true,
162+
color = Color.WHITE.setAlpha(stateAlpha)
163+
)
164+
}
165+
}
108166
}
109167
}
110168
}
111169

112170
listen<ButtonEvent.Mouse.Scroll> { event ->
113-
if (!scrollBind.isSatisfied()) return@listen
114-
event.cancel()
115-
distance += event.delta.y
171+
if (distanceScrollBind.isSatisfied()) {
172+
event.cancel()
173+
distance += event.delta.y
174+
return@listen
175+
} else if (rotationScrollBind.isSatisfied()) {
176+
event.cancel()
177+
placementState = placementState?.withSteppedRotation(event.delta.y < 0)
178+
}
116179
}
117180
}
118181

182+
private fun setPosAndState(pos: BlockPos? = null, state: BlockState? = null) {
183+
if (state === backingState) {
184+
placementPos = pos
185+
return
186+
}
187+
backingState = state
188+
placementState = state
189+
}
190+
191+
private fun BlockState.withSteppedRotation(reverse: Boolean): BlockState {
192+
var rotatedState = this
193+
rotatingProperties.forEach { property ->
194+
if (property in rotatedState) {
195+
rotatedState = DebugStickItem.cycle(rotatedState, property, reverse)
196+
}
197+
}
198+
return rotatedState
199+
}
200+
201+
private fun SafeContext.getHitResult(): BlockHitResult {
202+
val raycastEnd = player.rotation.vector.multiply(distance).add(player.eyePos)
203+
val raycastContext = RaycastContext(
204+
player.eyePos,
205+
raycastEnd,
206+
RaycastContext.ShapeType.OUTLINE,
207+
RaycastContext.FluidHandling.NONE,
208+
player
209+
)
210+
return world.raycast(raycastContext)
211+
}
212+
119213
private fun SafeContext.airPlace(): Boolean {
120214
if (player.inventory.selectedStack.item !is BlockItem) return false
121215
placementPos?.let { pos ->
122216
placementState?.let { state ->
123217
runSafeAutomated {
124-
mapOf(pos to TargetState.State(state))
218+
request = mapOf(pos to TargetState.State(state))
125219
.simulate()
126220
.interactRequest(pendingInteractions)
127221
?.submit()

src/main/resources/lambda.accesswidener

Lines changed: 2 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,6 @@ transitive-accessible field net/minecraft/client/MinecraftClient paused Z
66
transitive-accessible field net/minecraft/client/MinecraftClient thread Ljava/lang/Thread;
77
transitive-accessible field net/minecraft/client/MinecraftClient uptimeInTicks J
88
transitive-accessible field net/minecraft/client/input/Input movementVector Lnet/minecraft/util/math/Vec2f;
9-
# REMOVED in 1.21.11: renderTaskQueue - use mc.execute {} instead (inherited from ReentrantThreadExecutor)
109
transitive-accessible field net/minecraft/client/option/KeyBinding boundKey Lnet/minecraft/client/util/InputUtil$Key;
1110
transitive-accessible method net/minecraft/client/MinecraftClient getWindowTitle ()Ljava/lang/String;
1211
transitive-accessible field net/minecraft/client/option/KeyBinding KEYS_BY_ID Ljava/util/Map;
@@ -26,7 +25,6 @@ transitive-accessible method net/minecraft/item/BlockItem placeFromNbt (Lnet/min
2625
transitive-accessible method net/minecraft/item/BlockItem postPlacement (Lnet/minecraft/util/math/BlockPos;Lnet/minecraft/world/World;Lnet/minecraft/entity/player/PlayerEntity;Lnet/minecraft/item/ItemStack;Lnet/minecraft/block/BlockState;)Z
2726
transitive-accessible method net/minecraft/item/BlockItem getPlaceSound (Lnet/minecraft/block/BlockState;)Lnet/minecraft/sound/SoundEvent;
2827
transitive-accessible field net/minecraft/state/State owner Ljava/lang/Object;
29-
# MOVED in 1.21.11: BackgroundRenderer$StatusEffectFogModifier -> net/minecraft/client/render/fog/StatusEffectFogModifier
3028
transitive-accessible class net/minecraft/client/render/fog/StatusEffectFogModifier
3129
transitive-accessible field net/minecraft/client/particle/NoRenderParticleRenderer EMPTY Lnet/minecraft/client/render/Submittable;
3230
transitive-accessible field net/minecraft/entity/Entity GLIDING_FLAG_INDEX I
@@ -75,7 +73,7 @@ transitive-accessible field net/minecraft/client/texture/SpriteContents image Ln
7573
transitive-accessible class net/minecraft/client/gui/screen/SplashOverlay$LogoTexture
7674
transitive-accessible field com/mojang/blaze3d/systems/RenderSystem$ShapeIndexBuffer indexBuffer Lcom/mojang/blaze3d/buffers/GpuBuffer;
7775
transitive-accessible field net/minecraft/client/gl/GlGpuBuffer id I
78-
accessible field net/minecraft/client/MinecraftClient entityRenderManager Lnet/minecraft/client/render/entity/EntityRenderManager;
76+
transitive-accessible field net/minecraft/client/MinecraftClient entityRenderManager Lnet/minecraft/client/render/entity/EntityRenderManager;
7977
transitive-accessible field net/minecraft/client/render/RenderLayer renderSetup Lnet/minecraft/client/render/RenderSetup;
8078
transitive-accessible field net/minecraft/client/render/RenderSetup layeringTransform Lnet/minecraft/client/render/LayeringTransform;
8179
transitive-accessible field net/minecraft/client/render/LayeringTransform transform Ljava/util/function/Consumer;
@@ -109,9 +107,7 @@ transitive-accessible field net/minecraft/text/Style obfuscated Ljava/lang/Boole
109107
transitive-accessible field net/minecraft/text/Style clickEvent Lnet/minecraft/text/ClickEvent;
110108
transitive-accessible field net/minecraft/text/Style hoverEvent Lnet/minecraft/text/HoverEvent;
111109
transitive-accessible field net/minecraft/text/Style insertion Ljava/lang/String;
112-
# CHANGED in 1.21.11: font type changed from Identifier to StyleSpriteSource
113110
transitive-accessible field net/minecraft/text/Style font Lnet/minecraft/text/StyleSpriteSource;
114-
# CHANGED in 1.21.11: constructor added shadowColor parameter, font type changed to StyleSpriteSource
115111
transitive-accessible method net/minecraft/text/Style <init> (Lnet/minecraft/text/TextColor;Ljava/lang/Integer;Ljava/lang/Boolean;Ljava/lang/Boolean;Ljava/lang/Boolean;Ljava/lang/Boolean;Ljava/lang/Boolean;Lnet/minecraft/text/ClickEvent;Lnet/minecraft/text/HoverEvent;Ljava/lang/String;Lnet/minecraft/text/StyleSpriteSource;)V
116112

117113
# Network
@@ -143,11 +139,10 @@ transitive-accessible method net/minecraft/util/math/Vec3i setY (I)Lnet/minecraf
143139
transitive-accessible method net/minecraft/util/math/Vec3i setZ (I)Lnet/minecraft/util/math/Vec3i;
144140

145141
# Debug
146-
# REMOVED in 1.21.11: showDebugHud - use DebugHud.shouldShowDebugHud() method instead
147142
transitive-accessible field net/minecraft/client/gui/hud/DebugHud renderingChartVisible Z
148143
transitive-accessible field net/minecraft/client/gui/hud/DebugHud renderingAndTickChartsVisible Z
149144
transitive-accessible field net/minecraft/client/gui/hud/DebugHud packetSizeAndPingChartsVisible Z
150-
# REMOVED in 1.21.11: showChunkBorder/showOctree - now controlled via debugHudEntryList.isEntryVisible(DebugHudEntries.CHUNK_BORDERS/CHUNK_SECTION_OCTREE)
145+
transitive-accessible method net/minecraft/item/DebugStickItem cycle (Lnet/minecraft/block/BlockState;Lnet/minecraft/state/property/Property;Z)Lnet/minecraft/block/BlockState;
151146

152147
# Other
153148
transitive-accessible field net/minecraft/structure/StructureTemplate blockInfoLists Ljava/util/List;

0 commit comments

Comments
 (0)