Skip to content

Commit

Permalink
feat: tracking structure
Browse files Browse the repository at this point in the history
  • Loading branch information
zly2006 committed Jul 30, 2023
1 parent 336ce41 commit eceb4f6
Show file tree
Hide file tree
Showing 5 changed files with 98 additions and 16 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -42,6 +42,7 @@ private fun <T : IConfigBase?> ConfigBase<T>.debug() = this.apply(DEBUG_TAB::add
@JvmField val DEBUG_TAG_BLOCK_POS = ConfigHotkey("debugTagBlockPos", "LEFT_CONTROL,LEFT_SHIFT,T", "Tag block position").debug().hotkey()
@JvmField val DEBUG_PREVIEW_UNDO = ConfigHotkey("debugPreviewUndo", "LEFT_CONTROL,LEFT_SHIFT,Z", "Preview undo").debug().hotkey()
@JvmField val MAX_CHAIN_UPDATES = ConfigInteger("maxChainUpdates", -1, "Max chain updates, affects after reopening").debug()
@JvmField val DO_ASSERTION_CHECKS = ConfigBoolean("doAssertionChecks", false, "").debug()

fun debug() = DEBUG_LOGGER.booleanValue

Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
package com.github.zly2006.reden.rvc.nbt;

import net.minecraft.nbt.NbtCompound;

public interface DiffProvider {
NbtDiff get(NbtCompound before, NbtCompound after);
}
14 changes: 14 additions & 0 deletions src/main/java/com/github/zly2006/reden/rvc/nbt/DirectDiff.kt
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
package com.github.zly2006.reden.rvc.nbt

import net.minecraft.nbt.NbtCompound
import java.util.function.Supplier

class DirectDiff(
private val after: NbtCompound
): NbtDiff {
override fun apply(nbt: Supplier<NbtCompound>): NbtCompound {
return after.copy()
}

override fun combine(parent: NbtDiff) = this
}
5 changes: 3 additions & 2 deletions src/main/java/com/github/zly2006/reden/rvc/nbt/NbtDiff.kt
Original file line number Diff line number Diff line change
@@ -1,8 +1,9 @@
package com.github.zly2006.reden.rvc.nbt

import net.minecraft.nbt.NbtCompound
import java.util.function.Supplier

interface NbtDiff {
fun apply(nbt: NbtCompound): NbtCompound
fun combine(another: NbtDiff)
fun apply(nbt: Supplier<NbtCompound>): NbtCompound
fun combine(parent: NbtDiff): NbtDiff
}
87 changes: 73 additions & 14 deletions src/main/java/com/github/zly2006/reden/rvc/tracking/TrackedDiff.kt
Original file line number Diff line number Diff line change
@@ -1,10 +1,19 @@
package com.github.zly2006.reden.rvc.tracking

import com.github.zly2006.reden.malilib.DO_ASSERTION_CHECKS
import com.github.zly2006.reden.rvc.Person
import com.github.zly2006.reden.rvc.nbt.DiffProvider
import com.github.zly2006.reden.rvc.nbt.DirectDiff
import com.github.zly2006.reden.rvc.nbt.NbtDiff
import net.minecraft.block.BlockState
import net.minecraft.nbt.NbtCompound
import net.minecraft.util.math.BlockPos
import java.util.*
import java.util.function.Supplier

val diffProvider = DiffProvider { _, b ->
DirectDiff(b)
}

class TrackedDiff(
val parentIds: LongArray,
Expand All @@ -18,18 +27,22 @@ class TrackedDiff(
/**
* should ensure that all keys are positive coordinates
*/
val changedBlocks: Map<BlockPos, BlockState> = mutableMapOf(),
val changedBlocks: Map<BlockPos, BlockState> = emptyMap(),
/**
* should ensure that all keys are positive coordinates
*/
val changedBlockEntities: Map<BlockPos, NbtDiff> = mutableMapOf(),
val removedBlockPoses: Set<BlockPos> = mutableSetOf(),
val entities: Map<UUID, NbtDiff> = mutableMapOf(),
val changedBlockEntities: Map<BlockPos, NbtDiff> = emptyMap(),
val removedBlockPoses: Set<BlockPos> = emptySet(),
val entities: Map<UUID, NbtDiff> = emptyMap(),
val timestamp: Long,
val author: Person
) {
var id: Long = 0; private set

fun getOrigin(storage: TrackedDiffStorage): BlockPos =
if (parentIds.isEmpty()) BlockPos.ORIGIN
else storage[parentIds[0]].getOrigin(storage).add(originDiff[0])

fun getTrackingPoses(storage: TrackedDiffStorage): Set<BlockPos> =
parentIds.map(storage::get).map { it.getTrackingPoses(storage) }.flatten().toMutableSet().apply {
addAll(changedBlocks.keys)
Expand All @@ -40,31 +53,77 @@ class TrackedDiff(
return when (parentIds.size) {
0 -> changedBlocks[pos]
1 -> changedBlocks[pos] ?: storage[parentIds[0]].getBlockState(storage, pos.subtract(originDiff[0]))
else -> {

}
else -> if (removedBlockPoses.contains(pos)) null
else (changedBlocks[pos]) ?:
parentIds.map(storage::get)
.mapIndexed { index, it -> it.getBlockState(storage, pos.subtract(originDiff[index])) }
.filterNotNull()
.apply {
if (size > 1 && DO_ASSERTION_CHECKS.booleanValue) {
throw IllegalStateException("Found $size matching blocks. This diff may be broken")
}
}.firstOrNull()
}
}

companion object {
fun create(storage: TrackedDiffStorage, before: TrackedDiff, after: TrackingStructure, author: Person) {
val originDiff = after.origin.toImmutable().subtract(before.originDiff[0])
val trackingPoses = before.getTrackingPoses(storage).toMutableSet()
fun getPosBefore(pos: BlockPos) = pos.subtract(originDiff)
fun getPosAfter(pos: BlockPos) = pos.add(originDiff)
fun create(storage: TrackedDiffStorage, before: TrackedDiff, after: TrackingStructure, author: Person): TrackedDiff {
val beforeOrigin = before.getOrigin(storage)
val originDiff = after.origin.toImmutable().subtract(beforeOrigin)
val changedBlocks = mutableMapOf<BlockPos, BlockState>()
val changedBlockEntities = mutableMapOf<BlockPos, NbtDiff>()

val ret = TrackedDiff(
parentIds = longArrayOf(before.id),
originDiff = arrayOf(originDiff),
author = author,
changedBlocks = changedBlocks,
changedBlockEntities = changedBlockEntities,
xSize = after.xSize,
ySize = after.ySize,
zSize = after.zSize,
timestamp = System.currentTimeMillis(),
removedBlockPoses = before.getTrackingPoses(storage) - after.trackingPositions.map { it.subtract(after.origin) }.toSet(),
removedBlockPoses = before.getTrackingPoses(storage).map(originDiff::add).toSet() - after.trackingPositions.map { it.subtract(after.origin) }.toSet(),
)

after.trackingPositions.filter { after.world.getBlockState(it) != before.getblockState(it.subtract(after.origin)) }
for (it in after.trackingPositions) {
val beforeState = before.getBlockState(storage, it.subtract(beforeOrigin))
val afterState = after.world.getBlockState(it)
if (beforeState != afterState) {
changedBlocks[it.subtract(after.origin)] = after.world.getBlockState(it)
}
val beforeData = before.getBlockEntityData(storage, it.subtract(beforeOrigin))
val afterData = after.world.getBlockEntity(it)?.createNbtWithId()
if (beforeData != afterData) {
changedBlockEntities[it.subtract(after.origin)] = diffProvider[beforeData, afterData]
}
}

return ret
}
}
object DummyDiff: NbtDiff {
override fun apply(nbt: Supplier<NbtCompound>): NbtCompound = nbt.get()
override fun combine(parent: NbtDiff): NbtDiff = parent
}
private fun getBlockEntityData(storage: TrackedDiffStorage, pos: BlockPos): NbtCompound? {
fun applyDiff(diff: NbtDiff, supplier: Supplier<NbtCompound?>): NbtCompound? {
return try {
@Suppress("UNCHECKED_CAST")
diff.apply(supplier as Supplier<NbtCompound>)
} catch (_: NullPointerException) { null }
}
return when (parentIds.size) {
0 -> null
1 -> applyDiff(changedBlockEntities[pos] ?: DummyDiff){
storage[parentIds[0]].getBlockEntityData(storage, pos.subtract(originDiff[0]))
}
else -> applyDiff(changedBlockEntities[pos] ?: DummyDiff) {
parentIds.map(storage::get)
.mapIndexed { index, it -> it.getBlockEntityData(storage, pos.subtract(originDiff[index])) }
.filterNotNull()
.firstOrNull()
}
}
}
}

0 comments on commit eceb4f6

Please sign in to comment.