mirror of
https://github.com/SquidDev-CC/CC-Tweaked
synced 2024-12-15 12:40:30 +00:00
Cleanup resource mount reloading
- Subscribe to the "on add reload listener" event, otherwise we don't get reloads beyond the first one! This means we no longer need to cast the resource manager to a reloadable one. - Change the mount cache so it's keyed on path, rather than "path ✕ manager". - Update the reload listener just to use the mount cache, rather than having its own separate list. I really don't understand what I was thinking before.
This commit is contained in:
parent
c2dc8bf675
commit
d3563a3854
@ -28,6 +28,7 @@ import dan200.computercraft.shared.peripheral.modem.wireless.WirelessNetwork;
|
|||||||
import dan200.computercraft.shared.util.IDAssigner;
|
import dan200.computercraft.shared.util.IDAssigner;
|
||||||
import dan200.computercraft.shared.wired.WiredNode;
|
import dan200.computercraft.shared.wired.WiredNode;
|
||||||
import net.minecraft.resources.IReloadableResourceManager;
|
import net.minecraft.resources.IReloadableResourceManager;
|
||||||
|
import net.minecraft.resources.IResourceManager;
|
||||||
import net.minecraft.tileentity.TileEntity;
|
import net.minecraft.tileentity.TileEntity;
|
||||||
import net.minecraft.util.Direction;
|
import net.minecraft.util.Direction;
|
||||||
import net.minecraft.util.ResourceLocation;
|
import net.minecraft.util.ResourceLocation;
|
||||||
@ -101,7 +102,7 @@ public final class ComputerCraftAPIImpl implements IComputerCraftAPI
|
|||||||
@Override
|
@Override
|
||||||
public IMount createResourceMount( @Nonnull String domain, @Nonnull String subPath )
|
public IMount createResourceMount( @Nonnull String domain, @Nonnull String subPath )
|
||||||
{
|
{
|
||||||
IReloadableResourceManager manager = (IReloadableResourceManager) ServerLifecycleHooks.getCurrentServer().getDataPackRegistries().getResourceManager();
|
IResourceManager manager = ServerLifecycleHooks.getCurrentServer().getDataPackRegistries().getResourceManager();
|
||||||
ResourceMount mount = ResourceMount.get( domain, subPath, manager );
|
ResourceMount mount = ResourceMount.get( domain, subPath, manager );
|
||||||
return mount.exists( "" ) ? mount : null;
|
return mount.exists( "" ) ? mount : null;
|
||||||
}
|
}
|
||||||
|
@ -7,19 +7,17 @@ package dan200.computercraft.core.filesystem;
|
|||||||
|
|
||||||
import com.google.common.cache.Cache;
|
import com.google.common.cache.Cache;
|
||||||
import com.google.common.cache.CacheBuilder;
|
import com.google.common.cache.CacheBuilder;
|
||||||
import com.google.common.collect.MapMaker;
|
|
||||||
import com.google.common.io.ByteStreams;
|
import com.google.common.io.ByteStreams;
|
||||||
import dan200.computercraft.ComputerCraft;
|
import dan200.computercraft.ComputerCraft;
|
||||||
import dan200.computercraft.api.filesystem.IMount;
|
import dan200.computercraft.api.filesystem.IMount;
|
||||||
import dan200.computercraft.core.apis.handles.ArrayByteChannel;
|
import dan200.computercraft.core.apis.handles.ArrayByteChannel;
|
||||||
import dan200.computercraft.shared.util.IoUtil;
|
import dan200.computercraft.shared.util.IoUtil;
|
||||||
import net.minecraft.resources.IReloadableResourceManager;
|
import net.minecraft.client.resources.ReloadListener;
|
||||||
|
import net.minecraft.profiler.IProfiler;
|
||||||
import net.minecraft.resources.IResource;
|
import net.minecraft.resources.IResource;
|
||||||
import net.minecraft.resources.IResourceManager;
|
import net.minecraft.resources.IResourceManager;
|
||||||
import net.minecraft.util.ResourceLocation;
|
import net.minecraft.util.ResourceLocation;
|
||||||
import net.minecraft.util.ResourceLocationException;
|
import net.minecraft.util.ResourceLocationException;
|
||||||
import net.minecraftforge.resource.IResourceType;
|
|
||||||
import net.minecraftforge.resource.ISelectiveResourceReloadListener;
|
|
||||||
|
|
||||||
import javax.annotation.Nonnull;
|
import javax.annotation.Nonnull;
|
||||||
import javax.annotation.Nullable;
|
import javax.annotation.Nullable;
|
||||||
@ -28,9 +26,10 @@ import java.io.IOException;
|
|||||||
import java.io.InputStream;
|
import java.io.InputStream;
|
||||||
import java.nio.channels.Channels;
|
import java.nio.channels.Channels;
|
||||||
import java.nio.channels.ReadableByteChannel;
|
import java.nio.channels.ReadableByteChannel;
|
||||||
import java.util.*;
|
import java.util.HashMap;
|
||||||
|
import java.util.List;
|
||||||
|
import java.util.Map;
|
||||||
import java.util.concurrent.TimeUnit;
|
import java.util.concurrent.TimeUnit;
|
||||||
import java.util.function.Predicate;
|
|
||||||
|
|
||||||
public final class ResourceMount implements IMount
|
public final class ResourceMount implements IMount
|
||||||
{
|
{
|
||||||
@ -58,50 +57,37 @@ public final class ResourceMount implements IMount
|
|||||||
.<FileEntry, byte[]>weigher( ( k, v ) -> v.length )
|
.<FileEntry, byte[]>weigher( ( k, v ) -> v.length )
|
||||||
.build();
|
.build();
|
||||||
|
|
||||||
private static final MapMaker CACHE_TEMPLATE = new MapMaker().weakValues().concurrencyLevel( 1 );
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Maintain a cache of currently loaded resource mounts. This cache is invalidated when currentManager changes.
|
* Maintain a cache of currently loaded resource mounts. This cache is invalidated when currentManager changes.
|
||||||
*/
|
*/
|
||||||
private static final Map<IReloadableResourceManager, Map<ResourceLocation, ResourceMount>> MOUNT_CACHE = new WeakHashMap<>( 2 );
|
private static final Map<ResourceLocation, ResourceMount> MOUNT_CACHE = new HashMap<>( 2 );
|
||||||
|
|
||||||
private final String namespace;
|
private final String namespace;
|
||||||
private final String subPath;
|
private final String subPath;
|
||||||
private final IReloadableResourceManager manager;
|
private IResourceManager manager;
|
||||||
|
|
||||||
@Nullable
|
@Nullable
|
||||||
private FileEntry root;
|
private FileEntry root;
|
||||||
|
|
||||||
public static ResourceMount get( String namespace, String subPath, IReloadableResourceManager manager )
|
public static ResourceMount get( String namespace, String subPath, IResourceManager manager )
|
||||||
{
|
{
|
||||||
Map<ResourceLocation, ResourceMount> cache;
|
ResourceLocation path = new ResourceLocation( namespace, subPath );
|
||||||
|
|
||||||
synchronized( MOUNT_CACHE )
|
synchronized( MOUNT_CACHE )
|
||||||
{
|
{
|
||||||
cache = MOUNT_CACHE.get( manager );
|
ResourceMount mount = MOUNT_CACHE.get( path );
|
||||||
if( cache == null ) MOUNT_CACHE.put( manager, cache = CACHE_TEMPLATE.makeMap() );
|
if( mount == null ) MOUNT_CACHE.put( path, mount = new ResourceMount( namespace, subPath, manager ) );
|
||||||
}
|
|
||||||
|
|
||||||
ResourceLocation path = new ResourceLocation( namespace, subPath );
|
|
||||||
synchronized( cache )
|
|
||||||
{
|
|
||||||
ResourceMount mount = cache.get( path );
|
|
||||||
if( mount == null ) cache.put( path, mount = new ResourceMount( namespace, subPath, manager ) );
|
|
||||||
return mount;
|
return mount;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private ResourceMount( String namespace, String subPath, IReloadableResourceManager manager )
|
private ResourceMount( String namespace, String subPath, IResourceManager manager )
|
||||||
{
|
{
|
||||||
this.namespace = namespace;
|
this.namespace = namespace;
|
||||||
this.subPath = subPath;
|
this.subPath = subPath;
|
||||||
this.manager = manager;
|
load( manager );
|
||||||
|
|
||||||
Listener.INSTANCE.add( manager, this );
|
|
||||||
if( root == null ) load();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private void load()
|
private void load( IResourceManager manager )
|
||||||
{
|
{
|
||||||
boolean hasAny = false;
|
boolean hasAny = false;
|
||||||
String existingNamespace = null;
|
String existingNamespace = null;
|
||||||
@ -118,6 +104,7 @@ public final class ResourceMount implements IMount
|
|||||||
hasAny = true;
|
hasAny = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
this.manager = manager;
|
||||||
root = hasAny ? newRoot : null;
|
root = hasAny ? newRoot : null;
|
||||||
|
|
||||||
if( !hasAny )
|
if( !hasAny )
|
||||||
@ -293,35 +280,30 @@ public final class ResourceMount implements IMount
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* A {@link ISelectiveResourceReloadListener} which reloads any associated mounts.
|
* A {@link ReloadListener} which reloads any associated mounts and correctly updates the resource manager they
|
||||||
*
|
* point to.
|
||||||
* While people should really be keeping a permanent reference to this, some people construct it every
|
|
||||||
* method call, so let's make this as small as possible.
|
|
||||||
*/
|
*/
|
||||||
static class Listener implements ISelectiveResourceReloadListener
|
public static final ReloadListener<Void> RELOAD_LISTENER = new ReloadListener<Void>()
|
||||||
{
|
{
|
||||||
private static final Listener INSTANCE = new Listener();
|
@Nonnull
|
||||||
|
|
||||||
private final Set<ResourceMount> mounts = Collections.newSetFromMap( new WeakHashMap<>() );
|
|
||||||
private final Set<IReloadableResourceManager> managers = Collections.newSetFromMap( new WeakHashMap<>() );
|
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void onResourceManagerReload( @Nonnull IResourceManager manager )
|
protected Void prepare( @Nonnull IResourceManager manager, @Nonnull IProfiler profiler )
|
||||||
{
|
{
|
||||||
// FIXME: Remove this. We need this patch in order to prevent trying to load ReloadRequirements.
|
profiler.push( "Reloading ComputerCraft mounts" );
|
||||||
onResourceManagerReload( manager, x -> true );
|
try
|
||||||
|
{
|
||||||
|
for( ResourceMount mount : MOUNT_CACHE.values() ) mount.load( manager );
|
||||||
|
}
|
||||||
|
finally
|
||||||
|
{
|
||||||
|
profiler.pop();
|
||||||
|
}
|
||||||
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public synchronized void onResourceManagerReload( @Nonnull IResourceManager manager, @Nonnull Predicate<IResourceType> predicate )
|
protected void apply( @Nonnull Void result, @Nonnull IResourceManager manager, @Nonnull IProfiler profiler )
|
||||||
{
|
{
|
||||||
for( ResourceMount mount : mounts ) mount.load();
|
|
||||||
}
|
|
||||||
|
|
||||||
synchronized void add( IReloadableResourceManager manager, ResourceMount mount )
|
|
||||||
{
|
|
||||||
if( managers.add( manager ) ) manager.registerReloadListener( this );
|
|
||||||
mounts.add( mount );
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
};
|
||||||
}
|
}
|
||||||
|
@ -8,6 +8,7 @@ package dan200.computercraft.shared;
|
|||||||
import dan200.computercraft.ComputerCraft;
|
import dan200.computercraft.ComputerCraft;
|
||||||
import dan200.computercraft.core.apis.http.NetworkUtils;
|
import dan200.computercraft.core.apis.http.NetworkUtils;
|
||||||
import dan200.computercraft.core.computer.MainThread;
|
import dan200.computercraft.core.computer.MainThread;
|
||||||
|
import dan200.computercraft.core.filesystem.ResourceMount;
|
||||||
import dan200.computercraft.core.tracking.ComputerMBean;
|
import dan200.computercraft.core.tracking.ComputerMBean;
|
||||||
import dan200.computercraft.core.tracking.Tracking;
|
import dan200.computercraft.core.tracking.Tracking;
|
||||||
import dan200.computercraft.shared.command.CommandComputerCraft;
|
import dan200.computercraft.shared.command.CommandComputerCraft;
|
||||||
@ -23,6 +24,7 @@ import net.minecraft.loot.TableLootEntry;
|
|||||||
import net.minecraft.server.MinecraftServer;
|
import net.minecraft.server.MinecraftServer;
|
||||||
import net.minecraft.server.dedicated.DedicatedServer;
|
import net.minecraft.server.dedicated.DedicatedServer;
|
||||||
import net.minecraft.util.ResourceLocation;
|
import net.minecraft.util.ResourceLocation;
|
||||||
|
import net.minecraftforge.event.AddReloadListenerEvent;
|
||||||
import net.minecraftforge.event.LootTableLoadEvent;
|
import net.minecraftforge.event.LootTableLoadEvent;
|
||||||
import net.minecraftforge.event.RegisterCommandsEvent;
|
import net.minecraftforge.event.RegisterCommandsEvent;
|
||||||
import net.minecraftforge.event.TickEvent;
|
import net.minecraftforge.event.TickEvent;
|
||||||
@ -138,4 +140,10 @@ public final class CommonHooks
|
|||||||
.name( "computercraft_treasure" )
|
.name( "computercraft_treasure" )
|
||||||
.build() );
|
.build() );
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@SubscribeEvent
|
||||||
|
public static void onAddReloadListeners( AddReloadListenerEvent event )
|
||||||
|
{
|
||||||
|
event.addListener( ResourceMount.RELOAD_LISTENER );
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user