Skip to content

Commit

Permalink
fix: piston block entity special behavior (#27)
Browse files Browse the repository at this point in the history
Most block entity will try to create one if there are none. for maybe some reason to save storage usage.

Due to Mojang's strange logic, pistons does not--they returns null instead of create a piston block entity.

This fix uses reflection to create a block entity--this may not suitable for all types of blocks and maybe not performative enough but it should works.

Mojang-ma=ojng

Note: The block entities will tick itself--so even if we dont add a BE ot scheduled tick, after redo, the pistons will still keep working instead of stopping. We think this works as intended due to mojang's bull-shit game mechanics.

close: #27
  • Loading branch information
zly2006 committed Sep 3, 2023
1 parent daea617 commit d9cd7b5
Show file tree
Hide file tree
Showing 3 changed files with 25 additions and 1 deletion.
10 changes: 10 additions & 0 deletions src/main/java/com/github/zly2006/reden/access/PlayerData.kt
Original file line number Diff line number Diff line change
Expand Up @@ -2,8 +2,11 @@ package com.github.zly2006.reden.access

import com.github.zly2006.reden.carpet.RedenCarpetSettings
import com.github.zly2006.reden.malilib.UNDO_CHEATING_ONLY
import com.github.zly2006.reden.utils.debugLogger
import com.github.zly2006.reden.utils.isClient
import com.github.zly2006.reden.utils.isSinglePlayerAndCheating
import net.minecraft.block.Blocks
import net.minecraft.block.entity.BlockEntity
import net.minecraft.command.EntitySelector
import net.minecraft.entity.EntityType
import net.minecraft.entity.TntEntity
Expand Down Expand Up @@ -32,6 +35,7 @@ class PlayerData(

data class Entry(
val blockState: NbtCompound,
val blockEntityClazz: Class<BlockEntity>?,
val blockEntity: NbtCompound?,
) {

Expand All @@ -55,10 +59,16 @@ class PlayerData(
val data: MutableMap<Long, Entry> = mutableMapOf()
) {
fun fromWorld(world: World, pos: BlockPos): Entry {
val be = world.getBlockEntity(pos)
return Entry(
NbtHelper.fromBlockState(world.getBlockState(pos)),
be?.javaClass,
world.getBlockEntity(pos)?.createNbt()
).apply {
if (world.getBlockState(pos).isOf(Blocks.MOVING_PISTON) &&
blockEntity == null) {
debugLogger("OHHHHHHHHH")
}
if (world.getBlockState(pos).getCollisionShape(world, pos).boundingBoxes.size != 0) {
val list = world.getEntitiesByType(
EntitySelector.PASSTHROUGH_FILTER,
Expand Down
15 changes: 14 additions & 1 deletion src/main/java/com/github/zly2006/reden/network/Rollback.kt
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@ import net.fabricmc.fabric.api.networking.v1.FabricPacket
import net.fabricmc.fabric.api.networking.v1.PacketType
import net.fabricmc.fabric.api.networking.v1.ServerPlayNetworking
import net.minecraft.block.Block
import net.minecraft.block.BlockState
import net.minecraft.entity.SpawnReason
import net.minecraft.nbt.NbtHelper
import net.minecraft.network.PacketByteBuf
Expand Down Expand Up @@ -49,7 +50,18 @@ class Rollback(
fluidTickScheduler.removeTicksIf { it.pos == pos }
// apply block entity
entry.blockEntity?.let { be ->
world.getBlockEntity(BlockPos.fromLong(posLong))?.readNbt(be)
var blockEntity = world.getBlockEntity(BlockPos.fromLong(posLong))
if (blockEntity == null) {
try {
// force add block entities, got blocks like piston.
blockEntity = entry.blockEntityClazz!!
.getConstructor(BlockPos::class.java, BlockState::class.java)
.newInstance(pos, state).also(world::addBlockEntity)
} catch (e: Exception) {
Reden.LOGGER.error("Failed to create block entity for $pos, $state", e)
}
}
blockEntity?.readNbt(be)
}
}
record.entities.forEach {
Expand All @@ -74,6 +86,7 @@ class Rollback(
if (last.data.isNotEmpty() || last.entities.isNotEmpty()) {
return last
}
// if the last record is empty, remove it
UpdateMonitorHelper.removeRecord(last.id)
this.removeLast()
}
Expand Down
1 change: 1 addition & 0 deletions src/main/resources/reden.accesswidener
Original file line number Diff line number Diff line change
Expand Up @@ -39,3 +39,4 @@ accessible field net/minecraft/world/tick/ChunkTickScheduler queuedTicks Ljava/u
accessible field net/minecraft/block/entity/PistonBlockEntity progress F
accessible field net/minecraft/block/entity/PistonBlockEntity lastProgress F
accessible method net/minecraft/client/network/ClientPlayerInteractionManager sendSequencedPacket (Lnet/minecraft/client/world/ClientWorld;Lnet/minecraft/client/network/SequencedPacketCreator;)V
accessible field net/minecraft/world/tick/ChunkTickScheduler tickQueue Ljava/util/Queue;

0 comments on commit d9cd7b5

Please sign in to comment.