complete refactor and cleanup
This commit is contained in:
@@ -14,9 +14,9 @@
|
|||||||
// along with this program. If not, see <https://www.gnu.org/licenses/>.
|
// along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||||
package net.gensokyoreimagined.nitori.access;
|
package net.gensokyoreimagined.nitori.access;
|
||||||
|
|
||||||
import ca.spottedleaf.moonrise.common.list.EntityList;
|
//import ca.spottedleaf.moonrise.common.list.EntityList;
|
||||||
|
//
|
||||||
public interface IMixinChunkEntitySlicesAccess {
|
//public interface IMixinChunkEntitySlicesAccess {
|
||||||
@SuppressWarnings("EmptyMethod")
|
// @SuppressWarnings("EmptyMethod")
|
||||||
EntityList getEntities();
|
// EntityList getEntities();
|
||||||
}
|
//}
|
||||||
|
|||||||
@@ -14,7 +14,7 @@
|
|||||||
// along with this program. If not, see <https://www.gnu.org/licenses/>.
|
// along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||||
package net.gensokyoreimagined.nitori.access;
|
package net.gensokyoreimagined.nitori.access;
|
||||||
|
|
||||||
public interface IMixinIteratorSafeOrderedReferenceSetAccess {
|
//public interface IMixinIteratorSafeOrderedReferenceSetAccess {
|
||||||
@SuppressWarnings("EmptyMethod")
|
// @SuppressWarnings("EmptyMethod")
|
||||||
int getListSize();
|
// int getListSize();
|
||||||
}
|
//}
|
||||||
|
|||||||
@@ -1,31 +0,0 @@
|
|||||||
package net.gensokyoreimagined.nitori.executor.annotation.thread;
|
|
||||||
|
|
||||||
//import java.lang.annotation.Documented;
|
|
||||||
//import java.lang.annotation.ElementType;
|
|
||||||
//import java.lang.annotation.Target;
|
|
||||||
//
|
|
||||||
///**
|
|
||||||
// * An annotation primarily for methods, identifying methods that can only be called on a thread that is an instance
|
|
||||||
// * of {@link AssistThread}.
|
|
||||||
// * <br>
|
|
||||||
// * This annotation can also be used on fields or classes, similar to {@link ThreadRestricted}.
|
|
||||||
// * <br>
|
|
||||||
// * In a method annotated with {@link AssistThreadOnly}, fields and methods annotated with
|
|
||||||
// * {@link AssistThreadOnly}, {@link BaseThreadOnly} or {@link AnyThreadSafe} may be used.
|
|
||||||
// * <br>
|
|
||||||
// * Methods that are annotated with {@link AssistThreadOnly} must never call methods that are annotated with
|
|
||||||
// * {@link PotentiallyBlocking}.
|
|
||||||
// *
|
|
||||||
// * @author Martijn Muijsers under AGPL-3.0
|
|
||||||
// */
|
|
||||||
//@SuppressWarnings("unused")
|
|
||||||
//@Documented
|
|
||||||
//@Target({ElementType.METHOD, ElementType.TYPE, ElementType.FIELD})
|
|
||||||
//public @interface AssistThreadOnly {
|
|
||||||
//
|
|
||||||
// /**
|
|
||||||
// * @see ThreadRestricted#fieldAccess()
|
|
||||||
// */
|
|
||||||
// Access value() default Access.READ_WRITE;
|
|
||||||
//
|
|
||||||
//}
|
|
||||||
@@ -1,114 +0,0 @@
|
|||||||
package net.gensokyoreimagined.nitori.executor.queue;
|
|
||||||
|
|
||||||
///**
|
|
||||||
// * A tier for {@link AbstractTaskQueue}s, that indicates the priority of the tasks in the task queues.
|
|
||||||
// * Every tier contains a list of the queues that are part of the tier.
|
|
||||||
// * The tiers are in order of priority, from high to low.
|
|
||||||
// * Similarly, the queues for each tier are in the same order of priority.
|
|
||||||
// * The tasks in each queue should also be in order of priority whenever relevant, but usually there
|
|
||||||
// * is no strong difference in priority between tasks in the same queue, so they typically operate as FIFO queues,
|
|
||||||
// * so that the longest waiting task implicitly has the highest priority within the queue.
|
|
||||||
// * <br>
|
|
||||||
// * Tasks from queues in the {@link #SERVER} tier can only be run on a {@link ServerThread}.
|
|
||||||
// * Tasks from other tiers can be run on {@link ServerThread}s as well as on {@link AssistThread}s.
|
|
||||||
// *
|
|
||||||
// * @author Martijn Muijsers under AGPL-3.0
|
|
||||||
// */
|
|
||||||
//public enum BaseTaskQueueTier {
|
|
||||||
//
|
|
||||||
// /**
|
|
||||||
// * A tier for queues that contain tasks that must be executed on a {@link ServerThread}.
|
|
||||||
// * <br>
|
|
||||||
// * Some parts of the server can only be safely accessed by one thread at a time.
|
|
||||||
// * If they can not be guarded by a lock (or if this is not desired,
|
|
||||||
// * because if a ticking thread would need to acquire this lock it would block it),
|
|
||||||
// * then these parts of the code are typically deferred to the server thread.
|
|
||||||
// * Based on the current use of the {@link TickThread} class, particularly given the existence of
|
|
||||||
// * {@link TickThread#isTickThreadFor(Entity)} and {@link TickThread#isTickThreadFor(ServerLevel, int, int)},
|
|
||||||
// * we can deduce that future support for performing some of these actions in parallel is planned.
|
|
||||||
// * In such a case, some server thread tasks may become tasks that must be
|
|
||||||
// * executed on an appropriate {@link TickThread}.
|
|
||||||
// * In that case, the queues below should be changed so that the server thread and any of the
|
|
||||||
// * ticking threads poll from queues that contain tasks appropriate for them.
|
|
||||||
// * For example, {@link BaseTaskQueues#deferredToUniversalTickThread} would be for tasks that can run
|
|
||||||
// * on any ticking thread, and additional queues would need to be added concerning a specific
|
|
||||||
// * subject (like an entity or chunk) with tasks that will be run on whichever ticking thread is the
|
|
||||||
// * ticking thread for that subject at the time of polling.
|
|
||||||
// * <br>
|
|
||||||
// * Note that a {@link ServerThread} can only yield to {@link TaskSpan#TINY} tasks in other tiers
|
|
||||||
// * (since there are no higher tiers, and threads can only yield to lower tiers when
|
|
||||||
// * the task yielded to is{@link TaskSpan#TINY}, or other non-yielding tasks in its own tier (since it
|
|
||||||
// * has a {@link BaseThread#maximumYieldDepth} of 1).
|
|
||||||
// * Yielding to other tasks in this same tier is somewhat risky, since this means that the tasks that were
|
|
||||||
// * yielded to must assume that although they are running on the server thread, they may be running at
|
|
||||||
// * some unknown point in execution of the main thread. Therefore, scheduling any non-yielding tasks to
|
|
||||||
// * a queue in this tier must be done with the utmost care that the task cannot disrupt, or be disrupted by,
|
|
||||||
// * the surrounding code that yields to it.
|
|
||||||
// */
|
|
||||||
// SERVER(new AbstractTaskQueue[]{
|
|
||||||
// BaseTaskQueues.deferredToServerThread,
|
|
||||||
// BaseTaskQueues.serverThreadTick,
|
|
||||||
// BaseTaskQueues.anyTickScheduledServerThread
|
|
||||||
// }, MinecraftServer.SERVER_THREAD_PRIORITY),
|
|
||||||
// /**
|
|
||||||
// * A tier for queues that contain tasks that are part of ticking,
|
|
||||||
// * to assist the main ticking thread(s) in doing so.
|
|
||||||
// */
|
|
||||||
// TICK_ASSIST(new AbstractTaskQueue[]{
|
|
||||||
// BaseTaskQueues.tickAssist
|
|
||||||
// }, Integer.getInteger("gale.thread.priority.tick", 7)),
|
|
||||||
// /**
|
|
||||||
// * A tier for queues that contain general tasks that must be performed at some point in time,
|
|
||||||
// * asynchronously with respect to the {@link ServerThread} and the ticking of the server.
|
|
||||||
// * Execution of
|
|
||||||
// */
|
|
||||||
// ASYNC(new AbstractTaskQueue[0], Integer.getInteger("gale.thread.priority.async", 6)),
|
|
||||||
// /**
|
|
||||||
// * A tier for queues that contain tasks with the same considerations as {@link #ASYNC},
|
|
||||||
// * but with a low priority.
|
|
||||||
// */
|
|
||||||
// LOW_PRIORITY_ASYNC(new AbstractTaskQueue[0], Integer.getInteger("gale.thread.priority.async.low", 3));
|
|
||||||
//
|
|
||||||
// /**
|
|
||||||
// * Equal to {@link #ordinal()}.
|
|
||||||
// */
|
|
||||||
// public final int ordinal;
|
|
||||||
//
|
|
||||||
// /**
|
|
||||||
// * The task queues that belong to this tier.
|
|
||||||
// */
|
|
||||||
// public final AbstractTaskQueue[] taskQueues;
|
|
||||||
//
|
|
||||||
// /**
|
|
||||||
// * The priority for threads that are executing a task from this tier.
|
|
||||||
// * <br>
|
|
||||||
// * If a thread yields to other tasks, the priority it will have is always the highest priority of any task
|
|
||||||
// * on its stack.
|
|
||||||
// */
|
|
||||||
// public final int threadPriority;
|
|
||||||
//
|
|
||||||
// BaseTaskQueueTier(AbstractTaskQueue[] taskQueues, int threadPriority) {
|
|
||||||
// this.ordinal = this.ordinal();
|
|
||||||
// this.taskQueues = taskQueues;
|
|
||||||
// for (AbstractTaskQueue queue : this.taskQueues) {
|
|
||||||
// queue.setTier(this);
|
|
||||||
// }
|
|
||||||
// this.threadPriority = threadPriority;
|
|
||||||
// }
|
|
||||||
//
|
|
||||||
// /**
|
|
||||||
// * Equal to {@link #values()}.
|
|
||||||
// */
|
|
||||||
// public static final BaseTaskQueueTier[] VALUES = values();
|
|
||||||
//
|
|
||||||
// /**
|
|
||||||
// * Equal to {@link #VALUES}{@code .length}.
|
|
||||||
// */
|
|
||||||
// public static final int length = VALUES.length;
|
|
||||||
//
|
|
||||||
// /**
|
|
||||||
// * Equal to {@link #VALUES} without {@link #SERVER}.
|
|
||||||
// */
|
|
||||||
// public static final BaseTaskQueueTier[] VALUES_EXCEPT_SERVER = Arrays.stream(VALUES).filter(tier -> tier != SERVER).toList().toArray(new BaseTaskQueueTier[length - 1]);
|
|
||||||
//
|
|
||||||
//}
|
|
||||||
@@ -1,69 +0,0 @@
|
|||||||
package net.gensokyoreimagined.nitori.executor.thread;
|
|
||||||
|
|
||||||
///**
|
|
||||||
// * A thread created by the {@link BaseThreadPool}.
|
|
||||||
// *
|
|
||||||
// * @author Martijn Muijsers under AGPL-3.0
|
|
||||||
// */
|
|
||||||
//public class AssistThread extends BaseThread {
|
|
||||||
//
|
|
||||||
// /**
|
|
||||||
// * The maximum yield depth. While an {@link AssistThread} has a yield depth equal to or greater than this value,
|
|
||||||
// * it can not start more potentially yielding tasks.
|
|
||||||
// */
|
|
||||||
// public static final int MAXIMUM_YIELD_DEPTH = Integer.getInteger("gale.yield.depth.max", 100);
|
|
||||||
//
|
|
||||||
// /**
|
|
||||||
// * The index of this thread, as needed as an argument to
|
|
||||||
// * {@link BaseThreadPool#getThreadByAssistIndex(int)}.
|
|
||||||
// */
|
|
||||||
// public final int assistThreadIndex;
|
|
||||||
//
|
|
||||||
// /**
|
|
||||||
// * Must only be called from {@link BaseThreadPool#addAssistThread}.
|
|
||||||
// */
|
|
||||||
// public AssistThread(int assistThreadIndex) {
|
|
||||||
// super(AssistThread::getCurrentAssistThreadAndRunForever, "Assist Thread " + assistThreadIndex, assistThreadIndex + 1, MAXIMUM_YIELD_DEPTH);
|
|
||||||
// this.assistThreadIndex = assistThreadIndex;
|
|
||||||
// }
|
|
||||||
//
|
|
||||||
// /**
|
|
||||||
// * Causes this thread to loop forever, always attempting to find a task to do, and if none is found,
|
|
||||||
// * registering itself with the places where a relevant task may be added in order to be signalled when
|
|
||||||
// * one is actually added.
|
|
||||||
// */
|
|
||||||
// @ThisThreadOnly
|
|
||||||
// protected void runForever() {
|
|
||||||
// this.runTasksUntil(null, () -> false, null);
|
|
||||||
// }
|
|
||||||
//
|
|
||||||
// /**
|
|
||||||
// * @return The current thread if it is a {@link AssistThread}, or null otherwise.
|
|
||||||
// */
|
|
||||||
// @SuppressWarnings("unused")
|
|
||||||
// @AnyThreadSafe
|
|
||||||
// @YieldFree
|
|
||||||
// public static @Nullable AssistThread currentAssistThread() {
|
|
||||||
// return Thread.currentThread() instanceof AssistThread assistThread ? assistThread : null;
|
|
||||||
// }
|
|
||||||
//
|
|
||||||
// /**
|
|
||||||
// * @return Whether the current thread is a {@link AssistThread}.
|
|
||||||
// */
|
|
||||||
// @SuppressWarnings("unused")
|
|
||||||
// @AnyThreadSafe
|
|
||||||
// @YieldFree
|
|
||||||
// public static boolean isAssistThread() {
|
|
||||||
// return Thread.currentThread() instanceof AssistThread;
|
|
||||||
// }
|
|
||||||
//
|
|
||||||
// /**
|
|
||||||
// * A method that simply acquires the {@link AssistThread} that is the current thread, and calls
|
|
||||||
// * {@link #runForever()} on it.
|
|
||||||
// */
|
|
||||||
// @BaseThreadOnly
|
|
||||||
// protected static void getCurrentAssistThreadAndRunForever() {
|
|
||||||
// ((AssistThread) Thread.currentThread()).runForever();
|
|
||||||
// }
|
|
||||||
//
|
|
||||||
//}
|
|
||||||
@@ -1,743 +0,0 @@
|
|||||||
package net.gensokyoreimagined.nitori.executor.thread;
|
|
||||||
|
|
||||||
//import net.gensokyoreimagined.nitori.executor.wrapper.MinecraftServerWrapper;
|
|
||||||
//
|
|
||||||
///**
|
|
||||||
// * An abstract base class implementing {@link AbstractYieldingThread},
|
|
||||||
// * that provides implementation that is common between
|
|
||||||
// * {@link TickThread} and {@link AssistThread}.
|
|
||||||
// *
|
|
||||||
// * @author Martijn Muijsers under AGPL-3.0
|
|
||||||
// */
|
|
||||||
//public abstract class BaseThread extends Thread implements AbstractYieldingThread {
|
|
||||||
//
|
|
||||||
// /**
|
|
||||||
// * The minimum time to wait as the {@link MinecraftServer#serverThread} when performing a timed wait.
|
|
||||||
// * Given in nanoseconds.
|
|
||||||
// * If a timed wait with a lower time is attempted, the wait is not performed at all.
|
|
||||||
// */
|
|
||||||
// public static final long SERVER_THREAD_WAIT_NANOS_MINIMUM = 10_000;
|
|
||||||
//
|
|
||||||
// /**
|
|
||||||
// * The time to wait as the {@link MinecraftServer#serverThread} during the oversleep phase, if
|
|
||||||
// * there may be delayed tasks.
|
|
||||||
// * Given in nanoseconds.
|
|
||||||
// */
|
|
||||||
// public static final long SERVER_THREAD_WAIT_NANOS_DURING_OVERSLEEP_WITH_DELAYED_TASKS = 50_000;
|
|
||||||
//
|
|
||||||
// /**
|
|
||||||
// * The index of this thread, as needed as an argument to
|
|
||||||
// * {@link BaseThreadPool#getThreadByBaseIndex(int)}.
|
|
||||||
// */
|
|
||||||
// public final int baseThreadIndex;
|
|
||||||
//
|
|
||||||
// /**
|
|
||||||
// * The maximum yield depth for this thread,
|
|
||||||
// * which equals 1 for a {@link ServerThread}
|
|
||||||
// * and {@link AssistThread#MAXIMUM_YIELD_DEPTH} for an {@link AssistThread}.
|
|
||||||
// */
|
|
||||||
// public final int maximumYieldDepth;
|
|
||||||
//
|
|
||||||
// /**
|
|
||||||
// * The number of times this thread holds a {@link YieldingLock},
|
|
||||||
// * used in {@link #holdsYieldingLock()}.
|
|
||||||
// *
|
|
||||||
// * @see AbstractYieldingThread#incrementHeldYieldingLockCount()
|
|
||||||
// */
|
|
||||||
// @ThisThreadOnly
|
|
||||||
// public int heldYieldingLockCount = 0;
|
|
||||||
//
|
|
||||||
// /**
|
|
||||||
// * The current yield depth of this thread.
|
|
||||||
// */
|
|
||||||
// @AnyThreadSafe(Access.READ) @ThisThreadOnly(Access.WRITE)
|
|
||||||
// public volatile int yieldDepth = 0;
|
|
||||||
//
|
|
||||||
// /**
|
|
||||||
// * Whether this thread can currently start yielding tasks with respect to being restricted
|
|
||||||
// * due to {@link #yieldDepth} being at least {@link #maximumYieldDepth}.
|
|
||||||
// * <br>
|
|
||||||
// * This is updated using {@link #updateCanStartYieldingTasks()}
|
|
||||||
// * after {@link #yieldDepth} or {@link #heldYieldingLockCount} is changed.
|
|
||||||
// */
|
|
||||||
// @AnyThreadSafe(Access.READ) @ThisThreadOnly(Access.WRITE)
|
|
||||||
// public volatile boolean canStartYieldingTasks = true;
|
|
||||||
//
|
|
||||||
// /**
|
|
||||||
// * The highest {@link BaseTaskQueueTier} of any task on the yielding execution stack of this thread,
|
|
||||||
// * or null if there is no task being executed on this thread.
|
|
||||||
// */
|
|
||||||
// @AnyThreadSafe(Access.READ) @ThisThreadOnly(Access.WRITE)
|
|
||||||
// public volatile @Nullable BaseTaskQueueTier highestTierOfTaskOnStack;
|
|
||||||
//
|
|
||||||
// /**
|
|
||||||
// * The {@link BaseTaskQueueTier} that the last non-null return value of {@link #pollTask} was polled from,
|
|
||||||
// * or null if {@link #pollTask} has never been called yet.
|
|
||||||
// */
|
|
||||||
// @ThisThreadOnly
|
|
||||||
// private @Nullable BaseTaskQueueTier lastPolledTaskTier;
|
|
||||||
//
|
|
||||||
// /**
|
|
||||||
// * The lock to guard this thread's sleeping and waking actions.
|
|
||||||
// */
|
|
||||||
// private final Lock waitLock = new ReentrantLock();
|
|
||||||
//
|
|
||||||
// /**
|
|
||||||
// * The condition to wait for a signal, when this thread has to wait for something to do.
|
|
||||||
// */
|
|
||||||
// private final Condition waitCondition = waitLock.newCondition();
|
|
||||||
//
|
|
||||||
// /**
|
|
||||||
// * Whether this thread is currently not working on the content of a task, but instead
|
|
||||||
// * attempting to poll a next task to do, checking whether it can accept tasks at all, or
|
|
||||||
// * attempting to acquire a {@link YieldingLock}, or waiting (although the fact that this value is true during
|
|
||||||
// * waiting is irrelevant, because at such a time, {@link #isWaiting} will be true, and this value will no longer
|
|
||||||
// * have any effect due to the implementation of {@link #signal}).
|
|
||||||
// * <br>
|
|
||||||
// * This value is used to determine whether to set {@link #skipNextWait} when {@link #signal} is called
|
|
||||||
// * and {@link #isWaiting} is false.
|
|
||||||
// */
|
|
||||||
// @AnyThreadSafe(Access.READ) @ThisThreadOnly(Access.WRITE)
|
|
||||||
// private volatile boolean isPollingTaskOrCheckingStopCondition = true;
|
|
||||||
//
|
|
||||||
// /**
|
|
||||||
// * Whether this thread should not start waiting for something to do the next time no task could be polled,
|
|
||||||
// * but instead try polling a task again.
|
|
||||||
// */
|
|
||||||
// @AnyThreadSafe
|
|
||||||
// public volatile boolean skipNextWait = false;
|
|
||||||
//
|
|
||||||
// /**
|
|
||||||
// * Whether this thread is currently waiting for something to do.
|
|
||||||
// * <br>
|
|
||||||
// * This is set to true at some point before actually starting to wait in a blocking fashion,
|
|
||||||
// * and set to false at some point after no longer waiting in a blocking fashion. So, at some point,
|
|
||||||
// * this value may be true while the thread is not blocked yet, or anymore.
|
|
||||||
// * Even more so, extra checks for whether the thread should block will be performed in between
|
|
||||||
// * the moment this value is set to true and the moment the thread potentially blocks. This means that if the
|
|
||||||
// * checks fail, this value may be set to true and then false again, without actually ever blocking.
|
|
||||||
// */
|
|
||||||
// @AnyThreadSafe(Access.READ) @ThisThreadOnly(Access.WRITE)
|
|
||||||
// @Guarded(value = "#waitLock", fieldAccess = Access.WRITE)
|
|
||||||
// public volatile boolean isWaiting = false;
|
|
||||||
//
|
|
||||||
// /**
|
|
||||||
// * Whether {@link #isWaiting} is irrelevant because this thread has already
|
|
||||||
// * been signalled via {@link #signal} to wake up.
|
|
||||||
// */
|
|
||||||
// @AnyThreadSafe(Access.READ) @ThisThreadOnly(Access.WRITE)
|
|
||||||
// @Guarded(value = "#waitLock", fieldAccess = Access.WRITE)
|
|
||||||
// public volatile boolean mayBeStillWaitingButHasBeenSignalled = false;
|
|
||||||
//
|
|
||||||
// /**
|
|
||||||
// * The {@link YieldingLock} that this thread is waiting for,
|
|
||||||
// * or null if this thread is not waiting for a {@link YieldingLock}.
|
|
||||||
// * This value only has meaning while {@link #isWaiting} is true.
|
|
||||||
// */
|
|
||||||
// @AnyThreadSafe(Access.READ) @ThisThreadOnly(Access.WRITE)
|
|
||||||
// @Guarded(value = "#waitLock", fieldAccess = Access.WRITE)
|
|
||||||
// public volatile @Nullable YieldingLock lockWaitingFor = null;
|
|
||||||
//
|
|
||||||
// /**
|
|
||||||
// * The value of {@link #lockWaitingFor} during the last wait (a call to {@link Condition#await})
|
|
||||||
// * or pre-wait check (while {@link #isNotActuallyWaitingYet} is true).
|
|
||||||
// */
|
|
||||||
// @ThisThreadOnly
|
|
||||||
// private @Nullable YieldingLock lastLockWaitedFor = null;
|
|
||||||
//
|
|
||||||
// /**
|
|
||||||
// * A special flag, used after changing {@link #isWaiting}, when the lock must be temporarily released to
|
|
||||||
// * call {@link BaseThreadActivation#callForUpdate()} (to avoid deadlocks in {@link #signal} calls),
|
|
||||||
// * and we wish the pool to regard this thread as waiting
|
|
||||||
// * (which it will, because {@link #isWaiting} will be true), but we must still
|
|
||||||
// * know not to signal the underlying {@link #waitCondition}, but set {@link #skipNextWait} to true,
|
|
||||||
// * when {@link #signal} is called at some point during the short release of {@link #waitLock}.
|
|
||||||
// */
|
|
||||||
// public volatile boolean isNotActuallyWaitingYet = false;
|
|
||||||
//
|
|
||||||
// /**
|
|
||||||
// * The last reason this thread was signalled before the current poll attempt, or null if the current
|
|
||||||
// * poll attempt was not preceded by signalling (but by yielding for example).
|
|
||||||
// */
|
|
||||||
// public volatile @Nullable SignalReason lastSignalReason = null;
|
|
||||||
//
|
|
||||||
// protected BaseThread(Runnable target, String name, int baseThreadIndex, int maximumYieldDepth) {
|
|
||||||
// super(target, name);
|
|
||||||
// this.baseThreadIndex = baseThreadIndex;
|
|
||||||
// this.maximumYieldDepth = maximumYieldDepth;
|
|
||||||
// }
|
|
||||||
//
|
|
||||||
// @Override
|
|
||||||
// public boolean holdsYieldingLock() {
|
|
||||||
// return this.heldYieldingLockCount > 0;
|
|
||||||
// }
|
|
||||||
//
|
|
||||||
// @Override
|
|
||||||
// public void incrementHeldYieldingLockCount() {
|
|
||||||
// this.heldYieldingLockCount++;
|
|
||||||
// if (this.heldYieldingLockCount == 1) {
|
|
||||||
// this.updateCanStartYieldingTasks();
|
|
||||||
// }
|
|
||||||
// }
|
|
||||||
//
|
|
||||||
// @Override
|
|
||||||
// public void decrementHeldYieldingLockCount() {
|
|
||||||
// this.heldYieldingLockCount--;
|
|
||||||
// if (this.heldYieldingLockCount == 0) {
|
|
||||||
// this.updateCanStartYieldingTasks();
|
|
||||||
// }
|
|
||||||
// }
|
|
||||||
//
|
|
||||||
// /**
|
|
||||||
// * Updates {@link #canStartYieldingTasks} according to {@link #yieldDepth} and {@link #heldYieldingLockCount}.
|
|
||||||
// */
|
|
||||||
// private void updateCanStartYieldingTasks() {
|
|
||||||
// this.canStartYieldingTasks = this.heldYieldingLockCount == 0 && this.yieldDepth < this.maximumYieldDepth;
|
|
||||||
// }
|
|
||||||
//
|
|
||||||
// /**
|
|
||||||
// * This method is based on {@link #signal}.
|
|
||||||
// * {@link #signal} must always return true if this method returns true;
|
|
||||||
// * otherwise {@link BaseThreadActivation} will get stuck while choosing a thread to activate.
|
|
||||||
// *
|
|
||||||
// * @see #signal
|
|
||||||
// */
|
|
||||||
// @SuppressWarnings("RedundantIfStatement")
|
|
||||||
// public boolean isWaitingAndNeedsSignal() {
|
|
||||||
// if (this.isWaiting) {
|
|
||||||
// if (this.isNotActuallyWaitingYet) {
|
|
||||||
// if (!this.skipNextWait) {
|
|
||||||
// return true;
|
|
||||||
// }
|
|
||||||
// return false;
|
|
||||||
// }
|
|
||||||
// if (!this.mayBeStillWaitingButHasBeenSignalled) {
|
|
||||||
// return true;
|
|
||||||
// }
|
|
||||||
// }
|
|
||||||
// return false;
|
|
||||||
// }
|
|
||||||
//
|
|
||||||
// /**
|
|
||||||
// * Yields to tasks: polls and executes tasks while possible and the stop condition is not met.
|
|
||||||
// * The stop condition is met if {@code stopCondition} is not null and returns true, or alternatively,
|
|
||||||
// * if {@code stopCondition} is null, and {@code yieldingLock} is successfully acquired.
|
|
||||||
// * When no tasks can be polled, this thread will block, waiting for either a task that can be executed by this
|
|
||||||
// * thread to become available, or for the {@code yieldingLock}, if given, to be released.
|
|
||||||
// * <br>
|
|
||||||
// * Exactly one of {@code stopCondition} and {@code yieldingLock} must be non-null.
|
|
||||||
// */
|
|
||||||
// public final void yieldUntil(@Nullable Long timeoutTime, @Nullable BooleanSupplier stopCondition, @Nullable YieldingLock yieldingLock) {
|
|
||||||
// int oldYieldDepth = this.yieldDepth;
|
|
||||||
// int newYieldDepth = oldYieldDepth + 1;
|
|
||||||
// this.yieldDepth = newYieldDepth;
|
|
||||||
// if (newYieldDepth == maximumYieldDepth) {
|
|
||||||
// this.updateCanStartYieldingTasks();
|
|
||||||
// }
|
|
||||||
// this.runTasksUntil(timeoutTime, stopCondition, yieldingLock);
|
|
||||||
// this.yieldDepth = oldYieldDepth;
|
|
||||||
// if (newYieldDepth == maximumYieldDepth) {
|
|
||||||
// this.updateCanStartYieldingTasks();
|
|
||||||
// }
|
|
||||||
// }
|
|
||||||
//
|
|
||||||
// /**
|
|
||||||
// * This method will keep attempting to find a task to do, and execute it, and if none is found, start waiting
|
|
||||||
// * until the {@code timeoutTime} is reached (which is compared to {@link System#nanoTime}),
|
|
||||||
// * or the thread is signalled by {@link BaseThreadPool} or by a {@link YieldingLock}.
|
|
||||||
// * The loop is broken as soon as the stop condition becomes true, or the given lock is successfully acquired.
|
|
||||||
// * <br>
|
|
||||||
// * The above is the same as {@link #yieldUntil}, except it may be called in situations that is not 'yielding',
|
|
||||||
// * for instance the endless loop polling tasks performed by a n{@link AssistThread}. The difference with
|
|
||||||
// * {@link #yieldUntil} is that this method does not increment or decrement things the yield depth of this thread.
|
|
||||||
// * <br>
|
|
||||||
// * Exactly one of {@code stopCondition} or {@code yieldingLock} must be non-null.
|
|
||||||
// *
|
|
||||||
// * @see #yieldUntil
|
|
||||||
// */
|
|
||||||
// @ThisThreadOnly
|
|
||||||
// @PotentiallyYielding("may yield further if an executed task is potentially yielding")
|
|
||||||
// public final void runTasksUntil(@Nullable Long timeoutTime, @Nullable BooleanSupplier stopCondition, @Nullable YieldingLock yieldingLock) {
|
|
||||||
// if (TickThread.isTickThread()) MinecraftServer.THREAD_DEBUG_LOGGER.ifPresent(it -> it.info("running tasks until"));
|
|
||||||
// this.isPollingTaskOrCheckingStopCondition = true;
|
|
||||||
//
|
|
||||||
// /*
|
|
||||||
// Endless loop that attempts to perform a task, and if one is found, tries to perform another again,
|
|
||||||
// but if none is found, starts awaiting such a task to become available, or for the given yielding lock
|
|
||||||
// to be released.
|
|
||||||
// */
|
|
||||||
// while (true) {
|
|
||||||
// try {
|
|
||||||
// if (timeoutTime != null && System.nanoTime() - timeoutTime >= 0) {
|
|
||||||
// break;
|
|
||||||
// }
|
|
||||||
// if (stopCondition != null) {
|
|
||||||
// if (this == MinecraftServerWrapper.serverThread) {
|
|
||||||
// MinecraftServer.currentManagedBlockStopConditionHasBecomeTrue = false;
|
|
||||||
// }
|
|
||||||
// if (stopCondition.getAsBoolean()) {
|
|
||||||
// if (this == MinecraftServerWrapper.serverThread) {
|
|
||||||
// MinecraftServer.currentManagedBlockStopConditionHasBecomeTrue = true;
|
|
||||||
// }
|
|
||||||
// break;
|
|
||||||
// }
|
|
||||||
// } else {
|
|
||||||
// //noinspection ConstantConditions
|
|
||||||
// if (yieldingLock.tryLock()) {
|
|
||||||
// break;
|
|
||||||
// }
|
|
||||||
// }
|
|
||||||
// } finally {
|
|
||||||
// // Make sure other threads can be signalled for the last waited-for lock again
|
|
||||||
// if (this.lastLockWaitedFor != null) {
|
|
||||||
// this.lastLockWaitedFor.canBeSignalledFor = true;
|
|
||||||
// this.lastLockWaitedFor = null;
|
|
||||||
// }
|
|
||||||
// }
|
|
||||||
//
|
|
||||||
// // If this is the original server thread, update isInSpareTimeAndHaveNoMoreTimeAndNotAlreadyBlocking
|
|
||||||
// if (this == MinecraftServerWrapper.serverThread) {
|
|
||||||
// MinecraftServer.isInSpareTimeAndHaveNoMoreTimeAndNotAlreadyBlocking = MinecraftServer.isInSpareTime && MinecraftServer.blockingCount == 0 && !MinecraftServer.SERVER.haveTime();
|
|
||||||
// }
|
|
||||||
//
|
|
||||||
// // Attempt to poll a task that can be started
|
|
||||||
// Runnable task = this.pollTask();
|
|
||||||
//
|
|
||||||
// // Run the task if found
|
|
||||||
// if (task != null) {
|
|
||||||
//
|
|
||||||
// // If this is the server thread, potentially set nextTimeAssumeWeMayHaveDelayedTasks to true
|
|
||||||
// if (this == MinecraftServerWrapper.serverThread && !MinecraftServer.nextTimeAssumeWeMayHaveDelayedTasks && AbstractTaskQueue.taskQueuesHaveTasks(BaseTaskQueueTier.SERVER.taskQueues)) {
|
|
||||||
// MinecraftServer.nextTimeAssumeWeMayHaveDelayedTasks = true;
|
|
||||||
// }
|
|
||||||
//
|
|
||||||
// // Update highestTierOfTaskOnStack and the thread priority
|
|
||||||
// var highestTierBeforeTask = this.highestTierOfTaskOnStack;
|
|
||||||
// var threadPriorityBeforeTask = this.getPriority();
|
|
||||||
// //noinspection DataFlowIssue
|
|
||||||
// var newHighestTier = highestTierBeforeTask == null ? this.lastPolledTaskTier : highestTierBeforeTask.ordinal < this.lastPolledTaskTier.ordinal ? highestTierBeforeTask : this.lastPolledTaskTier;
|
|
||||||
// //noinspection DataFlowIssue
|
|
||||||
// var newThreadPriority = newHighestTier.threadPriority;
|
|
||||||
// if (newHighestTier != highestTierBeforeTask) {
|
|
||||||
// this.highestTierOfTaskOnStack = newHighestTier;
|
|
||||||
// BaseThreadActivation.callForUpdate();
|
|
||||||
// if (threadPriorityBeforeTask != newThreadPriority) {
|
|
||||||
// this.setPriority(newThreadPriority);
|
|
||||||
// }
|
|
||||||
// }
|
|
||||||
//
|
|
||||||
// this.isPollingTaskOrCheckingStopCondition = false;
|
|
||||||
// task.run();
|
|
||||||
//
|
|
||||||
// // If this is the server thread, execute some chunk tasks
|
|
||||||
// if (this == MinecraftServerWrapper.serverThread) {
|
|
||||||
// if (newHighestTier != BaseTaskQueueTier.SERVER) {
|
|
||||||
// newHighestTier = BaseTaskQueueTier.SERVER;
|
|
||||||
// this.highestTierOfTaskOnStack = newHighestTier;
|
|
||||||
// BaseThreadActivation.callForUpdate();
|
|
||||||
// if (newThreadPriority != newHighestTier.threadPriority) {
|
|
||||||
// newThreadPriority = newHighestTier.threadPriority;
|
|
||||||
// this.setPriority(newThreadPriority);
|
|
||||||
// }
|
|
||||||
// }
|
|
||||||
// MinecraftServer.SERVER.executeMidTickTasks(); // Paper - execute chunk tasks mid tick
|
|
||||||
// }
|
|
||||||
//
|
|
||||||
// // Reset highestTierOfTaskOnStack and the thread priority
|
|
||||||
// if (newHighestTier != highestTierBeforeTask) {
|
|
||||||
// this.highestTierOfTaskOnStack = highestTierBeforeTask;
|
|
||||||
// BaseThreadActivation.callForUpdate();
|
|
||||||
// if (threadPriorityBeforeTask != newThreadPriority) {
|
|
||||||
// this.setPriority(threadPriorityBeforeTask);
|
|
||||||
// }
|
|
||||||
// }
|
|
||||||
//
|
|
||||||
// this.isPollingTaskOrCheckingStopCondition = true;
|
|
||||||
// continue;
|
|
||||||
//
|
|
||||||
// }
|
|
||||||
//
|
|
||||||
// /*
|
|
||||||
// If no task that can be started by this thread was found, wait for a task that we are allowed
|
|
||||||
// to poll to become available (when that happens, the BaseThreadPool will signal this thread),
|
|
||||||
// or for the given yielding lock to be released. This is the only time we should ever block inside
|
|
||||||
// a potentially yielding procedure.
|
|
||||||
// */
|
|
||||||
// this.waitUntilSignalled(timeoutTime, yieldingLock);
|
|
||||||
//
|
|
||||||
// }
|
|
||||||
//
|
|
||||||
// this.isPollingTaskOrCheckingStopCondition = false;
|
|
||||||
//
|
|
||||||
// /*
|
|
||||||
// If the thread was signalled for another reason than the lock, but we acquired the lock instead,
|
|
||||||
// another thread should be signalled for that reason.
|
|
||||||
// */
|
|
||||||
// SignalReason lastSignalReason = this.lastSignalReason;
|
|
||||||
// if (lastSignalReason != null && yieldingLock != null && lastSignalReason != SignalReason.YIELDING_LOCK) {
|
|
||||||
// BaseThreadActivation.callForUpdate();
|
|
||||||
// }
|
|
||||||
//
|
|
||||||
// }
|
|
||||||
//
|
|
||||||
// /**
|
|
||||||
// * @see #pollTask()
|
|
||||||
// */
|
|
||||||
// @ThisThreadOnly
|
|
||||||
// @YieldFree
|
|
||||||
// private @Nullable Runnable pollTaskFromTier(BaseTaskQueueTier tier, boolean tinyOnly) {
|
|
||||||
// for (var queue : tier.taskQueues) {
|
|
||||||
// // Check whether we can not yield to the queue, if we are yielding
|
|
||||||
// boolean canQueueBeYieldedTo = queue.canBeYieldedTo();
|
|
||||||
// if (!canQueueBeYieldedTo && this.yieldDepth > 0) {
|
|
||||||
// continue;
|
|
||||||
// }
|
|
||||||
// Runnable task = tinyOnly ? queue.pollTiny(this) : queue.poll(this);
|
|
||||||
// if (task != null) {
|
|
||||||
// this.lastPolledTaskTier = tier;
|
|
||||||
// return task;
|
|
||||||
// }
|
|
||||||
// /*
|
|
||||||
// Check if the tier has run out of tasks for a span,
|
|
||||||
// in order to update BaseThreadActivation#thereMayBeTasks.
|
|
||||||
// */
|
|
||||||
// for (int spanI = 0; spanI < TaskSpan.length; spanI++) {
|
|
||||||
// TaskSpan span = TaskSpan.VALUES[spanI];
|
|
||||||
// if (queue.canHaveTasks(span)) {
|
|
||||||
// int oldTasks = BaseThreadActivation.thereMayBeTasks[tier.ordinal][spanI][canQueueBeYieldedTo ? 1 : 0].get();
|
|
||||||
// if (oldTasks > 0) {
|
|
||||||
// if (!queue.hasTasks(span)) {
|
|
||||||
// boolean tierHasNoTasksForSpan = true;
|
|
||||||
// for (AbstractTaskQueue otherTierQueue : tier.taskQueues) {
|
|
||||||
// // We already know there are no tasks in this queue
|
|
||||||
// if (otherTierQueue == queue) {
|
|
||||||
// continue;
|
|
||||||
// }
|
|
||||||
// if (otherTierQueue.hasTasks(span)) {
|
|
||||||
// tierHasNoTasksForSpan = false;
|
|
||||||
// break;
|
|
||||||
// }
|
|
||||||
// }
|
|
||||||
// if (tierHasNoTasksForSpan) {
|
|
||||||
// // Set thereMayBeTasks to false, but only if it did not change in the meantime
|
|
||||||
// BaseThreadActivation.thereMayBeTasks[tier.ordinal][spanI][canQueueBeYieldedTo ? 1 : 0].compareAndSet(oldTasks, 0);
|
|
||||||
// }
|
|
||||||
// }
|
|
||||||
// }
|
|
||||||
// }
|
|
||||||
// }
|
|
||||||
// }
|
|
||||||
// return null;
|
|
||||||
// }
|
|
||||||
//
|
|
||||||
// /**
|
|
||||||
// * Polls a task from any queue this thread can currently poll from, and returns it.
|
|
||||||
// * Polling potentially yielding tasks is attempted before yield-free tasks.
|
|
||||||
// *
|
|
||||||
// * @return The task that was polled, or null if no task was found.
|
|
||||||
// */
|
|
||||||
// @ThisThreadOnly
|
|
||||||
// @YieldFree
|
|
||||||
// private @Nullable Runnable pollTask() {
|
|
||||||
// /*
|
|
||||||
// * If this is a server thread, poll from SERVER, and poll tiny tasks from other tiers.
|
|
||||||
// * Note that when polling on the ServerThread, we do not check whether we would be allowed to do so
|
|
||||||
// * by the BaseThreadPool, as we consider keeping the ServerThread in the Thread.State.RUNNABLE state for
|
|
||||||
// * as long as possible to be more important than the off-chance of for example starting a TINY ASYNC task
|
|
||||||
// * on the server thread while no ASYNC tasks are allowed to be polled by other threads at the moment.
|
|
||||||
// */
|
|
||||||
// if (this instanceof ServerThread) {
|
|
||||||
// // Poll from the SERVER queues
|
|
||||||
// Runnable task = this.pollTaskFromTier(BaseTaskQueueTier.SERVER, false);
|
|
||||||
// if (task != null) {
|
|
||||||
// return task;
|
|
||||||
// }
|
|
||||||
// // Poll tiny tasks from other tiers
|
|
||||||
// for (var tier : BaseTaskQueueTier.VALUES_EXCEPT_SERVER) {
|
|
||||||
// task = this.pollTaskFromTier(tier, true);
|
|
||||||
// if (task != null) {
|
|
||||||
// return task;
|
|
||||||
// }
|
|
||||||
// }
|
|
||||||
// // We failed to poll any task
|
|
||||||
// return null;
|
|
||||||
// }
|
|
||||||
// // If this is not a server thread, poll from all queues except SERVER
|
|
||||||
// for (var tier : BaseTaskQueueTier.VALUES_EXCEPT_SERVER) {
|
|
||||||
// /*
|
|
||||||
// Make sure that we are allowed to poll from the tier, according to the presence of an excess number of
|
|
||||||
// threads working on tasks from that tier during the last BaseThreadActivation#update call.
|
|
||||||
// In the case this check's result is too optimistic, and a task is started when ideally it wouldn't have been,
|
|
||||||
// then so be it - it is not terrible. Whenever this happens, enough threads will surely be allocated
|
|
||||||
// by the BaseThreadPool for the task tier that is more in demand anyway, so it does not matter much.
|
|
||||||
// In the case this check's result is too pessimistic, the polling fails and this thread will start to sleep,
|
|
||||||
// but before doing this, will make a call to BaseThreadActivation#callForUpdate that re-activated this
|
|
||||||
// thread if necessary, so no harm is done.
|
|
||||||
// In the case this check causes this thread to go to sleep, the call to BaseThreadActivation#callForUpdate
|
|
||||||
// while isWaiting is true will make sure the BaseThreadPool has the ability to correctly activate a
|
|
||||||
// different thread (that is able to start tasks of a higher tier) if needed.
|
|
||||||
// Here, we do not even make an exception for TINY tasks, since there may already be ongoing avoidable
|
|
||||||
// context-switching due to excess threads that we can solve by letting this thread go to sleep.
|
|
||||||
// */
|
|
||||||
// if (tier.ordinal < BaseThreadActivation.tierInExcessOrdinal) {
|
|
||||||
// /*
|
|
||||||
// Tasks of a certain tier may yield to tasks of the same or a higher
|
|
||||||
// tier, and they may also yield to tiny tasks of a lower tier.
|
|
||||||
// */
|
|
||||||
// var tierYieldingFrom = this.highestTierOfTaskOnStack;
|
|
||||||
// Runnable task = this.pollTaskFromTier(tier, tierYieldingFrom != null && tier.ordinal > tierYieldingFrom.ordinal);
|
|
||||||
// if (task != null) {
|
|
||||||
// return task;
|
|
||||||
// }
|
|
||||||
// }
|
|
||||||
// }
|
|
||||||
// // We failed to poll any task
|
|
||||||
// return null;
|
|
||||||
// }
|
|
||||||
//
|
|
||||||
// /**
|
|
||||||
// * Starts waiting on something to do.
|
|
||||||
// *
|
|
||||||
// * @param timeoutTime The maximum time to wait until (compared to {@link System#nanoTime}).
|
|
||||||
// * @param yieldingLock A {@link YieldingLock} to register with, or null if this thread is not waiting for
|
|
||||||
// * a yielding lock.
|
|
||||||
// */
|
|
||||||
// @ThisThreadOnly
|
|
||||||
// @PotentiallyBlocking
|
|
||||||
// private void waitUntilSignalled(@Nullable Long timeoutTime, @Nullable YieldingLock yieldingLock) {
|
|
||||||
//
|
|
||||||
// // Remember whether we registered to wait with the lock, to unregister later
|
|
||||||
// // Register this thread with the lock if necessary
|
|
||||||
// boolean registeredAsWaitingWithLock = false;
|
|
||||||
// if (yieldingLock != null) {
|
|
||||||
// // No point in registering if we're not going to wait anyway
|
|
||||||
// if (!this.skipNextWait) {
|
|
||||||
// yieldingLock.incrementWaitingThreads();
|
|
||||||
// registeredAsWaitingWithLock = true;
|
|
||||||
// }
|
|
||||||
// }
|
|
||||||
//
|
|
||||||
// /*
|
|
||||||
// Remember whether we changed anything that requires a BaseThreadPool#update call
|
|
||||||
// (after the last call to that method).
|
|
||||||
// */
|
|
||||||
// boolean mustCallPoolUpdateAtEnd = false;
|
|
||||||
//
|
|
||||||
// /*
|
|
||||||
// If we cannot acquire the lock, we can assume this thread is being signalled,
|
|
||||||
// so there is no reason to start waiting.
|
|
||||||
// */
|
|
||||||
// waitWithLock: if (this.waitLock.tryLock()) {
|
|
||||||
// try {
|
|
||||||
//
|
|
||||||
// // If it was set that this thread should skip the wait in the meantime, skip it
|
|
||||||
// if (this.skipNextWait) {
|
|
||||||
// break waitWithLock;
|
|
||||||
// }
|
|
||||||
//
|
|
||||||
// // Mark this thread as waiting
|
|
||||||
// this.lockWaitingFor = yieldingLock;
|
|
||||||
// this.mayBeStillWaitingButHasBeenSignalled = false;
|
|
||||||
// this.isWaiting = true;
|
|
||||||
// // But actually we are not waiting yet, signal has no effect yet during the next short lock release
|
|
||||||
// this.isNotActuallyWaitingYet = true;
|
|
||||||
//
|
|
||||||
// } finally {
|
|
||||||
// this.waitLock.unlock();
|
|
||||||
// }
|
|
||||||
//
|
|
||||||
// // Update the pool
|
|
||||||
// BaseThreadActivation.callForUpdate();
|
|
||||||
//
|
|
||||||
// /*
|
|
||||||
// If we cannot acquire the lock, we can assume this thread is being signalled,
|
|
||||||
// so there is no reason to start waiting.
|
|
||||||
// */
|
|
||||||
// if (this.waitLock.tryLock()) {
|
|
||||||
// try {
|
|
||||||
//
|
|
||||||
// // We passed the short lock release
|
|
||||||
// this.isNotActuallyWaitingYet = false;
|
|
||||||
//
|
|
||||||
// // If it was set that this thread should skip the wait in the meantime, skip it
|
|
||||||
// if (this.skipNextWait) {
|
|
||||||
// this.isWaiting = false;
|
|
||||||
// this.lastLockWaitedFor = this.lockWaitingFor;
|
|
||||||
// this.lockWaitingFor = null;
|
|
||||||
// mustCallPoolUpdateAtEnd = true;
|
|
||||||
// break waitWithLock;
|
|
||||||
// }
|
|
||||||
//
|
|
||||||
// // Wait
|
|
||||||
// try {
|
|
||||||
//
|
|
||||||
// // -1 indicates to not use a timeout (this value is not later set to any other negative value)
|
|
||||||
// long waitForNanos = -1;
|
|
||||||
// if (timeoutTime != null) {
|
|
||||||
// waitForNanos = Math.max(timeoutTime - System.nanoTime(), SERVER_THREAD_WAIT_NANOS_MINIMUM);
|
|
||||||
// } else {
|
|
||||||
// /*
|
|
||||||
// Check if we should wait with a tick-based timeout:
|
|
||||||
// this only happens if this thread is the server thread, in
|
|
||||||
// which case we do not want to wait past the start of the next tick.
|
|
||||||
// */
|
|
||||||
// if (this == MinecraftServerWrapper.serverThread) {
|
|
||||||
// if (MinecraftServer.isWaitingUntilNextTick) {
|
|
||||||
// /*
|
|
||||||
// During waiting until the next tick, we wait until the next tick start.
|
|
||||||
// If it already passed, we do not have to use a timeout, because we will be notified
|
|
||||||
// when the stop condition becomes true.
|
|
||||||
// */
|
|
||||||
// waitForNanos = MinecraftServer.nextTickStartNanoTime - System.nanoTime();
|
|
||||||
// if (waitForNanos < 0) {
|
|
||||||
// waitForNanos = -1;
|
|
||||||
// }
|
|
||||||
// } else if (MinecraftServer.SERVER.isOversleep) {
|
|
||||||
// /*
|
|
||||||
// During this phase, MinecraftServer#mayHaveDelayedTasks() is checked, and we may not
|
|
||||||
// be notified when it changes. Therefore, if the next tick start has not passed, we will
|
|
||||||
// wait until then, but if it has, we wait for a short interval to make sure we keep
|
|
||||||
// checking the stop condition (but not for longer than until the last time we can be
|
|
||||||
// executing extra delayed tasks).
|
|
||||||
// */
|
|
||||||
// waitForNanos = MinecraftServer.nextTickStartNanoTime - System.nanoTime();
|
|
||||||
// if (waitForNanos < 0) {
|
|
||||||
// waitForNanos = Math.min(Math.max(0, MinecraftServer.delayedTasksMaxNextTickNanoTime - System.nanoTime()), SERVER_THREAD_WAIT_NANOS_DURING_OVERSLEEP_WITH_DELAYED_TASKS);
|
|
||||||
// }
|
|
||||||
// }
|
|
||||||
// }
|
|
||||||
// }
|
|
||||||
// if (waitForNanos >= 0) {
|
|
||||||
// // Set the last signal reason to null in case the timeout elapses without a signal
|
|
||||||
// this.lastSignalReason = null;
|
|
||||||
// // Skip if the time is too short
|
|
||||||
// if (waitForNanos >= SERVER_THREAD_WAIT_NANOS_MINIMUM) {
|
|
||||||
// //noinspection ResultOfMethodCallIgnored
|
|
||||||
// this.waitCondition.await(waitForNanos, TimeUnit.NANOSECONDS);
|
|
||||||
// }
|
|
||||||
// } else {
|
|
||||||
// /*
|
|
||||||
// If we did not wait with a timeout, wait indefinitely. If this thread is the server thread,
|
|
||||||
// and the intended start time of the next tick has already passed, but the stop condition to stop
|
|
||||||
// running tasks is still not true, this thread must be signalled when a change in conditions causes
|
|
||||||
// the stop condition to become true.
|
|
||||||
// */
|
|
||||||
// this.waitCondition.await();
|
|
||||||
// }
|
|
||||||
//
|
|
||||||
// } catch (InterruptedException e) {
|
|
||||||
// throw new IllegalStateException(e);
|
|
||||||
// }
|
|
||||||
//
|
|
||||||
// // Unmark this thread as waiting
|
|
||||||
// this.isWaiting = false;
|
|
||||||
// this.lastLockWaitedFor = this.lockWaitingFor;
|
|
||||||
// this.lockWaitingFor = null;
|
|
||||||
// mustCallPoolUpdateAtEnd = true;
|
|
||||||
//
|
|
||||||
// } finally {
|
|
||||||
// this.waitLock.unlock();
|
|
||||||
// }
|
|
||||||
// }
|
|
||||||
//
|
|
||||||
// }
|
|
||||||
//
|
|
||||||
// // Unregister this thread from the lock if necessary
|
|
||||||
// if (registeredAsWaitingWithLock) {
|
|
||||||
// yieldingLock.decrementWaitingThreads();
|
|
||||||
// }
|
|
||||||
//
|
|
||||||
// // Reset skipping the next wait
|
|
||||||
// this.skipNextWait = false;
|
|
||||||
//
|
|
||||||
// // Update the pool if necessary
|
|
||||||
// if (mustCallPoolUpdateAtEnd) {
|
|
||||||
// BaseThreadActivation.callForUpdate();
|
|
||||||
// }
|
|
||||||
//
|
|
||||||
// }
|
|
||||||
//
|
|
||||||
// /**
|
|
||||||
// * An auxiliary method for exclusive use in {@link #signal}, that marks the {@link YieldingLock}
|
|
||||||
// * that this thread is waiting for as having been signalled for, so that no other threads
|
|
||||||
// * are also signalled for it.
|
|
||||||
// * <br>
|
|
||||||
// * This must be called when {@link #signal} returns true, and must be called before any other
|
|
||||||
// * actions relating to the signalling of this thread are performed.
|
|
||||||
// */
|
|
||||||
// private void markLockWaitingForAsSignalledFor() {
|
|
||||||
// @Nullable YieldingLock lockWaitingFor = this.lockWaitingFor;
|
|
||||||
// if (lockWaitingFor != null) {
|
|
||||||
// lockWaitingFor.canBeSignalledFor = false;
|
|
||||||
// }
|
|
||||||
// }
|
|
||||||
//
|
|
||||||
// /**
|
|
||||||
// * Signals this thread to wake up, or if it was not sleeping but attempting to poll a task:
|
|
||||||
// * to not go to sleep the next time no task could be polled, and instead try polling a task again.
|
|
||||||
// *
|
|
||||||
// * @param reason The reason why this thread was signalled, or null if it is irrelevant (e.g. when the signal
|
|
||||||
// * will never need to be repeated because there is only thread waiting for this specific event
|
|
||||||
// * to happen).
|
|
||||||
// * @return Whether this thread was sleeping before, and has woken up now,
|
|
||||||
// * or whether {@link #skipNextWait} was set to true.
|
|
||||||
// */
|
|
||||||
// @AnyThreadSafe
|
|
||||||
// @YieldFree
|
|
||||||
// public final boolean signal(@Nullable SignalReason reason) {
|
|
||||||
// while (!this.waitLock.tryLock()) { // TODO Gale use a wait-free system here by using a sort of leave-a-message-at-the-door Atomic class system
|
|
||||||
// Thread.onSpinWait();
|
|
||||||
// }
|
|
||||||
// try {
|
|
||||||
// if (this.isWaiting) {
|
|
||||||
// if (this.isNotActuallyWaitingYet) {
|
|
||||||
// if (!this.skipNextWait) {
|
|
||||||
// this.markLockWaitingForAsSignalledFor();
|
|
||||||
// this.lastSignalReason = reason;
|
|
||||||
// this.skipNextWait = true;
|
|
||||||
// return true;
|
|
||||||
// }
|
|
||||||
// return false;
|
|
||||||
// }
|
|
||||||
// if (!this.mayBeStillWaitingButHasBeenSignalled) {
|
|
||||||
// this.markLockWaitingForAsSignalledFor();
|
|
||||||
// this.lastSignalReason = reason;
|
|
||||||
// this.mayBeStillWaitingButHasBeenSignalled = true;
|
|
||||||
// this.waitCondition.signal();
|
|
||||||
// return true;
|
|
||||||
// }
|
|
||||||
// } else if (this.isPollingTaskOrCheckingStopCondition) {
|
|
||||||
// if (!this.skipNextWait) {
|
|
||||||
// this.markLockWaitingForAsSignalledFor();
|
|
||||||
// this.lastSignalReason = reason;
|
|
||||||
// this.skipNextWait = true;
|
|
||||||
// return true;
|
|
||||||
// }
|
|
||||||
// }
|
|
||||||
// return false;
|
|
||||||
// } finally {
|
|
||||||
// this.waitLock.unlock();
|
|
||||||
// }
|
|
||||||
// }
|
|
||||||
//
|
|
||||||
// /**
|
|
||||||
// * @return The current thread if it is a {@link BaseThread}, or null otherwise.
|
|
||||||
// */
|
|
||||||
// @SuppressWarnings("unused")
|
|
||||||
// @AnyThreadSafe
|
|
||||||
// @YieldFree
|
|
||||||
// public static @Nullable BaseThread currentBaseThread() {
|
|
||||||
// return Thread.currentThread() instanceof BaseThread baseThread ? baseThread : null;
|
|
||||||
// }
|
|
||||||
//
|
|
||||||
// /**
|
|
||||||
// * @return Whether the current thread is a {@link BaseThread}.
|
|
||||||
// */
|
|
||||||
// @SuppressWarnings("unused")
|
|
||||||
// @AnyThreadSafe
|
|
||||||
// @YieldFree
|
|
||||||
// public static boolean isBaseThread() {
|
|
||||||
// return Thread.currentThread() instanceof BaseThread;
|
|
||||||
// }
|
|
||||||
//
|
|
||||||
//}
|
|
||||||
@@ -1,18 +0,0 @@
|
|||||||
package net.gensokyoreimagined.nitori.executor.thread;
|
|
||||||
|
|
||||||
//import net.minecraft.server.MinecraftServer;
|
|
||||||
//import org.spigotmc.WatchdogThread;
|
|
||||||
//
|
|
||||||
///**
|
|
||||||
// * A type that is unique to {@link MinecraftServer#serverThread},
|
|
||||||
// * to distinguish it from {@link WatchdogThread#instance}.
|
|
||||||
// *
|
|
||||||
// * @author Martijn Muijsers under AGPL-3.0
|
|
||||||
// */
|
|
||||||
//public final class OriginalServerThread extends ServerThread {
|
|
||||||
//
|
|
||||||
// public OriginalServerThread(final Runnable run, final String name) {
|
|
||||||
// super(run, name);
|
|
||||||
// }
|
|
||||||
//
|
|
||||||
//}
|
|
||||||
@@ -1,54 +0,0 @@
|
|||||||
package net.gensokyoreimagined.nitori.executor.thread;
|
|
||||||
|
|
||||||
//import io.papermc.paper.util.TickThread;
|
|
||||||
//import net.gensokyoreimagined.nitori.executor.wrapper.MinecraftServerWrapper;
|
|
||||||
//import net.gensokyoreimagined.nitori.mixin.virtual_thread.accessors.MixinMinecraftServer;
|
|
||||||
//import net.gensokyoreimagined.nitori.mixin.virtual_thread.accessors.MixinWatchdogThread;
|
|
||||||
//import net.minecraft.server.MinecraftServer;
|
|
||||||
//import org.gradle.internal.impldep.com.esotericsoftware.kryo.NotNull;
|
|
||||||
//import org.spigotmc.WatchdogThread;
|
|
||||||
//
|
|
||||||
//import javax.annotation.Nullable;
|
|
||||||
//
|
|
||||||
///**
|
|
||||||
// * A {@link TickThread} that provides an implementation for {@link BaseThread},
|
|
||||||
// * that is shared between the {@link MinecraftServer#serverThread} and {@link WatchdogThread#instance}.
|
|
||||||
// *
|
|
||||||
// * @author Martijn Muijsers under AGPL-3.0
|
|
||||||
// */
|
|
||||||
//public class ServerThread extends TickThread {
|
|
||||||
//
|
|
||||||
// protected ServerThread(final String name) {
|
|
||||||
// super(name);
|
|
||||||
// }
|
|
||||||
//
|
|
||||||
// protected ServerThread(final Runnable run, final String name) {
|
|
||||||
// super(run, name);
|
|
||||||
// }
|
|
||||||
//
|
|
||||||
// /**
|
|
||||||
// * This method must not be called while {@link MinecraftServer#isConstructed} is false.
|
|
||||||
// *
|
|
||||||
// * @return The global {@link ServerThread} instance, which is either
|
|
||||||
// * {@link MinecraftServer#serverThread}, or {@link WatchdogThread#instance} while the server is shutting
|
|
||||||
// * down and the {@link WatchdogThread} was responsible.
|
|
||||||
// */
|
|
||||||
// public static @NotNull Thread getInstance() {
|
|
||||||
// if (((MixinMinecraftServer) MinecraftServerWrapper.SERVER).hasStopped()) {
|
|
||||||
// if (((MixinMinecraftServer) MinecraftServerWrapper.SERVER).shutdownThread() == MixinWatchdogThread.getInstance()) {
|
|
||||||
// return MixinWatchdogThread.getInstance();
|
|
||||||
// }
|
|
||||||
// }
|
|
||||||
//
|
|
||||||
// return MinecraftServerWrapper.serverThread;
|
|
||||||
// }
|
|
||||||
//
|
|
||||||
// /**
|
|
||||||
// * @return The same value as {@link #getInstance()} if {@link MinecraftServer#isConstructed} is true,
|
|
||||||
// * or null otherwise.
|
|
||||||
// */
|
|
||||||
// public static @Nullable Thread getInstanceIfConstructed() {
|
|
||||||
// return MinecraftServerWrapper.isConstructed ? getInstance() : null;
|
|
||||||
// }
|
|
||||||
//
|
|
||||||
//}
|
|
||||||
@@ -1,208 +0,0 @@
|
|||||||
// Taken from https://github.com/GaleMC/Gale/blob/ver/1.19.4/patches/server/0151-Base-thread-pool.patch (separate license)
|
|
||||||
|
|
||||||
package net.gensokyoreimagined.nitori.executor.thread.pool;
|
|
||||||
|
|
||||||
///**
|
|
||||||
// * A pool of threads that can perform tasks to assist the current {@link ServerThread}. These tasks can be of
|
|
||||||
// * different {@linkplain BaseTaskQueueTier tiers}.
|
|
||||||
// * <br>
|
|
||||||
// * This pool intends to keep {@link #targetParallelism} threads active at any time,
|
|
||||||
// * which includes a potentially active {@link ServerThread}.
|
|
||||||
// * <br>
|
|
||||||
// * As such, this pool is closely intertwined with the {@link ServerThread}. This pool can not control the
|
|
||||||
// * {@link ServerThread} in any way, but it is responsible for signalling the {@link ServerThread} when tasks become
|
|
||||||
// * available in a {@link BaseTaskQueueTier#SERVER} task queue, and for listening for when the {@link ServerThread}
|
|
||||||
// * becomes (in)active in order to update the number of active {@link AssistThread}s accordingly.
|
|
||||||
// * <br><br>
|
|
||||||
// * Updates to the threads in this pool are done in a lock-free manner that attempts to do the right thing with
|
|
||||||
// * the volatile information that is available. In some cases, this may cause a thread to be woken up when it
|
|
||||||
// * should not have been, and so on, but the updates being lock-free is more significant than the updates being
|
|
||||||
// * optimal in a high-contention environment. The environment is not expected to have high enough contention for
|
|
||||||
// * this to have much of an impact. Additionally, the suboptimalities in updates are always optimistic in terms of
|
|
||||||
// * making/keeping threads active rather than inactive, and can not a situation where a thread was intended
|
|
||||||
// * to be active, but ends but not being active.
|
|
||||||
// *
|
|
||||||
// * @author Martijn Muijsers under AGPL-3.0
|
|
||||||
// */
|
|
||||||
//public final class BaseThreadPool {
|
|
||||||
//
|
|
||||||
// private BaseThreadPool() {}
|
|
||||||
//
|
|
||||||
// public static final String targetParallelismEnvironmentVariable = "gale.threads.target";
|
|
||||||
// public static final String maxUndisturbedLowerTierThreadCountEnvironmentVariable = "gale.threads.undisturbed";
|
|
||||||
//
|
|
||||||
// /**
|
|
||||||
// * The target number of threads that will be actively in use by this pool,
|
|
||||||
// * which includes a potentially active {@link ServerThread}.
|
|
||||||
// * <br>
|
|
||||||
// * This value is always positive.
|
|
||||||
// * <br>
|
|
||||||
// * The value is currently automatically determined according to the following table:
|
|
||||||
// * <table>
|
|
||||||
// * <tr><th>system threads</th><th>threads spared</th></tr>
|
|
||||||
// * <tr><td>≤ 3</td><td>0</td></tr>
|
|
||||||
// * <tr><td>[4, 14]</td><td>1</td></tr>
|
|
||||||
// * <tr><td>[15, 23]</td><td>2</td></tr>
|
|
||||||
// * <tr><td>[24, 37]</td><td>3</td></tr>
|
|
||||||
// * <tr><td>[38, 54]</td><td>4</td></tr>
|
|
||||||
// * <tr><td>[55, 74]</td><td>5</td></tr>
|
|
||||||
// * <tr><td>[75, 99]</td><td>6</td></tr>
|
|
||||||
// * <tr><td>[100, 127]</td><td>7</td></tr>
|
|
||||||
// * <tr><td>[128, 158]</td><td>8</td></tr>
|
|
||||||
// * <tr><td>[159, 193]</td><td>9</td></tr>
|
|
||||||
// * <tr><td>[194, 232]</td><td>10</td></tr>
|
|
||||||
// * <tr><td>[233, 274]</td><td>11</td></tr>
|
|
||||||
// * <tr><td>≥ 275</td><td>12</td></tr>
|
|
||||||
// * </table>
|
|
||||||
// * Then <code>target parallelism = system threads - threads spared</code>.
|
|
||||||
// * <br>
|
|
||||||
// * The computed value above can be overridden using the {@link #targetParallelismEnvironmentVariable}.
|
|
||||||
// */
|
|
||||||
// public static final int targetParallelism;
|
|
||||||
// static {
|
|
||||||
// int parallelismByEnvironmentVariable = Integer.getInteger(targetParallelismEnvironmentVariable, -1);
|
|
||||||
// int targetParallelismBeforeSetAtLeastOne;
|
|
||||||
// if (parallelismByEnvironmentVariable >= 0) {
|
|
||||||
// targetParallelismBeforeSetAtLeastOne = parallelismByEnvironmentVariable;
|
|
||||||
// } else {
|
|
||||||
// int systemThreads = Runtime.getRuntime().availableProcessors();
|
|
||||||
// int threadsSpared;
|
|
||||||
// if (systemThreads <= 3) {
|
|
||||||
// threadsSpared = 0;
|
|
||||||
// } else if (systemThreads <= 14) {
|
|
||||||
// threadsSpared = 1;
|
|
||||||
// } else if (systemThreads <= 23) {
|
|
||||||
// threadsSpared = 2;
|
|
||||||
// } else if (systemThreads <= 37) {
|
|
||||||
// threadsSpared = 3;
|
|
||||||
// } else if (systemThreads <= 54) {
|
|
||||||
// threadsSpared = 4;
|
|
||||||
// } else if (systemThreads <= 74) {
|
|
||||||
// threadsSpared = 5;
|
|
||||||
// } else if (systemThreads <= 99) {
|
|
||||||
// threadsSpared = 6;
|
|
||||||
// } else if (systemThreads <= 127) {
|
|
||||||
// threadsSpared = 7;
|
|
||||||
// } else if (systemThreads <= 158) {
|
|
||||||
// threadsSpared = 8;
|
|
||||||
// } else if (systemThreads <= 193) {
|
|
||||||
// threadsSpared = 9;
|
|
||||||
// } else if (systemThreads <= 232) {
|
|
||||||
// threadsSpared = 10;
|
|
||||||
// } else if (systemThreads <= 274) {
|
|
||||||
// threadsSpared = 11;
|
|
||||||
// } else {
|
|
||||||
// threadsSpared = 12;
|
|
||||||
// }
|
|
||||||
// targetParallelismBeforeSetAtLeastOne = systemThreads - threadsSpared;
|
|
||||||
// }
|
|
||||||
// targetParallelism = Math.max(1, targetParallelismBeforeSetAtLeastOne);
|
|
||||||
// }
|
|
||||||
//
|
|
||||||
// /**
|
|
||||||
// * The maximum number of threads to be executing tasks, that only have tasks on their thread that are strictly
|
|
||||||
// * below a certain tier, before a thread wishing to execute such tasks gets activated regardless.
|
|
||||||
// * If this threshold of lower tier threads is not exceeded, activating a thread to execute a higher tier task
|
|
||||||
// * will be delayed until one of the active threads finishes execution of their stack or blocks for another
|
|
||||||
// * reason.
|
|
||||||
// * <br>
|
|
||||||
// * This value is always nonnegative.
|
|
||||||
// * <br>
|
|
||||||
// * This value is currently automatically determined according to the following rule:
|
|
||||||
// * <ul>
|
|
||||||
// * <li>0, if {@link #targetParallelism} = 1</li>
|
|
||||||
// * <li>{@code max(1, floor(2/5 * }{@link #targetParallelism}{@code ))}</li>
|
|
||||||
// * </ul>
|
|
||||||
// * The computed value above can be overridden using the {@link #maxUndisturbedLowerTierThreadCountEnvironmentVariable}.
|
|
||||||
// */
|
|
||||||
// public static final int maxUndisturbedLowerTierThreadCount;
|
|
||||||
// static {
|
|
||||||
// int maxUndisturbedLowerTierThreadCountByEnvironmentVariable = Integer.getInteger(maxUndisturbedLowerTierThreadCountEnvironmentVariable, -1);
|
|
||||||
// maxUndisturbedLowerTierThreadCount = maxUndisturbedLowerTierThreadCountByEnvironmentVariable >= 0 ? maxUndisturbedLowerTierThreadCountByEnvironmentVariable : targetParallelism == 1 ? 0 : Math.max(1, targetParallelism * 2 / 5);
|
|
||||||
// }
|
|
||||||
//
|
|
||||||
// /**
|
|
||||||
// * An array of the {@link AssistThread}s in this pool, indexed by their {@link AssistThread#assistThreadIndex}.
|
|
||||||
// * <br>
|
|
||||||
// * This field must only ever be changed from within {@link #addAssistThread}.
|
|
||||||
// */
|
|
||||||
// private static volatile AssistThread[] assistThreads = new AssistThread[0];
|
|
||||||
//
|
|
||||||
// /**
|
|
||||||
// * An array of the {@link BaseThread}s in this pool, indexed by their {@link BaseThread#baseThreadIndex}.
|
|
||||||
// * <br>
|
|
||||||
// * This field must not be referenced anywhere outside {@link #addAssistThread} or {@link #getBaseThreads()}:
|
|
||||||
// * it only holds the last computed value.
|
|
||||||
// */
|
|
||||||
// private static volatile @Nullable BaseThread @NotNull [] lastComputedBaseThreads = new BaseThread[1];
|
|
||||||
//
|
|
||||||
// /**
|
|
||||||
// * Creates a new {@link AssistThread}, adds it to this pool and starts it.
|
|
||||||
// * <br>
|
|
||||||
// * Must only be called from within {@link BaseThreadActivation#update()} while
|
|
||||||
// * {@link BaseThreadActivation#updateOngoingOnThread} is not null.
|
|
||||||
// */
|
|
||||||
// public static void addAssistThread() {
|
|
||||||
// int oldThreadsLength = assistThreads.length;
|
|
||||||
// int newThreadsLength = oldThreadsLength + 1;
|
|
||||||
// // Expand the thread array
|
|
||||||
// AssistThread[] newAssistThreads = Arrays.copyOf(assistThreads, newThreadsLength);
|
|
||||||
// // Create the new thread
|
|
||||||
// AssistThread newThread = newAssistThreads[oldThreadsLength] = new AssistThread(oldThreadsLength);
|
|
||||||
// // Save the new thread array
|
|
||||||
// assistThreads = newAssistThreads;
|
|
||||||
// // Update the assist threads in baseThreads
|
|
||||||
// @SuppressWarnings("NonAtomicOperationOnVolatileField")
|
|
||||||
// BaseThread[] newLastComputedBaseThreads = lastComputedBaseThreads = Arrays.copyOf(lastComputedBaseThreads, newThreadsLength + 1);
|
|
||||||
// newLastComputedBaseThreads[newThreadsLength] = newThread;
|
|
||||||
// // Start the thread
|
|
||||||
// newThread.start();
|
|
||||||
// MinecraftServer.THREAD_DEBUG_LOGGER.ifPresent(it -> it.info("Added assist thread " + newAssistThreads.length));
|
|
||||||
// }
|
|
||||||
//
|
|
||||||
// /**
|
|
||||||
// * The {@link BaseThread}s ({@link ServerThread}s and {@link AssistThread}s) in this thread pool,
|
|
||||||
// * specifically for the purpose of easy iteration.
|
|
||||||
// * <br>
|
|
||||||
// * Note that the {@link ServerThread} at index 0 may be null if {@link MinecraftServer#isConstructed} is false.
|
|
||||||
// * <br>
|
|
||||||
// * Must only be called from within {@link BaseThreadActivation#update()} while
|
|
||||||
// * {@link BaseThreadActivation#updateOngoingOnThread} is not null.
|
|
||||||
// */
|
|
||||||
// static @Nullable BaseThread @NotNull [] getBaseThreads() {
|
|
||||||
// // Store in a non-local volatile
|
|
||||||
// @Nullable BaseThread @NotNull [] baseThreads = lastComputedBaseThreads;
|
|
||||||
// // Update the server thread if necessary
|
|
||||||
// baseThreads[0] = ServerThread.getInstanceIfConstructed();
|
|
||||||
// // Return the value
|
|
||||||
// return baseThreads;
|
|
||||||
// }
|
|
||||||
//
|
|
||||||
// /**
|
|
||||||
// * This method must not be called with {@code index} = 0 while {@link MinecraftServer#isConstructed} is false.
|
|
||||||
// *
|
|
||||||
// * @return The {@link BaseThread} with the given {@link BaseThread#baseThreadIndex}.
|
|
||||||
// * This must not be called
|
|
||||||
// */
|
|
||||||
// public static @NotNull BaseThread getThreadByBaseIndex(int index) {
|
|
||||||
// if (index == 0) {
|
|
||||||
// return ServerThread.getInstance();
|
|
||||||
// }
|
|
||||||
// return assistThreads[index - 1];
|
|
||||||
// }
|
|
||||||
//
|
|
||||||
// /**
|
|
||||||
// * @return The same value as {@link #getThreadByBaseIndex} if {@link MinecraftServer#isConstructed} is true
|
|
||||||
// * or if the given {@code index} is not 0,
|
|
||||||
// * or null otherwise (i.e. if {@link MinecraftServer#isConstructed} is false and the given {@code index} is 0).
|
|
||||||
// */
|
|
||||||
// @SuppressWarnings("unused")
|
|
||||||
// public static @Nullable BaseThread getThreadByBaseIndexIfConstructed(int index) {
|
|
||||||
// return index != 0 || MinecraftServer.isConstructed ? getThreadByBaseIndex(index) : null;
|
|
||||||
// }
|
|
||||||
//
|
|
||||||
// public static AssistThread getThreadByAssistIndex(int index) {
|
|
||||||
// return assistThreads[index];
|
|
||||||
// }
|
|
||||||
//
|
|
||||||
//}
|
|
||||||
@@ -1,10 +0,0 @@
|
|||||||
package net.gensokyoreimagined.nitori.executor.wrapper;
|
|
||||||
|
|
||||||
import net.minecraft.server.MinecraftServer;
|
|
||||||
|
|
||||||
public class MinecraftServerWrapper {
|
|
||||||
// Named to make replacement of Gale patches easier (replace MinecraftServer.serverThread with MinecraftServerWrapper.serverThread)
|
|
||||||
public static Thread serverThread;
|
|
||||||
public static MinecraftServer SERVER;
|
|
||||||
public static boolean isConstructed;
|
|
||||||
}
|
|
||||||
@@ -39,7 +39,7 @@ public abstract class MixinEntity {
|
|||||||
* Implementation of 0065-some-entity-micro-opts.patch
|
* Implementation of 0065-some-entity-micro-opts.patch
|
||||||
*/
|
*/
|
||||||
@Unique
|
@Unique
|
||||||
public float gensouHacks$getLightLevelDependentMagicValue(BlockPos pos) {
|
public float nitori$getLightLevelDependentMagicValue(BlockPos pos) {
|
||||||
return this.level.hasChunkAt(this.getBlockX(), this.getBlockZ()) ? this.level.getLightLevelDependentMagicValue(pos) : 0.0F;
|
return this.level.hasChunkAt(this.getBlockX(), this.getBlockZ()) ? this.level.getLightLevelDependentMagicValue(pos) : 0.0F;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -48,7 +48,7 @@ public abstract class MixinEntity {
|
|||||||
*/
|
*/
|
||||||
@Inject(method = "getLightLevelDependentMagicValue", at = @At("HEAD"), cancellable = true)
|
@Inject(method = "getLightLevelDependentMagicValue", at = @At("HEAD"), cancellable = true)
|
||||||
private void getLightLevelDependentMagicValue(CallbackInfoReturnable<Float> cir) {
|
private void getLightLevelDependentMagicValue(CallbackInfoReturnable<Float> cir) {
|
||||||
cir.setReturnValue(this.gensouHacks$getLightLevelDependentMagicValue(new BlockPos(this.getBlockX(), (int) this.getEyeY(), this.getBlockZ())));
|
cir.setReturnValue(this.nitori$getLightLevelDependentMagicValue(new BlockPos(this.getBlockX(), (int) this.getEyeY(), this.getBlockZ())));
|
||||||
cir.cancel();
|
cir.cancel();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -79,12 +79,12 @@ public class MixinEntitySectionStorage<T extends EntityAccess> {
|
|||||||
// are placed somewhere inside the packed long
|
// are placed somewhere inside the packed long
|
||||||
for (int x = j; x <= m; x++) {
|
for (int x = j; x <= m; x++) {
|
||||||
for (int z = Math.max(l, 0); z <= o; z++) {
|
for (int z = Math.max(l, 0); z <= o; z++) {
|
||||||
this.gensouHacks$forEachInColumn(x, k, n, z, consumer);
|
this.nitori$forEachInColumn(x, k, n, z, consumer);
|
||||||
}
|
}
|
||||||
|
|
||||||
int bound = Math.min(-1, o);
|
int bound = Math.min(-1, o);
|
||||||
for (int z = l; z <= bound; z++) {
|
for (int z = l; z <= bound; z++) {
|
||||||
this.gensouHacks$forEachInColumn(x, k, n, z, consumer);
|
this.nitori$forEachInColumn(x, k, n, z, consumer);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -95,19 +95,19 @@ public class MixinEntitySectionStorage<T extends EntityAccess> {
|
|||||||
|
|
||||||
// Mirai start - lithium: fast retrieval
|
// Mirai start - lithium: fast retrieval
|
||||||
@Unique
|
@Unique
|
||||||
private void gensouHacks$forEachInColumn(int x, int k, int n, int z, AbortableIterationConsumer<EntitySection<T>> action) {
|
private void nitori$forEachInColumn(int x, int k, int n, int z, AbortableIterationConsumer<EntitySection<T>> action) {
|
||||||
// y from negative to positive, but y is treated as unsigned
|
// y from negative to positive, but y is treated as unsigned
|
||||||
for (int y = Math.max(k, 0); y <= n; y++) {
|
for (int y = Math.max(k, 0); y <= n; y++) {
|
||||||
this.gensouHacks$consumeSection(SectionPos.asLong(x, y, z), action);
|
this.nitori$consumeSection(SectionPos.asLong(x, y, z), action);
|
||||||
}
|
}
|
||||||
int bound = Math.min(-1, n);
|
int bound = Math.min(-1, n);
|
||||||
for (int y = k; y <= bound; y++) {
|
for (int y = k; y <= bound; y++) {
|
||||||
this.gensouHacks$consumeSection(SectionPos.asLong(x, y, z), action);
|
this.nitori$consumeSection(SectionPos.asLong(x, y, z), action);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@Unique
|
@Unique
|
||||||
private void gensouHacks$consumeSection(long pos, AbortableIterationConsumer<EntitySection<T>> action) {
|
private void nitori$consumeSection(long pos, AbortableIterationConsumer<EntitySection<T>> action) {
|
||||||
EntitySection<T> entitySection = this.getSection(pos);
|
EntitySection<T> entitySection = this.getSection(pos);
|
||||||
if (entitySection != null && !entitySection.isEmpty() && entitySection.getStatus().isAccessible()) {
|
if (entitySection != null && !entitySection.isEmpty() && entitySection.getStatus().isAccessible()) {
|
||||||
action.accept(entitySection);
|
action.accept(entitySection);
|
||||||
|
|||||||
@@ -1,29 +0,0 @@
|
|||||||
// Nitori Copyright (C) 2024 Gensokyo Reimagined
|
|
||||||
//
|
|
||||||
// This program is free software: you can redistribute it and/or modify
|
|
||||||
// it under the terms of the GNU General Public License as published by
|
|
||||||
// the Free Software Foundation, either version 3 of the License, or
|
|
||||||
// (at your option) any later version.
|
|
||||||
//
|
|
||||||
// This program is distributed in the hope that it will be useful,
|
|
||||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
||||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
||||||
// GNU General Public License for more details.
|
|
||||||
//
|
|
||||||
// You should have received a copy of the GNU General Public License
|
|
||||||
// along with this program. If not, see <https://www.gnu.org/licenses/>.
|
|
||||||
package net.gensokyoreimagined.nitori.mixin;
|
|
||||||
|
|
||||||
import ca.spottedleaf.moonrise.common.list.IteratorSafeOrderedReferenceSet;
|
|
||||||
import net.gensokyoreimagined.nitori.access.IMixinIteratorSafeOrderedReferenceSetAccess;
|
|
||||||
import org.spongepowered.asm.mixin.Mixin;
|
|
||||||
import org.spongepowered.asm.mixin.gen.Accessor;
|
|
||||||
|
|
||||||
@Mixin(IteratorSafeOrderedReferenceSet.class)
|
|
||||||
public abstract class MixinIteratorSafeOrderedReferenceSet implements IMixinIteratorSafeOrderedReferenceSetAccess {
|
|
||||||
// Implementation of 0107-Multithreaded-Tracker.patch
|
|
||||||
// @Accessor happens to do exactly what is needed, making for nice shorthand
|
|
||||||
@Override
|
|
||||||
@Accessor
|
|
||||||
public abstract int getListSize(); // Mirai - expose listSize
|
|
||||||
}
|
|
||||||
@@ -1,42 +0,0 @@
|
|||||||
// Nitori Copyright (C) 2024 Gensokyo Reimagined
|
|
||||||
//
|
|
||||||
// This program is free software: you can redistribute it and/or modify
|
|
||||||
// it under the terms of the GNU General Public License as published by
|
|
||||||
// the Free Software Foundation, either version 3 of the License, or
|
|
||||||
// (at your option) any later version.
|
|
||||||
//
|
|
||||||
// This program is distributed in the hope that it will be useful,
|
|
||||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
||||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
||||||
// GNU General Public License for more details.
|
|
||||||
//
|
|
||||||
// You should have received a copy of the GNU General Public License
|
|
||||||
// along with this program. If not, see <https://www.gnu.org/licenses/>.
|
|
||||||
package net.gensokyoreimagined.nitori.mixin;
|
|
||||||
|
|
||||||
import com.google.common.collect.Sets;
|
|
||||||
import net.minecraft.server.level.ServerBossEvent;
|
|
||||||
import net.minecraft.server.level.ServerPlayer;
|
|
||||||
import org.spongepowered.asm.mixin.Final;
|
|
||||||
import org.spongepowered.asm.mixin.Mixin;
|
|
||||||
import org.spongepowered.asm.mixin.Mutable;
|
|
||||||
import org.spongepowered.asm.mixin.Shadow;
|
|
||||||
import org.spongepowered.asm.mixin.injection.At;
|
|
||||||
import org.spongepowered.asm.mixin.injection.Inject;
|
|
||||||
import org.spongepowered.asm.mixin.injection.callback.CallbackInfo;
|
|
||||||
|
|
||||||
import java.util.Set;
|
|
||||||
|
|
||||||
@Mixin(ServerBossEvent.class)
|
|
||||||
public abstract class MixinServerBossEvent {
|
|
||||||
@Final
|
|
||||||
@Mutable
|
|
||||||
@Shadow
|
|
||||||
private Set<ServerPlayer> players;
|
|
||||||
|
|
||||||
@Inject(method = "<init>", at = @At("RETURN"))
|
|
||||||
private void reassignEntityTrackers(CallbackInfo ci) {
|
|
||||||
// Implementation of 0107-Multithreaded-Tracker.patch
|
|
||||||
this.players = Sets.newConcurrentHashSet(); // Mirai - players can be removed in async tracking
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -12,7 +12,7 @@
|
|||||||
//
|
//
|
||||||
// You should have received a copy of the GNU General Public License
|
// You should have received a copy of the GNU General Public License
|
||||||
// along with this program. If not, see <https://www.gnu.org/licenses/>.
|
// along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||||
package net.gensokyoreimagined.nitori.mixin;
|
package net.gensokyoreimagined.nitori.mixin.logic.stats;
|
||||||
|
|
||||||
import net.minecraft.resources.ResourceLocation;
|
import net.minecraft.resources.ResourceLocation;
|
||||||
import net.minecraft.world.entity.Entity;
|
import net.minecraft.world.entity.Entity;
|
||||||
@@ -25,8 +25,8 @@ import org.spongepowered.asm.mixin.injection.At;
|
|||||||
import org.spongepowered.asm.mixin.injection.Redirect;
|
import org.spongepowered.asm.mixin.injection.Redirect;
|
||||||
|
|
||||||
@Mixin(Player.class)
|
@Mixin(Player.class)
|
||||||
public abstract class MixinPlayer extends Entity {
|
public abstract class FasterStatsMixin extends Entity {
|
||||||
public MixinPlayer(Level world) {
|
public FasterStatsMixin(Level world) {
|
||||||
super(EntityType.PLAYER, world);
|
super(EntityType.PLAYER, world);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1,4 +1,4 @@
|
|||||||
package net.gensokyoreimagined.nitori.mixin.world.tick_scheduler;
|
package net.gensokyoreimagined.nitori.mixin.removed.world.tick_scheduler;
|
||||||
|
|
||||||
//TODO: Make this work with paper
|
//TODO: Make this work with paper
|
||||||
|
|
||||||
@@ -12,7 +12,7 @@
|
|||||||
//
|
//
|
||||||
// You should have received a copy of the GNU General Public License
|
// You should have received a copy of the GNU General Public License
|
||||||
// along with this program. If not, see <https://www.gnu.org/licenses/>.
|
// along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||||
package net.gensokyoreimagined.nitori.mixin;
|
package net.gensokyoreimagined.nitori.mixin.save;
|
||||||
|
|
||||||
import net.minecraft.Util;
|
import net.minecraft.Util;
|
||||||
import net.minecraft.server.players.PlayerList;
|
import net.minecraft.server.players.PlayerList;
|
||||||
@@ -27,13 +27,13 @@ import org.spongepowered.asm.mixin.injection.Redirect;
|
|||||||
import java.util.concurrent.CompletableFuture;
|
import java.util.concurrent.CompletableFuture;
|
||||||
|
|
||||||
@Mixin(PlayerList.class)
|
@Mixin(PlayerList.class)
|
||||||
public class MixinPlayerList {
|
public class AsyncPlayerSaveMixin {
|
||||||
@Final
|
@Final
|
||||||
@Shadow
|
@Shadow
|
||||||
public PlayerDataStorage playerIo;
|
public PlayerDataStorage playerIo;
|
||||||
|
|
||||||
@Redirect(method = "save", at = @At(value = "INVOKE", target = "Lnet/minecraft/world/level/storage/PlayerDataStorage;save(Lnet/minecraft/world/entity/player/Player;)V"))
|
@Redirect(method = "save", at = @At(value = "INVOKE", target = "Lnet/minecraft/world/level/storage/PlayerDataStorage;save(Lnet/minecraft/world/entity/player/Player;)V"))
|
||||||
private void gensouHacks$savePlayerData(PlayerDataStorage instance, Player player) {
|
private void nitori$savePlayerData(PlayerDataStorage instance, Player player) {
|
||||||
Runnable writeRunnable = () -> playerIo.save(player);
|
Runnable writeRunnable = () -> playerIo.save(player);
|
||||||
|
|
||||||
var ioExecutor = Util.backgroundExecutor();
|
var ioExecutor = Util.backgroundExecutor();
|
||||||
@@ -12,7 +12,7 @@
|
|||||||
//
|
//
|
||||||
// You should have received a copy of the GNU General Public License
|
// You should have received a copy of the GNU General Public License
|
||||||
// along with this program. If not, see <https://www.gnu.org/licenses/>.
|
// along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||||
package net.gensokyoreimagined.nitori.mixin;
|
package net.gensokyoreimagined.nitori.mixin.save;
|
||||||
|
|
||||||
import net.minecraft.Util;
|
import net.minecraft.Util;
|
||||||
import net.minecraft.world.entity.player.Player;
|
import net.minecraft.world.entity.player.Player;
|
||||||
@@ -28,7 +28,7 @@ import java.util.concurrent.CompletableFuture;
|
|||||||
@Mixin(CraftPlayer.class)
|
@Mixin(CraftPlayer.class)
|
||||||
public class MixinCraftPlayer {
|
public class MixinCraftPlayer {
|
||||||
@Redirect(method = "saveData", at = @At(value = "INVOKE", target = "Lnet/minecraft/world/level/storage/PlayerDataStorage;save(Lnet/minecraft/world/entity/player/Player;)V"))
|
@Redirect(method = "saveData", at = @At(value = "INVOKE", target = "Lnet/minecraft/world/level/storage/PlayerDataStorage;save(Lnet/minecraft/world/entity/player/Player;)V"))
|
||||||
private void gensouHacks$savePlayerData(PlayerDataStorage instance, Player path) {
|
private void nitori$savePlayerData(PlayerDataStorage instance, Player path) {
|
||||||
Runnable writeRunnable = () -> {
|
Runnable writeRunnable = () -> {
|
||||||
var craftPlayer = (CraftPlayer) (Object) this;
|
var craftPlayer = (CraftPlayer) (Object) this;
|
||||||
var server = craftPlayer.getServer();
|
var server = craftPlayer.getServer();
|
||||||
@@ -12,7 +12,7 @@
|
|||||||
//
|
//
|
||||||
// You should have received a copy of the GNU General Public License
|
// You should have received a copy of the GNU General Public License
|
||||||
// along with this program. If not, see <https://www.gnu.org/licenses/>.
|
// along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||||
package net.gensokyoreimagined.nitori.mixin;
|
package net.gensokyoreimagined.nitori.mixin.save;
|
||||||
|
|
||||||
import net.minecraft.Util;
|
import net.minecraft.Util;
|
||||||
import net.minecraft.nbt.CompoundTag;
|
import net.minecraft.nbt.CompoundTag;
|
||||||
@@ -29,7 +29,7 @@ public abstract class MixinLevelStorageAccess {
|
|||||||
@Shadow protected abstract void saveLevelData(CompoundTag nbt);
|
@Shadow protected abstract void saveLevelData(CompoundTag nbt);
|
||||||
|
|
||||||
@Redirect(method = "modifyLevelDataWithoutDatafix", at = @At(value = "INVOKE", target = "Lnet/minecraft/world/level/storage/LevelStorageSource$LevelStorageAccess;saveLevelData(Lnet/minecraft/nbt/CompoundTag;)V"))
|
@Redirect(method = "modifyLevelDataWithoutDatafix", at = @At(value = "INVOKE", target = "Lnet/minecraft/world/level/storage/LevelStorageSource$LevelStorageAccess;saveLevelData(Lnet/minecraft/nbt/CompoundTag;)V"))
|
||||||
private void gensouHacks$saveLevelData(LevelStorageSource.LevelStorageAccess levelStorageAccess, CompoundTag compoundTag) {
|
private void nitori$saveLevelData(LevelStorageSource.LevelStorageAccess levelStorageAccess, CompoundTag compoundTag) {
|
||||||
Runnable writeRunnable = () -> saveLevelData(compoundTag);
|
Runnable writeRunnable = () -> saveLevelData(compoundTag);
|
||||||
|
|
||||||
var ioExecutor = Util.backgroundExecutor();
|
var ioExecutor = Util.backgroundExecutor();
|
||||||
@@ -37,7 +37,7 @@ public abstract class MixinLevelStorageAccess {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Redirect(method = "saveDataTag(Lnet/minecraft/core/RegistryAccess;Lnet/minecraft/world/level/storage/WorldData;Lnet/minecraft/nbt/CompoundTag;)V", at = @At(value = "INVOKE", target = "Lnet/minecraft/world/level/storage/LevelStorageSource$LevelStorageAccess;saveLevelData(Lnet/minecraft/nbt/CompoundTag;)V"))
|
@Redirect(method = "saveDataTag(Lnet/minecraft/core/RegistryAccess;Lnet/minecraft/world/level/storage/WorldData;Lnet/minecraft/nbt/CompoundTag;)V", at = @At(value = "INVOKE", target = "Lnet/minecraft/world/level/storage/LevelStorageSource$LevelStorageAccess;saveLevelData(Lnet/minecraft/nbt/CompoundTag;)V"))
|
||||||
private void gensouHacks$saveLevelData2(LevelStorageSource.LevelStorageAccess levelStorageAccess, CompoundTag compoundTag) {
|
private void nitori$saveLevelData2(LevelStorageSource.LevelStorageAccess levelStorageAccess, CompoundTag compoundTag) {
|
||||||
Runnable writeRunnable = () -> saveLevelData(compoundTag);
|
Runnable writeRunnable = () -> saveLevelData(compoundTag);
|
||||||
|
|
||||||
var ioExecutor = Util.backgroundExecutor();
|
var ioExecutor = Util.backgroundExecutor();
|
||||||
@@ -12,20 +12,20 @@
|
|||||||
//
|
//
|
||||||
// You should have received a copy of the GNU General Public License
|
// You should have received a copy of the GNU General Public License
|
||||||
// along with this program. If not, see <https://www.gnu.org/licenses/>.
|
// along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||||
package net.gensokyoreimagined.nitori.mixin;
|
package net.gensokyoreimagined.nitori.mixin.unapplied;
|
||||||
|
|
||||||
import ca.spottedleaf.moonrise.common.list.EntityList;
|
//import ca.spottedleaf.moonrise.common.list.EntityList;
|
||||||
import ca.spottedleaf.moonrise.patches.chunk_system.level.entity.ChunkEntitySlices;
|
//import ca.spottedleaf.moonrise.patches.chunk_system.level.entity.ChunkEntitySlices;
|
||||||
import net.gensokyoreimagined.nitori.access.IMixinChunkEntitySlicesAccess;
|
//import net.gensokyoreimagined.nitori.access.IMixinChunkEntitySlicesAccess;
|
||||||
import org.spongepowered.asm.mixin.Final;
|
//import org.spongepowered.asm.mixin.Final;
|
||||||
import org.spongepowered.asm.mixin.Mixin;
|
//import org.spongepowered.asm.mixin.Mixin;
|
||||||
import org.spongepowered.asm.mixin.gen.Accessor;
|
//import org.spongepowered.asm.mixin.gen.Accessor;
|
||||||
|
//
|
||||||
@Mixin(ChunkEntitySlices.class)
|
//@Mixin(ChunkEntitySlices.class)
|
||||||
public abstract class MixinChunkEntitySlices implements IMixinChunkEntitySlicesAccess {
|
//public abstract class MixinChunkEntitySlices implements IMixinChunkEntitySlicesAccess {
|
||||||
// Implementation of 0107-Multithreaded-Tracker.patch
|
// // Implementation of 0107-Multithreaded-Tracker.patch
|
||||||
@Override
|
// @Override
|
||||||
@Final
|
// @Final
|
||||||
@Accessor
|
// @Accessor
|
||||||
public abstract EntityList getEntities();
|
// public abstract EntityList getEntities();
|
||||||
}
|
//}
|
||||||
@@ -0,0 +1,29 @@
|
|||||||
|
// Nitori Copyright (C) 2024 Gensokyo Reimagined
|
||||||
|
//
|
||||||
|
// This program is free software: you can redistribute it and/or modify
|
||||||
|
// it under the terms of the GNU General Public License as published by
|
||||||
|
// the Free Software Foundation, either version 3 of the License, or
|
||||||
|
// (at your option) any later version.
|
||||||
|
//
|
||||||
|
// This program is distributed in the hope that it will be useful,
|
||||||
|
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
// GNU General Public License for more details.
|
||||||
|
//
|
||||||
|
// You should have received a copy of the GNU General Public License
|
||||||
|
// along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||||
|
package net.gensokyoreimagined.nitori.mixin.unapplied;
|
||||||
|
|
||||||
|
//import ca.spottedleaf.moonrise.common.list.IteratorSafeOrderedReferenceSet;
|
||||||
|
//import net.gensokyoreimagined.nitori.access.IMixinIteratorSafeOrderedReferenceSetAccess;
|
||||||
|
//import org.spongepowered.asm.mixin.Mixin;
|
||||||
|
//import org.spongepowered.asm.mixin.gen.Accessor;
|
||||||
|
//
|
||||||
|
//@Mixin(IteratorSafeOrderedReferenceSet.class)
|
||||||
|
//public abstract class MixinIteratorSafeOrderedReferenceSet implements IMixinIteratorSafeOrderedReferenceSetAccess {
|
||||||
|
// // Implementation of 0107-Multithreaded-Tracker.patch
|
||||||
|
// // @Accessor happens to do exactly what is needed, making for nice shorthand
|
||||||
|
// @Override
|
||||||
|
// @Accessor
|
||||||
|
// public abstract int getListSize(); // Mirai - expose listSize
|
||||||
|
//}
|
||||||
@@ -0,0 +1,42 @@
|
|||||||
|
// Nitori Copyright (C) 2024 Gensokyo Reimagined
|
||||||
|
//
|
||||||
|
// This program is free software: you can redistribute it and/or modify
|
||||||
|
// it under the terms of the GNU General Public License as published by
|
||||||
|
// the Free Software Foundation, either version 3 of the License, or
|
||||||
|
// (at your option) any later version.
|
||||||
|
//
|
||||||
|
// This program is distributed in the hope that it will be useful,
|
||||||
|
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
// GNU General Public License for more details.
|
||||||
|
//
|
||||||
|
// You should have received a copy of the GNU General Public License
|
||||||
|
// along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||||
|
package net.gensokyoreimagined.nitori.mixin.unapplied;
|
||||||
|
|
||||||
|
//import com.google.common.collect.Sets;
|
||||||
|
//import net.minecraft.server.level.ServerBossEvent;
|
||||||
|
//import net.minecraft.server.level.ServerPlayer;
|
||||||
|
//import org.spongepowered.asm.mixin.Final;
|
||||||
|
//import org.spongepowered.asm.mixin.Mixin;
|
||||||
|
//import org.spongepowered.asm.mixin.Mutable;
|
||||||
|
//import org.spongepowered.asm.mixin.Shadow;
|
||||||
|
//import org.spongepowered.asm.mixin.injection.At;
|
||||||
|
//import org.spongepowered.asm.mixin.injection.Inject;
|
||||||
|
//import org.spongepowered.asm.mixin.injection.callback.CallbackInfo;
|
||||||
|
//
|
||||||
|
//import java.util.Set;
|
||||||
|
//
|
||||||
|
//@Mixin(ServerBossEvent.class)
|
||||||
|
//public abstract class MixinServerBossEvent {
|
||||||
|
// @Final
|
||||||
|
// @Mutable
|
||||||
|
// @Shadow
|
||||||
|
// private Set<ServerPlayer> players;
|
||||||
|
//
|
||||||
|
// @Inject(method = "<init>", at = @At("RETURN"))
|
||||||
|
// private void reassignEntityTrackers(CallbackInfo ci) {
|
||||||
|
// // Implementation of 0107-Multithreaded-Tracker.patch
|
||||||
|
// this.players = Sets.newConcurrentHashSet(); // Mirai - players can be removed in async tracking
|
||||||
|
// }
|
||||||
|
//}
|
||||||
@@ -1,4 +1,4 @@
|
|||||||
package net.gensokyoreimagined.nitori.mixin.experimental.entity.block_caching.block_support;
|
package net.gensokyoreimagined.nitori.mixin.unapplied.experimental.entity.block_caching.block_support;
|
||||||
|
|
||||||
//import net.gensokyoreimagined.nitori.common.entity.block_tracking.BlockCache;
|
//import net.gensokyoreimagined.nitori.common.entity.block_tracking.BlockCache;
|
||||||
//import net.gensokyoreimagined.nitori.common.entity.block_tracking.BlockCacheProvider;
|
//import net.gensokyoreimagined.nitori.common.entity.block_tracking.BlockCacheProvider;
|
||||||
@@ -1,35 +0,0 @@
|
|||||||
package net.gensokyoreimagined.nitori.mixin.virtual_thread.accessors;
|
|
||||||
|
|
||||||
//import com.llamalad7.mixinextras.sugar.Local;
|
|
||||||
//import net.gensokyoreimagined.nitori.executor.thread.OriginalServerThread;
|
|
||||||
//import net.gensokyoreimagined.nitori.executor.wrapper.MinecraftServerWrapper;
|
|
||||||
//import net.minecraft.server.MinecraftServer;
|
|
||||||
//import org.spongepowered.asm.mixin.Mixin;
|
|
||||||
//import org.spongepowered.asm.mixin.gen.Accessor;
|
|
||||||
//import org.spongepowered.asm.mixin.injection.At;
|
|
||||||
//import org.spongepowered.asm.mixin.injection.Inject;
|
|
||||||
//import org.spongepowered.asm.mixin.injection.callback.CallbackInfo;
|
|
||||||
//
|
|
||||||
//@Mixin(MinecraftServer.class)
|
|
||||||
//public interface MixinMinecraftServer {
|
|
||||||
// @Inject(method = "<init>", at = @At("RETURN"))
|
|
||||||
// private void onConstructed(CallbackInfo ci, @Local(argsOnly = true) Thread thread) {
|
|
||||||
// MinecraftServerWrapper.SERVER = (MinecraftServer) this;
|
|
||||||
// MinecraftServerWrapper.isConstructed = true;
|
|
||||||
//
|
|
||||||
// if (thread instanceof OriginalServerThread) {
|
|
||||||
// MinecraftServerWrapper.serverThread = (OriginalServerThread) thread;
|
|
||||||
// return;
|
|
||||||
// }
|
|
||||||
//
|
|
||||||
// throw new AssertionError("Type of serverThread is not OriginalServerThread!");
|
|
||||||
// }
|
|
||||||
//
|
|
||||||
// @Accessor("hasStopped")
|
|
||||||
// boolean hasStopped();
|
|
||||||
//
|
|
||||||
// @Accessor("shutdownThread")
|
|
||||||
// Thread shutdownThread();
|
|
||||||
//
|
|
||||||
// @Accessor("")
|
|
||||||
//}
|
|
||||||
@@ -1,13 +0,0 @@
|
|||||||
package net.gensokyoreimagined.nitori.mixin.virtual_thread.accessors;
|
|
||||||
|
|
||||||
import org.spigotmc.WatchdogThread;
|
|
||||||
import org.spongepowered.asm.mixin.Mixin;
|
|
||||||
import org.spongepowered.asm.mixin.gen.Accessor;
|
|
||||||
|
|
||||||
@Mixin(WatchdogThread.class)
|
|
||||||
public interface MixinWatchdogThread {
|
|
||||||
@Accessor("instance")
|
|
||||||
static WatchdogThread getInstance() {
|
|
||||||
throw new AssertionError("MixinWatchdogThread was not transformed!");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -7,17 +7,14 @@
|
|||||||
"compatibilityLevel": "JAVA_17",
|
"compatibilityLevel": "JAVA_17",
|
||||||
"server": [
|
"server": [
|
||||||
"MixinBlockPos",
|
"MixinBlockPos",
|
||||||
"MixinChunkEntitySlices",
|
"save.MixinCraftPlayer",
|
||||||
"MixinCraftPlayer",
|
|
||||||
"MixinEntity",
|
"MixinEntity",
|
||||||
"MixinEntitySectionStorage",
|
"MixinEntitySectionStorage",
|
||||||
"MixinIteratorSafeOrderedReferenceSet",
|
"save.MixinLevelStorageAccess",
|
||||||
"MixinLevelStorageAccess",
|
|
||||||
"MixinNoiseBasedChunkGenerator",
|
"MixinNoiseBasedChunkGenerator",
|
||||||
"MixinPlayer",
|
"logic.stats.FasterStatsMixin",
|
||||||
"MixinPlayerList",
|
"save.AsyncPlayerSaveMixin",
|
||||||
"MixinReobfServer",
|
"MixinReobfServer",
|
||||||
"MixinServerBossEvent",
|
|
||||||
"alloc.blockstate.StateMixin",
|
"alloc.blockstate.StateMixin",
|
||||||
"alloc.composter.ComposterMixin$ComposterBlockComposterInventoryMixin",
|
"alloc.composter.ComposterMixin$ComposterBlockComposterInventoryMixin",
|
||||||
"alloc.composter.ComposterMixin$ComposterBlockDummyInventoryMixin",
|
"alloc.composter.ComposterMixin$ComposterBlockDummyInventoryMixin",
|
||||||
|
|||||||
Reference in New Issue
Block a user