Remove cache eviction for model data, optimize
This commit is contained in:
parent
61b612c88a
commit
fb30820e2b
1 changed files with 29 additions and 35 deletions
|
@ -21,46 +21,35 @@ package net.minecraftforge.client.model;
|
||||||
|
|
||||||
import java.lang.ref.WeakReference;
|
import java.lang.ref.WeakReference;
|
||||||
import java.util.Collections;
|
import java.util.Collections;
|
||||||
import java.util.HashMap;
|
|
||||||
import java.util.HashSet;
|
import java.util.HashSet;
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
import java.util.Set;
|
import java.util.Set;
|
||||||
import java.util.concurrent.ConcurrentHashMap;
|
import java.util.concurrent.ConcurrentHashMap;
|
||||||
import java.util.concurrent.TimeUnit;
|
|
||||||
|
|
||||||
import javax.annotation.Nonnull;
|
|
||||||
import javax.annotation.Nullable;
|
import javax.annotation.Nullable;
|
||||||
|
|
||||||
import com.google.common.base.Preconditions;
|
import com.google.common.base.Preconditions;
|
||||||
import com.google.common.cache.CacheBuilder;
|
|
||||||
import com.google.common.cache.CacheLoader;
|
|
||||||
import com.google.common.cache.LoadingCache;
|
|
||||||
|
|
||||||
import net.minecraft.client.Minecraft;
|
import net.minecraft.client.Minecraft;
|
||||||
import net.minecraft.tileentity.TileEntity;
|
import net.minecraft.tileentity.TileEntity;
|
||||||
import net.minecraft.util.math.BlockPos;
|
import net.minecraft.util.math.BlockPos;
|
||||||
import net.minecraft.util.math.ChunkPos;
|
import net.minecraft.util.math.ChunkPos;
|
||||||
import net.minecraft.world.World;
|
import net.minecraft.world.World;
|
||||||
|
import net.minecraftforge.api.distmarker.Dist;
|
||||||
import net.minecraftforge.client.model.data.IModelData;
|
import net.minecraftforge.client.model.data.IModelData;
|
||||||
|
import net.minecraftforge.event.world.ChunkEvent;
|
||||||
|
import net.minecraftforge.eventbus.api.SubscribeEvent;
|
||||||
|
import net.minecraftforge.fml.common.Mod.EventBusSubscriber;
|
||||||
|
import net.minecraftforge.fml.common.Mod.EventBusSubscriber.Bus;
|
||||||
|
|
||||||
|
@EventBusSubscriber(modid = "forge", bus = Bus.FORGE, value = Dist.CLIENT)
|
||||||
public class ModelDataManager
|
public class ModelDataManager
|
||||||
{
|
{
|
||||||
private static WeakReference<World> currentWorld = new WeakReference<>(null);
|
private static WeakReference<World> currentWorld = new WeakReference<>(null);
|
||||||
|
|
||||||
private static final Map<ChunkPos, Set<BlockPos>> needModelDataRefresh = new HashMap<>();
|
private static final Map<ChunkPos, Set<BlockPos>> needModelDataRefresh = new ConcurrentHashMap<>();
|
||||||
|
|
||||||
private static final LoadingCache<ChunkPos, Map<BlockPos, IModelData>> modelDataCache = CacheBuilder.newBuilder()
|
private static final Map<ChunkPos, Map<BlockPos, IModelData>> modelDataCache = new ConcurrentHashMap<>();
|
||||||
.maximumSize(1000)
|
|
||||||
.concurrencyLevel(5)
|
|
||||||
.expireAfterAccess(30, TimeUnit.SECONDS)
|
|
||||||
.build(new CacheLoader<ChunkPos, Map<BlockPos, IModelData>>(){
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public Map<BlockPos, IModelData> load(@Nonnull ChunkPos key)
|
|
||||||
{
|
|
||||||
return new ConcurrentHashMap<>();
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
private static void cleanCaches(World world)
|
private static void cleanCaches(World world)
|
||||||
{
|
{
|
||||||
|
@ -68,7 +57,7 @@ public class ModelDataManager
|
||||||
{
|
{
|
||||||
currentWorld = new WeakReference<>(world);
|
currentWorld = new WeakReference<>(world);
|
||||||
needModelDataRefresh.clear();
|
needModelDataRefresh.clear();
|
||||||
modelDataCache.invalidateAll();
|
modelDataCache.clear();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -77,25 +66,20 @@ public class ModelDataManager
|
||||||
World world = te.getWorld();
|
World world = te.getWorld();
|
||||||
Preconditions.checkNotNull(world, "Tile entity world must not be null");
|
Preconditions.checkNotNull(world, "Tile entity world must not be null");
|
||||||
Preconditions.checkArgument(world == Minecraft.getInstance().world, "Cannot request a model data refresh for a world other than the current client world");
|
Preconditions.checkArgument(world == Minecraft.getInstance().world, "Cannot request a model data refresh for a world other than the current client world");
|
||||||
synchronized (needModelDataRefresh)
|
|
||||||
{
|
cleanCaches(world);
|
||||||
cleanCaches(world);
|
needModelDataRefresh.computeIfAbsent(new ChunkPos(te.getPos()), $ -> Collections.synchronizedSet(new HashSet<>()))
|
||||||
needModelDataRefresh.computeIfAbsent(new ChunkPos(te.getPos()), $ -> Collections.synchronizedSet(new HashSet<>()))
|
.add(te.getPos());
|
||||||
.add(te.getPos());
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private static void refreshModelData(World world, ChunkPos chunk)
|
private static void refreshModelData(World world, ChunkPos chunk)
|
||||||
{
|
{
|
||||||
Set<BlockPos> needUpdate;
|
cleanCaches(world);
|
||||||
synchronized (needModelDataRefresh)
|
Set<BlockPos> needUpdate = needModelDataRefresh.remove(chunk);
|
||||||
{
|
|
||||||
cleanCaches(world);
|
|
||||||
needUpdate = needModelDataRefresh.remove(chunk);
|
|
||||||
}
|
|
||||||
if (needUpdate != null)
|
if (needUpdate != null)
|
||||||
{
|
{
|
||||||
Map<BlockPos, IModelData> data = modelDataCache.getUnchecked(chunk);
|
Map<BlockPos, IModelData> data = modelDataCache.computeIfAbsent(chunk, $ -> new ConcurrentHashMap<>());
|
||||||
for (BlockPos pos : needUpdate)
|
for (BlockPos pos : needUpdate)
|
||||||
{
|
{
|
||||||
TileEntity toUpdate = world.getTileEntity(pos);
|
TileEntity toUpdate = world.getTileEntity(pos);
|
||||||
|
@ -107,6 +91,16 @@ public class ModelDataManager
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@SubscribeEvent
|
||||||
|
public static void onChunkUnload(ChunkEvent.Unload event)
|
||||||
|
{
|
||||||
|
if (!event.getChunk().getWorldForge().isRemote()) return;
|
||||||
|
|
||||||
|
ChunkPos chunk = event.getChunk().getPos();
|
||||||
|
needModelDataRefresh.remove(chunk);
|
||||||
|
modelDataCache.remove(chunk);
|
||||||
|
}
|
||||||
|
|
||||||
public static @Nullable IModelData getModelData(World world, BlockPos pos)
|
public static @Nullable IModelData getModelData(World world, BlockPos pos)
|
||||||
{
|
{
|
||||||
return getModelData(world, new ChunkPos(pos)).get(pos);
|
return getModelData(world, new ChunkPos(pos)).get(pos);
|
||||||
|
@ -115,6 +109,6 @@ public class ModelDataManager
|
||||||
public static Map<BlockPos, IModelData> getModelData(World world, ChunkPos pos)
|
public static Map<BlockPos, IModelData> getModelData(World world, ChunkPos pos)
|
||||||
{
|
{
|
||||||
refreshModelData(world, pos);
|
refreshModelData(world, pos);
|
||||||
return modelDataCache.getUnchecked(pos);
|
return modelDataCache.getOrDefault(pos, Collections.emptyMap());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in a new issue