package com.xfestudio.mydimensionlord.builder.anchor;
import com.xfestudio.mydimensionlord.MyDimension;
import com.xfestudio.mydimensionlord.config.BuilderConfig;
import com.xfestudio.mydimensionlord.registry.ModBlocks;
import net.minecraft.server.MinecraftServer;
import net.minecraft.server.level.ServerLevel;
import net.minecraft.world.level.ChunkPos;
import net.minecraft.world.level.Level;
import net.minecraft.world.level.block.state.BlockState;
import net.minecraftforge.event.level.ChunkEvent;
import net.minecraftforge.eventbus.api.SubscribeEvent;
import net.minecraftforge.fml.common.Mod;
/** Precise, non-scanning wake-up for anchors whose target container chunk loads later. */
@Mod.EventBusSubscriber(modid = MyDimension.MOD_ID, bus = Mod.EventBusSubscriber.Bus.FORGE)
public final class ResonantSupplyAnchorLifecycle {
private ResonantSupplyAnchorLifecycle() {
}
@SubscribeEvent
public static void chunkLoaded(ChunkEvent.Load event) {
if (!(event.getLevel() instanceof ServerLevel level) || !BuilderConfig.isEnabled()) {
return;
}
ChunkPos loadedChunk = event.getChunk().getPos();
MinecraftServer server = level.getServer();
// Load can fire on the server thread before the chunk's FULL future
// completes. Querying its blocks inline waits on that same callback.
// tell always queues; execute may run immediately on the server thread.
server.tell(new net.minecraft.server.TickTask(server.getTickCount(),
() -> wakeAnchorsTargeting(level, loadedChunk)));
}
static void wakeAnchorsTargeting(ServerLevel level, ChunkPos loadedChunk) {
if (!BuilderConfig.isEnabled() || !level.getChunkSource().hasChunk(loadedChunk.x, loadedChunk.z)) {
return;
}
MinecraftServer server = level.getServer();
if (server.getLevel(Level.OVERWORLD) == null) {
return;
}
for (AnchorIndexSavedData.AnchorLocation location : AnchorIndexSavedData.get(server)
.findTargetingChunk(level.dimension(), loadedChunk)) {
// Never load the adjacent anchor chunk merely to validate it.
var position = location.position();
var anchorChunk = level.getChunkSource().getChunkNow(position.getX() >> 4, position.getZ() >> 4);
if (anchorChunk == null) {
continue;
}
BlockState state = anchorChunk.getBlockState(position);
if (state.is(ModBlocks.RESONANT_SUPPLY_ANCHOR.get())
&& state.getValue(ResonantSupplyAnchorBlock.FACING) == location.facing()) {
level.scheduleTick(location.position(), ModBlocks.RESONANT_SUPPLY_ANCHOR.get(), 1);
}
}
}
}
package com.xfestudio.mydimensionlord.builder.anchor;
import com.xfestudio.mydimensionlord.MyDimension;
import com.xfestudio.mydimensionlord.config.BuilderConfig;
import com.xfestudio.mydimensionlord.registry.ModBlocks;
import net.minecraft.server.MinecraftServer;
import net.minecraft.server.level.ServerLevel;
import net.minecraft.world.level.ChunkPos;
import net.minecraft.world.level.Level;
import net.minecraft.world.level.block.state.BlockState;
import net.minecraftforge.event.level.ChunkEvent;
import net.minecraftforge.eventbus.api.SubscribeEvent;
import net.minecraftforge.fml.common.Mod;
/** Precise, non-scanning wake-up for anchors whose target container chunk loads later. */
@Mod.EventBusSubscriber(modid = MyDimension.MOD_ID, bus = Mod.EventBusSubscriber.Bus.FORGE)
public final class ResonantSupplyAnchorLifecycle {
private ResonantSupplyAnchorLifecycle() {
}
@SubscribeEvent
public static void chunkLoaded(ChunkEvent.Load event) {
if (!(event.getLevel() instanceof ServerLevel level) || !BuilderConfig.isEnabled()) {
return;
}
ChunkPos loadedChunk = event.getChunk().getPos();
MinecraftServer server = level.getServer();
// Load can fire on the server thread before the chunk's FULL future
// completes. Querying its blocks inline waits on that same callback.
// tell always queues; execute may run immediately on the server thread.
server.tell(new net.minecraft.server.TickTask(server.getTickCount(),
() -> wakeAnchorsTargeting(level, loadedChunk)));
}
static void wakeAnchorsTargeting(ServerLevel level, ChunkPos loadedChunk) {
if (!BuilderConfig.isEnabled() || !level.getChunkSource().hasChunk(loadedChunk.x, loadedChunk.z)) {
return;
}
MinecraftServer server = level.getServer();
if (server.getLevel(Level.OVERWORLD) == null) {
return;
}
for (AnchorIndexSavedData.AnchorLocation location : AnchorIndexSavedData.get(server)
.findTargetingChunk(level.dimension(), loadedChunk)) {
// Never load the adjacent anchor chunk merely to validate it.
var position = location.position();
var anchorChunk = level.getChunkSource().getChunkNow(position.getX() >> 4, position.getZ() >> 4);
if (anchorChunk == null) {
continue;
}
BlockState state = anchorChunk.getBlockState(position);
if (state.is(ModBlocks.RESONANT_SUPPLY_ANCHOR.get())
&& state.getValue(ResonantSupplyAnchorBlock.FACING) == location.facing()) {
level.scheduleTick(location.position(), ModBlocks.RESONANT_SUPPLY_ANCHOR.get(), 1);
}
}
}
}