Skip to content

Commit

Permalink
Debug option for invalid chunk data
Browse files Browse the repository at this point in the history
  • Loading branch information
2No2Name committed Feb 2, 2025
1 parent 016512f commit 385ae87
Show file tree
Hide file tree
Showing 8 changed files with 120 additions and 2 deletions.
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
@MixinConfigOption(description = "Debug features", enabled = false)
package net.caffeinemc.mods.lithium.mixin.debug;

import net.caffeinemc.gradle.MixinConfigOption;
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
package net.caffeinemc.mods.lithium.mixin.debug.palette;

import net.minecraft.network.protocol.game.ClientboundLevelChunkPacketData;
import org.spongepowered.asm.mixin.Mixin;
import org.spongepowered.asm.mixin.gen.Accessor;

@Mixin(ClientboundLevelChunkPacketData.class)
public interface ClientBoundLevelChunkPacketDataAccessor {

@Accessor("buffer")
byte[] getBuffer();

}
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
package net.caffeinemc.mods.lithium.mixin.debug.palette;

import com.llamalad7.mixinextras.injector.wrapmethod.WrapMethod;
import com.llamalad7.mixinextras.injector.wrapoperation.Operation;
import net.minecraft.client.multiplayer.ClientPacketListener;
import net.minecraft.network.protocol.game.ClientboundLevelChunkPacketData;
import org.spongepowered.asm.mixin.Mixin;

import java.util.Arrays;

@Mixin(ClientPacketListener.class)
public class ClientPacketListenerMixin {

@WrapMethod(
method = "updateLevelChunk(IILnet/minecraft/network/protocol/game/ClientboundLevelChunkPacketData;)V"
)
private void addExceptionInfo(int i, int j, ClientboundLevelChunkPacketData clientboundLevelChunkPacketData, Operation<Void> original) {
try {
original.call(i, j, clientboundLevelChunkPacketData);
} catch (IllegalStateException e) {
String message = "Exception occurred while receiving data for chunk at " + i + ", " + j + ".\n" +
"**The following may include sensitive data, e.g. text that is written with blocks or built \n" +
"structures. Make sure the chunk with chunk coordinates " + i + ", " + j + " does not contain block\n" +
"or biome structures (e.g. your non-pseudonym name written with blocks) that you do not want\n" +
"published. This does not include block entities or items.**\n" +
"Possible sensitive chunk biome and blockstate data: " + Arrays.toString(((ClientBoundLevelChunkPacketDataAccessor) clientboundLevelChunkPacketData).getBuffer());
throw new IllegalStateException(message, e);
}
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,44 @@
package net.caffeinemc.mods.lithium.mixin.debug.palette;

import net.minecraft.network.FriendlyByteBuf;
import net.minecraft.util.BitStorage;
import net.minecraft.world.level.chunk.MissingPaletteEntryException;
import net.minecraft.world.level.chunk.Palette;
import net.minecraft.world.level.chunk.PalettedContainer;
import org.spongepowered.asm.mixin.Mixin;
import org.spongepowered.asm.mixin.Shadow;
import org.spongepowered.asm.mixin.injection.At;
import org.spongepowered.asm.mixin.injection.Inject;
import org.spongepowered.asm.mixin.injection.callback.CallbackInfo;

@Mixin(PalettedContainer.class)
public class PalettedContainerMixin<T> {

@Shadow
private volatile PalettedContainer.Data<T> data;

@Inject(
method = "read", at = @At("RETURN")
)
private void checkConsistency(FriendlyByteBuf friendlyByteBuf, CallbackInfo ci) {
BitStorage storage = this.data.storage();
Palette<T> palette = this.data.palette();
int i = -1;
int index = -1;
try {
for (i = 0; i < storage.getSize(); i++) {
index = storage.get(i);
T t = palette.valueFor(index);
//noinspection ConstantValue
if (t == null) {
throw new MissingPaletteEntryException(index);
}
}
} catch (Exception e) {
String builder = "Received invalid paletted container data!\n" +
"Entry at index " + i + " has palette index " + index + ".\n" +
"Palette: " + palette + " Size: " + palette.getSize() + "\n";
throw new IllegalStateException(builder, e);
}
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
@MixinConfigOption(description = "Clients check the chunk section data when receiving a chunk data packet.")
package net.caffeinemc.mods.lithium.mixin.debug.palette;

import net.caffeinemc.gradle.MixinConfigOption;
3 changes: 3 additions & 0 deletions common/src/main/resources/lithium.mixins.json
Original file line number Diff line number Diff line change
Expand Up @@ -242,6 +242,9 @@
],
"client" : [
"chunk.entity_class_groups.ClientLevelMixin",
"debug.palette.ClientBoundLevelChunkPacketDataAccessor",
"debug.palette.ClientPacketListenerMixin",
"debug.palette.PalettedContainerMixin",
"util.accessors.TransientEntitySectionManagerAccessor"
]
}
12 changes: 11 additions & 1 deletion lithium-fabric-mixin-config.md
Original file line number Diff line number Diff line change
Expand Up @@ -267,6 +267,14 @@ Send updates to hoppers when adding inventory block entities to chunks when worl
Requirements:
- `mixin.util.block_entity_retrieval=true`

### `mixin.debug`
(default: `false`)
Debug features

### `mixin.debug.palette`
(default: `true`)
Clients check the chunk section data when receiving a chunk data packet.

### `mixin.entity`
(default: `true`)
Various entity optimizations
Expand Down Expand Up @@ -505,7 +513,9 @@ Access chunks of worlds, chunk caches and chunk regions directly.

### `mixin.util.chunk_status_tracking`
(default: `true`)
Allows reacting to changes of the load status of chunks.
Allows reacting to changes of the load status of chunks.
Requirements:
- `mixin.util.accessors=true`

### `mixin.util.data_storage`
(default: `true`)
Expand Down
12 changes: 11 additions & 1 deletion lithium-neoforge-mixin-config.md
Original file line number Diff line number Diff line change
Expand Up @@ -253,6 +253,14 @@ Uses fastutil hashmaps for gamerules
(default: `true`)
Uses custom hashset/list combination for faster mob spawn checks

### `mixin.debug`
(default: `false`)
Debug features

### `mixin.debug.palette`
(default: `true`)
Clients check the chunk section data when receiving a chunk data packet.

### `mixin.entity`
(default: `true`)
Various entity optimizations
Expand Down Expand Up @@ -482,7 +490,9 @@ Access chunks of worlds, chunk caches and chunk regions directly.

### `mixin.util.chunk_status_tracking`
(default: `true`)
Allows reacting to changes of the load status of chunks.
Allows reacting to changes of the load status of chunks.
Requirements:
- `mixin.util.accessors=true`

### `mixin.util.data_storage`
(default: `true`)
Expand Down

0 comments on commit 385ae87

Please sign in to comment.