diff --git a/Spigot-API-Patches/Timings-v2.patch b/Spigot-API-Patches/Timings-v2.patch index 784071a5f1..f321c1c559 100644 --- a/Spigot-API-Patches/Timings-v2.patch +++ b/Spigot-API-Patches/Timings-v2.patch @@ -659,7 +659,10 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000 + */ +package co.aikar.timings; + ++import co.aikar.timings.TimingHistory.RegionData.RegionId; ++import co.aikar.util.JSONUtil; +import com.google.common.base.Function; ++import com.google.common.collect.Maps; +import com.google.common.collect.Sets; +import org.bukkit.Bukkit; +import org.bukkit.Chunk; @@ -683,7 +686,7 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000 +import static co.aikar.timings.TimingsManager.MINUTE_REPORTS; +import static co.aikar.util.JSONUtil.*; + -+@SuppressWarnings({"deprecation", "SuppressionAnnotation"}) ++@SuppressWarnings({"deprecation", "SuppressionAnnotation", "Convert2Lambda", "Anonymous2MethodRef"}) +public class TimingHistory { + public static long lastMinuteTime; + public static long timedTicks; @@ -691,23 +694,23 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000 + public static long entityTicks; + public static long tileEntityTicks; + public static long activatedEntityTicks; -+ static int worldIdPool = 1; ++ private static int worldIdPool = 1; + static Map worldMap = LoadingMap.newHashMap(new Function() { + @Override + public Integer apply(String input) { + return worldIdPool++; + } + }); -+ final long endTime; -+ final long startTime; -+ final long totalTicks; -+ final long totalTime; // Represents all time spent running the server this history -+ final MinuteReport[] minuteReports; ++ private final long endTime; ++ private final long startTime; ++ private final long totalTicks; ++ private final long totalTime; // Represents all time spent running the server this history ++ private final MinuteReport[] minuteReports; + -+ final TimingHistoryEntry[] entries; ++ private final TimingHistoryEntry[] entries; + final Set tileEntityTypeSet = Sets.newHashSet(); + final Set entityTypeSet = Sets.newHashSet(); -+ final Map worlds; ++ private final Map worlds; + + TimingHistory() { + this.endTime = System.currentTimeMillis() / 1000; @@ -731,71 +734,129 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000 + entries[i++] = new TimingHistoryEntry(handler); + } + -+ final Map entityCounts = MRUMapCache.of(LoadingMap.of( -+ new EnumMap(EntityType.class), Counter.LOADER -+ )); -+ final Map tileEntityCounts = MRUMapCache.of(LoadingMap.of( -+ new EnumMap(Material.class), Counter.LOADER -+ )); ++ + // Information about all loaded chunks/entities ++ //noinspection unchecked + this.worlds = toObjectMapper(Bukkit.getWorlds(), new Function() { -+ @Override -+ public JSONPair apply(World world) { ++ @Override ++ public JSONPair apply(World world) { ++ Map regions = LoadingMap.newHashMap(RegionData.LOADER); ++ ++ for (Chunk chunk : world.getLoadedChunks()) { ++ RegionData data = regions.get(new RegionId(chunk.getX(), chunk.getZ())); ++ ++ for (Entity entity : chunk.getEntities()) { ++ data.entityCounts.get(entity.getType()).increment(); ++ } ++ ++ for (BlockState tileEntity : chunk.getTileEntities()) { ++ data.tileEntityCounts.get(tileEntity.getBlock().getType()).increment(); ++ } ++ } + return pair( + worldMap.get(world.getName()), -+ toArrayMapper(world.getLoadedChunks(), new Function() { ++ toArrayMapper(regions.values(),new Function() { + @Override -+ public Object apply(Chunk chunk) { -+ entityCounts.clear(); -+ tileEntityCounts.clear(); -+ -+ for (Entity entity : chunk.getEntities()) { -+ entityCounts.get(entity.getType()).increment(); -+ } -+ -+ for (BlockState tileEntity : chunk.getTileEntities()) { -+ tileEntityCounts.get(tileEntity.getBlock().getType()).increment(); -+ } -+ -+ if (tileEntityCounts.isEmpty() && entityCounts.isEmpty()) { -+ return null; -+ } -+ return toArray( -+ chunk.getX(), -+ chunk.getZ(), -+ toObjectMapper(entityCounts.entrySet(), -+ new Function, JSONPair>() { -+ @Override -+ public JSONPair apply(Map.Entry entry) { -+ entityTypeSet.add(entry.getKey()); -+ return pair( -+ String.valueOf(entry.getKey().getTypeId()), -+ entry.getValue().count() -+ ); ++ public Object apply(RegionData input) { ++ return toArray( ++ input.regionId.x, ++ input.regionId.z, ++ toObjectMapper(input.entityCounts.entrySet(), ++ new Function, JSONPair>() { ++ @Override ++ public JSONPair apply(Map.Entry entry) { ++ entityTypeSet.add(entry.getKey()); ++ return pair( ++ String.valueOf(entry.getKey().getTypeId()), ++ entry.getValue().count() ++ ); ++ } + } -+ } -+ ), -+ toObjectMapper(tileEntityCounts.entrySet(), -+ new Function, JSONPair>() { -+ @Override -+ public JSONPair apply(Map.Entry entry) { -+ tileEntityTypeSet.add(entry.getKey()); -+ return pair( -+ String.valueOf(entry.getKey().getId()), -+ entry.getValue().count() -+ ); ++ ), ++ toObjectMapper(input.tileEntityCounts.entrySet(), ++ new Function, JSONPair>() { ++ @Override ++ public JSONPair apply(Map.Entry entry) { ++ tileEntityTypeSet.add(entry.getKey()); ++ return pair( ++ String.valueOf(entry.getKey().getId()), ++ entry.getValue().count() ++ ); ++ } + } -+ } -+ ) -+ ); ++ ) ++ ); + } + }) + ); + } + }); + } ++ static class RegionData { ++ private final RegionId regionId; ++ @SuppressWarnings("Guava") ++ static Function LOADER = new Function() { ++ @Override ++ public RegionData apply(RegionId id) { ++ return new RegionData(id); ++ } ++ }; ++ RegionData(RegionId id) { ++ this.regionId = id; ++ } + -+ public static void resetTicks(boolean fullReset) { ++ @Override ++ public boolean equals(Object o) { ++ if (this == o) return true; ++ if (o == null || getClass() != o.getClass()) return false; ++ ++ RegionData that = (RegionData) o; ++ ++ return regionId.equals(that.regionId); ++ ++ } ++ ++ @Override ++ public int hashCode() { ++ return regionId.hashCode(); ++ } ++ ++ @SuppressWarnings("unchecked") ++ final Map entityCounts = MRUMapCache.of(LoadingMap.of( ++ new EnumMap(EntityType.class), Counter.LOADER ++ )); ++ @SuppressWarnings("unchecked") ++ final Map tileEntityCounts = MRUMapCache.of(LoadingMap.of( ++ new EnumMap(Material.class), Counter.LOADER ++ )); ++ ++ static class RegionId { ++ final int x, z; ++ final long regionId; ++ RegionId(int x, int z) { ++ this.x = x >> 5 << 5; ++ this.z = z >> 5 << 5; ++ this.regionId = ((long) (this.x) << 32) + (this.z >> 5 << 5) - Integer.MIN_VALUE; ++ } ++ ++ @Override ++ public boolean equals(Object o) { ++ if (this == o) return true; ++ if (o == null || getClass() != o.getClass()) return false; ++ ++ RegionId regionId1 = (RegionId) o; ++ ++ return regionId == regionId1.regionId; ++ ++ } ++ ++ @Override ++ public int hashCode() { ++ return (int) (regionId ^ (regionId >>> 32)); ++ } ++ } ++ } ++ static void resetTicks(boolean fullReset) { + if (fullReset) { + // Non full is simply for 1 minute reports + timedTicks = 0; @@ -863,7 +924,7 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000 + } + } + -+ static class TicksRecord { ++ private static class TicksRecord { + final long timed; + final long player; + final long entity; @@ -880,7 +941,7 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000 + + } + -+ static class PingRecord { ++ private static class PingRecord { + final double avg; + + PingRecord() { @@ -893,9 +954,10 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000 + } + } + -+ static class Counter { ++ @SuppressWarnings("WeakerAccess") ++ public static class Counter { + int count = 0; -+ @SuppressWarnings({"rawtypes", "SuppressionAnnotation"}) ++ @SuppressWarnings({"rawtypes", "SuppressionAnnotation", "Guava"}) + static Function LOADER = new LoadingMap.Feeder() { + @Override + public Counter apply() {