491 lines
22 KiB
Diff
491 lines
22 KiB
Diff
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
|
|
From: Spottedleaf <Spottedleaf@users.noreply.github.com>
|
|
Date: Sat, 1 Jun 2019 13:00:55 -0700
|
|
Subject: [PATCH] Chunk debug command
|
|
|
|
Prints all chunk information to a text file into the debug
|
|
folder in the root server folder. The format is in JSON, and
|
|
the data format is described in MCUtil#dumpChunks(File)
|
|
|
|
The command will output server version and all online players to the
|
|
file as well. We do not log anything but the location, world and
|
|
username of the player.
|
|
|
|
Also logs the value of these config values (note not all are paper's):
|
|
- keep spawn loaded value
|
|
- spawn radius
|
|
- view distance
|
|
|
|
Each chunk has the following logged:
|
|
- Coordinate
|
|
- Ticket level & its corresponding state
|
|
- Whether it is queued for unload
|
|
- Chunk status (may be unloaded)
|
|
- All tickets on the chunk
|
|
|
|
Example log:
|
|
https://gist.githubusercontent.com/Spottedleaf/0131e7710ffd5d531e5fd246c3367380/raw/169ae1b2e240485f99bc7a6bd8e78d90e3af7397/chunks-2019-06-01_19.57.05.txt
|
|
|
|
For references on certain keywords (ticket, status, etc), please see:
|
|
|
|
https://bugs.mojang.com/browse/MC-141484?focusedCommentId=528273&page=com.atlassian.jira.plugin.system.issuetabpanels%3Acomment-tabpanel#comment-528273
|
|
https://bugs.mojang.com/browse/MC-141484?focusedCommentId=528577&page=com.atlassian.jira.plugin.system.issuetabpanels%3Acomment-tabpanel#comment-528577
|
|
|
|
diff --git a/src/main/java/com/destroystokyo/paper/PaperCommand.java b/src/main/java/com/destroystokyo/paper/PaperCommand.java
|
|
index 8fd716bf2e1402694798b8be03fd85821153be44..53dd6c18de8e80378852bbb141016d9574d42162 100644
|
|
--- a/src/main/java/com/destroystokyo/paper/PaperCommand.java
|
|
+++ b/src/main/java/com/destroystokyo/paper/PaperCommand.java
|
|
@@ -6,13 +6,15 @@ import com.google.common.collect.ImmutableSet;
|
|
import com.google.common.collect.Iterables;
|
|
import com.google.common.collect.Lists;
|
|
import com.google.common.collect.Maps;
|
|
-import net.minecraft.resources.ResourceLocation;
|
|
import net.minecraft.server.MinecraftServer;
|
|
+import net.minecraft.server.level.ChunkHolder;
|
|
import net.minecraft.server.level.ServerChunkCache;
|
|
import net.minecraft.server.level.ServerLevel;
|
|
import net.minecraft.world.entity.Entity;
|
|
import net.minecraft.world.entity.EntityType;
|
|
import net.minecraft.world.level.ChunkPos;
|
|
+import net.minecraft.resources.ResourceLocation;
|
|
+import net.minecraft.server.MCUtil;
|
|
import org.apache.commons.lang3.tuple.MutablePair;
|
|
import org.apache.commons.lang3.tuple.Pair;
|
|
import org.bukkit.Bukkit;
|
|
@@ -41,7 +43,7 @@ import java.util.stream.Collectors;
|
|
|
|
public class PaperCommand extends Command {
|
|
private static final String BASE_PERM = "bukkit.command.paper.";
|
|
- private static final ImmutableSet<String> SUBCOMMANDS = ImmutableSet.<String>builder().add("heap", "entity", "reload", "version").build();
|
|
+ private static final ImmutableSet<String> SUBCOMMANDS = ImmutableSet.<String>builder().add("heap", "entity", "reload", "version", "debug", "chunkinfo").build();
|
|
|
|
public PaperCommand(String name) {
|
|
super(name);
|
|
@@ -69,6 +71,21 @@ public class PaperCommand extends Command {
|
|
if (args.length == 3)
|
|
return getListMatchingLast(sender, args, EntityType.getEntityNameList().stream().map(ResourceLocation::toString).sorted().toArray(String[]::new));
|
|
break;
|
|
+ case "debug":
|
|
+ if (args.length == 2) {
|
|
+ return getListMatchingLast(sender, args, "help", "chunks");
|
|
+ }
|
|
+ break;
|
|
+ case "chunkinfo":
|
|
+ List<String> worldNames = new ArrayList<>();
|
|
+ worldNames.add("*");
|
|
+ for (org.bukkit.World world : Bukkit.getWorlds()) {
|
|
+ worldNames.add(world.getName());
|
|
+ }
|
|
+ if (args.length == 2) {
|
|
+ return getListMatchingLast(sender, args, worldNames);
|
|
+ }
|
|
+ break;
|
|
}
|
|
return Collections.emptyList();
|
|
}
|
|
@@ -135,6 +152,12 @@ public class PaperCommand extends Command {
|
|
case "reload":
|
|
doReload(sender);
|
|
break;
|
|
+ case "debug":
|
|
+ doDebug(sender, args);
|
|
+ break;
|
|
+ case "chunkinfo":
|
|
+ doChunkInfo(sender, args);
|
|
+ break;
|
|
case "ver":
|
|
if (!testPermission(sender, "version")) break; // "ver" needs a special check because it's an alias. All other commands are checked up before the switch statement (because they are present in the SUBCOMMANDS set)
|
|
case "version":
|
|
@@ -152,6 +175,114 @@ public class PaperCommand extends Command {
|
|
return true;
|
|
}
|
|
|
|
+ private void doChunkInfo(CommandSender sender, String[] args) {
|
|
+ List<org.bukkit.World> worlds;
|
|
+ if (args.length < 2 || args[1].equals("*")) {
|
|
+ worlds = Bukkit.getWorlds();
|
|
+ } else {
|
|
+ worlds = new ArrayList<>(args.length - 1);
|
|
+ for (int i = 1; i < args.length; ++i) {
|
|
+ org.bukkit.World world = Bukkit.getWorld(args[i]);
|
|
+ if (world == null) {
|
|
+ sender.sendMessage(ChatColor.RED + "World '" + args[i] + "' is invalid");
|
|
+ return;
|
|
+ }
|
|
+ worlds.add(world);
|
|
+ }
|
|
+ }
|
|
+
|
|
+ int accumulatedTotal = 0;
|
|
+ int accumulatedInactive = 0;
|
|
+ int accumulatedBorder = 0;
|
|
+ int accumulatedTicking = 0;
|
|
+ int accumulatedEntityTicking = 0;
|
|
+
|
|
+ for (org.bukkit.World bukkitWorld : worlds) {
|
|
+ ServerLevel world = ((CraftWorld)bukkitWorld).getHandle();
|
|
+
|
|
+ int total = 0;
|
|
+ int inactive = 0;
|
|
+ int border = 0;
|
|
+ int ticking = 0;
|
|
+ int entityTicking = 0;
|
|
+
|
|
+ for (ChunkHolder chunk : world.getChunkSource().chunkMap.updatingChunkMap.values()) {
|
|
+ if (chunk.getFullChunkIfCached() == null) {
|
|
+ continue;
|
|
+ }
|
|
+
|
|
+ ++total;
|
|
+
|
|
+ ChunkHolder.FullChunkStatus state = ChunkHolder.getFullChunkStatus(chunk.getTicketLevel());
|
|
+
|
|
+ switch (state) {
|
|
+ case INACCESSIBLE:
|
|
+ ++inactive;
|
|
+ continue;
|
|
+ case BORDER:
|
|
+ ++border;
|
|
+ continue;
|
|
+ case TICKING:
|
|
+ ++ticking;
|
|
+ continue;
|
|
+ case ENTITY_TICKING:
|
|
+ ++entityTicking;
|
|
+ continue;
|
|
+ }
|
|
+ }
|
|
+
|
|
+ accumulatedTotal += total;
|
|
+ accumulatedInactive += inactive;
|
|
+ accumulatedBorder += border;
|
|
+ accumulatedTicking += ticking;
|
|
+ accumulatedEntityTicking += entityTicking;
|
|
+
|
|
+ sender.sendMessage(ChatColor.BLUE + "Chunks in " + ChatColor.GREEN + bukkitWorld.getName() + ChatColor.DARK_AQUA + ":");
|
|
+ sender.sendMessage(ChatColor.BLUE + "Total: " + ChatColor.DARK_AQUA + total + ChatColor.BLUE + " Inactive: " + ChatColor.DARK_AQUA
|
|
+ + inactive + ChatColor.BLUE + " Border: " + ChatColor.DARK_AQUA + border + ChatColor.BLUE + " Ticking: "
|
|
+ + ChatColor.DARK_AQUA + ticking + ChatColor.BLUE + " Entity: " + ChatColor.DARK_AQUA + entityTicking);
|
|
+ }
|
|
+ if (worlds.size() > 1) {
|
|
+ sender.sendMessage(ChatColor.BLUE + "Chunks in " + ChatColor.GREEN + "all listed worlds" + ChatColor.DARK_AQUA + ":");
|
|
+ sender.sendMessage(ChatColor.BLUE + "Total: " + ChatColor.DARK_AQUA + accumulatedTotal + ChatColor.BLUE + " Inactive: " + ChatColor.DARK_AQUA
|
|
+ + accumulatedInactive + ChatColor.BLUE + " Border: " + ChatColor.DARK_AQUA + accumulatedBorder + ChatColor.BLUE + " Ticking: "
|
|
+ + ChatColor.DARK_AQUA + accumulatedTicking + ChatColor.BLUE + " Entity: " + ChatColor.DARK_AQUA + accumulatedEntityTicking);
|
|
+ }
|
|
+ }
|
|
+
|
|
+ private void doDebug(CommandSender sender, String[] args) {
|
|
+ if (args.length < 2) {
|
|
+ sender.sendMessage(ChatColor.RED + "Use /paper debug [chunks] help for more information on a specific command");
|
|
+ return;
|
|
+ }
|
|
+
|
|
+ String debugType = args[1].toLowerCase(Locale.ENGLISH);
|
|
+ switch (debugType) {
|
|
+ case "chunks":
|
|
+ if (args.length >= 3 && args[2].toLowerCase(Locale.ENGLISH).equals("help")) {
|
|
+ sender.sendMessage(ChatColor.RED + "Use /paper debug chunks to dump loaded chunk information to a file");
|
|
+ break;
|
|
+ }
|
|
+ File file = new File(new File(new File("."), "debug"),
|
|
+ "chunks-" + DateTimeFormatter.ofPattern("yyyy-MM-dd_HH.mm.ss").format(LocalDateTime.now()) + ".txt");
|
|
+ sender.sendMessage(ChatColor.GREEN + "Writing chunk information dump to " + file.toString());
|
|
+ try {
|
|
+ MCUtil.dumpChunks(file);
|
|
+ sender.sendMessage(ChatColor.GREEN + "Successfully written chunk information!");
|
|
+ } catch (Throwable thr) {
|
|
+ MinecraftServer.LOGGER.warn("Failed to dump chunk information to file " + file.toString(), thr);
|
|
+ sender.sendMessage(ChatColor.RED + "Failed to dump chunk information, see console");
|
|
+ }
|
|
+
|
|
+ break;
|
|
+ case "help":
|
|
+ // fall through to default
|
|
+ default:
|
|
+ sender.sendMessage(ChatColor.RED + "Use /paper debug [chunks] help for more information on a specific command");
|
|
+ return;
|
|
+ }
|
|
+ }
|
|
+
|
|
/*
|
|
* Ported from MinecraftForge - author: LexManos <LexManos@gmail.com> - License: LGPLv2.1
|
|
*/
|
|
diff --git a/src/main/java/net/minecraft/server/MCUtil.java b/src/main/java/net/minecraft/server/MCUtil.java
|
|
index 1fecc81b25109592907623741225a6222a8c5ccc..a16551c81a444685f6337a65b6d7862b8c0dc684 100644
|
|
--- a/src/main/java/net/minecraft/server/MCUtil.java
|
|
+++ b/src/main/java/net/minecraft/server/MCUtil.java
|
|
@@ -9,13 +9,27 @@ import net.minecraft.core.BlockPos;
|
|
import net.minecraft.core.Direction;
|
|
import net.minecraft.nbt.CompoundTag;
|
|
import net.minecraft.network.chat.Component;
|
|
+import net.minecraft.server.level.ChunkHolder;
|
|
+import net.minecraft.server.level.ChunkMap;
|
|
+import net.minecraft.server.level.DistanceManager;
|
|
+import net.minecraft.server.level.ServerChunkCache;
|
|
import net.minecraft.server.level.ServerLevel;
|
|
+import net.minecraft.server.level.ServerPlayer;
|
|
+import net.minecraft.server.level.Ticket;
|
|
import net.minecraft.world.entity.Entity;
|
|
import net.minecraft.world.level.ChunkPos;
|
|
import net.minecraft.world.level.ClipContext;
|
|
import net.minecraft.world.level.Level;
|
|
+import net.minecraft.world.level.chunk.ChunkAccess;
|
|
+import net.minecraft.world.level.chunk.ChunkStatus;
|
|
import org.apache.commons.lang.exception.ExceptionUtils;
|
|
+import com.google.gson.JsonArray;
|
|
+import com.google.gson.JsonObject;
|
|
+import com.google.gson.internal.Streams;
|
|
+import com.google.gson.stream.JsonWriter;
|
|
import com.mojang.authlib.GameProfile;
|
|
+import com.mojang.datafixers.util.Either;
|
|
+import it.unimi.dsi.fastutil.longs.Long2ObjectLinkedOpenHashMap;
|
|
import org.bukkit.Location;
|
|
import org.bukkit.block.BlockFace;
|
|
import org.bukkit.craftbukkit.CraftWorld;
|
|
@@ -24,8 +38,11 @@ import org.spigotmc.AsyncCatcher;
|
|
|
|
import javax.annotation.Nonnull;
|
|
import javax.annotation.Nullable;
|
|
+import java.io.*;
|
|
+import java.util.ArrayList;
|
|
import java.util.List;
|
|
import java.util.Queue;
|
|
+import java.util.Set;
|
|
import java.util.concurrent.CompletableFuture;
|
|
import java.util.concurrent.ExecutionException;
|
|
import java.util.concurrent.LinkedBlockingQueue;
|
|
@@ -531,4 +548,170 @@ public final class MCUtil {
|
|
|
|
return null;
|
|
}
|
|
+
|
|
+ public static ChunkStatus getChunkStatus(ChunkHolder chunk) {
|
|
+ List<ChunkStatus> statuses = ServerChunkCache.getPossibleChunkStatuses();
|
|
+ for (int i = statuses.size() - 1; i >= 0; --i) {
|
|
+ ChunkStatus curr = statuses.get(i);
|
|
+ CompletableFuture<Either<ChunkAccess, ChunkHolder.ChunkLoadingFailure>> future = chunk.getFutureIfPresentUnchecked(curr);
|
|
+ if (future != ChunkHolder.UNLOADED_CHUNK_FUTURE) {
|
|
+ return curr;
|
|
+ }
|
|
+ }
|
|
+ return null; // unloaded
|
|
+ }
|
|
+
|
|
+ public static void dumpChunks(File file) throws IOException {
|
|
+ file.getParentFile().mkdirs();
|
|
+ file.createNewFile();
|
|
+ /*
|
|
+ * Json format:
|
|
+ *
|
|
+ * Main data format:
|
|
+ * -server-version:<string>
|
|
+ * -data-version:<int>
|
|
+ * -worlds:
|
|
+ * -name:<world name>
|
|
+ * -view-distance:<int>
|
|
+ * -keep-spawn-loaded:<boolean>
|
|
+ * -keep-spawn-loaded-range:<int>
|
|
+ * -visible-chunk-count:<int>
|
|
+ * -loaded-chunk-count:<int>
|
|
+ * -verified-fully-loaded-chunks:<int>
|
|
+ * -players:<array of player>
|
|
+ * -chunk-data:<array of chunks>
|
|
+ *
|
|
+ * Player format:
|
|
+ * -name:<string>
|
|
+ * -x:<double>
|
|
+ * -y:<double>
|
|
+ * -z:<double>
|
|
+ *
|
|
+ * Chunk Format:
|
|
+ * -x:<integer>
|
|
+ * -z:<integer>
|
|
+ * -ticket-level:<integer>
|
|
+ * -state:<string>
|
|
+ * -queued-for-unload:<boolean>
|
|
+ * -status:<string>
|
|
+ * -tickets:<array of tickets>
|
|
+ *
|
|
+ *
|
|
+ * Ticket format:
|
|
+ * -ticket-type:<string>
|
|
+ * -ticket-level:<int>
|
|
+ * -add-tick:<long>
|
|
+ * -object-reason:<string> // This depends on the type of ticket. ie POST_TELEPORT -> entity id
|
|
+ */
|
|
+ List<org.bukkit.World> worlds = org.bukkit.Bukkit.getWorlds();
|
|
+ JsonObject data = new JsonObject();
|
|
+
|
|
+ data.addProperty("server-version", org.bukkit.Bukkit.getVersion());
|
|
+ data.addProperty("data-version", 0);
|
|
+
|
|
+ JsonArray worldsData = new JsonArray();
|
|
+
|
|
+ for (org.bukkit.World bukkitWorld : worlds) {
|
|
+ JsonObject worldData = new JsonObject();
|
|
+
|
|
+ ServerLevel world = ((org.bukkit.craftbukkit.CraftWorld)bukkitWorld).getHandle();
|
|
+ ChunkMap chunkMap = world.getChunkSource().chunkMap;
|
|
+ Long2ObjectLinkedOpenHashMap<ChunkHolder> visibleChunks = chunkMap.visibleChunkMap;
|
|
+ DistanceManager chunkMapDistance = chunkMap.distanceManager;
|
|
+ List<ChunkHolder> allChunks = new ArrayList<>(visibleChunks.values());
|
|
+ List<ServerPlayer> players = world.players;
|
|
+
|
|
+ int fullLoadedChunks = 0;
|
|
+
|
|
+ for (ChunkHolder chunk : allChunks) {
|
|
+ if (chunk.getFullChunkIfCached() != null) {
|
|
+ ++fullLoadedChunks;
|
|
+ }
|
|
+ }
|
|
+
|
|
+ // sorting by coordinate makes the log easier to read
|
|
+ allChunks.sort((ChunkHolder v1, ChunkHolder v2) -> {
|
|
+ if (v1.location.x != v2.location.x) {
|
|
+ return Integer.compare(v1.location.x, v2.location.x);
|
|
+ }
|
|
+ return Integer.compare(v1.location.z, v2.location.z);
|
|
+ });
|
|
+
|
|
+ worldData.addProperty("name", world.getWorld().getName());
|
|
+ worldData.addProperty("view-distance", world.spigotConfig.viewDistance);
|
|
+ worldData.addProperty("keep-spawn-loaded", world.keepSpawnInMemory);
|
|
+ worldData.addProperty("keep-spawn-loaded-range", world.paperConfig.keepLoadedRange);
|
|
+ worldData.addProperty("visible-chunk-count", visibleChunks.size());
|
|
+ worldData.addProperty("loaded-chunk-count", chunkMap.entitiesInLevel.size());
|
|
+ worldData.addProperty("verified-fully-loaded-chunks", fullLoadedChunks);
|
|
+
|
|
+ JsonArray playersData = new JsonArray();
|
|
+
|
|
+ for (ServerPlayer player : players) {
|
|
+ JsonObject playerData = new JsonObject();
|
|
+
|
|
+ playerData.addProperty("name", player.getScoreboardName());
|
|
+ playerData.addProperty("x", player.getX());
|
|
+ playerData.addProperty("y", player.getY());
|
|
+ playerData.addProperty("z", player.getZ());
|
|
+
|
|
+ playersData.add(playerData);
|
|
+
|
|
+ }
|
|
+
|
|
+ worldData.add("players", playersData);
|
|
+
|
|
+ JsonArray chunksData = new JsonArray();
|
|
+
|
|
+ for (ChunkHolder playerChunk : allChunks) {
|
|
+ JsonObject chunkData = new JsonObject();
|
|
+
|
|
+ Set<Ticket<?>> tickets = chunkMapDistance.tickets.get(playerChunk.pos.pair());
|
|
+ ChunkStatus status = getChunkStatus(playerChunk);
|
|
+
|
|
+ chunkData.addProperty("x", playerChunk.location.x);
|
|
+ chunkData.addProperty("z", playerChunk.location.z);
|
|
+ chunkData.addProperty("ticket-level", playerChunk.getTicketLevel());
|
|
+ chunkData.addProperty("state", ChunkHolder.getFullChunkStatus(playerChunk.getTicketLevel()).toString());
|
|
+ chunkData.addProperty("queued-for-unload", chunkMap.toDrop.contains(playerChunk.pos.pair()));
|
|
+ chunkData.addProperty("status", status == null ? "unloaded" : status.toString());
|
|
+
|
|
+ JsonArray ticketsData = new JsonArray();
|
|
+
|
|
+ if (tickets != null) {
|
|
+ for (Ticket<?> ticket : tickets) {
|
|
+ JsonObject ticketData = new JsonObject();
|
|
+
|
|
+ ticketData.addProperty("ticket-type", ticket.getType().toString());
|
|
+ ticketData.addProperty("ticket-level", ticket.getTicketLevel());
|
|
+ ticketData.addProperty("object-reason", String.valueOf(ticket.getObjectReason()));
|
|
+ ticketData.addProperty("add-tick", ticket.getCreationTick());
|
|
+
|
|
+ ticketsData.add(ticketData);
|
|
+ }
|
|
+ }
|
|
+
|
|
+ chunkData.add("tickets", ticketsData);
|
|
+ chunksData.add(chunkData);
|
|
+ }
|
|
+
|
|
+
|
|
+ worldData.add("chunk-data", chunksData);
|
|
+ worldsData.add(worldData);
|
|
+ }
|
|
+
|
|
+ data.add("worlds", worldsData);
|
|
+
|
|
+ StringWriter stringWriter = new StringWriter();
|
|
+ JsonWriter jsonWriter = new JsonWriter(stringWriter);
|
|
+ jsonWriter.setIndent(" ");
|
|
+ jsonWriter.setLenient(false);
|
|
+ Streams.write(data, jsonWriter);
|
|
+
|
|
+ String fileData = stringWriter.toString();
|
|
+
|
|
+ try (PrintStream out = new PrintStream(new FileOutputStream(file), false, "UTF-8")) {
|
|
+ out.print(fileData);
|
|
+ }
|
|
+ }
|
|
}
|
|
diff --git a/src/main/java/net/minecraft/server/level/ChunkHolder.java b/src/main/java/net/minecraft/server/level/ChunkHolder.java
|
|
index 89e90806b78d94d5c1d781113da420dafa47930a..a89b9dab043ad4536014141d5a942670b4152a95 100644
|
|
--- a/src/main/java/net/minecraft/server/level/ChunkHolder.java
|
|
+++ b/src/main/java/net/minecraft/server/level/ChunkHolder.java
|
|
@@ -53,7 +53,7 @@ public class ChunkHolder {
|
|
public int oldTicketLevel;
|
|
private int ticketLevel;
|
|
private int queueLevel;
|
|
- private final ChunkPos pos;
|
|
+ final ChunkPos pos; // Paper - private -> package
|
|
private boolean hasChangedSections;
|
|
private final ShortSet[] changedBlocksPerSection;
|
|
private int blockChangedLightSectionFilter;
|
|
diff --git a/src/main/java/net/minecraft/server/level/ChunkMap.java b/src/main/java/net/minecraft/server/level/ChunkMap.java
|
|
index 5d87a282042d7112415b7d7175031f734219f2c9..7585b6f87b72f53deccbcb8627a13503921fc682 100644
|
|
--- a/src/main/java/net/minecraft/server/level/ChunkMap.java
|
|
+++ b/src/main/java/net/minecraft/server/level/ChunkMap.java
|
|
@@ -104,7 +104,7 @@ public class ChunkMap extends ChunkStorage implements ChunkHolder.PlayerProvider
|
|
public final Long2ObjectLinkedOpenHashMap<ChunkHolder> updatingChunkMap = new Long2ObjectLinkedOpenHashMap();
|
|
public volatile Long2ObjectLinkedOpenHashMap<ChunkHolder> visibleChunkMap;
|
|
private final Long2ObjectLinkedOpenHashMap<ChunkHolder> pendingUnloads;
|
|
- private final LongSet entitiesInLevel;
|
|
+ public final LongSet entitiesInLevel; // Paper - private -> public
|
|
public final ServerLevel level;
|
|
private final ThreadedLevelLightEngine lightEngine;
|
|
private final BlockableEventLoop<Runnable> mainThreadExecutor;
|
|
diff --git a/src/main/java/net/minecraft/server/level/ServerChunkCache.java b/src/main/java/net/minecraft/server/level/ServerChunkCache.java
|
|
index a7122a0411f4a8656efd4facde3403c8093bc8a6..6d33c1ee44bc732b58d18a8f6b0fd4bbdcb2dcd6 100644
|
|
--- a/src/main/java/net/minecraft/server/level/ServerChunkCache.java
|
|
+++ b/src/main/java/net/minecraft/server/level/ServerChunkCache.java
|
|
@@ -46,7 +46,7 @@ import it.unimi.dsi.fastutil.longs.Long2ObjectOpenHashMap; // Paper
|
|
|
|
public class ServerChunkCache extends ChunkSource {
|
|
|
|
- private static final List<ChunkStatus> CHUNK_STATUSES = ChunkStatus.getStatusList();
|
|
+ private static final List<ChunkStatus> CHUNK_STATUSES = ChunkStatus.getStatusList(); public static final List<ChunkStatus> getPossibleChunkStatuses() { return ServerChunkCache.CHUNK_STATUSES; } // Paper - OBFHELPER
|
|
private final DistanceManager distanceManager;
|
|
public final ChunkGenerator generator;
|
|
private final ServerLevel level;
|
|
diff --git a/src/main/java/net/minecraft/server/level/Ticket.java b/src/main/java/net/minecraft/server/level/Ticket.java
|
|
index 0c118d482e304c567fe7fe778c6ff386f960bdde..c6b5f32153b63ac92df9c4b31b8de168481f79f2 100644
|
|
--- a/src/main/java/net/minecraft/server/level/Ticket.java
|
|
+++ b/src/main/java/net/minecraft/server/level/Ticket.java
|
|
@@ -6,8 +6,8 @@ public final class Ticket<T> implements Comparable<Ticket<?>> {
|
|
|
|
private final TicketType<T> type;
|
|
private final int ticketLevel;
|
|
- public final T key;
|
|
- private long createdTick;
|
|
+ public final T key; public final T getObjectReason() { return this.key; } // Paper - OBFHELPER
|
|
+ private long createdTick; public final long getCreationTick() { return this.createdTick; } // Paper - OBFHELPER
|
|
|
|
protected Ticket(TicketType<T> type, int level, T argument) {
|
|
this.type = type;
|
|
@@ -51,6 +51,7 @@ public final class Ticket<T> implements Comparable<Ticket<?>> {
|
|
return this.type;
|
|
}
|
|
|
|
+ public final int getTicketLevel() { return this.getTicketLevel(); } // Paper - OBFHELPER
|
|
public int getTicketLevel() {
|
|
return this.ticketLevel;
|
|
}
|