318 lines
		
	
	
	
		
			9.2 KiB
		
	
	
	
		
			Java
		
	
	
	
	
	
			
		
		
	
	
			318 lines
		
	
	
	
		
			9.2 KiB
		
	
	
	
		
			Java
		
	
	
	
	
	
| package net.minecraft.client.server;
 | |
| 
 | |
| import com.google.common.base.MoreObjects;
 | |
| import com.google.common.collect.Lists;
 | |
| import com.mojang.authlib.GameProfile;
 | |
| import com.mojang.logging.LogUtils;
 | |
| import java.io.IOException;
 | |
| import java.nio.file.Path;
 | |
| import java.util.UUID;
 | |
| import java.util.function.BooleanSupplier;
 | |
| import java.util.function.Supplier;
 | |
| import net.fabricmc.api.EnvType;
 | |
| import net.fabricmc.api.Environment;
 | |
| import net.minecraft.CrashReport;
 | |
| import net.minecraft.SharedConstants;
 | |
| import net.minecraft.SystemReport;
 | |
| import net.minecraft.client.Minecraft;
 | |
| import net.minecraft.client.gui.components.toasts.SystemToast;
 | |
| import net.minecraft.server.MinecraftServer;
 | |
| import net.minecraft.server.Services;
 | |
| import net.minecraft.server.WorldStem;
 | |
| import net.minecraft.server.level.ServerPlayer;
 | |
| import net.minecraft.server.level.progress.ChunkProgressListenerFactory;
 | |
| import net.minecraft.server.packs.repository.PackRepository;
 | |
| import net.minecraft.stats.Stats;
 | |
| import net.minecraft.util.ModCheck;
 | |
| import net.minecraft.util.debugchart.LocalSampleLogger;
 | |
| import net.minecraft.util.profiling.Profiler;
 | |
| import net.minecraft.util.profiling.ProfilerFiller;
 | |
| import net.minecraft.world.level.ChunkPos;
 | |
| import net.minecraft.world.level.GameType;
 | |
| import net.minecraft.world.level.chunk.storage.RegionStorageInfo;
 | |
| import net.minecraft.world.level.storage.LevelStorageSource;
 | |
| import org.jetbrains.annotations.Nullable;
 | |
| import org.slf4j.Logger;
 | |
| 
 | |
| @Environment(EnvType.CLIENT)
 | |
