diff --git a/src/main/java/ca/spottedleaf/moonrise/mixin/chunk_system/CommandsMixin.java b/src/main/java/ca/spottedleaf/moonrise/mixin/chunk_system/CommandsMixin.java new file mode 100644 index 00000000..0c4d9494 --- /dev/null +++ b/src/main/java/ca/spottedleaf/moonrise/mixin/chunk_system/CommandsMixin.java @@ -0,0 +1,36 @@ +package ca.spottedleaf.moonrise.mixin.chunk_system; + +import ca.spottedleaf.moonrise.patches.chunk_system.command.MoonriseCommand; +import com.mojang.brigadier.CommandDispatcher; +import net.minecraft.commands.CommandBuildContext; +import net.minecraft.commands.CommandSourceStack; +import net.minecraft.commands.Commands; +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; +import org.spongepowered.asm.mixin.injection.Inject; +import org.spongepowered.asm.mixin.injection.callback.CallbackInfo; + +@Mixin(Commands.class) +public abstract class CommandsMixin { + + @Shadow + @Final + private CommandDispatcher dispatcher; + + /** + * @reason Hook for registering the moonrise command + * @author Spottedleaf + */ + @Inject( + method = "", + at = @At( + value = "INVOKE", + target = "Lcom/mojang/brigadier/CommandDispatcher;setConsumer(Lcom/mojang/brigadier/ResultConsumer;)V" + ) + ) + private void registerCommands(CallbackInfo ci) { + MoonriseCommand.register(this.dispatcher); + } +} diff --git a/src/main/java/ca/spottedleaf/moonrise/patches/chunk_system/command/MoonriseCommand.java b/src/main/java/ca/spottedleaf/moonrise/patches/chunk_system/command/MoonriseCommand.java new file mode 100644 index 00000000..1c84b3ba --- /dev/null +++ b/src/main/java/ca/spottedleaf/moonrise/patches/chunk_system/command/MoonriseCommand.java @@ -0,0 +1,129 @@ +package ca.spottedleaf.moonrise.patches.chunk_system.command; + +import ca.spottedleaf.moonrise.patches.chunk_system.ChunkSystem; +import ca.spottedleaf.moonrise.patches.chunk_system.level.ChunkSystemServerLevel; +import ca.spottedleaf.moonrise.patches.chunk_system.scheduling.NewChunkHolder; +import com.mojang.brigadier.CommandDispatcher; +import com.mojang.brigadier.arguments.StringArgumentType; +import com.mojang.brigadier.context.CommandContext; +import net.minecraft.commands.CommandSourceStack; +import net.minecraft.commands.Commands; +import net.minecraft.commands.arguments.DimensionArgument; +import net.minecraft.network.chat.ComponentContents; +import net.minecraft.network.chat.MutableComponent; +import net.minecraft.network.chat.contents.PlainTextContents; +import net.minecraft.server.level.ChunkHolder; +import net.minecraft.server.level.FullChunkStatus; +import net.minecraft.world.level.chunk.ChunkAccess; +import net.minecraft.world.level.chunk.ImposterProtoChunk; +import net.minecraft.world.level.chunk.LevelChunk; +import net.minecraft.world.level.chunk.ProtoChunk; + +public final class MoonriseCommand { + + public static void register(final CommandDispatcher dispatcher) { + dispatcher.register( + Commands.literal("moonrise").requires((final CommandSourceStack src) -> { + return src.hasPermission(2); + }).then( + Commands.literal("holderinfo") + .executes((final CommandContext ctx) -> { + return MoonriseCommand.holderInfo(ctx); + }) + ).then( + Commands.literal("chunkinfo") + .executes((final CommandContext ctx) -> { + return MoonriseCommand.chunkInfo(ctx); + }) + ) + ); + } + + public static int holderInfo(final CommandContext ctx) { + int total = 0; + int canUnload = 0; + int nullChunks = 0; + int readOnly = 0; + int protoChunk = 0; + int fullChunk = 0; + + for (final NewChunkHolder holder : ((ChunkSystemServerLevel)ctx.getSource().getLevel()).moonrise$getChunkTaskScheduler().chunkHolderManager.getChunkHolders()) { + final NewChunkHolder.ChunkCompletion completion = holder.getLastChunkCompletion(); + final ChunkAccess chunk = completion == null ? null : completion.chunk(); + + ++total; + + if (chunk == null) { + ++nullChunks; + } else if (chunk instanceof ImposterProtoChunk) { + ++readOnly; + } else if (chunk instanceof ProtoChunk) { + ++protoChunk; + } else if (chunk instanceof LevelChunk) { + ++fullChunk; + } + + if (holder.isSafeToUnload() == null) { + ++canUnload; + } + } + + ctx.getSource().sendSystemMessage(MutableComponent.create( + new PlainTextContents.LiteralContents( + "Total: " + total + " Unloadable: " + canUnload + + " Null: " + nullChunks + " ReadOnly: " + readOnly + + " Proto: " + protoChunk + " Full: " + fullChunk + ) + )); + + return total; + } + + public static int chunkInfo(final CommandContext ctx) { + int total = 0; + int inactive = 0; + int full = 0; + int blockTicking = 0; + int entityTicking = 0; + + for (final NewChunkHolder holder : ((ChunkSystemServerLevel)ctx.getSource().getLevel()).moonrise$getChunkTaskScheduler().chunkHolderManager.getChunkHolders()) { + final NewChunkHolder.ChunkCompletion completion = holder.getLastChunkCompletion(); + final ChunkAccess chunk = completion == null ? null : completion.chunk(); + + if (!(chunk instanceof LevelChunk fullChunk)) { + continue; + } + + ++total; + + switch (holder.getChunkStatus()) { + case INACCESSIBLE: { + ++inactive; + break; + } + case FULL: { + ++full; + break; + } + case BLOCK_TICKING: { + ++blockTicking; + break; + } + case ENTITY_TICKING: { + ++entityTicking; + break; + } + } + } + + ctx.getSource().sendSystemMessage(MutableComponent.create( + new PlainTextContents.LiteralContents( + "Total: " + total + " Inactive: " + inactive + + " Full: " + full + " Block Ticking: " + blockTicking + + " Entity Ticking: " + entityTicking + ) + )); + + return total; + } +} diff --git a/src/main/resources/moonrise.mixins.json b/src/main/resources/moonrise.mixins.json index c364f39f..538a5ed2 100644 --- a/src/main/resources/moonrise.mixins.json +++ b/src/main/resources/moonrise.mixins.json @@ -21,6 +21,7 @@ "chunk_system.ChunkSerializerMixin", "chunk_system.ChunkStatusMixin", "chunk_system.ChunkStorageMixin", + "chunk_system.CommandsMixin", "chunk_system.DistanceManagerMixin", "chunk_system.EntityGetterMixin", "chunk_system.EntityMixin",