197 lines
		
	
	
	
		
			7.7 KiB
		
	
	
	
		
			Java
		
	
	
	
	
	
			
		
		
	
	
			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(Commands.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();
 | |
| 		}
 | |
| 	}
 | |
| }
 |