Skip to content

Commit 1614f38

Browse files
committed
Distinct block update event for server updates
1 parent 4d63c79 commit 1614f38

File tree

6 files changed

+67
-38
lines changed

6 files changed

+67
-38
lines changed

common/src/main/java/com/lambda/mixin/world/ClientWorldMixin.java

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -19,10 +19,13 @@
1919

2020
import com.lambda.event.EventFlow;
2121
import com.lambda.event.events.EntityEvent;
22+
import com.lambda.event.events.WorldEvent;
2223
import com.lambda.module.modules.render.WorldColors;
2324
import com.lambda.util.math.ColorKt;
25+
import net.minecraft.block.BlockState;
2426
import net.minecraft.client.world.ClientWorld;
2527
import net.minecraft.entity.Entity;
28+
import net.minecraft.util.math.BlockPos;
2629
import net.minecraft.util.math.Vec3d;
2730
import org.spongepowered.asm.mixin.Mixin;
2831
import org.spongepowered.asm.mixin.injection.At;
@@ -57,4 +60,9 @@ private void getSkyColorInject(Vec3d cameraPos, float tickDelta, CallbackInfoRet
5760
cir.setReturnValue(ColorKt.getVec3d(WorldColors.getSkyColor()));
5861
}
5962
}
63+
64+
@Inject(method = "handleBlockUpdate", at = @At("HEAD"), cancellable = true)
65+
private void handleBlockUpdateInject(BlockPos pos, BlockState newState, int flags, CallbackInfo ci) {
66+
if (EventFlow.post(new WorldEvent.BlockUpdate.Server(pos, newState)).isCanceled()) ci.cancel();
67+
}
6068
}

common/src/main/java/com/lambda/mixin/world/WorldMixin.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -31,6 +31,6 @@
3131
public abstract class WorldMixin {
3232
@Inject(method = "onBlockChanged", at = @At("TAIL"))
3333
void onBlockChanged(BlockPos pos, BlockState oldBlock, BlockState newBlock, CallbackInfo ci) {
34-
EventFlow.post(new WorldEvent.BlockChange(pos, oldBlock, newBlock));
34+
EventFlow.post(new WorldEvent.BlockUpdateClientSide(pos, oldBlock, newBlock));
3535
}
3636
}

common/src/main/kotlin/com/lambda/event/events/WorldEvent.kt

Lines changed: 34 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -18,7 +18,12 @@
1818
package com.lambda.event.events
1919

