From 1b07a5eff7b607f0b3e7bfee0de6e6545f6c6492 Mon Sep 17 00:00:00 2001 From: aromaa Date: Wed, 6 Nov 2024 23:54:41 +0200 Subject: [PATCH] Adjust PhaseTracker to support multithreaded levels --- .../common/block/SpongeBlockSnapshot.java | 2 +- .../network/chat/SpongeChatDecorator.java | 2 +- .../GenericMutableDataProviderBase.java | 3 +- .../inventory/InventoryEventFactory.java | 13 +- .../common/event/tracking/PhaseContext.java | 9 +- .../common/event/tracking/PhaseTracker.java | 55 +++++++-- .../event/tracking/PooledPhaseState.java | 8 +- .../common/event/tracking/TrackingUtil.java | 48 ++++---- .../phase/packet/PacketPhaseUtil.java | 8 +- .../common/hooks/GeneralHooks.java | 3 +- .../common/scheduler/ServerScheduler.java | 2 +- .../archetype/SpongeArchetypeVolume.java | 3 +- .../world/entity/EntityMixin_API.java | 3 +- .../world/level/LevelAccessorMixin_API.java | 2 +- .../mixin/core/client/MinecraftMixin.java | 2 +- .../core/server/MinecraftServerMixin.java | 2 +- .../core/server/level/ServerLevelMixin.java | 7 +- .../core/server/level/ServerPlayerMixin.java | 9 +- .../core/server/players/PlayerListMixin.java | 7 +- .../mixin/core/world/entity/EntityMixin.java | 14 ++- .../core/world/entity/LivingEntityMixin.java | 9 +- .../entity/LivingEntityMixin_Attack_Impl.java | 2 +- .../entity/decoration/ArmorStandMixin.java | 2 +- .../world/entity/item/ItemEntityMixin.java | 2 +- .../player/PlayerMixin_Attack_Impl.java | 2 +- .../projectile/ProjectileUtilMixin.java | 3 +- .../PersistentEntitySectionManagerMixin.java | 3 +- .../ServerPlayerMixin_Inventory_API.java | 2 +- .../level/ServerPlayerMixin_Inventory.java | 20 ++-- .../ServerPlayerMixin_Shared_Inventory.java | 13 +- ...GamePacketListenerImplMixin_Inventory.java | 16 +-- .../AbstractContainerMenuMixin_Inventory.java | 22 ++-- .../inventory/AnvilMenuMixin_Inventory.java | 2 +- .../CraftingMenuMixin_Inventory.java | 2 +- .../inventory/ResultSlotMixin_Inventory.java | 2 +- .../world/inventory/SlotMixin_Inventory.java | 5 +- .../HopperBlockEntityMixin_Inventory.java | 4 +- .../server/MinecraftServerMixin_Tracker.java | 10 +- .../server/level/ChunkMapMixin_Tracker.java | 7 +- .../level/ChunkStatusTasksMixin_Tracker.java | 14 ++- .../level/ServerChunkCacheMixin_Tracker.java | 4 +- .../level/ServerLevelMixin_Tracker.java | 41 ++++--- .../ServerPlayerGameModeMixin_Tracker.java | 8 +- ...erGamePacketListenerImplMixin_Tracker.java | 2 +- .../players/PlayerListMixin_Tracker.java | 6 +- .../world/entity/EntityMixin_Tracker.java | 12 +- .../entity/LivingEntityMixin_Tracker.java | 15 +-- .../world/item/BoneMealItemMixin_Tracker.java | 5 +- .../world/item/ItemStackMixin_Tracker.java | 3 +- .../world/level/block/BlockMixin_Tracker.java | 111 +++++++++++++----- .../block/DispenserBlockMixin_Tracker.java | 2 +- .../level/block/LeavesBlockMixin_Tracker.java | 2 +- .../block/SaplingBlockMixin_Tracker.java | 7 +- .../level/chunk/LevelChunkMixin_Tracker.java | 12 +- .../end/EndDragonFightMixin_Tracker.java | 9 +- .../NeighborUpdaterMixin_Tracker.java | 2 +- .../world/ticks/LevelTicksMixin_Tracker.java | 2 +- .../level/ServerPlayerMixin_Vanilla.java | 8 +- ...erGamePacketListenerImplMixin_Vanilla.java | 2 +- ...erPlayerGameModeMixin_Vanilla_Tracker.java | 3 +- 60 files changed, 379 insertions(+), 221 deletions(-) diff --git a/src/main/java/org/spongepowered/common/block/SpongeBlockSnapshot.java b/src/main/java/org/spongepowered/common/block/SpongeBlockSnapshot.java index 5fd5dee4143..b508e0bab40 100644 --- a/src/main/java/org/spongepowered/common/block/SpongeBlockSnapshot.java +++ b/src/main/java/org/spongepowered/common/block/SpongeBlockSnapshot.java @@ -177,7 +177,7 @@ public boolean restore(final boolean force, final BlockChangeFlag flag) { final ServerLevel world = optionalWorld.get(); // We need to deterministically define the context as nullable if we don't need to enter. // this way we guarantee an exit. - try (final PhaseContext context = BlockPhase.State.RESTORING_BLOCKS.createPhaseContext(PhaseTracker.SERVER)) { + try (final PhaseContext context = BlockPhase.State.RESTORING_BLOCKS.createPhaseContext(PhaseTracker.getWorldInstance(world))) { context.buildAndSwitch(); final BlockPos pos = VecHelper.toBlockPos(this.pos); if (!world.isInWorldBounds(pos)) { // Invalid position. Inline this check diff --git a/src/main/java/org/spongepowered/common/bridge/network/chat/SpongeChatDecorator.java b/src/main/java/org/spongepowered/common/bridge/network/chat/SpongeChatDecorator.java index 4fc27bc7dfe..ead45659749 100644 --- a/src/main/java/org/spongepowered/common/bridge/network/chat/SpongeChatDecorator.java +++ b/src/main/java/org/spongepowered/common/bridge/network/chat/SpongeChatDecorator.java @@ -42,7 +42,7 @@ public class SpongeChatDecorator implements ChatDecorator { @Override public Component decorate(@Nullable final ServerPlayer player, final Component message) { - try (final CauseStackManager.StackFrame frame = PhaseTracker.SERVER.pushCauseFrame()) { + try (final CauseStackManager.StackFrame frame = PhaseTracker.getServerInstanceExplicitly().pushCauseFrame()) { if (player != null) { frame.pushCause(player); } diff --git a/src/main/java/org/spongepowered/common/data/provider/GenericMutableDataProviderBase.java b/src/main/java/org/spongepowered/common/data/provider/GenericMutableDataProviderBase.java index e6b66c94410..0056806ef64 100644 --- a/src/main/java/org/spongepowered/common/data/provider/GenericMutableDataProviderBase.java +++ b/src/main/java/org/spongepowered/common/data/provider/GenericMutableDataProviderBase.java @@ -25,6 +25,7 @@ package org.spongepowered.common.data.provider; import io.leangen.geantyref.GenericTypeReflector; +import net.minecraft.server.level.ServerLevel; import net.minecraft.world.level.entity.EntityInLevelCallback; import org.spongepowered.api.data.DataHolder; import org.spongepowered.api.data.DataTransactionResult; @@ -260,7 +261,7 @@ private Optional> callReplacementEvent( .result(DataTransactionResult.Type.SUCCESS); originalValue.ifPresent(transaction::replace); final ChangeDataHolderEvent.ValueChange valueChange = SpongeEventFactory.createChangeDataHolderEventValueChange( - PhaseTracker.SERVER.currentCause(), + PhaseTracker.getWorldInstance((ServerLevel) entity.world()).currentCause(), transaction.build(), dataHolder); if (SpongeCommon.post(valueChange)) { diff --git a/src/main/java/org/spongepowered/common/event/inventory/InventoryEventFactory.java b/src/main/java/org/spongepowered/common/event/inventory/InventoryEventFactory.java index 8bbf9b9fd43..0abee380cbd 100644 --- a/src/main/java/org/spongepowered/common/event/inventory/InventoryEventFactory.java +++ b/src/main/java/org/spongepowered/common/event/inventory/InventoryEventFactory.java @@ -25,6 +25,7 @@ package org.spongepowered.common.event.inventory; import net.kyori.adventure.text.Component; +import net.minecraft.server.level.ServerLevel; import net.minecraft.server.level.ServerPlayer; import net.minecraft.world.Container; import net.minecraft.world.MenuProvider; @@ -91,9 +92,10 @@ public class InventoryEventFactory { public static boolean callPlayerInventoryPickupEvent(final Player player, final ItemEntity itemToPickup) { final ItemStack stack = itemToPickup.getItem(); final ItemStackSnapshot snapshot = ItemStackUtil.snapshotOf(stack); + final PhaseTracker phaseTracker = PhaseTracker.getWorldInstance((ServerLevel) player.level()); final ChangeInventoryEvent.Pickup.Pre event = SpongeEventFactory.createChangeInventoryEventPickupPre( - PhaseTracker.getCauseStackManager().currentCause(), + phaseTracker.currentCause(), Optional.empty(), Collections.singletonList(snapshot), ((Inventory) player.containerMenu), (Item) itemToPickup, snapshot); SpongeCommon.post(event); if (event.isCancelled()) { @@ -106,7 +108,7 @@ public static boolean callPlayerInventoryPickupEvent(final Player player, final return true; } - final PhaseContext<@NonNull ?> context = PhaseTracker.SERVER.getPhaseContext(); + final PhaseContext<@NonNull ?> context = phaseTracker.getPhaseContext(); final TransactionalCaptureSupplier transactor = context.getTransactor(); try (final EffectTransactor ignored = transactor.logPlayerInventoryChangeWithEffect(player, PlayerInventoryTransaction.EventCreator.PICKUP)) { for (final ItemStackSnapshot item : list) { @@ -126,7 +128,7 @@ public static boolean callPlayerInventoryPickupEvent(final Player player, final stack.setCount(0); return true; } else { - final PhaseContext<@NonNull ?> context = PhaseTracker.SERVER.getPhaseContext(); + final PhaseContext<@NonNull ?> context = phaseTracker.getPhaseContext(); final TransactionalCaptureSupplier transactor = context.getTransactor(); final boolean added; try (final EffectTransactor ignored = transactor.logPlayerInventoryChangeWithEffect(player, PlayerInventoryTransaction.EventCreator.PICKUP)) { @@ -141,7 +143,8 @@ public static boolean callPlayerInventoryPickupEvent(final Player player, final } public static ItemStack callHopperInventoryPickupEvent(final Container inventory, final ItemEntity item, final ItemStack stack) { - try (final CauseStackManager.StackFrame frame = PhaseTracker.getCauseStackManager().pushCauseFrame()) { + final PhaseTracker phaseTracker = PhaseTracker.getWorldInstance((ServerLevel) item.level()); + try (final CauseStackManager.StackFrame frame = phaseTracker.pushCauseFrame()) { frame.pushCause(inventory); final ItemStackSnapshot snapshot = ItemStackUtil.snapshotOf(stack); @@ -227,7 +230,7 @@ public static boolean callInteractContainerOpenEvent(final ServerPlayer player) final ItemStackSnapshot newCursor = ItemStackUtil.snapshotOf(player.containerMenu.getCarried()); final Transaction cursorTransaction = new Transaction<>(ItemStackSnapshot.empty(), newCursor); final InteractContainerEvent.Open event = - SpongeEventFactory.createInteractContainerEventOpen(PhaseTracker.getCauseStackManager().currentCause(), + SpongeEventFactory.createInteractContainerEventOpen(PhaseTracker.getWorldInstance(player.serverLevel()).currentCause(), (org.spongepowered.api.item.inventory.Container) player.containerMenu, cursorTransaction); SpongeCommon.post(event); if (event.isCancelled()) { diff --git a/src/main/java/org/spongepowered/common/event/tracking/PhaseContext.java b/src/main/java/org/spongepowered/common/event/tracking/PhaseContext.java index 02aa5b19a3a..e655e457281 100644 --- a/src/main/java/org/spongepowered/common/event/tracking/PhaseContext.java +++ b/src/main/java/org/spongepowered/common/event/tracking/PhaseContext.java @@ -160,7 +160,7 @@ public P buildAndSwitch() { if (SpongeConfigs.getCommon().get().phaseTracker.generateStackTracePerPhase) { this.stackTrace = new Exception("Debug Trace").getStackTrace(); } - PhaseTracker.getInstance().switchToPhase(this.state, this); + this.createdTracker.switchToPhase(this.state, this); return (P) this; } @@ -321,16 +321,15 @@ public void close() { // Should never throw an exception this.state, this, new IllegalStateException("Closing empty phase context")); return; } - final PhaseTracker instance = PhaseTracker.getInstance(); - instance.completePhase(this); + this.createdTracker.completePhase(this); if (this.usedFrame != null) { - this.usedFrame.iterator().forEachRemaining(instance::popCauseFrame); + this.usedFrame.iterator().forEachRemaining(this.createdTracker::popCauseFrame); this.usedFrame = null; } else if (this.shouldProvideModifiers()) { // So, this part is interesting... Since the used frame is null, that means // the cause stack manager still has the reference of this context/phase, we have // to "pop off" the list. - instance.popFrameMutator(this); + this.createdTracker.popFrameMutator(this); } this.reset(); this.isCompleted = false; diff --git a/src/main/java/org/spongepowered/common/event/tracking/PhaseTracker.java b/src/main/java/org/spongepowered/common/event/tracking/PhaseTracker.java index b5258e55a14..383dc92de14 100644 --- a/src/main/java/org/spongepowered/common/event/tracking/PhaseTracker.java +++ b/src/main/java/org/spongepowered/common/event/tracking/PhaseTracker.java @@ -32,6 +32,7 @@ import net.minecraft.resources.ResourceLocation; import net.minecraft.server.level.ServerLevel; import net.minecraft.world.entity.Entity; +import net.minecraft.world.level.LevelAccessor; import net.minecraft.world.level.block.Block; import net.minecraft.world.level.block.entity.BlockEntity; import net.minecraft.world.level.block.entity.BlockEntityType; @@ -88,7 +89,7 @@ public final class PhaseTracker implements CauseStackManager { public static final PhaseTracker CLIENT = new PhaseTracker(); - public static final PhaseTracker SERVER = new PhaseTracker(); + private static final PhaseTracker SERVER = new PhaseTracker(); public static final Logger LOGGER = LogManager.getLogger(PhaseTracker.class); static final CopyOnWriteArrayList ASYNC_CAPTURED_ENTITIES = new CopyOnWriteArrayList<>(); private static final Map SPINOFF_TRACKERS = new MapMaker().weakKeys().concurrencyLevel(8).makeMap(); @@ -118,6 +119,44 @@ public static PhaseTracker getInstance() { }); } + /** + * The server phase tracker should be used for actions + * that are not tied to any specific {@link ServerLevel}. + * + *

For actions that are specific to a {@link ServerLevel}, + * the {@link #getWorldInstance(ServerLevel)} should be + * preferred.

+ * + *

For actions that could be performed inside a world + * generation thread, the {@link #getWorldInstance(LevelAccessor)} + * should be used instead.

+ * + *

If the current world instance is unknown, the + * implementation can perform more expensive lookup + * using the parameterless {@link #getWorldInstance}.

+ */ + public static PhaseTracker getServerInstanceExplicitly() { + return PhaseTracker.SERVER; + } + + public static PhaseTracker getWorldInstance() { + //This is reserved for a mod that wishes to implement + //multithreaded levels. + return PhaseTracker.SERVER; + } + + public static PhaseTracker getWorldInstance(final LevelAccessor level) { + //This is reserved for a mod that wishes to implement + //multithreaded levels. + return PhaseTracker.SERVER; + } + + public static PhaseTracker getWorldInstance(final ServerLevel level) { + //This is reserved for a mod that wishes to implement + //multithreaded levels. + return PhaseTracker.SERVER; + } + public static CauseStackManager getCauseStackManager() { return PhaseTracker.getInstance(); } @@ -231,7 +270,7 @@ public static Block validateBlockForNeighborNotification(final ServerLevel world } public void init() { - if (this != PhaseTracker.SERVER) { + if (this == PhaseTracker.CLIENT) { return; } if (this.hasRun) { @@ -302,14 +341,14 @@ public boolean onSidedThread() { // ----------------- SIMPLE GETTERS -------------------------------------- public IPhaseState getCurrentState() { - if (Thread.currentThread() != this.getSidedThread()) { + if (!this.onSidedThread()) { throw new UnsupportedOperationException("Cannot access the PhaseTracker off-thread, please use the respective PhaseTracker for their proper thread."); } return this.stack.peekState(); } public PhaseContext getPhaseContext() { - if (Thread.currentThread() != this.getSidedThread()) { + if (!this.onSidedThread()) { throw new UnsupportedOperationException("Cannot access the PhaseTracker off-thread, please use the respective PhaseTracker for their proper thread."); } return this.stack.peekContext(); @@ -322,7 +361,7 @@ public PhaseContext getPhaseContext() { // ----------------- STATE ACCESS ---------------------------------- void switchToPhase(final IPhaseState state, final PhaseContext phaseContext) { - if (phaseContext.createdTracker != this && Thread.currentThread() != this.getSidedThread()) { + if (phaseContext.createdTracker != this && !this.onSidedThread()) { // lol no, report the block change properly new PrettyPrinter(60).add("Illegal Async PhaseTracker Access").centre().hr() .addWrapped(PhasePrinter.ASYNC_TRACKER_ACCESS) @@ -335,7 +374,7 @@ void switchToPhase(final IPhaseState state, final PhaseContext phaseContex Objects.requireNonNull(state, "State cannot be null!"); Objects.requireNonNull(phaseContext, "PhaseContext cannot be null!"); Preconditions.checkArgument(phaseContext.isComplete(), "PhaseContext must be complete!"); - if (this == PhaseTracker.SERVER && SpongeConfigs.getCommon().get().phaseTracker.verbose) { + if (this != PhaseTracker.CLIENT && SpongeConfigs.getCommon().get().phaseTracker.verbose) { if (this.stack.size() > 6) { if (this.stack.checkForRunaways(state, phaseContext)) { PhasePrinter.printRunawayPhase(this.stack, state, phaseContext); @@ -352,7 +391,7 @@ void switchToPhase(final IPhaseState state, final PhaseContext phaseContex @SuppressWarnings({"rawtypes", "unused", "try"}) void completePhase(final PhaseContext context) { - if (context.createdTracker != this && Thread.currentThread() != this.getSidedThread()) { + if (context.createdTracker != this && !this.onSidedThread()) { // lol no, report the block change properly new PrettyPrinter(60).add("Illegal Async PhaseTracker Access").centre().hr() .addWrapped(PhasePrinter.ASYNC_TRACKER_ACCESS) @@ -741,7 +780,7 @@ public Optional removeContext(final EventContextKey key) { private void enforceMainThread() { // On clients, this may not be available immediately, we can't bomb out that early. - if (Thread.currentThread() != this.getSidedThread()) { + if (!this.onSidedThread()) { throw new IllegalStateException(String.format( "CauseStackManager called from off main thread (current='%s', expected='%s')!", ThreadUtil.getDescription(Thread.currentThread()), diff --git a/src/main/java/org/spongepowered/common/event/tracking/PooledPhaseState.java b/src/main/java/org/spongepowered/common/event/tracking/PooledPhaseState.java index 24e8ddce470..59b1ecb2a87 100644 --- a/src/main/java/org/spongepowered/common/event/tracking/PooledPhaseState.java +++ b/src/main/java/org/spongepowered/common/event/tracking/PooledPhaseState.java @@ -38,11 +38,11 @@ protected PooledPhaseState() { @Override public final C createPhaseContext(final PhaseTracker tracker) { - if (Thread.currentThread() != tracker.getSidedThread()) { + if (!tracker.onSidedThread()) { throw new IllegalStateException("Asynchronous Thread Access to PhaseTracker: " + tracker); } - if (tracker == PhaseTracker.SERVER) { + if (tracker == PhaseTracker.getServerInstanceExplicitly()) { if (this.serverCached != null) { final C cached = this.serverCached; this.serverCached = null; @@ -64,10 +64,10 @@ public final C createPhaseContext(final PhaseTracker tracker) { final void releaseContextFromPool(final C context) { final PhaseTracker createdTracker = context.createdTracker; - if (Thread.currentThread() != createdTracker.getSidedThread()) { + if (!createdTracker.onSidedThread()) { throw new IllegalStateException("Asynchronous Thread Access to PhaseTracker: " + createdTracker); } - if (createdTracker == PhaseTracker.SERVER) { + if (createdTracker == PhaseTracker.getServerInstanceExplicitly()) { if (this.serverCached == null) { this.serverCached = context; return; diff --git a/src/main/java/org/spongepowered/common/event/tracking/TrackingUtil.java b/src/main/java/org/spongepowered/common/event/tracking/TrackingUtil.java index 67a35d5fa35..f240e990292 100644 --- a/src/main/java/org/spongepowered/common/event/tracking/TrackingUtil.java +++ b/src/main/java/org/spongepowered/common/event/tracking/TrackingUtil.java @@ -110,7 +110,8 @@ public static void tickEntity(final Consumer return; } - final EntityTickContext tickContext = TickPhase.Tick.ENTITY.createPhaseContext(PhaseTracker.SERVER).source(entity); + final PhaseTracker phaseTracker = PhaseTracker.getWorldInstance((ServerLevel) entity.level()); + final EntityTickContext tickContext = TickPhase.Tick.ENTITY.createPhaseContext(phaseTracker).source(entity); try (final EntityTickContext context = tickContext) { if (entity instanceof CreatorTrackedBridge) { ((CreatorTrackedBridge) entity).tracker$getNotifierUUID().ifPresent(context::notifier); @@ -126,7 +127,7 @@ public static void tickEntity(final Consumer SpongeCommonEventFactory.callNaturalRotateEntityEvent(entity); } } catch (final Exception e) { - PhasePrinter.printExceptionFromPhase(PhaseTracker.getInstance().stack, e, tickContext); + PhasePrinter.printExceptionFromPhase(phaseTracker.stack, e, tickContext); } } @@ -163,7 +164,8 @@ public static void tickTileEntity(final TrackedWorldBridge mixinWorldServer, fin ((ActiveChunkReferantBridge) blockEntity).bridge$setActiveChunk((TrackedLevelChunkBridge) blockEntity.getLevel().getChunkAt(blockEntity.getBlockPos())); } - final TileEntityTickContext context = TickPhase.Tick.TILE_ENTITY.createPhaseContext(PhaseTracker.SERVER).source(mixinTileEntity); + final PhaseTracker phaseTracker = PhaseTracker.getWorldInstance((ServerLevel) blockEntity.getLevel()); + final TileEntityTickContext context = TickPhase.Tick.TILE_ENTITY.createPhaseContext(phaseTracker).source(mixinTileEntity); try (final PhaseContext<@NonNull ?> phaseContext = context) { if (blockEntity instanceof CreatorTrackedBridge) { @@ -191,7 +193,7 @@ public static void tickTileEntity(final TrackedWorldBridge mixinWorldServer, fin } } catch (final Exception e) { - PhasePrinter.printExceptionFromPhase(PhaseTracker.getInstance().stack, e, context); + PhasePrinter.printExceptionFromPhase(phaseTracker.stack, e, context); } // We delay clearing active chunk if TE is invalidated during tick so we must remove it after if (blockEntity.isRemoved()) { @@ -204,10 +206,11 @@ public static void updateTickBlock( final TrackedWorldBridge mixinWorld, final net.minecraft.world.level.block.state.BlockState block, final BlockPos pos, final RandomSource random) { final ServerLevel world = (ServerLevel) mixinWorld; final org.spongepowered.api.world.server.ServerWorld apiWorld = (org.spongepowered.api.world.server.ServerWorld) world; + final PhaseTracker phaseTracker = PhaseTracker.getWorldInstance(world); if (ShouldFire.TICK_BLOCK_EVENT) { final BlockSnapshot snapshot = mixinWorld.bridge$createSnapshot(block, pos, BlockChangeFlags.NONE); - final TickBlockEvent event = SpongeEventFactory.createTickBlockEventScheduled(PhaseTracker.getCauseStackManager().currentCause(), snapshot); + final TickBlockEvent event = SpongeEventFactory.createTickBlockEventScheduled(phaseTracker.currentCause(), snapshot); SpongeCommon.post(event); if (event.isCancelled()) { return; @@ -215,10 +218,10 @@ public static void updateTickBlock( } final LocatableBlock locatable = new SpongeLocatableBlockBuilder().world(apiWorld).position(pos.getX(), pos.getY(), pos.getZ()).state((BlockState)block).build(); - final BlockTickContext phaseContext = TickPhase.Tick.BLOCK.createPhaseContext(PhaseTracker.SERVER).source(locatable); + final BlockTickContext phaseContext = TickPhase.Tick.BLOCK.createPhaseContext(phaseTracker).source(locatable); // We have to associate any notifiers in case of scheduled block updates from other sources - final PhaseContext<@NonNull ?> currentContext = PhaseTracker.getInstance().getPhaseContext(); + final PhaseContext<@NonNull ?> currentContext = phaseTracker.getPhaseContext(); currentContext.appendNotifierPreBlockTick(world, pos, phaseContext); // Now actually switch to the new phase @@ -227,7 +230,7 @@ public static void updateTickBlock( PhaseTracker.LOGGER.trace(TrackingUtil.BLOCK_TICK, () -> "Wrapping Block Tick: " + block.toString()); block.tick(world, pos, random); } catch (final Exception | NoClassDefFoundError e) { - PhasePrinter.printExceptionFromPhase(PhaseTracker.getInstance().stack, e, phaseContext); + PhasePrinter.printExceptionFromPhase(phaseTracker.stack, e, phaseContext); } } @@ -236,10 +239,11 @@ public static void updateTickFluid( final TrackedWorldBridge mixinWorld, final FluidState fluidState, final BlockPos pos, final net.minecraft.world.level.block.state.BlockState blockState) { final ServerLevel world = (ServerLevel) mixinWorld; final org.spongepowered.api.world.server.ServerWorld apiWorld = (org.spongepowered.api.world.server.ServerWorld) world; + final PhaseTracker phaseTracker = PhaseTracker.getWorldInstance(world); if (ShouldFire.TICK_BLOCK_EVENT) { final BlockSnapshot snapshot = mixinWorld.bridge$createSnapshot(blockState, pos, BlockChangeFlags.NONE); - final TickBlockEvent event = SpongeEventFactory.createTickBlockEventScheduled(PhaseTracker.getCauseStackManager().currentCause(), snapshot); + final TickBlockEvent event = SpongeEventFactory.createTickBlockEventScheduled(phaseTracker.currentCause(), snapshot); SpongeCommon.post(event); if (event.isCancelled()) { return; @@ -247,12 +251,12 @@ public static void updateTickFluid( } final LocatableBlock locatable = new SpongeLocatableBlockBuilder().world(apiWorld).position(pos.getX(), pos.getY(), pos.getZ()).state((BlockState) blockState).build(); - final FluidTickContext phaseContext = TickPhase.Tick.FLUID.createPhaseContext(PhaseTracker.SERVER) + final FluidTickContext phaseContext = TickPhase.Tick.FLUID.createPhaseContext(phaseTracker) .source(locatable) .fluid(fluidState); // We have to associate any notifiers in case of scheduled block updates from other sources - final PhaseContext<@NonNull ?> currentContext = PhaseTracker.getInstance().getPhaseContext(); + final PhaseContext<@NonNull ?> currentContext = phaseTracker.getPhaseContext(); currentContext.appendNotifierPreBlockTick(world, pos, phaseContext); // Now actually switch to the new phase @@ -261,7 +265,7 @@ public static void updateTickFluid( PhaseTracker.LOGGER.trace(TrackingUtil.FLUID_TICK, () -> "Wrapping Fluid Tick: " + fluidState.toString()); fluidState.tick(world, pos, blockState); } catch (final Exception | NoClassDefFoundError e) { - PhasePrinter.printExceptionFromPhase(PhaseTracker.getInstance().stack, e, phaseContext); + PhasePrinter.printExceptionFromPhase(phaseTracker.stack, e, phaseContext); } } @@ -271,12 +275,13 @@ public static void randomTickBlock(final TrackedWorldBridge mixinWorld, final net.minecraft.world.level.block.state.BlockState state, final BlockPos pos, final RandomSource random) { final ServerLevel world = (ServerLevel) mixinWorld; final org.spongepowered.api.world.server.ServerWorld apiWorld = (org.spongepowered.api.world.server.ServerWorld) world; + final PhaseTracker phaseTracker = PhaseTracker.getWorldInstance(world); if (ShouldFire.TICK_BLOCK_EVENT) { final BlockSnapshot currentTickBlock = mixinWorld.bridge$createSnapshot(state, pos, BlockChangeFlags.NONE); final TickBlockEvent event = - SpongeEventFactory.createTickBlockEventRandom(PhaseTracker.getCauseStackManager().currentCause(), currentTickBlock); + SpongeEventFactory.createTickBlockEventRandom(phaseTracker.currentCause(), currentTickBlock); SpongeCommon.post(event); if (event.isCancelled()) { return; @@ -288,10 +293,10 @@ public static void randomTickBlock(final TrackedWorldBridge mixinWorld, .position(pos.getX(), pos.getY(), pos.getZ()) .state((BlockState) state) .build(); - final BlockTickContext phaseContext = TickPhase.Tick.RANDOM_BLOCK.createPhaseContext(PhaseTracker.SERVER).source(locatable); + final BlockTickContext phaseContext = TickPhase.Tick.RANDOM_BLOCK.createPhaseContext(phaseTracker).source(locatable); // We have to associate any notifiers in case of scheduled block updates from other sources - final PhaseContext<@NonNull ?> currentContext = PhaseTracker.getInstance().getPhaseContext(); + final PhaseContext<@NonNull ?> currentContext = phaseTracker.getPhaseContext(); currentContext.appendNotifierPreBlockTick(world, pos, phaseContext); // Now actually switch to the new phase try (final PhaseContext<@NonNull ?> context = phaseContext) { @@ -299,7 +304,7 @@ public static void randomTickBlock(final TrackedWorldBridge mixinWorld, PhaseTracker.LOGGER.trace(TrackingUtil.BLOCK_TICK, "Wrapping Random Block Tick: {}", state); state.randomTick(world, pos, random); } catch (final Exception | NoClassDefFoundError e) { - PhasePrinter.printExceptionFromPhase(PhaseTracker.getInstance().stack, e, phaseContext); + PhasePrinter.printExceptionFromPhase(phaseTracker.stack, e, phaseContext); } } @SuppressWarnings("rawtypes") @@ -307,12 +312,13 @@ public static void randomTickFluid(final TrackedWorldBridge mixinWorld, final FluidState state, final BlockPos pos, final RandomSource random) { final ServerLevel world = (ServerLevel) mixinWorld; final org.spongepowered.api.world.server.ServerWorld apiWorld = (org.spongepowered.api.world.server.ServerWorld) world; + final PhaseTracker phaseTracker = PhaseTracker.getWorldInstance(world); if (ShouldFire.TICK_BLOCK_EVENT) { final BlockSnapshot currentTickBlock = mixinWorld.bridge$createSnapshot(state.createLegacyBlock(), pos, BlockChangeFlags.NONE); final TickBlockEvent event = - SpongeEventFactory.createTickBlockEventRandom(PhaseTracker.getCauseStackManager().currentCause(), currentTickBlock); + SpongeEventFactory.createTickBlockEventRandom(phaseTracker.currentCause(), currentTickBlock); SpongeCommon.post(event); if (event.isCancelled()) { return; @@ -324,13 +330,13 @@ public static void randomTickFluid(final TrackedWorldBridge mixinWorld, .position(pos.getX(), pos.getY(), pos.getZ()) .state((BlockState) state.createLegacyBlock()) .build(); - final FluidTickContext phaseContext = TickPhase.Tick.RANDOM_FLUID.createPhaseContext(PhaseTracker.SERVER) + final FluidTickContext phaseContext = TickPhase.Tick.RANDOM_FLUID.createPhaseContext(phaseTracker) .source(locatable) .fluid(state); // We have to associate any notifiers in case of scheduled block updates from other sources - final PhaseContext<@NonNull ?> currentContext = PhaseTracker.getInstance().getPhaseContext(); + final PhaseContext<@NonNull ?> currentContext = phaseTracker.getPhaseContext(); currentContext.appendNotifierPreBlockTick(world, pos, phaseContext); // Now actually switch to the new phase try (final PhaseContext<@NonNull ?> context = phaseContext) { @@ -338,7 +344,7 @@ public static void randomTickFluid(final TrackedWorldBridge mixinWorld, PhaseTracker.LOGGER.trace(TrackingUtil.FLUID_TICK, () -> "Wrapping Random Fluid Tick: " + state.toString()); state.randomTick(world, pos, random); } catch (final Exception | NoClassDefFoundError e) { - PhasePrinter.printExceptionFromPhase(PhaseTracker.getInstance().stack, e, phaseContext); + PhasePrinter.printExceptionFromPhase(phaseTracker.stack, e, phaseContext); } } @@ -351,7 +357,7 @@ public static boolean fireMinecraftBlockEvent(final ServerLevel worldIn, final B // No source present which means we are ignoring the phase state return currentState.triggerEvent(worldIn, event.pos(), event.paramA(), event.paramB()); } - final BlockEventTickContext phaseContext = TickPhase.Tick.BLOCK_EVENT.createPhaseContext(PhaseTracker.SERVER); + final BlockEventTickContext phaseContext = TickPhase.Tick.BLOCK_EVENT.createPhaseContext(PhaseTracker.getWorldInstance(worldIn)); phaseContext.source(source); final UUID user = ((TrackableBlockEventDataBridge) (Object) event).bridge$getSourceUserUUID(); diff --git a/src/main/java/org/spongepowered/common/event/tracking/phase/packet/PacketPhaseUtil.java b/src/main/java/org/spongepowered/common/event/tracking/phase/packet/PacketPhaseUtil.java index 7e2013123b9..4b398bf6b44 100644 --- a/src/main/java/org/spongepowered/common/event/tracking/phase/packet/PacketPhaseUtil.java +++ b/src/main/java/org/spongepowered/common/event/tracking/phase/packet/PacketPhaseUtil.java @@ -32,6 +32,7 @@ import net.minecraft.network.protocol.game.ClientboundContainerSetSlotPacket; import net.minecraft.network.protocol.game.ServerboundMovePlayerPacket; import net.minecraft.network.syncher.EntityDataAccessor; +import net.minecraft.server.level.ServerLevel; import net.minecraft.server.network.ServerGamePacketListenerImpl; import net.minecraft.world.InteractionHand; import net.minecraft.world.entity.Entity; @@ -82,7 +83,10 @@ public final class PacketPhaseUtil { @SuppressWarnings("removal") public static void handleSlotRestore(@Nullable final Player player, final @Nullable AbstractContainerMenu containerMenu, final List slotTransactions, final boolean eventCancelled) { - try (PhaseContext<@NonNull ?> ignored = BlockPhase.State.RESTORING_BLOCKS.createPhaseContext(PhaseTracker.SERVER).buildAndSwitch()) { + final PhaseTracker phaseTracker = player != null + ? PhaseTracker.getWorldInstance((ServerLevel) player.level()) + : PhaseTracker.getWorldInstance(); + try (PhaseContext<@NonNull ?> ignored = BlockPhase.State.RESTORING_BLOCKS.createPhaseContext(phaseTracker).buildAndSwitch()) { boolean restoredAny = false; for (final SlotTransaction slotTransaction : slotTransactions) { @@ -252,7 +256,7 @@ public static void onProcessPacket(final Packet packetIn, final PacketListener n } else { final IPhaseState> packetState = PacketPhase.getInstance().getStateForPacket(packetIn); // At the very least make an unknown packet state case. - final PacketContext context = packetState.createPhaseContext(PhaseTracker.SERVER); + final PacketContext context = packetState.createPhaseContext(PhaseTracker.getWorldInstance(packetPlayer.serverLevel())); context.source(packetPlayer) .packetPlayer(packetPlayer) .packet(packetIn); diff --git a/src/main/java/org/spongepowered/common/hooks/GeneralHooks.java b/src/main/java/org/spongepowered/common/hooks/GeneralHooks.java index f0d91d4c46b..1932195b812 100644 --- a/src/main/java/org/spongepowered/common/hooks/GeneralHooks.java +++ b/src/main/java/org/spongepowered/common/hooks/GeneralHooks.java @@ -27,6 +27,7 @@ import net.minecraft.network.chat.Component; import net.minecraft.network.protocol.status.ServerStatus; import org.spongepowered.api.Sponge; +import org.spongepowered.common.event.tracking.PhaseTracker; import java.util.Optional; @@ -36,7 +37,7 @@ default boolean onServerThread() { // Return true when the server isn't yet initialized, this means on a client // that the game is still being loaded. This is needed to support initialization // events with cause tracking. - return !Sponge.isServerAvailable() || Sponge.server().onMainThread(); + return !Sponge.isServerAvailable() || PhaseTracker.getWorldInstance().onSidedThread(); } default ServerStatus createServerStatus(ServerStatus originalStatus, Component description, Optional players, Optional version, Optional favicon) { diff --git a/src/main/java/org/spongepowered/common/scheduler/ServerScheduler.java b/src/main/java/org/spongepowered/common/scheduler/ServerScheduler.java index 76f8599ed66..be1b41179ce 100644 --- a/src/main/java/org/spongepowered/common/scheduler/ServerScheduler.java +++ b/src/main/java/org/spongepowered/common/scheduler/ServerScheduler.java @@ -41,7 +41,7 @@ public void tick() { super.tick(); Sponge.server().streamOnlinePlayers().forEach(player -> { - try (final EntityTickContext context = TickPhase.Tick.ENTITY.createPhaseContext(PhaseTracker.SERVER).source(player)) { + try (final EntityTickContext context = TickPhase.Tick.ENTITY.createPhaseContext(PhaseTracker.getServerInstanceExplicitly()).source(player)) { context.buildAndSwitch(); // Detect Changes on PlayerInventories marked as dirty. ((PlayerInventoryBridge) ((net.minecraft.world.entity.player.Player) player).getInventory()).bridge$cleanupDirty(); diff --git a/src/main/java/org/spongepowered/common/world/volume/buffer/archetype/SpongeArchetypeVolume.java b/src/main/java/org/spongepowered/common/world/volume/buffer/archetype/SpongeArchetypeVolume.java index ac0577f93b7..4f7d26d1780 100644 --- a/src/main/java/org/spongepowered/common/world/volume/buffer/archetype/SpongeArchetypeVolume.java +++ b/src/main/java/org/spongepowered/common/world/volume/buffer/archetype/SpongeArchetypeVolume.java @@ -24,6 +24,7 @@ */ package org.spongepowered.common.world.volume.buffer.archetype; +import net.minecraft.server.level.ServerLevel; import org.checkerframework.checker.nullness.qual.NonNull; import org.spongepowered.api.Sponge; import org.spongepowered.api.block.BlockState; @@ -276,7 +277,7 @@ public void applyToWorld( Objects.requireNonNull(target, "Target world cannot be null"); Objects.requireNonNull(placement, "Target position cannot be null"); try (final PhaseContext<@NonNull ?> context = PluginPhase.State.VOLUME_STREAM_APPLICATION - .createPhaseContext(PhaseTracker.SERVER) + .createPhaseContext(PhaseTracker.getWorldInstance((ServerLevel) target)) .spawnType(spawnContext) .source(this)) { context.buildAndSwitch(); diff --git a/src/mixins/java/org/spongepowered/common/mixin/api/minecraft/world/entity/EntityMixin_API.java b/src/mixins/java/org/spongepowered/common/mixin/api/minecraft/world/entity/EntityMixin_API.java index cfe05e7ba24..ae8d346c17d 100644 --- a/src/mixins/java/org/spongepowered/common/mixin/api/minecraft/world/entity/EntityMixin_API.java +++ b/src/mixins/java/org/spongepowered/common/mixin/api/minecraft/world/entity/EntityMixin_API.java @@ -32,6 +32,7 @@ import net.minecraft.nbt.CompoundTag; import net.minecraft.resources.ResourceLocation; import net.minecraft.server.MinecraftServer; +import net.minecraft.server.level.ServerLevel; import net.minecraft.server.level.ServerPlayer; import net.minecraft.world.damagesource.DamageSource; import net.minecraft.world.entity.Entity; @@ -165,7 +166,7 @@ public Transform transform() { @Override public boolean setTransform(final Transform transform) { - if (!PhaseTracker.SERVER.onSidedThread()) { + if (!PhaseTracker.getWorldInstance((ServerLevel) this.shadow$level()).onSidedThread()) { return false; } diff --git a/src/mixins/java/org/spongepowered/common/mixin/api/minecraft/world/level/LevelAccessorMixin_API.java b/src/mixins/java/org/spongepowered/common/mixin/api/minecraft/world/level/LevelAccessorMixin_API.java index 8b51058fdbd..d09d59cc265 100644 --- a/src/mixins/java/org/spongepowered/common/mixin/api/minecraft/world/level/LevelAccessorMixin_API.java +++ b/src/mixins/java/org/spongepowered/common/mixin/api/minecraft/world/level/LevelAccessorMixin_API.java @@ -171,7 +171,7 @@ default boolean setBlock(final int x, final int y, final int z, final org.sponge if (!((Level) this).isInWorldBounds(new BlockPos(x, y, z))) { throw new PositionOutOfBoundsException(new Vector3i(x, y, z), Constants.World.BLOCK_MIN, Constants.World.BLOCK_MAX); } - try (final @Nullable PhaseContext<@NonNull ?> context = PluginPhase.State.BLOCK_WORKER.switchIfNecessary(PhaseTracker.SERVER)) { + try (final @Nullable PhaseContext<@NonNull ?> context = PluginPhase.State.BLOCK_WORKER.switchIfNecessary(PhaseTracker.getWorldInstance((LevelAccessor) this))) { if (context != null) { context.buildAndSwitch(); } diff --git a/src/mixins/java/org/spongepowered/common/mixin/core/client/MinecraftMixin.java b/src/mixins/java/org/spongepowered/common/mixin/core/client/MinecraftMixin.java index 9bf069259f9..ce0fb5a032c 100644 --- a/src/mixins/java/org/spongepowered/common/mixin/core/client/MinecraftMixin.java +++ b/src/mixins/java/org/spongepowered/common/mixin/core/client/MinecraftMixin.java @@ -116,7 +116,7 @@ public MinecraftMixin(String param0) { private void impl$nullServerRefAndPhaseTracker(Screen screenIn, CallbackInfo ci) { ((MinecraftBridge) this).bridge$setTemporaryIntegratedServer(null); try { - PhaseTracker.SERVER.setThread(null); + PhaseTracker.getServerInstanceExplicitly().setThread(null); } catch (IllegalAccessException ignore) { } } diff --git a/src/mixins/java/org/spongepowered/common/mixin/core/server/MinecraftServerMixin.java b/src/mixins/java/org/spongepowered/common/mixin/core/server/MinecraftServerMixin.java index 00401bb7d4d..a701c9d68db 100644 --- a/src/mixins/java/org/spongepowered/common/mixin/core/server/MinecraftServerMixin.java +++ b/src/mixins/java/org/spongepowered/common/mixin/core/server/MinecraftServerMixin.java @@ -154,7 +154,7 @@ public Subject subject() { final AtomicReference atomicReference, final Thread thread) { try { - PhaseTracker.SERVER.setThread(thread); + PhaseTracker.getServerInstanceExplicitly().setThread(thread); } catch (final IllegalAccessException e) { throw new RuntimeException("Could not initialize the server PhaseTracker!"); } diff --git a/src/mixins/java/org/spongepowered/common/mixin/core/server/level/ServerLevelMixin.java b/src/mixins/java/org/spongepowered/common/mixin/core/server/level/ServerLevelMixin.java index a6520bddc20..3f7af4b2ea8 100644 --- a/src/mixins/java/org/spongepowered/common/mixin/core/server/level/ServerLevelMixin.java +++ b/src/mixins/java/org/spongepowered/common/mixin/core/server/level/ServerLevelMixin.java @@ -235,8 +235,9 @@ public abstract class ServerLevelMixin extends LevelMixin implements ServerLevel @Override public void bridge$triggerExplosion(Explosion explosion) { // Set up the pre event + final PhaseTracker phaseTracker = PhaseTracker.getWorldInstance((ServerLevel) (Object) this); if (ShouldFire.EXPLOSION_EVENT_PRE) { - final var cause = PhaseTracker.getCauseStackManager().currentCause(); + final var cause = phaseTracker.currentCause(); final ExplosionEvent.Pre event = SpongeEventFactory.createExplosionEventPre(cause, explosion, (ServerWorld) this); if (SpongeCommon.post(event)) { return; @@ -246,7 +247,7 @@ public abstract class ServerLevelMixin extends LevelMixin implements ServerLevel final ServerExplosion mcExplosion = (ServerExplosion) explosion; - try (final PhaseContext ignored = GeneralPhase.State.EXPLOSION.createPhaseContext(PhaseTracker.SERVER) + try (final PhaseContext ignored = GeneralPhase.State.EXPLOSION.createPhaseContext(phaseTracker) .explosion(mcExplosion) .source(explosion.sourceExplosive().isPresent() ? explosion.sourceExplosive() : this)) { ignored.buildAndSwitch(); @@ -474,7 +475,7 @@ public void save(@Nullable final ProgressListener progress, final boolean flush, @Inject(method = "globalLevelEvent", at = @At("HEAD"), cancellable = true) private void impl$throwBroadcastGlobalEvent(int effectID, BlockPos pos, int pitch, CallbackInfo ci) { if (!this.bridge$isFake() && ShouldFire.PLAY_SOUND_EVENT_BROADCAST) { - try (final CauseStackManager.StackFrame frame = PhaseTracker.SERVER.pushCauseFrame()) { + try (final CauseStackManager.StackFrame frame = PhaseTracker.getWorldInstance((ServerLevel) (Object) this).pushCauseFrame()) { final PlaySoundEvent.Broadcast event = SpongeCommonEventFactory.callPlaySoundBroadcastEvent(frame, this, pos, effectID); if (event != null && event.isCancelled()) { ci.cancel(); diff --git a/src/mixins/java/org/spongepowered/common/mixin/core/server/level/ServerPlayerMixin.java b/src/mixins/java/org/spongepowered/common/mixin/core/server/level/ServerPlayerMixin.java index 7f5bb335570..6de6a633dad 100644 --- a/src/mixins/java/org/spongepowered/common/mixin/core/server/level/ServerPlayerMixin.java +++ b/src/mixins/java/org/spongepowered/common/mixin/core/server/level/ServerPlayerMixin.java @@ -523,11 +523,12 @@ public boolean teleportTo(final ServerLevel world, var isDimensionChange = transition.newLevel() != thisPlayer.serverLevel(); if (!this.impl$moveEventsFired) { - final var contextToSwitchTo = EntityPhase.State.PORTAL_DIMENSION_CHANGE.createPhaseContext(PhaseTracker.getInstance()).worldChange() + final PhaseTracker phaseTracker = PhaseTracker.getWorldInstance(thisPlayer.serverLevel()); + final var contextToSwitchTo = EntityPhase.State.PORTAL_DIMENSION_CHANGE.createPhaseContext(phaseTracker).worldChange() .player(); - final boolean hasMovementContext = PhaseTracker.SERVER.currentContext().containsKey(EventContextKeys.MOVEMENT_TYPE); + final boolean hasMovementContext = phaseTracker.currentContext().containsKey(EventContextKeys.MOVEMENT_TYPE); try (final TeleportContext context = contextToSwitchTo.buildAndSwitch(); - final CauseStackManager.StackFrame frame = PhaseTracker.getCauseStackManager().pushCauseFrame()) { + final CauseStackManager.StackFrame frame = phaseTracker.pushCauseFrame()) { frame.pushCause(thisPlayer); if (!hasMovementContext) { // TODO we should be able to detect normal plugin code though @@ -563,7 +564,7 @@ public boolean teleportTo(final ServerLevel world, newDest = reposition.destinationPosition(); } else { if (ShouldFire.MOVE_ENTITY_EVENT) { // TODO move into impl$fireMoveEvent? - newDest = this.impl$fireMoveEvent(PhaseTracker.SERVER, originalDest); + newDest = this.impl$fireMoveEvent(phaseTracker, originalDest); if (newDest == null) { return null; } diff --git a/src/mixins/java/org/spongepowered/common/mixin/core/server/players/PlayerListMixin.java b/src/mixins/java/org/spongepowered/common/mixin/core/server/players/PlayerListMixin.java index a0a538b1aa2..1a3ff1df7ab 100755 --- a/src/mixins/java/org/spongepowered/common/mixin/core/server/players/PlayerListMixin.java +++ b/src/mixins/java/org/spongepowered/common/mixin/core/server/players/PlayerListMixin.java @@ -444,8 +444,9 @@ public abstract class PlayerListMixin implements PlayerListBridge { ((ServerPlayerBridge) mcPlayer).bridge$setConnectionMessageToSend(null); - final PhaseContext context = PhaseTracker.SERVER.getPhaseContext(); - PhaseTracker.SERVER.pushCause(event); + final PhaseTracker phaseTracker = PhaseTracker.getWorldInstance(mcPlayer.serverLevel()); + final PhaseContext context = phaseTracker.getPhaseContext(); + phaseTracker.pushCause(event); final TransactionalCaptureSupplier transactor = context.getTransactor(); transactor.logPlayerInventoryChange(mcPlayer, PlayerInventoryTransaction.EventCreator.STANDARD); try (final EffectTransactor ignored = BroadcastInventoryChangesEffect.transact(transactor)) { @@ -642,7 +643,7 @@ public abstract class PlayerListMixin implements PlayerListBridge { final Predicate filter; ChatType.Bound boundChatType; - try (final CauseStackManager.StackFrame frame = PhaseTracker.SERVER.pushCauseFrame()) { + try (final CauseStackManager.StackFrame frame = PhaseTracker.getServerInstanceExplicitly().pushCauseFrame()) { if ($$2 != null) { frame.pushCause($$2); } diff --git a/src/mixins/java/org/spongepowered/common/mixin/core/world/entity/EntityMixin.java b/src/mixins/java/org/spongepowered/common/mixin/core/world/entity/EntityMixin.java index 2e6241aa51b..fff2eb84924 100644 --- a/src/mixins/java/org/spongepowered/common/mixin/core/world/entity/EntityMixin.java +++ b/src/mixins/java/org/spongepowered/common/mixin/core/world/entity/EntityMixin.java @@ -240,10 +240,11 @@ public abstract class EntityMixin implements EntityBridge, PlatformEntityBridge, return false; } - try (final CauseStackManager.StackFrame frame = PhaseTracker.getCauseStackManager().pushCauseFrame()) { + final ServerLevel originalWorld = (ServerLevel) this.shadow$level(); + final PhaseTracker phaseTracker = PhaseTracker.getWorldInstance(originalWorld); + try (final CauseStackManager.StackFrame frame = phaseTracker.pushCauseFrame()) { frame.addContext(EventContextKeys.MOVEMENT_TYPE, MovementTypes.PLUGIN); - final ServerLevel originalWorld = (ServerLevel) this.shadow$level(); final ServerLevel originalDestinationWorld = (ServerLevel) location.world(); final ServerLevel destinationWorld; final @org.checkerframework.checker.nullness.qual.Nullable Vector3d destinationPosition; @@ -265,7 +266,7 @@ public abstract class EntityMixin implements EntityBridge, PlatformEntityBridge, destinationPosition = repositionEvent.destinationPosition(); } else { destinationWorld = (ServerLevel) this.shadow$level(); - destinationPosition = this.impl$fireMoveEvent(PhaseTracker.SERVER, location.position()); + destinationPosition = this.impl$fireMoveEvent(phaseTracker, location.position()); if (destinationPosition == null) { return false; } @@ -275,7 +276,7 @@ public abstract class EntityMixin implements EntityBridge, PlatformEntityBridge, if (isChangeOfWorld) { Sponge.eventManager().post(SpongeEventFactory.createChangeEntityWorldEventPost( - PhaseTracker.getCauseStackManager().currentCause(), + phaseTracker.currentCause(), (org.spongepowered.api.entity.Entity) this, (ServerWorld) originalWorld, (ServerWorld) originalDestinationWorld, @@ -875,7 +876,8 @@ public void stopRiding() { this.remainingFireTicks < 1 && ticks >= Constants.Entity.MINIMUM_FIRE_TICKS && this.impl$canCallIgniteEntityEvent()) { - try (final CauseStackManager.StackFrame frame = PhaseTracker.getCauseStackManager().pushCauseFrame()) { + final PhaseTracker phaseTracker = PhaseTracker.getWorldInstance((ServerLevel) entity.level()); + try (final CauseStackManager.StackFrame frame = phaseTracker.pushCauseFrame()) { frame.pushCause(((org.spongepowered.api.entity.Entity) this).location().world()); final IgniteEntityEvent event = SpongeEventFactory. @@ -892,7 +894,7 @@ public void stopRiding() { .build(); final ChangeDataHolderEvent.ValueChange valueChange = SpongeEventFactory.createChangeDataHolderEventValueChange( - PhaseTracker.SERVER.currentCause(), + phaseTracker.currentCause(), transaction, (DataHolder.Mutable) this); diff --git a/src/mixins/java/org/spongepowered/common/mixin/core/world/entity/LivingEntityMixin.java b/src/mixins/java/org/spongepowered/common/mixin/core/world/entity/LivingEntityMixin.java index fff8bd381fb..994a4510d38 100644 --- a/src/mixins/java/org/spongepowered/common/mixin/core/world/entity/LivingEntityMixin.java +++ b/src/mixins/java/org/spongepowered/common/mixin/core/world/entity/LivingEntityMixin.java @@ -146,7 +146,7 @@ public abstract class LivingEntityMixin extends EntityMixin implements LivingEnt @Inject(method = "die", at = @At("HEAD"), cancellable = true) private void impl$throwDestructEntityDeath(final DamageSource cause, final CallbackInfo ci) { - final boolean throwEvent = !((LevelBridge) this.shadow$level()).bridge$isFake() && Sponge.isServerAvailable() && Sponge.server().onMainThread(); + final boolean throwEvent = !((LevelBridge) this.shadow$level()).bridge$isFake() && Sponge.isServerAvailable() && PhaseTracker.getWorldInstance().onSidedThread(); if (!this.dead) { // isDead should be set later on in this method so we aren't re-throwing the events. if (throwEvent && this.impl$deathEventsPosted <= Constants.Sponge.MAX_DEATH_EVENTS_BEFORE_GIVING_UP) { // ignore because some moron is not resetting the entity. @@ -454,17 +454,18 @@ public abstract class LivingEntityMixin extends EntityMixin implements LivingEnt stack.releaseUsing(world, self, duration); return; } - try (final CauseStackManager.StackFrame frame = PhaseTracker.getCauseStackManager().pushCauseFrame()) { + final PhaseTracker phaseTracker = PhaseTracker.getWorldInstance((ServerLevel) world); + try (final CauseStackManager.StackFrame frame = phaseTracker.pushCauseFrame()) { final ItemStackSnapshot snapshot = ItemStackUtil.snapshotOf(stack); final HandType handType = (HandType) (Object) this.shadow$getUsedItemHand(); this.impl$addSelfToFrame(frame, snapshot, handType); final Ticks ticksDuration = SpongeTicks.ticksOrInfinite(duration); - if (!SpongeCommon.post(SpongeEventFactory.createUseItemStackEventStop(PhaseTracker.getCauseStackManager().currentCause(), + if (!SpongeCommon.post(SpongeEventFactory.createUseItemStackEventStop(phaseTracker.currentCause(), ticksDuration, ticksDuration, snapshot))) { stack.releaseUsing(world, self, duration); if (self instanceof ServerPlayer) { // Log Change and capture SlotTransactions - PhaseTracker.SERVER.getPhaseContext().getTransactor().logPlayerInventoryChange(((ServerPlayer) self), PlayerInventoryTransaction.EventCreator.STANDARD); + phaseTracker.getPhaseContext().getTransactor().logPlayerInventoryChange(((ServerPlayer) self), PlayerInventoryTransaction.EventCreator.STANDARD); ((ServerPlayer) self).inventoryMenu.broadcastChanges(); } } diff --git a/src/mixins/java/org/spongepowered/common/mixin/core/world/entity/LivingEntityMixin_Attack_Impl.java b/src/mixins/java/org/spongepowered/common/mixin/core/world/entity/LivingEntityMixin_Attack_Impl.java index dd36c767846..8bce4b1a806 100644 --- a/src/mixins/java/org/spongepowered/common/mixin/core/world/entity/LivingEntityMixin_Attack_Impl.java +++ b/src/mixins/java/org/spongepowered/common/mixin/core/world/entity/LivingEntityMixin_Attack_Impl.java @@ -373,7 +373,7 @@ public abstract class LivingEntityMixin_Attack_Impl extends EntityMixin implemen result.damageToHelmet().isPresent() || result.damageToArmor().isPresent()) && (Object) this instanceof Player player) { - PhaseTracker.SERVER.getPhaseContext().getTransactor().logPlayerInventoryChange(player, PlayerInventoryTransaction.EventCreator.STANDARD); + PhaseTracker.getWorldInstance((ServerLevel) this.shadow$level()).getPhaseContext().getTransactor().logPlayerInventoryChange(player, PlayerInventoryTransaction.EventCreator.STANDARD); player.inventoryMenu.broadcastChanges(); // capture } } diff --git a/src/mixins/java/org/spongepowered/common/mixin/core/world/entity/decoration/ArmorStandMixin.java b/src/mixins/java/org/spongepowered/common/mixin/core/world/entity/decoration/ArmorStandMixin.java index d377bb6d48e..7ca9cfd76d5 100644 --- a/src/mixins/java/org/spongepowered/common/mixin/core/world/entity/decoration/ArmorStandMixin.java +++ b/src/mixins/java/org/spongepowered/common/mixin/core/world/entity/decoration/ArmorStandMixin.java @@ -147,7 +147,7 @@ public abstract class ArmorStandMixin extends LivingEntityMixin { target = "Lnet/minecraft/world/entity/decoration/ArmorStand;brokenByPlayer(Lnet/minecraft/server/level/ServerLevel;Lnet/minecraft/world/damagesource/DamageSource;)V")) public void impl$onBrokenByPlayer(final ArmorStand instance, final ServerLevel $$0, final DamageSource $$1) { - try (final EffectTransactor ignored = PhaseTracker.SERVER.getPhaseContext().getTransactor().ensureEntityDropTransactionEffect((LivingEntity) (Object) this)) { + try (final EffectTransactor ignored = PhaseTracker.getWorldInstance($$0).getPhaseContext().getTransactor().ensureEntityDropTransactionEffect((LivingEntity) (Object) this)) { this.shadow$brokenByPlayer($$0, $$1); } } diff --git a/src/mixins/java/org/spongepowered/common/mixin/core/world/entity/item/ItemEntityMixin.java b/src/mixins/java/org/spongepowered/common/mixin/core/world/entity/item/ItemEntityMixin.java index 0dd2ca7b6ad..199d69d5742 100644 --- a/src/mixins/java/org/spongepowered/common/mixin/core/world/entity/item/ItemEntityMixin.java +++ b/src/mixins/java/org/spongepowered/common/mixin/core/world/entity/item/ItemEntityMixin.java @@ -123,7 +123,7 @@ public abstract class ItemEntityMixin extends EntityMixin implements ItemEntityB ) ) private void impl$fireExpireEntityEventTargetItem(final CallbackInfo ci) { - if (!PhaseTracker.SERVER.onSidedThread() || this.shadow$getItem().isEmpty()) { + if (!PhaseTracker.getWorldInstance((ServerLevel) this.shadow$level()).onSidedThread() || this.shadow$getItem().isEmpty()) { // In the rare case the first if block is actually at the end of the method instruction list, we don't want to // erroneously be calling this twice. return; diff --git a/src/mixins/java/org/spongepowered/common/mixin/core/world/entity/player/PlayerMixin_Attack_Impl.java b/src/mixins/java/org/spongepowered/common/mixin/core/world/entity/player/PlayerMixin_Attack_Impl.java index 07a49e1163f..50c8b1c2238 100644 --- a/src/mixins/java/org/spongepowered/common/mixin/core/world/entity/player/PlayerMixin_Attack_Impl.java +++ b/src/mixins/java/org/spongepowered/common/mixin/core/world/entity/player/PlayerMixin_Attack_Impl.java @@ -291,7 +291,7 @@ public abstract class PlayerMixin_Attack_Impl extends LivingEntityMixin_Attack_I instance.setItemInHand(interactionHand, stack); // Capture... - final PhaseContext<@NonNull ?> context = PhaseTracker.SERVER.getPhaseContext(); + final PhaseContext<@NonNull ?> context = PhaseTracker.getWorldInstance((ServerLevel) this.shadow$level()).getPhaseContext(); final TransactionalCaptureSupplier transactor = context.getTransactor(); transactor.logPlayerInventoryChange(instance, PlayerInventoryTransaction.EventCreator.STANDARD); this.inventoryMenu.broadcastChanges(); diff --git a/src/mixins/java/org/spongepowered/common/mixin/core/world/entity/projectile/ProjectileUtilMixin.java b/src/mixins/java/org/spongepowered/common/mixin/core/world/entity/projectile/ProjectileUtilMixin.java index 0e8674220a6..6f786188ad6 100644 --- a/src/mixins/java/org/spongepowered/common/mixin/core/world/entity/projectile/ProjectileUtilMixin.java +++ b/src/mixins/java/org/spongepowered/common/mixin/core/world/entity/projectile/ProjectileUtilMixin.java @@ -26,6 +26,7 @@ import net.minecraft.core.BlockPos; import net.minecraft.core.Direction; +import net.minecraft.server.level.ServerLevel; import net.minecraft.world.entity.Entity; import net.minecraft.world.entity.projectile.ProjectileUtil; import net.minecraft.world.level.Level; @@ -84,7 +85,7 @@ public abstract class ProjectileUtilMixin { return ProjectileUtil.getEntityHitResult($$0, $$1, $$2, $$3, $$4, $$5, $$6); } try (final PhaseContext<@NonNull ?> context = EntityPhase.State.COLLISION - .createPhaseContext(PhaseTracker.SERVER) + .createPhaseContext(PhaseTracker.getWorldInstance((ServerLevel) $$0)) .source($$1) ) { context.buildAndSwitch(); diff --git a/src/mixins/java/org/spongepowered/common/mixin/core/world/level/entity/PersistentEntitySectionManagerMixin.java b/src/mixins/java/org/spongepowered/common/mixin/core/world/level/entity/PersistentEntitySectionManagerMixin.java index 2759957ff5d..f3b9c8b2fb3 100644 --- a/src/mixins/java/org/spongepowered/common/mixin/core/world/level/entity/PersistentEntitySectionManagerMixin.java +++ b/src/mixins/java/org/spongepowered/common/mixin/core/world/level/entity/PersistentEntitySectionManagerMixin.java @@ -24,6 +24,7 @@ */ package org.spongepowered.common.mixin.core.world.level.entity; +import net.minecraft.server.level.ServerLevel; import net.minecraft.world.entity.Entity; import net.minecraft.world.level.entity.EntityAccess; import net.minecraft.world.level.entity.PersistentEntitySectionManager; @@ -73,7 +74,7 @@ public class PersistentEntitySectionManagerMixin { final ServerLocation location = ServerLocation.of(sw, position.x(), position.y(), position.z()); final Vec2 rotationVector = mcEntity.getRotationVector(); final Vector3d rotation = new Vector3d(rotationVector.x, rotationVector.y, 0); - try (final CauseStackManager.StackFrame frame = PhaseTracker.SERVER.pushCauseFrame()) { + try (final CauseStackManager.StackFrame frame = PhaseTracker.getWorldInstance((ServerLevel) sw).pushCauseFrame()) { frame.pushCause(entity); final Event construct = SpongeEventFactory.createConstructEntityEventPost(frame.currentCause(), (org.spongepowered.api.entity.Entity) entity, location, rotation, ((EntityType) mcEntity.getType())); diff --git a/src/mixins/java/org/spongepowered/common/mixin/inventory/api/server/level/ServerPlayerMixin_Inventory_API.java b/src/mixins/java/org/spongepowered/common/mixin/inventory/api/server/level/ServerPlayerMixin_Inventory_API.java index 3c4711ab9f7..8bbb25f2918 100644 --- a/src/mixins/java/org/spongepowered/common/mixin/inventory/api/server/level/ServerPlayerMixin_Inventory_API.java +++ b/src/mixins/java/org/spongepowered/common/mixin/inventory/api/server/level/ServerPlayerMixin_Inventory_API.java @@ -72,7 +72,7 @@ public boolean closeInventory() throws IllegalArgumentException { } // Create Close_Window to capture item drops final net.minecraft.server.level.ServerPlayer player = (net.minecraft.server.level.ServerPlayer) (Object) this; - try (final PhaseContext<@NonNull ?> ctx = PacketPhase.General.CLOSE_WINDOW.createPhaseContext(PhaseTracker.SERVER) + try (final PhaseContext<@NonNull ?> ctx = PacketPhase.General.CLOSE_WINDOW.createPhaseContext(PhaseTracker.getWorldInstance(player.serverLevel())) .source(this) .packetPlayer(player) ) { diff --git a/src/mixins/java/org/spongepowered/common/mixin/inventory/event/server/level/ServerPlayerMixin_Inventory.java b/src/mixins/java/org/spongepowered/common/mixin/inventory/event/server/level/ServerPlayerMixin_Inventory.java index 2e300ee4b00..9e01385102d 100644 --- a/src/mixins/java/org/spongepowered/common/mixin/inventory/event/server/level/ServerPlayerMixin_Inventory.java +++ b/src/mixins/java/org/spongepowered/common/mixin/inventory/event/server/level/ServerPlayerMixin_Inventory.java @@ -24,6 +24,7 @@ */ package org.spongepowered.common.mixin.inventory.event.server.level; +import net.minecraft.server.level.ServerLevel; import net.minecraft.server.level.ServerPlayer; import net.minecraft.world.Container; import net.minecraft.world.entity.Entity; @@ -45,6 +46,7 @@ import org.spongepowered.api.item.inventory.Slot; import org.spongepowered.api.item.inventory.equipment.EquipmentType; import org.spongepowered.asm.mixin.Mixin; +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.Redirect; @@ -72,9 +74,13 @@ @Mixin(ServerPlayer.class) public abstract class ServerPlayerMixin_Inventory extends PlayerMixin_Inventory { + // @formatter:off @Nullable private EffectTransactor inventory$effectTransactor = null; @Nullable private Object inventory$menuProvider; + @Shadow public abstract ServerLevel shadow$serverLevel(); + // @formatter:on + // Ignore ServerPlayerMixin_Inventory(final EntityType param0, final Level param1) { super(param0, param1); @@ -84,7 +90,7 @@ public abstract class ServerPlayerMixin_Inventory extends PlayerMixin_Inventory @Override protected void impl$beforeSetItemSlot(final EquipmentSlot param0, final ItemStack param1, final CallbackInfo ci) { - final PhaseContext<@NonNull ?> context = PhaseTracker.SERVER.getPhaseContext(); + final PhaseContext<@NonNull ?> context = PhaseTracker.getWorldInstance(this.shadow$serverLevel()).getPhaseContext(); final TransactionalCaptureSupplier transactor = context.getTransactor(); final PlayerInventoryTransaction.EventCreator eventCreator = context.getState() instanceof SwapHandItemsState ? PlayerInventoryTransaction.EventCreator.SWAP_HAND : PlayerInventoryTransaction.EventCreator.STANDARD; @@ -103,7 +109,7 @@ public abstract class ServerPlayerMixin_Inventory extends PlayerMixin_Inventory @Inject(method = "drop(Z)Z", at = @At(value = "INVOKE", target = "Lnet/minecraft/world/entity/player/Inventory;removeFromSelected(Z)Lnet/minecraft/world/item/ItemStack;")) protected void impl$beforeRemoveItem(final boolean param0, final CallbackInfoReturnable cir) { - final PhaseContext<@NonNull ?> context = PhaseTracker.SERVER.getPhaseContext(); + final PhaseContext<@NonNull ?> context = PhaseTracker.getWorldInstance(this.shadow$serverLevel()).getPhaseContext(); final TransactionalCaptureSupplier transactor = context.getTransactor(); this.inventory$effectTransactor = transactor.logDropFromPlayerInventory((ServerPlayer) (Object) this, param0); } @@ -127,7 +133,7 @@ public abstract class ServerPlayerMixin_Inventory extends PlayerMixin_Inventory } final ServerPlayer serverPlayer = (ServerPlayer) player; - try (final PhaseContext<@NonNull ?> ctx = PacketPhase.General.CLOSE_WINDOW.createPhaseContext(PhaseTracker.SERVER) + try (final PhaseContext<@NonNull ?> ctx = PacketPhase.General.CLOSE_WINDOW.createPhaseContext(PhaseTracker.getWorldInstance(this.shadow$serverLevel())) .source(serverPlayer) .packetPlayer(serverPlayer) ) { @@ -150,7 +156,7 @@ public abstract class ServerPlayerMixin_Inventory extends PlayerMixin_Inventory entity.playerTouch(player); return; } - final PhaseContext<@NonNull ?> context = PhaseTracker.SERVER.getPhaseContext(); + final PhaseContext<@NonNull ?> context = PhaseTracker.getWorldInstance(this.shadow$serverLevel()).getPhaseContext(); try (final EffectTransactor ignored = context.getTransactor().logPlayerInventoryChangeWithEffect(player, PlayerInventoryTransaction.EventCreator.STANDARD)) { entity.playerTouch(player); this.inventoryMenu.broadcastChanges(); // capture @@ -165,7 +171,7 @@ public abstract class ServerPlayerMixin_Inventory extends PlayerMixin_Inventory @Override protected void inventory$onUpdateUsingItem(final LivingEntity thisPlayer) { - final PhaseContext<@NonNull ?> context = PhaseTracker.SERVER.getPhaseContext(); + final PhaseContext<@NonNull ?> context = PhaseTracker.getWorldInstance(this.shadow$serverLevel()).getPhaseContext(); final TransactionalCaptureSupplier transactor = context.getTransactor(); try (final EffectTransactor ignored = transactor.logPlayerInventoryChangeWithEffect((ServerPlayer) (Object) this, PlayerInventoryTransaction.EventCreator.STANDARD)) { this.shadow$completeUsingItem(); @@ -184,7 +190,7 @@ public abstract class ServerPlayerMixin_Inventory extends PlayerMixin_Inventory ) ) private void impl$afterOpenHorseInventory(final AbstractHorse $$0, final Container $$1, final CallbackInfo ci) { - PhaseTracker.SERVER.getPhaseContext() + PhaseTracker.getWorldInstance(this.shadow$serverLevel()).getPhaseContext() .getTransactor() .logContainerSet((ServerPlayer) (Object) this); } @@ -223,7 +229,7 @@ public abstract class ServerPlayerMixin_Inventory extends PlayerMixin_Inventory private HorseInventoryMenu impl$transactHorseInventoryMenuCreationWithEffect( final int $$0, final net.minecraft.world.entity.player.Inventory $$1, final Container $$2, final AbstractHorse $$3, final int $$4 ) { - try (final EffectTransactor ignored = PhaseTracker.SERVER.getPhaseContext() + try (final EffectTransactor ignored = PhaseTracker.getWorldInstance(this.shadow$serverLevel()).getPhaseContext() .getTransactor() .logOpenInventory((ServerPlayer) (Object) this) ) { diff --git a/src/mixins/java/org/spongepowered/common/mixin/inventory/event/server/level/ServerPlayerMixin_Shared_Inventory.java b/src/mixins/java/org/spongepowered/common/mixin/inventory/event/server/level/ServerPlayerMixin_Shared_Inventory.java index 82ec70039e9..377ea19010a 100644 --- a/src/mixins/java/org/spongepowered/common/mixin/inventory/event/server/level/ServerPlayerMixin_Shared_Inventory.java +++ b/src/mixins/java/org/spongepowered/common/mixin/inventory/event/server/level/ServerPlayerMixin_Shared_Inventory.java @@ -24,6 +24,7 @@ */ package org.spongepowered.common.mixin.inventory.event.server.level; +import net.minecraft.server.level.ServerLevel; import net.minecraft.server.level.ServerPlayer; import net.minecraft.world.MenuProvider; import net.minecraft.world.entity.player.Player; @@ -31,6 +32,7 @@ import org.checkerframework.checker.nullness.qual.Nullable; import org.objectweb.asm.Opcodes; import org.spongepowered.asm.mixin.Mixin; +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.Redirect; @@ -42,7 +44,12 @@ // Forge and Vanilla @Mixin(ServerPlayer.class) -public class ServerPlayerMixin_Shared_Inventory { +public abstract class ServerPlayerMixin_Shared_Inventory { + + // @formatter:off + @Shadow public abstract ServerLevel shadow$serverLevel(); + // @formatter:on + @Nullable private Object inventory$menuProvider; @Inject( @@ -55,7 +62,7 @@ public class ServerPlayerMixin_Shared_Inventory { ) ) private void impl$afterOpenMenu(final CallbackInfoReturnable cir) { - PhaseTracker.SERVER.getPhaseContext().getTransactor().logContainerSet((ServerPlayer) (Object) this); + PhaseTracker.getWorldInstance(this.shadow$serverLevel()).getPhaseContext().getTransactor().logContainerSet((ServerPlayer) (Object) this); } @Inject(method = "openMenu", at = @At(value = "INVOKE", target = "Lnet/minecraft/server/level/ServerPlayer;initMenu(Lnet/minecraft/world/inventory/AbstractContainerMenu;)V")) @@ -74,7 +81,7 @@ public class ServerPlayerMixin_Shared_Inventory { final MenuProvider menuProvider, final int containerCounter, final net.minecraft.world.entity.player.Inventory inventory, final Player player ) { - try (final EffectTransactor ignored = PhaseTracker.SERVER.getPhaseContext() + try (final EffectTransactor ignored = PhaseTracker.getWorldInstance(this.shadow$serverLevel()).getPhaseContext() .getTransactor() .logOpenInventory((ServerPlayer) (Object) this) ) { diff --git a/src/mixins/java/org/spongepowered/common/mixin/inventory/event/server/network/ServerGamePacketListenerImplMixin_Inventory.java b/src/mixins/java/org/spongepowered/common/mixin/inventory/event/server/network/ServerGamePacketListenerImplMixin_Inventory.java index c95c646d4f6..6866a22f93b 100644 --- a/src/mixins/java/org/spongepowered/common/mixin/inventory/event/server/network/ServerGamePacketListenerImplMixin_Inventory.java +++ b/src/mixins/java/org/spongepowered/common/mixin/inventory/event/server/network/ServerGamePacketListenerImplMixin_Inventory.java @@ -66,7 +66,7 @@ public class ServerGamePacketListenerImplMixin_Inventory { @Redirect(method = "handleSetCreativeModeSlot", at = @At(value = "INVOKE", target = "Lnet/minecraft/world/inventory/InventoryMenu;broadcastChanges()V")) private void impl$onBroadcastCreativeActionResult(final InventoryMenu inventoryMenu, final ServerboundSetCreativeModeSlotPacket packetIn) { - final PhaseContext<@NonNull ?> context = PhaseTracker.SERVER.getPhaseContext(); + final PhaseContext<@NonNull ?> context = PhaseTracker.getWorldInstance(this.player.serverLevel()).getPhaseContext(); final TransactionalCaptureSupplier transactor = context.getTransactor(); final ItemStack itemstack = packetIn.itemStack(); @@ -79,7 +79,7 @@ public class ServerGamePacketListenerImplMixin_Inventory { @Redirect(method = "handleSetCreativeModeSlot", at = @At(value = "INVOKE", target = "Lnet/minecraft/server/level/ServerPlayer;drop(Lnet/minecraft/world/item/ItemStack;Z)Lnet/minecraft/world/entity/item/ItemEntity;")) private ItemEntity impl$onBroadcastCreativeActionResult(final ServerPlayer serverPlayer, final ItemStack stack, final boolean param1) { - final PhaseContext<@NonNull ?> context = PhaseTracker.SERVER.getPhaseContext(); + final PhaseContext<@NonNull ?> context = PhaseTracker.getWorldInstance(this.player.serverLevel()).getPhaseContext(); final TransactionalCaptureSupplier transactor = context.getTransactor(); try (final EffectTransactor ignored = transactor.logCreativeClickContainer(-1, ItemStackUtil.snapshotOf(stack), this.player)) { return serverPlayer.drop(stack, param1); @@ -92,7 +92,7 @@ public class ServerGamePacketListenerImplMixin_Inventory { slice = @Slice(from = @At(value = "INVOKE", target = "Lnet/minecraft/server/level/ServerPlayer;stopUsingItem()V")) ) private void impl$onHandleSetCarriedItem(final ServerboundSetCarriedItemPacket packet, final CallbackInfo ci) { - final PhaseContext<@NonNull ?> context = PhaseTracker.SERVER.getPhaseContext(); + final PhaseContext<@NonNull ?> context = PhaseTracker.getWorldInstance(this.player.serverLevel()).getPhaseContext(); final TransactionalCaptureSupplier transactor = context.getTransactor(); final int slotIdx = packet.getSlot(); transactor.logPlayerCarriedItem(this.player, slotIdx); @@ -101,7 +101,7 @@ public class ServerGamePacketListenerImplMixin_Inventory { @Redirect(method = "handleContainerClick", at = @At(value = "INVOKE", target = "Lnet/minecraft/world/inventory/AbstractContainerMenu;sendAllDataToRemote()V")) private void impl$onSpectatorClick(final AbstractContainerMenu menu, final ServerboundContainerClickPacket packet) { - final PhaseContext<@NonNull ?> context = PhaseTracker.SERVER.getPhaseContext(); + final PhaseContext<@NonNull ?> context = PhaseTracker.getWorldInstance(this.player.serverLevel()).getPhaseContext(); final TransactionalCaptureSupplier transactor = context.getTransactor(); try (final EffectTransactor ignored = transactor.logClickContainer(menu, packet.getSlotNum(), packet.getButtonNum(), packet.getClickType(), this.player @@ -120,7 +120,7 @@ public class ServerGamePacketListenerImplMixin_Inventory { at = @At(value = "INVOKE", target = "Lnet/minecraft/server/level/ServerPlayerGameMode;useItem(Lnet/minecraft/server/level/ServerPlayer;Lnet/minecraft/world/level/Level;Lnet/minecraft/world/item/ItemStack;Lnet/minecraft/world/InteractionHand;)Lnet/minecraft/world/InteractionResult;")) private InteractionResult impl$onHandleUseItem(final ServerPlayerGameMode serverPlayerGameMode, final ServerPlayer param0, final Level param1, final ItemStack param2, final InteractionHand param3) { - final PhaseContext<@NonNull ?> context = PhaseTracker.SERVER.getPhaseContext(); + final PhaseContext<@NonNull ?> context = PhaseTracker.getWorldInstance(this.player.serverLevel()).getPhaseContext(); final TransactionalCaptureSupplier transactor = context.getTransactor(); try (final EffectTransactor ignored = transactor.logPlayerInventoryChangeWithEffect(this.player, PlayerInventoryTransaction.EventCreator.STANDARD)) { final InteractionResult result = serverPlayerGameMode.useItem(param0, param1, param2, param3); @@ -133,7 +133,7 @@ public class ServerGamePacketListenerImplMixin_Inventory { @Redirect(method = "handleContainerClose", at = @At(value = "INVOKE", target = "Lnet/minecraft/server/level/ServerPlayer;doCloseContainer()V")) private void impl$onHandleContainerClose(final ServerPlayer player) { - final PhaseContext<@NonNull ?> context = PhaseTracker.SERVER.getPhaseContext(); + final PhaseContext<@NonNull ?> context = PhaseTracker.getWorldInstance(this.player.serverLevel()).getPhaseContext(); final TransactionalCaptureSupplier transactor = context.getTransactor(); try (final EffectTransactor ignored = transactor.logCloseInventory(player, true)) { this.player.containerMenu.removed(player); @@ -144,7 +144,7 @@ public class ServerGamePacketListenerImplMixin_Inventory { @Redirect(method = "handleRenameItem(Lnet/minecraft/network/protocol/game/ServerboundRenameItemPacket;)V", at = @At(value = "INVOKE", target = "Lnet/minecraft/world/inventory/AnvilMenu;setItemName(Ljava/lang/String;)Z")) private boolean impl$onHandleRenameItem(final AnvilMenu menu, final String name) { - final PhaseContext<@NonNull ?> context = PhaseTracker.SERVER.getPhaseContext(); + final PhaseContext<@NonNull ?> context = PhaseTracker.getWorldInstance(this.player.serverLevel()).getPhaseContext(); final TransactionalCaptureSupplier transactor = context.getTransactor(); try (final var ignored = transactor.logIgnoredInventory(this.player.containerMenu)) { return menu.setItemName(name); @@ -154,7 +154,7 @@ public class ServerGamePacketListenerImplMixin_Inventory { @Inject(method = "handleSelectTrade", at = @At("RETURN")) private void impl$onHandleSelectTrade(final ServerboundSelectTradePacket param0, final CallbackInfo ci) { if (this.player.containerMenu instanceof MerchantMenu) { - final PhaseContext<@NonNull ?> context = PhaseTracker.SERVER.getPhaseContext(); + final PhaseContext<@NonNull ?> context = PhaseTracker.getWorldInstance(this.player.serverLevel()).getPhaseContext(); final TransactionalCaptureSupplier transactor = context.getTransactor(); transactor.logSelectTrade(this.player, param0.getItem()); this.player.containerMenu.broadcastChanges(); // capture diff --git a/src/mixins/java/org/spongepowered/common/mixin/inventory/event/world/inventory/AbstractContainerMenuMixin_Inventory.java b/src/mixins/java/org/spongepowered/common/mixin/inventory/event/world/inventory/AbstractContainerMenuMixin_Inventory.java index b530cc8df35..d8db0a26fbb 100644 --- a/src/mixins/java/org/spongepowered/common/mixin/inventory/event/world/inventory/AbstractContainerMenuMixin_Inventory.java +++ b/src/mixins/java/org/spongepowered/common/mixin/inventory/event/world/inventory/AbstractContainerMenuMixin_Inventory.java @@ -25,6 +25,7 @@ package org.spongepowered.common.mixin.inventory.event.world.inventory; import net.minecraft.core.NonNullList; +import net.minecraft.server.level.ServerLevel; import net.minecraft.server.level.ServerPlayer; import net.minecraft.world.entity.player.Inventory; import net.minecraft.world.entity.player.Player; @@ -114,7 +115,7 @@ public abstract class AbstractContainerMenuMixin_Inventory implements TrackedCon ) ) private void impl$handleUnviewedSlotSwap(final Inventory inv, final int index, final ItemStack newStack) { - if (!PhaseTracker.SERVER.onSidedThread() || inv.player.inventoryMenu == inv.player.containerMenu || Inventory.isHotbarSlot(index)) { + if (!PhaseTracker.getWorldInstance().onSidedThread() || inv.player.inventoryMenu == inv.player.containerMenu || Inventory.isHotbarSlot(index)) { inv.setItem(index, newStack); } else { final ItemStackSnapshot oldItem = ItemStackUtil.snapshotOf(inv.getItem(index)); @@ -139,7 +140,7 @@ public abstract class AbstractContainerMenuMixin_Inventory implements TrackedCon ) private ItemStack impl$handleUnviewedSlotSwap2(final ItemStack origin, final int splitOff, int $$0, int index, ClickType $$2, Player $$3) { Inventory inv = $$3.getInventory(); - if (!PhaseTracker.SERVER.onSidedThread() || inv.player.inventoryMenu == inv.player.containerMenu || Inventory.isHotbarSlot(index)) { + if (!PhaseTracker.getWorldInstance().onSidedThread() || inv.player.inventoryMenu == inv.player.containerMenu || Inventory.isHotbarSlot(index)) { return origin.split(splitOff); } else { final ItemStackSnapshot oldItem = ItemStackUtil.snapshotOf(origin); @@ -188,7 +189,7 @@ public abstract class AbstractContainerMenuMixin_Inventory implements TrackedCon return result; } this.bridge$detectAndSendChanges(true, true); - final PhaseContext<@NonNull ?> context = PhaseTracker.SERVER.getPhaseContext(); + final PhaseContext<@NonNull ?> context = PhaseTracker.getWorldInstance((ServerLevel) player.level()).getPhaseContext(); TrackingUtil.processBlockCaptures(context); // ClickContainerEvent -> CraftEvent -> PreviewEvent // result is modified by the ClickMenuTransaction return result; @@ -207,7 +208,7 @@ public abstract class AbstractContainerMenuMixin_Inventory implements TrackedCon this.shadow$doClick(slotId, dragType, clickType, player); return; } - final PhaseContext<@NonNull ?> context = PhaseTracker.SERVER.getPhaseContext(); + final PhaseContext<@NonNull ?> context = PhaseTracker.getWorldInstance((ServerLevel) player.level()).getPhaseContext(); final TransactionalCaptureSupplier transactor = context.getTransactor(); try (final EffectTransactor ignored = transactor.logClickContainer(menu, slotId, dragType, clickType, player)) { this.impl$isClicking = true; @@ -222,7 +223,7 @@ public abstract class AbstractContainerMenuMixin_Inventory implements TrackedCon @Inject(method = "broadcastFullState", at = @At("HEAD"), cancellable = true) private void impl$broadcastFullStateWithTransactions(final CallbackInfo ci) { - if (!PhaseTracker.SERVER.onSidedThread()) { + if (!PhaseTracker.getWorldInstance().onSidedThread()) { return; } this.bridge$detectAndSendChanges(false, false); @@ -243,7 +244,7 @@ public abstract class AbstractContainerMenuMixin_Inventory implements TrackedCon */ @Inject(method = "broadcastChanges", at = @At("HEAD"), cancellable = true) private void impl$broadcastChangesWithTransactions(final CallbackInfo ci) { - if (!PhaseTracker.SERVER.onSidedThread()) { + if (!PhaseTracker.getWorldInstance().onSidedThread()) { return; } this.bridge$detectAndSendChanges(false, true); @@ -256,7 +257,7 @@ public abstract class AbstractContainerMenuMixin_Inventory implements TrackedCon public void bridge$detectAndSendChanges(final boolean capture, final boolean synchronize) { // Code-Flow changed from vanilla completely! - final PhaseContext phaseContext = PhaseTracker.SERVER.getPhaseContext(); + final PhaseContext phaseContext = PhaseTracker.getWorldInstance().getPhaseContext(); if (phaseContext.captureModifiedContainer((AbstractContainerMenu) (Object) this)) { return; } @@ -342,8 +343,9 @@ public abstract class AbstractContainerMenuMixin_Inventory implements TrackedCon } private void impl$capture(final Integer index, final ItemStack newStack, final ItemStack oldStack) { - final PhaseContext phaseContext = PhaseTracker.SERVER.getPhaseContext(); - if (PhaseTracker.SERVER.onSidedThread() && + final PhaseTracker phaseTracker = PhaseTracker.getWorldInstance(); + final PhaseContext phaseContext = phaseTracker.getPhaseContext(); + if (phaseTracker.onSidedThread() && !(phaseContext.isRestoring() // do not capture when block restoring & initial sync on inventory open || phaseContext instanceof TileEntityTickContext)) { // do not capture for open inventories when ticking BlockEntities final ItemStackSnapshot oldItem = ItemStackUtil.snapshotOf(oldStack); @@ -359,7 +361,7 @@ public abstract class AbstractContainerMenuMixin_Inventory implements TrackedCon } private void impl$captureSwap(int index, Inventory inv, ItemStackSnapshot oldItem, ItemStackSnapshot newItem) { - final PhaseContext<@NonNull ?> phaseContext = PhaseTracker.SERVER.getPhaseContext(); + final PhaseContext<@NonNull ?> phaseContext = PhaseTracker.getWorldInstance().getPhaseContext(); final TransactionalCaptureSupplier transactor = phaseContext.getTransactor(); final org.spongepowered.api.item.inventory.Slot adapter = ((InventoryAdapter) inv.player.getInventory()).inventoryAdapter$getSlot(index).get(); final SlotTransaction newTransaction = new SlotTransaction(adapter, oldItem, newItem); diff --git a/src/mixins/java/org/spongepowered/common/mixin/inventory/event/world/inventory/AnvilMenuMixin_Inventory.java b/src/mixins/java/org/spongepowered/common/mixin/inventory/event/world/inventory/AnvilMenuMixin_Inventory.java index 2d5f4c7aa4e..a081fce9f6a 100644 --- a/src/mixins/java/org/spongepowered/common/mixin/inventory/event/world/inventory/AnvilMenuMixin_Inventory.java +++ b/src/mixins/java/org/spongepowered/common/mixin/inventory/event/world/inventory/AnvilMenuMixin_Inventory.java @@ -49,7 +49,7 @@ public abstract class AnvilMenuMixin_Inventory extends ItemCombinerMenuMixin_Inv @Inject(method = "createResult", at = @At(value = "RETURN")) private void impl$throwUpdateAnvilEvent(final CallbackInfo ci) { - if (!ShouldFire.UPDATE_ANVIL_EVENT || !PhaseTracker.SERVER.onSidedThread()) { + if (!ShouldFire.UPDATE_ANVIL_EVENT || !PhaseTracker.getWorldInstance().onSidedThread()) { return; } diff --git a/src/mixins/java/org/spongepowered/common/mixin/inventory/event/world/inventory/CraftingMenuMixin_Inventory.java b/src/mixins/java/org/spongepowered/common/mixin/inventory/event/world/inventory/CraftingMenuMixin_Inventory.java index 3b173f8ebbe..4e7bf87dcb6 100644 --- a/src/mixins/java/org/spongepowered/common/mixin/inventory/event/world/inventory/CraftingMenuMixin_Inventory.java +++ b/src/mixins/java/org/spongepowered/common/mixin/inventory/event/world/inventory/CraftingMenuMixin_Inventory.java @@ -62,7 +62,7 @@ private static void beforeSlotChangedCraftingGrid( return; } - final PhaseContext<@NonNull ?> context = PhaseTracker.SERVER.getPhaseContext(); + final PhaseContext<@NonNull ?> context = PhaseTracker.getWorldInstance().getPhaseContext(); if (!context.isRestoring()) { final TransactionalCaptureSupplier transactor = context.getTransactor(); transactor.logCraftingPreview((ServerPlayer) player, (CraftingInventory) inv, craftingContainer); diff --git a/src/mixins/java/org/spongepowered/common/mixin/inventory/event/world/inventory/ResultSlotMixin_Inventory.java b/src/mixins/java/org/spongepowered/common/mixin/inventory/event/world/inventory/ResultSlotMixin_Inventory.java index 7a43a4977ea..80c4c55a145 100644 --- a/src/mixins/java/org/spongepowered/common/mixin/inventory/event/world/inventory/ResultSlotMixin_Inventory.java +++ b/src/mixins/java/org/spongepowered/common/mixin/inventory/event/world/inventory/ResultSlotMixin_Inventory.java @@ -134,7 +134,7 @@ public void set(@Nullable final ItemStack stack) { return; } - final PhaseContext<@NonNull ?> context = PhaseTracker.SERVER.getPhaseContext(); + final PhaseContext<@NonNull ?> context = PhaseTracker.getWorldInstance().getPhaseContext(); final TransactionalCaptureSupplier transactor = context.getTransactor(); transactor.logCrafting(thePlayer, this.impl$craftedStack, (CraftingInventory) craftInv, this.impl$onTakeRecipe); diff --git a/src/mixins/java/org/spongepowered/common/mixin/inventory/event/world/inventory/SlotMixin_Inventory.java b/src/mixins/java/org/spongepowered/common/mixin/inventory/event/world/inventory/SlotMixin_Inventory.java index db84f046d84..f71309dd8f3 100644 --- a/src/mixins/java/org/spongepowered/common/mixin/inventory/event/world/inventory/SlotMixin_Inventory.java +++ b/src/mixins/java/org/spongepowered/common/mixin/inventory/event/world/inventory/SlotMixin_Inventory.java @@ -47,8 +47,9 @@ public abstract class SlotMixin_Inventory { @Inject(method = "onQuickCraft(Lnet/minecraft/world/item/ItemStack;Lnet/minecraft/world/item/ItemStack;)V", at = @At("HEAD")) private void inventory$onQuickCraft(final ItemStack slotStack, final ItemStack stackTaken, final CallbackInfo ci) { - if (PhaseTracker.SERVER.onSidedThread()) { - final PhaseContext<@NonNull ?> ctx = PhaseTracker.SERVER.getPhaseContext(); + final PhaseTracker phaseTracker = PhaseTracker.getWorldInstance(); + if (phaseTracker.onSidedThread()) { + final PhaseContext<@NonNull ?> ctx = phaseTracker.getPhaseContext(); ctx.getTransactor().logShiftCraftingResult((Slot) (Object) this, stackTaken); } } diff --git a/src/mixins/java/org/spongepowered/common/mixin/inventory/event/world/level/block/entity/HopperBlockEntityMixin_Inventory.java b/src/mixins/java/org/spongepowered/common/mixin/inventory/event/world/level/block/entity/HopperBlockEntityMixin_Inventory.java index 658609e9705..1ffd6924c48 100644 --- a/src/mixins/java/org/spongepowered/common/mixin/inventory/event/world/level/block/entity/HopperBlockEntityMixin_Inventory.java +++ b/src/mixins/java/org/spongepowered/common/mixin/inventory/event/world/level/block/entity/HopperBlockEntityMixin_Inventory.java @@ -121,7 +121,7 @@ public abstract class HopperBlockEntityMixin_Inventory { // Ignore all container transactions in affected inventories if (hopper instanceof final ViewableInventoryBridge bridge) { - try (final PhaseContext context = BlockPhase.State.RESTORING_BLOCKS.createPhaseContext(PhaseTracker.SERVER)) { + try (final PhaseContext context = BlockPhase.State.RESTORING_BLOCKS.createPhaseContext(PhaseTracker.getWorldInstance())) { context.buildAndSwitch(); for (final ServerPlayer player : bridge.viewableBridge$getViewers()) { player.containerMenu.broadcastChanges(); @@ -129,7 +129,7 @@ public abstract class HopperBlockEntityMixin_Inventory { } } if (iInventory instanceof final ViewableInventoryBridge bridge) { - try (final PhaseContext context = BlockPhase.State.RESTORING_BLOCKS.createPhaseContext(PhaseTracker.SERVER)) { + try (final PhaseContext context = BlockPhase.State.RESTORING_BLOCKS.createPhaseContext(PhaseTracker.getWorldInstance())) { context.buildAndSwitch(); for (final ServerPlayer player : bridge.viewableBridge$getViewers()) { player.containerMenu.broadcastChanges(); diff --git a/src/mixins/java/org/spongepowered/common/mixin/tracker/server/MinecraftServerMixin_Tracker.java b/src/mixins/java/org/spongepowered/common/mixin/tracker/server/MinecraftServerMixin_Tracker.java index acc316eb42e..0f583e1fe05 100644 --- a/src/mixins/java/org/spongepowered/common/mixin/tracker/server/MinecraftServerMixin_Tracker.java +++ b/src/mixins/java/org/spongepowered/common/mixin/tracker/server/MinecraftServerMixin_Tracker.java @@ -63,7 +63,7 @@ public abstract class MinecraftServerMixin_Tracker extends BlockableEventLoopMix @Inject(method = "tickServer", at = @At("RETURN")) private void tracker$ensurePhaseTrackerEmpty(final BooleanSupplier hasTimeLeft, final CallbackInfo ci) { - PhaseTracker.SERVER.ensureEmpty(); + PhaseTracker.getServerInstanceExplicitly().ensureEmpty(); } @Redirect( @@ -76,7 +76,7 @@ public abstract class MinecraftServerMixin_Tracker extends BlockableEventLoopMix private void tracker$wrapUpdateTimeLightAndEntities(final MinecraftServer minecraftServer, final BooleanSupplier hasTimeLeft) { try ( final PhaseContext<@NonNull ?> context = TickPhase.Tick.SERVER_TICK - .createPhaseContext(PhaseTracker.SERVER) + .createPhaseContext(PhaseTracker.getServerInstanceExplicitly()) .server(minecraftServer) ) { context.buildAndSwitch(); @@ -94,7 +94,7 @@ public abstract class MinecraftServerMixin_Tracker extends BlockableEventLoopMix private void tracker$wrapWorldTick(final ServerLevel serverWorld, final BooleanSupplier hasTimeLeft) { try ( final PhaseContext<@NonNull ?> context = TickPhase.Tick.WORLD_TICK - .createPhaseContext(PhaseTracker.SERVER) + .createPhaseContext(PhaseTracker.getWorldInstance(serverWorld)) .world(serverWorld) ) { context.buildAndSwitch(); @@ -104,7 +104,7 @@ public abstract class MinecraftServerMixin_Tracker extends BlockableEventLoopMix @Inject(method = "wrapRunnable(Ljava/lang/Runnable;)Lnet/minecraft/server/TickTask;", at = @At("RETURN")) private void tracker$associatePhaseContextWithWrappedTask(final Runnable runnable, final CallbackInfoReturnable cir) { final TickTask returnValue = cir.getReturnValue(); - if (!PhaseTracker.SERVER.onSidedThread()) { + if (!PhaseTracker.getServerInstanceExplicitly().onSidedThread()) { final PhaseContext<@NonNull ?> phaseContext = PhaseTracker.getInstance().getPhaseContext(); if (phaseContext.isEmpty()) { return; @@ -122,7 +122,7 @@ public abstract class MinecraftServerMixin_Tracker extends BlockableEventLoopMix ) @SuppressWarnings("unchecked") private void tracker$wrapAndPerformContextSwitch(final ReentrantBlockableEventLoop thisServer, final Runnable runnable) { - try (final PhaseContext<@NonNull ?> context = PluginPhase.State.DELAYED_TASK.createPhaseContext(PhaseTracker.SERVER) + try (final PhaseContext<@NonNull ?> context = PluginPhase.State.DELAYED_TASK.createPhaseContext(PhaseTracker.getServerInstanceExplicitly()) .source(runnable) .setDelayedContextPopulator(((TickTaskBridge) runnable).bridge$getFrameModifier().orElse(null)) ) { diff --git a/src/mixins/java/org/spongepowered/common/mixin/tracker/server/level/ChunkMapMixin_Tracker.java b/src/mixins/java/org/spongepowered/common/mixin/tracker/server/level/ChunkMapMixin_Tracker.java index 894d7e8a63d..a009abaa2ea 100644 --- a/src/mixins/java/org/spongepowered/common/mixin/tracker/server/level/ChunkMapMixin_Tracker.java +++ b/src/mixins/java/org/spongepowered/common/mixin/tracker/server/level/ChunkMapMixin_Tracker.java @@ -63,7 +63,8 @@ public abstract class ChunkMapMixin_Tracker { @Redirect(method = "lambda$prepareTickingChunk$25", at = @At(value = "INVOKE", target = "Lnet/minecraft/server/level/ServerLevel;startTickingChunk(Lnet/minecraft/world/level/chunk/LevelChunk;)V")) private void tracker$wrapUnpackTicks(final ServerLevel level, final LevelChunk chunk) { - if (!PhaseTracker.SERVER.onSidedThread()) { + final PhaseTracker phaseTracker = PhaseTracker.getWorldInstance(level); + if (!phaseTracker.onSidedThread()) { new PrettyPrinter(60).add("Illegal Async Chunk Unpacking").centre().hr() .addWrapped("Someone is attempting to unpack chunk scheduled updates while off the main thread, this is" + "generally unsupported and Sponge would appreciate a report about this. Please attach " + @@ -76,10 +77,10 @@ public abstract class ChunkMapMixin_Tracker { .log(SpongeCommon.logger(), Level.ERROR); return; } - if (PhaseTracker.getInstance().getCurrentState() == GenerationPhase.State.CHUNK_LOADING) { + if (phaseTracker.getCurrentState() == GenerationPhase.State.CHUNK_LOADING) { return; } - try (final PhaseContext<@NonNull ?> ctx = GenerationPhase.State.CHUNK_LOADING.createPhaseContext(PhaseTracker.getInstance()) + try (final PhaseContext<@NonNull ?> ctx = GenerationPhase.State.CHUNK_LOADING.createPhaseContext(phaseTracker) .source(chunk) .world(level) .chunk(chunk)) { diff --git a/src/mixins/java/org/spongepowered/common/mixin/tracker/server/level/ChunkStatusTasksMixin_Tracker.java b/src/mixins/java/org/spongepowered/common/mixin/tracker/server/level/ChunkStatusTasksMixin_Tracker.java index ea2d4ed8e56..6e26bad1ab8 100644 --- a/src/mixins/java/org/spongepowered/common/mixin/tracker/server/level/ChunkStatusTasksMixin_Tracker.java +++ b/src/mixins/java/org/spongepowered/common/mixin/tracker/server/level/ChunkStatusTasksMixin_Tracker.java @@ -60,7 +60,8 @@ public abstract class ChunkStatusTasksMixin_Tracker { if (isFake) { return; } - if (!PhaseTracker.SERVER.onSidedThread()) { + final PhaseTracker phaseTracker = PhaseTracker.getWorldInstance((ServerLevel) chunk.getLevel()); + if (!phaseTracker.onSidedThread()) { new PrettyPrinter(60).add("Illegal Async Chunk Load").centre().hr() .addWrapped("Sponge relies on knowing when chunks are being loaded as chunks add entities" + " to the parented world for management. These operations are generally not" @@ -73,10 +74,10 @@ public abstract class ChunkStatusTasksMixin_Tracker { .log(SpongeCommon.logger(), Level.ERROR); return; } - if (PhaseTracker.getInstance().getCurrentState() == GenerationPhase.State.CHUNK_REGENERATING_LOAD_EXISTING) { + if (phaseTracker.getCurrentState() == GenerationPhase.State.CHUNK_REGENERATING_LOAD_EXISTING) { return; } - GenerationPhase.State.CHUNK_LOADING.createPhaseContext(PhaseTracker.getInstance()) + GenerationPhase.State.CHUNK_LOADING.createPhaseContext(phaseTracker) .source(chunk) .world((ServerLevel) chunk.getLevel()) .chunk(chunk) @@ -92,12 +93,13 @@ public abstract class ChunkStatusTasksMixin_Tracker { ) private static void tracker$endLoad(final ChunkAccess $$0x, final WorldGenContext $$1x, final GenerationChunkHolder $$2x, final CallbackInfoReturnable cir) { - if (!((LevelBridge) $$1x.level()).bridge$isFake() && PhaseTracker.SERVER.onSidedThread()) { - if (PhaseTracker.getInstance().getCurrentState() == GenerationPhase.State.CHUNK_REGENERATING_LOAD_EXISTING) { + final PhaseTracker phaseTracker = PhaseTracker.getWorldInstance($$1x.level()); + if (!((LevelBridge) $$1x.level()).bridge$isFake() && phaseTracker.onSidedThread()) { + if (phaseTracker.getCurrentState() == GenerationPhase.State.CHUNK_REGENERATING_LOAD_EXISTING) { return; } // IF we're not on the main thread, - PhaseTracker.getInstance().getPhaseContext().close(); + phaseTracker.getPhaseContext().close(); } } diff --git a/src/mixins/java/org/spongepowered/common/mixin/tracker/server/level/ServerChunkCacheMixin_Tracker.java b/src/mixins/java/org/spongepowered/common/mixin/tracker/server/level/ServerChunkCacheMixin_Tracker.java index 4551170d435..bdcf5b3f7ae 100644 --- a/src/mixins/java/org/spongepowered/common/mixin/tracker/server/level/ServerChunkCacheMixin_Tracker.java +++ b/src/mixins/java/org/spongepowered/common/mixin/tracker/server/level/ServerChunkCacheMixin_Tracker.java @@ -55,7 +55,7 @@ public abstract class ServerChunkCacheMixin_Tracker { final NaturalSpawner.SpawnState spawnState, final List mobCategories ) { - try (final PhaseContext<@NonNull ?> context = GenerationPhase.State.WORLD_SPAWNER_SPAWNING.createPhaseContext(PhaseTracker.SERVER) + try (final PhaseContext<@NonNull ?> context = GenerationPhase.State.WORLD_SPAWNER_SPAWNING.createPhaseContext(PhaseTracker.getWorldInstance(serverWorld)) .world(serverWorld)) { context.buildAndSwitch(); NaturalSpawner.spawnForChunk(serverWorld, targetChunk, spawnState, mobCategories); @@ -74,7 +74,7 @@ public abstract class ServerChunkCacheMixin_Tracker { final boolean spawnHostileMobs, final boolean spawnPeacefulMobs ) { - try (final PhaseContext<@NonNull ?> context = GenerationPhase.State.WORLD_SPAWNER_SPAWNING.createPhaseContext(PhaseTracker.SERVER) + try (final PhaseContext<@NonNull ?> context = GenerationPhase.State.WORLD_SPAWNER_SPAWNING.createPhaseContext(PhaseTracker.getWorldInstance(serverWorld)) .world(serverWorld)) { context.buildAndSwitch(); serverWorld.tickCustomSpawners(spawnHostileMobs, spawnPeacefulMobs); diff --git a/src/mixins/java/org/spongepowered/common/mixin/tracker/server/level/ServerLevelMixin_Tracker.java b/src/mixins/java/org/spongepowered/common/mixin/tracker/server/level/ServerLevelMixin_Tracker.java index e37bc495c69..cdb68aa0138 100644 --- a/src/mixins/java/org/spongepowered/common/mixin/tracker/server/level/ServerLevelMixin_Tracker.java +++ b/src/mixins/java/org/spongepowered/common/mixin/tracker/server/level/ServerLevelMixin_Tracker.java @@ -135,7 +135,7 @@ public abstract class ServerLevelMixin_Tracker extends LevelMixin_Tracker implem private void tracker$wrapNormalEntityTick(final ServerLevel level, final Consumer entityUpdateConsumer, final Entity entity ) { - final PhaseContext<@NonNull ?> currentState = PhaseTracker.SERVER.getPhaseContext(); + final PhaseContext<@NonNull ?> currentState = PhaseTracker.getWorldInstance((ServerLevel) (Object) this).getPhaseContext(); TrackingUtil.tickEntity(entityUpdateConsumer, entity); } @@ -204,7 +204,7 @@ public abstract class ServerLevelMixin_Tracker extends LevelMixin_Tracker implem ) ) private void tracker$startWeatherTickPhase(final LevelChunk param0, final int param1, final CallbackInfo ci) { - TickPhase.Tick.WEATHER.createPhaseContext(PhaseTracker.SERVER) + TickPhase.Tick.WEATHER.createPhaseContext(PhaseTracker.getWorldInstance((ServerLevel) (Object) this)) .buildAndSwitch(); } @@ -217,7 +217,7 @@ public abstract class ServerLevelMixin_Tracker extends LevelMixin_Tracker implem ) ) private void tracker$closeWeatherTickPhase(final LevelChunk param0, final int param1, final CallbackInfo ci) { - final PhaseContext<@NonNull ?> context = PhaseTracker.SERVER.getPhaseContext(); + final PhaseContext<@NonNull ?> context = PhaseTracker.getWorldInstance((ServerLevel) (Object) this).getPhaseContext(); if (context.getState() != TickPhase.Tick.WEATHER) { throw new IllegalStateException("Expected to be in a Weather ticking state, but we aren't."); } @@ -242,7 +242,7 @@ public abstract class ServerLevelMixin_Tracker extends LevelMixin_Tracker implem final ObjectLinkedOpenHashSet list, final Object data, final BlockPos pos, final Block blockIn, final int eventID, final int eventParam ) { - final PhaseContext<@NonNull ?> currentContext = PhaseTracker.getInstance().getPhaseContext(); + final PhaseContext<@NonNull ?> currentContext = PhaseTracker.getWorldInstance((ServerLevel) (Object) this).getPhaseContext(); final BlockEventData blockEventData = (BlockEventData) data; final TrackableBlockEventDataBridge blockEvent = (TrackableBlockEventDataBridge) (Object) blockEventData; // Short circuit phase states who do not track during block events @@ -323,7 +323,8 @@ public abstract class ServerLevelMixin_Tracker extends LevelMixin_Tracker implem final var explosionBuilder = org.spongepowered.api.world.explosion.Explosion.builder().from((org.spongepowered.api.world.explosion.Explosion) mcExplosion); Explosive apiExplosive = (Explosive) entity; - final var detonateEvent = SpongeEventFactory.createDetonateExplosiveEvent(PhaseTracker.getCauseStackManager().currentCause(), + final PhaseTracker phaseTracker = PhaseTracker.getWorldInstance((ServerLevel) (Object) this); + final var detonateEvent = SpongeEventFactory.createDetonateExplosiveEvent(phaseTracker.currentCause(), explosionBuilder, apiExplosive, (org.spongepowered.api.world.explosion.Explosion) instance); if (Sponge.eventManager().post(detonateEvent)) { this.tracker$cancelExplosionEffects(entity); @@ -340,7 +341,7 @@ public abstract class ServerLevelMixin_Tracker extends LevelMixin_Tracker implem if (ShouldFire.EXPLOSION_EVENT_PRE) { // Set up the pre event final ExplosionEvent.Pre event = - SpongeEventFactory.createExplosionEventPre(PhaseTracker.SERVER.currentCause(), apiExplosion, thisWorld); + SpongeEventFactory.createExplosionEventPre(phaseTracker.currentCause(), apiExplosion, thisWorld); if (SpongeCommon.post(event)) { this.tracker$cancelExplosionEffects(entity); return; @@ -358,7 +359,7 @@ public abstract class ServerLevelMixin_Tracker extends LevelMixin_Tracker implem } } - try (final PhaseContext<@NonNull ?> ctx = GeneralPhase.State.EXPLOSION.createPhaseContext(PhaseTracker.SERVER).explosion(mcExplosion) + try (final PhaseContext<@NonNull ?> ctx = GeneralPhase.State.EXPLOSION.createPhaseContext(phaseTracker).explosion(mcExplosion) .source(((Optional) apiExplosion.sourceExplosive()).orElse(this))) { ctx.buildAndSwitch(); @@ -404,8 +405,8 @@ public abstract class ServerLevelMixin_Tracker extends LevelMixin_Tracker implem if (this.bridge$isFake()) { return Optional.empty(); } - final PhaseTracker instance = PhaseTracker.getInstance(); - if (instance.getSidedThread() != PhaseTracker.SERVER.getSidedThread() && instance != PhaseTracker.SERVER) { + final PhaseTracker instance = PhaseTracker.getWorldInstance((ServerLevel) (Object) this); + if (!instance.onSidedThread()) { throw new UnsupportedOperationException("Cannot perform a tracked Block Change on a ServerWorld while not on the main thread!"); } final SpongeBlockChangeFlag spongeFlag = BlockChangeFlagManager.fromNativeInt(flags); @@ -466,8 +467,8 @@ public boolean setBlock(final BlockPos pos, final net.minecraft.world.level.bloc if (this.bridge$isFake()) { return super.setBlock(pos, newState, flags, limit); } - final PhaseTracker instance = PhaseTracker.getInstance(); - if (instance.getSidedThread() != PhaseTracker.SERVER.getSidedThread() && instance != PhaseTracker.SERVER) { + final PhaseTracker instance = PhaseTracker.getWorldInstance((ServerLevel) (Object) this); + if (!instance.onSidedThread()) { throw new UnsupportedOperationException("Cannot perform a tracked Block Change on a ServerWorld while not on the main thread!"); } final SpongeBlockChangeFlag spongeFlag = BlockChangeFlagManager.fromNativeInt(flags); @@ -499,8 +500,8 @@ public boolean destroyBlock(final BlockPos pos, final boolean doDrops, @Nullable if (this.bridge$isFake()) { return super.destroyBlock(pos, doDrops, p_241212_3_, limit); } - final PhaseTracker instance = PhaseTracker.getInstance(); - if (instance.getSidedThread() != PhaseTracker.SERVER.getSidedThread() && instance != PhaseTracker.SERVER) { + final PhaseTracker instance = PhaseTracker.getWorldInstance((ServerLevel) (Object) this); + if (!instance.onSidedThread()) { throw new UnsupportedOperationException("Cannot perform a tracked Block Change on a ServerWorld while not on the main thread!"); } final FluidState fluidstate = this.shadow$getFluidState(pos); @@ -592,7 +593,8 @@ public boolean destroyBlock(final BlockPos pos, final boolean doDrops, @Nullable if (tileentity == null) { return; } - if (this.bridge$isFake() || PhaseTracker.SERVER.getSidedThread() != Thread.currentThread()) { + final PhaseTracker phaseTracker = PhaseTracker.getWorldInstance((ServerLevel) (Object) this); + if (this.bridge$isFake() || !phaseTracker.onSidedThread()) { // If we're fake or not on the server thread, well, we could effectively call // out whoever is trying to remove tile entities asynchronously.... super.shadow$removeBlockEntity(immutable); @@ -601,7 +603,7 @@ public boolean destroyBlock(final BlockPos pos, final boolean doDrops, @Nullable // Otherwise, let's go on and check if we're recording transactions, // and if so, log the tile entity removal (may associate with an existing transaction, // or create a new transaction. - final PhaseContext<@NonNull ?> current = PhaseTracker.SERVER.getPhaseContext(); + final PhaseContext<@NonNull ?> current = phaseTracker.getPhaseContext(); if (current.getTransactor().logTileRemoval(tileentity, () -> (ServerLevel) (Object) this)) { final TileEntityPipeline pipeline = TileEntityPipeline.kickOff((ServerLevel) (Object) this, immutable) .addEffect(RemoveTileEntityFromChunkEffect.getInstance()) @@ -616,7 +618,8 @@ public boolean destroyBlock(final BlockPos pos, final boolean doDrops, @Nullable @Override public void shadow$setBlockEntity(final net.minecraft.world.level.block.entity.BlockEntity proposed) { final BlockPos immutable = proposed.getBlockPos().immutable(); - if (this.bridge$isFake() || PhaseTracker.SERVER.getSidedThread() != Thread.currentThread()) { + final PhaseTracker phaseTracker = PhaseTracker.getWorldInstance((ServerLevel) (Object) this); + if (this.bridge$isFake() || !phaseTracker.onSidedThread()) { // If we're fake or not on the server thread, well, we could effectively call // out whoever is trying to remove tile entities asynchronously.... super.shadow$setBlockEntity(proposed); @@ -630,7 +633,7 @@ public boolean destroyBlock(final BlockPos pos, final boolean doDrops, @Nullable // Otherwise, let's go on and check if we're recording transactions, // and if so, log the tile entity removal (may associate with an existing transaction, // or create a new transaction. - final PhaseContext<@NonNull ?> current = PhaseTracker.SERVER.getPhaseContext(); + final PhaseContext<@NonNull ?> current = phaseTracker.getPhaseContext(); if (current.doesBlockEventTracking()) { final net.minecraft.world.level.block.entity.@Nullable BlockEntity existing = this.shadow$getChunkAt(immutable).getBlockEntity(immutable); if (current.getTransactor().logTileReplacement(immutable, existing, proposed, () -> (ServerLevel) (Object) this)) { @@ -657,8 +660,8 @@ public boolean destroyBlock(final BlockPos pos, final boolean doDrops, @Nullable if (this.bridge$isFake()) { return; } - final PhaseTracker tracker = PhaseTracker.SERVER; - if (tracker.getSidedThread() != Thread.currentThread()) { + final PhaseTracker tracker = PhaseTracker.getWorldInstance((ServerLevel) (Object) this); + if (!tracker.onSidedThread()) { // TODO - async entity spawn logging return; } diff --git a/src/mixins/java/org/spongepowered/common/mixin/tracker/server/level/ServerPlayerGameModeMixin_Tracker.java b/src/mixins/java/org/spongepowered/common/mixin/tracker/server/level/ServerPlayerGameModeMixin_Tracker.java index 06fb1b321cc..1a01fd029a5 100644 --- a/src/mixins/java/org/spongepowered/common/mixin/tracker/server/level/ServerPlayerGameModeMixin_Tracker.java +++ b/src/mixins/java/org/spongepowered/common/mixin/tracker/server/level/ServerPlayerGameModeMixin_Tracker.java @@ -26,6 +26,7 @@ import net.minecraft.advancements.CriteriaTriggers; import net.minecraft.core.BlockPos; +import net.minecraft.server.level.ServerLevel; import net.minecraft.server.level.ServerPlayer; import net.minecraft.server.level.ServerPlayerGameMode; import net.minecraft.world.InteractionHand; @@ -112,6 +113,7 @@ public InteractionResult useItemOn(final ServerPlayer playerIn, final Level worl player.inventoryMenu.sendAllDataToRemote(); return InteractionResult.FAIL; } + final PhaseTracker phaseTracker = PhaseTracker.getWorldInstance((ServerLevel) worldIn); // Sponge end if (this.gameModeForPlayer == GameType.SPECTATOR) { final MenuProvider inamedcontainerprovider = blockstate.getMenuProvider(worldIn, blockpos); @@ -119,7 +121,7 @@ public InteractionResult useItemOn(final ServerPlayer playerIn, final Level worl playerIn.openMenu(inamedcontainerprovider); final Vector3i pos = VecHelper.toVector3i(blockRaytraceResultIn.getBlockPos()); final ServerLocation location = ServerLocation.of((ServerWorld) worldIn, pos); - try (final CauseStackManager.StackFrame frame = PhaseTracker.getCauseStackManager().pushCauseFrame()) { + try (final CauseStackManager.StackFrame frame = phaseTracker.pushCauseFrame()) { frame.pushCause(playerIn); frame.addContext(EventContextKeys.BLOCK_HIT, ((ServerWorld)(worldIn)).createSnapshot(pos)); ((ContainerBridge) playerIn.containerMenu).bridge$setOpenLocation(location); @@ -151,7 +153,7 @@ public InteractionResult useItemOn(final ServerPlayer playerIn, final Level worl if (lastOpenContainer != playerIn.containerMenu) { final Vector3i pos = VecHelper.toVector3i(blockRaytraceResultIn.getBlockPos()); final ServerLocation location = ServerLocation.of((ServerWorld) worldIn, pos); - try (final CauseStackManager.StackFrame frame = PhaseTracker.getCauseStackManager().pushCauseFrame()) { + try (final CauseStackManager.StackFrame frame = phaseTracker.pushCauseFrame()) { frame.pushCause(playerIn); frame.addContext(EventContextKeys.BLOCK_HIT, ((ServerWorld) (worldIn)).createSnapshot(pos)); ((ContainerBridge) playerIn.containerMenu).bridge$setOpenLocation(location); @@ -184,7 +186,7 @@ public InteractionResult useItemOn(final ServerPlayer playerIn, final Level worl } else { result = stackIn.useOn(itemusecontext); // Sponge start - log change in hand - final PhaseContext<@NonNull ?> context = PhaseTracker.SERVER.getPhaseContext(); + final PhaseContext<@NonNull ?> context = phaseTracker.getPhaseContext(); final TransactionalCaptureSupplier transactor = context.getTransactor(); if (!transactor.isEmpty()) { //TODO: Add effect to attach the transaction to be the child of the parents try (final EffectTransactor ignored = context.getTransactor().pushEffect(new ResultingTransactionBySideEffect(InventoryEffect.getInstance()))) { diff --git a/src/mixins/java/org/spongepowered/common/mixin/tracker/server/network/ServerGamePacketListenerImplMixin_Tracker.java b/src/mixins/java/org/spongepowered/common/mixin/tracker/server/network/ServerGamePacketListenerImplMixin_Tracker.java index 5a3e28c562c..2fb2e423001 100644 --- a/src/mixins/java/org/spongepowered/common/mixin/tracker/server/network/ServerGamePacketListenerImplMixin_Tracker.java +++ b/src/mixins/java/org/spongepowered/common/mixin/tracker/server/network/ServerGamePacketListenerImplMixin_Tracker.java @@ -61,7 +61,7 @@ public abstract class ServerGamePacketListenerImplMixin_Tracker { player.doTick(); return; } - try (final PlayerTickContext context = TickPhase.Tick.PLAYER.createPhaseContext(PhaseTracker.SERVER).source(player)) { + try (final PlayerTickContext context = TickPhase.Tick.PLAYER.createPhaseContext(PhaseTracker.getWorldInstance(this.player.serverLevel())).source(player)) { context.buildAndSwitch(); PhaseTracker.LOGGER.trace(TrackingUtil.PLAYER_TICK, () -> "Wrapping Player Tick: " + player.toString()); player.doTick(); diff --git a/src/mixins/java/org/spongepowered/common/mixin/tracker/server/players/PlayerListMixin_Tracker.java b/src/mixins/java/org/spongepowered/common/mixin/tracker/server/players/PlayerListMixin_Tracker.java index a552b3ff9de..06b0b047334 100644 --- a/src/mixins/java/org/spongepowered/common/mixin/tracker/server/players/PlayerListMixin_Tracker.java +++ b/src/mixins/java/org/spongepowered/common/mixin/tracker/server/players/PlayerListMixin_Tracker.java @@ -47,7 +47,7 @@ public class PlayerListMixin_Tracker { final Entity.RemovalReason reason ) { try (final GeneralizedContext context = PlayerPhase.State.PLAYER_LOGOUT - .createPhaseContext(PhaseTracker.SERVER) + .createPhaseContext(PhaseTracker.getWorldInstance(world)) .source(player)) { context.buildAndSwitch(); world.removePlayerImmediately(player, reason); @@ -57,7 +57,7 @@ public class PlayerListMixin_Tracker { @Redirect(method = "placeNewPlayer", at = @At(value = "INVOKE", target = "Lnet/minecraft/server/level/ServerPlayer;initInventoryMenu()V")) private void tracker$onPlaceNewPlayerInitMenu(final ServerPlayer player) { - try (final PhaseContext context = BlockPhase.State.RESTORING_BLOCKS.createPhaseContext(PhaseTracker.SERVER).source(player);) { + try (final PhaseContext context = BlockPhase.State.RESTORING_BLOCKS.createPhaseContext(PhaseTracker.getWorldInstance(player.serverLevel())).source(player);) { context.buildAndSwitch(); player.initInventoryMenu(); } @@ -66,7 +66,7 @@ public class PlayerListMixin_Tracker { @Redirect(method = "respawn", at = @At(value = "INVOKE", target = "Lnet/minecraft/server/level/ServerPlayer;initInventoryMenu()V")) private void tracker$onRespawnInitMenu(final ServerPlayer player) { - try (final PhaseContext context = BlockPhase.State.RESTORING_BLOCKS.createPhaseContext(PhaseTracker.SERVER).source(player);) { + try (final PhaseContext context = BlockPhase.State.RESTORING_BLOCKS.createPhaseContext(PhaseTracker.getWorldInstance(player.serverLevel())).source(player);) { context.buildAndSwitch(); player.initInventoryMenu(); } diff --git a/src/mixins/java/org/spongepowered/common/mixin/tracker/world/entity/EntityMixin_Tracker.java b/src/mixins/java/org/spongepowered/common/mixin/tracker/world/entity/EntityMixin_Tracker.java index 4647439094d..96005a33810 100644 --- a/src/mixins/java/org/spongepowered/common/mixin/tracker/world/entity/EntityMixin_Tracker.java +++ b/src/mixins/java/org/spongepowered/common/mixin/tracker/world/entity/EntityMixin_Tracker.java @@ -94,11 +94,11 @@ public abstract class EntityMixin_Tracker implements DelegatingConfigTrackableBr ) private void tracker$logEntityDropTransactionIfNecessary(final ServerLevel level, final ItemStack stack, final float offsetY, final CallbackInfoReturnable cir) { - final PhaseTracker instance = PhaseTracker.SERVER; - if (!instance.onSidedThread()) { + if (((LevelBridge) level).bridge$isFake()) { return; } - if (((LevelBridge) level).bridge$isFake()) { + final PhaseTracker instance = PhaseTracker.getWorldInstance(level); + if (!instance.onSidedThread()) { return; } final PhaseContext<@NonNull ?> context = instance.getPhaseContext(); @@ -112,11 +112,11 @@ public abstract class EntityMixin_Tracker implements DelegatingConfigTrackableBr @Inject(method = "setRemoved(Lnet/minecraft/world/entity/Entity$RemovalReason;)V", at = @At("RETURN")) private void tracker$ensureDropEffectCompleted(final Entity.RemovalReason reason, final CallbackInfo ci) { - final PhaseTracker instance = PhaseTracker.SERVER; - if (!instance.onSidedThread()) { + if (((LevelBridge) this.shadow$level()).bridge$isFake()) { return; } - if (((LevelBridge) this.shadow$level()).bridge$isFake()) { + final PhaseTracker instance = PhaseTracker.getWorldInstance((ServerLevel) this.shadow$level()); + if (!instance.onSidedThread()) { return; } final PhaseContext<@NonNull ?> context = instance.getPhaseContext(); diff --git a/src/mixins/java/org/spongepowered/common/mixin/tracker/world/entity/LivingEntityMixin_Tracker.java b/src/mixins/java/org/spongepowered/common/mixin/tracker/world/entity/LivingEntityMixin_Tracker.java index 43ffb8ba24c..cfaee3f54c7 100644 --- a/src/mixins/java/org/spongepowered/common/mixin/tracker/world/entity/LivingEntityMixin_Tracker.java +++ b/src/mixins/java/org/spongepowered/common/mixin/tracker/world/entity/LivingEntityMixin_Tracker.java @@ -24,6 +24,7 @@ */ package org.spongepowered.common.mixin.tracker.world.entity; +import net.minecraft.server.level.ServerLevel; import net.minecraft.world.damagesource.CombatEntry; import net.minecraft.world.damagesource.CombatTracker; import net.minecraft.world.damagesource.DamageSource; @@ -96,12 +97,12 @@ public abstract class LivingEntityMixin_Tracker extends EntityMixin_Tracker { at = @At(value = "INVOKE", target = "Lnet/minecraft/world/entity/LivingEntity;tickDeath()V")) private void tracker$enterDeathPhase(final LivingEntity livingEntity) { - final PhaseTracker instance = PhaseTracker.SERVER; - if (!instance.onSidedThread()) { + if (((LevelBridge) this.shadow$level()).bridge$isFake()) { this.shadow$tickDeath(); return; } - if (((LevelBridge) this.shadow$level()).bridge$isFake()) { + final PhaseTracker instance = PhaseTracker.getWorldInstance((ServerLevel) livingEntity.level()); + if (!instance.onSidedThread()) { this.shadow$tickDeath(); return; } @@ -127,11 +128,11 @@ public abstract class LivingEntityMixin_Tracker extends EntityMixin_Tracker { ) private void tracker$wrapOnDeathWithState(final LivingEntity thisEntity, final DamageSource cause) { // Sponge Start - notify the cause tracker - final PhaseTracker instance = PhaseTracker.SERVER; - if (!instance.onSidedThread()) { + if (((LevelBridge) this.shadow$level()).bridge$isFake()) { return; } - if (((LevelBridge) this.shadow$level()).bridge$isFake()) { + final PhaseTracker instance = PhaseTracker.getWorldInstance((ServerLevel) thisEntity.level()); + if (!instance.onSidedThread()) { return; } final PhaseContext<@NonNull ?> context = instance.getPhaseContext(); @@ -156,7 +157,7 @@ public abstract class LivingEntityMixin_Tracker extends EntityMixin_Tracker { return; } try (final PhaseContext<@NonNull ?> context = EntityPhase.State.COLLISION - .createPhaseContext(PhaseTracker.SERVER) + .createPhaseContext(PhaseTracker.getWorldInstance((ServerLevel) livingEntity.level())) .source(livingEntity) ) { context.buildAndSwitch(); diff --git a/src/mixins/java/org/spongepowered/common/mixin/tracker/world/item/BoneMealItemMixin_Tracker.java b/src/mixins/java/org/spongepowered/common/mixin/tracker/world/item/BoneMealItemMixin_Tracker.java index c38e4b355d1..14f8d2e9bde 100644 --- a/src/mixins/java/org/spongepowered/common/mixin/tracker/world/item/BoneMealItemMixin_Tracker.java +++ b/src/mixins/java/org/spongepowered/common/mixin/tracker/world/item/BoneMealItemMixin_Tracker.java @@ -79,11 +79,12 @@ public abstract class BoneMealItemMixin_Tracker { return; } - final PhaseContext<@NonNull ?> current = PhaseTracker.getInstance().getPhaseContext(); + final PhaseTracker phaseTracker = PhaseTracker.getWorldInstance(worldIn); + final PhaseContext<@NonNull ?> current = phaseTracker.getPhaseContext(); final boolean doesEvent = current.doesBlockEventTracking(); if (doesEvent) { // We can enter the new phase state. - try (final GrowablePhaseContext context = BlockPhase.State.GROWING.createPhaseContext(PhaseTracker.SERVER) + try (final GrowablePhaseContext context = BlockPhase.State.GROWING.createPhaseContext(phaseTracker) .provideItem(stack) .world(worldIn) .block(state) diff --git a/src/mixins/java/org/spongepowered/common/mixin/tracker/world/item/ItemStackMixin_Tracker.java b/src/mixins/java/org/spongepowered/common/mixin/tracker/world/item/ItemStackMixin_Tracker.java index 71009642869..f981aa4e7fb 100644 --- a/src/mixins/java/org/spongepowered/common/mixin/tracker/world/item/ItemStackMixin_Tracker.java +++ b/src/mixins/java/org/spongepowered/common/mixin/tracker/world/item/ItemStackMixin_Tracker.java @@ -25,6 +25,7 @@ package org.spongepowered.common.mixin.tracker.world.item; import net.minecraft.core.BlockPos; +import net.minecraft.server.level.ServerLevel; import net.minecraft.server.level.ServerPlayer; import net.minecraft.world.entity.LivingEntity; import net.minecraft.world.entity.player.Player; @@ -55,7 +56,7 @@ public abstract class ItemStackMixin_Tracker { final LivingEntity player, final Level levelIn, final BlockState stateIn, final BlockPos posIn, final Player playerIn ) { final boolean isServerLevel = !((LevelBridge) level).bridge$isFake(); - final PhaseContext<@NonNull ?> context = isServerLevel ? PhaseTracker.SERVER.getPhaseContext() : null; + final PhaseContext<@NonNull ?> context = isServerLevel ? PhaseTracker.getWorldInstance((ServerLevel) level).getPhaseContext() : null; try { if (isServerLevel) { context.capturePlayerUsingStackToBreakBlock((ServerPlayer) playerIn); diff --git a/src/mixins/java/org/spongepowered/common/mixin/tracker/world/level/block/BlockMixin_Tracker.java b/src/mixins/java/org/spongepowered/common/mixin/tracker/world/level/block/BlockMixin_Tracker.java index 093ad2e886a..1041962e966 100644 --- a/src/mixins/java/org/spongepowered/common/mixin/tracker/world/level/block/BlockMixin_Tracker.java +++ b/src/mixins/java/org/spongepowered/common/mixin/tracker/world/level/block/BlockMixin_Tracker.java @@ -27,6 +27,7 @@ import net.minecraft.core.BlockPos; import net.minecraft.core.Registry; import net.minecraft.core.registries.BuiltInRegistries; +import net.minecraft.server.level.ServerLevel; import net.minecraft.world.entity.Entity; import net.minecraft.world.item.ItemStack; import net.minecraft.world.level.Level; @@ -73,19 +74,43 @@ public abstract class BlockMixin_Tracker implements TrackableBlockBridge, Regist * @param ci The callback info */ @Inject( - method = { - "dropResources(Lnet/minecraft/world/level/block/state/BlockState;Lnet/minecraft/world/level/Level;Lnet/minecraft/core/BlockPos;)V", - "dropResources(Lnet/minecraft/world/level/block/state/BlockState;Lnet/minecraft/world/level/LevelAccessor;Lnet/minecraft/core/BlockPos;Lnet/minecraft/world/level/block/entity/BlockEntity;)V", - "dropResources(Lnet/minecraft/world/level/block/state/BlockState;Lnet/minecraft/world/level/Level;Lnet/minecraft/core/BlockPos;Lnet/minecraft/world/level/block/entity/BlockEntity;Lnet/minecraft/world/entity/Entity;Lnet/minecraft/world/item/ItemStack;)V" - }, + method = "dropResources(Lnet/minecraft/world/level/block/state/BlockState;Lnet/minecraft/world/level/Level;Lnet/minecraft/core/BlockPos;)V", + at = @At("HEAD"), + cancellable = true + ) + private static void tracker$cancelOnBlockRestoration(final BlockState state, final Level worldIn, + final BlockPos pos, final CallbackInfo ci) { + final PhaseTracker phaseTracker = PhaseTracker.getWorldInstance((ServerLevel) worldIn); + if (phaseTracker.onSidedThread() && phaseTracker.getPhaseContext().isRestoring()) { + ci.cancel(); + } + } + + @Inject( + method = "dropResources(Lnet/minecraft/world/level/block/state/BlockState;Lnet/minecraft/world/level/LevelAccessor;Lnet/minecraft/core/BlockPos;Lnet/minecraft/world/level/block/entity/BlockEntity;)V", at = @At("HEAD"), cancellable = true ) - private static void tracker$cancelOnBlockRestoration(final CallbackInfo ci) { - if (Thread.currentThread() == PhaseTracker.SERVER.getSidedThread()) { - if (PhaseTracker.SERVER.getPhaseContext().isRestoring()) { - ci.cancel(); - } + private static void tracker$cancelOnBlockRestoration( + final BlockState state, final LevelAccessor worldIn, + final BlockPos pos, final @Nullable BlockEntity tileEntity, final CallbackInfo ci) { + final PhaseTracker phaseTracker = PhaseTracker.getWorldInstance((ServerLevel) worldIn); + if (phaseTracker.onSidedThread() && phaseTracker.getPhaseContext().isRestoring()) { + ci.cancel(); + } + } + + @Inject( + method = "dropResources(Lnet/minecraft/world/level/block/state/BlockState;Lnet/minecraft/world/level/Level;Lnet/minecraft/core/BlockPos;Lnet/minecraft/world/level/block/entity/BlockEntity;Lnet/minecraft/world/entity/Entity;Lnet/minecraft/world/item/ItemStack;)V", + at = @At("HEAD"), + cancellable = true + ) + private static void tracker$cancelOnBlockRestoration(final BlockState state, final Level worldIn, + final BlockPos pos, final @Nullable BlockEntity tileEntity, final Entity entity, final ItemStack itemStack, + final CallbackInfo ci) { + final PhaseTracker phaseTracker = PhaseTracker.getWorldInstance((ServerLevel) worldIn); + if (phaseTracker.onSidedThread() && phaseTracker.getPhaseContext().isRestoring()) { + ci.cancel(); } } @@ -95,11 +120,11 @@ public abstract class BlockMixin_Tracker implements TrackableBlockBridge, Regist ) private static void tracker$captureBlockProposedToBeSpawningDrops(final BlockState state, final Level worldIn, final BlockPos pos, final CallbackInfo ci) { - final PhaseTracker server = PhaseTracker.SERVER; - if (server.getSidedThread() != Thread.currentThread()) { + final PhaseTracker phaseTracker = PhaseTracker.getWorldInstance((ServerLevel) worldIn); + if (!phaseTracker.onSidedThread()) { return; } - final PhaseContext<@NonNull ?> context = server.getPhaseContext(); + final PhaseContext<@NonNull ?> context = phaseTracker.getPhaseContext(); BlockMixin_Tracker.tracker$effectTransactorForDrops = context.getTransactor() .logBlockDrops(worldIn, pos, state, null); } @@ -115,11 +140,11 @@ public abstract class BlockMixin_Tracker implements TrackableBlockBridge, Regist if (!(worldIn instanceof Level)) { return; // In the name of my father, and his father before him, I cast you out! } - final PhaseTracker server = PhaseTracker.SERVER; - if (server.getSidedThread() != Thread.currentThread()) { + final PhaseTracker phaseTracker = PhaseTracker.getWorldInstance((ServerLevel) worldIn); + if (!phaseTracker.onSidedThread()) { return; } - final PhaseContext<@NonNull ?> context = server.getPhaseContext(); + final PhaseContext<@NonNull ?> context = phaseTracker.getPhaseContext(); BlockMixin_Tracker.tracker$effectTransactorForDrops = context.getTransactor() .logBlockDrops((Level) worldIn, pos, state, tileEntity); } @@ -131,30 +156,60 @@ public abstract class BlockMixin_Tracker implements TrackableBlockBridge, Regist private static void tracker$captureBlockProposedToBeSpawningDrops(final BlockState state, final Level worldIn, final BlockPos pos, final @Nullable BlockEntity tileEntity, final Entity entity, final ItemStack itemStack, final CallbackInfo ci) { - final PhaseTracker server = PhaseTracker.SERVER; - if (server.getSidedThread() != Thread.currentThread()) { + final PhaseTracker phaseTracker = PhaseTracker.getWorldInstance((ServerLevel) worldIn); + if (!phaseTracker.onSidedThread()) { return; } - final PhaseContext<@NonNull ?> context = server.getPhaseContext(); + final PhaseContext<@NonNull ?> context = phaseTracker.getPhaseContext(); BlockMixin_Tracker.tracker$effectTransactorForDrops = context.getTransactor() .logBlockDrops(worldIn, pos, state, tileEntity); } @Inject( - method = { - "dropResources(Lnet/minecraft/world/level/block/state/BlockState;Lnet/minecraft/world/level/Level;Lnet/minecraft/core/BlockPos;)V", - "dropResources(Lnet/minecraft/world/level/block/state/BlockState;Lnet/minecraft/world/level/LevelAccessor;Lnet/minecraft/core/BlockPos;Lnet/minecraft/world/level/block/entity/BlockEntity;)V", - "dropResources(Lnet/minecraft/world/level/block/state/BlockState;Lnet/minecraft/world/level/Level;Lnet/minecraft/core/BlockPos;Lnet/minecraft/world/level/block/entity/BlockEntity;Lnet/minecraft/world/entity/Entity;Lnet/minecraft/world/item/ItemStack;)V" - }, + method = "dropResources(Lnet/minecraft/world/level/block/state/BlockState;Lnet/minecraft/world/level/Level;Lnet/minecraft/core/BlockPos;)V", + at = @At("TAIL") + ) + private static void tracker$closeEffectIfCapturing(final BlockState state, final Level worldIn, + final BlockPos pos, final CallbackInfo ci) { + final PhaseTracker phaseTracker = PhaseTracker.getWorldInstance((ServerLevel) worldIn); + if (!phaseTracker.onSidedThread()) { + return; + } + final PhaseContext<@NonNull ?> context = phaseTracker.getPhaseContext(); + context.getTransactor().completeBlockDrops(BlockMixin_Tracker.tracker$effectTransactorForDrops); + BlockMixin_Tracker.tracker$effectTransactorForDrops = null; + } + + @Inject( + method = "dropResources(Lnet/minecraft/world/level/block/state/BlockState;Lnet/minecraft/world/level/LevelAccessor;Lnet/minecraft/core/BlockPos;Lnet/minecraft/world/level/block/entity/BlockEntity;)V", + at = @At("TAIL") + ) + private static void tracker$closeEffectIfCapturing( + final BlockState state, final LevelAccessor worldIn, final BlockPos pos, + final @Nullable BlockEntity tileEntity, final CallbackInfo ci + ) { + final PhaseTracker phaseTracker = PhaseTracker.getWorldInstance((ServerLevel) worldIn); + if (!phaseTracker.onSidedThread()) { + return; + } + final PhaseContext<@NonNull ?> context = phaseTracker.getPhaseContext(); + context.getTransactor().completeBlockDrops(BlockMixin_Tracker.tracker$effectTransactorForDrops); + BlockMixin_Tracker.tracker$effectTransactorForDrops = null; + } + + @Inject( + method = "dropResources(Lnet/minecraft/world/level/block/state/BlockState;Lnet/minecraft/world/level/Level;Lnet/minecraft/core/BlockPos;Lnet/minecraft/world/level/block/entity/BlockEntity;Lnet/minecraft/world/entity/Entity;Lnet/minecraft/world/item/ItemStack;)V", at = @At("TAIL") ) - private static void tracker$closeEffectIfCapturing(final CallbackInfo ci) { - final PhaseTracker server = PhaseTracker.SERVER; - if (server.getSidedThread() != Thread.currentThread()) { + private static void tracker$closeEffectIfCapturing(final BlockState state, final Level worldIn, + final BlockPos pos, final @Nullable BlockEntity tileEntity, final Entity entity, final ItemStack itemStack, + final CallbackInfo ci) { + final PhaseTracker phaseTracker = PhaseTracker.getWorldInstance((ServerLevel) worldIn); + if (!phaseTracker.onSidedThread()) { return; } - final PhaseContext<@NonNull ?> context = server.getPhaseContext(); + final PhaseContext<@NonNull ?> context = phaseTracker.getPhaseContext(); context.getTransactor().completeBlockDrops(BlockMixin_Tracker.tracker$effectTransactorForDrops); BlockMixin_Tracker.tracker$effectTransactorForDrops = null; } diff --git a/src/mixins/java/org/spongepowered/common/mixin/tracker/world/level/block/DispenserBlockMixin_Tracker.java b/src/mixins/java/org/spongepowered/common/mixin/tracker/world/level/block/DispenserBlockMixin_Tracker.java index 1efbbc0112a..b3174cc508d 100644 --- a/src/mixins/java/org/spongepowered/common/mixin/tracker/world/level/block/DispenserBlockMixin_Tracker.java +++ b/src/mixins/java/org/spongepowered/common/mixin/tracker/world/level/block/DispenserBlockMixin_Tracker.java @@ -67,7 +67,7 @@ public abstract class DispenserBlockMixin_Tracker { private void tracker$createContextOnDispensing(final ServerLevel worldIn, final BlockState state, final BlockPos pos, final CallbackInfo ci) { final SpongeBlockSnapshot spongeBlockSnapshot = ((TrackedWorldBridge) worldIn).bridge$createSnapshot(state, pos, BlockChangeFlags.ALL); final LevelChunkBridge mixinChunk = (LevelChunkBridge) worldIn.getChunkAt(pos); - this.tracker$context = BlockPhase.State.DISPENSE.createPhaseContext(PhaseTracker.SERVER) + this.tracker$context = BlockPhase.State.DISPENSE.createPhaseContext(PhaseTracker.getWorldInstance(worldIn)) .source(spongeBlockSnapshot) .creator(() -> mixinChunk.bridge$getBlockCreatorUUID(pos)) .notifier(() -> mixinChunk.bridge$getBlockNotifierUUID(pos)) diff --git a/src/mixins/java/org/spongepowered/common/mixin/tracker/world/level/block/LeavesBlockMixin_Tracker.java b/src/mixins/java/org/spongepowered/common/mixin/tracker/world/level/block/LeavesBlockMixin_Tracker.java index bf8920550a0..7490c140490 100644 --- a/src/mixins/java/org/spongepowered/common/mixin/tracker/world/level/block/LeavesBlockMixin_Tracker.java +++ b/src/mixins/java/org/spongepowered/common/mixin/tracker/world/level/block/LeavesBlockMixin_Tracker.java @@ -90,7 +90,7 @@ public void randomTick(final net.minecraft.world.level.block.state.BlockState st if (this.shadow$decaying(state)) { // Sponge Start - PhaseTracker checks and phase entry if (!((LevelBridge) worldIn).bridge$isFake()) { - try (final PhaseContext<@NonNull ?> context = BlockPhase.State.BLOCK_DECAY.createPhaseContext(PhaseTracker.SERVER) + try (final PhaseContext<@NonNull ?> context = BlockPhase.State.BLOCK_DECAY.createPhaseContext(PhaseTracker.getWorldInstance(worldIn)) .source(new SpongeLocatableBlockBuilder() .world((ServerWorld) worldIn) .position(pos.getX(), pos.getY(), pos.getZ()) diff --git a/src/mixins/java/org/spongepowered/common/mixin/tracker/world/level/block/SaplingBlockMixin_Tracker.java b/src/mixins/java/org/spongepowered/common/mixin/tracker/world/level/block/SaplingBlockMixin_Tracker.java index f2bf8151a03..605c5f04a62 100644 --- a/src/mixins/java/org/spongepowered/common/mixin/tracker/world/level/block/SaplingBlockMixin_Tracker.java +++ b/src/mixins/java/org/spongepowered/common/mixin/tracker/world/level/block/SaplingBlockMixin_Tracker.java @@ -57,11 +57,12 @@ public class SaplingBlockMixin_Tracker { return instance.growTree(level, generator, pos, state, random); } - if (PhaseTracker.getInstance().getPhaseContext() instanceof GrowablePhaseContext) { + final PhaseTracker phaseTracker = PhaseTracker.getWorldInstance(level); + if (phaseTracker.getPhaseContext() instanceof GrowablePhaseContext) { instance.growTree(level, generator, pos, state, random); - } else if (PhaseTracker.getInstance().getPhaseContext().doesBlockEventTracking()) { + } else if (phaseTracker.getPhaseContext().doesBlockEventTracking()) { // We can enter the new phase state. - try (GrowablePhaseContext context = BlockPhase.State.GROWING.createPhaseContext(PhaseTracker.SERVER) + try (GrowablePhaseContext context = BlockPhase.State.GROWING.createPhaseContext(phaseTracker) .world(level) .block(state) .pos(pos)) { diff --git a/src/mixins/java/org/spongepowered/common/mixin/tracker/world/level/chunk/LevelChunkMixin_Tracker.java b/src/mixins/java/org/spongepowered/common/mixin/tracker/world/level/chunk/LevelChunkMixin_Tracker.java index 1aa4d23ee8a..266ada0ee0e 100644 --- a/src/mixins/java/org/spongepowered/common/mixin/tracker/world/level/chunk/LevelChunkMixin_Tracker.java +++ b/src/mixins/java/org/spongepowered/common/mixin/tracker/world/level/chunk/LevelChunkMixin_Tracker.java @@ -130,7 +130,7 @@ public abstract class LevelChunkMixin_Tracker extends ChunkAccessMixin_Tracker i } // Sponge Start - Build out the BlockTransaction - final PhaseContext<@NonNull ?> context = PhaseTracker.getInstance().getPhaseContext(); + final PhaseContext<@NonNull ?> context = PhaseTracker.getWorldInstance((ServerLevel) this.level).getPhaseContext(); final @Nullable BlockEntity existing = this.shadow$getBlockEntity(pos, LevelChunk.EntityCreationType.CHECK); // Build a transaction maybe? final WeakReference ref = new WeakReference<>((ServerLevel) this.level); @@ -165,11 +165,12 @@ public abstract class LevelChunkMixin_Tracker extends ChunkAccessMixin_Tracker i @Inject(method = "postProcessGeneration", at = @At("HEAD")) private void tracker$startChunkPostProcess(final CallbackInfo ci) { + final PhaseTracker phaseTracker = PhaseTracker.getWorldInstance((ServerLevel) this.level); if (this.tracker$postProcessContext != null) { - PhasePrinter.printMessageWithCaughtException(PhaseTracker.SERVER, "Expected to not have a chunk post process", "Chunk Post Process has not completed!", GenerationPhase.State.CHUNK_LOADING, this.tracker$postProcessContext, new NullPointerException("spongecommon.ChunkMixin_Tracker:tracker$postProcessContext is Null")); + PhasePrinter.printMessageWithCaughtException(phaseTracker, "Expected to not have a chunk post process", "Chunk Post Process has not completed!", GenerationPhase.State.CHUNK_LOADING, this.tracker$postProcessContext, new NullPointerException("spongecommon.ChunkMixin_Tracker:tracker$postProcessContext is Null")); this.tracker$postProcessContext.close(); } - this.tracker$postProcessContext = GenerationPhase.State.CHUNK_LOADING.createPhaseContext(PhaseTracker.SERVER) + this.tracker$postProcessContext = GenerationPhase.State.CHUNK_LOADING.createPhaseContext(phaseTracker) .chunk((LevelChunk) (Object) this) .world((ServerLevel) this.level) .buildAndSwitch(); @@ -205,10 +206,11 @@ public abstract class LevelChunkMixin_Tracker extends ChunkAccessMixin_Tracker i @SuppressWarnings({"rawtypes", "unchecked"}) @Redirect(method = "unpackTicks", at = @At(value = "INVOKE", target = "Lnet/minecraft/world/ticks/LevelChunkTicks;unpack(J)V")) private void tracker$wrapRescheduledTicks(final LevelChunkTicks instance, final long $$0) { - if (!PhaseTracker.SERVER.onSidedThread()) { + final PhaseTracker phaseTracker = PhaseTracker.getWorldInstance((ServerLevel) this.level); + if (!phaseTracker.onSidedThread()) { return; } - try (final ChunkLoadContext context = GenerationPhase.State.CHUNK_LOADING.createPhaseContext(PhaseTracker.SERVER)) { + try (final ChunkLoadContext context = GenerationPhase.State.CHUNK_LOADING.createPhaseContext(phaseTracker)) { context.chunk((LevelChunk) (Object) this); context.buildAndSwitch(); instance.unpack($$0); diff --git a/src/mixins/java/org/spongepowered/common/mixin/tracker/world/level/dimension/end/EndDragonFightMixin_Tracker.java b/src/mixins/java/org/spongepowered/common/mixin/tracker/world/level/dimension/end/EndDragonFightMixin_Tracker.java index b0ebcce7ac3..de559780be2 100644 --- a/src/mixins/java/org/spongepowered/common/mixin/tracker/world/level/dimension/end/EndDragonFightMixin_Tracker.java +++ b/src/mixins/java/org/spongepowered/common/mixin/tracker/world/level/dimension/end/EndDragonFightMixin_Tracker.java @@ -34,6 +34,7 @@ import net.minecraft.world.level.dimension.end.DragonRespawnAnimation; import net.minecraft.world.level.dimension.end.EndDragonFight; import net.minecraft.world.level.levelgen.feature.ConfiguredFeature; +import org.spongepowered.asm.mixin.Final; import org.spongepowered.asm.mixin.Mixin; import org.spongepowered.asm.mixin.Shadow; import org.spongepowered.asm.mixin.injection.At; @@ -50,6 +51,8 @@ public abstract class EndDragonFightMixin_Tracker { // @formatter:off + @Shadow @Final private ServerLevel level; + @Shadow protected abstract EnderDragon shadow$createNewDragon(); // @formatter:on @@ -59,7 +62,7 @@ public abstract class EndDragonFightMixin_Tracker { final RandomSource rand, final BlockPos pos ) { - try (final FeaturePhaseContext context = GenerationPhase.State.FEATURE_PLACEMENT.createPhaseContext(PhaseTracker.SERVER)) { + try (final FeaturePhaseContext context = GenerationPhase.State.FEATURE_PLACEMENT.createPhaseContext(PhaseTracker.getWorldInstance(worldIn.getLevel()))) { context .world((ServerLevel) worldIn) .generator(generator) @@ -75,7 +78,7 @@ public abstract class EndDragonFightMixin_Tracker { @Redirect(method = "tick()V", at = @At(value = "INVOKE", target = "Lnet/minecraft/world/level/dimension/end/DragonRespawnAnimation;tick(Lnet/minecraft/server/level/ServerLevel;Lnet/minecraft/world/level/dimension/end/EndDragonFight;Ljava/util/List;ILnet/minecraft/core/BlockPos;)V")) private void tracker$switchToSpawnDragonState(final DragonRespawnAnimation dragonSpawnState, final ServerLevel worldIn, final EndDragonFight manager, final List crystals, int respawnStateTicks, final BlockPos exitPortalLocation) { - try (final SpawnDragonContext context = DragonPhase.State.SPAWN_DRAGON.createPhaseContext(PhaseTracker.SERVER)) { + try (final SpawnDragonContext context = DragonPhase.State.SPAWN_DRAGON.createPhaseContext(PhaseTracker.getWorldInstance(worldIn))) { context .manager(manager) .setIsRespawn(true) @@ -88,7 +91,7 @@ public abstract class EndDragonFightMixin_Tracker { @Redirect(method = "findOrCreateDragon", at = @At(value = "INVOKE", target = "Lnet/minecraft/world/level/dimension/end/EndDragonFight;createNewDragon()Lnet/minecraft/world/entity/boss/enderdragon/EnderDragon;")) private EnderDragon tracker$switchToSpawnDragonState(final EndDragonFight manager) { - try (final SpawnDragonContext context = DragonPhase.State.SPAWN_DRAGON.createPhaseContext(PhaseTracker.SERVER)) { + try (final SpawnDragonContext context = DragonPhase.State.SPAWN_DRAGON.createPhaseContext(PhaseTracker.getWorldInstance(this.level))) { context .manager(manager) .setIsRespawn(false) diff --git a/src/mixins/java/org/spongepowered/common/mixin/tracker/world/level/redstone/NeighborUpdaterMixin_Tracker.java b/src/mixins/java/org/spongepowered/common/mixin/tracker/world/level/redstone/NeighborUpdaterMixin_Tracker.java index 05776e94678..f34827ef39d 100644 --- a/src/mixins/java/org/spongepowered/common/mixin/tracker/world/level/redstone/NeighborUpdaterMixin_Tracker.java +++ b/src/mixins/java/org/spongepowered/common/mixin/tracker/world/level/redstone/NeighborUpdaterMixin_Tracker.java @@ -58,11 +58,11 @@ public interface NeighborUpdaterMixin_Tracker { )) private static void tracker$wrapNeighborUpdateInSideEffect(Level level, BlockState targetState, BlockPos targetPos, Block fromBlock, @Nullable Orientation orientation, boolean movement, CallbackInfo ci) { // Sponge start - prepare notification - final PhaseContext<@NonNull ?> peek = PhaseTracker.getInstance().getPhaseContext(); if (!(level instanceof ServerLevel serverLevel)) { return; } + final PhaseContext<@NonNull ?> peek = PhaseTracker.getWorldInstance(serverLevel).getPhaseContext(); final var targetChunk = serverLevel.getChunkAt(targetPos); final Supplier worldSupplier = VolumeStreamUtils.createWeaklyReferencedSupplier(serverLevel, "ServerWorld"); final net.minecraft.world.level.block.entity.@Nullable BlockEntity existingTile = targetChunk.getBlockEntity( diff --git a/src/mixins/java/org/spongepowered/common/mixin/tracker/world/ticks/LevelTicksMixin_Tracker.java b/src/mixins/java/org/spongepowered/common/mixin/tracker/world/ticks/LevelTicksMixin_Tracker.java index 8b878f94796..e37721c2337 100644 --- a/src/mixins/java/org/spongepowered/common/mixin/tracker/world/ticks/LevelTicksMixin_Tracker.java +++ b/src/mixins/java/org/spongepowered/common/mixin/tracker/world/ticks/LevelTicksMixin_Tracker.java @@ -70,7 +70,7 @@ public abstract class LevelTicksMixin_Tracker { final var thisScheduledTick = this.alreadyRunThisTick.get(this.alreadyRunThisTick.size() - 1); if (((ScheduledTickBridge) (Object) thisScheduledTick).bridge$isPartOfWorldGeneration()) { try (final var context = GenerationPhase.State.DEFERRED_SCHEDULED_UPDATE.createPhaseContext( - PhaseTracker.SERVER) + PhaseTracker.getWorldInstance()) .source(this) .scheduledUpdate((BlockPos) blockPos, ticking) ) { diff --git a/vanilla/src/mixins/java/org/spongepowered/vanilla/mixin/core/server/level/ServerPlayerMixin_Vanilla.java b/vanilla/src/mixins/java/org/spongepowered/vanilla/mixin/core/server/level/ServerPlayerMixin_Vanilla.java index 0718cf4e114..d1bd9c40e2b 100644 --- a/vanilla/src/mixins/java/org/spongepowered/vanilla/mixin/core/server/level/ServerPlayerMixin_Vanilla.java +++ b/vanilla/src/mixins/java/org/spongepowered/vanilla/mixin/core/server/level/ServerPlayerMixin_Vanilla.java @@ -24,8 +24,10 @@ */ package org.spongepowered.vanilla.mixin.core.server.level; +import net.minecraft.server.level.ServerLevel; import org.checkerframework.checker.nullness.qual.NonNull; import org.spongepowered.asm.mixin.Mixin; +import org.spongepowered.asm.mixin.Shadow; import org.spongepowered.asm.mixin.injection.callback.CallbackInfo; import org.spongepowered.common.bridge.server.level.ServerPlayerBridge; import org.spongepowered.common.event.tracking.PhaseContext; @@ -38,10 +40,14 @@ @Mixin(net.minecraft.server.level.ServerPlayer.class) public abstract class ServerPlayerMixin_Vanilla extends LivingEntityMixin_Vanilla implements ServerPlayerBridge { + // @formatter:off + @Shadow public abstract ServerLevel shadow$serverLevel(); + // @formatter:on + // override from LivingEntityMixin_Vanilla @Override protected void vanilla$onElytraUse(final CallbackInfo ci) { - final PhaseContext<@NonNull ?> context = PhaseTracker.SERVER.getPhaseContext(); + final PhaseContext<@NonNull ?> context = PhaseTracker.getWorldInstance(this.shadow$serverLevel()).getPhaseContext(); final TransactionalCaptureSupplier transactor = context.getTransactor(); final net.minecraft.server.level.ServerPlayer player = (net.minecraft.server.level.ServerPlayer) (Object) this; try (final EffectTransactor ignored = transactor.logPlayerInventoryChangeWithEffect(player, PlayerInventoryTransaction.EventCreator.STANDARD)) { diff --git a/vanilla/src/mixins/java/org/spongepowered/vanilla/mixin/core/server/network/ServerGamePacketListenerImplMixin_Vanilla.java b/vanilla/src/mixins/java/org/spongepowered/vanilla/mixin/core/server/network/ServerGamePacketListenerImplMixin_Vanilla.java index 78e63b13177..6b8ab1f5b59 100644 --- a/vanilla/src/mixins/java/org/spongepowered/vanilla/mixin/core/server/network/ServerGamePacketListenerImplMixin_Vanilla.java +++ b/vanilla/src/mixins/java/org/spongepowered/vanilla/mixin/core/server/network/ServerGamePacketListenerImplMixin_Vanilla.java @@ -54,7 +54,7 @@ public abstract class ServerGamePacketListenerImplMixin_Vanilla implements Serve final RecipeHolder recipe, final ServerLevel serverLevel, final net.minecraft.world.entity.player.Inventory inventory) { final var player = inventory.player; - final PhaseContext<@NonNull ?> context = PhaseTracker.SERVER.getPhaseContext(); + final PhaseContext<@NonNull ?> context = PhaseTracker.getWorldInstance(serverLevel).getPhaseContext(); final TransactionalCaptureSupplier transactor = context.getTransactor(); final Inventory craftInv = ((Inventory) player.containerMenu).query(QueryTypes.INVENTORY_TYPE.get().of(CraftingInventory.class)); diff --git a/vanilla/src/mixins/java/org/spongepowered/vanilla/mixin/tracker/server/level/ServerPlayerGameModeMixin_Vanilla_Tracker.java b/vanilla/src/mixins/java/org/spongepowered/vanilla/mixin/tracker/server/level/ServerPlayerGameModeMixin_Vanilla_Tracker.java index 54d359b533e..477a99368df 100644 --- a/vanilla/src/mixins/java/org/spongepowered/vanilla/mixin/tracker/server/level/ServerPlayerGameModeMixin_Vanilla_Tracker.java +++ b/vanilla/src/mixins/java/org/spongepowered/vanilla/mixin/tracker/server/level/ServerPlayerGameModeMixin_Vanilla_Tracker.java @@ -25,6 +25,7 @@ package org.spongepowered.vanilla.mixin.tracker.server.level; import net.minecraft.core.BlockPos; +import net.minecraft.server.level.ServerLevel; import net.minecraft.server.level.ServerPlayer; import net.minecraft.server.level.ServerPlayerGameMode; import net.minecraft.world.entity.player.Player; @@ -55,7 +56,7 @@ public abstract class ServerPlayerGameModeMixin_Vanilla_Tracker { @Redirect(method = "destroyBlock", at = @At(value = "INVOKE", target = "Lnet/minecraft/world/item/ItemStack;mineBlock(Lnet/minecraft/world/level/Level;Lnet/minecraft/world/level/block/state/BlockState;Lnet/minecraft/core/BlockPos;Lnet/minecraft/world/entity/player/Player;)V")) public void vanillaTracker$onMineBlock(final ItemStack itemStack, final Level param0, final BlockState param1, final BlockPos param2, final Player param3) { - final PhaseContext<@NonNull ?> context = PhaseTracker.SERVER.getPhaseContext(); + final PhaseContext<@NonNull ?> context = PhaseTracker.getWorldInstance((ServerLevel) param0).getPhaseContext(); final TransactionalCaptureSupplier transactor = context.getTransactor(); itemStack.mineBlock(param0, param1, param2, param3); // Needs to get logged as a sideeffect under the BlockChange