| public class IntegratedServer extends MinecraftServer {
 | |
| 	private static final Logger LOGGER = LogUtils.getLogger();
 | |
| 	private static final int MIN_SIM_DISTANCE = 2;
 | |
| 	private final Minecraft minecraft;
 | |
| 	private boolean paused = true;
 | |
| 	private int publishedPort = -1;
 | |
| 	@Nullable
 | |
| 	private GameType publishedGameType;
 | |
| 	@Nullable
 | |
| 	private LanServerPinger lanPinger;
 | |
| 	@Nullable
 | |
| 	private UUID uuid;
 | |
| 	private int previousSimulationDistance = 0;
 | |
| 
 | |
| 	public IntegratedServer(
 | |
| 		Thread serverThread,
 | |
| 		Minecraft minecraft,
 | |
| 		LevelStorageSource.LevelStorageAccess storageSource,
 | |
| 		PackRepository packRepository,
 | |
| 		WorldStem worldStem,
 | |
| 		Services services,
 | |
| 		ChunkProgressListenerFactory progressListenerFactory
 | |
| 	) {
 | |
| 		super(serverThread, storageSource, packRepository, worldStem, minecraft.getProxy(), minecraft.getFixerUpper(), services, progressListenerFactory);
 | |
| 		this.setSingleplayerProfile(minecraft.getGameProfile());
 | |
| 		this.setDemo(minecraft.isDemo());
 | |
| 		this.setPlayerList(new IntegratedPlayerList(this, this.registries(), this.playerDataStorage));
 | |
| 		this.minecraft = minecraft;
 | |
| 	}
 | |
| 
 | |
| 	@Override
 | |
| 	public boolean initServer() {
 | |
| 		LOGGER.info("Starting integrated minecraft server version {}", SharedConstants.getCurrentVersion().name());
 | |
| 		this.setUsesAuthentication(true);
 | |
| 		this.setPvpAllowed(true);
 | |
| 		this.setFlightAllowed(true);
 | |
| 		this.initializeKeyPair();
 | |
| 		this.loadLevel();
 | |
| 		GameProfile gameProfile = this.getSingleplayerProfile();
 | |
| 		String string = this.getWorldData().getLevelName();
 | |
| 		this.setMotd(gameProfile != null ? gameProfile.getName() + " - " + string : string);
 | |
| 		return true;
 | |
| 	}
 | |
| 
 | |
| 	@Override
 | |
| 	public boolean isPaused() {
 | |
| 		return this.paused;
 | |
| 	}
 | |
| 
 | |
| 	@Override
 | |
| 	public void tickServer(BooleanSupplier hasTimeLeft) {
 | |
| 		boolean bl = this.paused;
 | |
| 		this.paused = Minecraft.getInstance().isPaused();
 | |
| 		ProfilerFiller profilerFiller = Profiler.get();
 | |
| 		if (!bl && this.paused) {
 | |
| 			profilerFiller.push("autoSave");
 | |
| 			LOGGER.info("Saving and pausing game...");
 | |
| 			this.saveEverything(false, false, false);
 | |
| 			profilerFiller.pop();
 | |
| 		}
 | |
| 
 | |
| 		boolean bl2 = Minecraft.getInstance().getConnection() != null;
 | |
| 		if (bl2 && this.paused) {
 | |
| 			this.tickPaused();
 | |
| 		} else {
 | |
| 			if (bl && !this.paused) {
 | |
| 				this.forceTimeSynchronization();
 | |
| 			}
 | |
| 
 | |
| 			super.tickServer(hasTimeLeft);
 | |
| 			int i = Math.max(2, this.minecraft.options.renderDistance().get());
 | |
| 			if (i != this.getPlayerList().getViewDistance()) {
 | |
| 				LOGGER.info("Changing view distance to {}, from {}", i, this.getPlayerList().getViewDistance());
 | |
| 				this.getPlayerList().setViewDistance(i);
 | |
| 			}
 | |
| 
 | |
| 			int j = Math.max(2, this.minecraft.options.simulationDistance().get());
 | |
| 			if (j != this.previousSimulationDistance) {
 | |
| 				LOGGER.info("Changing simulation distance to {}, from {}", j, this.previousSimulationDistance);
 | |
| 				this.getPlayerList().setSimulationDistance(j);
 | |
| 				this.previousSimulationDistance = j;
 | |
| 			}
 | |
| 		}
 | |
| 	}
 | |
| 
 | |
| 	protected LocalSampleLogger getTickTimeLogger() {
 | |
| 		return this.minecraft.getDebugOverlay().getTickTimeLogger();
 | |
| 	}
 | |
| 
 | |
| 	@Override
 | |
| 	public boolean isTickTimeLoggingEnabled() {
 | |
| 		return true;
 | |
| 	}
 | |
| 
 | |
| 	private void tickPaused() {
 | |
| 		for (ServerPlayer serverPlayer : this.getPlayerList().getPlayers()) {
 | |
| 			serverPlayer.awardStat(Stats.TOTAL_WORLD_TIME);
 | |
| 		}
 | |
| 	}
 | |
| 
 | |
| 	@Override
 | |
| 	public boolean shouldRconBroadcast() {
 | |
| 		return true;
 | |
| 	}
 | |
| 
 | |
| 	@Override
 | |
| 	public boolean shouldInformAdmins() {
 | |
| 		return true;
 | |
| 	}
 | |
| 
 | |
| 	@Override
 | |
| 	public Path getServerDirectory() {
 | |
| 		return this.minecraft.gameDirectory.toPath();
 | |
| 	}
 | |
| 
 | |
| 	@Override
 | |
| 	public boolean isDedicatedServer() {
 | |
| 		return false;
 | |
| 	}
 | |
| 
 | |
| 	@Override
 | |
| 	public int getRateLimitPacketsPerSecond() {
 | |
| 		return 0;
 | |
| 	}
 | |
| 
 | |
| 	@Override
 | |
| 	public boolean isEpollEnabled() {
 | |
| 		return false;
 | |
| 	}
 | |
| 
 | |
| 	@Override
 | |
| 	public void onServerCrash(CrashReport report) {
 | |
| 		this.minecraft.delayCrashRaw(report);
 | |
| 	}
 | |
| 
 | |
| 	@Override
 | |
| 	public SystemReport fillServerSystemReport(SystemReport report) {
 | |
| 		report.setDetail("Type", "Integrated Server (map_client.txt)");
 | |
| 		report.setDetail("Is Modded", (Supplier<String>)(() -> this.getModdedStatus().fullDescription()));
 | |
| 		report.setDetail("Launched Version", this.minecraft::getLaunchedVersion);
 | |
| 		return report;
 | |
| 	}
 | |
| 
 | |
| 	@Override
 | |
| 	public ModCheck getModdedStatus() {
 | |
| 		return Minecraft.checkModStatus().merge(super.getModdedStatus());
 | |
| 	}
 | |
| 
 | |
| 	@Override
 | |
| 	public boolean publishServer(@Nullable GameType gameMode, boolean commands, int port) {
 | |
| 		try {
 | |
| 			this.minecraft.prepareForMultiplayer();
 | |
| 			this.minecraft.getConnection().prepareKeyPair();
 | |
| 			this.getConnection().startTcpServerListener(null, port);
 | |
| 			LOGGER.info("Started serving on {}", port);
 | |
| 			this.publishedPort = port;
 | |
| 			this.lanPinger = new LanServerPinger(this.getMotd(), port + "");
 | |
| 			this.lanPinger.start();
 | |
| 			this.publishedGameType = gameMode;
 | |
| 			this.getPlayerList().setAllowCommandsForAllPlayers(commands);
 | |
| 			int i = this.getProfilePermissions(this.minecraft.player.getGameProfile());
 | |
| 			this.minecraft.player.setPermissionLevel(i);
 | |
| 
 | |
| 			for (ServerPlayer serverPlayer : this.getPlayerList().getPlayers()) {
 | |
| 				this.getCommands().sendCommands(serverPlayer);
 | |
| 			}
 | |
| 
 | |
| 			return true;
 | |
| 		} catch (IOException var7) {
 | |
| 			return false;
 | |
| 		}
 | |
| 	}
 | |
| 
 | |
| 	@Override
 | |
| 	public void stopServer() {
 | |
| 		super.stopServer();
 | |
| 		if (this.lanPinger != null) {
 | |
| 			this.lanPinger.interrupt();
 | |
| 			this.lanPinger = null;
 | |
| 		}
 | |
| 	}
 | |
| 
 | |
| 	@Override
 | |
| 	public void halt(boolean waitForServer) {
 | |
| 		this.executeBlocking(() -> {
 | |
| 			for (ServerPlayer serverPlayer : Lists.newArrayList(this.getPlayerList().getPlayers())) {
 | |
| 				if (!serverPlayer.getUUID().equals(this.uuid)) {
 | |
| 					this.getPlayerList().remove(serverPlayer);
 | |
| 				}
 | |
| 			}
 | |
| 		});
 | |
| 		super.halt(waitForServer);
 | |
| 		if (this.lanPinger != null) {
 | |
| 			this.lanPinger.interrupt();
 | |
| 			this.lanPinger = null;
 | |
| 		}
 | |
| 	}
 | |
| 
 | |
| 	@Override
 | |
| 	public boolean isPublished() {
 | |
| 		return this.publishedPort > -1;
 | |
| 	}
 | |
| 
 | |
| 	@Override
 | |
| 	public int getPort() {
 | |
| 		return this.publishedPort;
 | |
| 	}
 | |
| 
 | |
| 	@Override
 | |
| 	public void setDefaultGameType(GameType gameMode) {
 | |
| 		super.setDefaultGameType(gameMode);
 | |
| 		this.publishedGameType = null;
 | |
| 	}
 | |
| 
 | |
| 	@Override
 | |
| 	public boolean isCommandBlockEnabled() {
 | |
| 		return true;
 | |
| 	}
 | |
| 
 | |
| 	@Override
 | |
| 	public int getOperatorUserPermissionLevel() {
 | |
| 		return 2;
 | |
| 	}
 | |
| 
 | |
| 	@Override
 | |
| 	public int getFunctionCompilationLevel() {
 | |
| 		return 2;
 | |
| 	}
 | |
| 
 | |
| 	public void setUUID(UUID uuid) {
 | |
| 		this.uuid = uuid;
 | |
| 	}
 | |
| 
 | |
| 	@Override
 | |
| 	public boolean isSingleplayerOwner(GameProfile profile) {
 | |
| 		return this.getSingleplayerProfile() != null && profile.getName().equalsIgnoreCase(this.getSingleplayerProfile().getName());
 | |
| 	}
 | |
| 
 | |
| 	@Override
 | |
| 	public int getScaledTrackingDistance(int trackingDistance) {
 | |
| 		return (int)(this.minecraft.options.entityDistanceScaling().get() * trackingDistance);
 | |
| 	}
 | |
| 
 | |
| 	@Override
 | |
| 	public boolean forceSynchronousWrites() {
 | |
| 		return this.minecraft.options.syncWrites;
 | |
| 	}
 | |
| 
 | |
| 	@Nullable
 | |
| 	@Override
 | |
| 	public GameType getForcedGameType() {
 | |
| 		return this.isPublished() && !this.isHardcore() ? MoreObjects.firstNonNull(this.publishedGameType, this.worldData.getGameType()) : null;
 | |
| 	}
 | |
| 
 | |
| 	@Override
 | |
| 	public boolean saveEverything(boolean suppressLog, boolean flush, boolean forced) {
 | |
| 		boolean bl = super.saveEverything(suppressLog, flush, forced);
 | |
| 		this.warnOnLowDiskSpace();
 | |
| 		return bl;
 | |
| 	}
 | |
| 
 | |
| 	private void warnOnLowDiskSpace() {
 | |
| 		if (this.storageSource.checkForLowDiskSpace()) {
 | |
| 			this.minecraft.execute(() -> SystemToast.onLowDiskSpace(this.minecraft));
 | |
| 		}
 | |
| 	}
 | |
| 
 | |
| 	@Override
 | |
| 	public void reportChunkLoadFailure(Throwable throwable, RegionStorageInfo regionStorageInfo, ChunkPos chunkPos) {
 | |
| 		super.reportChunkLoadFailure(throwable, regionStorageInfo, chunkPos);
 | |
| 		this.warnOnLowDiskSpace();
 | |
| 		this.minecraft.execute(() -> SystemToast.onChunkLoadFailure(this.minecraft, chunkPos));
 | |
| 	}
 | |
| 
 | |
| 	@Override
 | |
| 	public void reportChunkSaveFailure(Throwable throwable, RegionStorageInfo regionStorageInfo, ChunkPos chunkPos) {
 | |
| 		super.reportChunkSaveFailure(throwable, regionStorageInfo, chunkPos);
 | |
| 		this.warnOnLowDiskSpace();
 | |
| 		this.minecraft.execute(() -> SystemToast.onChunkSaveFailure(this.minecraft, chunkPos));
 | |
| 	}
 | |
| }
 |