Invalidate capabilities that we attach to vanilla entities and TileEntities. Closes #5307

This commit is contained in:
LexManos committed 2019-02-06 22:55:17 -08:00
1 parent d930c8ae8b
commit 0b1b3c68fa
13 files changed
+139 -53

No files matched your search

@@ -52,18 +52,20 @@ public final class CapabilityDispatcher implements INBTSerializable<NBTTagCompou
private ICapabilityProvider[] caps;
private INBTSerializable<INBTBase>[] writers;
private String[] names;
private final List<Runnable> listeners;
public CapabilityDispatcher(Map<ResourceLocation, ICapabilityProvider> list)
public CapabilityDispatcher(Map<ResourceLocation, ICapabilityProvider> list, List<Runnable> listeners)
{
this(list, null);
this(list, listeners, null);
}
@SuppressWarnings("unchecked")
public CapabilityDispatcher(Map<ResourceLocation, ICapabilityProvider> list, @Nullable ICapabilityProvider parent)
public CapabilityDispatcher(Map<ResourceLocation, ICapabilityProvider> list, List<Runnable> listeners, @Nullable ICapabilityProvider parent)
{
List<ICapabilityProvider> lstCaps = Lists.newArrayList();
List<INBTSerializable<INBTBase>> lstWriters = Lists.newArrayList();
List<String> lstNames = Lists.newArrayList();
this.listeners = listeners;
if (parent != null) // Parents go first!
{
@@ -134,4 +136,9 @@ public final class CapabilityDispatcher implements INBTSerializable<NBTTagCompou
if (this.writers.length == 0) return other.writers.length == 0;
return this.serializeNBT().equals(other.serializeNBT());
}
public void invalidate()
{
this.listeners.forEach(Runnable::run);
}
}
@@ -35,24 +35,25 @@ public abstract class CapabilityProvider<B extends CapabilityProvider<B>> implem
{
private final @Nonnull Class<B> baseClass;
private @Nullable CapabilityDispatcher capabilities;
private boolean valid = true;
protected CapabilityProvider(Class<B> baseClass)
{
this.baseClass = baseClass;
}
protected final void gatherCapabilities() { gatherCapabilities(null); }
protected final void gatherCapabilities(@Nullable ICapabilityProvider parent)
{
this.capabilities = ForgeEventFactory.gatherCapabilities(baseClass, this, parent);
}
protected final @Nullable CapabilityDispatcher getCapabilities()
{
return this.capabilities;
}
public final boolean areCapsCompatible(CapabilityProvider<B> other)
{
return areCapsCompatible(other.getCapabilities());
@@ -71,23 +72,23 @@ public abstract class CapabilityProvider<B extends CapabilityProvider<B>> implem
{
return other.areCompatible(null);
}
}
}
else
{
return disp.areCompatible(other);
}
}
protected final @Nullable NBTTagCompound serializeCaps()
{
final CapabilityDispatcher disp = getCapabilities();
if (disp != null)
if (disp != null)
{
return disp.serializeNBT();
}
return null;
}
protected final void deserializeCaps(NBTTagCompound tag)
{
final CapabilityDispatcher disp = getCapabilities();
@@ -97,11 +98,19 @@ public abstract class CapabilityProvider<B extends CapabilityProvider<B>> implem
}
}
protected void invalidateCaps()
{
this.valid = false;
final CapabilityDispatcher disp = getCapabilities();
if (disp != null)
disp.invalidate();
}
@Override
@Nonnull
public <T> LazyOptional<T> getCapability(@Nonnull Capability<T> cap, @Nullable EnumFacing side)
{
final CapabilityDispatcher disp = getCapabilities();
return disp == null ? LazyOptional.empty() : disp.getCapability(cap, side);
return !valid || disp == null ? LazyOptional.empty() : disp.getCapability(cap, side);
}
}
@@ -20,8 +20,10 @@
package net.minecraftforge.event;
import java.util.Collections;
import java.util.List;
import java.util.Map;
import com.google.common.collect.Lists;
import com.google.common.collect.Maps;
import net.minecraft.util.ResourceLocation;
@@ -40,6 +42,8 @@ public class AttachCapabilitiesEvent<T> extends GenericEvent<T>
private final T obj;
private final Map<ResourceLocation, ICapabilityProvider> caps = Maps.newLinkedHashMap();
private final Map<ResourceLocation, ICapabilityProvider> view = Collections.unmodifiableMap(caps);
private final List<Runnable> listeners = Lists.newArrayList();
private final List<Runnable> listenersView = Collections.unmodifiableList(listeners);
public AttachCapabilitiesEvent(Class<T> type, T obj)
{
@@ -77,4 +81,20 @@ public class AttachCapabilitiesEvent<T> extends GenericEvent<T>
{
return view;
}
/**
* Adds a callback that is fired when the attacked object is invalidated.
* Such as a Entity/TileEntity being removed from world.
* All attached providers should invalidate all of their held capability instances.
*/
public void addListener(Runnable listener)
{
this.listeners.add(listener);
}
public List<Runnable> getListeners()
{
return this.listenersView;
}
}
@@ -569,7 +569,7 @@ public class ForgeEventFactory
private static CapabilityDispatcher gatherCapabilities(AttachCapabilitiesEvent<?> event, @Nullable ICapabilityProvider parent)
{
MinecraftForge.EVENT_BUS.post(event);
return event.getCapabilities().size() > 0 || parent != null ? new CapabilityDispatcher(event.getCapabilities(), parent) : null;
return event.getCapabilities().size() > 0 || parent != null ? new CapabilityDispatcher(event.getCapabilities(), event.getListeners(), parent) : null;
}
public static boolean fireSleepingLocationCheck(EntityPlayer player, BlockPos sleepingLocation)
@@ -634,7 +634,7 @@ public class ForgeEventFactory
{
return MinecraftForge.EVENT_BUS.post(new ProjectileImpactEvent.Throwable(throwable, ray));
}
public static boolean onReplaceBiomeBlocks(IChunkGenerator<?> gen, IChunk chunk, IWorld world)
{
ChunkGeneratorEvent.ReplaceBiomeBlocks event = new ChunkGeneratorEvent.ReplaceBiomeBlocks(gen, chunk, world);