diff --git a/src/main/java/net/minecraft/server/management/PlayerManager.java b/src/main/java/net/minecraft/server/management/PlayerManager.java index 33810c5..f92d6dd 100644 --- a/src/main/java/net/minecraft/server/management/PlayerManager.java +++ b/src/main/java/net/minecraft/server/management/PlayerManager.java @@ -190,7 +190,7 @@ public void updatePlayerPertinentChunks(EntityPlayerMP par1EntityPlayerMP) { - par1EntityPlayerMP.getChunkMgr().updatePlayerPertinentChunks(); +// par1EntityPlayerMP.getChunkMgr().updatePlayerPertinentChunks(); } public boolean isPlayerWatchingChunk(EntityPlayerMP p_72694_1_, int p_72694_2_, int p_72694_3_) diff --git a/src/main/java/net/minecraft/world/World.java b/src/main/java/net/minecraft/world/World.java index 306b245..b16f623 100644 --- a/src/main/java/net/minecraft/world/World.java +++ b/src/main/java/net/minecraft/world/World.java @@ -873,13 +873,13 @@ { if (p_72976_1_ >= -MAX_BLOCK_COORD && p_72976_2_ >= -MAX_BLOCK_COORD && p_72976_1_ < MAX_BLOCK_COORD && p_72976_2_ < MAX_BLOCK_COORD) { - if (!this.chunkExists(p_72976_1_ >> 4, p_72976_2_ >> 4)) + Chunk chunk = this.getChunkIfExists(p_72976_1_ >> 4, p_72976_2_ >> 4); + if (chunk == null) { return 0; } else { - Chunk chunk = this.getChunkFromChunkCoords(p_72976_1_ >> 4, p_72976_2_ >> 4); return chunk.getHeightValue(p_72976_1_ & 15, p_72976_2_ & 15); } } @@ -893,13 +893,13 @@ { if (p_82734_1_ >= -MAX_BLOCK_COORD && p_82734_2_ >= -MAX_BLOCK_COORD && p_82734_1_ < MAX_BLOCK_COORD && p_82734_2_ < MAX_BLOCK_COORD) { - if (!this.chunkExists(p_82734_1_ >> 4, p_82734_2_ >> 4)) + Chunk chunk = this.getChunkIfExists(p_82734_1_ >> 4, p_82734_2_ >> 4); + if (chunk == null) { return 0; } else { - Chunk chunk = this.getChunkFromChunkCoords(p_82734_1_ >> 4, p_82734_2_ >> 4); return chunk.heightMapMinimum; } } @@ -996,13 +996,13 @@ int l = p_72972_2_ >> 4; int i1 = p_72972_4_ >> 4; - if (!this.chunkExists(l, i1)) + Chunk chunk = this.getChunkIfExists(l, i1); + if (chunk == null) { return p_72972_1_.defaultLightValue; } else { - Chunk chunk = this.getChunkFromChunkCoords(l, i1); return chunk.getSavedLightValue(p_72972_1_, p_72972_2_ & 15, p_72972_3_, p_72972_4_ & 15); } } @@ -1020,9 +1020,9 @@ { if (p_72915_3_ < 256) { - if (this.chunkExists(p_72915_2_ >> 4, p_72915_4_ >> 4)) + Chunk chunk = this.getChunkIfExists(p_72915_2_ >> 4, p_72915_4_ >> 4); + if (chunk != null) { - Chunk chunk = this.getChunkFromChunkCoords(p_72915_2_ >> 4, p_72915_4_ >> 4); chunk.setLightValue(p_72915_1_, p_72915_2_ & 15, p_72915_3_, p_72915_4_ & 15, p_72915_5_); for (int i1 = 0; i1 < this.worldAccesses.size(); ++i1) @@ -2200,7 +2200,6 @@ } else if(p_72866_1_.isEntityPlayerMP()) { - ((EntityPlayerMP)p_72866_1_).getChunkMgr().updatePlayerPertinentChunks(); ((EntityPlayerMP)p_72866_1_).getChunkMgr().update(); } diff --git a/src/main/java/net/minecraft/world/chunk/storage/RegionFileCache.java b/src/main/java/net/minecraft/world/chunk/storage/RegionFileCache.java index 851d88d..902d8ad 100644 --- a/src/main/java/net/minecraft/world/chunk/storage/RegionFileCache.java +++ b/src/main/java/net/minecraft/world/chunk/storage/RegionFileCache.java @@ -8,11 +8,16 @@ import java.util.Iterator; import java.util.Map; +import com.google.common.collect.Maps; import net.minecraft.world.storage.ThreadedFileIOBase; +import org.ultramine.server.internal.LambdaHolder; +import org.ultramine.server.util.CachedEntry; +import org.ultramine.server.util.CollectionUtil; public class RegionFileCache { - private static final Map regionsByFilename = new HashMap(); + private static final Map> regionsByFilenameUM = new HashMap<>(); + private static final Map regionsByFilename = Maps.transformValues(regionsByFilenameUM, LambdaHolder.cachedEntryGetValueGuavaFunc()); private static final String __OBFID = "CL_00000383"; public static synchronized RegionFile createOrLoadRegionFile(File p_76550_0_, int p_76550_1_, int p_76550_2_) @@ -34,11 +39,21 @@ if (regionsByFilename.size() >= 256) { - clearRegionFileReferences(); + for(CachedEntry entry : CollectionUtil.retainNewestEntries(regionsByFilenameUM.values(), 128)) + { + try + { + entry.getValueAndUpdateTime().close(); + } + catch (IOException e) + { + e.printStackTrace(); + } + } } RegionFile regionfile1 = new RegionFile(file3); - regionsByFilename.put(file3, regionfile1); + regionsByFilenameUM.put(file3, CachedEntry.of(regionfile1)); return regionfile1; } } diff --git a/src/main/java/org/ultramine/server/RecipeCache.java b/src/main/java/org/ultramine/server/RecipeCache.java index 73beefa..526ea81 100644 --- a/src/main/java/org/ultramine/server/RecipeCache.java +++ b/src/main/java/org/ultramine/server/RecipeCache.java @@ -1,12 +1,9 @@ package org.ultramine.server; import java.util.Arrays; -import java.util.Collections; import java.util.HashMap; import java.util.Map; -import java.util.Optional; -import cpw.mods.fml.common.FMLCommonHandler; import cpw.mods.fml.common.eventhandler.SubscribeEvent; import cpw.mods.fml.common.gameevent.TickEvent; import net.minecraft.inventory.InventoryCrafting; @@ -14,8 +11,9 @@ import net.minecraft.item.ItemStack; import net.minecraft.item.crafting.CraftingManager; import net.minecraft.item.crafting.IRecipe; -import net.minecraft.server.MinecraftServer; import net.minecraft.world.World; +import org.ultramine.server.util.CachedEntry; +import org.ultramine.server.util.CollectionUtil; import org.ultramine.server.util.ModificationControlList; import javax.annotation.Nullable; @@ -23,9 +21,8 @@ public class RecipeCache { private static final int CACHE_SIZE = 12287; - private static final int CLEANUP_INTERVAL = 20*10; private final ModificationControlList originList; - private final Map> cache = new HashMap<>(); + private final Map> cache = new HashMap<>(); private boolean enabled; @SuppressWarnings("unchecked") @@ -48,13 +45,14 @@ if(key.width == 0) return null; - Optional rcp = cache.get(key); + CachedEntry rcp = cache.get(key); if (rcp != null) { - if(!rcp.isPresent()) + IRecipe recipe = rcp.getValueAndUpdateTime(); + if(recipe == null) return null; - if(rcp.get().matches(inv, world)) - return rcp.get(); + if(recipe.matches(inv, world)) + return recipe; } IRecipe recipe = originalSearch(inv, world); @@ -65,8 +63,8 @@ private void addToCache(RecipeKey key, @Nullable IRecipe recipe) { if(cache.size() >= CACHE_SIZE) - cache.clear(); - cache.put(key, Optional.ofNullable(recipe)); + CollectionUtil.retainNewestEntries(cache.values(), CACHE_SIZE / 2); + cache.put(key, CachedEntry.of(recipe)); } private @Nullable IRecipe originalSearch(InventoryCrafting inv, World world) @@ -96,10 +94,6 @@ { clearCache(); } - else if(MinecraftServer.getServer().getTickCounter() % CLEANUP_INTERVAL == 0) - { - cache.values().removeAll(Collections.singleton(Optional.empty())); - } } private static class RecipeKey implements Comparable diff --git a/src/main/java/org/ultramine/server/chunk/ChunkSendManager.java b/src/main/java/org/ultramine/server/chunk/ChunkSendManager.java index d792727..5ce209d 100644 --- a/src/main/java/org/ultramine/server/chunk/ChunkSendManager.java +++ b/src/main/java/org/ultramine/server/chunk/ChunkSendManager.java @@ -205,6 +205,7 @@ { if(manager == null) return; + updatePlayerPertinentChunks(); if(!toSend.isEmpty()) { int queueSize = sendingQueueSize.get(); @@ -323,7 +324,7 @@ } } - public void updatePlayerPertinentChunks() + private void updatePlayerPertinentChunks() { checkDistance(); diff --git a/src/main/java/org/ultramine/server/internal/LambdaHolder.java b/src/main/java/org/ultramine/server/internal/LambdaHolder.java index d34b795..2d14247 100644 --- a/src/main/java/org/ultramine/server/internal/LambdaHolder.java +++ b/src/main/java/org/ultramine/server/internal/LambdaHolder.java @@ -4,6 +4,7 @@ import net.minecraft.tileentity.TileEntity; import net.openhft.koloboke.collect.map.ShortObjMap; import net.openhft.koloboke.collect.map.hash.HashShortObjMaps; +import org.ultramine.server.util.CachedEntry; import java.util.TreeSet; import java.util.function.Predicate; @@ -15,18 +16,19 @@ public static final Predicate ENTITY_REMOVAL_PREDICATE = o -> ((Entity)o).removeThisTick; public static final Predicate TILE_ENTITY_REMOVAL_PREDICATE = o -> ((TileEntity)o).removeThisTick; - private static final Supplier> NEW_TREE_SET = TreeSet::new; - private static final Supplier> NEW_SHORT_OBJ_MAP = HashShortObjMaps::newMutableMap; - - @SuppressWarnings("unchecked") public static Supplier> newTreeSet() { - return (Supplier>) (Object) NEW_TREE_SET; + return TreeSet::new; } - @SuppressWarnings("unchecked") public static Supplier> newShortObjMap() { - return (Supplier>) (Object) NEW_SHORT_OBJ_MAP; + return HashShortObjMaps::newMutableMap; + } + + @SuppressWarnings({"Guava"}) + public static com.google.common.base.Function, T> cachedEntryGetValueGuavaFunc() + { + return CachedEntry::getValueAndUpdateTime; } } diff --git a/src/main/java/org/ultramine/server/util/CachedEntry.java b/src/main/java/org/ultramine/server/util/CachedEntry.java new file mode 100644 index 0000000..2816ea1 --- /dev/null +++ b/src/main/java/org/ultramine/server/util/CachedEntry.java @@ -0,0 +1,65 @@ +package org.ultramine.server.util; + +public class CachedEntry implements Comparable> +{ + private final T value; + private long time; + + private CachedEntry(T value, long time) + { + this.value = value; + this.time = time; + } + + private CachedEntry(T value) + { + this(value, System.nanoTime()); + } + + public static CachedEntry of(T val) + { + return new CachedEntry<>(val); + } + + public T getValueAndUpdateTime() + { + this.time = System.nanoTime(); + return value; + } + + public long getTime() + { + return time; + } + + @Override + public int compareTo(CachedEntry o) + { + return Long.compare(time, o.time); + } + + @Override + public boolean equals(Object o) + { + if(this == o) return true; + if(o == null || getClass() != o.getClass()) return false; + + CachedEntry that = (CachedEntry) o; + + return value != null ? value.equals(that.value) : that.value == null; + } + + @Override + public int hashCode() + { + return value != null ? value.hashCode() : 0; + } + + @Override + public String toString() + { + return "CachedEntry{" + + "value=" + value + + '}'; + } +} diff --git a/src/main/java/org/ultramine/server/util/CollectionUtil.java b/src/main/java/org/ultramine/server/util/CollectionUtil.java index f907b27..c1a1d2e 100644 --- a/src/main/java/org/ultramine/server/util/CollectionUtil.java +++ b/src/main/java/org/ultramine/server/util/CollectionUtil.java @@ -1,5 +1,12 @@ package org.ultramine.server.util; +import java.util.ArrayList; +import java.util.Collection; +import java.util.Collections; +import java.util.HashSet; +import java.util.List; +import java.util.Set; + public class CollectionUtil { private static final int INSERTIONSORT_THRESHOLD = 7; @@ -62,4 +69,34 @@ x[a] = x[b]; x[b] = t; } + + /** @return removed entries */ + public static > List removeOldestEntries(Collection collection, int entriesToRemove) + { + if(entriesToRemove <= 0) + throw new IllegalArgumentException(); + List list = new ArrayList<>(collection); + Collections.sort(list); + + if(entriesToRemove >= collection.size()) + { + collection.clear(); + return list; + } + + List listToRemove = list.subList(0, entriesToRemove); + if(collection instanceof Set) + collection.removeAll(listToRemove); + else + collection.removeAll(new HashSet<>(listToRemove)); + return listToRemove; + } + + /** @return removed entries */ + public static > List retainNewestEntries(Collection collection, int entriesToRetain) + { + if(entriesToRetain >= collection.size()) + return Collections.emptyList(); + return removeOldestEntries(collection, collection.size() - entriesToRetain); + } }