mirror of
https://github.com/MinecraftForge/MinecraftForge.git
synced 2026-11-12 08:17:35 +00:00
Add RegisterCapabilitiesEvent (#8021)
This commit is contained in:
1 parent
d612dc3a6d
commit
aa97ddad8b
7 files changed
+112
-31
No files matched your search
@@ -33,6 +33,7 @@ import net.minecraft.world.level.storage.WorldData;
|
||||
import net.minecraft.world.level.storage.LevelStorageSource;
|
||||
import net.minecraftforge.api.distmarker.Dist;
|
||||
import net.minecraftforge.client.ForgeHooksClient;
|
||||
import net.minecraftforge.common.capabilities.RegisterCapabilitiesEvent;
|
||||
import net.minecraftforge.common.data.ExistingFileHelper;
|
||||
import net.minecraftforge.common.data.ForgeFluidTagsProvider;
|
||||
import net.minecraftforge.common.loot.GlobalLootModifierSerializer;
|
||||
@@ -150,6 +151,7 @@ public class ForgeMod implements WorldPersistenceHooks.WorldPersistenceHook
|
||||
WorldPersistenceHooks.addHook(this);
|
||||
WorldPersistenceHooks.addHook(new FMLWorldPersistenceHook());
|
||||
final IEventBus modEventBus = FMLJavaModLoadingContext.get().getModEventBus();
|
||||
modEventBus.addListener(this::registerCapabilities);
|
||||
modEventBus.addListener(this::preInit);
|
||||
modEventBus.addListener(this::gatherData);
|
||||
modEventBus.addListener(this::loadComplete);
|
||||
@@ -171,13 +173,16 @@ public class ForgeMod implements WorldPersistenceHooks.WorldPersistenceHook
|
||||
BiomeDictionary.init();
|
||||
}
|
||||
|
||||
public void registerCapabilities(RegisterCapabilitiesEvent event)
|
||||
{
|
||||
CapabilityItemHandler.register(event);
|
||||
CapabilityFluidHandler.register(event);
|
||||
CapabilityAnimation.register(event);
|
||||
CapabilityEnergy.register(event);
|
||||
}
|
||||
|
||||
public void preInit(FMLCommonSetupEvent evt)
|
||||
{
|
||||
CapabilityItemHandler.register();
|
||||
CapabilityFluidHandler.register();
|
||||
CapabilityAnimation.register();
|
||||
CapabilityEnergy.register();
|
||||
|
||||
VersionChecker.startVersionCheck();
|
||||
|
||||
registerArgumentTypes();
|
||||
|
||||
@@ -24,12 +24,12 @@ import java.lang.reflect.Method;
|
||||
import java.lang.reflect.Modifier;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collection;
|
||||
import java.util.Collections;
|
||||
import java.util.IdentityHashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Objects;
|
||||
|
||||
import net.minecraftforge.fml.ModLoader;
|
||||
import net.minecraftforge.forgespi.language.ModFileScanData;
|
||||
import org.apache.logging.log4j.LogManager;
|
||||
import org.apache.logging.log4j.Logger;
|
||||
@@ -43,7 +43,7 @@ import static net.minecraftforge.fml.Logging.CAPABILITIES;
|
||||
public enum CapabilityManager
|
||||
{
|
||||
INSTANCE;
|
||||
private static final Logger LOGGER = LogManager.getLogger();
|
||||
static final Logger LOGGER = LogManager.getLogger();
|
||||
private static final Type CAP_INJECT = Type.getType(CapabilityInject.class);
|
||||
|
||||
/**
|
||||
@@ -53,7 +53,9 @@ public enum CapabilityManager
|
||||
* This method is safe to call during parallel mod loading.
|
||||
*
|
||||
* @param type The class type to be registered
|
||||
* @deprecated use {@link RegisterCapabilitiesEvent}
|
||||
*/
|
||||
@Deprecated(forRemoval = true)
|
||||
public <T> void register(Class<T> type)
|
||||
{
|
||||
Objects.requireNonNull(type,"Attempted to register a capability with invalid type");
|
||||
@@ -71,7 +73,7 @@ public enum CapabilityManager
|
||||
providers.put(realName, cap);
|
||||
}
|
||||
|
||||
callbacks.getOrDefault(realName, Collections.emptyList()).forEach(func -> func.apply(cap));
|
||||
fireCallbacks(this.callbacks, List.of(cap));
|
||||
}
|
||||
|
||||
// INTERNAL
|
||||
@@ -79,21 +81,36 @@ public enum CapabilityManager
|
||||
private volatile IdentityHashMap<String, List<Function<Capability<?>, Object>>> callbacks;
|
||||
public void injectCapabilities(List<ModFileScanData> data)
|
||||
{
|
||||
final List<ModFileScanData.AnnotationData> capabilities = data.stream()
|
||||
final List<ModFileScanData.AnnotationData> elementsToInject = data.stream()
|
||||
.map(ModFileScanData::getAnnotations)
|
||||
.flatMap(Collection::stream)
|
||||
.filter(a -> CAP_INJECT.equals(a.annotationType()))
|
||||
.collect(Collectors.toList());
|
||||
final IdentityHashMap<String, List<Function<Capability<?>, Object>>> m = new IdentityHashMap<>();
|
||||
capabilities.forEach(entry -> attachCapabilityToMethod(m, entry));
|
||||
callbacks = m;
|
||||
final IdentityHashMap<String, List<Function<Capability<?>, Object>>> callbacks = new IdentityHashMap<>();
|
||||
elementsToInject.forEach(entry -> gatherCallbacks(callbacks, entry));
|
||||
|
||||
var event = new RegisterCapabilitiesEvent();
|
||||
ModLoader.get().postEvent(event);
|
||||
fireCallbacks(callbacks, event.getCapabilities().values());
|
||||
|
||||
// TODO 1.18: remove these fields
|
||||
this.providers.putAll(event.getCapabilities());
|
||||
this.callbacks = callbacks;
|
||||
}
|
||||
|
||||
private static void attachCapabilityToMethod(Map<String, List<Function<Capability<?>, Object>>> cbs, ModFileScanData.AnnotationData entry)
|
||||
private static void fireCallbacks(Map<String, List<Function<Capability<?>, Object>>> callbacks, Iterable<Capability<?>> caps)
|
||||
{
|
||||
final String targetClass = entry.clazz().getClassName();
|
||||
final String targetName = entry.memberName();
|
||||
Type type = (Type)entry.annotationData().get("value");
|
||||
for (var cap : caps)
|
||||
{
|
||||
callbacks.getOrDefault(cap.getName(), List.of()).forEach(f -> f.apply(cap));
|
||||
}
|
||||
}
|
||||
|
||||
private static void gatherCallbacks(Map<String, List<Function<Capability<?>, Object>>> callbacks, ModFileScanData.AnnotationData annotationData)
|
||||
{
|
||||
final String targetClass = annotationData.clazz().getClassName();
|
||||
final String targetName = annotationData.memberName();
|
||||
Type type = (Type)annotationData.annotationData().get("value");
|
||||
if (type == null)
|
||||
{
|
||||
LOGGER.warn(CAPABILITIES,"Unable to inject capability at {}.{} (Invalid Annotation)", targetClass, targetName);
|
||||
@@ -101,9 +118,9 @@ public enum CapabilityManager
|
||||
}
|
||||
final String capabilityName = type.getInternalName().replace('/', '.').intern();
|
||||
|
||||
List<Function<Capability<?>, Object>> list = cbs.computeIfAbsent(capabilityName, k -> new ArrayList<>());
|
||||
List<Function<Capability<?>, Object>> list = callbacks.computeIfAbsent(capabilityName, k -> new ArrayList<>());
|
||||
|
||||
if (entry.memberName().indexOf('(') > 0)
|
||||
if (annotationData.memberName().indexOf('(') > 0)
|
||||
{
|
||||
list.add(input -> {
|
||||
try
|
||||
|
||||
@@ -0,0 +1,60 @@
|
||||
/*
|
||||
* Minecraft Forge
|
||||
* Copyright (c) 2016-2021.
|
||||
*
|
||||
* This library is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU Lesser General Public
|
||||
* License as published by the Free Software Foundation version 2.1
|
||||
* of the License.
|
||||
*
|
||||
* This library is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
* Lesser General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public
|
||||
* License along with this library; if not, write to the Free Software
|
||||
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
|
||||
*/
|
||||
|
||||
package net.minecraftforge.common.capabilities;
|
||||
|
||||
import net.minecraftforge.eventbus.api.Event;
|
||||
import net.minecraftforge.fml.event.IModBusEvent;
|
||||
|
||||
import java.util.*;
|
||||
|
||||
import static net.minecraftforge.fml.Logging.CAPABILITIES;
|
||||
|
||||
/**
|
||||
* This event fires when it is time to register your capabilities.
|
||||
* @see Capability
|
||||
*/
|
||||
public final class RegisterCapabilitiesEvent extends Event implements IModBusEvent
|
||||
{
|
||||
|
||||
private final IdentityHashMap<String, Capability<?>> capabilities = new IdentityHashMap<>();
|
||||
|
||||
/**
|
||||
* Registers a capability to be consumed by others.
|
||||
* APIs who define the capability should call this.
|
||||
* To retrieve the Capability instance, use the @CapabilityInject annotation.
|
||||
*
|
||||
* @param type The type to be registered
|
||||
*/
|
||||
public <T> void register(Class<T> type)
|
||||
{
|
||||
Objects.requireNonNull(type,"Attempted to register a capability with invalid type");
|
||||
String realName = type.getName().intern();
|
||||
if (capabilities.putIfAbsent(realName, new Capability<>(realName)) != null) {
|
||||
CapabilityManager.LOGGER.error(CAPABILITIES, "Cannot register capability implementation multiple times : {}", realName);
|
||||
throw new IllegalArgumentException("Cannot register a capability implementation multiple times : "+ realName);
|
||||
}
|
||||
}
|
||||
|
||||
IdentityHashMap<String, Capability<?>> getCapabilities()
|
||||
{
|
||||
return this.capabilities;
|
||||
}
|
||||
|
||||
}
|
||||
@@ -19,11 +19,10 @@
|
||||
|
||||
package net.minecraftforge.common.model.animation;
|
||||
|
||||
import net.minecraft.nbt.Tag;
|
||||
import net.minecraft.core.Direction;
|
||||
import net.minecraftforge.common.capabilities.Capability;
|
||||
import net.minecraftforge.common.capabilities.CapabilityInject;
|
||||
import net.minecraftforge.common.capabilities.CapabilityManager;
|
||||
import net.minecraftforge.common.capabilities.RegisterCapabilitiesEvent;
|
||||
import net.minecraftforge.common.capabilities.ICapabilityProvider;
|
||||
import net.minecraftforge.common.util.LazyOptional;
|
||||
|
||||
@@ -35,9 +34,9 @@ public class CapabilityAnimation
|
||||
@CapabilityInject(IAnimationStateMachine.class)
|
||||
public static Capability<IAnimationStateMachine> ANIMATION_CAPABILITY = null;
|
||||
|
||||
public static void register()
|
||||
public static void register(RegisterCapabilitiesEvent event)
|
||||
{
|
||||
CapabilityManager.INSTANCE.register(IAnimationStateMachine.class);
|
||||
event.register(IAnimationStateMachine.class);
|
||||
}
|
||||
|
||||
public static class DefaultItemAnimationCapabilityProvider implements ICapabilityProvider
|
||||
|
||||
@@ -26,8 +26,8 @@ public class CapabilityEnergy
|
||||
@CapabilityInject(IEnergyStorage.class)
|
||||
public static Capability<IEnergyStorage> ENERGY = null;
|
||||
|
||||
public static void register()
|
||||
public static void register(RegisterCapabilitiesEvent event)
|
||||
{
|
||||
CapabilityManager.INSTANCE.register(IEnergyStorage.class);
|
||||
event.register(IEnergyStorage.class);
|
||||
}
|
||||
}
|
||||
@@ -21,7 +21,7 @@ package net.minecraftforge.fluids.capability;
|
||||
|
||||
import net.minecraftforge.common.capabilities.Capability;
|
||||
import net.minecraftforge.common.capabilities.CapabilityInject;
|
||||
import net.minecraftforge.common.capabilities.CapabilityManager;
|
||||
import net.minecraftforge.common.capabilities.RegisterCapabilitiesEvent;
|
||||
|
||||
public class CapabilityFluidHandler
|
||||
{
|
||||
@@ -30,10 +30,10 @@ public class CapabilityFluidHandler
|
||||
@CapabilityInject(IFluidHandlerItem.class)
|
||||
public static Capability<IFluidHandlerItem> FLUID_HANDLER_ITEM_CAPABILITY = null;
|
||||
|
||||
public static void register()
|
||||
public static void register(RegisterCapabilitiesEvent event)
|
||||
{
|
||||
CapabilityManager.INSTANCE.register(IFluidHandler.class);
|
||||
event.register(IFluidHandler.class);
|
||||
|
||||
CapabilityManager.INSTANCE.register(IFluidHandlerItem.class);
|
||||
event.register(IFluidHandlerItem.class);
|
||||
}
|
||||
}
|
||||
@@ -21,16 +21,16 @@ package net.minecraftforge.items;
|
||||
|
||||
import net.minecraftforge.common.capabilities.Capability;
|
||||
import net.minecraftforge.common.capabilities.CapabilityInject;
|
||||
import net.minecraftforge.common.capabilities.CapabilityManager;
|
||||
import net.minecraftforge.common.capabilities.RegisterCapabilitiesEvent;
|
||||
|
||||
public class CapabilityItemHandler
|
||||
{
|
||||
@CapabilityInject(IItemHandler.class)
|
||||
public static Capability<IItemHandler> ITEM_HANDLER_CAPABILITY = null;
|
||||
|
||||
public static void register()
|
||||
public static void register(RegisterCapabilitiesEvent event)
|
||||
{
|
||||
CapabilityManager.INSTANCE.register(IItemHandler.class);
|
||||
event.register(IItemHandler.class);
|
||||
}
|
||||
|
||||
}
|
||||
Reference in new issue
Block a user