:mind_blown: More multiblock code
This commit is contained in:
parent
f97ad565d4
commit
c356cd703e
@ -0,0 +1,23 @@
|
|||||||
|
package ru.dbotthepony.mc.otm.mixin;
|
||||||
|
|
||||||
|
import net.minecraft.world.level.block.entity.BlockEntity;
|
||||||
|
import org.spongepowered.asm.mixin.Mixin;
|
||||||
|
import org.spongepowered.asm.mixin.injection.At;
|
||||||
|
import org.spongepowered.asm.mixin.injection.Inject;
|
||||||
|
import ru.dbotthepony.mc.otm.core.MultiblockKt;
|
||||||
|
|
||||||
|
// because i know
|
||||||
|
// someone
|
||||||
|
// somewhere
|
||||||
|
// will try to break the system
|
||||||
|
// either on purpose or accidentally because of other mod
|
||||||
|
@Mixin(BlockEntity.class)
|
||||||
|
public abstract class BlockEntityMixin {
|
||||||
|
@Inject(
|
||||||
|
at = @At("TAIL"),
|
||||||
|
method = "setRemoved()V"
|
||||||
|
)
|
||||||
|
public void setRemovedListener() {
|
||||||
|
MultiblockKt.onBlockEntityInvalidated((BlockEntity) (Object) this);
|
||||||
|
}
|
||||||
|
}
|
@ -11,19 +11,29 @@ import net.minecraft.core.BlockPos
|
|||||||
import net.minecraft.core.Direction
|
import net.minecraft.core.Direction
|
||||||
import net.minecraft.core.Vec3i
|
import net.minecraft.core.Vec3i
|
||||||
import net.minecraft.tags.TagKey
|
import net.minecraft.tags.TagKey
|
||||||
|
import net.minecraft.world.level.Level
|
||||||
import net.minecraft.world.level.LevelAccessor
|
import net.minecraft.world.level.LevelAccessor
|
||||||
import net.minecraft.world.level.block.Block
|
import net.minecraft.world.level.block.Block
|
||||||
import net.minecraft.world.level.block.Rotation
|
import net.minecraft.world.level.block.Rotation
|
||||||
import net.minecraft.world.level.block.entity.BlockEntity
|
import net.minecraft.world.level.block.entity.BlockEntity
|
||||||
import net.minecraft.world.level.block.state.BlockState
|
import net.minecraft.world.level.block.state.BlockState
|
||||||
|
import ru.dbotthepony.mc.otm.core.collect.WeakHashSet
|
||||||
import ru.dbotthepony.mc.otm.core.collect.collect
|
import ru.dbotthepony.mc.otm.core.collect.collect
|
||||||
import ru.dbotthepony.mc.otm.core.collect.map
|
import ru.dbotthepony.mc.otm.core.collect.map
|
||||||
import ru.dbotthepony.mc.otm.core.math.RelativeSide
|
import ru.dbotthepony.mc.otm.core.math.RelativeSide
|
||||||
import ru.dbotthepony.mc.otm.core.math.plus
|
import ru.dbotthepony.mc.otm.core.math.plus
|
||||||
import java.util.Collections
|
import java.util.Collections
|
||||||
|
import java.util.WeakHashMap
|
||||||
import java.util.function.Predicate
|
import java.util.function.Predicate
|
||||||
import kotlin.reflect.KClass
|
import kotlin.reflect.KClass
|
||||||
|
|
||||||
|
private val blockEntityListeners = WeakHashMap<Level, WeakHashMap<BlockEntity, WeakHashSet<Multiblock>>>()
|
||||||
|
|
||||||
|
fun onBlockEntityInvalidated(blockEntity: BlockEntity) {
|
||||||
|
blockEntityListeners[blockEntity.level]?.get(blockEntity)?.forEach { it.blockEntityRemoved(blockEntity) }
|
||||||
|
blockEntityListeners[blockEntity.level]?.remove(blockEntity)
|
||||||
|
}
|
||||||
|
|
||||||
fun interface BlockPredicate {
|
fun interface BlockPredicate {
|
||||||
fun test(pos: BlockPos, access: LevelAccessor): Boolean
|
fun test(pos: BlockPos, access: LevelAccessor): Boolean
|
||||||
|
|
||||||
@ -358,14 +368,20 @@ class Multiblock(
|
|||||||
|
|
||||||
private val configurations = ArrayList<Config>()
|
private val configurations = ArrayList<Config>()
|
||||||
|
|
||||||
private class BEList<T : BlockEntity>(val tag: MultiblockBuilder.EntityTag<T>) {
|
private inner class BEList<T : BlockEntity>(val tag: MultiblockBuilder.EntityTag<T>) {
|
||||||
val list = ArrayList<T>()
|
val list = ArrayList<T>()
|
||||||
val set = ObjectArraySet<T>()
|
val set = ObjectArraySet<T>()
|
||||||
val setView: Set<T> = Collections.unmodifiableSet(set)
|
val setView: Set<T> = Collections.unmodifiableSet(set)
|
||||||
|
|
||||||
fun add(blockEntity: BlockEntity) {
|
fun add(blockEntity: BlockEntity) {
|
||||||
if (tag.test(blockEntity)) {
|
if (tag.test(blockEntity)) {
|
||||||
set.add(blockEntity as T)
|
if (set.add(blockEntity as T)) {
|
||||||
|
blockEntityListeners
|
||||||
|
.computeIfAbsent(blockEntity.level) { WeakHashMap() }
|
||||||
|
.computeIfAbsent(blockEntity) { WeakHashSet() }
|
||||||
|
.add(this@Multiblock)
|
||||||
|
}
|
||||||
|
|
||||||
list.add(blockEntity)
|
list.add(blockEntity)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -376,11 +392,42 @@ class Multiblock(
|
|||||||
|
|
||||||
if (blockEntity !in list) {
|
if (blockEntity !in list) {
|
||||||
set.remove(blockEntity)
|
set.remove(blockEntity)
|
||||||
|
|
||||||
|
val getSet = blockEntityListeners[blockEntity.level]?.get(blockEntity)
|
||||||
|
|
||||||
|
if (getSet != null) {
|
||||||
|
getSet.remove(this@Multiblock)
|
||||||
|
|
||||||
|
if (getSet.isEmpty()) {
|
||||||
|
blockEntityListeners[blockEntity.level]?.remove(blockEntity)
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fun blockEntityRemoved(blockEntity: BlockEntity): Boolean {
|
||||||
|
if (blockEntity in list) {
|
||||||
|
while (list.remove(blockEntity)) {}
|
||||||
|
set.remove(blockEntity)
|
||||||
|
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
|
||||||
fun clear() {
|
fun clear() {
|
||||||
|
set.forEach {
|
||||||
|
val getSet = checkNotNull(blockEntityListeners[it.level]) { "Consistency check failed: No subscriber lists for level ${it.level}" }.get(it)
|
||||||
|
checkNotNull(getSet) { "Consistency check failed: No subscriber list for $it" }
|
||||||
|
check(getSet.remove(this@Multiblock)) { "Consistency check failed: Can't remove ${this@Multiblock} from $it subscriber list" }
|
||||||
|
|
||||||
|
if (getSet.isEmpty()) {
|
||||||
|
blockEntityListeners[it.level]?.remove(it)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
list.clear()
|
list.clear()
|
||||||
set.clear()
|
set.clear()
|
||||||
}
|
}
|
||||||
@ -471,12 +518,12 @@ class Multiblock(
|
|||||||
if (old != null) {
|
if (old != null) {
|
||||||
assignedBlockStateLists.forEach {
|
assignedBlockStateLists.forEach {
|
||||||
it[old] = it.getInt(old) - 1
|
it[old] = it.getInt(old) - 1
|
||||||
check(it.getInt(old) >= 0) { "Counter for block state $old turned negative" }
|
check(it.getInt(old) >= 0) { "Consistency check failed: Counter for block state $old turned negative" }
|
||||||
}
|
}
|
||||||
|
|
||||||
assignedBlockLists.forEach {
|
assignedBlockLists.forEach {
|
||||||
it[old.block] = it.getInt(old.block) - 1
|
it[old.block] = it.getInt(old.block) - 1
|
||||||
check(it.getInt(old.block) >= 0) { "Counter for block ${old.block.registryName} turned negative" }
|
check(it.getInt(old.block) >= 0) { "Consistency check failed: Counter for block ${old.block.registryName} turned negative" }
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -510,12 +557,12 @@ class Multiblock(
|
|||||||
if (blockState != null) {
|
if (blockState != null) {
|
||||||
assignedBlockStateLists.forEach {
|
assignedBlockStateLists.forEach {
|
||||||
it[blockState] = it.getInt(blockState) - 1
|
it[blockState] = it.getInt(blockState) - 1
|
||||||
check(it.getInt(blockState) >= 0) { "Counter for block state $blockState turned negative" }
|
check(it.getInt(blockState) >= 0) { "Consistency check failed: Counter for block state $blockState turned negative" }
|
||||||
}
|
}
|
||||||
|
|
||||||
assignedBlockLists.forEach {
|
assignedBlockLists.forEach {
|
||||||
it[blockState.block] = it.getInt(blockState.block) - 1
|
it[blockState.block] = it.getInt(blockState.block) - 1
|
||||||
check(it.getInt(blockState.block) >= 0) { "Counter for block ${blockState.block.registryName} turned negative" }
|
check(it.getInt(blockState.block) >= 0) { "Consistency check failed: Counter for block ${blockState.block.registryName} turned negative" }
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -575,6 +622,16 @@ class Multiblock(
|
|||||||
fun <T : BlockEntity> blockEntities(tag: MultiblockBuilder.EntityTag<T>): Set<T> {
|
fun <T : BlockEntity> blockEntities(tag: MultiblockBuilder.EntityTag<T>): Set<T> {
|
||||||
return (tag2BlockEntity[tag]?.setView ?: setOf()) as Set<T>
|
return (tag2BlockEntity[tag]?.setView ?: setOf()) as Set<T>
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fun blockEntityRemoved(blockEntity: BlockEntity): Boolean {
|
||||||
|
var any = false
|
||||||
|
|
||||||
|
blockEntityLists.forEach {
|
||||||
|
any = it.blockEntityRemoved(blockEntity) || any
|
||||||
|
}
|
||||||
|
|
||||||
|
return any
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private val north = Config(pos, north).also { configurations.add(it) }
|
private val north = Config(pos, north).also { configurations.add(it) }
|
||||||
@ -585,9 +642,14 @@ class Multiblock(
|
|||||||
private var activeConfig: Config? = null
|
private var activeConfig: Config? = null
|
||||||
|
|
||||||
fun <T : BlockEntity> blockEntities(tag: MultiblockBuilder.EntityTag<T>): Set<T> {
|
fun <T : BlockEntity> blockEntities(tag: MultiblockBuilder.EntityTag<T>): Set<T> {
|
||||||
|
if (!isValid) return emptySet()
|
||||||
return activeConfig?.blockEntities(tag) ?: setOf()
|
return activeConfig?.blockEntities(tag) ?: setOf()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fun blockEntityRemoved(blockEntity: BlockEntity) {
|
||||||
|
activeConfig?.blockEntityRemoved(blockEntity)
|
||||||
|
}
|
||||||
|
|
||||||
fun update(levelAccessor: LevelAccessor): Boolean {
|
fun update(levelAccessor: LevelAccessor): Boolean {
|
||||||
val activeConfig = activeConfig
|
val activeConfig = activeConfig
|
||||||
|
|
||||||
|
@ -6,6 +6,7 @@
|
|||||||
"minVersion": "0.8",
|
"minVersion": "0.8",
|
||||||
"refmap": "overdrive_that_matters.refmap.json",
|
"refmap": "overdrive_that_matters.refmap.json",
|
||||||
"mixins": [
|
"mixins": [
|
||||||
|
"BlockEntityMixin",
|
||||||
"EnchantmentHelperMixin",
|
"EnchantmentHelperMixin",
|
||||||
"FoodDataMixin",
|
"FoodDataMixin",
|
||||||
"MixinPatchProjectileFinder",
|
"MixinPatchProjectileFinder",
|
||||||
|
Loading…
Reference in New Issue
Block a user