2020
import com.lambda.event.Event
21+
import com.lambda.event.callback.Cancellable
22+
import com.lambda.event.callback.ICancellable
23+
import com.lambda.threading.runSafe
24+
import com.lambda.util.BlockUtils.blockState
2125
import net.minecraft.block.BlockState
26+
import net.minecraft.block.Blocks
2227
import net.minecraft.util.math.BlockPos
2328
import net.minecraft.util.shape.VoxelShape
2429
import net.minecraft.world.chunk.WorldChunk
@@ -41,7 +46,7 @@ sealed class WorldEvent {
4146
* These events can be used to listen for and respond to changes in the state
4247
* of chunks within the game world, providing contextual data for the operations.
4348
*/
44-
sealed class ChunkEvent : Event {
49+
sealed class ChunkEvent {
4550
/**
4651
* Event triggering upon chunk loading
4752
*/
@@ -59,17 +64,36 @@ sealed class WorldEvent {
5964
}
6065

6166
/**
62-
* Represents a block state change event within the world.
67+
* Represents events related to block updates in the world.
6368
*
64-
* @property pos The position of the block within the world where the change occurred.
65-
* @property oldState The block state prior to the change.
66-
* @property newState The block state after the change.
69+
* This sealed class encapsulates different types of block update events,
70+
* distinguishing between client-side state changes and server-side updates.
6771
*/
68-
data class BlockChange(
69-
val pos: BlockPos,
70-
val oldState: BlockState,
71-
val newState: BlockState,
72-
) : Event
72+
sealed class BlockUpdate {
73+
/**
74+
* Represents a client side block state change event within the world.
75+
*
76+
* @property pos The position of the block within the world where the change occurred.
77+
* @property oldState The block state prior to the change.
78+
* @property newState The block state after the change.
79+
*/
80+
data class Client(
81+
val pos: BlockPos,
82+
val oldState: BlockState,
83+
val newState: BlockState,
84+
) : Event
85+
86+
/**
87+
* Represents a server block update event in the world.
88+
*
89+
* @property pos The position of the block in the world.
90+
* @property newState The new state of the block after the update.
91+
*/
92+
data class Server(
93+
val pos: BlockPos,
94+
val newState: BlockState,
95+
) : ICancellable by Cancellable()
96+
}
7397

7498
/**
7599
* Represents a collision event in the game world.

common/src/main/kotlin/com/lambda/graphics/renderer/esp/ChunkedESP.kt

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -53,7 +53,7 @@ class ChunkedESP private constructor(
5353
}
5454

5555
init {
56-
listenConcurrently<WorldEvent.BlockChange> { event ->
56+
listenConcurrently<WorldEvent.BlockUpdate.Client> { event ->
5757
world.getWorldChunk(event.pos).renderer.notifyChunks()
5858
}
5959

common/src/main/kotlin/com/lambda/module/modules/player/PacketMine.kt

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -28,7 +28,6 @@ import com.lambda.graphics.renderer.esp.global.DynamicESP
2828
import com.lambda.interaction.request.rotation.RotationManager
2929
import com.lambda.interaction.request.rotation.RotationManager.onRotate
3030
import com.lambda.interaction.request.rotation.RotationRequest
31-
import com.lambda.interaction.request.rotation.visibilty.VisibilityChecker.collectHitsFor
3231
import com.lambda.interaction.request.rotation.visibilty.lookAtBlock
3332
import com.lambda.module.Module
3433
import com.lambda.module.modules.client.TaskFlowModule
@@ -515,7 +514,7 @@ object PacketMine : Module(
515514
}
516515
}
517516

518-
listen<WorldEvent.BlockChange> {
517+
listen<WorldEvent.BlockUpdate.Client> {
519518
currentMiningBlock.forEach { ctx ->
520519
ctx?.apply {
521520
if (it.pos != pos || !isStateBroken(pos.blockState(world), it.newState)) return@forEach

common/src/main/kotlin/com/lambda/task/tasks/BuildTask.kt

Lines changed: 22 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -50,10 +50,10 @@ import com.lambda.util.Communication.info
5050
import com.lambda.util.Formatting.string
5151
import com.lambda.util.collections.LimitedDecayQueue
5252
import com.lambda.util.extension.Structure
53-
import com.lambda.util.world.toFastVec
53+
import net.minecraft.block.BlockState
5454
import net.minecraft.network.packet.s2c.play.BlockUpdateS2CPacket
55+
import net.minecraft.network.packet.s2c.play.ChunkDeltaUpdateS2CPacket
5556
import net.minecraft.util.math.BlockPos
56-
import java.util.concurrent.ConcurrentLinkedQueue
5757

5858
class BuildTask @Ta5kBuilder constructor(
5959
private val blueprint: Blueprint,
@@ -68,7 +68,7 @@ class BuildTask @Ta5kBuilder constructor(
6868

6969
private val pendingInteractions = LimitedDecayQueue<BuildContext>(
7070
build.maxPendingInteractions, build.interactionTimeout * 50L
71-
) { info("Interaction at ${it.expectedPos.toShortString()} timed out") }
71+
) { info("${it::class.simpleName} at ${it.expectedPos.toShortString()} timed out") }
7272
private var currentInteraction: BuildContext? = null
7373

7474
private var placements = 0
@@ -106,16 +106,18 @@ class BuildTask @Ta5kBuilder constructor(
106106
.plus(pendingInteractions.toList())
107107
// .plus(sim.goodPositions())
108108

109-
val instantResults = results.filterIsInstance<BreakResult.Break>()
110-
.filter { it.context.instantBreak }
111-
.sorted()
112-
.take(build.breaksPerTick)
109+
if (build.breaksPerTick > 1) {
110+
val instantResults = results.filterIsInstance<BreakResult.Break>()
111+
.filter { it.context.instantBreak }
112+
.sorted()
113+
.take(build.breaksPerTick)
113114

114-
if (build.breaksPerTick > 1 && instantResults.isNotEmpty()) {
115115
instantResults.forEach {
116116
it.context.interact(interact.swingHand)
117+
pendingInteractions.add(it.context)
117118
}
118-
return@listen
119+
120+
if (instantResults.isNotEmpty()) return@listen
119121
}
120122

121123
val resultsWithoutPending = results.filterNot { result ->
@@ -186,24 +188,20 @@ class BuildTask @Ta5kBuilder constructor(
186188
}
187189
}
188190

189-
listen<WorldEvent.BlockChange> { event ->
190-
val interaction = currentInteraction ?: return@listen
191-
if (interaction.expectedPos != event.pos) return@listen
191+
listen<WorldEvent.BlockUpdate.Client> { event ->
192+
val context = currentInteraction ?: return@listen
193+
if (context.expectedPos != event.pos) return@listen
192194
currentInteraction = null
193-
pendingInteractions.add(interaction)
195+
pendingInteractions.add(context)
194196
}
195197

196-
listen<PacketEvent.Receive.Pre> { event ->
197-
val packet = event.packet
198-
if (packet !is BlockUpdateS2CPacket) return@listen
199-
200-
pendingInteractions.firstOrNull { it.expectedPos == packet.pos }?.let {
201-
if (it.targetState.matches(packet.state, packet.pos, world)) {
202-
pendingInteractions.remove(it)
203-
when (it) {
204-
is BreakContext -> breaks++
205-
is PlaceContext -> placements++
206-
}
198+
listen<WorldEvent.BlockUpdate.Server> { event ->
199+
pendingInteractions.firstOrNull { it.expectedPos == event.pos }?.let { context ->
200+
if (!context.targetState.matches(event.newState, event.pos, world)) return@let
201+
pendingInteractions.remove(context)
202+
when (context) {
203+
is BreakContext -> breaks++
204+
is PlaceContext -> placements++
207205
}
208206
}
209207
}

0 commit comments

Comments
 (0)