This is generated by calude As it's only change the display, no tests and review are required
2740 lines
149 KiB
Diff
2740 lines
149 KiB
Diff
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
|
|
From: MrHua269 <mrhua269@gmail.com>
|
|
Date: Thu, 9 Jul 2026 12:00:19 +0800
|
|
Subject: [PATCH] Leaves Lithium Sleeping Block Entity
|
|
|
|
As a part of leaves
|
|
|
|
Origin patch link: https://github.com/LeavesMC/Leaves/blob/master/leaves-server/minecraft-patches/features/0136-Lithium-Sleeping-Block-Entity.patch
|
|
Origin license: https://github.com/LeavesMC/Leaves/blob/master/LICENSE.md
|
|
|
|
diff --git a/io/papermc/paper/threadedregions/RegionizedWorldData.java b/io/papermc/paper/threadedregions/RegionizedWorldData.java
|
|
index fe17157c4c6fc9ec745c5c11f6837e715d7949ab..be3bdce1b42a32f57d9ec71d8f115ea1ceac9d52 100644
|
|
--- a/io/papermc/paper/threadedregions/RegionizedWorldData.java
|
|
+++ b/io/papermc/paper/threadedregions/RegionizedWorldData.java
|
|
@@ -65,6 +65,10 @@ import java.util.Set;
|
|
import java.util.concurrent.CopyOnWriteArrayList;
|
|
import java.util.function.Consumer;
|
|
import java.util.function.Predicate;
|
|
+// Camellia start - imports for lithium sleeping block entity
|
|
+import org.leavesmc.leaves.lithium.common.tracking.entity.ChunkSectionInventoryEntityTracker;
|
|
+import org.leavesmc.leaves.lithium.common.tracking.entity.ChunkSectionItemEntityMovementTracker;
|
|
+// Camellia end
|
|
|
|
public final class RegionizedWorldData {
|
|
|
|
@@ -75,6 +79,32 @@ public final class RegionizedWorldData {
|
|
public static final RegionizedData.RegioniserCallback<RegionizedWorldData> REGION_CALLBACK = new RegionizedData.RegioniserCallback<>() {
|
|
@Override
|
|
public void merge(final RegionizedWorldData from, final RegionizedWorldData into, final long fromTickOffset) {
|
|
+ // Camellia start - Region threading for lithium sleeping block entity
|
|
+ // lithium listeners
|
|
+ final long fromRedstoneTimeOffsetForLithiumTracker = into.redstoneTime - from.redstoneTime;
|
|
+ for (var entry : from.containerEntityMovementTrackerMap.entrySet()) {
|
|
+ var key = entry.getKey();
|
|
+ var tracker = entry.getValue();
|
|
+
|
|
+ if (!tracker.hasUser()) {
|
|
+ continue;
|
|
+ }
|
|
+
|
|
+ tracker.updateTicks(fromTickOffset, fromRedstoneTimeOffsetForLithiumTracker);
|
|
+ into.containerEntityMovementTrackerMap.put(key, tracker);
|
|
+ }
|
|
+ for (var entry : from.itemEntityMovementTrackerMap.entrySet()) {
|
|
+ var key = entry.getKey();
|
|
+ var tracker = entry.getValue();
|
|
+
|
|
+ if (!tracker.hasUser()) {
|
|
+ continue;
|
|
+ }
|
|
+
|
|
+ tracker.updateTicks(fromTickOffset, fromRedstoneTimeOffsetForLithiumTracker);
|
|
+ into.itemEntityMovementTrackerMap.put(key, tracker);
|
|
+ }
|
|
+ // Camellia end
|
|
// connections
|
|
for (final Connection conn : from.connections) {
|
|
into.connections.add(conn);
|
|
@@ -114,16 +144,22 @@ public final class RegionizedWorldData {
|
|
from.fluidLevelTicks.merge(into.fluidLevelTicks, fromRedstoneTimeOffset);
|
|
|
|
// tile entity ticking
|
|
- for (final TickingBlockEntity tileEntityWrapped : from.pendingBlockEntityTickers) {
|
|
+ for (TickingBlockEntity tileEntityWrapped : from.pendingBlockEntityTickers) { // Camellia - Region threading for lithium sleeping block entity
|
|
into.pendingBlockEntityTickers.add(tileEntityWrapped);
|
|
- final BlockEntity tileEntity = tileEntityWrapped.getTileEntity();
|
|
+ BlockEntity tileEntity = tileEntityWrapped.getTileEntity(); // Camellia - Region threading for lithium sleeping block entity
|
|
+ // Camellia start - Region threading for lithium sleeping block entity
|
|
+ tileEntityWrapped.updateTicksForLithium(fromRedstoneTimeOffset);
|
|
+ // Camellia end - Region threading for lithium sleeping block entity
|
|
if (tileEntity != null) {
|
|
tileEntity.updateTicks(fromTickOffset, fromRedstoneTimeOffset);
|
|
}
|
|
}
|
|
- for (final TickingBlockEntity tileEntityWrapped : from.blockEntityTickers) {
|
|
+ for (TickingBlockEntity tileEntityWrapped : from.blockEntityTickers) { // Camellia - Region threading for lithium sleeping block entity
|
|
into.blockEntityTickers.add(tileEntityWrapped);
|
|
- final BlockEntity tileEntity = tileEntityWrapped.getTileEntity();
|
|
+ BlockEntity tileEntity = tileEntityWrapped.getTileEntity(); // Camellia - Region threading for lithium sleeping block entity
|
|
+ // Camellia start - Region threading for lithium sleeping block entity
|
|
+ tileEntityWrapped.updateTicksForLithium(fromRedstoneTimeOffset);
|
|
+ // Camellia end - Region threading for lithium sleeping block entity
|
|
if (tileEntity != null) {
|
|
tileEntity.updateTicks(fromTickOffset, fromRedstoneTimeOffset);
|
|
}
|
|
@@ -167,6 +203,37 @@ public final class RegionizedWorldData {
|
|
public void split(final RegionizedWorldData from, final int chunkToRegionShift,
|
|
final Long2ReferenceOpenHashMap<RegionizedWorldData> regionToData,
|
|
final ReferenceOpenHashSet<RegionizedWorldData> dataSet) {
|
|
+ // Camellia start - Region threading for lithium sleeping block entity
|
|
+ // lithium entity movement listeners
|
|
+ for (var entry : from.containerEntityMovementTrackerMap.entrySet()) {
|
|
+ final long key = entry.getKey();
|
|
+ var tracker = entry.getValue();
|
|
+
|
|
+ var sectionPos = net.minecraft.core.SectionPos.of(key);
|
|
+ var pos = sectionPos.chunk();
|
|
+
|
|
+ // skip no user listeners
|
|
+ if (!tracker.hasUser()) {
|
|
+ continue;
|
|
+ }
|
|
+
|
|
+ regionToData.get(CoordinateUtils.getChunkKey(pos.x() >> chunkToRegionShift, pos.z() >> chunkToRegionShift)).containerEntityMovementTrackerMap.put(key, tracker);
|
|
+ }
|
|
+ for (var entry : from.itemEntityMovementTrackerMap.entrySet()) {
|
|
+ final long key = entry.getKey();
|
|
+ var tracker = entry.getValue();
|
|
+
|
|
+ var sectionPos = net.minecraft.core.SectionPos.of(key);
|
|
+ var pos = sectionPos.chunk();
|
|
+
|
|
+ // skip no user listeners
|
|
+ if (!tracker.hasUser()) {
|
|
+ continue;
|
|
+ }
|
|
+
|
|
+ regionToData.get(CoordinateUtils.getChunkKey(pos.x() >> chunkToRegionShift, pos.z() >> chunkToRegionShift)).itemEntityMovementTrackerMap.put(key, tracker);
|
|
+ }
|
|
+ // Camellia end
|
|
// connections
|
|
for (final Connection conn : from.connections) {
|
|
final ServerPlayer player = conn.getPlayer();
|
|
@@ -243,8 +310,9 @@ public final class RegionizedWorldData {
|
|
from.fluidLevelTicks.split(chunkToRegionShift, levelTicksFluidRegionData);
|
|
|
|
// tile entity ticking
|
|
- for (final TickingBlockEntity tileEntity : from.pendingBlockEntityTickers) {
|
|
- final BlockPos pos = tileEntity.getPos();
|
|
+ for (final TickingBlockEntity tileEntity : from.pendingBlockEntityTickers) { // Camellia - Region threading for lithium sleeping block entity
|
|
+ BlockPos pos = tileEntity.getPos(); // Camellia - Region threading for lithium sleeping block entity
|
|
+ if (pos == null) pos = tileEntity.getTileEntity().getBlockPos(); // Camellia - Region threading for lithium sleeping block entity
|
|
final int chunkX = pos.getX() >> 4;
|
|
final int chunkZ = pos.getZ() >> 4;
|
|
|
|
@@ -254,8 +322,9 @@ public final class RegionizedWorldData {
|
|
} // else: when a chunk unloads, it does not actually _remove_ the tile entity from the list, it just gets
|
|
// marked as removed. So if there is no section, it's probably removed!
|
|
}
|
|
- for (final TickingBlockEntity tileEntity : from.blockEntityTickers) {
|
|
- final BlockPos pos = tileEntity.getPos();
|
|
+ for (final TickingBlockEntity tileEntity : from.blockEntityTickers) { // Camellia - Region threading for lithium sleeping block entity
|
|
+ BlockPos pos = tileEntity.getPos(); // Camellia - Region threading for lithium sleeping block entity
|
|
+ if (pos == null) pos = tileEntity.getTileEntity().getBlockPos(); // Camellia - Region threading for lithium sleeping block entity
|
|
final int chunkX = pos.getX() >> 4;
|
|
final int chunkZ = pos.getZ() >> 4;
|
|
|
|
@@ -483,6 +552,11 @@ public final class RegionizedWorldData {
|
|
public final io.papermc.paper.redstone.RedstoneWireTurbo turbo;
|
|
// Environment attribute system
|
|
public Reference2ObjectOpenHashMap<EnvironmentAttribute<?>, EnvironmentAttributeSystem.ValueSampler<?>> attributeSamplers;
|
|
+ // Camellia start - Region threading for lithium sleeping block entity
|
|
+ // Lithium
|
|
+ public final Map<Long, ChunkSectionInventoryEntityTracker> containerEntityMovementTrackerMap = new it.unimi.dsi.fastutil.objects.Object2ObjectLinkedOpenHashMap<>();
|
|
+ public final Map<Long, ChunkSectionItemEntityMovementTracker> itemEntityMovementTrackerMap = new it.unimi.dsi.fastutil.objects.Object2ObjectLinkedOpenHashMap<>();
|
|
+ // Camellia end
|
|
|
|
public final TickRegions.TickRegionData regionData;
|
|
|
|
diff --git a/net/minecraft/core/NonNullList.java b/net/minecraft/core/NonNullList.java
|
|
index 8fd27a342f7302284c48b3db7d085bb692e08cdc..8992e13df499333235e1a51b725c0ad3ccd0284d 100644
|
|
--- a/net/minecraft/core/NonNullList.java
|
|
+++ b/net/minecraft/core/NonNullList.java
|
|
@@ -8,7 +8,7 @@ import java.util.Objects;
|
|
import org.jspecify.annotations.Nullable;
|
|
|
|
public class NonNullList<E> extends AbstractList<E> {
|
|
- private final List<E> list;
|
|
+ public final List<E> list; // Leaves - private -> public
|
|
private final @Nullable E defaultValue;
|
|
|
|
public static <E> NonNullList<E> create() {
|
|
diff --git a/net/minecraft/core/component/PatchedDataComponentMap.java b/net/minecraft/core/component/PatchedDataComponentMap.java
|
|
index 08ea8107fc8cbec3742278ab5cf03ef9048720f9..e59250af5d769076578017fb880e9168bc720947 100644
|
|
--- a/net/minecraft/core/component/PatchedDataComponentMap.java
|
|
+++ b/net/minecraft/core/component/PatchedDataComponentMap.java
|
|
@@ -14,7 +14,7 @@ import java.util.Map.Entry;
|
|
import java.util.stream.Collectors;
|
|
import org.jspecify.annotations.Nullable;
|
|
|
|
-public final class PatchedDataComponentMap implements DataComponentMap {
|
|
+public final class PatchedDataComponentMap implements DataComponentMap, org.leavesmc.leaves.lithium.common.util.change_tracking.ChangePublisher<net.minecraft.core.component.PatchedDataComponentMap> { // Leaves - Lithium Sleeping Block Entity
|
|
private final DataComponentMap prototype;
|
|
private Reference2ObjectMap<DataComponentType<?>, Optional<?>> patch;
|
|
private boolean copyOnWrite;
|
|
@@ -137,6 +137,7 @@ public final class PatchedDataComponentMap implements DataComponentMap {
|
|
}
|
|
|
|
private void ensureMapOwnership() {
|
|
+ if (moe.monnairealms.camellia.config.modules.optimizations.LeavesSleepingBlockEntityConfig.enabled && this.copyOnWrite && this.subscriber != null) this.subscriber.lithium$notify((PatchedDataComponentMap) (Object) this, 0); // Leaves - Lithium Sleeping Block Entity (only notify when actually copying, matches Lithium mixin semantics)
|
|
if (this.copyOnWrite) {
|
|
this.patch = new Reference2ObjectArrayMap<>(this.patch);
|
|
this.copyOnWrite = false;
|
|
@@ -233,4 +234,22 @@ public final class PatchedDataComponentMap implements DataComponentMap {
|
|
public String toString() {
|
|
return "{" + this.stream().map(TypedDataComponent::toString).collect(Collectors.joining(", ")) + "}";
|
|
}
|
|
+
|
|
+ // Leaves start - Lithium Sleeping Block Entity
|
|
+ private org.leavesmc.leaves.lithium.common.util.change_tracking.ChangeSubscriber<net.minecraft.core.component.PatchedDataComponentMap> subscriber;
|
|
+
|
|
+ @Override
|
|
+ public void lithium$subscribe(org.leavesmc.leaves.lithium.common.util.change_tracking.ChangeSubscriber<net.minecraft.core.component.PatchedDataComponentMap> subscriber, int subscriberData) {
|
|
+ if (subscriberData != 0) {
|
|
+ throw new UnsupportedOperationException("ComponentMapImpl does not support subscriber data");
|
|
+ }
|
|
+ this.subscriber = org.leavesmc.leaves.lithium.common.util.change_tracking.ChangeSubscriber.combine(this.subscriber, 0, subscriber, 0);
|
|
+ }
|
|
+
|
|
+ @Override
|
|
+ public int lithium$unsubscribe(org.leavesmc.leaves.lithium.common.util.change_tracking.ChangeSubscriber<net.minecraft.core.component.PatchedDataComponentMap> subscriber) {
|
|
+ this.subscriber = org.leavesmc.leaves.lithium.common.util.change_tracking.ChangeSubscriber.without(this.subscriber, subscriber);
|
|
+ return 0;
|
|
+ }
|
|
+ // Leaves end - Lithium Sleeping Block Entity
|
|
}
|
|
diff --git a/net/minecraft/server/commands/data/EntityDataAccessor.java b/net/minecraft/server/commands/data/EntityDataAccessor.java
|
|
index f2c5a6ce769d8a5fdb4b836eae6a61a4da91cb3f..968cdfa8a153b892963428967fd35c617b089d72 100644
|
|
--- a/net/minecraft/server/commands/data/EntityDataAccessor.java
|
|
+++ b/net/minecraft/server/commands/data/EntityDataAccessor.java
|
|
@@ -57,6 +57,7 @@ public class EntityDataAccessor implements DataAccessor {
|
|
try (ProblemReporter.ScopedCollector reporter = new ProblemReporter.ScopedCollector(this.entity.problemPath(), LOGGER)) {
|
|
this.entity.load(TagValueInput.create(reporter, this.entity.registryAccess(), tag));
|
|
this.entity.setUUID(uuid);
|
|
+ if (moe.monnairealms.camellia.config.modules.optimizations.LeavesSleepingBlockEntityConfig.enabled && this.entity instanceof net.minecraft.world.entity.item.ItemEntity itemEntity) itemEntity.levelCallback.onMove(); // Leaves - Lithium Sleeping Block Entity
|
|
}
|
|
}
|
|
|
|
diff --git a/net/minecraft/world/Container.java b/net/minecraft/world/Container.java
|
|
index 6e08d50794c4af4405f3e164a3fd46f376b3f78f..dd2d0940eece3e85078e574f66f71a4c497d75fd 100644
|
|
--- a/net/minecraft/world/Container.java
|
|
+++ b/net/minecraft/world/Container.java
|
|
@@ -16,7 +16,7 @@ import net.minecraft.world.level.Level;
|
|
import net.minecraft.world.level.block.entity.BlockEntity;
|
|
import org.jspecify.annotations.Nullable;
|
|
|
|
-public interface Container extends Clearable, Iterable<ItemStack>, SlotProvider {
|
|
+public interface Container extends Clearable, Iterable<ItemStack>, SlotProvider, org.leavesmc.leaves.lithium.api.inventory.LithiumCooldownReceivingInventory, org.leavesmc.leaves.lithium.api.inventory.LithiumTransferConditionInventory { // Leaves - Lithium Sleeping Block Entity
|
|
float DEFAULT_DISTANCE_BUFFER = 4.0F;
|
|
|
|
int getContainerSize();
|
|
diff --git a/net/minecraft/world/entity/Entity.java b/net/minecraft/world/entity/Entity.java
|
|
index 18e0572fe28461e57edb13e6ed6f5a0b6b3604c9..83914a091cc8fd6ef726f2732238b164bb590ea2 100644
|
|
--- a/net/minecraft/world/entity/Entity.java
|
|
+++ b/net/minecraft/world/entity/Entity.java
|
|
@@ -324,7 +324,7 @@ public abstract class Entity
|
|
private static final EntityDataAccessor<Boolean> DATA_NO_GRAVITY = SynchedEntityData.defineId(Entity.class, EntityDataSerializers.BOOLEAN);
|
|
protected static final EntityDataAccessor<Pose> DATA_POSE = SynchedEntityData.defineId(Entity.class, EntityDataSerializers.POSE);
|
|
public static final EntityDataAccessor<Integer> DATA_TICKS_FROZEN = SynchedEntityData.defineId(Entity.class, EntityDataSerializers.INT);
|
|
- private EntityInLevelCallback levelCallback = EntityInLevelCallback.NULL;
|
|
+ public EntityInLevelCallback levelCallback = EntityInLevelCallback.NULL; // Leaves - private -> public
|
|
private final VecDeltaCodec packetPositionCodec = new VecDeltaCodec();
|
|
public boolean needsSync;
|
|
public boolean syncPosition;
|
|
@@ -4467,11 +4467,13 @@ public abstract class Entity
|
|
}
|
|
|
|
protected Entity transformForAsyncTeleport(ServerLevel destination, Vec3 pos, Float yaw, Float pitch, Vec3 velocity) {
|
|
+ final boolean toSameWorld = this.level != destination; // Camellia - Region threading for lithium sleeping block entity
|
|
this.removeAfterChangingDimensions(); // remove before so that any CBEntity#getHandle call affects this entity before copying
|
|
|
|
Entity copy = this.getType().create(destination, EntitySpawnReason.DIMENSION_TRAVEL);
|
|
copy.restoreFrom(this);
|
|
copy.transform(pos, yaw, pitch, velocity);
|
|
+ if (toSameWorld) copy.notifyLithiumTrackerIfNeeded(); // Camellia - Region threading for lithium sleeping block entity
|
|
if (copy instanceof net.minecraft.world.entity.boss.enderdragon.EnderDragon dragon) dragon.syncDragonPartsAfterTeleportTransform(); // Camellia - Fix dragon part desync
|
|
// vanilla code used to call remove _after_ copying, and some stuff is required to be after copy - so add hook here
|
|
// for example, clearing of inventory after switching dimensions
|
|
@@ -5953,8 +5955,29 @@ public abstract class Entity
|
|
this.setBoundingBox(this.makeBoundingBox());
|
|
}
|
|
// Paper end - Block invalid positions and bounding box
|
|
+ this.notifyLithiumTrackerIfNeeded(); // Camellia - Leaves lithium sleeping block entity
|
|
}
|
|
|
|
+ // Camellia start - Region threading for lithium sleeping block entity
|
|
+ private void notifyLithiumTrackerIfNeeded() {
|
|
+ // Leaves start - Lithium Sleeping Block Entity
|
|
+ if (!moe.monnairealms.camellia.config.modules.optimizations.LeavesSleepingBlockEntityConfig.enabled) return;
|
|
+ var currentWorldData = io.papermc.paper.threadedregions.TickRegionScheduler.getCurrentRegionizedWorldData();
|
|
+ if (currentWorldData == null || currentWorldData.world != this.level) return;
|
|
+ if (this instanceof ItemEntity) {
|
|
+ long sectionKey = ca.spottedleaf.moonrise.common.util.CoordinateUtils.getChunkSectionKey(this);
|
|
+ org.leavesmc.leaves.lithium.common.tracking.entity.ChunkSectionItemEntityMovementTracker tracker = currentWorldData.itemEntityMovementTrackerMap.get(sectionKey);
|
|
+ if (tracker != null) tracker.notifyAllListeners(currentWorldData.getRedstoneGameTime()); // Camellia - Region threading for lithium sleeping block entity
|
|
+ }
|
|
+ else if (this instanceof net.minecraft.world.entity.vehicle.ContainerEntity) {
|
|
+ long sectionKey = ca.spottedleaf.moonrise.common.util.CoordinateUtils.getChunkSectionKey(this);
|
|
+ org.leavesmc.leaves.lithium.common.tracking.entity.ChunkSectionInventoryEntityTracker tracker = currentWorldData.containerEntityMovementTrackerMap.get(sectionKey);
|
|
+ if (tracker != null) tracker.notifyAllListeners(currentWorldData.getRedstoneGameTime()); // Camellia - Region threading for lithium sleeping block entity
|
|
+ }
|
|
+ // Leaves end - Lithium Sleeping Block Entity
|
|
+ }
|
|
+ // Camellia end
|
|
+
|
|
public void checkDespawn() {
|
|
}
|
|
|
|
diff --git a/net/minecraft/world/entity/item/ItemEntity.java b/net/minecraft/world/entity/item/ItemEntity.java
|
|
index 9a75c6b38f1cabd4415067d781f6ad49f4d8ebc8..1606bb148203d4bf7bdacb58acf1144c74fcbffb 100644
|
|
--- a/net/minecraft/world/entity/item/ItemEntity.java
|
|
+++ b/net/minecraft/world/entity/item/ItemEntity.java
|
|
@@ -35,8 +35,12 @@ import net.minecraft.world.level.storage.ValueInput;
|
|
import net.minecraft.world.level.storage.ValueOutput;
|
|
import net.minecraft.world.phys.Vec3;
|
|
import org.jspecify.annotations.Nullable;
|
|
+// Leaves start - Lithium Sleeping Block Entity
|
|
+import org.leavesmc.leaves.lithium.common.util.change_tracking.ChangePublisher;
|
|
+import org.leavesmc.leaves.lithium.common.util.change_tracking.ChangeSubscriber;
|
|
+// Leaves end - Lithium Sleeping Block Entity
|
|
|
|
-public class ItemEntity extends Entity implements TraceableEntity {
|
|
+public class ItemEntity extends Entity implements TraceableEntity, ChangePublisher<ItemEntity>, ChangeSubscriber.CountChangeSubscriber<ItemStack> { // Leaves - Lithium Sleeping Block Entity
|
|
private static final EntityDataAccessor<ItemStack> DATA_ITEM = SynchedEntityData.defineId(ItemEntity.class, EntityDataSerializers.ITEM_STACK);
|
|
private static final float FLOAT_HEIGHT = 0.1F;
|
|
public static final float EYE_HEIGHT = 0.2125F;
|
|
@@ -532,6 +536,25 @@ public class ItemEntity extends Entity implements TraceableEntity {
|
|
}
|
|
|
|
public void setItem(final ItemStack itemStack) {
|
|
+ // Leaves start - Lithium Sleeping Block Entity
|
|
+ if (moe.monnairealms.camellia.config.modules.optimizations.LeavesSleepingBlockEntityConfig.enabled && this.subscriber != null) {
|
|
+ ItemStack oldStack = this.getItem();
|
|
+ if (oldStack != itemStack) {
|
|
+ if (!oldStack.isEmpty()) {
|
|
+ oldStack.lithium$unsubscribe(this);
|
|
+ }
|
|
+
|
|
+ if (!itemStack.isEmpty()) {
|
|
+ itemStack.lithium$subscribe(this, this.subscriberData);
|
|
+ this.subscriber.lithium$notify((ItemEntity) (Object) this, this.subscriberData);
|
|
+ } else {
|
|
+ this.subscriber.lithium$forceUnsubscribe((ItemEntity) (Object) this, this.subscriberData);
|
|
+ this.subscriber = null;
|
|
+ this.subscriberData = 0;
|
|
+ }
|
|
+ }
|
|
+ }
|
|
+ // Leaves end - Lithium Sleeping Block Entity
|
|
this.getEntityData().set(DATA_ITEM, itemStack);
|
|
this.despawnRate = this.level().paperConfig().entities.spawning.altItemDespawnRate.enabled ? this.level().paperConfig().entities.spawning.altItemDespawnRate.items.getOrDefault(itemStack.getItem(), this.level().spigotConfig.itemDespawnRate) : this.level().spigotConfig.itemDespawnRate; // Paper - Alternative item-despawn-rate
|
|
}
|
|
@@ -599,4 +622,76 @@ public class ItemEntity extends Entity implements TraceableEntity {
|
|
public @Nullable SlotAccess getSlot(final int slot) {
|
|
return slot == 0 ? SlotAccess.of(this::getItem, this::setItem) : super.getSlot(slot);
|
|
}
|
|
+
|
|
+ // Leaves start - Lithium Sleeping Block Entity
|
|
+ private ChangeSubscriber<ItemEntity> subscriber;
|
|
+ //Stores the data of the subscriber, unless the subscriber is a Multi which stores the data in a list, in which case this variable stores 0
|
|
+ private int subscriberData;
|
|
+
|
|
+ private void startTrackingChanges() {
|
|
+ ItemStack stack = this.getItem();
|
|
+ if (!stack.isEmpty()) {
|
|
+ stack.lithium$subscribe(this, 0);
|
|
+ }
|
|
+ }
|
|
+
|
|
+ @Override
|
|
+ public void lithium$subscribe(ChangeSubscriber<ItemEntity> subscriber, int subscriberData) {
|
|
+ if (this.subscriber == null) {
|
|
+ this.startTrackingChanges();
|
|
+ }
|
|
+ this.subscriber = ChangeSubscriber.combine(this.subscriber, this.subscriberData, subscriber, subscriberData);
|
|
+ if (this.subscriber instanceof ChangeSubscriber.Multi<?>) {
|
|
+ this.subscriberData = 0;
|
|
+ } else {
|
|
+ this.subscriberData = subscriberData;
|
|
+ }
|
|
+ }
|
|
+
|
|
+ @Override
|
|
+ public int lithium$unsubscribe(ChangeSubscriber<ItemEntity> subscriber) {
|
|
+ int retval = ChangeSubscriber.dataOf(this.subscriber, subscriber, this.subscriberData);
|
|
+ this.subscriberData = ChangeSubscriber.dataWithout(this.subscriber, subscriber, this.subscriberData);
|
|
+ this.subscriber = ChangeSubscriber.without(this.subscriber, subscriber);
|
|
+
|
|
+ if (this.subscriber == null) {
|
|
+ ItemStack stack = this.getItem();
|
|
+ if (!stack.isEmpty()) {
|
|
+ stack.lithium$unsubscribe(this);
|
|
+ }
|
|
+ }
|
|
+ return retval;
|
|
+ }
|
|
+
|
|
+ @Override
|
|
+ public void lithium$notify(ItemStack publisher, int subscriberData) {
|
|
+ if (publisher != this.getItem()) {
|
|
+ throw new IllegalStateException("Received notification from an unexpected publisher");
|
|
+ }
|
|
+
|
|
+ if (this.subscriber != null) {
|
|
+ this.subscriber.lithium$notify(this, this.subscriberData);
|
|
+ }
|
|
+ }
|
|
+
|
|
+ @Override
|
|
+ public void lithium$forceUnsubscribe(ItemStack publisher, int subscriberData) {
|
|
+ if (this.subscriber != null) {
|
|
+ this.subscriber.lithium$forceUnsubscribe(this, this.subscriberData);
|
|
+ this.subscriber = null;
|
|
+ this.subscriberData = 0;
|
|
+ }
|
|
+ }
|
|
+
|
|
+ @Override
|
|
+ public void lithium$notifyCount(ItemStack publisher, int subscriberData, int newCount) {
|
|
+ if (publisher != this.getItem()) {
|
|
+ throw new IllegalStateException("Received notification from an unexpected publisher");
|
|
+ }
|
|
+
|
|
+ if (this.subscriber instanceof ChangeSubscriber.CountChangeSubscriber<ItemEntity> countChangeSubscriber) {
|
|
+ countChangeSubscriber.lithium$notifyCount(this, this.subscriberData, newCount);
|
|
+ }
|
|
+ }
|
|
+ // Leaves end - Lithium Sleeping Block Entity
|
|
}
|
|
diff --git a/net/minecraft/world/entity/vehicle/minecart/AbstractMinecartContainer.java b/net/minecraft/world/entity/vehicle/minecart/AbstractMinecartContainer.java
|
|
index d3651110e15e8e1ad530df4bb4c05dbc73a79a63..d87dcb72fd5d2b22eafc1a444d4fc3807595b6a5 100644
|
|
--- a/net/minecraft/world/entity/vehicle/minecart/AbstractMinecartContainer.java
|
|
+++ b/net/minecraft/world/entity/vehicle/minecart/AbstractMinecartContainer.java
|
|
@@ -23,7 +23,7 @@ import net.minecraft.world.level.storage.loot.LootTable;
|
|
import net.minecraft.world.phys.Vec3;
|
|
import org.jspecify.annotations.Nullable;
|
|
|
|
-public abstract class AbstractMinecartContainer extends AbstractMinecart implements ContainerEntity {
|
|
+public abstract class AbstractMinecartContainer extends AbstractMinecart implements ContainerEntity, org.leavesmc.leaves.lithium.api.inventory.LithiumInventory { // Leaves - Lithium Sleeping Block Entity
|
|
private NonNullList<ItemStack> itemStacks = NonNullList.withSize(this.getContainerSize(), ItemStack.EMPTY); // CraftBukkit - SPIGOT-3513
|
|
private @Nullable ResourceKey<LootTable> lootTable;
|
|
private long lootTableSeed;
|
|
@@ -217,4 +217,15 @@ public abstract class AbstractMinecartContainer extends AbstractMinecart impleme
|
|
return this.getBukkitEntity().getLocation();
|
|
}
|
|
// CraftBukkit end
|
|
+ // Leaves start - Lithium Sleeping Block Entity
|
|
+ @Override
|
|
+ public net.minecraft.core.NonNullList<net.minecraft.world.item.ItemStack> getInventoryLithium() {
|
|
+ return itemStacks;
|
|
+ }
|
|
+
|
|
+ @Override
|
|
+ public void setInventoryLithium(net.minecraft.core.NonNullList<net.minecraft.world.item.ItemStack> inventory) {
|
|
+ itemStacks = inventory;
|
|
+ }
|
|
+ // Leaves end - Lithium Sleeping Block Entity
|
|
}
|
|
diff --git a/net/minecraft/world/inventory/AbstractContainerMenu.java b/net/minecraft/world/inventory/AbstractContainerMenu.java
|
|
index 136e018d83c5be90894358a97b23f5fcfa6c0d38..93c94a059873993b2e3e03a47c61f90d28f82362 100644
|
|
--- a/net/minecraft/world/inventory/AbstractContainerMenu.java
|
|
+++ b/net/minecraft/world/inventory/AbstractContainerMenu.java
|
|
@@ -893,6 +893,7 @@ public abstract class AbstractContainerMenu {
|
|
|
|
float totalPercent = 0.0F;
|
|
|
|
+ if (moe.monnairealms.camellia.config.modules.optimizations.LeavesSleepingBlockEntityConfig.enabled && container instanceof org.leavesmc.leaves.lithium.api.inventory.LithiumInventory optimizedInventory) return org.leavesmc.leaves.lithium.common.hopper.InventoryHelper.getLithiumStackList(optimizedInventory).getSignalStrength(container); // Leaves - Lithium Sleeping Block Entity
|
|
for (int i = 0; i < container.getContainerSize(); i++) {
|
|
ItemStack itemStack = container.getItem(i);
|
|
if (!itemStack.isEmpty()) {
|
|
diff --git a/net/minecraft/world/item/ItemStack.java b/net/minecraft/world/item/ItemStack.java
|
|
index dc1e9acce122f3ebd7bf2b03150b4045db9493df..0bd2f2da669aa1a59d0af65aea3b305dd9be4476 100644
|
|
--- a/net/minecraft/world/item/ItemStack.java
|
|
+++ b/net/minecraft/world/item/ItemStack.java
|
|
@@ -98,8 +98,12 @@ import org.apache.commons.lang3.function.TriConsumer;
|
|
import org.apache.commons.lang3.mutable.MutableBoolean;
|
|
import org.jspecify.annotations.Nullable;
|
|
import org.slf4j.Logger;
|
|
+// Leaves start - Lithium Sleeping Block Entity
|
|
+import org.leavesmc.leaves.lithium.common.util.change_tracking.ChangePublisher;
|
|
+import org.leavesmc.leaves.lithium.common.util.change_tracking.ChangeSubscriber;
|
|
+// Leaves end - Lithium Sleeping Block Entity
|
|
|
|
-public final class ItemStack implements DataComponentHolder, ItemInstance {
|
|
+public final class ItemStack implements DataComponentHolder, ItemInstance, ChangePublisher<net.minecraft.world.item.ItemStack>, ChangeSubscriber<PatchedDataComponentMap> { // Leaves - Lithium Sleeping Block Entity
|
|
private static final List<Component> OP_NBT_WARNING = List.of(
|
|
Component.translatable("item.op_warning.line1").withStyle(ChatFormatting.RED, ChatFormatting.BOLD),
|
|
Component.translatable("item.op_warning.line2").withStyle(ChatFormatting.RED),
|
|
@@ -965,6 +969,7 @@ public final class ItemStack implements DataComponentHolder, ItemInstance {
|
|
// CraftBukkit end
|
|
|
|
public <T> @Nullable T set(final DataComponentType<T> type, final @Nullable T value) {
|
|
+ if (moe.monnairealms.camellia.config.modules.optimizations.LeavesSleepingBlockEntityConfig.enabled && type == DataComponents.ENCHANTMENTS && this.subscriber instanceof ChangeSubscriber.EnchantmentSubscriber<ItemStack> enchantmentSubscriber) enchantmentSubscriber.lithium$notifyAfterEnchantmentChange(this, this.subscriberData); // Leaves - Lithium Sleeping Block Entity
|
|
return this.components.set(type, value);
|
|
}
|
|
|
|
@@ -1304,6 +1309,23 @@ public final class ItemStack implements DataComponentHolder, ItemInstance {
|
|
}
|
|
|
|
public void setCount(final int count) {
|
|
+ // Leaves start - Lithium Sleeping Block Entity
|
|
+ if (moe.monnairealms.camellia.config.modules.optimizations.LeavesSleepingBlockEntityConfig.enabled && count != this.count) {
|
|
+ if (this.subscriber instanceof ChangeSubscriber.CountChangeSubscriber<ItemStack> countChangeSubscriber) {
|
|
+ countChangeSubscriber.lithium$notifyCount(this, this.subscriberData, count);
|
|
+ }
|
|
+
|
|
+ if (count == 0) {
|
|
+ this.components.lithium$unsubscribe(this);
|
|
+
|
|
+ if (this.subscriber != null) {
|
|
+ this.subscriber.lithium$forceUnsubscribe(this, this.subscriberData);
|
|
+ this.subscriber = null;
|
|
+ this.subscriberData = 0;
|
|
+ }
|
|
+ }
|
|
+ }
|
|
+ // Leaves end - Lithium Sleeping Block Entity
|
|
this.count = count;
|
|
}
|
|
|
|
@@ -1371,4 +1393,90 @@ public final class ItemStack implements DataComponentHolder, ItemInstance {
|
|
.or(() -> Optional.ofNullable(this.getItem().getItemDamageSource(attacker)))
|
|
.orElseGet(attacker::createDamageSource);
|
|
}
|
|
+
|
|
+ // Leaves start - Lithium Sleeping Block Entity
|
|
+ private ChangeSubscriber<ItemStack> subscriber;
|
|
+ private int subscriberData;
|
|
+
|
|
+ @Override
|
|
+ public void lithium$subscribe(ChangeSubscriber<ItemStack> subscriber, int subscriberData) {
|
|
+ if (this.isEmpty()) {
|
|
+ throw new IllegalStateException("Cannot subscribe to an empty ItemStack!");
|
|
+ }
|
|
+
|
|
+ if (this.subscriber == null) {
|
|
+ this.startTrackingChanges();
|
|
+ }
|
|
+ this.subscriber = ChangeSubscriber.combine(this.subscriber, this.subscriberData, subscriber, subscriberData);
|
|
+ if (this.subscriber instanceof ChangeSubscriber.Multi<?>) {
|
|
+ this.subscriberData = 0;
|
|
+ } else {
|
|
+ this.subscriberData = subscriberData;
|
|
+ }
|
|
+ }
|
|
+
|
|
+ @Override
|
|
+ public int lithium$unsubscribe(ChangeSubscriber<ItemStack> subscriber) {
|
|
+ if (this.isEmpty()) {
|
|
+ throw new IllegalStateException("Cannot unsubscribe from an empty ItemStack!");
|
|
+ }
|
|
+
|
|
+ int retval = ChangeSubscriber.dataOf(this.subscriber, subscriber, this.subscriberData);
|
|
+ this.subscriberData = ChangeSubscriber.dataWithout(this.subscriber, subscriber, this.subscriberData);
|
|
+ this.subscriber = ChangeSubscriber.without(this.subscriber, subscriber);
|
|
+
|
|
+ if (this.subscriber == null) {
|
|
+ this.components.lithium$unsubscribe(this);
|
|
+ }
|
|
+ return retval;
|
|
+ }
|
|
+
|
|
+ @Override
|
|
+ public void lithium$unsubscribeWithData(ChangeSubscriber<ItemStack> subscriber, int subscriberData) {
|
|
+ if (this.isEmpty()) {
|
|
+ throw new IllegalStateException("Cannot unsubscribe from an empty ItemStack!");
|
|
+ }
|
|
+
|
|
+ this.subscriberData = ChangeSubscriber.dataWithout(this.subscriber, subscriber, this.subscriberData, subscriberData, true);
|
|
+ this.subscriber = ChangeSubscriber.without(this.subscriber, subscriber, subscriberData, true);
|
|
+
|
|
+ if (this.subscriber == null) {
|
|
+ this.components.lithium$unsubscribe(this);
|
|
+ }
|
|
+ }
|
|
+
|
|
+ @Override
|
|
+ public boolean lithium$isSubscribedWithData(ChangeSubscriber<ItemStack> subscriber, int subscriberData) {
|
|
+ if (this.isEmpty()) {
|
|
+ throw new IllegalStateException("Cannot be subscribed to an empty ItemStack!");
|
|
+ }
|
|
+
|
|
+ return ChangeSubscriber.containsSubscriber(this.subscriber, this.subscriberData, subscriber, subscriberData);
|
|
+ }
|
|
+
|
|
+ @Override
|
|
+ public void lithium$forceUnsubscribe(PatchedDataComponentMap publisher, int subscriberData) {
|
|
+ if (publisher != this.components) {
|
|
+ throw new IllegalStateException("Invalid publisher, expected " + this.components + " but got " + publisher);
|
|
+ }
|
|
+ this.subscriber.lithium$forceUnsubscribe(this, this.subscriberData);
|
|
+ this.subscriber = null;
|
|
+ this.subscriberData = 0;
|
|
+ }
|
|
+
|
|
+ private void startTrackingChanges() {
|
|
+ this.components.lithium$subscribe(this, 0);
|
|
+ }
|
|
+
|
|
+ @Override
|
|
+ public void lithium$notify(PatchedDataComponentMap publisher, int subscriberData) {
|
|
+ if (publisher != this.components) {
|
|
+ throw new IllegalStateException("Invalid publisher, expected " + this.components + " but got " + publisher);
|
|
+ }
|
|
+
|
|
+ if (this.subscriber != null) {
|
|
+ this.subscriber.lithium$notify(this, this.subscriberData);
|
|
+ }
|
|
+ }
|
|
+ // Leaves end - Lithium Sleeping Block Entity
|
|
}
|
|
diff --git a/net/minecraft/world/level/Level.java b/net/minecraft/world/level/Level.java
|
|
index 41b84a84a2ae24555a065d0779957b7b71611523..a6d1f8ccf2e33394508d8d14bec2141942e31ccd 100644
|
|
--- a/net/minecraft/world/level/Level.java
|
|
+++ b/net/minecraft/world/level/Level.java
|
|
@@ -1553,7 +1553,7 @@ public abstract class Level implements LevelAccessor, AutoCloseable, ca.spottedl
|
|
// Paper end - Fix MC-117075 use removeAll
|
|
if (ticker.isRemoved()) {
|
|
toRemove.add(ticker); // Paper - Fix MC-117075 use removeAll
|
|
- } else if (tickBlockEntities && this.shouldTickBlocksAt(ticker.getPos())) {
|
|
+ } else if (tickBlockEntities && this.shouldTickBlockPosFilterNull(ticker.getPos())) { // Leaves - Lithium Sleeping Block Entity
|
|
ticker.tick();
|
|
// Paper start - rewrite chunk system
|
|
if ((++tickedEntities & 7) == 0) {
|
|
@@ -1631,6 +1631,27 @@ public abstract class Level implements LevelAccessor, AutoCloseable, ca.spottedl
|
|
return this.shouldTickBlocksAt(ChunkPos.pack(pos));
|
|
}
|
|
|
|
+ // Leaves start - Lithium Sleeping Block Entity
|
|
+ public @org.jspecify.annotations.Nullable BlockEntity lithium$getLoadedExistingBlockEntity(BlockPos pos) {
|
|
+ if (!this.isOutsideBuildHeight(pos)) {
|
|
+ if (this.isClientSide || ca.spottedleaf.moonrise.common.util.TickThread.isTickThreadFor(this, pos)) {
|
|
+ ChunkAccess chunk = this.getChunk(SectionPos.blockToSectionCoord(pos.getX()), SectionPos.blockToSectionCoord(pos.getZ()), ChunkStatus.FULL, false);
|
|
+ if (chunk != null) {
|
|
+ return chunk.getBlockEntity(pos);
|
|
+ }
|
|
+ }
|
|
+ }
|
|
+ return null;
|
|
+ }
|
|
+
|
|
+ private boolean shouldTickBlockPosFilterNull(BlockPos pos) {
|
|
+ if (pos == null) {
|
|
+ return false;
|
|
+ }
|
|
+ return shouldTickBlocksAt(pos);
|
|
+ }
|
|
+ // Leaves end - Lithium Sleeping Block Entity
|
|
+
|
|
public void explode(
|
|
final @Nullable Entity source, final double x, final double y, final double z, final float r, final Level.ExplosionInteraction blockInteraction
|
|
) {
|
|
diff --git a/net/minecraft/world/level/block/ComposterBlock.java b/net/minecraft/world/level/block/ComposterBlock.java
|
|
index 69e3969242ad52168e947af209e6fa72f36178ae..82f041a6c72eb09d365b5f83dd4731467ad49563 100644
|
|
--- a/net/minecraft/world/level/block/ComposterBlock.java
|
|
+++ b/net/minecraft/world/level/block/ComposterBlock.java
|
|
@@ -426,7 +426,7 @@ public class ComposterBlock extends Block implements WorldlyContainerHolder {
|
|
}
|
|
}
|
|
|
|
- public static class EmptyContainer extends SimpleContainer implements WorldlyContainer {
|
|
+ public static class EmptyContainer extends SimpleContainer implements WorldlyContainer, org.leavesmc.leaves.lithium.common.hopper.BlockStateOnlyInventory { // Leaves - Lithium Sleeping Block Entity
|
|
public EmptyContainer(LevelAccessor levelAccessor, BlockPos blockPos) { // CraftBukkit
|
|
super(0);
|
|
this.bukkitOwner = new org.bukkit.craftbukkit.inventory.CraftBlockInventoryHolder(levelAccessor, blockPos, this); // CraftBukkit
|
|
@@ -448,7 +448,7 @@ public class ComposterBlock extends Block implements WorldlyContainerHolder {
|
|
}
|
|
}
|
|
|
|
- public static class InputContainer extends SimpleContainer implements WorldlyContainer {
|
|
+ public static class InputContainer extends SimpleContainer implements WorldlyContainer, org.leavesmc.leaves.lithium.common.hopper.BlockStateOnlyInventory { // Leaves - Lithium Sleeping Block Entity
|
|
private final BlockState state;
|
|
private final LevelAccessor level;
|
|
private final BlockPos pos;
|
|
@@ -494,12 +494,13 @@ public class ComposterBlock extends Block implements WorldlyContainerHolder {
|
|
}
|
|
// Paper end - Add CompostItemEvent and EntityCompostItemEvent
|
|
this.level.levelEvent(LevelEvent.COMPOSTER_FILL, this.pos, newState != this.state ? 1 : 0);
|
|
+ if (moe.monnairealms.camellia.config.modules.optimizations.LeavesSleepingBlockEntityConfig.enabled) this.changed = false; // Leaves - Lithium Sleeping Block Entity
|
|
this.removeItemNoUpdate(0);
|
|
}
|
|
}
|
|
}
|
|
|
|
- public static class OutputContainer extends SimpleContainer implements WorldlyContainer {
|
|
+ public static class OutputContainer extends SimpleContainer implements WorldlyContainer, org.leavesmc.leaves.lithium.common.hopper.BlockStateOnlyInventory { // Leaves - Lithium Sleeping Block Entity
|
|
private final BlockState state;
|
|
private final LevelAccessor level;
|
|
private final BlockPos pos;
|
|
diff --git a/net/minecraft/world/level/block/DiodeBlock.java b/net/minecraft/world/level/block/DiodeBlock.java
|
|
index 2339099e05af80b234e64778822b012cc6318157..d828f2535a4860d96f3ca6c95a54e00b035ffdc3 100644
|
|
--- a/net/minecraft/world/level/block/DiodeBlock.java
|
|
+++ b/net/minecraft/world/level/block/DiodeBlock.java
|
|
@@ -179,6 +179,7 @@ public abstract class DiodeBlock extends HorizontalDirectionalBlock {
|
|
@Override
|
|
protected void onPlace(final BlockState state, final Level level, final BlockPos pos, final BlockState oldState, final boolean movedByPiston) {
|
|
this.updateNeighborsInFront(level, pos, state);
|
|
+ if (moe.monnairealms.camellia.config.modules.optimizations.LeavesSleepingBlockEntityConfig.enabled && this instanceof ComparatorBlock && !oldState.is(Blocks.COMPARATOR)) org.leavesmc.leaves.lithium.common.block.entity.inventory_comparator_tracking.ComparatorTracking.notifyNearbyBlockEntitiesAboutNewComparator(level, pos); // Leaves - Lithium Sleeping Block Entity
|
|
}
|
|
|
|
@Override
|
|
diff --git a/net/minecraft/world/level/block/HopperBlock.java b/net/minecraft/world/level/block/HopperBlock.java
|
|
index 3932da81757ea0ab7a41617165f5b64dc44ea3eb..2ccabd98f9fa7f2a228c7ee320d0f8c98b4926ac 100644
|
|
--- a/net/minecraft/world/level/block/HopperBlock.java
|
|
+++ b/net/minecraft/world/level/block/HopperBlock.java
|
|
@@ -38,7 +38,7 @@ import net.minecraft.world.phys.shapes.Shapes;
|
|
import net.minecraft.world.phys.shapes.VoxelShape;
|
|
import org.jspecify.annotations.Nullable;
|
|
|
|
-public class HopperBlock extends BaseEntityBlock {
|
|
+public class HopperBlock extends BaseEntityBlock implements org.leavesmc.leaves.lithium.common.block.entity.ShapeUpdateHandlingBlockBehaviour { // Leaves - Lithium Sleeping Block Entity
|
|
public static final MapCodec<HopperBlock> CODEC = simpleCodec(HopperBlock::new);
|
|
public static final EnumProperty<Direction> FACING = BlockStateProperties.FACING_HOPPER;
|
|
public static final BooleanProperty ENABLED = BlockStateProperties.ENABLED;
|
|
@@ -100,6 +100,17 @@ public class HopperBlock extends BaseEntityBlock {
|
|
protected void onPlace(final BlockState state, final Level level, final BlockPos pos, final BlockState oldState, final boolean movedByPiston) {
|
|
if (!oldState.is(state.getBlock())) {
|
|
this.checkPoweredState(level, pos, state);
|
|
+ // Leaves start - Lithium Sleeping Block Entity
|
|
+ //invalidate caches of nearby hoppers when placing an update suppressed hopper
|
|
+ if (moe.monnairealms.camellia.config.modules.optimizations.LeavesSleepingBlockEntityConfig.enabled && level.getBlockState(pos) != state) {
|
|
+ for (Direction direction : UPDATE_SHAPE_ORDER) {
|
|
+ BlockEntity hopper = level.lithium$getLoadedExistingBlockEntity(pos.relative(direction));
|
|
+ if (hopper instanceof org.leavesmc.leaves.lithium.common.hopper.UpdateReceiver updateReceiver) {
|
|
+ updateReceiver.lithium$invalidateCacheOnNeighborUpdate(direction == Direction.DOWN);
|
|
+ }
|
|
+ }
|
|
+ }
|
|
+ // Leaves end - Lithium Sleeping Block Entity
|
|
}
|
|
}
|
|
|
|
@@ -118,6 +129,7 @@ public class HopperBlock extends BaseEntityBlock {
|
|
protected void neighborChanged(
|
|
final BlockState state, final Level level, final BlockPos pos, final Block block, final @Nullable Orientation orientation, final boolean movedByPiston
|
|
) {
|
|
+ if (moe.monnairealms.camellia.config.modules.optimizations.LeavesSleepingBlockEntityConfig.enabled && level.lithium$getLoadedExistingBlockEntity(pos) instanceof org.leavesmc.leaves.lithium.common.hopper.UpdateReceiver updateReceiver) updateReceiver.lithium$invalidateCacheOnUndirectedNeighborUpdate(); // Leaves - Lithium Sleeping Block Entity
|
|
this.checkPoweredState(level, pos, state);
|
|
}
|
|
|
|
@@ -177,4 +189,25 @@ public class HopperBlock extends BaseEntityBlock {
|
|
protected boolean isPathfindable(final BlockState state, final PathComputationType type) {
|
|
return false;
|
|
}
|
|
+
|
|
+ // Leaves start - Lithium Sleeping Block Entity
|
|
+ @Override
|
|
+ public void lithium$handleShapeUpdate(net.minecraft.world.level.LevelReader levelReader, BlockState myBlockState, BlockPos myPos, BlockPos posFrom, BlockState newState) {
|
|
+ //invalidate cache when composters change state
|
|
+ if (newState.getBlock() instanceof net.minecraft.world.WorldlyContainerHolder) {
|
|
+ this.updateHopper(levelReader, myBlockState, myPos, posFrom);
|
|
+ }
|
|
+ }
|
|
+
|
|
+ private void updateHopper(net.minecraft.world.level.LevelReader world, BlockState myBlockState, BlockPos myPos, BlockPos posFrom) {
|
|
+ Direction facing = myBlockState.getValue(HopperBlock.FACING);
|
|
+ boolean above = posFrom.getY() == myPos.getY() + 1;
|
|
+ if (above || posFrom.getX() == myPos.getX() + facing.getStepX() && posFrom.getY() == myPos.getY() + facing.getStepY() && posFrom.getZ() == myPos.getZ() + facing.getStepZ()) {
|
|
+ BlockEntity hopper = ((net.minecraft.world.level.Level) world).lithium$getLoadedExistingBlockEntity(myPos);
|
|
+ if (hopper instanceof org.leavesmc.leaves.lithium.common.hopper.UpdateReceiver updateReceiver) {
|
|
+ updateReceiver.lithium$invalidateCacheOnNeighborUpdate(above);
|
|
+ }
|
|
+ }
|
|
+ }
|
|
+ // Leaves end - Lithium Sleeping Block Entity
|
|
}
|
|
diff --git a/net/minecraft/world/level/block/entity/AbstractFurnaceBlockEntity.java b/net/minecraft/world/level/block/entity/AbstractFurnaceBlockEntity.java
|
|
index 78dbdf43ac9095eb3cf0b0653bab2603d5527ff4..601471d7578b93f30d8033bfab4d4050a8ef78f8 100644
|
|
--- a/net/minecraft/world/level/block/entity/AbstractFurnaceBlockEntity.java
|
|
+++ b/net/minecraft/world/level/block/entity/AbstractFurnaceBlockEntity.java
|
|
@@ -39,7 +39,7 @@ import net.minecraft.world.level.storage.ValueOutput;
|
|
import net.minecraft.world.phys.Vec3;
|
|
import org.jspecify.annotations.Nullable;
|
|
|
|
-public abstract class AbstractFurnaceBlockEntity extends BaseContainerBlockEntity implements WorldlyContainer, StackedContentsCompatible, RecipeCraftingHolder {
|
|
+public abstract class AbstractFurnaceBlockEntity extends BaseContainerBlockEntity implements WorldlyContainer, StackedContentsCompatible, RecipeCraftingHolder, org.leavesmc.leaves.lithium.common.block.entity.inventory_change_tracking.InventoryChangeTracker, org.leavesmc.leaves.lithium.common.block.entity.SleepingBlockEntity, org.leavesmc.leaves.lithium.common.block.entity.SetChangedHandlingBlockEntity, org.leavesmc.leaves.lithium.api.inventory.LithiumInventory { // Leaves - Lithium Sleeping Block Entity
|
|
protected static final int SLOT_INPUT = 0;
|
|
protected static final int SLOT_FUEL = 1;
|
|
protected static final int SLOT_RESULT = 2;
|
|
@@ -162,6 +162,7 @@ public abstract class AbstractFurnaceBlockEntity extends BaseContainerBlockEntit
|
|
this.recipesUsed.clear();
|
|
this.recipesUsed.putAll(input.read("RecipesUsed", RECIPES_USED_CODEC).orElse(Map.of()));
|
|
this.cookSpeedMultiplier = input.getDoubleOr("Paper.CookSpeedMultiplier", 1); // Paper - cook speed multiplier API
|
|
+ if (moe.monnairealms.camellia.config.modules.optimizations.LeavesSleepingBlockEntityConfig.enabled && this.isSleeping() && this.level != null) this.wakeUpNow(); // Leaves - Lithium Sleeping Block Entity
|
|
}
|
|
|
|
@Override
|
|
@@ -269,6 +270,7 @@ public abstract class AbstractFurnaceBlockEntity extends BaseContainerBlockEntit
|
|
if (changed) {
|
|
setChanged(level, pos, state);
|
|
}
|
|
+ if (moe.monnairealms.camellia.config.modules.optimizations.LeavesSleepingBlockEntityConfig.enabled) entity.checkSleep(state); // Leaves - Lithium Sleeping Block Entity
|
|
}
|
|
|
|
private static void consumeFuel(final NonNullList<ItemStack> items, final ItemStack fuel) {
|
|
@@ -510,4 +512,53 @@ public abstract class AbstractFurnaceBlockEntity extends BaseContainerBlockEntit
|
|
this.getRecipesToAwardAndPopExperience(serverLevel, Vec3.atCenterOf(pos));
|
|
}
|
|
}
|
|
+
|
|
+ // Leaves start - Lithium Sleeping Block Entity
|
|
+ private net.minecraft.world.level.chunk.LevelChunk.RebindableTickingBlockEntityWrapper tickWrapper = null;
|
|
+ private TickingBlockEntity sleepingTicker = null;
|
|
+
|
|
+ @Override
|
|
+ public net.minecraft.world.level.chunk.LevelChunk.RebindableTickingBlockEntityWrapper lithium$getTickWrapper() {
|
|
+ return tickWrapper;
|
|
+ }
|
|
+
|
|
+ @Override
|
|
+ public void lithium$setTickWrapper(net.minecraft.world.level.chunk.LevelChunk.RebindableTickingBlockEntityWrapper tickWrapper) {
|
|
+ this.tickWrapper = tickWrapper;
|
|
+ this.lithium$setSleepingTicker(null);
|
|
+ }
|
|
+
|
|
+ @Override
|
|
+ public TickingBlockEntity lithium$getSleepingTicker() {
|
|
+ return sleepingTicker;
|
|
+ }
|
|
+
|
|
+ @Override
|
|
+ public void lithium$setSleepingTicker(TickingBlockEntity sleepingTicker) {
|
|
+ this.sleepingTicker = sleepingTicker;
|
|
+ }
|
|
+
|
|
+ private void checkSleep(BlockState state) {
|
|
+ if (this.litTimeRemaining <= 0 && this.cookingTimer == 0 && (state.is(net.minecraft.world.level.block.Blocks.FURNACE) || state.is(net.minecraft.world.level.block.Blocks.BLAST_FURNACE) || state.is(net.minecraft.world.level.block.Blocks.SMOKER)) && this.level != null) { // Leaves - Paper 26.1 fix
|
|
+ this.lithium$startSleeping();
|
|
+ }
|
|
+ }
|
|
+
|
|
+ @Override
|
|
+ public void lithium$handleSetChanged() {
|
|
+ if (this.isSleeping() && this.level != null && !this.level.isClientSide()) {
|
|
+ this.wakeUpNow();
|
|
+ }
|
|
+ }
|
|
+
|
|
+ @Override
|
|
+ public net.minecraft.core.NonNullList<net.minecraft.world.item.ItemStack> getInventoryLithium() {
|
|
+ return items;
|
|
+ }
|
|
+
|
|
+ @Override
|
|
+ public void setInventoryLithium(net.minecraft.core.NonNullList<net.minecraft.world.item.ItemStack> inventory) {
|
|
+ items = inventory;
|
|
+ }
|
|
+ // Leaves end - Lithium Sleeping Block Entity
|
|
}
|
|
diff --git a/net/minecraft/world/level/block/entity/BarrelBlockEntity.java b/net/minecraft/world/level/block/entity/BarrelBlockEntity.java
|
|
index 118af4e35eec652e7eb8a484a44652cfabc1bab5..fd2c62a4c9a9dbd81c3c4d1410694e5c6eea5d29 100644
|
|
--- a/net/minecraft/world/level/block/entity/BarrelBlockEntity.java
|
|
+++ b/net/minecraft/world/level/block/entity/BarrelBlockEntity.java
|
|
@@ -23,7 +23,7 @@ import net.minecraft.world.level.block.state.BlockState;
|
|
import net.minecraft.world.level.storage.ValueInput;
|
|
import net.minecraft.world.level.storage.ValueOutput;
|
|
|
|
-public class BarrelBlockEntity extends RandomizableContainerBlockEntity {
|
|
+public class BarrelBlockEntity extends RandomizableContainerBlockEntity implements org.leavesmc.leaves.lithium.common.block.entity.inventory_change_tracking.InventoryChangeTracker, org.leavesmc.leaves.lithium.api.inventory.LithiumInventory { // Leaves - Lithium Sleeping Block Entity
|
|
// CraftBukkit start - add fields and methods
|
|
public java.util.List<org.bukkit.entity.HumanEntity> transaction = new java.util.ArrayList<>();
|
|
private int maxStack = MAX_STACK;
|
|
@@ -129,6 +129,7 @@ public class BarrelBlockEntity extends RandomizableContainerBlockEntity {
|
|
@Override
|
|
protected void setItems(final NonNullList<ItemStack> items) {
|
|
this.items = items;
|
|
+ if (moe.monnairealms.camellia.config.modules.optimizations.LeavesSleepingBlockEntityConfig.enabled) this.lithium$emitStackListReplaced(); // Leaves - Lithium Sleeping Block Entity
|
|
}
|
|
|
|
@Override
|
|
@@ -180,4 +181,18 @@ public class BarrelBlockEntity extends RandomizableContainerBlockEntity {
|
|
double z = this.worldPosition.getZ() + 0.5 + direction.getZ() / 2.0;
|
|
this.level.playSound(null, x, y, z, event, SoundSource.BLOCKS, 0.5F, this.level.getRandom().nextFloat() * 0.1F + 0.9F);
|
|
}
|
|
+
|
|
+ // Leaves start - Lithium Sleeping Block Entity
|
|
+
|
|
+
|
|
+ @Override
|
|
+ public net.minecraft.core.NonNullList<net.minecraft.world.item.ItemStack> getInventoryLithium() {
|
|
+ return items;
|
|
+ }
|
|
+
|
|
+ @Override
|
|
+ public void setInventoryLithium(net.minecraft.core.NonNullList<net.minecraft.world.item.ItemStack> inventory) {
|
|
+ items = inventory;
|
|
+ }
|
|
+ // Leaves end - Lithium Sleeping Block Entity
|
|
}
|
|
diff --git a/net/minecraft/world/level/block/entity/BaseContainerBlockEntity.java b/net/minecraft/world/level/block/entity/BaseContainerBlockEntity.java
|
|
index 0e594121b60aa5a01b5bbe94b80350f2fc698b1a..f100d51275522748664592453c9c51cb627ef5bd 100644
|
|
--- a/net/minecraft/world/level/block/entity/BaseContainerBlockEntity.java
|
|
+++ b/net/minecraft/world/level/block/entity/BaseContainerBlockEntity.java
|
|
@@ -25,8 +25,17 @@ import net.minecraft.world.level.storage.ValueInput;
|
|
import net.minecraft.world.level.storage.ValueOutput;
|
|
import net.minecraft.world.phys.Vec3;
|
|
import org.jspecify.annotations.Nullable;
|
|
+// Leaves start - Lithium Sleeping Block Entity
|
|
+import it.unimi.dsi.fastutil.objects.ReferenceArraySet;
|
|
+import org.leavesmc.leaves.lithium.api.inventory.LithiumInventory;
|
|
+import org.leavesmc.leaves.lithium.common.block.entity.inventory_change_tracking.InventoryChangeEmitter;
|
|
+import org.leavesmc.leaves.lithium.common.block.entity.inventory_change_tracking.InventoryChangeListener;
|
|
+import org.leavesmc.leaves.lithium.common.block.entity.inventory_change_tracking.InventoryChangeTracker;
|
|
+import org.leavesmc.leaves.lithium.common.hopper.InventoryHelper;
|
|
+import org.leavesmc.leaves.lithium.common.hopper.LithiumStackList;
|
|
+// Leaves end - Lithium Sleeping Block Entity
|
|
|
|
-public abstract class BaseContainerBlockEntity extends BlockEntity implements Container, MenuProvider, Nameable {
|
|
+public abstract class BaseContainerBlockEntity extends BlockEntity implements Container, MenuProvider, Nameable, InventoryChangeEmitter { // Leaves - Lithium Sleeping Block Entity
|
|
public LockCode lockKey = LockCode.NO_LOCK;
|
|
public @Nullable Component name;
|
|
|
|
@@ -39,6 +48,7 @@ public abstract class BaseContainerBlockEntity extends BlockEntity implements Co
|
|
super.loadAdditional(input);
|
|
this.lockKey = LockCode.fromTag(input);
|
|
this.name = parseCustomNameSafe(input, "CustomName");
|
|
+ if (moe.monnairealms.camellia.config.modules.optimizations.LeavesSleepingBlockEntityConfig.enabled && this instanceof InventoryChangeTracker inventoryChangeTracker) inventoryChangeTracker.lithium$emitStackListReplaced(); // Leaves - Lithium Sleeping Block Entity
|
|
}
|
|
|
|
@Override
|
|
@@ -183,4 +193,98 @@ public abstract class BaseContainerBlockEntity extends BlockEntity implements Co
|
|
return org.bukkit.craftbukkit.util.CraftLocation.toBukkit(this.worldPosition, this.level);
|
|
}
|
|
// CraftBukkit end
|
|
+
|
|
+ // Leaves start - Lithium Sleeping Block Entity
|
|
+ ReferenceArraySet<InventoryChangeListener> inventoryChangeListeners = null;
|
|
+ ReferenceArraySet<InventoryChangeListener> inventoryHandlingTypeListeners = null;
|
|
+
|
|
+ @Override
|
|
+ public void lithium$emitContentModified() {
|
|
+ ReferenceArraySet<InventoryChangeListener> inventoryChangeListeners = this.inventoryChangeListeners;
|
|
+ if (inventoryChangeListeners != null) {
|
|
+ for (InventoryChangeListener inventoryChangeListener : inventoryChangeListeners) {
|
|
+ inventoryChangeListener.lithium$handleInventoryContentModified(this);
|
|
+ }
|
|
+ inventoryChangeListeners.clear();
|
|
+ }
|
|
+ }
|
|
+
|
|
+ @Override
|
|
+ public void lithium$emitStackListReplaced() {
|
|
+ ReferenceArraySet<InventoryChangeListener> listeners = this.inventoryHandlingTypeListeners;
|
|
+ if (listeners != null && !listeners.isEmpty()) {
|
|
+ for (InventoryChangeListener inventoryChangeListener : listeners) {
|
|
+ inventoryChangeListener.handleStackListReplaced(this);
|
|
+ }
|
|
+ listeners.clear();
|
|
+ }
|
|
+
|
|
+ if (this instanceof InventoryChangeListener listener) {
|
|
+ listener.handleStackListReplaced(this);
|
|
+ }
|
|
+
|
|
+ this.invalidateChangeListening();
|
|
+ }
|
|
+
|
|
+ @Override
|
|
+ public void lithium$emitRemoved() {
|
|
+ ReferenceArraySet<InventoryChangeListener> listeners = this.inventoryHandlingTypeListeners;
|
|
+ if (listeners != null && !listeners.isEmpty()) {
|
|
+ for (InventoryChangeListener listener : listeners) {
|
|
+ listener.lithium$handleInventoryRemoved(this);
|
|
+ }
|
|
+ listeners.clear();
|
|
+ }
|
|
+
|
|
+ if (this instanceof InventoryChangeListener listener) {
|
|
+ listener.lithium$handleInventoryRemoved(this);
|
|
+ }
|
|
+
|
|
+ this.invalidateChangeListening();
|
|
+ }
|
|
+
|
|
+ private void invalidateChangeListening() {
|
|
+ if (this.inventoryChangeListeners != null) {
|
|
+ this.inventoryChangeListeners.clear();
|
|
+ }
|
|
+
|
|
+ LithiumStackList lithiumStackList = this instanceof LithiumInventory ? InventoryHelper.getLithiumStackListOrNull((LithiumInventory) this) : null;
|
|
+ if (lithiumStackList != null && this instanceof InventoryChangeTracker inventoryChangeTracker) {
|
|
+ lithiumStackList.removeInventoryModificationCallback(inventoryChangeTracker);
|
|
+ }
|
|
+ }
|
|
+
|
|
+ @Override
|
|
+ public void lithium$emitFirstComparatorAdded() {
|
|
+ ReferenceArraySet<InventoryChangeListener> inventoryChangeListeners = this.inventoryChangeListeners;
|
|
+ if (inventoryChangeListeners != null && !inventoryChangeListeners.isEmpty()) {
|
|
+ inventoryChangeListeners.removeIf(inventoryChangeListener -> inventoryChangeListener.lithium$handleComparatorAdded(this));
|
|
+ }
|
|
+ }
|
|
+
|
|
+ @Override
|
|
+ public void lithium$forwardContentChangeOnce(InventoryChangeListener inventoryChangeListener, LithiumStackList stackList, InventoryChangeTracker thisTracker) {
|
|
+ if (this.inventoryChangeListeners == null) {
|
|
+ this.inventoryChangeListeners = new ReferenceArraySet<>(1);
|
|
+ }
|
|
+ stackList.setInventoryModificationCallback(thisTracker);
|
|
+ this.inventoryChangeListeners.add(inventoryChangeListener);
|
|
+
|
|
+ }
|
|
+
|
|
+ @Override
|
|
+ public void lithium$forwardMajorInventoryChanges(InventoryChangeListener inventoryChangeListener) {
|
|
+ if (this.inventoryHandlingTypeListeners == null) {
|
|
+ this.inventoryHandlingTypeListeners = new ReferenceArraySet<>(1);
|
|
+ }
|
|
+ this.inventoryHandlingTypeListeners.add(inventoryChangeListener);
|
|
+ }
|
|
+
|
|
+ @Override
|
|
+ public void lithium$stopForwardingMajorInventoryChanges(InventoryChangeListener inventoryChangeListener) {
|
|
+ if (this.inventoryHandlingTypeListeners != null) {
|
|
+ this.inventoryHandlingTypeListeners.remove(inventoryChangeListener);
|
|
+ }
|
|
+ }
|
|
+ // Leaves end - Lithium Sleeping Block Entity
|
|
}
|
|
diff --git a/net/minecraft/world/level/block/entity/BlockEntity.java b/net/minecraft/world/level/block/entity/BlockEntity.java
|
|
index 2887cbaa954771d0fe357d8ec8df75073e9afa91..69227ca2534a3abe3be3d5c704335bc5397e2d20 100644
|
|
--- a/net/minecraft/world/level/block/entity/BlockEntity.java
|
|
+++ b/net/minecraft/world/level/block/entity/BlockEntity.java
|
|
@@ -37,8 +37,16 @@ import net.minecraft.world.level.storage.ValueInput;
|
|
import net.minecraft.world.level.storage.ValueOutput;
|
|
import org.jspecify.annotations.Nullable;
|
|
import org.slf4j.Logger;
|
|
-
|
|
-public abstract class BlockEntity implements DebugValueSource, TypedInstance<BlockEntityType<?>> {
|
|
+// Leaves start - Lithium Sleeping Block Entity
|
|
+import net.minecraft.core.Direction;
|
|
+import org.leavesmc.leaves.lithium.common.block.entity.inventory_comparator_tracking.ComparatorTracker;
|
|
+import org.leavesmc.leaves.lithium.common.block.entity.inventory_comparator_tracking.ComparatorTracking;
|
|
+import org.leavesmc.leaves.lithium.common.block.entity.inventory_change_tracking.InventoryChangeTracker;
|
|
+import org.leavesmc.leaves.lithium.common.block.entity.SetBlockStateHandlingBlockEntity;
|
|
+import org.leavesmc.leaves.lithium.common.block.entity.SetChangedHandlingBlockEntity;
|
|
+// Leaves end - Lithium Sleeping Block Entity
|
|
+
|
|
+public abstract class BlockEntity implements DebugValueSource, TypedInstance<BlockEntityType<?>>, ComparatorTracker, SetBlockStateHandlingBlockEntity, SetChangedHandlingBlockEntity { // Leaves - Lithium Sleeping Block Entity
|
|
static final ThreadLocal<Boolean> IGNORE_TILE_UPDATES = ThreadLocal.withInitial(() -> Boolean.FALSE); // Paper - Perf: Optimize Hoppers // Folia - region threading
|
|
// CraftBukkit start - data containers
|
|
private static final org.bukkit.craftbukkit.persistence.CraftPersistentDataTypeRegistry DATA_TYPE_REGISTRY = new org.bukkit.craftbukkit.persistence.CraftPersistentDataTypeRegistry();
|
|
@@ -65,6 +73,7 @@ public abstract class BlockEntity implements DebugValueSource, TypedInstance<Blo
|
|
this.validateBlockState(blockState);
|
|
this.blockState = blockState;
|
|
this.persistentDataContainer = new org.bukkit.craftbukkit.persistence.CraftPersistentDataContainer(DATA_TYPE_REGISTRY); // Paper - always init
|
|
+ this.hasComparators = UNKNOWN; // Leaves - Lithium Sleeping Block Entity
|
|
}
|
|
|
|
private void validateBlockState(final BlockState blockState) {
|
|
@@ -218,6 +227,7 @@ public abstract class BlockEntity implements DebugValueSource, TypedInstance<Blo
|
|
if (this.level != null) {
|
|
if (IGNORE_TILE_UPDATES.get().booleanValue()) return; // Paper - Perf: Optimize Hoppers // Folia - region threading
|
|
setChanged(this.level, this.worldPosition, this.blockState);
|
|
+ if (moe.monnairealms.camellia.config.modules.optimizations.LeavesSleepingBlockEntityConfig.enabled) lithium$handleSetChanged(); // Leaves - Lithium Sleeping Block Entity
|
|
}
|
|
}
|
|
|
|
@@ -249,7 +259,9 @@ public abstract class BlockEntity implements DebugValueSource, TypedInstance<Blo
|
|
}
|
|
|
|
public void setRemoved() {
|
|
+ this.hasComparators = UNKNOWN; // Leaves - Lithium Sleeping Block Entity
|
|
this.remove = true;
|
|
+ if (moe.monnairealms.camellia.config.modules.optimizations.LeavesSleepingBlockEntityConfig.enabled && this.level != null && !this.level.isClientSide() && this instanceof InventoryChangeTracker inventoryChangeTracker) inventoryChangeTracker.lithium$emitRemoved(); // Leaves - Lithium Sleeping Block Entity
|
|
}
|
|
|
|
public void clearRemoved() {
|
|
@@ -294,6 +306,7 @@ public abstract class BlockEntity implements DebugValueSource, TypedInstance<Blo
|
|
public void setBlockState(final BlockState blockState) {
|
|
this.validateBlockState(blockState);
|
|
this.blockState = blockState;
|
|
+ if (moe.monnairealms.camellia.config.modules.optimizations.LeavesSleepingBlockEntityConfig.enabled) this.lithium$handleSetBlockState(); // Leaves - Lithium Sleeping Block Entity
|
|
}
|
|
|
|
protected void applyImplicitComponents(final DataComponentGetter components) {
|
|
@@ -396,4 +409,32 @@ public abstract class BlockEntity implements DebugValueSource, TypedInstance<Blo
|
|
return this.blockEntity.getNameForReporting() + "@" + this.blockEntity.getBlockPos();
|
|
}
|
|
}
|
|
+
|
|
+ // Leaves start - Lithium Sleeping Block Entity
|
|
+ private static final byte UNKNOWN = (byte) -1;
|
|
+ private static final byte COMPARATOR_PRESENT = (byte) 1;
|
|
+ private static final byte COMPARATOR_ABSENT = (byte) 0;
|
|
+
|
|
+ byte hasComparators;
|
|
+
|
|
+ @Override
|
|
+ public void lithium$onComparatorAdded(Direction direction, int offset) {
|
|
+ byte hasComparators = this.hasComparators;
|
|
+ if (direction.getAxis() != Direction.Axis.Y && hasComparators != COMPARATOR_PRESENT && offset >= 1 && offset <= 2) {
|
|
+ this.hasComparators = COMPARATOR_PRESENT;
|
|
+
|
|
+ if (this instanceof InventoryChangeTracker inventoryChangeTracker) {
|
|
+ inventoryChangeTracker.lithium$emitFirstComparatorAdded();
|
|
+ }
|
|
+ }
|
|
+ }
|
|
+
|
|
+ @Override
|
|
+ public boolean lithium$hasAnyComparatorNearby() {
|
|
+ if (this.hasComparators == UNKNOWN) {
|
|
+ this.hasComparators = ComparatorTracking.findNearbyComparators(this.level, this.worldPosition) ? COMPARATOR_PRESENT : COMPARATOR_ABSENT;
|
|
+ }
|
|
+ return this.hasComparators == COMPARATOR_PRESENT;
|
|
+ }
|
|
+ // Leaves end - Lithium Sleeping Block Entity
|
|
}
|
|
diff --git a/net/minecraft/world/level/block/entity/BrewingStandBlockEntity.java b/net/minecraft/world/level/block/entity/BrewingStandBlockEntity.java
|
|
index 5d26efb1feb1fd7d0f3bcc0fd7678b303518312a..bd320bcaa7964bf5532c6cb9634a5227e6859d1a 100644
|
|
--- a/net/minecraft/world/level/block/entity/BrewingStandBlockEntity.java
|
|
+++ b/net/minecraft/world/level/block/entity/BrewingStandBlockEntity.java
|
|
@@ -27,7 +27,7 @@ import net.minecraft.world.level.storage.ValueInput;
|
|
import net.minecraft.world.level.storage.ValueOutput;
|
|
import org.jspecify.annotations.Nullable;
|
|
|
|
-public class BrewingStandBlockEntity extends BaseContainerBlockEntity implements WorldlyContainer {
|
|
+public class BrewingStandBlockEntity extends BaseContainerBlockEntity implements WorldlyContainer, org.leavesmc.leaves.lithium.common.block.entity.inventory_change_tracking.InventoryChangeTracker, org.leavesmc.leaves.lithium.common.block.entity.SleepingBlockEntity, org.leavesmc.leaves.lithium.common.block.entity.SetChangedHandlingBlockEntity, org.leavesmc.leaves.lithium.api.inventory.LithiumInventory { // Leaves - Lithium Sleeping Block Entity
|
|
private static final int INGREDIENT_SLOT = 3;
|
|
private static final int FUEL_SLOT = 4;
|
|
private static final int[] SLOTS_FOR_UP = new int[]{3};
|
|
@@ -139,6 +139,7 @@ public class BrewingStandBlockEntity extends BaseContainerBlockEntity implements
|
|
}
|
|
|
|
public static void serverTick(final Level level, final BlockPos pos, final BlockState selfState, final BrewingStandBlockEntity entity) {
|
|
+ if (moe.monnairealms.camellia.config.modules.optimizations.LeavesSleepingBlockEntityConfig.enabled) entity.checkSleep(selfState); // Leaves - Lithium Sleeping Block Entity
|
|
ItemStack fuel = entity.items.get(4);
|
|
if (entity.fuel <= 0 && fuel.is(ItemTags.BREWING_FUEL)) {
|
|
// CraftBukkit start
|
|
@@ -156,6 +157,7 @@ public class BrewingStandBlockEntity extends BaseContainerBlockEntity implements
|
|
fuel.shrink(1);
|
|
}
|
|
// CraftBukkit end
|
|
+ if (moe.monnairealms.camellia.config.modules.optimizations.LeavesSleepingBlockEntityConfig.enabled) entity.wakeUpNow(); // Leaves - Lithium Sleeping Block Entity
|
|
setChanged(level, pos, selfState);
|
|
}
|
|
|
|
@@ -170,7 +172,7 @@ public class BrewingStandBlockEntity extends BaseContainerBlockEntity implements
|
|
} else if (!brewable || !ingredient.is(entity.ingredient)) {
|
|
entity.brewTime = 0;
|
|
}
|
|
-
|
|
+ if (moe.monnairealms.camellia.config.modules.optimizations.LeavesSleepingBlockEntityConfig.enabled) entity.wakeUpNow(); // Leaves - Lithium Sleeping Block Entity
|
|
setChanged(level, pos, selfState);
|
|
} else if (brewable && entity.fuel > 0) {
|
|
entity.fuel--;
|
|
@@ -183,6 +185,7 @@ public class BrewingStandBlockEntity extends BaseContainerBlockEntity implements
|
|
entity.brewTime = event.getBrewingTime(); // 400 -> event.getTotalBrewTime() // Paper - use brewing time from event
|
|
// CraftBukkit end
|
|
entity.ingredient = ingredient.getItem();
|
|
+ if (moe.monnairealms.camellia.config.modules.optimizations.LeavesSleepingBlockEntityConfig.enabled) entity.wakeUpNow(); // Leaves - Lithium Sleeping Block Entity
|
|
setChanged(level, pos, selfState);
|
|
}
|
|
|
|
@@ -291,6 +294,7 @@ public class BrewingStandBlockEntity extends BaseContainerBlockEntity implements
|
|
}
|
|
|
|
this.fuel = input.getByteOr("Fuel", (byte)0);
|
|
+ if (moe.monnairealms.camellia.config.modules.optimizations.LeavesSleepingBlockEntityConfig.enabled && this.isSleeping() && this.level != null) this.wakeUpNow(); // Leaves - Lithium Sleeping Block Entity
|
|
}
|
|
|
|
@Override
|
|
@@ -337,4 +341,53 @@ public class BrewingStandBlockEntity extends BaseContainerBlockEntity implements
|
|
protected AbstractContainerMenu createMenu(final int containerId, final Inventory inventory) {
|
|
return new BrewingStandMenu(containerId, inventory, this, this.dataAccess);
|
|
}
|
|
+
|
|
+ // Leaves start - Lithium Sleeping Block Entity
|
|
+ private net.minecraft.world.level.chunk.LevelChunk.RebindableTickingBlockEntityWrapper tickWrapper = null;
|
|
+ private TickingBlockEntity sleepingTicker = null;
|
|
+
|
|
+ @Override
|
|
+ public net.minecraft.world.level.chunk.LevelChunk.RebindableTickingBlockEntityWrapper lithium$getTickWrapper() {
|
|
+ return tickWrapper;
|
|
+ }
|
|
+
|
|
+ @Override
|
|
+ public void lithium$setTickWrapper(net.minecraft.world.level.chunk.LevelChunk.RebindableTickingBlockEntityWrapper tickWrapper) {
|
|
+ this.tickWrapper = tickWrapper;
|
|
+ this.lithium$setSleepingTicker(null);
|
|
+ }
|
|
+
|
|
+ @Override
|
|
+ public TickingBlockEntity lithium$getSleepingTicker() {
|
|
+ return sleepingTicker;
|
|
+ }
|
|
+
|
|
+ @Override
|
|
+ public void lithium$setSleepingTicker(TickingBlockEntity sleepingTicker) {
|
|
+ this.sleepingTicker = sleepingTicker;
|
|
+ }
|
|
+
|
|
+ private void checkSleep(BlockState state) {
|
|
+ if (this.brewTime == 0 && state.is(net.minecraft.world.level.block.Blocks.BREWING_STAND) && this.level != null) {
|
|
+ this.lithium$startSleeping();
|
|
+ }
|
|
+ }
|
|
+
|
|
+ @Override
|
|
+ public void lithium$handleSetChanged() {
|
|
+ if (this.isSleeping() && this.level != null) {
|
|
+ this.wakeUpNow();
|
|
+ }
|
|
+ }
|
|
+
|
|
+ @Override
|
|
+ public net.minecraft.core.NonNullList<net.minecraft.world.item.ItemStack> getInventoryLithium() {
|
|
+ return items;
|
|
+ }
|
|
+
|
|
+ @Override
|
|
+ public void setInventoryLithium(net.minecraft.core.NonNullList<net.minecraft.world.item.ItemStack> inventory) {
|
|
+ items = inventory;
|
|
+ }
|
|
+ // Leaves end - Lithium Sleeping Block Entity
|
|
}
|
|
diff --git a/net/minecraft/world/level/block/entity/CampfireBlockEntity.java b/net/minecraft/world/level/block/entity/CampfireBlockEntity.java
|
|
index 64d0d60d9025de2b5eb16b31c6437372d4c20c5e..54070ae70b1d4a6ed4fd51ba758dead40275864e 100644
|
|
--- a/net/minecraft/world/level/block/entity/CampfireBlockEntity.java
|
|
+++ b/net/minecraft/world/level/block/entity/CampfireBlockEntity.java
|
|
@@ -39,7 +39,7 @@ import net.minecraft.world.level.storage.ValueOutput;
|
|
import org.jspecify.annotations.Nullable;
|
|
import org.slf4j.Logger;
|
|
|
|
-public class CampfireBlockEntity extends BlockEntity implements Clearable {
|
|
+public class CampfireBlockEntity extends BlockEntity implements Clearable, org.leavesmc.leaves.lithium.common.block.entity.SleepingBlockEntity { // Leaves - Lithium Sleeping Block Entity
|
|
private static final Logger LOGGER = LogUtils.getLogger();
|
|
private static final int BURN_COOL_SPEED = 2;
|
|
private static final int NUM_SLOTS = 4;
|
|
@@ -111,7 +111,7 @@ public class CampfireBlockEntity extends BlockEntity implements Clearable {
|
|
|
|
if (changed) {
|
|
setChanged(level, pos, state);
|
|
- }
|
|
+ } else if (moe.monnairealms.camellia.config.modules.optimizations.LeavesSleepingBlockEntityConfig.enabled) entity.lithium$startSleeping(); // Leaves - Lithium Sleeping Block Entity
|
|
}
|
|
|
|
public static void cooldownTick(final Level level, final BlockPos pos, final BlockState state, final CampfireBlockEntity entity) {
|
|
@@ -126,7 +126,7 @@ public class CampfireBlockEntity extends BlockEntity implements Clearable {
|
|
|
|
if (changed) {
|
|
setChanged(level, pos, state);
|
|
- }
|
|
+ } else if (moe.monnairealms.camellia.config.modules.optimizations.LeavesSleepingBlockEntityConfig.enabled) entity.lithium$startSleeping(); // Leaves - Lithium Sleeping Block Entity
|
|
}
|
|
|
|
public static void particleTick(final Level level, final BlockPos pos, final BlockState state, final CampfireBlockEntity entity) {
|
|
@@ -183,6 +183,7 @@ public class CampfireBlockEntity extends BlockEntity implements Clearable {
|
|
System.arraycopy(cookingState, 0, this.stopCooking, 0, Math.min(this.stopCooking.length, bytes.capacity()));
|
|
});
|
|
// Paper end - Add more Campfire API
|
|
+ if (moe.monnairealms.camellia.config.modules.optimizations.LeavesSleepingBlockEntityConfig.enabled) this.wakeUpNow(); // Leaves - Lithium Sleeping Block Entity
|
|
}
|
|
|
|
@Override
|
|
@@ -234,6 +235,7 @@ public class CampfireBlockEntity extends BlockEntity implements Clearable {
|
|
this.cookingTime[slot] = event.getTotalCookTime(); // recipe.get().value().cookingTime() -> event.getTotalCookTime()
|
|
// CraftBukkit end
|
|
this.cookingProgress[slot] = 0;
|
|
+ if (moe.monnairealms.camellia.config.modules.optimizations.LeavesSleepingBlockEntityConfig.enabled) this.wakeUpNow(); // Leaves - Lithium Sleeping Block Entity
|
|
this.items.set(slot, placeItem.consumeAndReturn(1, sourceEntity));
|
|
serverLevel.gameEvent(GameEvent.BLOCK_CHANGE, this.getBlockPos(), GameEvent.Context.of(sourceEntity, this.getBlockState()));
|
|
this.markUpdated();
|
|
@@ -277,4 +279,30 @@ public class CampfireBlockEntity extends BlockEntity implements Clearable {
|
|
public void removeComponentsFromTag(final ValueOutput output) {
|
|
output.discard("Items");
|
|
}
|
|
+
|
|
+ // Leaves start - Lithium Sleeping Block Entity
|
|
+ private net.minecraft.world.level.chunk.LevelChunk.RebindableTickingBlockEntityWrapper tickWrapper = null;
|
|
+ private TickingBlockEntity sleepingTicker = null;
|
|
+
|
|
+ @Override
|
|
+ public net.minecraft.world.level.chunk.LevelChunk.RebindableTickingBlockEntityWrapper lithium$getTickWrapper() {
|
|
+ return tickWrapper;
|
|
+ }
|
|
+
|
|
+ @Override
|
|
+ public void lithium$setTickWrapper(net.minecraft.world.level.chunk.LevelChunk.RebindableTickingBlockEntityWrapper tickWrapper) {
|
|
+ this.tickWrapper = tickWrapper;
|
|
+ this.lithium$setSleepingTicker(null);
|
|
+ }
|
|
+
|
|
+ @Override
|
|
+ public TickingBlockEntity lithium$getSleepingTicker() {
|
|
+ return sleepingTicker;
|
|
+ }
|
|
+
|
|
+ @Override
|
|
+ public void lithium$setSleepingTicker(TickingBlockEntity sleepingTicker) {
|
|
+ this.sleepingTicker = sleepingTicker;
|
|
+ }
|
|
+ // Leaves end - Lithium Sleeping Block Entity
|
|
}
|
|
diff --git a/net/minecraft/world/level/block/entity/ChestBlockEntity.java b/net/minecraft/world/level/block/entity/ChestBlockEntity.java
|
|
index a9273aebb5c8efe78e88158f11e1ee2af0dff3f1..c0d636ebe2fd9f2c63c1b9cb62ba257bd545de36 100644
|
|
--- a/net/minecraft/world/level/block/entity/ChestBlockEntity.java
|
|
+++ b/net/minecraft/world/level/block/entity/ChestBlockEntity.java
|
|
@@ -25,7 +25,7 @@ import net.minecraft.world.level.block.state.properties.ChestType;
|
|
import net.minecraft.world.level.storage.ValueInput;
|
|
import net.minecraft.world.level.storage.ValueOutput;
|
|
|
|
-public class ChestBlockEntity extends RandomizableContainerBlockEntity implements LidBlockEntity {
|
|
+public class ChestBlockEntity extends RandomizableContainerBlockEntity implements LidBlockEntity, org.leavesmc.leaves.lithium.common.block.entity.inventory_change_tracking.InventoryChangeTracker, org.leavesmc.leaves.lithium.common.block.entity.inventory_change_tracking.InventoryChangeEmitter, org.leavesmc.leaves.lithium.common.block.entity.SetBlockStateHandlingBlockEntity, org.leavesmc.leaves.lithium.common.block.entity.SleepingBlockEntity, org.leavesmc.leaves.lithium.api.inventory.LithiumInventory { // Leaves - Lithium Sleeping Block Entity
|
|
private static final int EVENT_SET_OPEN_COUNT = 1;
|
|
public static final Component DEFAULT_NAME = Component.translatable("container.chest");
|
|
private NonNullList<ItemStack> items = NonNullList.withSize(27, ItemStack.EMPTY);
|
|
@@ -140,6 +140,7 @@ public class ChestBlockEntity extends RandomizableContainerBlockEntity implement
|
|
|
|
public static void lidAnimateTick(final Level level, final BlockPos pos, final BlockState state, final ChestBlockEntity entity) {
|
|
entity.chestLidController.tickLid();
|
|
+ if (moe.monnairealms.camellia.config.modules.optimizations.LeavesSleepingBlockEntityConfig.enabled) entity.checkSleep(); // Leaves - Lithium Sleeping Block Entity
|
|
}
|
|
|
|
public static void playSound(final Level level, final BlockPos worldPosition, final BlockState blockState, final SoundEvent event) {
|
|
@@ -161,6 +162,7 @@ public class ChestBlockEntity extends RandomizableContainerBlockEntity implement
|
|
@Override
|
|
public boolean triggerEvent(final int b0, final int b1) {
|
|
if (b0 == EVENT_SET_OPEN_COUNT) {
|
|
+ if (moe.monnairealms.camellia.config.modules.optimizations.LeavesSleepingBlockEntityConfig.enabled && this.sleepingTicker != null) this.wakeUpNow(); // Leaves - Lithium Sleeping Block Entity
|
|
this.chestLidController.shouldBeOpen(b1 > 0);
|
|
return true;
|
|
} else {
|
|
@@ -198,6 +200,7 @@ public class ChestBlockEntity extends RandomizableContainerBlockEntity implement
|
|
@Override
|
|
protected void setItems(final NonNullList<ItemStack> items) {
|
|
this.items = items;
|
|
+ if (moe.monnairealms.camellia.config.modules.optimizations.LeavesSleepingBlockEntityConfig.enabled) this.lithium$emitStackListReplaced(); // Leaves - Lithium Sleeping Block Entity
|
|
}
|
|
|
|
@Override
|
|
@@ -233,4 +236,52 @@ public class ChestBlockEntity extends RandomizableContainerBlockEntity implement
|
|
Block block = blockState.getBlock();
|
|
level.blockEvent(pos, block, EVENT_SET_OPEN_COUNT, current);
|
|
}
|
|
+
|
|
+ // Leaves start - Lithium Sleeping Block Entity
|
|
+ private net.minecraft.world.level.chunk.LevelChunk.RebindableTickingBlockEntityWrapper tickWrapper = null;
|
|
+ private TickingBlockEntity sleepingTicker = null;
|
|
+
|
|
+ private void checkSleep() {
|
|
+ //If the animation is finished, it will stay unchanged until the next triggerEvent, which may change shouldBeOpen
|
|
+ if (this.getOpenNess(0.0F) == this.getOpenNess(1.0F)) {
|
|
+ this.lithium$startSleeping();
|
|
+ }
|
|
+ }
|
|
+
|
|
+ @Override
|
|
+ public net.minecraft.world.level.chunk.LevelChunk.RebindableTickingBlockEntityWrapper lithium$getTickWrapper() {
|
|
+ return this.tickWrapper;
|
|
+ }
|
|
+
|
|
+ @Override
|
|
+ public void lithium$setTickWrapper(net.minecraft.world.level.chunk.LevelChunk.RebindableTickingBlockEntityWrapper tickWrapper) {
|
|
+ this.tickWrapper = tickWrapper;
|
|
+ }
|
|
+
|
|
+ @Override
|
|
+ public TickingBlockEntity lithium$getSleepingTicker() {
|
|
+ return this.sleepingTicker;
|
|
+ }
|
|
+
|
|
+ @Override
|
|
+ public void lithium$setSleepingTicker(TickingBlockEntity sleepingTicker) {
|
|
+ this.sleepingTicker = sleepingTicker;
|
|
+ }
|
|
+
|
|
+ @Override
|
|
+ public void lithium$handleSetBlockState() {
|
|
+ //Handle switching double / single chest state
|
|
+ this.lithium$emitRemoved();
|
|
+ }
|
|
+
|
|
+ @Override
|
|
+ public net.minecraft.core.NonNullList<net.minecraft.world.item.ItemStack> getInventoryLithium() {
|
|
+ return items;
|
|
+ }
|
|
+
|
|
+ @Override
|
|
+ public void setInventoryLithium(net.minecraft.core.NonNullList<net.minecraft.world.item.ItemStack> inventory) {
|
|
+ items = inventory;
|
|
+ }
|
|
+ // Leaves end - Lithium Sleeping Block Entity
|
|
}
|
|
diff --git a/net/minecraft/world/level/block/entity/ChiseledBookShelfBlockEntity.java b/net/minecraft/world/level/block/entity/ChiseledBookShelfBlockEntity.java
|
|
index 8697f4d589766163a56b0de5be4fad999d09f809..19db4302ca6f1b3f2f86aef34f0d80229fb1ace8 100644
|
|
--- a/net/minecraft/world/level/block/entity/ChiseledBookShelfBlockEntity.java
|
|
+++ b/net/minecraft/world/level/block/entity/ChiseledBookShelfBlockEntity.java
|
|
@@ -22,7 +22,7 @@ import net.minecraft.world.level.storage.ValueInput;
|
|
import net.minecraft.world.level.storage.ValueOutput;
|
|
import org.slf4j.Logger;
|
|
|
|
-public class ChiseledBookShelfBlockEntity extends BlockEntity implements ListBackedContainer {
|
|
+public class ChiseledBookShelfBlockEntity extends BlockEntity implements ListBackedContainer, org.leavesmc.leaves.lithium.api.inventory.LithiumTransferConditionInventory { // Leaves - Lithium Sleeping Block Entity
|
|
public static final int MAX_BOOKS_IN_STORAGE = 6;
|
|
private static final Logger LOGGER = LogUtils.getLogger();
|
|
private static final int DEFAULT_LAST_INTERACTED_SLOT = -1;
|
|
@@ -171,4 +171,6 @@ public class ChiseledBookShelfBlockEntity extends BlockEntity implements ListBac
|
|
public void removeComponentsFromTag(final ValueOutput output) {
|
|
output.discard("Items");
|
|
}
|
|
+
|
|
+ @Override public boolean lithium$itemInsertionTestRequiresStackSize1() {return true;} // Leaves - Lithium Sleeping Block Entity
|
|
}
|
|
diff --git a/net/minecraft/world/level/block/entity/CrafterBlockEntity.java b/net/minecraft/world/level/block/entity/CrafterBlockEntity.java
|
|
index 02d86d0675de22546a225dd6eaac5875eba0ce54..d3aff67c70b7c69daf6c6674325b26a41b780920 100644
|
|
--- a/net/minecraft/world/level/block/entity/CrafterBlockEntity.java
|
|
+++ b/net/minecraft/world/level/block/entity/CrafterBlockEntity.java
|
|
@@ -23,7 +23,7 @@ import net.minecraft.world.level.block.state.BlockState;
|
|
import net.minecraft.world.level.storage.ValueInput;
|
|
import net.minecraft.world.level.storage.ValueOutput;
|
|
|
|
-public class CrafterBlockEntity extends RandomizableContainerBlockEntity implements CraftingContainer {
|
|
+public class CrafterBlockEntity extends RandomizableContainerBlockEntity implements CraftingContainer, org.leavesmc.leaves.lithium.common.block.entity.SleepingBlockEntity, org.leavesmc.leaves.lithium.common.block.entity.SetChangedHandlingBlockEntity { // Leaves - Lithium Sleeping Block Entity
|
|
public static final int CONTAINER_WIDTH = 3;
|
|
public static final int CONTAINER_HEIGHT = 3;
|
|
public static final int CONTAINER_SIZE = 9;
|
|
@@ -171,6 +171,7 @@ public class CrafterBlockEntity extends RandomizableContainerBlockEntity impleme
|
|
}
|
|
});
|
|
this.containerData.set(9, input.getIntOr("triggered", 0));
|
|
+ if (moe.monnairealms.camellia.config.modules.optimizations.LeavesSleepingBlockEntityConfig.enabled && this.isSleeping() && this.level != null) this.wakeUpNow(); // Leaves - Lithium Sleeping Block Entity
|
|
}
|
|
|
|
@Override
|
|
@@ -280,10 +281,12 @@ public class CrafterBlockEntity extends RandomizableContainerBlockEntity impleme
|
|
level.setBlock(blockPos, blockState.setValue(CrafterBlock.CRAFTING, false), Block.UPDATE_ALL);
|
|
}
|
|
}
|
|
+ if (moe.monnairealms.camellia.config.modules.optimizations.LeavesSleepingBlockEntityConfig.enabled && craftingTicksRemaining < 0) entity.checkSleep(); // Leaves - Lithium Sleeping Block Entity
|
|
}
|
|
|
|
public void setCraftingTicksRemaining(final int maxCraftingTicks) {
|
|
this.craftingTicksRemaining = maxCraftingTicks;
|
|
+ if (moe.monnairealms.camellia.config.modules.optimizations.LeavesSleepingBlockEntityConfig.enabled && this.isSleeping() && this.level != null) this.wakeUpNow(); // Leaves - Lithium Sleeping Block Entity
|
|
}
|
|
|
|
public int getRedstoneSignal() {
|
|
@@ -302,4 +305,43 @@ public class CrafterBlockEntity extends RandomizableContainerBlockEntity impleme
|
|
private boolean slotCanBeDisabled(final int slotId) {
|
|
return slotId > -1 && slotId < 9 && this.items.get(slotId).isEmpty();
|
|
}
|
|
+
|
|
+ // Leaves start - Lithium Sleeping Block Entity
|
|
+ private net.minecraft.world.level.chunk.LevelChunk.RebindableTickingBlockEntityWrapper tickWrapper = null;
|
|
+ private TickingBlockEntity sleepingTicker = null;
|
|
+
|
|
+ @Override
|
|
+ public net.minecraft.world.level.chunk.LevelChunk.RebindableTickingBlockEntityWrapper lithium$getTickWrapper() {
|
|
+ return this.tickWrapper;
|
|
+ }
|
|
+
|
|
+ @Override
|
|
+ public void lithium$setTickWrapper(net.minecraft.world.level.chunk.LevelChunk.RebindableTickingBlockEntityWrapper tickWrapper) {
|
|
+ this.tickWrapper = tickWrapper;
|
|
+ this.lithium$setSleepingTicker(null);
|
|
+ }
|
|
+
|
|
+ @Override
|
|
+ public TickingBlockEntity lithium$getSleepingTicker() {
|
|
+ return this.sleepingTicker;
|
|
+ }
|
|
+
|
|
+ @Override
|
|
+ public void lithium$setSleepingTicker(TickingBlockEntity sleepingTicker) {
|
|
+ this.sleepingTicker = sleepingTicker;
|
|
+ }
|
|
+
|
|
+ private void checkSleep() {
|
|
+ if (this.craftingTicksRemaining == 0) {
|
|
+ this.lithium$startSleeping();
|
|
+ }
|
|
+ }
|
|
+
|
|
+ @Override
|
|
+ public void lithium$handleSetChanged() {
|
|
+ if (this.isSleeping() && this.level != null && !this.level.isClientSide()) {
|
|
+ this.wakeUpNow();
|
|
+ }
|
|
+ }
|
|
+ // Leaves end - Lithium Sleeping Block Entity
|
|
}
|
|
diff --git a/net/minecraft/world/level/block/entity/DispenserBlockEntity.java b/net/minecraft/world/level/block/entity/DispenserBlockEntity.java
|
|
index 736f5fd76f4a86ab16740904b5c0823413d65cd2..8995d91aed44b8c7933eaf0111332d83e9789817 100644
|
|
--- a/net/minecraft/world/level/block/entity/DispenserBlockEntity.java
|
|
+++ b/net/minecraft/world/level/block/entity/DispenserBlockEntity.java
|
|
@@ -13,7 +13,7 @@ import net.minecraft.world.level.block.state.BlockState;
|
|
import net.minecraft.world.level.storage.ValueInput;
|
|
import net.minecraft.world.level.storage.ValueOutput;
|
|
|
|
-public class DispenserBlockEntity extends RandomizableContainerBlockEntity {
|
|
+public class DispenserBlockEntity extends RandomizableContainerBlockEntity implements org.leavesmc.leaves.lithium.common.block.entity.inventory_change_tracking.InventoryChangeTracker, org.leavesmc.leaves.lithium.api.inventory.LithiumInventory { // Leaves - Lithium Sleeping Block Entity
|
|
public static final int CONTAINER_SIZE = 9;
|
|
private static final Component DEFAULT_NAME = Component.translatable("container.dispenser");
|
|
private NonNullList<ItemStack> items = NonNullList.withSize(9, ItemStack.EMPTY);
|
|
@@ -135,10 +135,23 @@ public class DispenserBlockEntity extends RandomizableContainerBlockEntity {
|
|
@Override
|
|
protected void setItems(final NonNullList<ItemStack> items) {
|
|
this.items = items;
|
|
+ if (moe.monnairealms.camellia.config.modules.optimizations.LeavesSleepingBlockEntityConfig.enabled) this.lithium$emitStackListReplaced(); // Leaves - Lithium Sleeping Block Entity
|
|
}
|
|
|
|
@Override
|
|
protected AbstractContainerMenu createMenu(final int containerId, final Inventory inventory) {
|
|
return new DispenserMenu(containerId, inventory, this);
|
|
}
|
|
+
|
|
+ // Leaves start - Lithium Sleeping Block Entity
|
|
+ @Override
|
|
+ public net.minecraft.core.NonNullList<net.minecraft.world.item.ItemStack> getInventoryLithium() {
|
|
+ return items;
|
|
+ }
|
|
+
|
|
+ @Override
|
|
+ public void setInventoryLithium(net.minecraft.core.NonNullList<net.minecraft.world.item.ItemStack> inventory) {
|
|
+ items = inventory;
|
|
+ }
|
|
+ // Leaves end - Lithium Sleeping Block Entity
|
|
}
|
|
diff --git a/net/minecraft/world/level/block/entity/EnderChestBlockEntity.java b/net/minecraft/world/level/block/entity/EnderChestBlockEntity.java
|
|
index 6109d8da984b398bb1eb6cd6ab9a55f0511a615c..4b92beb60cb56dc35107dd2c2e7cc6a29f6c3473 100644
|
|
--- a/net/minecraft/world/level/block/entity/EnderChestBlockEntity.java
|
|
+++ b/net/minecraft/world/level/block/entity/EnderChestBlockEntity.java
|
|
@@ -11,7 +11,7 @@ import net.minecraft.world.level.block.Blocks;
|
|
import net.minecraft.world.level.block.ChestBlock;
|
|
import net.minecraft.world.level.block.state.BlockState;
|
|
|
|
-public class EnderChestBlockEntity extends BlockEntity implements LidBlockEntity {
|
|
+public class EnderChestBlockEntity extends BlockEntity implements LidBlockEntity, org.leavesmc.leaves.lithium.common.block.entity.SleepingBlockEntity { // Leaves - Lithium Sleeping Block Entity
|
|
private final ChestLidController chestLidController = new ChestLidController();
|
|
public final ContainerOpenersCounter openersCounter = new ContainerOpenersCounter() {
|
|
// Paper start - delay open/close callbacks
|
|
@@ -66,11 +66,13 @@ public class EnderChestBlockEntity extends BlockEntity implements LidBlockEntity
|
|
|
|
public static void lidAnimateTick(final Level level, final BlockPos pos, final BlockState state, final EnderChestBlockEntity entity) {
|
|
entity.chestLidController.tickLid();
|
|
+ if (moe.monnairealms.camellia.config.modules.optimizations.LeavesSleepingBlockEntityConfig.enabled) entity.checkSleep(); // Leaves - Lithium Sleeping Block Entity
|
|
}
|
|
|
|
@Override
|
|
public boolean triggerEvent(final int b0, final int b1) {
|
|
if (b0 == ChestBlock.EVENT_SET_OPEN_COUNT) {
|
|
+ if (moe.monnairealms.camellia.config.modules.optimizations.LeavesSleepingBlockEntityConfig.enabled && this.sleepingTicker != null) this.wakeUpNow(); // Leaves - Lithium Sleeping Block Entity
|
|
this.chestLidController.shouldBeOpen(b1 > 0);
|
|
return true;
|
|
} else {
|
|
@@ -107,4 +109,36 @@ public class EnderChestBlockEntity extends BlockEntity implements LidBlockEntity
|
|
public float getOpenNess(final float a) {
|
|
return this.chestLidController.getOpenness(a);
|
|
}
|
|
+
|
|
+ // Leaves start - Lithium Sleeping Block Entity
|
|
+ private net.minecraft.world.level.chunk.LevelChunk.RebindableTickingBlockEntityWrapper tickWrapper = null;
|
|
+ private TickingBlockEntity sleepingTicker = null;
|
|
+
|
|
+ @Override
|
|
+ public net.minecraft.world.level.chunk.LevelChunk.RebindableTickingBlockEntityWrapper lithium$getTickWrapper() {
|
|
+ return this.tickWrapper;
|
|
+ }
|
|
+
|
|
+ @Override
|
|
+ public void lithium$setTickWrapper(net.minecraft.world.level.chunk.LevelChunk.RebindableTickingBlockEntityWrapper tickWrapper) {
|
|
+ this.tickWrapper = tickWrapper;
|
|
+ }
|
|
+
|
|
+ @Override
|
|
+ public TickingBlockEntity lithium$getSleepingTicker() {
|
|
+ return this.sleepingTicker;
|
|
+ }
|
|
+
|
|
+ @Override
|
|
+ public void lithium$setSleepingTicker(TickingBlockEntity sleepingTicker) {
|
|
+ this.sleepingTicker = sleepingTicker;
|
|
+ }
|
|
+
|
|
+ private void checkSleep() {
|
|
+ //If the animation is finished, it will stay unchanged until the next triggerEvent, which may change shouldBeOpen
|
|
+ if (this.getOpenNess(0.0F) == this.getOpenNess(1.0F)) {
|
|
+ this.lithium$startSleeping();
|
|
+ }
|
|
+ }
|
|
+ // Leaves end - Lithium Sleeping Block Entity
|
|
}
|
|
diff --git a/net/minecraft/world/level/block/entity/HopperBlockEntity.java b/net/minecraft/world/level/block/entity/HopperBlockEntity.java
|
|
index 4c9d0bcd8820b250b51c06fff4531021ab57d408..fa34778b1ce7a34385c192182e521b00cc7f4d8e 100644
|
|
--- a/net/minecraft/world/level/block/entity/HopperBlockEntity.java
|
|
+++ b/net/minecraft/world/level/block/entity/HopperBlockEntity.java
|
|
@@ -27,8 +27,29 @@ import net.minecraft.world.level.storage.ValueInput;
|
|
import net.minecraft.world.level.storage.ValueOutput;
|
|
import net.minecraft.world.phys.AABB;
|
|
import org.jspecify.annotations.Nullable;
|
|
-
|
|
-public class HopperBlockEntity extends RandomizableContainerBlockEntity implements Hopper {
|
|
+// Leaves start - Lithium Sleeping Block Entity
|
|
+import java.util.Objects;
|
|
+import net.minecraft.world.level.chunk.LevelChunk;
|
|
+import net.minecraft.world.CompoundContainer;
|
|
+import net.minecraft.server.level.ServerLevel;
|
|
+import org.leavesmc.leaves.lithium.api.inventory.LithiumInventory;
|
|
+import org.leavesmc.leaves.lithium.common.block.entity.SleepingBlockEntity;
|
|
+import org.leavesmc.leaves.lithium.common.block.entity.inventory_change_tracking.InventoryChangeListener;
|
|
+import org.leavesmc.leaves.lithium.common.block.entity.inventory_change_tracking.InventoryChangeTracker;
|
|
+import org.leavesmc.leaves.lithium.common.block.entity.inventory_comparator_tracking.ComparatorTracker;
|
|
+import org.leavesmc.leaves.lithium.common.hopper.BlockStateOnlyInventory;
|
|
+import org.leavesmc.leaves.lithium.common.hopper.HopperCachingState;
|
|
+import org.leavesmc.leaves.lithium.common.hopper.HopperHelper;
|
|
+import org.leavesmc.leaves.lithium.common.hopper.InventoryHelper;
|
|
+import org.leavesmc.leaves.lithium.common.hopper.LithiumStackList;
|
|
+import org.leavesmc.leaves.lithium.common.hopper.UpdateReceiver;
|
|
+import org.leavesmc.leaves.lithium.common.tracking.entity.ChunkSectionEntityMovementListener;
|
|
+import org.leavesmc.leaves.lithium.common.tracking.entity.ChunkSectionEntityMovementTracker;
|
|
+import org.leavesmc.leaves.lithium.common.tracking.entity.ChunkSectionInventoryEntityTracker;
|
|
+import org.leavesmc.leaves.lithium.common.tracking.entity.ChunkSectionItemEntityMovementTracker;
|
|
+// Leaves end - Lithium Sleeping Block Entity
|
|
+
|
|
+public class HopperBlockEntity extends RandomizableContainerBlockEntity implements Hopper, SleepingBlockEntity, ChunkSectionEntityMovementListener, LithiumInventory, InventoryChangeListener, UpdateReceiver, InventoryChangeTracker { // Leaves - Lithium Sleeping Block Entity
|
|
public static final int MOVE_ITEM_SPEED = 8;
|
|
public static final int HOPPER_CONTAINER_SIZE = 5;
|
|
private static final int[][] CACHED_SLOTS = new int[54][];
|
|
@@ -77,9 +98,19 @@ public class HopperBlockEntity extends RandomizableContainerBlockEntity implemen
|
|
@Override
|
|
public void updateTicks(final long fromTickOffset, final long fromRedstoneTimeOffset) {
|
|
super.updateTicks(fromTickOffset, fromRedstoneTimeOffset);
|
|
- if (this.tickedGameTime != Long.MIN_VALUE) {
|
|
+ if (this.tickedGameTime != Long.MIN_VALUE && this.tickedGameTime != Long.MAX_VALUE) { // Camellia - Region threading for lithium sleeping block entity
|
|
this.tickedGameTime += fromRedstoneTimeOffset;
|
|
}
|
|
+ // Camellia start - Region threading for lithium sleeping block entity
|
|
+ if (this.insertInventoryEntityFailedSearchTime != Long.MIN_VALUE)
|
|
+ this.insertInventoryEntityFailedSearchTime += fromRedstoneTimeOffset;
|
|
+
|
|
+ if (this.extractInventoryEntityFailedSearchTime != Long.MIN_VALUE)
|
|
+ this.extractInventoryEntityFailedSearchTime += fromRedstoneTimeOffset;
|
|
+
|
|
+ if (this.collectItemEntityAttemptTime != Long.MIN_VALUE)
|
|
+ this.collectItemEntityAttemptTime += fromRedstoneTimeOffset;
|
|
+ // Camellia end
|
|
}
|
|
// Folia end - region threading
|
|
|
|
@@ -129,6 +160,7 @@ public class HopperBlockEntity extends RandomizableContainerBlockEntity implemen
|
|
|
|
@Override
|
|
public void setBlockState(final BlockState blockState) {
|
|
+ if (moe.monnairealms.camellia.config.modules.optimizations.LeavesSleepingBlockEntityConfig.enabled && this.level != null && !this.level.isClientSide() && blockState.getValue(HopperBlock.FACING) != this.getBlockState().getValue(HopperBlock.FACING)) this.invalidateCachedData(); // Leaves - Lithium Sleeping Block Entity
|
|
super.setBlockState(blockState);
|
|
this.facing = blockState.getValue(HopperBlock.FACING);
|
|
}
|
|
@@ -145,6 +177,7 @@ public class HopperBlockEntity extends RandomizableContainerBlockEntity implemen
|
|
entity.setCooldown(0);
|
|
// Spigot start
|
|
boolean result = tryMoveItems(level, pos, state, entity, () -> suckInItems(level, entity));
|
|
+ if (moe.monnairealms.camellia.config.modules.optimizations.LeavesSleepingBlockEntityConfig.enabled) entity.checkSleepingConditions(); // Leaves - Lithium Sleeping Block Entity
|
|
if (!result && entity.level.spigotConfig.hopperCheck > 1) {
|
|
entity.setCooldown(entity.level.spigotConfig.hopperCheck);
|
|
}
|
|
@@ -210,6 +243,14 @@ public class HopperBlockEntity extends RandomizableContainerBlockEntity implemen
|
|
if (changed) {
|
|
entity.setCooldown(level.spigotConfig.hopperTransfer); // Spigot
|
|
setChanged(level, pos, state);
|
|
+ // Leaves start - Lithium Sleeping Block Entity
|
|
+ if (moe.monnairealms.camellia.config.modules.optimizations.LeavesSleepingBlockEntityConfig.enabled
|
|
+ && !entity.isOnCooldown()
|
|
+ && !entity.isSleeping()
|
|
+ && !state.getValue(HopperBlock.ENABLED)) {
|
|
+ entity.lithium$startSleeping();
|
|
+ }
|
|
+ // Leaves end - Lithium Sleeping Block Entity
|
|
return true;
|
|
}
|
|
}
|
|
@@ -406,6 +447,7 @@ public class HopperBlockEntity extends RandomizableContainerBlockEntity implemen
|
|
private static void applyCooldown(final Hopper hopper) {
|
|
if (hopper instanceof HopperBlockEntity blockEntity && blockEntity.getLevel() != null) {
|
|
blockEntity.setCooldown(blockEntity.getLevel().spigotConfig.hopperTransfer);
|
|
+ blockEntity.skipNextSleepCheckAfterCooldown = true; // Leaves - Lithium Sleeping Block Entity
|
|
}
|
|
}
|
|
|
|
@@ -449,12 +491,20 @@ public class HopperBlockEntity extends RandomizableContainerBlockEntity implemen
|
|
// Paper end - Perf: Optimize Hoppers
|
|
|
|
private static boolean ejectItems(final Level level, final BlockPos blockPos, final HopperBlockEntity self) {
|
|
- Container container = getAttachedContainer(level, blockPos, self);
|
|
+ Container container = moe.monnairealms.camellia.config.modules.optimizations.LeavesSleepingBlockEntityConfig.enabled ? self.getInsertInventory(level) : getAttachedContainer(level, blockPos, self); // Leaves - Lithium Sleeping Block Entity
|
|
if (container == null) {
|
|
return false;
|
|
}
|
|
|
|
Direction direction = self.facing.getOpposite();
|
|
+ // Leaves start - Lithium Sleeping Block Entity
|
|
+ if (moe.monnairealms.camellia.config.modules.optimizations.LeavesSleepingBlockEntityConfig.enabled) {
|
|
+ Boolean res = lithiumInsert(level, blockPos, self, container);
|
|
+ if (res != null) {
|
|
+ return res;
|
|
+ }
|
|
+ }
|
|
+ // Leaves end - Lithium Sleeping Block Entity
|
|
if (isFullContainer(container, direction)) {
|
|
return false;
|
|
}
|
|
@@ -510,13 +560,21 @@ public class HopperBlockEntity extends RandomizableContainerBlockEntity implemen
|
|
io.papermc.paper.threadedregions.RegionizedWorldData worldData = io.papermc.paper.threadedregions.TickRegionScheduler.getCurrentRegionizedWorldData(); // Folia - region threading
|
|
BlockPos blockPos = BlockPos.containing(hopper.getLevelX(), hopper.getLevelY() + 1.0, hopper.getLevelZ());
|
|
BlockState blockState = level.getBlockState(blockPos);
|
|
- Container container = getSourceContainer(level, hopper, blockPos, blockState);
|
|
- if (container != null) {
|
|
+ Container sourceContainer = moe.monnairealms.camellia.config.modules.optimizations.LeavesSleepingBlockEntityConfig.enabled ? getExtractInventory(level, hopper, blockPos, blockState) : getSourceContainer(level, hopper, blockPos, blockState); // Leaves - Lithium Sleeping Block Entity
|
|
+ if (sourceContainer != null) {
|
|
Direction direction = Direction.DOWN;
|
|
worldData.skipPullModeEventFire = worldData.skipHopperEvents; // Paper - Perf: Optimize Hoppers // Folia - region threading
|
|
+ // Leaves start - Lithium Sleeping Block Entity
|
|
+ if (moe.monnairealms.camellia.config.modules.optimizations.LeavesSleepingBlockEntityConfig.enabled) {
|
|
+ Boolean res = lithiumExtract(level, hopper, sourceContainer);
|
|
+ if (res != null) {
|
|
+ return res;
|
|
+ }
|
|
+ }
|
|
+ // Leaves end - Lithium Sleeping Block Entity
|
|
|
|
- for (int slot : getSlots(container, direction)) {
|
|
- if (tryTakeInItemFromSlot(hopper, container, slot, direction, level)) { // Spigot
|
|
+ for (int slot : getSlots(sourceContainer, direction)) {
|
|
+ if (tryTakeInItemFromSlot(hopper, sourceContainer, slot, direction, level)) { // Spigot
|
|
return true;
|
|
}
|
|
}
|
|
@@ -527,7 +585,7 @@ public class HopperBlockEntity extends RandomizableContainerBlockEntity implemen
|
|
&& blockState.isCollisionShapeFullBlock(level, blockPos)
|
|
&& !blockState.is(BlockTags.DOES_NOT_BLOCK_HOPPERS);
|
|
if (!isBlocked) {
|
|
- for (ItemEntity entity : getItemsAtAndAbove(level, hopper)) {
|
|
+ for (ItemEntity entity : moe.monnairealms.camellia.config.modules.optimizations.LeavesSleepingBlockEntityConfig.enabled ? lithiumGetInputItemEntities(level, hopper) : getItemsAtAndAbove(level, hopper)) { // Leaves - Lithium Sleeping Block Entity
|
|
if (addItem(hopper, entity)) {
|
|
return true;
|
|
}
|
|
@@ -649,7 +707,7 @@ public class HopperBlockEntity extends RandomizableContainerBlockEntity implemen
|
|
|
|
// CraftBukkit start
|
|
private static @Nullable Container runHopperInventorySearchEvent(
|
|
- Container container,
|
|
+ @Nullable Container container, // Leaves - Lithium Sleeping Block Entity
|
|
org.bukkit.craftbukkit.block.CraftBlock hopper,
|
|
org.bukkit.craftbukkit.block.CraftBlock searchLocation,
|
|
org.bukkit.event.inventory.HopperInventorySearchEvent.ContainerType containerType
|
|
@@ -775,6 +833,19 @@ public class HopperBlockEntity extends RandomizableContainerBlockEntity implemen
|
|
}
|
|
|
|
public void setCooldown(final int time) {
|
|
+ // Leaves start - Lithium Sleeping Block Entity
|
|
+ if (moe.monnairealms.camellia.config.modules.optimizations.LeavesSleepingBlockEntityConfig.enabled) {
|
|
+ if (time == 7) {
|
|
+ if (this.tickedGameTime == Long.MAX_VALUE) {
|
|
+ this.sleepOnlyCurrentTick();
|
|
+ } else {
|
|
+ this.wakeUpNow();
|
|
+ }
|
|
+ } else if (time > 0 && this.sleepingTicker != null) {
|
|
+ this.wakeUpNow();
|
|
+ }
|
|
+ }
|
|
+ // Leaves end - Lithium Sleeping Block Entity
|
|
this.cooldownTime = time;
|
|
}
|
|
|
|
@@ -794,6 +865,7 @@ public class HopperBlockEntity extends RandomizableContainerBlockEntity implemen
|
|
@Override
|
|
protected void setItems(final NonNullList<ItemStack> items) {
|
|
this.items = items;
|
|
+ if (moe.monnairealms.camellia.config.modules.optimizations.LeavesSleepingBlockEntityConfig.enabled) this.lithium$emitStackListReplaced(); // Leaves - Lithium Sleeping Block Entity
|
|
}
|
|
|
|
public static void entityInside(final Level level, final BlockPos pos, final BlockState blockState, final Entity entity, final HopperBlockEntity hopper) {
|
|
@@ -808,4 +880,758 @@ public class HopperBlockEntity extends RandomizableContainerBlockEntity implemen
|
|
protected AbstractContainerMenu createMenu(final int containerId, final Inventory inventory) {
|
|
return new HopperMenu(containerId, inventory, this);
|
|
}
|
|
+
|
|
+ // Leaves start - Lithium Sleeping Block Entity
|
|
+ private LevelChunk.@org.jspecify.annotations.Nullable RebindableTickingBlockEntityWrapper tickWrapper = null; // Leaves - Paper 26.1 fix
|
|
+ @Nullable private TickingBlockEntity sleepingTicker = null;
|
|
+ private long myModCountAtLastInsert, myModCountAtLastExtract, myModCountAtLastItemCollect;
|
|
+ private boolean skipNextSleepCheckAfterCooldown = false;
|
|
+
|
|
+ private HopperCachingState.BlockInventory insertionMode = HopperCachingState.BlockInventory.UNKNOWN;
|
|
+ private HopperCachingState.BlockInventory extractionMode = HopperCachingState.BlockInventory.UNKNOWN;
|
|
+
|
|
+ //The currently used block inventories
|
|
+ @Nullable
|
|
+ private Container insertBlockInventory, extractBlockInventory;
|
|
+
|
|
+ //The currently used inventories (optimized type, if not present, skip optimizations)
|
|
+ @Nullable
|
|
+ private LithiumInventory insertInventory, extractInventory;
|
|
+ @Nullable //Null iff corresp. LithiumInventory field is null
|
|
+ private LithiumStackList insertStackList, extractStackList;
|
|
+ //Mod count used to avoid transfer attempts that are known to fail (no change since last attempt)
|
|
+ private long insertStackListModCount, extractStackListModCount;
|
|
+
|
|
+ @Nullable
|
|
+ private List<ChunkSectionItemEntityMovementTracker> collectItemEntityTracker;
|
|
+ private boolean collectItemEntityTrackerWasEmpty;
|
|
+ @Nullable
|
|
+ private AABB collectItemEntityBox;
|
|
+ private long collectItemEntityAttemptTime;
|
|
+
|
|
+ @Nullable
|
|
+ private List<ChunkSectionInventoryEntityTracker> extractInventoryEntityTracker;
|
|
+ @Nullable
|
|
+ private AABB extractInventoryEntityBox;
|
|
+ private long extractInventoryEntityFailedSearchTime;
|
|
+
|
|
+ @Nullable
|
|
+ private List<ChunkSectionInventoryEntityTracker> insertInventoryEntityTracker;
|
|
+ @Nullable
|
|
+ private AABB insertInventoryEntityBox;
|
|
+ private long insertInventoryEntityFailedSearchTime;
|
|
+
|
|
+ private boolean shouldCheckSleep;
|
|
+
|
|
+ private void checkSleepingConditions() {
|
|
+ if (this.cooldownTime > 0 || this.getLevel() == null || skipNextSleepCheckAfterCooldown) {
|
|
+ return;
|
|
+ }
|
|
+ if (isSleeping()) {
|
|
+ return;
|
|
+ }
|
|
+ if (!this.shouldCheckSleep) {
|
|
+ this.shouldCheckSleep = true;
|
|
+ return;
|
|
+ }
|
|
+ boolean listenToExtractTracker = false;
|
|
+ boolean listenToInsertTracker = false;
|
|
+ boolean listenToExtractEntities = false;
|
|
+ boolean listenToItemEntities = false;
|
|
+ boolean listenToInsertEntities = false;
|
|
+
|
|
+ LithiumStackList thisStackList = InventoryHelper.getLithiumStackList(this);
|
|
+
|
|
+ if (this.extractionMode != HopperCachingState.BlockInventory.BLOCK_STATE && thisStackList.getFullSlots() != thisStackList.size()) {
|
|
+ if (this.extractionMode == HopperCachingState.BlockInventory.REMOVAL_TRACKING_BLOCK_ENTITY) {
|
|
+ Container blockInventory = this.extractBlockInventory;
|
|
+ if (this.extractStackList != null &&
|
|
+ blockInventory instanceof InventoryChangeTracker) {
|
|
+ if (!this.extractStackList.maybeSendsComparatorUpdatesOnFailedExtract() || (blockInventory instanceof ComparatorTracker comparatorTracker && !comparatorTracker.lithium$hasAnyComparatorNearby())) {
|
|
+ listenToExtractTracker = true;
|
|
+ } else {
|
|
+ return;
|
|
+ }
|
|
+ } else {
|
|
+ return;
|
|
+ }
|
|
+ } else if (this.extractionMode == HopperCachingState.BlockInventory.NO_BLOCK_INVENTORY) {
|
|
+ BlockState hopperState = this.getBlockState();
|
|
+ listenToExtractEntities = true;
|
|
+
|
|
+ BlockPos blockPos = this.getBlockPos().above();
|
|
+ BlockState blockState = this.getLevel().getBlockState(blockPos);
|
|
+ if (!blockState.isCollisionShapeFullBlock(this.getLevel(), blockPos) || blockState.is(BlockTags.DOES_NOT_BLOCK_HOPPERS)) {
|
|
+ listenToItemEntities = true;
|
|
+ }
|
|
+ } else {
|
|
+ return;
|
|
+ }
|
|
+ }
|
|
+ if (this.insertionMode != HopperCachingState.BlockInventory.BLOCK_STATE && 0 < thisStackList.getOccupiedSlots()) {
|
|
+ if (this.insertionMode == HopperCachingState.BlockInventory.REMOVAL_TRACKING_BLOCK_ENTITY) {
|
|
+ Container blockInventory = this.insertBlockInventory;
|
|
+ if (this.insertStackList != null && blockInventory instanceof InventoryChangeTracker) {
|
|
+ listenToInsertTracker = true;
|
|
+ } else {
|
|
+ return;
|
|
+ }
|
|
+ } else if (this.insertionMode == HopperCachingState.BlockInventory.NO_BLOCK_INVENTORY) {
|
|
+ BlockState hopperState = this.getBlockState();
|
|
+ listenToInsertEntities = true;
|
|
+ } else {
|
|
+ return;
|
|
+ }
|
|
+ }
|
|
+
|
|
+ if (listenToExtractTracker) {
|
|
+ ((InventoryChangeTracker) this.extractBlockInventory).listenForContentChangesOnce(this.extractStackList, this);
|
|
+ }
|
|
+ if (listenToInsertTracker) {
|
|
+ ((InventoryChangeTracker) this.insertBlockInventory).listenForContentChangesOnce(this.insertStackList, this);
|
|
+ }
|
|
+ if (listenToInsertEntities) {
|
|
+ if (this.insertInventoryEntityTracker == null || this.insertInventoryEntityTracker.isEmpty()) {
|
|
+ return;
|
|
+ }
|
|
+ ChunkSectionEntityMovementTracker.listenToEntityMovementOnce(this, insertInventoryEntityTracker);
|
|
+ }
|
|
+ if (listenToExtractEntities) {
|
|
+ if (this.extractInventoryEntityTracker == null || this.extractInventoryEntityTracker.isEmpty()) {
|
|
+ return;
|
|
+ }
|
|
+ ChunkSectionEntityMovementTracker.listenToEntityMovementOnce(this, extractInventoryEntityTracker);
|
|
+ }
|
|
+ if (listenToItemEntities) {
|
|
+ if (this.collectItemEntityTracker == null || this.collectItemEntityTracker.isEmpty()) {
|
|
+ return;
|
|
+ }
|
|
+ ChunkSectionEntityMovementTracker.listenToEntityMovementOnce(this, collectItemEntityTracker);
|
|
+ }
|
|
+
|
|
+ this.listenForContentChangesOnce(thisStackList, this);
|
|
+ lithium$startSleeping();
|
|
+ }
|
|
+
|
|
+ @Override
|
|
+ public void lithium$setSleepingTicker(@Nullable TickingBlockEntity sleepingTicker) {
|
|
+ this.sleepingTicker = sleepingTicker;
|
|
+ }
|
|
+
|
|
+ @Override
|
|
+ public @Nullable TickingBlockEntity lithium$getSleepingTicker() {
|
|
+ return sleepingTicker;
|
|
+ }
|
|
+
|
|
+ @Override
|
|
+ public void lithium$setTickWrapper(LevelChunk.RebindableTickingBlockEntityWrapper tickWrapper) {
|
|
+ this.tickWrapper = tickWrapper;
|
|
+ this.lithium$setSleepingTicker(null);
|
|
+ }
|
|
+
|
|
+ @Override
|
|
+ public LevelChunk.@org.jspecify.annotations.Nullable RebindableTickingBlockEntityWrapper lithium$getTickWrapper() { // Leaves - Paper 26.1 fix
|
|
+ return tickWrapper;
|
|
+ }
|
|
+
|
|
+ @Override
|
|
+ public boolean lithium$startSleeping() {
|
|
+ if (this.isSleeping()) {
|
|
+ return false;
|
|
+ }
|
|
+
|
|
+ LevelChunk.RebindableTickingBlockEntityWrapper tickWrapper = this.lithium$getTickWrapper();
|
|
+ if (tickWrapper != null) {
|
|
+ this.lithium$setSleepingTicker(tickWrapper.ticker);
|
|
+ tickWrapper.rebind(SleepingBlockEntity.SLEEPING_BLOCK_ENTITY_TICKER);
|
|
+
|
|
+ // Set the last tick time to max value, so other hoppers transferring into this hopper will set it to 7gt
|
|
+ // cooldown. Then when waking up, we make sure to not tick this hopper in the same gametick.
|
|
+ // This makes the observable hopper cooldown not be different from vanilla.
|
|
+ this.tickedGameTime = Long.MAX_VALUE;
|
|
+ return true;
|
|
+ }
|
|
+ return false;
|
|
+ }
|
|
+
|
|
+ @Override
|
|
+ public void handleEntityMovement() {
|
|
+ this.wakeUpNow();
|
|
+ }
|
|
+
|
|
+ @Override
|
|
+ public NonNullList<ItemStack> getInventoryLithium() {
|
|
+ return items;
|
|
+ }
|
|
+
|
|
+ @Override
|
|
+ public void setInventoryLithium(NonNullList<ItemStack> inventory) {
|
|
+ this.items = inventory;
|
|
+ }
|
|
+
|
|
+ @Override
|
|
+ public void lithium$handleInventoryContentModified(Container inventory) {
|
|
+ wakeUpNow();
|
|
+ }
|
|
+
|
|
+ @Override
|
|
+ public void lithium$handleInventoryRemoved(Container inventory) {
|
|
+ wakeUpNow();
|
|
+ if (inventory == this.insertBlockInventory) {
|
|
+ this.invalidateBlockInsertionData();
|
|
+ }
|
|
+ if (inventory == this.extractBlockInventory) {
|
|
+ this.invalidateBlockExtractionData();
|
|
+ }
|
|
+ if (inventory == this) {
|
|
+ this.invalidateCachedData();
|
|
+ }
|
|
+ }
|
|
+
|
|
+ @Override
|
|
+ public boolean lithium$handleComparatorAdded(Container inventory) {
|
|
+ if (inventory == this.extractBlockInventory) {
|
|
+ wakeUpNow();
|
|
+ return true;
|
|
+ }
|
|
+ return false;
|
|
+ }
|
|
+
|
|
+ @Override
|
|
+ public void lithium$invalidateCacheOnNeighborUpdate(boolean fromAbove) {
|
|
+ //Clear the block inventory cache (composter inventories and no inventory present) on block update / observer update
|
|
+ if (fromAbove) {
|
|
+ if (this.extractionMode == HopperCachingState.BlockInventory.NO_BLOCK_INVENTORY || this.extractionMode == HopperCachingState.BlockInventory.BLOCK_STATE) {
|
|
+ this.invalidateBlockExtractionData();
|
|
+ }
|
|
+ } else {
|
|
+ if (this.insertionMode == HopperCachingState.BlockInventory.NO_BLOCK_INVENTORY || this.insertionMode == HopperCachingState.BlockInventory.BLOCK_STATE) {
|
|
+ this.invalidateBlockInsertionData();
|
|
+ }
|
|
+ }
|
|
+ }
|
|
+
|
|
+ @Override
|
|
+ public void lithium$invalidateCacheOnUndirectedNeighborUpdate() {
|
|
+ if (this.extractionMode == HopperCachingState.BlockInventory.NO_BLOCK_INVENTORY || this.extractionMode == HopperCachingState.BlockInventory.BLOCK_STATE) {
|
|
+ this.invalidateBlockExtractionData();
|
|
+ }
|
|
+ if (this.insertionMode == HopperCachingState.BlockInventory.NO_BLOCK_INVENTORY || this.insertionMode == HopperCachingState.BlockInventory.BLOCK_STATE) {
|
|
+ this.invalidateBlockInsertionData();
|
|
+ }
|
|
+ }
|
|
+
|
|
+ @Override
|
|
+ public void lithium$invalidateCacheOnNeighborUpdate(Direction fromDirection) {
|
|
+ boolean fromAbove = fromDirection == Direction.UP;
|
|
+ if (fromAbove || this.getBlockState().getValue(HopperBlock.FACING) == fromDirection) {
|
|
+ this.lithium$invalidateCacheOnNeighborUpdate(fromAbove);
|
|
+ }
|
|
+ }
|
|
+
|
|
+ private void invalidateBlockInsertionData() {
|
|
+ this.insertionMode = HopperCachingState.BlockInventory.UNKNOWN;
|
|
+ this.insertBlockInventory = null;
|
|
+ this.insertInventory = null;
|
|
+ this.insertStackList = null;
|
|
+ this.insertStackListModCount = 0;
|
|
+
|
|
+ wakeUpNow();
|
|
+ }
|
|
+
|
|
+ private void invalidateCachedData() {
|
|
+ this.shouldCheckSleep = false;
|
|
+ this.invalidateInsertionData();
|
|
+ this.invalidateExtractionData();
|
|
+ }
|
|
+
|
|
+ private void invalidateInsertionData() {
|
|
+ if (this.level instanceof ServerLevel) {
|
|
+ if (this.insertInventoryEntityTracker != null) {
|
|
+ ChunkSectionEntityMovementTracker.unregister(this.insertInventoryEntityTracker);
|
|
+ this.insertInventoryEntityTracker = null;
|
|
+ this.insertInventoryEntityBox = null;
|
|
+ this.insertInventoryEntityFailedSearchTime = 0L;
|
|
+ }
|
|
+ }
|
|
+
|
|
+ if (this.insertionMode == HopperCachingState.BlockInventory.REMOVAL_TRACKING_BLOCK_ENTITY) {
|
|
+ assert this.insertBlockInventory != null;
|
|
+ ((InventoryChangeTracker) this.insertBlockInventory).stopListenForMajorInventoryChanges(this);
|
|
+ }
|
|
+ this.invalidateBlockInsertionData();
|
|
+ }
|
|
+
|
|
+ private void invalidateExtractionData() {
|
|
+ if (this.level instanceof ServerLevel) {
|
|
+ if (this.extractInventoryEntityTracker != null) {
|
|
+ ChunkSectionEntityMovementTracker.unregister(this.extractInventoryEntityTracker);
|
|
+ this.extractInventoryEntityTracker = null;
|
|
+ this.extractInventoryEntityBox = null;
|
|
+ this.extractInventoryEntityFailedSearchTime = 0L;
|
|
+ }
|
|
+ if (this.collectItemEntityTracker != null) {
|
|
+ ChunkSectionEntityMovementTracker.unregister(this.collectItemEntityTracker);
|
|
+ this.collectItemEntityTracker = null;
|
|
+ this.collectItemEntityBox = null;
|
|
+ this.collectItemEntityTrackerWasEmpty = false;
|
|
+ }
|
|
+ }
|
|
+ if (this.extractionMode == HopperCachingState.BlockInventory.REMOVAL_TRACKING_BLOCK_ENTITY) {
|
|
+ assert this.extractBlockInventory != null;
|
|
+ ((InventoryChangeTracker) this.extractBlockInventory).stopListenForMajorInventoryChanges(this);
|
|
+ }
|
|
+ this.invalidateBlockExtractionData();
|
|
+ }
|
|
+
|
|
+ private void invalidateBlockExtractionData() {
|
|
+ this.extractionMode = HopperCachingState.BlockInventory.UNKNOWN;
|
|
+ this.extractBlockInventory = null;
|
|
+ this.extractInventory = null;
|
|
+ this.extractStackList = null;
|
|
+ this.extractStackListModCount = 0;
|
|
+
|
|
+ this.wakeUpNow();
|
|
+ }
|
|
+
|
|
+ private static @Nullable Container getExtractInventory(Level world, Hopper hopper, BlockPos extractBlockPos, BlockState extractBlockState) {
|
|
+ if (!(hopper instanceof HopperBlockEntity hopperBlockEntity)) {
|
|
+ return getSourceContainer(world, hopper, extractBlockPos, extractBlockState); //Hopper Minecarts do not cache Inventories
|
|
+ }
|
|
+
|
|
+ Container blockInventory = hopperBlockEntity.lithium$getExtractBlockInventory(world, extractBlockPos, extractBlockState);
|
|
+ if (blockInventory == null) {
|
|
+ blockInventory = hopperBlockEntity.lithium$getExtractEntityInventory(world);
|
|
+ }
|
|
+ return org.bukkit.event.inventory.HopperInventorySearchEvent.getHandlerList().getRegisteredListeners().length == 0 ? blockInventory : runHopperInventorySearchEvent(
|
|
+ blockInventory,
|
|
+ org.bukkit.craftbukkit.block.CraftBlock.at(world, hopperBlockEntity.getBlockPos()),
|
|
+ org.bukkit.craftbukkit.block.CraftBlock.at(world, extractBlockPos),
|
|
+ org.bukkit.event.inventory.HopperInventorySearchEvent.ContainerType.SOURCE
|
|
+ );
|
|
+ }
|
|
+
|
|
+ public @Nullable Container lithium$getExtractBlockInventory(Level world, BlockPos extractBlockPos, BlockState extractBlockState) {
|
|
+ Container blockInventory = this.extractBlockInventory;
|
|
+ if (this.extractionMode == HopperCachingState.BlockInventory.NO_BLOCK_INVENTORY) {
|
|
+ return null;
|
|
+ } else if (this.extractionMode == HopperCachingState.BlockInventory.BLOCK_STATE) {
|
|
+ return blockInventory;
|
|
+ } else if (this.extractionMode == HopperCachingState.BlockInventory.REMOVAL_TRACKING_BLOCK_ENTITY) {
|
|
+ return blockInventory;
|
|
+ } else if (this.extractionMode == HopperCachingState.BlockInventory.BLOCK_ENTITY) {
|
|
+ BlockEntity blockEntity = (BlockEntity) Objects.requireNonNull(blockInventory);
|
|
+ //Movable Block Entity compatibility - position comparison
|
|
+ BlockPos pos = blockEntity.getBlockPos();
|
|
+ if (!(blockEntity).isRemoved() && pos.equals(extractBlockPos)) {
|
|
+ LithiumInventory optimizedInventory;
|
|
+ if ((optimizedInventory = this.extractInventory) != null) {
|
|
+ LithiumStackList insertInventoryStackList = InventoryHelper.getLithiumStackList(optimizedInventory);
|
|
+ //This check is necessary as sometimes the stacklist is silently replaced (e.g. command making furnace read inventory from nbt)
|
|
+ if (insertInventoryStackList == this.extractStackList) {
|
|
+ return optimizedInventory;
|
|
+ } else {
|
|
+ this.invalidateBlockExtractionData();
|
|
+ }
|
|
+ } else {
|
|
+ return blockInventory;
|
|
+ }
|
|
+ }
|
|
+ }
|
|
+
|
|
+ //No Cached Inventory: Get like vanilla and cache
|
|
+ blockInventory = getBlockContainer(world, extractBlockPos, extractBlockState);
|
|
+ blockInventory = HopperHelper.replaceDoubleInventory(blockInventory);
|
|
+ this.cacheExtractBlockInventory(blockInventory);
|
|
+ return blockInventory;
|
|
+ }
|
|
+
|
|
+ public @Nullable Container lithium$getInsertBlockInventory(Level world) {
|
|
+ Container blockInventory = this.insertBlockInventory;
|
|
+ if (this.insertionMode == HopperCachingState.BlockInventory.NO_BLOCK_INVENTORY) {
|
|
+ return null;
|
|
+ } else if (this.insertionMode == HopperCachingState.BlockInventory.BLOCK_STATE) {
|
|
+ return blockInventory;
|
|
+ } else if (this.insertionMode == HopperCachingState.BlockInventory.REMOVAL_TRACKING_BLOCK_ENTITY) {
|
|
+ return blockInventory;
|
|
+ } else if (this.insertionMode == HopperCachingState.BlockInventory.BLOCK_ENTITY) {
|
|
+ BlockEntity blockEntity = (BlockEntity) Objects.requireNonNull(blockInventory);
|
|
+ //Movable Block Entity compatibility - position comparison
|
|
+ BlockPos pos = blockEntity.getBlockPos();
|
|
+ Direction direction = this.facing;
|
|
+ BlockPos transferPos = this.getBlockPos().relative(direction);
|
|
+ if (!(blockEntity).isRemoved() &&
|
|
+ pos.equals(transferPos)) {
|
|
+ LithiumInventory optimizedInventory;
|
|
+ if ((optimizedInventory = this.insertInventory) != null) {
|
|
+ LithiumStackList insertInventoryStackList = InventoryHelper.getLithiumStackList(optimizedInventory);
|
|
+ //This check is necessary as sometimes the stacklist is silently replaced (e.g. command making furnace read inventory from nbt)
|
|
+ if (insertInventoryStackList == this.insertStackList) {
|
|
+ return optimizedInventory;
|
|
+ } else {
|
|
+ this.invalidateBlockInsertionData();
|
|
+ }
|
|
+ } else {
|
|
+ return blockInventory;
|
|
+ }
|
|
+ }
|
|
+ }
|
|
+
|
|
+ //No Cached Inventory: Get like vanilla and cache
|
|
+ Direction direction = this.facing;
|
|
+ BlockPos insertBlockPos = this.getBlockPos().relative(direction);
|
|
+ BlockState blockState = world.getBlockState(insertBlockPos);
|
|
+ blockInventory = getBlockContainer(world, insertBlockPos, blockState);
|
|
+ blockInventory = HopperHelper.replaceDoubleInventory(blockInventory);
|
|
+ this.cacheInsertBlockInventory(blockInventory);
|
|
+ return blockInventory;
|
|
+ }
|
|
+
|
|
+ public @Nullable Container getInsertInventory(Level world) {
|
|
+ Container blockInventory = getInsertInventory0(world);
|
|
+ return org.bukkit.event.inventory.HopperInventorySearchEvent.getHandlerList().getRegisteredListeners().length == 0 ? blockInventory : runHopperInventorySearchEvent(
|
|
+ blockInventory,
|
|
+ org.bukkit.craftbukkit.block.CraftBlock.at(world, this.getBlockPos()),
|
|
+ org.bukkit.craftbukkit.block.CraftBlock.at(world, this.getBlockPos().relative(this.facing)),
|
|
+ org.bukkit.event.inventory.HopperInventorySearchEvent.ContainerType.DESTINATION
|
|
+ );
|
|
+ }
|
|
+
|
|
+ public @Nullable Container getInsertInventory0(Level world) {
|
|
+ Container blockInventory = this.lithium$getInsertBlockInventory(world);
|
|
+ if (blockInventory != null) {
|
|
+ return blockInventory;
|
|
+ }
|
|
+
|
|
+ if (this.insertInventoryEntityTracker == null) {
|
|
+ this.initInsertInventoryTracker(world);
|
|
+ }
|
|
+ if (ChunkSectionEntityMovementTracker.isUnchangedSince(this.insertInventoryEntityFailedSearchTime, this.insertInventoryEntityTracker)) {
|
|
+ this.insertInventoryEntityFailedSearchTime = this.tickedGameTime;
|
|
+ return null;
|
|
+ }
|
|
+ this.insertInventoryEntityFailedSearchTime = Long.MIN_VALUE;
|
|
+ this.shouldCheckSleep = false;
|
|
+
|
|
+ List<Container> inventoryEntities = ChunkSectionInventoryEntityTracker.getEntities(world, this.insertInventoryEntityBox);
|
|
+ if (inventoryEntities.isEmpty()) {
|
|
+ this.insertInventoryEntityFailedSearchTime = this.tickedGameTime;
|
|
+ //Remember failed entity search timestamp. This allows shortcutting if no entity movement happens.
|
|
+ return null;
|
|
+ }
|
|
+ Container inventory = inventoryEntities.get(world.getRandom().nextInt(inventoryEntities.size())); // Leaves - Paper 26.1 fix
|
|
+ if (inventory instanceof LithiumInventory optimizedInventory) {
|
|
+ LithiumStackList insertInventoryStackList = InventoryHelper.getLithiumStackList(optimizedInventory);
|
|
+ if (inventory != this.insertInventory || this.insertStackList != insertInventoryStackList) {
|
|
+ this.cacheInsertLithiumInventory(optimizedInventory);
|
|
+ }
|
|
+ }
|
|
+
|
|
+ return inventory;
|
|
+ }
|
|
+
|
|
+ private void initCollectItemEntityTracker() {
|
|
+ assert this.level instanceof ServerLevel;
|
|
+ AABB inputBox = this.getSuckAabb().move(this.worldPosition.getX(), this.worldPosition.getY(), this.worldPosition.getZ());
|
|
+ this.collectItemEntityBox = inputBox;
|
|
+ this.collectItemEntityTracker =
|
|
+ ChunkSectionItemEntityMovementTracker.registerAt(
|
|
+ (ServerLevel) this.level,
|
|
+ inputBox
|
|
+ );
|
|
+ this.collectItemEntityAttemptTime = Long.MIN_VALUE;
|
|
+ }
|
|
+
|
|
+ private void initExtractInventoryTracker(Level world) {
|
|
+ assert world instanceof ServerLevel;
|
|
+ BlockPos pos = this.worldPosition.relative(Direction.UP);
|
|
+ this.extractInventoryEntityBox = new AABB(pos.getX(), pos.getY(), pos.getZ(), pos.getX() + 1, pos.getY() + 1, pos.getZ() + 1);
|
|
+ this.extractInventoryEntityTracker =
|
|
+ ChunkSectionInventoryEntityTracker.registerAt(
|
|
+ (ServerLevel) this.level,
|
|
+ this.extractInventoryEntityBox
|
|
+ );
|
|
+ this.extractInventoryEntityFailedSearchTime = Long.MIN_VALUE;
|
|
+ }
|
|
+
|
|
+ private void initInsertInventoryTracker(Level world) {
|
|
+ assert world instanceof ServerLevel;
|
|
+ Direction direction = this.facing;
|
|
+ BlockPos pos = this.worldPosition.relative(direction);
|
|
+ this.insertInventoryEntityBox = new AABB(pos.getX(), pos.getY(), pos.getZ(), pos.getX() + 1, pos.getY() + 1, pos.getZ() + 1);
|
|
+ this.insertInventoryEntityTracker =
|
|
+ ChunkSectionInventoryEntityTracker.registerAt(
|
|
+ (ServerLevel) this.level,
|
|
+ this.insertInventoryEntityBox
|
|
+ );
|
|
+ this.insertInventoryEntityFailedSearchTime = Long.MIN_VALUE;
|
|
+ }
|
|
+
|
|
+ private @Nullable Container lithium$getExtractEntityInventory(Level world) {
|
|
+ if (this.extractInventoryEntityTracker == null) {
|
|
+ this.initExtractInventoryTracker(world);
|
|
+ }
|
|
+ if (ChunkSectionEntityMovementTracker.isUnchangedSince(this.extractInventoryEntityFailedSearchTime, this.extractInventoryEntityTracker)) {
|
|
+ this.extractInventoryEntityFailedSearchTime = this.tickedGameTime;
|
|
+ return null;
|
|
+ }
|
|
+ this.extractInventoryEntityFailedSearchTime = Long.MIN_VALUE;
|
|
+ this.shouldCheckSleep = false;
|
|
+
|
|
+ List<Container> inventoryEntities = ChunkSectionInventoryEntityTracker.getEntities(world, this.extractInventoryEntityBox);
|
|
+ if (inventoryEntities.isEmpty()) {
|
|
+ this.extractInventoryEntityFailedSearchTime = this.tickedGameTime;
|
|
+ //only set unchanged when no entity present. this allows shortcutting this case
|
|
+ //shortcutting the entity present case requires checking its change counter
|
|
+ return null;
|
|
+ }
|
|
+ Container inventory = inventoryEntities.get(world.getRandom().nextInt(inventoryEntities.size())); // Leaves - Paper 26.1 fix
|
|
+ if (inventory instanceof LithiumInventory optimizedInventory) {
|
|
+ LithiumStackList extractInventoryStackList = InventoryHelper.getLithiumStackList(optimizedInventory);
|
|
+ if (inventory != this.extractInventory || this.extractStackList != extractInventoryStackList) {
|
|
+ //not caching the inventory (NO_BLOCK_INVENTORY prevents it)
|
|
+ //make change counting on the entity inventory possible, without caching it as block inventory
|
|
+ this.cacheExtractLithiumInventory(optimizedInventory);
|
|
+ }
|
|
+ }
|
|
+ return inventory;
|
|
+ }
|
|
+
|
|
+ /**
|
|
+ * Makes this hopper remember the given inventory.
|
|
+ *
|
|
+ * @param insertInventory Block inventory / Blockentity inventory to be remembered
|
|
+ */
|
|
+ private void cacheInsertBlockInventory(@Nullable Container insertInventory) {
|
|
+ assert !(insertInventory instanceof Entity);
|
|
+ if (insertInventory instanceof LithiumInventory optimizedInventory) {
|
|
+ this.cacheInsertLithiumInventory(optimizedInventory);
|
|
+ } else {
|
|
+ this.insertInventory = null;
|
|
+ this.insertStackList = null;
|
|
+ this.insertStackListModCount = 0;
|
|
+ }
|
|
+
|
|
+ if (insertInventory instanceof BlockEntity || insertInventory instanceof CompoundContainer) {
|
|
+ this.insertBlockInventory = insertInventory;
|
|
+ if (insertInventory instanceof InventoryChangeTracker) {
|
|
+ this.insertionMode = HopperCachingState.BlockInventory.REMOVAL_TRACKING_BLOCK_ENTITY;
|
|
+ ((InventoryChangeTracker) insertInventory).listenForMajorInventoryChanges(this);
|
|
+ } else {
|
|
+ this.insertionMode = HopperCachingState.BlockInventory.BLOCK_ENTITY;
|
|
+ }
|
|
+ } else {
|
|
+ if (insertInventory == null) {
|
|
+ this.insertBlockInventory = null;
|
|
+ this.insertionMode = HopperCachingState.BlockInventory.NO_BLOCK_INVENTORY;
|
|
+ } else {
|
|
+ this.insertBlockInventory = insertInventory;
|
|
+ this.insertionMode = insertInventory instanceof BlockStateOnlyInventory ? HopperCachingState.BlockInventory.BLOCK_STATE : HopperCachingState.BlockInventory.UNKNOWN;
|
|
+ }
|
|
+ }
|
|
+ }
|
|
+
|
|
+ private void cacheInsertLithiumInventory(LithiumInventory optimizedInventory) {
|
|
+ LithiumStackList insertInventoryStackList = InventoryHelper.getLithiumStackList(optimizedInventory);
|
|
+ this.insertInventory = optimizedInventory;
|
|
+ this.insertStackList = insertInventoryStackList;
|
|
+ this.insertStackListModCount = insertInventoryStackList.getModCount() - 1;
|
|
+ }
|
|
+
|
|
+ private void cacheExtractLithiumInventory(LithiumInventory optimizedInventory) {
|
|
+ LithiumStackList extractInventoryStackList = InventoryHelper.getLithiumStackList(optimizedInventory);
|
|
+ this.extractInventory = optimizedInventory;
|
|
+ this.extractStackList = extractInventoryStackList;
|
|
+ this.extractStackListModCount = extractInventoryStackList.getModCount() - 1;
|
|
+ }
|
|
+
|
|
+ /**
|
|
+ * Makes this hopper remember the given inventory.
|
|
+ *
|
|
+ * @param extractInventory Block inventory / Blockentity inventory to be remembered
|
|
+ */
|
|
+ private void cacheExtractBlockInventory(@Nullable Container extractInventory) {
|
|
+ assert !(extractInventory instanceof Entity);
|
|
+ if (extractInventory instanceof LithiumInventory optimizedInventory) {
|
|
+ this.cacheExtractLithiumInventory(optimizedInventory);
|
|
+ } else {
|
|
+ this.extractInventory = null;
|
|
+ this.extractStackList = null;
|
|
+ this.extractStackListModCount = 0;
|
|
+ }
|
|
+
|
|
+ if (extractInventory instanceof BlockEntity || extractInventory instanceof CompoundContainer) {
|
|
+ this.extractBlockInventory = extractInventory;
|
|
+ if (extractInventory instanceof InventoryChangeTracker) {
|
|
+ this.extractionMode = HopperCachingState.BlockInventory.REMOVAL_TRACKING_BLOCK_ENTITY;
|
|
+ ((InventoryChangeTracker) extractInventory).listenForMajorInventoryChanges(this);
|
|
+ } else {
|
|
+ this.extractionMode = HopperCachingState.BlockInventory.BLOCK_ENTITY;
|
|
+ }
|
|
+ } else {
|
|
+ if (extractInventory == null) {
|
|
+ this.extractBlockInventory = null;
|
|
+ this.extractionMode = HopperCachingState.BlockInventory.NO_BLOCK_INVENTORY;
|
|
+ } else {
|
|
+ this.extractBlockInventory = extractInventory;
|
|
+ this.extractionMode = extractInventory instanceof BlockStateOnlyInventory ? HopperCachingState.BlockInventory.BLOCK_STATE : HopperCachingState.BlockInventory.UNKNOWN;
|
|
+ }
|
|
+ }
|
|
+ }
|
|
+
|
|
+ private static List<ItemEntity> lithiumGetInputItemEntities(Level world, Hopper hopper) {
|
|
+ if (!(hopper instanceof HopperBlockEntity hopperBlockEntity)) {
|
|
+ return getItemsAtAndAbove(world, hopper); //optimizations not implemented for hopper minecarts
|
|
+ }
|
|
+
|
|
+ if (hopperBlockEntity.collectItemEntityTracker == null) {
|
|
+ hopperBlockEntity.initCollectItemEntityTracker();
|
|
+ }
|
|
+
|
|
+ long modCount = InventoryHelper.getLithiumStackList(hopperBlockEntity).getModCount();
|
|
+
|
|
+ if ((hopperBlockEntity.collectItemEntityTrackerWasEmpty || hopperBlockEntity.myModCountAtLastItemCollect == modCount) &&
|
|
+ ChunkSectionEntityMovementTracker.isUnchangedSince(hopperBlockEntity.collectItemEntityAttemptTime, hopperBlockEntity.collectItemEntityTracker)) {
|
|
+ hopperBlockEntity.collectItemEntityAttemptTime = hopperBlockEntity.tickedGameTime;
|
|
+ return java.util.Collections.emptyList();
|
|
+ }
|
|
+
|
|
+ hopperBlockEntity.myModCountAtLastItemCollect = modCount;
|
|
+ hopperBlockEntity.shouldCheckSleep = false;
|
|
+
|
|
+ List<ItemEntity> itemEntities = ChunkSectionItemEntityMovementTracker.getEntities(world, hopperBlockEntity.collectItemEntityBox);
|
|
+ hopperBlockEntity.collectItemEntityAttemptTime = hopperBlockEntity.tickedGameTime;
|
|
+ hopperBlockEntity.collectItemEntityTrackerWasEmpty = itemEntities.isEmpty();
|
|
+ //set unchanged so that if this extract fails and there is no other change to hoppers or items, extracting
|
|
+ // items can be skipped.
|
|
+ return itemEntities;
|
|
+ }
|
|
+
|
|
+ private static @Nullable Boolean lithiumInsert(Level world, BlockPos pos, HopperBlockEntity hopperBlockEntity, @Nullable Container insertInventory) {
|
|
+ if (insertInventory == null || hopperBlockEntity instanceof net.minecraft.world.WorldlyContainer) {
|
|
+ //call the vanilla code to allow other mods inject features
|
|
+ //e.g. carpet mod allows hoppers to insert items into wool blocks
|
|
+ return null;
|
|
+ }
|
|
+
|
|
+ LithiumStackList hopperStackList = InventoryHelper.getLithiumStackList(hopperBlockEntity);
|
|
+ if (hopperBlockEntity.insertInventory == insertInventory && hopperStackList.getModCount() == hopperBlockEntity.myModCountAtLastInsert) {
|
|
+ if (hopperBlockEntity.insertStackList != null && hopperBlockEntity.insertStackList.getModCount() == hopperBlockEntity.insertStackListModCount) {
|
|
+// ComparatorUpdatePattern.NO_UPDATE.apply(hopperBlockEntity, hopperStackList); //commented because it's a noop, Hoppers do not send useless comparator updates
|
|
+ return false;
|
|
+ }
|
|
+ }
|
|
+
|
|
+ boolean insertInventoryWasEmptyHopperNotDisabled = insertInventory instanceof HopperBlockEntity hopperInv &&
|
|
+ !hopperInv.isOnCustomCooldown() && hopperBlockEntity.insertStackList != null &&
|
|
+ hopperBlockEntity.insertStackList.getOccupiedSlots() == 0;
|
|
+
|
|
+ boolean insertInventoryHandlesModdedCooldown =
|
|
+ insertInventory.canReceiveTransferCooldown() &&
|
|
+ hopperBlockEntity.insertStackList != null ?
|
|
+ hopperBlockEntity.insertStackList.getOccupiedSlots() == 0 :
|
|
+ insertInventory.isEmpty();
|
|
+
|
|
+ var worldData = world.getCurrentWorldData();
|
|
+ worldData.skipPushModeEventFire = worldData.skipHopperEvents;
|
|
+ //noinspection ConstantConditions
|
|
+ if (!(hopperBlockEntity.insertInventory == insertInventory && hopperBlockEntity.insertStackList.getFullSlots() == hopperBlockEntity.insertStackList.size())) {
|
|
+ Direction fromDirection = hopperBlockEntity.facing.getOpposite();
|
|
+ int size = hopperStackList.size();
|
|
+ for (int i = 0; i < size; ++i) {
|
|
+ ItemStack transferStack = hopperStackList.get(i);
|
|
+ if (!transferStack.isEmpty()) {
|
|
+ if (!worldData.skipPushModeEventFire && canTakeItemFromContainer(insertInventory, hopperBlockEntity, transferStack, i, Direction.DOWN)) {
|
|
+ transferStack = callPushMoveEvent(insertInventory, transferStack, hopperBlockEntity);
|
|
+ if (transferStack == null) { // cancelled
|
|
+ break;
|
|
+ }
|
|
+ }
|
|
+ boolean transferSuccess = HopperHelper.tryMoveSingleItem(insertInventory, transferStack, fromDirection);
|
|
+ if (transferSuccess) {
|
|
+ if (insertInventoryWasEmptyHopperNotDisabled) {
|
|
+ HopperBlockEntity receivingHopper = (HopperBlockEntity) insertInventory;
|
|
+ int k = 8;
|
|
+ if (receivingHopper.tickedGameTime >= hopperBlockEntity.tickedGameTime) {
|
|
+ k = 7;
|
|
+ }
|
|
+ receivingHopper.setCooldown(k);
|
|
+ }
|
|
+ if (insertInventoryHandlesModdedCooldown) {
|
|
+ insertInventory.setTransferCooldown(hopperBlockEntity.tickedGameTime);
|
|
+ }
|
|
+ insertInventory.setChanged();
|
|
+ return true;
|
|
+ }
|
|
+ }
|
|
+ }
|
|
+ }
|
|
+ hopperBlockEntity.myModCountAtLastInsert = hopperStackList.getModCount();
|
|
+ if (hopperBlockEntity.insertStackList != null) {
|
|
+ hopperBlockEntity.insertStackListModCount = hopperBlockEntity.insertStackList.getModCount();
|
|
+ }
|
|
+ return false;
|
|
+ }
|
|
+
|
|
+ private static @Nullable Boolean lithiumExtract(Level world, Hopper to, Container from) {
|
|
+ if (!(to instanceof HopperBlockEntity hopperBlockEntity)) {
|
|
+ return null; //optimizations not implemented for hopper minecarts
|
|
+ }
|
|
+
|
|
+ if (from != hopperBlockEntity.extractInventory || hopperBlockEntity.extractStackList == null) {
|
|
+ return null; //from inventory is not an optimized inventory, vanilla fallback
|
|
+ }
|
|
+
|
|
+ LithiumStackList hopperStackList = InventoryHelper.getLithiumStackList(hopperBlockEntity);
|
|
+ LithiumStackList fromStackList = hopperBlockEntity.extractStackList;
|
|
+
|
|
+ if (hopperStackList.getModCount() == hopperBlockEntity.myModCountAtLastExtract) {
|
|
+ if (fromStackList.getModCount() == hopperBlockEntity.extractStackListModCount) {
|
|
+ if (!(from instanceof ComparatorTracker comparatorTracker) || comparatorTracker.lithium$hasAnyComparatorNearby()) {
|
|
+ //noinspection CollectionAddedToSelf
|
|
+ fromStackList.runComparatorUpdatePatternOnFailedExtract(fromStackList, from);
|
|
+ }
|
|
+ return false;
|
|
+ }
|
|
+ }
|
|
+
|
|
+ int[] availableSlots = from instanceof WorldlyContainer ? ((WorldlyContainer) from).getSlotsForFace(Direction.DOWN) : null;
|
|
+ int fromSize = availableSlots != null ? availableSlots.length : from.getContainerSize();
|
|
+ for (int i = 0; i < fromSize; i++) {
|
|
+ int fromSlot = availableSlots != null ? availableSlots[i] : i;
|
|
+ ItemStack itemStack = fromStackList.get(fromSlot);
|
|
+ if (!itemStack.isEmpty() && canTakeItemFromContainer(to, from, itemStack, fromSlot, Direction.DOWN)) {
|
|
+ if (!world.getCurrentWorldData().skipPullModeEventFire) {
|
|
+ itemStack = callPullMoveEvent(to, from, itemStack);
|
|
+ if (itemStack == null) { // cancelled
|
|
+ return true;
|
|
+ }
|
|
+ }
|
|
+ //calling removeStack is necessary due to its side effects (markDirty in LootableContainerBlockEntity)
|
|
+ ItemStack takenItem = from.removeItem(fromSlot, 1);
|
|
+ assert !takenItem.isEmpty();
|
|
+ boolean transferSuccess = HopperHelper.tryMoveSingleItem(to, takenItem, null);
|
|
+ if (transferSuccess) {
|
|
+ to.setChanged();
|
|
+ from.setChanged();
|
|
+ return true;
|
|
+ }
|
|
+ //put the item back similar to vanilla
|
|
+ ItemStack restoredStack = fromStackList.get(fromSlot);
|
|
+ if (restoredStack.isEmpty()) {
|
|
+ restoredStack = takenItem;
|
|
+ } else {
|
|
+ restoredStack.grow(1);
|
|
+ }
|
|
+ //calling setStack is necessary due to its side effects (markDirty in LootableContainerBlockEntity)
|
|
+ from.setItem(fromSlot, restoredStack);
|
|
+ }
|
|
+ }
|
|
+ hopperBlockEntity.myModCountAtLastExtract = hopperStackList.getModCount();
|
|
+ if (fromStackList != null) {
|
|
+ hopperBlockEntity.extractStackListModCount = fromStackList.getModCount();
|
|
+ }
|
|
+ return false;
|
|
+ }
|
|
+ // Leaves end - Lithium Sleeping Block Entity
|
|
}
|
|
diff --git a/net/minecraft/world/level/block/entity/ShulkerBoxBlockEntity.java b/net/minecraft/world/level/block/entity/ShulkerBoxBlockEntity.java
|
|
index 174e39fb109bef3dd27ebc14aa13f6faabb10547..e898171acd7c4ef83d630e25c71222f4ee83445a 100644
|
|
--- a/net/minecraft/world/level/block/entity/ShulkerBoxBlockEntity.java
|
|
+++ b/net/minecraft/world/level/block/entity/ShulkerBoxBlockEntity.java
|
|
@@ -32,7 +32,7 @@ import net.minecraft.world.phys.AABB;
|
|
import net.minecraft.world.phys.Vec3;
|
|
import org.jspecify.annotations.Nullable;
|
|
|
|
-public class ShulkerBoxBlockEntity extends RandomizableContainerBlockEntity implements WorldlyContainer {
|
|
+public class ShulkerBoxBlockEntity extends RandomizableContainerBlockEntity implements WorldlyContainer, org.leavesmc.leaves.lithium.common.block.entity.inventory_change_tracking.InventoryChangeTracker, org.leavesmc.leaves.lithium.common.block.entity.SleepingBlockEntity, org.leavesmc.leaves.lithium.api.inventory.LithiumInventory { // Leaves - Lithium Sleeping Block Entity
|
|
public static final int COLUMNS = 9;
|
|
public static final int ROWS = 3;
|
|
public static final int CONTAINER_SIZE = 27;
|
|
@@ -134,6 +134,7 @@ public class ShulkerBoxBlockEntity extends RandomizableContainerBlockEntity impl
|
|
doNeighborUpdates(level, pos, blockState);
|
|
}
|
|
}
|
|
+ if (moe.monnairealms.camellia.config.modules.optimizations.LeavesSleepingBlockEntityConfig.enabled && this.animationStatus == ShulkerBoxBlockEntity.AnimationStatus.CLOSED && this.progressOld == 0.0f && this.progress == 0.0f) this.lithium$startSleeping(); // Leaves - Lithium Sleeping Block Entity
|
|
}
|
|
|
|
public ShulkerBoxBlockEntity.AnimationStatus getAnimationStatus() {
|
|
@@ -174,6 +175,7 @@ public class ShulkerBoxBlockEntity extends RandomizableContainerBlockEntity impl
|
|
|
|
@Override
|
|
public boolean triggerEvent(final int b0, final int b1) {
|
|
+ if (moe.monnairealms.camellia.config.modules.optimizations.LeavesSleepingBlockEntityConfig.enabled && this.sleepingTicker != null) this.wakeUpNow(); // Leaves - Lithium Sleeping Block Entity
|
|
if (b0 == EVENT_SET_OPEN_COUNT) {
|
|
this.openCount = b1;
|
|
if (b1 == 0) {
|
|
@@ -269,6 +271,7 @@ public class ShulkerBoxBlockEntity extends RandomizableContainerBlockEntity impl
|
|
@Override
|
|
protected void setItems(final NonNullList<ItemStack> items) {
|
|
this.itemStacks = items;
|
|
+ if (moe.monnairealms.camellia.config.modules.optimizations.LeavesSleepingBlockEntityConfig.enabled) this.lithium$emitStackListReplaced(); // Leaves - Lithium Sleeping Block Entity
|
|
}
|
|
|
|
@Override
|
|
@@ -309,4 +312,39 @@ public class ShulkerBoxBlockEntity extends RandomizableContainerBlockEntity impl
|
|
OPENED,
|
|
CLOSING;
|
|
}
|
|
+
|
|
+ // Leaves start - Lithium Sleeping Block Entity
|
|
+ private net.minecraft.world.level.chunk.LevelChunk.RebindableTickingBlockEntityWrapper tickWrapper = null;
|
|
+ private TickingBlockEntity sleepingTicker = null;
|
|
+
|
|
+ @Override
|
|
+ public net.minecraft.world.level.chunk.LevelChunk.RebindableTickingBlockEntityWrapper lithium$getTickWrapper() {
|
|
+ return tickWrapper;
|
|
+ }
|
|
+
|
|
+ @Override
|
|
+ public void lithium$setTickWrapper(net.minecraft.world.level.chunk.LevelChunk.RebindableTickingBlockEntityWrapper tickWrapper) {
|
|
+ this.tickWrapper = tickWrapper;
|
|
+ }
|
|
+
|
|
+ @Override
|
|
+ public TickingBlockEntity lithium$getSleepingTicker() {
|
|
+ return sleepingTicker;
|
|
+ }
|
|
+
|
|
+ @Override
|
|
+ public void lithium$setSleepingTicker(TickingBlockEntity sleepingTicker) {
|
|
+ this.sleepingTicker = sleepingTicker;
|
|
+ }
|
|
+
|
|
+ @Override
|
|
+ public net.minecraft.core.NonNullList<net.minecraft.world.item.ItemStack> getInventoryLithium() {
|
|
+ return itemStacks;
|
|
+ }
|
|
+
|
|
+ @Override
|
|
+ public void setInventoryLithium(net.minecraft.core.NonNullList<net.minecraft.world.item.ItemStack> inventory) {
|
|
+ itemStacks = inventory;
|
|
+ }
|
|
+ // Leaves end - Lithium Sleeping Block Entity
|
|
}
|
|
diff --git a/net/minecraft/world/level/block/entity/TickingBlockEntity.java b/net/minecraft/world/level/block/entity/TickingBlockEntity.java
|
|
index c8facee29ee08e0975528083f89b64f0b593957f..2499535f0aa699decad88917ab46fccc9b374088 100644
|
|
--- a/net/minecraft/world/level/block/entity/TickingBlockEntity.java
|
|
+++ b/net/minecraft/world/level/block/entity/TickingBlockEntity.java
|
|
@@ -12,4 +12,8 @@ public interface TickingBlockEntity {
|
|
String getType();
|
|
|
|
BlockEntity getTileEntity(); // Folia - region threading
|
|
+
|
|
+ // Camellia start - Region threading for lithium sleeping block entity
|
|
+ default void updateTicksForLithium(long redstoneGameTimeOffset) {}
|
|
+ // Camellia end
|
|
}
|
|
diff --git a/net/minecraft/world/level/block/state/BlockBehaviour.java b/net/minecraft/world/level/block/state/BlockBehaviour.java
|
|
index c78d77089e34c4bb559f173b449bfb7d91b05d5c..f4cce42ddd319cfd11cc43d68044f51b4514af38 100644
|
|
--- a/net/minecraft/world/level/block/state/BlockBehaviour.java
|
|
+++ b/net/minecraft/world/level/block/state/BlockBehaviour.java
|
|
@@ -83,7 +83,7 @@ import net.minecraft.world.phys.shapes.Shapes;
|
|
import net.minecraft.world.phys.shapes.VoxelShape;
|
|
import org.jspecify.annotations.Nullable;
|
|
|
|
-public abstract class BlockBehaviour implements FeatureElement {
|
|
+public abstract class BlockBehaviour implements FeatureElement, org.leavesmc.leaves.lithium.common.block.entity.ShapeUpdateHandlingBlockBehaviour { // Leaves - Lithium Sleeping Block Entity
|
|
protected static final Direction[] UPDATE_SHAPE_ORDER = new Direction[]{
|
|
Direction.WEST, Direction.EAST, Direction.NORTH, Direction.SOUTH, Direction.DOWN, Direction.UP
|
|
};
|
|
@@ -155,6 +155,7 @@ public abstract class BlockBehaviour implements FeatureElement {
|
|
final BlockState neighbourState,
|
|
final RandomSource random
|
|
) {
|
|
+ if (moe.monnairealms.camellia.config.modules.optimizations.LeavesSleepingBlockEntityConfig.enabled) this.lithium$handleShapeUpdate(level, state, pos, neighbourPos, neighbourState); // Leaves - Lithium Sleeping Block Entity /* Triggers when a shape update (= update that observers can detect) is sent */
|
|
return state;
|
|
}
|
|
|
|
diff --git a/net/minecraft/world/level/block/state/pattern/BlockPattern.java b/net/minecraft/world/level/block/state/pattern/BlockPattern.java
|
|
index ed5a5fb38bfe8fb9216c7eab00b833485c4bbade..fc45703525901d700c98b5ad0c6eb10b65e775d8 100644
|
|
--- a/net/minecraft/world/level/block/state/pattern/BlockPattern.java
|
|
+++ b/net/minecraft/world/level/block/state/pattern/BlockPattern.java
|
|
@@ -57,7 +57,7 @@ public class BlockPattern {
|
|
return this.matches(origin, forwards, up, cache);
|
|
}
|
|
|
|
- private BlockPattern.@Nullable BlockPatternMatch matches(
|
|
+ public BlockPattern.@Nullable BlockPatternMatch matches( // Leaves - private -> public
|
|
final BlockPos origin, final Direction forwards, final Direction up, final LoadingCache<BlockPos, BlockInWorld> cache
|
|
) {
|
|
for (int x = 0; x < this.width; x++) {
|
|
diff --git a/net/minecraft/world/level/chunk/LevelChunk.java b/net/minecraft/world/level/chunk/LevelChunk.java
|
|
index 0e84b695a677e71f443a29c78fc5025eec7ae7f4..3cb6c24a21538569d73b95803dde7e4a2fdb67f5 100644
|
|
--- a/net/minecraft/world/level/chunk/LevelChunk.java
|
|
+++ b/net/minecraft/world/level/chunk/LevelChunk.java
|
|
@@ -622,6 +622,7 @@ public class LevelChunk extends ChunkAccess implements DebugValueSource, ca.spot
|
|
LevelChunk.RebindableTickingBlockEntityWrapper ticker = this.tickersInLevel.remove(pos);
|
|
if (ticker != null) {
|
|
ticker.rebind(NULL_TICKER);
|
|
+ ticker.createdBy = null; // Camellia - Region threading for sleeping block entity
|
|
}
|
|
}
|
|
|
|
@@ -883,6 +884,7 @@ public class LevelChunk extends ChunkAccess implements DebugValueSource, ca.spot
|
|
this.blockEntities.values().forEach(BlockEntity::setRemoved);
|
|
this.blockEntities.clear();
|
|
this.tickersInLevel.values().forEach(ticker -> ticker.rebind(NULL_TICKER));
|
|
+ this.tickersInLevel.values().forEach(ticker -> ticker.createdBy = null); // Camellia - Region threading for sleeping block entity
|
|
this.tickersInLevel.clear();
|
|
}
|
|
|
|
@@ -916,10 +918,14 @@ public class LevelChunk extends ChunkAccess implements DebugValueSource, ca.spot
|
|
this.tickersInLevel.compute(blockEntity.getBlockPos(), (blockPos, existingTicker) -> {
|
|
TickingBlockEntity actualTicker = this.createTicker(blockEntity, ticker);
|
|
if (existingTicker != null) {
|
|
+ if (moe.monnairealms.camellia.config.modules.optimizations.LeavesSleepingBlockEntityConfig.enabled && blockEntity instanceof org.leavesmc.leaves.lithium.common.block.entity.SleepingBlockEntity sleepingBlockEntity) sleepingBlockEntity.lithium$setTickWrapper(existingTicker); // Leaves - Lithium Sleeping Block Entity
|
|
+ if (moe.monnairealms.camellia.config.modules.optimizations.LeavesSleepingBlockEntityConfig.enabled) existingTicker.createdBy = blockEntity; // Camellia - Region threading for lithium sleeping block entity
|
|
existingTicker.rebind(actualTicker);
|
|
return (LevelChunk.RebindableTickingBlockEntityWrapper)existingTicker;
|
|
} else if (this.isInLevel()) {
|
|
LevelChunk.RebindableTickingBlockEntityWrapper result = new LevelChunk.RebindableTickingBlockEntityWrapper(actualTicker);
|
|
+ if (moe.monnairealms.camellia.config.modules.optimizations.LeavesSleepingBlockEntityConfig.enabled && blockEntity instanceof org.leavesmc.leaves.lithium.common.block.entity.SleepingBlockEntity sleepingBlockEntity) sleepingBlockEntity.lithium$setTickWrapper(result); // Leaves - Lithium Sleeping Block Entity
|
|
+ if (moe.monnairealms.camellia.config.modules.optimizations.LeavesSleepingBlockEntityConfig.enabled) result.createdBy = blockEntity; // Camellia - Region threading for lithium sleeping block entity
|
|
this.level.addBlockEntityTicker(result);
|
|
return result;
|
|
} else {
|
|
@@ -1028,20 +1034,36 @@ public class LevelChunk extends ChunkAccess implements DebugValueSource, ca.spot
|
|
void run(LevelChunk levelChunk);
|
|
}
|
|
|
|
- private static class RebindableTickingBlockEntityWrapper implements TickingBlockEntity {
|
|
- private TickingBlockEntity ticker;
|
|
+ public static class RebindableTickingBlockEntityWrapper implements TickingBlockEntity { // Leaves - default -> public
|
|
+ public TickingBlockEntity ticker; // Leaves - private -> public
|
|
+ @org.jetbrains.annotations.Nullable private BlockEntity createdBy; // Camellia - Region threading for lithium sleeping block entity
|
|
|
|
private RebindableTickingBlockEntityWrapper(final TickingBlockEntity ticker) {
|
|
this.ticker = ticker;
|
|
}
|
|
|
|
- private void rebind(final TickingBlockEntity ticker) {
|
|
+ public void rebind(final TickingBlockEntity ticker) { // Leaves - default -> public
|
|
this.ticker = ticker;
|
|
}
|
|
|
|
// Folia start - region threading
|
|
@Override
|
|
public BlockEntity getTileEntity() {
|
|
+ // Camellia start - Region threading for lithium sleeping block entity
|
|
+ if (true) {
|
|
+ if (this.ticker != null) {
|
|
+ var ret = this.ticker.getTileEntity();
|
|
+
|
|
+ if (ret == null) {
|
|
+ return this.createdBy;
|
|
+ }
|
|
+
|
|
+ return ret;
|
|
+ }
|
|
+
|
|
+ return null;
|
|
+ }
|
|
+ // Camellia end
|
|
return this.ticker == null ? null : this.ticker.getTileEntity();
|
|
}
|
|
// Folia end - region threading
|
|
@@ -1070,6 +1092,16 @@ public class LevelChunk extends ChunkAccess implements DebugValueSource, ca.spot
|
|
public String toString() {
|
|
return this.ticker + " <wrapped>";
|
|
}
|
|
+
|
|
+ // Camellia start - Region threading for lithium sleeping block entity
|
|
+ @Override
|
|
+ public void updateTicksForLithium(long redstoneGameTimeOffset) {
|
|
+ if (this.ticker != null) {
|
|
+ this.ticker.updateTicksForLithium(redstoneGameTimeOffset);
|
|
+ }
|
|
+ }
|
|
+
|
|
+ // Camellia end
|
|
}
|
|
|
|
@FunctionalInterface
|