minecraft-src/net/minecraft/server/commands/ForceLoadCommand.java
2025-07-04 03:45:38 +03:00

197 lines
7.7 KiB
Java

package net.minecraft.server.commands;
import com.google.common.base.Joiner;
import com.mojang.brigadier.CommandDispatcher;
import com.mojang.brigadier.exceptions.CommandSyntaxException;
import com.mojang.brigadier.exceptions.Dynamic2CommandExceptionType;
import com.mojang.brigadier.exceptions.SimpleCommandExceptionType;
import it.unimi.dsi.fastutil.longs.LongSet;
import net.minecraft.commands.CommandSourceStack;
import net.minecraft.commands.Commands;
import net.minecraft.commands.arguments.coordinates.BlockPosArgument;
import net.minecraft.commands.arguments.coordinates.ColumnPosArgument;
import net.minecraft.core.SectionPos;
import net.minecraft.network.chat.Component;
import net.minecraft.resources.ResourceKey;
import net.minecraft.server.level.ColumnPos;
import net.minecraft.server.level.ServerLevel;
import net.minecraft.world.level.ChunkPos;
import net.minecraft.world.level.Level;
public class ForceLoadCommand {
private static final int MAX_CHUNK_LIMIT = 256;
private static final Dynamic2CommandExceptionType ERROR_TOO_MANY_CHUNKS = new Dynamic2CommandExceptionType(
(object, object2) -> Component.translatableEscape("commands.forceload.toobig", object, object2)
);
private static final Dynamic2CommandExceptionType ERROR_NOT_TICKING = new Dynamic2CommandExceptionType(
(object, object2) -> Component.translatableEscape("commands.forceload.query.failure", object, object2)
);
private static final SimpleCommandExceptionType ERROR_ALL_ADDED = new SimpleCommandExceptionType(Component.translatable("commands.forceload.added.failure"));
private static final SimpleCommandExceptionType ERROR_NONE_REMOVED = new SimpleCommandExceptionType(
Component.translatable("commands.forceload.removed.failure")
);
public static void register(CommandDispatcher<CommandSourceStack> dispatcher) {
dispatcher.register(
Commands.literal("forceload")
.requires(commandSourceStack -> commandSourceStack.hasPermission(2))
.then(
Commands.literal("add")
.then(
Commands.argument("from", ColumnPosArgument.columnPos())
.executes(
commandContext -> changeForceLoad(
commandContext.getSource(), ColumnPosArgument.getColumnPos(commandContext, "from"), ColumnPosArgument.getColumnPos(commandContext, "from"), true
)
)
.then(
Commands.argument("to", ColumnPosArgument.columnPos())
.executes(
commandContext -> changeForceLoad(
commandContext.getSource(), ColumnPosArgument.getColumnPos(commandContext, "from"), ColumnPosArgument.getColumnPos(commandContext, "to"), true
)
)
)
)
)
.then(
Commands.literal("remove")
.then(
Commands.argument("from", ColumnPosArgument.columnPos())
.executes(
commandContext -> changeForceLoad(
commandContext.getSource(), ColumnPosArgument.getColumnPos(commandContext, "from"), ColumnPosArgument.getColumnPos(commandContext, "from"), false
)
)
.then(
Commands.argument("to", ColumnPosArgument.columnPos())
.executes(
commandContext -> changeForceLoad(
commandContext.getSource(), ColumnPosArgument.getColumnPos(commandContext, "from"), ColumnPosArgument.getColumnPos(commandContext, "to"), false
)
)
)
)
.then(Commands.literal("all").executes(commandContext -> removeAll(commandContext.getSource())))
)
.then(
Commands.literal("query")
.executes(commandContext -> listForceLoad(commandContext.getSource()))
.then(
Commands.argument("pos", ColumnPosArgument.columnPos())
.executes(commandContext -> queryForceLoad(commandContext.getSource(), ColumnPosArgument.getColumnPos(commandContext, "pos")))
)
)
);
}
private static int queryForceLoad(CommandSourceStack source, ColumnPos pos) throws CommandSyntaxException {
ChunkPos chunkPos = pos.toChunkPos();
ServerLevel serverLevel = source.getLevel();
ResourceKey<Level> resourceKey = serverLevel.dimension();
boolean bl = serverLevel.getForceLoadedChunks().contains(chunkPos.toLong());
if (bl) {
source.sendSuccess(
() -> Component.translatable("commands.forceload.query.success", Component.translationArg(chunkPos), Component.translationArg(resourceKey.location())),
false
);
return 1;
} else {
throw ERROR_NOT_TICKING.create(chunkPos, resourceKey.location());
}
}
private static int listForceLoad(CommandSourceStack source) {
ServerLevel serverLevel = source.getLevel();
ResourceKey<Level> resourceKey = serverLevel.dimension();
LongSet longSet = serverLevel.getForceLoadedChunks();
int i = longSet.size();
if (i > 0) {
String string = Joiner.on(", ").join(longSet.stream().sorted().map(ChunkPos::new).map(ChunkPos::toString).iterator());
if (i == 1) {
source.sendSuccess(() -> Component.translatable("commands.forceload.list.single", Component.translationArg(resourceKey.location()), string), false);
} else {
source.sendSuccess(() -> Component.translatable("commands.forceload.list.multiple", i, Component.translationArg(resourceKey.location()), string), false);
}
} else {
source.sendFailure(Component.translatable("commands.forceload.added.none", Component.translationArg(resourceKey.location())));
}
return i;
}
private static int removeAll(CommandSourceStack source) {
ServerLevel serverLevel = source.getLevel();
ResourceKey<Level> resourceKey = serverLevel.dimension();
LongSet longSet = serverLevel.getForceLoadedChunks();
longSet.forEach(l -> serverLevel.setChunkForced(ChunkPos.getX(l), ChunkPos.getZ(l), false));
source.sendSuccess(() -> Component.translatable("commands.forceload.removed.all", Component.translationArg(resourceKey.location())), true);
return 0;
}
private static int changeForceLoad(CommandSourceStack source, ColumnPos from, ColumnPos to, boolean add) throws CommandSyntaxException {
int i = Math.min(from.x(), to.x());
int j = Math.min(from.z(), to.z());
int k = Math.max(from.x(), to.x());
int l = Math.max(from.z(), to.z());
if (i >= -30000000 && j >= -30000000 && k < 30000000 && l < 30000000) {
int m = SectionPos.blockToSectionCoord(i);
int n = SectionPos.blockToSectionCoord(j);
int o = SectionPos.blockToSectionCoord(k);
int p = SectionPos.blockToSectionCoord(l);
long q = (o - m + 1L) * (p - n + 1L);
if (q > 256L) {
throw ERROR_TOO_MANY_CHUNKS.create(256, q);
} else {
ServerLevel serverLevel = source.getLevel();
ResourceKey<Level> resourceKey = serverLevel.dimension();
ChunkPos chunkPos = null;
int r = 0;
for (int s = m; s <= o; s++) {
for (int t = n; t <= p; t++) {
boolean bl = serverLevel.setChunkForced(s, t, add);
if (bl) {
r++;
if (chunkPos == null) {
chunkPos = new ChunkPos(s, t);
}
}
}
}
ChunkPos chunkPos2 = chunkPos;
int tx = r;
if (tx == 0) {
throw (add ? ERROR_ALL_ADDED : ERROR_NONE_REMOVED).create();
} else {
if (tx == 1) {
source.sendSuccess(
() -> Component.translatable(
"commands.forceload." + (add ? "added" : "removed") + ".single", Component.translationArg(chunkPos2), Component.translationArg(resourceKey.location())
),
true
);
} else {
ChunkPos chunkPos3 = new ChunkPos(m, n);
ChunkPos chunkPos4 = new ChunkPos(o, p);
source.sendSuccess(
() -> Component.translatable(
"commands.forceload." + (add ? "added" : "removed") + ".multiple",
t,
Component.translationArg(resourceKey.location()),
Component.translationArg(chunkPos3),
Component.translationArg(chunkPos4)
),
true
);
}
return tx;
}
}
} else {
throw BlockPosArgument.ERROR_OUT_OF_WORLD.create();
}
}
}