Yatopia/patches/server/0065-lithium-skip-ticking-block-entities-that-are-doing-n.patch
2021-06-02 22:37:38 -04:00

1218 lines
49 KiB
Diff

From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
From: 2No2Name <50278648+2No2Name@users.noreply.github.com>
Date: Sun, 21 Feb 2021 21:34:18 -0500
Subject: [PATCH] lithium: skip ticking block entities that are doing nothing
diff --git a/src/main/java/me/jellysquid/mods/lithium/common/util/collections/ListeningList.java b/src/main/java/me/jellysquid/mods/lithium/common/util/collections/ListeningList.java
new file mode 100644
index 0000000000000000000000000000000000000000..edcc9ec27cc7d8dc5bf04e1f70362b505742570c
--- /dev/null
+++ b/src/main/java/me/jellysquid/mods/lithium/common/util/collections/ListeningList.java
@@ -0,0 +1,255 @@
+package me.jellysquid.mods.lithium.common.util.collections;
+
+import org.jetbrains.annotations.NotNull;
+
+import java.util.*;
+import java.util.function.Consumer;
+import java.util.function.Predicate;
+import java.util.function.UnaryOperator;
+import java.util.stream.Stream;
+
+public class ListeningList<T> implements List<T> {
+ private final List<T> delegate;
+ private final Runnable changeCallback;
+
+ public ListeningList(List<T> delegate, Runnable changeCallback) {
+ this.delegate = delegate;
+ this.changeCallback = changeCallback;
+ }
+
+ private void onChange() {
+ this.changeCallback.run();
+ }
+
+
+ @Override
+ public int size() {
+ return this.delegate.size();
+ }
+
+ @Override
+ public boolean isEmpty() {
+ return this.delegate.isEmpty();
+ }
+
+ @Override
+ public boolean contains(Object o) {
+ return this.delegate.contains(o);
+ }
+
+ @NotNull
+ @Override
+ public Iterator<T> iterator() {
+ return this.listIterator();
+ }
+
+ @NotNull
+ @Override
+ public Object[] toArray() {
+ return this.delegate.toArray();
+ }
+
+ @Override
+ public void forEach(Consumer<? super T> consumer) {
+ this.delegate.forEach(consumer);
+ }
+
+ @NotNull
+ @Override
+ public <T1> T1[] toArray(@NotNull T1[] t1s) {
+ //noinspection SuspiciousToArrayCall
+ return this.delegate.toArray(t1s);
+ }
+
+ @Override
+ public boolean add(T t) {
+ boolean add = this.delegate.add(t);
+ this.onChange();
+ //noinspection ConstantConditions
+ return add;
+ }
+
+ @Override
+ public boolean remove(Object o) {
+ boolean remove = this.delegate.remove(o);
+ this.onChange();
+ return remove;
+ }
+
+ @Override
+ public boolean containsAll(@NotNull Collection<?> collection) {
+ return this.delegate.containsAll(collection);
+ }
+
+ @Override
+ public boolean addAll(@NotNull Collection<? extends T> collection) {
+ boolean addAll = this.delegate.addAll(collection);
+ this.onChange();
+ return addAll;
+ }
+
+ @Override
+ public boolean addAll(int i, @NotNull Collection<? extends T> collection) {
+ boolean addAll = this.delegate.addAll(i, collection);
+ this.onChange();
+ return addAll;
+ }
+
+ @Override
+ public boolean removeAll(@NotNull Collection<?> collection) {
+ boolean b = this.delegate.removeAll(collection);
+ this.onChange();
+ return b;
+ }
+
+ @Override
+ public boolean removeIf(Predicate<? super T> predicate) {
+ boolean b = this.delegate.removeIf(predicate);
+ this.onChange();
+ return b;
+ }
+
+ @Override
+ public boolean retainAll(@NotNull Collection<?> collection) {
+ boolean b = this.delegate.retainAll(collection);
+ this.onChange();
+ return b;
+ }
+
+ @Override
+ public void replaceAll(UnaryOperator<T> unaryOperator) {
+ this.delegate.replaceAll( unaryOperator);
+ this.onChange();
+ }
+
+ @Override
+ public void sort(Comparator<? super T> comparator) {
+ this.delegate.sort(comparator);
+ this.onChange();
+ }
+
+ @Override
+ public void clear() {
+ this.delegate.clear();
+ this.onChange();
+ }
+
+ @Override
+ public T get(int i) {
+ return this.delegate.get(i);
+ }
+
+ @Override
+ public T set(int i, T t) {
+ T set = this.delegate.set(i, t);
+ this.onChange();
+ return set;
+ }
+
+ @Override
+ public void add(int i, T t) {
+ this.delegate.add(i, t);
+ this.onChange();
+ }
+
+ @Override
+ public T remove(int i) {
+ T remove = this.delegate.remove(i);
+ this.onChange();
+ return remove;
+ }
+
+ @Override
+ public int indexOf(Object o) {
+ return this.delegate.indexOf(o);
+ }
+
+ @Override
+ public int lastIndexOf(Object o) {
+ return this.delegate.lastIndexOf(o);
+ }
+
+ @NotNull
+ @Override
+ public ListIterator<T> listIterator() {
+ return this.listIterator(0);
+ }
+
+ @NotNull
+ @Override
+ public ListIterator<T> listIterator(int i) {
+ return new ListIterator<T>() {
+ final ListIterator<T> itDelegate = ListeningList.this.delegate.listIterator(i);
+
+ @Override
+ public boolean hasNext() {
+ return this.itDelegate.hasNext();
+ }
+
+ @Override
+ public T next() {
+ return this.itDelegate.next();
+ }
+
+ @Override
+ public boolean hasPrevious() {
+ return this.itDelegate.hasPrevious();
+ }
+
+ @Override
+ public T previous() {
+ return this.itDelegate.previous();
+ }
+
+ @Override
+ public int nextIndex() {
+ return this.itDelegate.nextIndex();
+ }
+
+ @Override
+ public int previousIndex() {
+ return this.itDelegate.previousIndex();
+ }
+
+ @Override
+ public void remove() {
+ this.itDelegate.remove();
+ ListeningList.this.onChange();
+ }
+
+ @Override
+ public void set(T t) {
+ this.itDelegate.set(t);
+ ListeningList.this.onChange();
+
+ }
+
+ @Override
+ public void add(T t) {
+ this.itDelegate.add(t);
+ ListeningList.this.onChange();
+ }
+ };
+ }
+
+ @NotNull
+ @Override
+ public List<T> subList(int i, int i1) {
+ throw new UnsupportedOperationException();
+ }
+
+ @Override
+ public Spliterator<T> spliterator() {
+ return this.delegate.spliterator();
+ }
+
+ @Override
+ public Stream<T> stream() {
+ return this.delegate.stream();
+ }
+
+ @Override
+ public Stream<T> parallelStream() {
+ return this.delegate.parallelStream();
+ }
+}
\ No newline at end of file
diff --git a/src/main/java/me/jellysquid/mods/lithium/common/util/collections/MaskedTickingBlockEntityList.java b/src/main/java/me/jellysquid/mods/lithium/common/util/collections/MaskedTickingBlockEntityList.java
new file mode 100644
index 0000000000000000000000000000000000000000..7f7e4810a9aca382d75862e56b0cf93157b54b92
--- /dev/null
+++ b/src/main/java/me/jellysquid/mods/lithium/common/util/collections/MaskedTickingBlockEntityList.java
@@ -0,0 +1,320 @@
+package me.jellysquid.mods.lithium.common.util.collections;
+
+import com.google.common.collect.Iterators;
+import it.unimi.dsi.fastutil.ints.IntArrayList;
+import it.unimi.dsi.fastutil.objects.Reference2IntOpenHashMap;
+import it.unimi.dsi.fastutil.objects.ReferenceArrayList;
+import org.jetbrains.annotations.NotNull;
+
+import java.util.*;
+import java.util.function.Predicate;
+
+public class MaskedTickingBlockEntityList<T> implements List<T> {
+ private final Predicate<T> mayContain;
+
+ private final Reference2IntOpenHashMap<T> allElements2Index;
+ private final ReferenceArrayList<T> allElements;
+
+ private final IntArrayList filteredSuccessor;
+ private final BitSet filteredElementsMask;
+
+ private int firstRemovedIndex;
+
+ //Visualization of the internal datastructures
+ //indices: 0 1 2 3 4 5 6 7 8 9
+ //allElements: A B C D - F G H I J //E was fully removed, C,F,G,I were filtered away
+ //filteredMask: 1 1 0 1 0 0 0 1 0 1
+ //successor: 0 1 3 - 7 - - - 9 - - (index offset by 1, due to the first successor having to point to the first element)
+ //Removals from the allElements ArrayList are done by setting the value to null
+ //The successor list is used to iterate through the allElements ArrayList with an increasing index, but skipping long chains of null elements.
+ //The BitSet mask is used to find the predecessor and successor quickly (not asymptotically fast, but fast enough)
+
+ public MaskedTickingBlockEntityList(List<T> list, Predicate<T> mayContain) {
+ this.mayContain = mayContain;
+ this.allElements = new ReferenceArrayList<>();
+ this.allElements2Index = new Reference2IntOpenHashMap<>();
+ this.allElements2Index.defaultReturnValue(-1);
+ this.filteredSuccessor = new IntArrayList();
+ this.filteredElementsMask = new BitSet();
+ this.firstRemovedIndex = Integer.MAX_VALUE;
+
+ for (T t : list) {
+ if (this.mayContain.test(t)) {
+ int index = this.allElements.size();
+ this.allElements.add(t);
+ this.filteredElementsMask.set(index);
+ this.filteredSuccessor.add(index);
+ this.allElements2Index.put(t, index);
+ }
+ }
+ this.filteredSuccessor.add(-1);
+ }
+
+ public void setEntryVisible(T t, boolean value) {
+ this.setEntryVisible(this.allElements2Index.getOrDefault(t, -1), value);
+ }
+
+ public void setEntryVisible(int index, boolean value) {
+ //Visualization of the operations possible
+ //All: A B C D - F G H I J (- for null)
+ //filteredMask:1 1 0 1 0 0 0 1 0 1
+ //indices: 0 1 2 3 4 5 6 7 8 9
+ //successor: 0 1 3 - 7 - - - 9 - - (- for no successor)
+ //Set F visible:
+ //All: A B C D - F G H I J
+ //filteredMask:1 1 0 1 0 1 0 1 0 1 //set mask at F to 1
+ //indices: 0 1 2 3 4 5 6 7 8 9
+ //successor: 0 1 3 - 5 - 7 - 9 - - //update successor of predecessor to F and set F's successor to old successor of predecessor
+ //Set D filtered:
+ //All: A B C D - F G H I J
+ //Mask: 1 1 0 0 0 1 0 1 0 1 //set mask at D to 0
+ //indices: 0 1 2 3 4 5 6 7 8 9
+ //successor: 0 1 5 - - - 7 - 9 - - //update successor of predecessor to old successor of D and remove D's successor value
+
+ //These calls do not modify the size, they can't cause rehashing, they are safe to use during iteration
+ if (index == -1 || value == this.filteredElementsMask.get(index)) {
+ return;
+ }
+
+ this.filteredElementsMask.set(index, value);
+ int predecessor = this.filteredElementsMask.previousSetBit(index - 1);
+ if (value) {
+ int successor = this.filteredSuccessor.getInt(predecessor + 1);
+ this.filteredSuccessor.set(predecessor + 1, index);
+ this.filteredSuccessor.set(index + 1, successor);
+ } else {
+ int successor = this.filteredSuccessor.getInt(index + 1);
+ this.filteredSuccessor.set(predecessor + 1, successor);
+ this.filteredSuccessor.set(index + 1, -2); //no successor as this element cannot be reached
+ }
+ }
+
+ private void compact() {
+ int targetSize = this.size();
+ int newIndex = this.firstRemovedIndex - 1;
+ int lastVisible = this.filteredElementsMask.previousSetBit(newIndex);
+
+
+ for (int i = newIndex + 1; i < this.allElements.size(); i++) {
+ T t = this.allElements.get(i);
+ if (t == null) {
+ continue;
+ }
+ boolean visible = this.filteredElementsMask.get(i);
+ //shift all entries to the lower indices (filling the gaps created by remove() setting null)
+ newIndex++;
+ //i is guaranteed to not be smaller than newIndex, therefore we can write to the same collections
+
+ this.allElements.set(newIndex, t);
+ this.allElements2Index.put(t, newIndex);
+ this.filteredElementsMask.set(newIndex, visible);
+
+ //update the successor links
+ this.filteredSuccessor.set(newIndex + 1, -2); //no successor as there is no next entry yet
+ if (visible) {
+ this.filteredSuccessor.set(lastVisible + 1, newIndex);
+ lastVisible = newIndex;
+ }
+ }
+
+ if (newIndex + 1 != targetSize) {
+ throw new IllegalStateException("Compaction ended up with incorrect size: Should be: " + targetSize + " but is: " + (newIndex + 1));
+ }
+
+ this.filteredSuccessor.set(lastVisible + 1, -1); //-1 means this was the last element
+ this.firstRemovedIndex = Integer.MAX_VALUE;
+
+ this.filteredSuccessor.removeElements(targetSize + 1, this.filteredSuccessor.size());
+ this.allElements.removeElements(targetSize, this.allElements.size());
+ this.filteredElementsMask.clear(targetSize, this.filteredElementsMask.size());
+
+ this.filteredSuccessor.trim(targetSize * 4);
+ this.allElements.trim(targetSize * 4);
+ this.allElements2Index.trim(targetSize * 4);
+ }
+
+ public Iterator<T> filteredIterator() {
+ return new Iterator<T>() {
+ int next = MaskedTickingBlockEntityList.this.filteredSuccessor.getInt(0);
+ T prev;
+
+ @Override
+ public boolean hasNext() {
+ return this.next != -1;
+ }
+
+ @Override
+ public T next() {
+ int next = this.next;
+ T prev = MaskedTickingBlockEntityList.this.allElements.get(next);
+ this.prev = prev;
+ this.next = MaskedTickingBlockEntityList.this.filteredSuccessor.getInt(next + 1);
+ return prev;
+ }
+
+ @Override
+ public void remove() {
+ MaskedTickingBlockEntityList.this.remove(this.prev);
+ }
+ };
+ }
+
+ @Override
+ public int size() {
+ return this.allElements2Index.size();
+ }
+
+ @Override
+ public boolean isEmpty() {
+ return this.size() == 0;
+ }
+
+ @Override
+ public boolean contains(Object o) {
+ //noinspection SuspiciousMethodCalls
+ return this.allElements2Index.containsKey(o);
+ }
+
+ @Override
+ public @NotNull Iterator<T> iterator() {
+ return Iterators.unmodifiableIterator(this.allElements2Index.keySet().iterator());
+ }
+
+ @Override
+ public Object[] toArray() {
+ return this.allElements2Index.keySet().toArray();
+ }
+
+ @NotNull
+ @Override
+ public <T1> T1[] toArray(@NotNull T1[] t1s) {
+ //noinspection SuspiciousToArrayCall
+ return this.allElements2Index.keySet().toArray(t1s);
+ }
+
+ @Override
+ public boolean add(T t) {
+ int arraySize = this.allElements.size();
+ int invalidEntries = arraySize - this.size();
+ //Compaction is done during the add operation as it is guaranteed to not happen during iteration
+ if ((arraySize > 2048 && invalidEntries > (arraySize >> 1)) || arraySize >= Integer.MAX_VALUE - 1 && invalidEntries != 0) {
+ this.compact();
+ }
+
+ if (!this.mayContain.test(t)) {
+ return false;
+ }
+
+ int index = this.allElements.size();
+ int i = this.allElements2Index.putIfAbsent(t, index);
+ if (i != -1) {
+ return false;
+ }
+ this.allElements.add(t);
+ this.filteredSuccessor.add(0);//increase size so setEntryVisible doesn't crash with indexOutOfBounds
+ this.setEntryVisible(index, true);
+
+ return true;
+ }
+
+ @Override
+ public boolean remove(Object o) {
+ int index = this.allElements2Index.removeInt(o);
+ if (index == -1) {
+ return false;
+ }
+ this.setEntryVisible(index, false);
+ this.allElements.set(index, null);
+ this.firstRemovedIndex = Math.min(this.firstRemovedIndex, index);
+ return true;
+ }
+
+ @Override
+ public boolean containsAll(@NotNull Collection<?> c) {
+ return this.allElements2Index.keySet().containsAll(c);
+ }
+
+ @Override
+ public boolean addAll(@NotNull Collection<? extends T> c) {
+ boolean b = false;
+ for (T t : c) {
+ this.add(t);
+ b = true;
+ }
+ return b;
+ }
+
+ @Override
+ public boolean addAll(int index, @NotNull Collection<? extends T> c) {
+ throw new UnsupportedOperationException();
+ }
+
+ @Override
+ public boolean removeAll(@NotNull Collection<?> c) {
+ boolean b = false;
+ for (Object t : c) {
+ b |= this.remove(t);
+ }
+ return b;
+ }
+
+ @Override
+ public boolean retainAll(@NotNull Collection<?> c) {
+ throw new UnsupportedOperationException();
+ }
+
+ @Override
+ public void clear() {
+ this.allElements2Index.clear();
+ this.allElements.clear();
+ this.filteredSuccessor.clear();
+ this.filteredElementsMask.clear();
+ this.firstRemovedIndex = Integer.MAX_VALUE;
+ this.filteredSuccessor.add(-1);
+ }
+
+ @Override
+ public T get(int index) {
+ throw new UnsupportedOperationException();
+ }
+
+ @Override
+ public T set(int index, T element) {
+ throw new UnsupportedOperationException();
+ }
+
+ @Override
+ public void add(int index, T element) {
+ throw new UnsupportedOperationException();
+ }
+
+ @Override
+ public T remove(int index) {
+ throw new UnsupportedOperationException();
+ }
+
+ @Override
+ public int indexOf(Object o) {
+ throw new UnsupportedOperationException();
+ }
+
+ @Override
+ public int lastIndexOf(Object o) {
+ throw new UnsupportedOperationException();
+ }
+
+ @Override
+ public @NotNull ListIterator<T> listIterator() {
+ throw new UnsupportedOperationException();
+ }
+
+ @Override
+ public @NotNull ListIterator<T> listIterator(int index) {
+ throw new UnsupportedOperationException();
+ }
+
+ @Override
+ public @NotNull List<T> subList(int fromIndex, int toIndex) {
+ throw new UnsupportedOperationException();
+ }
+}
diff --git a/src/main/java/me/jellysquid/mods/lithium/common/world/blockentity/BlockEntitySleepTracker.java b/src/main/java/me/jellysquid/mods/lithium/common/world/blockentity/BlockEntitySleepTracker.java
new file mode 100644
index 0000000000000000000000000000000000000000..c54e1e1f9c6b09022c0f20d5ea4d552bd3ceed55
--- /dev/null
+++ b/src/main/java/me/jellysquid/mods/lithium/common/world/blockentity/BlockEntitySleepTracker.java
@@ -0,0 +1,7 @@
+package me.jellysquid.mods.lithium.common.world.blockentity;
+
+import net.minecraft.world.level.block.entity.TileEntity;
+
+public interface BlockEntitySleepTracker {
+ void setAwake(TileEntity tileEntity, boolean needsTicking);
+}
\ No newline at end of file
diff --git a/src/main/java/me/jellysquid/mods/lithium/common/world/blockentity/SleepingBlockEntity.java b/src/main/java/me/jellysquid/mods/lithium/common/world/blockentity/SleepingBlockEntity.java
new file mode 100644
index 0000000000000000000000000000000000000000..4e765ab19ffb300b6c810333b2dc797637ae5c1b
--- /dev/null
+++ b/src/main/java/me/jellysquid/mods/lithium/common/world/blockentity/SleepingBlockEntity.java
@@ -0,0 +1,7 @@
+package me.jellysquid.mods.lithium.common.world.blockentity;
+
+public interface SleepingBlockEntity {
+ default boolean canTickOnSide(boolean isClient) {
+ return true;
+ }
+}
\ No newline at end of file
diff --git a/src/main/java/net/minecraft/world/level/World.java b/src/main/java/net/minecraft/world/level/World.java
index a5dd3b71f9b96047826d01002dbad718c463500c..324342f57249be6a37d7ad10a326a71edcd2fa82 100644
--- a/src/main/java/net/minecraft/world/level/World.java
+++ b/src/main/java/net/minecraft/world/level/World.java
@@ -97,8 +97,11 @@ import org.bukkit.event.block.BlockPhysicsEvent;
// CraftBukkit end
import net.gegy1000.tictacs.NonBlockingWorldAccess; // Yatopia
+import me.jellysquid.mods.lithium.common.util.collections.MaskedTickingBlockEntityList; // Yatopia
+import me.jellysquid.mods.lithium.common.world.blockentity.BlockEntitySleepTracker; // Yatopia
+import me.jellysquid.mods.lithium.common.world.blockentity.SleepingBlockEntity; // Yatopia
-public abstract class World implements GeneratorAccess, AutoCloseable, NonBlockingWorldAccess { // Yatopia
+public abstract class World implements GeneratorAccess, AutoCloseable, NonBlockingWorldAccess, BlockEntitySleepTracker { // Yatopia
protected static final Logger LOGGER = LogManager.getLogger();
public static final Codec<ResourceKey<World>> f = MinecraftKey.a.xmap(ResourceKey.b(IRegistry.L), ResourceKey::a);
@@ -107,9 +110,17 @@ public abstract class World implements GeneratorAccess, AutoCloseable, NonBlocki
public static final ResourceKey<World> THE_END = ResourceKey.a(IRegistry.L, new MinecraftKey("the_end"));
private static final EnumDirection[] a = EnumDirection.values();
//public final List<TileEntity> tileEntityList = Lists.newArrayList(); // Paper - remove unused list
- public final List<TileEntity> tileEntityListTick = me.jellysquid.mods.lithium.common.util.collections.HashedList.wrapper(Lists.newArrayList()); // Yatopia
+ public List<TileEntity> tileEntityListTick = me.jellysquid.mods.lithium.common.util.collections.HashedList.wrapper(Lists.newArrayList()); // Yatopia
protected final List<TileEntity> tileEntityListPending = me.jellysquid.mods.lithium.common.util.collections.HashedList.wrapper(Lists.newArrayList()); // Yatopia
protected final java.util.Set<TileEntity> tileEntityListUnload = java.util.Collections.newSetFromMap(new java.util.IdentityHashMap<>()); // Airplane - use set with faster contains
+ // Yatopia start - lithium: skip ticking block entities that are doing nothing
+ private MaskedTickingBlockEntityList<TileEntity> tileEntityListTick$lithium;
+
+ @Override
+ public void setAwake(TileEntity tileEntity, boolean needsTicking) {
+ this.tileEntityListTick$lithium.setEntryVisible(tileEntity, needsTicking);
+ }
+ // Yatopia end
public final Thread serverThread;
private final boolean debugWorld;
private int d;
@@ -332,6 +343,8 @@ public abstract class World implements GeneratorAccess, AutoCloseable, NonBlocki
this.keepSpawnInMemory = this.paperConfig.keepSpawnInMemory; // Paper
this.entityLimiter = new org.spigotmc.TickLimiter(spigotConfig.entityMaxTickTime);
this.tileLimiter = new org.spigotmc.TickLimiter(spigotConfig.tileMaxTickTime);
+ this.tileEntityListTick$lithium = new MaskedTickingBlockEntityList<>(this.tileEntityListTick, blockEntity -> ((SleepingBlockEntity) blockEntity).canTickOnSide(false)); // Yatopia
+ this.tileEntityListTick = tileEntityListTick$lithium; // Yatopia
}
// Paper start
@@ -996,6 +1009,15 @@ public abstract class World implements GeneratorAccess, AutoCloseable, NonBlocki
}
+ // Yatopia start - lithium: skip ticking block entities that are doing nothing
+ public Iterator<TileEntity> getAwakeBlockEntities(List<TileEntity> list) {
+ if (list == this.tileEntityListTick && list instanceof MaskedTickingBlockEntityList) {
+ return ((MaskedTickingBlockEntityList<TileEntity>) list).filteredIterator();
+ }
+ return list.iterator();
+ }
+ // Yatopia end
+
public void tickBlockEntities() {
GameProfilerFiller gameprofilerfiller = this.getMethodProfiler();
@@ -1018,11 +1040,19 @@ public abstract class World implements GeneratorAccess, AutoCloseable, NonBlocki
this.tickingTileEntities = true;
// Spigot start
+ // Yatopia start - lithium: skip ticking block entities that are doing nothing
// Iterator iterator = this.tileEntityListTick.iterator();
+ Iterator iterator = getAwakeBlockEntities(this.tileEntityListTick);
+
int tilesThisCycle = 0;
+ while (iterator.hasNext()) {
+ TileEntity tileentity = (TileEntity) iterator.next();
+ /*
for (tileTickPosition = 0; tileTickPosition < tileEntityListTick.size(); tileTickPosition++) { // Paper - Disable tick limiters
tileTickPosition = (tileTickPosition < tileEntityListTick.size()) ? tileTickPosition : 0;
TileEntity tileentity = (TileEntity) this.tileEntityListTick.get(tileTickPosition);
+ */
+ // Yatopia end
// Spigot start
if (tileentity == null) {
getServer().getLogger().severe("Spigot has detected a null entity and has removed it, preventing a crash");
@@ -1060,8 +1090,7 @@ public abstract class World implements GeneratorAccess, AutoCloseable, NonBlocki
throwable.printStackTrace();
getServer().getPluginManager().callEvent(new ServerExceptionEvent(new ServerInternalException(msg, throwable)));
// Paper end
- tilesThisCycle--;
- this.tileEntityListTick.remove(tileTickPosition--);
+ iterator.remove(); // Yatopia
continue;
// Paper end
// Spigot start
@@ -1074,8 +1103,7 @@ public abstract class World implements GeneratorAccess, AutoCloseable, NonBlocki
if (tileentity.isRemoved()) {
// Spigot start
- tilesThisCycle--;
- this.tileEntityListTick.remove(tileTickPosition--);
+ iterator.remove(); // Yatopia
// Spigot end
//this.tileEntityList.remove(tileentity); // Paper - remove unused list
// Paper - prevent double chunk lookups
diff --git a/src/main/java/net/minecraft/world/level/block/entity/TileEntity.java b/src/main/java/net/minecraft/world/level/block/entity/TileEntity.java
index 93d02ccb87c17404c55884f52ae40c7b7ddfb103..cc9e6b9e5f550f9e633ea124f3dd8cbcf0e43e12 100644
--- a/src/main/java/net/minecraft/world/level/block/entity/TileEntity.java
+++ b/src/main/java/net/minecraft/world/level/block/entity/TileEntity.java
@@ -26,8 +26,9 @@ import org.bukkit.inventory.InventoryHolder;
import org.spigotmc.CustomTimingsHandler; // Spigot
import co.aikar.timings.MinecraftTimings; // Paper
import co.aikar.timings.Timing; // Paper
+import me.jellysquid.mods.lithium.common.world.blockentity.SleepingBlockEntity;
-public abstract class TileEntity implements net.minecraft.server.KeyedObject { // Paper
+public abstract class TileEntity implements net.minecraft.server.KeyedObject, SleepingBlockEntity { // Paper // Yatopia
public Timing tickTimer = MinecraftTimings.getTileEntityTimings(this); // Paper
// CraftBukkit start - data containers
diff --git a/src/main/java/net/minecraft/world/level/block/entity/TileEntityBeehive.java b/src/main/java/net/minecraft/world/level/block/entity/TileEntityBeehive.java
index cacef4349a8dba02c2faee77e30f7c938f3d31af..a1651a7155f7fe2f01882a1eee4fbb5a067e1b38 100644
--- a/src/main/java/net/minecraft/world/level/block/entity/TileEntityBeehive.java
+++ b/src/main/java/net/minecraft/world/level/block/entity/TileEntityBeehive.java
@@ -23,6 +23,9 @@ import net.minecraft.world.level.block.BlockBeehive;
import net.minecraft.world.level.block.BlockCampfire;
import net.minecraft.world.level.block.BlockFire;
import net.minecraft.world.level.block.state.IBlockData;
+import me.jellysquid.mods.lithium.common.util.collections.ListeningList;
+import me.jellysquid.mods.lithium.common.world.blockentity.BlockEntitySleepTracker;
+import java.util.ArrayList;
public class TileEntityBeehive extends TileEntity implements ITickable {
@@ -30,11 +33,24 @@ public class TileEntityBeehive extends TileEntity implements ITickable {
@Nullable
public BlockPosition flowerPos = null;
public int maxBees = 3; // CraftBukkit - allow setting max amount of bees a hive can hold
+ public boolean doInit = true; // Yatopia
+ public boolean isTicking = true; // Yatopia
public TileEntityBeehive() {
super(TileEntityTypes.BEEHIVE);
}
+ // Yatopia start - lithium: skip ticking block entities that are doing nothing
+ public void checkSleepState() {
+ if (this.world != null ) {
+ if ((this.bees.size() == 0) == this.isTicking) {
+ this.isTicking = !this.isTicking;
+ ((BlockEntitySleepTracker) this.world).setAwake(this, this.isTicking);
+ }
+ }
+ }
+ // Yatopia end
+
@Override
public void update() {
if (this.d()) {
@@ -309,6 +325,12 @@ public class TileEntityBeehive extends TileEntity implements ITickable {
@Override
public void tick() {
+ // Yatopia start - lithium: skip ticking block entities that are doing nothing
+ if (this.doInit) {
+ this.doInit = false;
+ this.checkSleepState();
+ }
+ // Yatopia end
if (this.bees.size() == 0) { return; } // Yatopia - TE optimizations
if (!this.world.isClientSide) {
this.y();
@@ -329,6 +351,7 @@ public class TileEntityBeehive extends TileEntity implements ITickable {
@Override
public void load(IBlockData iblockdata, NBTTagCompound nbttagcompound) {
super.load(iblockdata, nbttagcompound);
+ this.checkSleepState(); // Yatopia
this.bees.clear();
NBTTagList nbttaglist = nbttagcompound.getList("Bees", 10);
diff --git a/src/main/java/net/minecraft/world/level/block/entity/TileEntityBell.java b/src/main/java/net/minecraft/world/level/block/entity/TileEntityBell.java
index 83626417aa9a00096680851a9a14f52f84fc7887..9f37518ada98c8ce64d283b49a9e3a7b6ec9457f 100644
--- a/src/main/java/net/minecraft/world/level/block/entity/TileEntityBell.java
+++ b/src/main/java/net/minecraft/world/level/block/entity/TileEntityBell.java
@@ -21,6 +21,7 @@ import net.minecraft.world.entity.player.EntityHuman;
import net.minecraft.world.level.World;
import net.minecraft.world.phys.AxisAlignedBB;
import org.apache.commons.lang3.mutable.MutableInt;
+import me.jellysquid.mods.lithium.common.world.blockentity.BlockEntitySleepTracker;
public class TileEntityBell extends TileEntity implements ITickable {
@@ -31,6 +32,8 @@ public class TileEntityBell extends TileEntity implements ITickable {
private List<EntityLiving> h; private List<EntityLiving> getEntitiesAtRing() { return this.h; } // Paper - OBFHELPER
private boolean i; private boolean getShouldReveal() { return this.i; } // Paper - OBFHELPER
private int j;
+ public boolean ringing; // Yatopia
+ public boolean resonating; // Yatopia
public TileEntityBell() {
super(TileEntityTypes.BELL);
@@ -38,6 +41,11 @@ public class TileEntityBell extends TileEntity implements ITickable {
@Override
public boolean setProperty(int i, int j) {
+ // Yatopia start - lithium: skip ticking block entities that are doing nothing
+ if (!this.ringing && i == 1 && this.world != null) {
+ ((BlockEntitySleepTracker) this.world).setAwake(this, true);
+ }
+ // Yatopia end
if (i == 1) {
this.f();
this.j = 0;
@@ -82,6 +90,11 @@ public class TileEntityBell extends TileEntity implements ITickable {
}
}
+ // Yatopia start - lithium: skip ticking block entities that are doing nothing
+ if (!this.ringing && !this.resonating && this.world != null) {
+ ((BlockEntitySleepTracker)this.world).setAwake(this, false);
+ }
+ // Yatopia end
}
private void d() {
@@ -89,6 +102,11 @@ public class TileEntityBell extends TileEntity implements ITickable {
}
public void a(EnumDirection enumdirection) {
+ // Yatopia start - lithium: skip ticking block entities that are doing nothing
+ if (!this.ringing && this.world != null) {
+ ((BlockEntitySleepTracker)this.world).setAwake(this, true);
+ }
+ // Yatopia end
BlockPosition blockposition = this.getPosition();
this.c = enumdirection;
diff --git a/src/main/java/net/minecraft/world/level/block/entity/TileEntityBrewingStand.java b/src/main/java/net/minecraft/world/level/block/entity/TileEntityBrewingStand.java
index 95ca7d9e1eadbe5cc5674ed7352c1ed4d707363d..b5d5f38e520bb5d7912cc86d8ee25858bbd0786b 100644
--- a/src/main/java/net/minecraft/world/level/block/entity/TileEntityBrewingStand.java
+++ b/src/main/java/net/minecraft/world/level/block/entity/TileEntityBrewingStand.java
@@ -34,6 +34,7 @@ import org.bukkit.event.inventory.BrewEvent;
import org.bukkit.event.inventory.BrewingStandFuelEvent;
import org.bukkit.inventory.InventoryHolder;
// CraftBukkit end
+import me.jellysquid.mods.lithium.common.world.blockentity.BlockEntitySleepTracker;
public class TileEntityBrewingStand extends TileEntityContainer implements IWorldInventory, ITickable {
@@ -50,6 +51,7 @@ public class TileEntityBrewingStand extends TileEntityContainer implements IWorl
private int lastTick = MinecraftServer.currentTick;
public List<HumanEntity> transaction = new java.util.ArrayList<HumanEntity>();
private int maxStack = 64;
+ public boolean isTicking = true; // Yatopia
public void onOpen(CraftHumanEntity who) {
transaction.add(who);
@@ -72,6 +74,17 @@ public class TileEntityBrewingStand extends TileEntityContainer implements IWorl
return maxStack;
}
+ // Yatopia start - lithium: skip ticking block entities that are doing nothing
+ @Override
+ public void update() {
+ super.update();
+ if (!this.isTicking && this.world != null) {
+ this.isTicking = true;
+ ((BlockEntitySleepTracker)this.world).setAwake(this, true);
+ }
+ }
+ // Yatopia end
+
public void setMaxStackSize(int size) {
maxStack = size;
}
@@ -141,6 +154,12 @@ public class TileEntityBrewingStand extends TileEntityContainer implements IWorl
@Override
public void tick() {
+ // Yatopia start - lithium: skip ticking block entities that are doing nothing
+ if (this.brewTime == 0 && this.world != null) {
+ this.isTicking = false;
+ ((BlockEntitySleepTracker)this.world).setAwake(this, false);
+ }
+ // Yatopia end
ItemStack itemstack = (ItemStack) this.items.get(4);
if (this.fuelLevel <= 0 && itemstack.getItem() == Items.BLAZE_POWDER) {
@@ -280,6 +299,12 @@ public class TileEntityBrewingStand extends TileEntityContainer implements IWorl
@Override
public void load(IBlockData iblockdata, NBTTagCompound nbttagcompound) {
super.load(iblockdata, nbttagcompound);
+ // Yatopia start - lithium: skip ticking block entities that are doing nothing
+ if (!this.isTicking && this.world != null) {
+ this.isTicking = true;
+ ((BlockEntitySleepTracker) this.world).setAwake(this, true);
+ }
+ // Yatopia end
this.items = NonNullList.a(this.getSize(), ItemStack.b);
ContainerUtil.b(nbttagcompound, this.items);
this.brewTime = nbttagcompound.getShort("BrewTime");
diff --git a/src/main/java/net/minecraft/world/level/block/entity/TileEntityCampfire.java b/src/main/java/net/minecraft/world/level/block/entity/TileEntityCampfire.java
index 08759f461ec947c0d5655557f49d8717afee6f00..cdff01d4da417ef1be6238d3faaf464ee7884bd5 100644
--- a/src/main/java/net/minecraft/world/level/block/entity/TileEntityCampfire.java
+++ b/src/main/java/net/minecraft/world/level/block/entity/TileEntityCampfire.java
@@ -27,12 +27,18 @@ import org.bukkit.craftbukkit.block.CraftBlock;
import org.bukkit.craftbukkit.inventory.CraftItemStack;
import org.bukkit.event.block.BlockCookEvent;
// CraftBukkit end
+import net.minecraft.core.NonNullList;
+import me.jellysquid.mods.lithium.common.world.blockentity.BlockEntitySleepTracker;
public class TileEntityCampfire extends TileEntity implements Clearable, ITickable {
private final NonNullList<ItemStack> items;
public final int[] cookingTimes;
public final int[] cookingTotalTimes;
+ // Yatopia start - lithium: skip ticking block entities that are doing nothing
+ public boolean isTicking = true;
+ public boolean doInit = true;
+ // Yatopia end
public TileEntityCampfire() {
super(TileEntityTypes.CAMPFIRE);
@@ -41,8 +47,50 @@ public class TileEntityCampfire extends TileEntity implements Clearable, ITickab
this.cookingTotalTimes = new int[4];
}
+ // Yatopia start - lithium: skip ticking block entities that are doing nothing
+ @Override
+ public void update() {
+ super.update();
+ this.checkSleepState();
+ }
+
+ @Override
+ public void invalidateBlockCache() {
+ super.invalidateBlockCache();
+ this.checkSleepState();
+ }
+
+ public void checkSleepState() {
+ if (this.world == null) {
+ return;
+ }
+ boolean shouldTick = false;
+ NonNullList<ItemStack> beingCooked = this.items;
+ for (int i = 0; i < beingCooked.size(); i++) {
+ ItemStack stack = beingCooked.get(i);
+ if (!stack.isEmpty()) {
+ if (this.cookingTimes[i] > 0 || this.getBlock().get(BlockCampfire.LIT)) {
+ shouldTick = true;
+ break;
+ }
+ }
+ }
+
+ if (shouldTick != this.isTicking) {
+ this.isTicking = shouldTick;
+ ((BlockEntitySleepTracker)this.world).setAwake(this, shouldTick);
+ }
+ }
+ // Yatopia end
+
@Override
public void tick() {
+ // Yatopia start - lithium: skip ticking block entities that are doing nothing
+ if (this.doInit) {
+ this.doInit = false;
+ this.checkSleepState();
+ }
+ // Yatopia end
boolean flag = (Boolean) this.getBlock().get(BlockCampfire.LIT);
boolean flag1 = this.world.isClientSide;
@@ -149,6 +197,7 @@ public class TileEntityCampfire extends TileEntity implements Clearable, ITickab
@Override
public void load(IBlockData iblockdata, NBTTagCompound nbttagcompound) {
super.load(iblockdata, nbttagcompound);
+ this.checkSleepState(); // Yatopia - lithium: skip ticking block entities that are doing nothing
this.items.clear();
ContainerUtil.b(nbttagcompound, this.items);
int[] aint;
diff --git a/src/main/java/net/minecraft/world/level/block/entity/TileEntityChest.java b/src/main/java/net/minecraft/world/level/block/entity/TileEntityChest.java
index 324b752c70e0bd7ea06caa98ec15cdd4e6ea40ae..ebc4385e648e6205b1b6893e818b302a66f1cfea 100644
--- a/src/main/java/net/minecraft/world/level/block/entity/TileEntityChest.java
+++ b/src/main/java/net/minecraft/world/level/block/entity/TileEntityChest.java
@@ -33,14 +33,27 @@ import net.minecraft.world.level.block.Blocks;
import org.bukkit.craftbukkit.entity.CraftHumanEntity;
import org.bukkit.entity.HumanEntity;
// CraftBukkit end
+ import me.jellysquid.mods.lithium.common.world.blockentity.BlockEntitySleepTracker; // Yatopia
public class TileEntityChest extends TileEntityLootable { // Paper - Remove ITickable
private gg.airplane.structs.ItemListWithBitset items; // Airplane
protected float a;
+ private float getAnimationAngle() { return a; } // Yatopia - OBFHELPER
protected float b;
+ private float getLastAnimationAngle() { return b; } // Yatopia - OBFHELPER
public int viewingCount;
private int j;
+ private int ticksOpen = j; // Yatopia - OBFHELPER
+ private int lastTime; // Yatopia
+
+ // Yatopia start - lithium: skip ticking block entities that are doing nothing
+ public void checkWakeUp() {
+ if ((this.viewingCount != 0 || this.getAnimationAngle() != 0.0F || this.getLastAnimationAngle() != 0) && this.world != null) {
+ ((BlockEntitySleepTracker) this.world).setAwake(this, true);
+ }
+ }
+ // Yatopia end
// CraftBukkit start - add fields and methods
public List<HumanEntity> transaction = new java.util.ArrayList<HumanEntity>();
@@ -137,11 +150,27 @@ public class TileEntityChest extends TileEntityLootable { // Paper - Remove ITic
}
public void tick() {
+ // Yatopia start - lithium: skip ticking block entities that are doing nothing
+ // noinspection ConstantConditions
+ int time = (int) this.world.getTime();
+ // ticksOpen == 0 implies most likely that this is the first tick. We don't want to update the value then.
+ // overflow case is handled by not going to sleep when this.ticksOpen == 0
+ if (this.ticksOpen != 0) {
+ this.ticksOpen += time - this.lastTime - 1;
+ }
+ this.lastTime = time;
+ // Yatopia end
+
int i = this.position.getX();
int j = this.position.getY();
int k = this.position.getZ();
++this.j;
+ // Yatopia start - lithium: skip ticking block entities that are doing nothing
+ if (this.viewingCount == 0 && this.getAnimationAngle() == 0.0F && this.getLastAnimationAngle() == 0 && this.ticksOpen != 0 && this.world != null) {
+ ((BlockEntitySleepTracker) this.world).setAwake(this, false);
+ }
+ // Yatopia end
}
public void doOpenLogic() {
@@ -247,6 +276,7 @@ public class TileEntityChest extends TileEntityLootable { // Paper - Remove ITic
@Override
public boolean setProperty(int i, int j) {
+ this.checkWakeUp(); // Yatopia - lithium: skip ticking block entities that are doing nothing
if (i == 1) {
this.viewingCount = j;
return true;
@@ -278,7 +308,7 @@ public class TileEntityChest extends TileEntityLootable { // Paper - Remove ITic
// CraftBukkit end
this.onOpen();
}
-
+ this.checkWakeUp(); // Yatopia - lithium: skip ticking block entities that are doing nothing
}
@Override
@@ -299,6 +329,7 @@ public class TileEntityChest extends TileEntityLootable { // Paper - Remove ITic
// CraftBukkit end
this.onOpen();
}
+ this.checkWakeUp(); // Yatopia - lithium: skip ticking block entities that are doing nothing
}
diff --git a/src/main/java/net/minecraft/world/level/block/entity/TileEntityEnchantTable.java b/src/main/java/net/minecraft/world/level/block/entity/TileEntityEnchantTable.java
index 4b1cb089355b455c6210f2df1af797cc363997cf..0049a675557cbc05e361c12e9fb84a38a3a21160 100644
--- a/src/main/java/net/minecraft/world/level/block/entity/TileEntityEnchantTable.java
+++ b/src/main/java/net/minecraft/world/level/block/entity/TileEntityEnchantTable.java
@@ -9,6 +9,7 @@ import net.minecraft.util.MathHelper;
import net.minecraft.world.INamableTileEntity;
import net.minecraft.world.entity.player.EntityHuman;
import net.minecraft.world.level.block.state.IBlockData;
+import me.jellysquid.mods.lithium.common.world.blockentity.BlockEntitySleepTracker;
public class TileEntityEnchantTable extends TileEntity implements INamableTileEntity, ITickable {
@@ -51,6 +52,7 @@ public class TileEntityEnchantTable extends TileEntity implements INamableTileEn
@Override
public void tick() {
if (!org.yatopiamc.yatopia.server.YatopiaConfig.shouldTickEnchantingTables) { return; } // Yatopia - TE optimizations
+ ((BlockEntitySleepTracker) this.world).setAwake(this, false); // Yatopia
this.j = this.i;
this.l = this.k;
EntityHuman entityhuman = this.world.a((double) this.position.getX() + 0.5D, (double) this.position.getY() + 0.5D, (double) this.position.getZ() + 0.5D, 3.0D, false);
diff --git a/src/main/java/net/minecraft/world/level/block/entity/TileEntityFurnace.java b/src/main/java/net/minecraft/world/level/block/entity/TileEntityFurnace.java
index 20193ba36c62fdd40ae905d1cea4bfd6d6aebcd7..b0f1c4f1660f3485303f0148bbc06dce4181e6b2 100644
--- a/src/main/java/net/minecraft/world/level/block/entity/TileEntityFurnace.java
+++ b/src/main/java/net/minecraft/world/level/block/entity/TileEntityFurnace.java
@@ -51,9 +51,11 @@ import org.bukkit.event.inventory.FurnaceBurnEvent;
import org.bukkit.event.inventory.FurnaceExtractEvent;
import org.bukkit.event.inventory.FurnaceSmeltEvent;
// CraftBukkit end
+import me.jellysquid.mods.lithium.common.world.blockentity.BlockEntitySleepTracker;
public abstract class TileEntityFurnace extends TileEntityContainer implements IWorldInventory, RecipeHolder, AutoRecipeOutput, ITickable {
+ private boolean isTicking = true; // Yatopia
private static final int[] g = new int[]{0};
private static final int[] h = new int[]{2, 1};
private static final int[] i = new int[]{1};
@@ -195,6 +197,17 @@ public abstract class TileEntityFurnace extends TileEntityContainer implements I
private int maxStack = MAX_STACK;
public List<HumanEntity> transaction = new java.util.ArrayList<HumanEntity>();
+ // Yatopia start - lithium: skip ticking block entities that are doing nothing
+ @Override
+ public void update() {
+ super.update();
+ if (!this.isTicking && this.world != null) {
+ this.isTicking = true;
+ ((BlockEntitySleepTracker) this.world).setAwake(this, true);
+ }
+ }
+ // Yatopia end
+
public List<ItemStack> getContents() {
return this.items;
}
@@ -257,6 +270,12 @@ public abstract class TileEntityFurnace extends TileEntityContainer implements I
@Override
public void load(IBlockData iblockdata, NBTTagCompound nbttagcompound) {
super.load(iblockdata, nbttagcompound);
+ // Yatopia start - lithium: skip ticking block entities that are doing nothing
+ if (!this.isTicking && this.world != null) {
+ this.isTicking = true;
+ ((BlockEntitySleepTracker)this.world).setAwake(this, true);
+ }
+ // Yatopia end
this.items = NonNullList.a(this.getSize(), ItemStack.b);
ContainerUtil.b(nbttagcompound, this.items);
this.burnTime = nbttagcompound.getShort("BurnTime");
@@ -369,7 +388,12 @@ public abstract class TileEntityFurnace extends TileEntityContainer implements I
if (flag1) {
this.update();
}
-
+ // Yatopia start - lithium: skip ticking block entities that are doing nothing
+ if (!this.isTicking && this.world != null) {
+ this.isTicking = true;
+ ((BlockEntitySleepTracker)this.world).setAwake(this, true);
+ }
+ // Yatopia end
}
protected boolean canBurn(@Nullable IRecipe<?> irecipe) {
diff --git a/src/main/java/net/minecraft/world/level/block/entity/TileEntityShulkerBox.java b/src/main/java/net/minecraft/world/level/block/entity/TileEntityShulkerBox.java
index c1a90eb01689b8b91200ba49d58360d5ea2004c4..8095740f1848443e87fd52c14d19dabb00a3ecd4 100644
--- a/src/main/java/net/minecraft/world/level/block/entity/TileEntityShulkerBox.java
+++ b/src/main/java/net/minecraft/world/level/block/entity/TileEntityShulkerBox.java
@@ -33,6 +33,7 @@ import net.minecraft.world.phys.shapes.VoxelShapes;
import org.bukkit.craftbukkit.entity.CraftHumanEntity;
import org.bukkit.entity.HumanEntity;
// CraftBukkit end
+import me.jellysquid.mods.lithium.common.world.blockentity.BlockEntitySleepTracker;
public class TileEntityShulkerBox extends TileEntityLootable implements IWorldInventory, ITickable {
@@ -41,7 +42,9 @@ public class TileEntityShulkerBox extends TileEntityLootable implements IWorldIn
public int viewingCount;
private TileEntityShulkerBox.AnimationPhase i;
private float j;
+ public float animationProgress = j; // Yatopia - OBFHELPER
private float k;
+ public float prevAnimationProgress = k; // Yatopia - OBFHELPER
@Nullable
private EnumColor l;
private boolean m;
@@ -96,6 +99,11 @@ public class TileEntityShulkerBox extends TileEntityLootable implements IWorldIn
this.m();
}
+ // Yatopia start - lithium: skip ticking block entities that are doing nothing
+ if (this.getAnimationPhase() == TileEntityShulkerBox.AnimationPhase.CLOSED && this.prevAnimationProgress == 0f && this.animationProgress == 0f && this.world != null) {
+ ((BlockEntitySleepTracker) this.world).setAwake(this, false);
+ }
+ // Yatopia end
}
protected void h() {
@@ -127,6 +135,7 @@ public class TileEntityShulkerBox extends TileEntityLootable implements IWorldIn
}
+ public TileEntityShulkerBox.AnimationPhase getAnimationPhase() {return this.j(); } // Yatopia - OBFHELPER
public TileEntityShulkerBox.AnimationPhase j() {
return this.i;
}
@@ -209,6 +218,7 @@ public class TileEntityShulkerBox extends TileEntityLootable implements IWorldIn
@Override
public boolean setProperty(int i, int j) {
+ if (this.world != null && i == 1) ((BlockEntitySleepTracker) this.world).setAwake(this, true); // Yatopia
if (i == 1) {
this.viewingCount = j;
if (j == 0) {