diff --git a/leaves-server/minecraft-patches/features/0096-Fast-resume.patch b/leaves-server/minecraft-patches/features/0096-Fast-resume.patch deleted file mode 100644 index 5ffc5340..00000000 --- a/leaves-server/minecraft-patches/features/0096-Fast-resume.patch +++ /dev/null @@ -1,80 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: violetc <58360096+s-yh-china@users.noreply.github.com> -Date: Wed, 5 Feb 2025 23:42:44 +0800 -Subject: [PATCH] Fast resume - - -diff --git a/ca/spottedleaf/moonrise/patches/chunk_system/scheduling/ChunkHolderManager.java b/ca/spottedleaf/moonrise/patches/chunk_system/scheduling/ChunkHolderManager.java -index f473999938840562b1007a789600342e5796a123..7e20b6469ef06c0338b5298d36b3a1ba1c52e897 100644 ---- a/ca/spottedleaf/moonrise/patches/chunk_system/scheduling/ChunkHolderManager.java -+++ b/ca/spottedleaf/moonrise/patches/chunk_system/scheduling/ChunkHolderManager.java -@@ -656,6 +656,49 @@ public final class ChunkHolderManager { - } - } - -+ // Leaves start - add custom ticket -+ public void addTicketAtLevelCustom(final Ticket ticket, final long chunk, final boolean lock) { -+ final long removeDelay = ticket.moonrise$getRemoveDelay(); -+ -+ final int chunkX = CoordinateUtils.getChunkX(chunk); -+ final int chunkZ = CoordinateUtils.getChunkZ(chunk); -+ -+ final ReentrantAreaLock.Node ticketLock = lock ? this.ticketLockArea.lock(chunkX, chunkZ) : null; -+ try { -+ final SortedArraySet ticketsAtChunk = this.tickets.computeIfAbsent(chunk, (final long keyInMap) -> SortedArraySet.create(4)); -+ -+ final int levelBefore = getTicketLevelAt(ticketsAtChunk); -+ final Ticket current = ((ChunkSystemSortedArraySet)ticketsAtChunk).moonrise$replace(ticket); -+ final int levelAfter = getTicketLevelAt(ticketsAtChunk); -+ -+ if (current != ticket) { -+ final long oldRemoveDelay = ((ChunkSystemTicket) current).moonrise$getRemoveDelay(); -+ if (removeDelay != oldRemoveDelay) { -+ if (oldRemoveDelay != NO_TIMEOUT_MARKER && removeDelay == NO_TIMEOUT_MARKER) { -+ this.removeExpireCount(chunkX, chunkZ); -+ } else if (oldRemoveDelay == NO_TIMEOUT_MARKER) { -+ // since old != new, we have that NO_TIMEOUT_MARKER != new -+ this.addExpireCount(chunkX, chunkZ); -+ } -+ } -+ } else { -+ if (removeDelay != NO_TIMEOUT_MARKER) { -+ this.addExpireCount(chunkX, chunkZ); -+ } -+ } -+ -+ if (levelBefore != levelAfter) { -+ this.updateTicketLevel(chunk, levelAfter); -+ } -+ -+ } finally { -+ if (ticketLock != null) { -+ this.ticketLockArea.unlock(ticketLock); -+ } -+ } -+ } -+ // Leaves end - add custom ticket -+ - private void removeTicketCounter(final TicketType type, final long pos) { - final long[] counterTypes = ((ChunkSystemTicketType)(Object)type).moonrise$getCounterTypes(); - if (counterTypes.length == 0) { -diff --git a/net/minecraft/server/MinecraftServer.java b/net/minecraft/server/MinecraftServer.java -index f1681577f27a618338cae1634094e728c98fc3ff..6bc08a61a51b19e8f5670b0c54a3faeeab16bbc4 100644 ---- a/net/minecraft/server/MinecraftServer.java -+++ b/net/minecraft/server/MinecraftServer.java -@@ -742,6 +742,7 @@ public abstract class MinecraftServer extends ReentrantBlockableEventLoop NEED_SAVED = Set.of(TicketType.PORTAL, RegionizedPlayerChunkLoader.PLAYER_TICKET); - - public static void tryToLoadTickets() { - if (!LeavesConfig.modify.fastResume) { - return; - } - - File file = MinecraftServer.getServer().getWorldPath(LevelResource.ROOT).resolve("chunk_tickets.leaves.json").toFile(); - if (file.isFile()) { - try (BufferedReader bfr = Files.newBufferedReader(file.toPath(), StandardCharsets.UTF_8)) { - JsonObject json = new Gson().fromJson(bfr, JsonObject.class); - loadSavedChunkTickets(json); - if (!file.delete()) { - throw new IOException(); - } - } catch (IOException e) { - LeavesLogger.LOGGER.severe("Failed to load saved chunk tickets file", e); - } - } - } - - public static void tryToSaveTickets() { - if (!LeavesConfig.modify.fastResume) { - return; - } - - File file = MinecraftServer.getServer().getWorldPath(LevelResource.ROOT).resolve("chunk_tickets.leaves.json").toFile(); - try (BufferedWriter bfw = Files.newBufferedWriter(file.toPath(), StandardCharsets.UTF_8)) { - bfw.write(new Gson().toJson(getSavedChunkTickets())); - } catch (IOException e) { - LeavesLogger.LOGGER.severe("Failed to save chunk tickets file", e); - } - } - - public static void loadSavedChunkTickets(JsonObject json) { - MinecraftServer server = MinecraftServer.getServer(); - for (String worldKey : json.keySet()) { - ResourceLocation dimensionKey = ResourceLocation.tryParse(worldKey); - if (dimensionKey == null) { - continue; - } - - ServerLevel level = server.getLevel(ResourceKey.create(Registries.DIMENSION, dimensionKey)); - if (level == null) { - continue; - } - - DistanceManager chunkDistanceManager = level.getChunkSource().chunkMap.distanceManager; - for (JsonElement chunkElement : json.get(worldKey).getAsJsonArray()) { - JsonObject chunkJson = (JsonObject) chunkElement; - long chunkKey = chunkJson.get("key").getAsLong(); - - for (JsonElement ticketElement : chunkJson.get("tickets").getAsJsonArray()) { - Ticket ticket = tickFormJson((JsonObject) ticketElement); - chunkDistanceManager.moonrise$getChunkHolderManager().addTicketAtLevelCustom(ticket, chunkKey, true); - } - } - } - } - - public static JsonObject getSavedChunkTickets() { - JsonObject json = new JsonObject(); - - for (ServerLevel level : MinecraftServer.getServer().getAllLevels()) { - JsonArray levelArray = new JsonArray(); - DistanceManager chunkDistanceManager = level.getChunkSource().chunkMap.distanceManager; - - for (Long2ObjectMap.Entry> chunkTickets : chunkDistanceManager.moonrise$getChunkHolderManager().getTicketsCopy().long2ObjectEntrySet()) { - long chunkKey = chunkTickets.getLongKey(); - JsonArray ticketArray = new JsonArray(); - SortedArraySet tickets = chunkTickets.getValue(); - - for (Ticket ticket : tickets) { - if (!NEED_SAVED.contains(ticket.getType())) { - continue; - } - - ticketArray.add(ticketToJson(ticket)); - } - - if (!ticketArray.isEmpty()) { - JsonObject chunkJson = new JsonObject(); - chunkJson.addProperty("key", chunkKey); - chunkJson.add("tickets", ticketArray); - levelArray.add(chunkJson); - } - } - - if (!levelArray.isEmpty()) { - json.add(level.dimension().location().toString(), levelArray); - } - } - - return json; - } - - private static JsonObject ticketToJson(Ticket ticket) { - JsonObject json = new JsonObject(); - json.addProperty("type", ticket.getType().toString()); - json.addProperty("ticketLevel", ticket.getTicketLevel()); - json.addProperty("removeDelay", ticket.moonrise$getRemoveDelay()); - switch (ticket.getIdentifier()) { - case BlockPos pos -> json.addProperty("key", pos.asLong()); - case ChunkPos pos -> json.addProperty("key", pos.toLong()); - case Long l -> json.addProperty("key", l); - default -> { - } - } - return json; - } - - private static Ticket tickFormJson(JsonObject json) { - TicketType ticketType = null; - Object key = null; - switch (json.get("type").getAsString()) { - case "portal" -> { - ticketType = TicketType.PORTAL; - key = BlockPos.of(json.get("key").getAsLong()); - } - case "chunk_system:player_ticket" -> { - ticketType = RegionizedPlayerChunkLoader.PLAYER_TICKET; - key = json.get("key").getAsLong(); - } - } - - if (ticketType == null) { - throw new IllegalArgumentException("Cant convert " + json.get("type").getAsString() + ", report it ???"); - } - - int ticketLevel = json.get("ticketLevel").getAsInt(); - long removeDelay = json.get("removeDelay").getAsLong(); - Ticket ticket = new Ticket<>(ticketType, ticketLevel, key); - ticket.moonrise$setRemoveDelay(removeDelay); - - return ticket; - } -}