diff --git a/cardinal-components-base/src/main/java/dev/onyxstudios/cca/internal/base/ComponentRegistrationInitializer.java b/cardinal-components-base/src/main/java/dev/onyxstudios/cca/internal/base/ComponentRegistrationInitializer.java new file mode 100644 index 00000000..60ad97f0 --- /dev/null +++ b/cardinal-components-base/src/main/java/dev/onyxstudios/cca/internal/base/ComponentRegistrationInitializer.java @@ -0,0 +1,29 @@ +/* + * Cardinal-Components-API + * Copyright (C) 2019-2020 OnyxStudios + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all + * copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. + * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, + * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR + * OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE + * OR OTHER DEALINGS IN THE SOFTWARE. + */ +package dev.onyxstudios.cca.internal.base; + +/** + * Internal marker for {@code "cardinal-components"} entrypoints + */ +public interface ComponentRegistrationInitializer { +} diff --git a/cardinal-components-base/src/main/java/dev/onyxstudios/cca/internal/base/asm/StaticComponentPluginBase.java b/cardinal-components-base/src/main/java/dev/onyxstudios/cca/internal/base/asm/StaticComponentPluginBase.java index ac916340..33d65cd6 100644 --- a/cardinal-components-base/src/main/java/dev/onyxstudios/cca/internal/base/asm/StaticComponentPluginBase.java +++ b/cardinal-components-base/src/main/java/dev/onyxstudios/cca/internal/base/asm/StaticComponentPluginBase.java @@ -26,8 +26,10 @@ import dev.onyxstudios.cca.api.v3.component.ComponentContainer; import dev.onyxstudios.cca.api.v3.component.ComponentFactory; import dev.onyxstudios.cca.api.v3.component.ComponentKey; +import dev.onyxstudios.cca.internal.base.ComponentRegistrationInitializer; import dev.onyxstudios.cca.internal.base.LazyDispatcher; import net.fabricmc.fabric.api.event.Event; +import net.fabricmc.loader.api.FabricLoader; import net.fabricmc.loader.api.entrypoint.EntrypointContainer; import net.fabricmc.loader.api.metadata.ModMetadata; import org.objectweb.asm.MethodVisitor; @@ -38,6 +40,7 @@ import java.io.IOException; import java.lang.reflect.Constructor; import java.lang.reflect.Method; +import java.util.ArrayList; import java.util.Arrays; import java.util.Collection; import java.util.Collections; @@ -156,6 +159,18 @@ public static void processInitializers(Collection> en } } + public static Collection> getComponentEntrypoints(String key, Class type) { + Collection> generic = FabricLoader.getInstance().getEntrypointContainers("cardinal-components", ComponentRegistrationInitializer.class); + Collection> specific = new ArrayList<>(FabricLoader.getInstance().getEntrypointContainers(key, type)); + for (EntrypointContainer container : generic) { + if (type.isInstance(container.getEntrypoint())) { + @SuppressWarnings("unchecked") EntrypointContainer c = (EntrypointContainer) container; + specific.add(c); + } + } + return specific; + } + protected abstract Collection> getEntrypoints(); protected abstract void dispatchRegistration(I entrypoint); diff --git a/cardinal-components-block/src/main/java/dev/onyxstudios/cca/api/v3/block/BlockComponentInitializer.java b/cardinal-components-block/src/main/java/dev/onyxstudios/cca/api/v3/block/BlockComponentInitializer.java index 479278c0..217783d7 100644 --- a/cardinal-components-block/src/main/java/dev/onyxstudios/cca/api/v3/block/BlockComponentInitializer.java +++ b/cardinal-components-block/src/main/java/dev/onyxstudios/cca/api/v3/block/BlockComponentInitializer.java @@ -22,19 +22,20 @@ */ package dev.onyxstudios.cca.api.v3.block; +import dev.onyxstudios.cca.internal.base.ComponentRegistrationInitializer; import net.minecraft.block.entity.BlockEntity; import org.jetbrains.annotations.ApiStatus; /** * Entrypoint getting invoked to register static block component factories. * - *

The entrypoint is exposed as {@code cardinal-components-block} in the mod json and runs for any environment. + *

The entrypoint is exposed as either {@code "cardinal-components"} or {@code "cardinal-components-block"} in the mod json and runs for any environment. * It usually executes right before the first {@link BlockEntity} instance is created. * * @since 2.5.0 */ @ApiStatus.Experimental -public interface BlockComponentInitializer { +public interface BlockComponentInitializer extends ComponentRegistrationInitializer { /** * Called to register component factories for statically declared component types. * diff --git a/cardinal-components-block/src/main/java/dev/onyxstudios/cca/internal/block/StaticBlockComponentPlugin.java b/cardinal-components-block/src/main/java/dev/onyxstudios/cca/internal/block/StaticBlockComponentPlugin.java index 71d29a2e..73b68bb7 100644 --- a/cardinal-components-block/src/main/java/dev/onyxstudios/cca/internal/block/StaticBlockComponentPlugin.java +++ b/cardinal-components-block/src/main/java/dev/onyxstudios/cca/internal/block/StaticBlockComponentPlugin.java @@ -176,7 +176,7 @@ public Registration beginRegi @Override protected void init() { StaticComponentPluginBase.processInitializers( - FabricLoader.getInstance().getEntrypointContainers("cardinal-components-block", BlockComponentInitializer.class), + StaticComponentPluginBase.getComponentEntrypoints("cardinal-components-block", BlockComponentInitializer.class), initializer -> initializer.registerBlockComponentFactories(this) ); this.wildcard = this.blockComponentFactories.getOrDefault(null, Collections.emptyMap()); diff --git a/cardinal-components-chunk/src/main/java/dev/onyxstudios/cca/api/v3/chunk/ChunkComponentInitializer.java b/cardinal-components-chunk/src/main/java/dev/onyxstudios/cca/api/v3/chunk/ChunkComponentInitializer.java index faa7ec90..c5a1471e 100644 --- a/cardinal-components-chunk/src/main/java/dev/onyxstudios/cca/api/v3/chunk/ChunkComponentInitializer.java +++ b/cardinal-components-chunk/src/main/java/dev/onyxstudios/cca/api/v3/chunk/ChunkComponentInitializer.java @@ -22,17 +22,18 @@ */ package dev.onyxstudios.cca.api.v3.chunk; +import dev.onyxstudios.cca.internal.base.ComponentRegistrationInitializer; import net.minecraft.world.chunk.Chunk; /** * Entrypoint getting invoked to register static chunk component factories. * - *

The entrypoint is exposed as {@code cardinal-components-chunk} in the mod json and runs for any environment. + *

The entrypoint is exposed as either {@code "cardinal-components"} or {@code "cardinal-components-chunk"} in the mod json and runs for any environment. * It usually executes right before the first {@link Chunk} instance is created. * * @since 2.4.0 */ -public interface ChunkComponentInitializer { +public interface ChunkComponentInitializer extends ComponentRegistrationInitializer { /** * Called to register component factories for statically declared component types. * diff --git a/cardinal-components-chunk/src/main/java/dev/onyxstudios/cca/internal/chunk/StaticChunkComponentPlugin.java b/cardinal-components-chunk/src/main/java/dev/onyxstudios/cca/internal/chunk/StaticChunkComponentPlugin.java index 2b102eb8..7114c332 100644 --- a/cardinal-components-chunk/src/main/java/dev/onyxstudios/cca/internal/chunk/StaticChunkComponentPlugin.java +++ b/cardinal-components-chunk/src/main/java/dev/onyxstudios/cca/internal/chunk/StaticChunkComponentPlugin.java @@ -51,7 +51,7 @@ private StaticChunkComponentPlugin() { @Override protected Collection> getEntrypoints() { - return FabricLoader.getInstance().getEntrypointContainers("cardinal-components-chunk", ChunkComponentInitializer.class); + return getComponentEntrypoints("cardinal-components-chunk", ChunkComponentInitializer.class); } @Override diff --git a/cardinal-components-entity/src/main/java/dev/onyxstudios/cca/api/v3/entity/EntityComponentInitializer.java b/cardinal-components-entity/src/main/java/dev/onyxstudios/cca/api/v3/entity/EntityComponentInitializer.java index 83eadba0..91cc349c 100644 --- a/cardinal-components-entity/src/main/java/dev/onyxstudios/cca/api/v3/entity/EntityComponentInitializer.java +++ b/cardinal-components-entity/src/main/java/dev/onyxstudios/cca/api/v3/entity/EntityComponentInitializer.java @@ -22,6 +22,7 @@ */ package dev.onyxstudios.cca.api.v3.entity; +import dev.onyxstudios.cca.internal.base.ComponentRegistrationInitializer; import net.minecraft.entity.Entity; /** @@ -32,7 +33,7 @@ * * @since 2.4.0 */ -public interface EntityComponentInitializer { +public interface EntityComponentInitializer extends ComponentRegistrationInitializer { /** * Called to register component factories for statically declared component types. * diff --git a/cardinal-components-entity/src/main/java/dev/onyxstudios/cca/internal/entity/StaticEntityComponentPlugin.java b/cardinal-components-entity/src/main/java/dev/onyxstudios/cca/internal/entity/StaticEntityComponentPlugin.java index 7b5f93c6..ca0c2cd0 100644 --- a/cardinal-components-entity/src/main/java/dev/onyxstudios/cca/internal/entity/StaticEntityComponentPlugin.java +++ b/cardinal-components-entity/src/main/java/dev/onyxstudios/cca/internal/entity/StaticEntityComponentPlugin.java @@ -102,7 +102,7 @@ public Class> spinDedicatedFactory(Class @Override protected void init() { StaticComponentPluginBase.processInitializers( - FabricLoader.getInstance().getEntrypointContainers("cardinal-components-entity", EntityComponentInitializer.class), + StaticComponentPluginBase.getComponentEntrypoints("cardinal-components-entity", EntityComponentInitializer.class), initializer -> initializer.registerEntityComponentFactories(this) ); } diff --git a/cardinal-components-item/src/main/java/dev/onyxstudios/cca/api/v3/item/ItemComponentInitializer.java b/cardinal-components-item/src/main/java/dev/onyxstudios/cca/api/v3/item/ItemComponentInitializer.java index 54f54e64..00702731 100644 --- a/cardinal-components-item/src/main/java/dev/onyxstudios/cca/api/v3/item/ItemComponentInitializer.java +++ b/cardinal-components-item/src/main/java/dev/onyxstudios/cca/api/v3/item/ItemComponentInitializer.java @@ -22,17 +22,18 @@ */ package dev.onyxstudios.cca.api.v3.item; +import dev.onyxstudios.cca.internal.base.ComponentRegistrationInitializer; import net.minecraft.item.ItemStack; /** * Entrypoint getting invoked to register static item component factories. * - *

The entrypoint is exposed as {@code "cardinal-components-item"} in the mod json and runs for any environment. + *

The entrypoint is exposed as either {@code "cardinal-components"} or {@code "cardinal-components-item"} in the mod json and runs for any environment. * It usually executes right before the first {@link ItemStack} instance is created. * * @since 2.4.0 */ -public interface ItemComponentInitializer { +public interface ItemComponentInitializer extends ComponentRegistrationInitializer { /** * Called to register component factories for statically declared component types. * diff --git a/cardinal-components-item/src/main/java/dev/onyxstudios/cca/internal/item/StaticItemComponentPlugin.java b/cardinal-components-item/src/main/java/dev/onyxstudios/cca/internal/item/StaticItemComponentPlugin.java index 395f17a3..b6bc2d70 100644 --- a/cardinal-components-item/src/main/java/dev/onyxstudios/cca/internal/item/StaticItemComponentPlugin.java +++ b/cardinal-components-item/src/main/java/dev/onyxstudios/cca/internal/item/StaticItemComponentPlugin.java @@ -75,7 +75,7 @@ public ComponentContainer.Factory getFactoryClass(Item item, Identifi @Override protected void init() { StaticComponentPluginBase.processInitializers( - FabricLoader.getInstance().getEntrypointContainers("cardinal-components-item", ItemComponentInitializer.class), + StaticComponentPluginBase.getComponentEntrypoints("cardinal-components-item", ItemComponentInitializer.class), initializer -> initializer.registerItemComponentFactories(this) ); } diff --git a/cardinal-components-level/src/main/java/dev/onyxstudios/cca/api/v3/level/LevelComponentInitializer.java b/cardinal-components-level/src/main/java/dev/onyxstudios/cca/api/v3/level/LevelComponentInitializer.java index 0bba987b..46cd0f57 100644 --- a/cardinal-components-level/src/main/java/dev/onyxstudios/cca/api/v3/level/LevelComponentInitializer.java +++ b/cardinal-components-level/src/main/java/dev/onyxstudios/cca/api/v3/level/LevelComponentInitializer.java @@ -22,19 +22,20 @@ */ package dev.onyxstudios.cca.api.v3.level; +import dev.onyxstudios.cca.internal.base.ComponentRegistrationInitializer; import net.minecraft.world.WorldProperties; import org.jetbrains.annotations.ApiStatus; /** * Entrypoint getting invoked to register static item component factories. * - *

The entrypoint is exposed as {@code cardinal-components-level} in the mod json and runs for any environment. + *

The entrypoint is exposed as either {@code "cardinal-components"} or {@code "cardinal-components-level"} in the mod json and runs for any environment. * It usually executes right before the first {@linkplain WorldProperties save properties object} gets loaded. * * @since 2.4.0 */ @ApiStatus.Experimental -public interface LevelComponentInitializer { +public interface LevelComponentInitializer extends ComponentRegistrationInitializer { /** * Called to register component factories for statically declared component types. * diff --git a/cardinal-components-level/src/main/java/dev/onyxstudios/cca/internal/level/StaticLevelComponentPlugin.java b/cardinal-components-level/src/main/java/dev/onyxstudios/cca/internal/level/StaticLevelComponentPlugin.java index 8fbb62c0..c3d94458 100644 --- a/cardinal-components-level/src/main/java/dev/onyxstudios/cca/internal/level/StaticLevelComponentPlugin.java +++ b/cardinal-components-level/src/main/java/dev/onyxstudios/cca/internal/level/StaticLevelComponentPlugin.java @@ -51,7 +51,7 @@ private StaticLevelComponentPlugin() { @Override protected Collection> getEntrypoints() { - return FabricLoader.getInstance().getEntrypointContainers("cardinal-components-level", LevelComponentInitializer.class); + return getComponentEntrypoints("cardinal-components-level", LevelComponentInitializer.class); } @Override diff --git a/cardinal-components-scoreboard/src/main/java/dev/onyxstudios/cca/api/v3/scoreboard/ScoreboardComponentInitializer.java b/cardinal-components-scoreboard/src/main/java/dev/onyxstudios/cca/api/v3/scoreboard/ScoreboardComponentInitializer.java index 565d0c8d..8b0d17af 100644 --- a/cardinal-components-scoreboard/src/main/java/dev/onyxstudios/cca/api/v3/scoreboard/ScoreboardComponentInitializer.java +++ b/cardinal-components-scoreboard/src/main/java/dev/onyxstudios/cca/api/v3/scoreboard/ScoreboardComponentInitializer.java @@ -22,18 +22,19 @@ */ package dev.onyxstudios.cca.api.v3.scoreboard; +import dev.onyxstudios.cca.internal.base.ComponentRegistrationInitializer; import org.jetbrains.annotations.ApiStatus; /** * Entrypoint getting invoked to register static team component factories. * - *

The entrypoint is exposed as {@code cardinal-components-scoreboard} in the mod json and runs for any environment. + *

The entrypoint is exposed as either {@code "cardinal-components"} or {@code "cardinal-components-scoreboard"} in the mod json and runs for any environment. * It usually executes right before the first {@link net.minecraft.scoreboard.Scoreboard} instance is created. * * @since 2.4.2 */ @ApiStatus.Experimental -public interface ScoreboardComponentInitializer { +public interface ScoreboardComponentInitializer extends ComponentRegistrationInitializer { /** * Called to register component factories for statically declared component types. * diff --git a/cardinal-components-scoreboard/src/main/java/dev/onyxstudios/cca/internal/scoreboard/StaticScoreboardComponentPlugin.java b/cardinal-components-scoreboard/src/main/java/dev/onyxstudios/cca/internal/scoreboard/StaticScoreboardComponentPlugin.java index 732133c3..12ddf509 100644 --- a/cardinal-components-scoreboard/src/main/java/dev/onyxstudios/cca/internal/scoreboard/StaticScoreboardComponentPlugin.java +++ b/cardinal-components-scoreboard/src/main/java/dev/onyxstudios/cca/internal/scoreboard/StaticScoreboardComponentPlugin.java @@ -48,7 +48,7 @@ private StaticScoreboardComponentPlugin() { @Override protected Collection> getEntrypoints() { - return FabricLoader.getInstance().getEntrypointContainers("cardinal-components-scoreboard", ScoreboardComponentInitializer.class); + return getComponentEntrypoints("cardinal-components-scoreboard", ScoreboardComponentInitializer.class); } @Override diff --git a/cardinal-components-util/src/main/java/dev/onyxstudios/cca/api/v3/util/GenericComponentInitializer.java b/cardinal-components-util/src/main/java/dev/onyxstudios/cca/api/v3/util/GenericComponentInitializer.java index 7572c69a..e5018cf0 100644 --- a/cardinal-components-util/src/main/java/dev/onyxstudios/cca/api/v3/util/GenericComponentInitializer.java +++ b/cardinal-components-util/src/main/java/dev/onyxstudios/cca/api/v3/util/GenericComponentInitializer.java @@ -22,18 +22,19 @@ */ package dev.onyxstudios.cca.api.v3.util; +import dev.onyxstudios.cca.internal.base.ComponentRegistrationInitializer; import org.jetbrains.annotations.ApiStatus; /** * Entrypoint getting invoked to register static generic (typically for third party providers) * component factories. * - *

The entrypoint is exposed as {@code "cardinal-components-util"} in the mod json and runs for any environment. + *

The entrypoint is exposed as either {@code "cardinal-components"} or {@code "cardinal-components-util"} in the mod json and runs for any environment. * * @since 2.4.0 */ @ApiStatus.Experimental -public interface GenericComponentInitializer { +public interface GenericComponentInitializer extends ComponentRegistrationInitializer { /** * Called to register component factories for statically declared component types. * diff --git a/cardinal-components-world/src/main/java/dev/onyxstudios/cca/api/v3/world/WorldComponentInitializer.java b/cardinal-components-world/src/main/java/dev/onyxstudios/cca/api/v3/world/WorldComponentInitializer.java index aa4e370b..da786f97 100644 --- a/cardinal-components-world/src/main/java/dev/onyxstudios/cca/api/v3/world/WorldComponentInitializer.java +++ b/cardinal-components-world/src/main/java/dev/onyxstudios/cca/api/v3/world/WorldComponentInitializer.java @@ -22,16 +22,17 @@ */ package dev.onyxstudios.cca.api.v3.world; +import dev.onyxstudios.cca.internal.base.ComponentRegistrationInitializer; import net.minecraft.world.World; /** * Entrypoint getting invoked to register static world component factories. * - *

The entrypoint is exposed as {@code cardinal-components-world} in the mod json and runs for any environment. + *

The entrypoint is exposed as either {@code "cardinal-components"} or {@code "cardinal-components-world"} in the mod json and runs for any environment. * It usually executes right before the first {@link World} instance is created. * * @since 2.4.0 */ -public interface WorldComponentInitializer { +public interface WorldComponentInitializer extends ComponentRegistrationInitializer { void registerWorldComponentFactories(WorldComponentFactoryRegistry registry); } diff --git a/cardinal-components-world/src/main/java/dev/onyxstudios/cca/internal/world/StaticWorldComponentPlugin.java b/cardinal-components-world/src/main/java/dev/onyxstudios/cca/internal/world/StaticWorldComponentPlugin.java index 97424bff..5c10f881 100644 --- a/cardinal-components-world/src/main/java/dev/onyxstudios/cca/internal/world/StaticWorldComponentPlugin.java +++ b/cardinal-components-world/src/main/java/dev/onyxstudios/cca/internal/world/StaticWorldComponentPlugin.java @@ -47,7 +47,7 @@ private StaticWorldComponentPlugin() { @Override protected Collection> getEntrypoints() { - return FabricLoader.getInstance().getEntrypointContainers("cardinal-components-world", WorldComponentInitializer.class); + return getComponentEntrypoints("cardinal-components-world", WorldComponentInitializer.class); } @Override diff --git a/changelog.md b/changelog.md index b72a0083..668381e6 100644 --- a/changelog.md +++ b/changelog.md @@ -13,6 +13,13 @@ Changes - Every class remaining in the `nerdhub.component.*` packages has been moved to a `dev.onyxstudios.cca.*` package - Replaced specific factory interfaces with a generic variant (eg. `ComponentFactory`) +------------------------------------------------------ +Version 2.7.5 +------------------------------------------------------ +Additions +- Added the universal `cardinal-components` entrypoint key + - This new key can be used for any CCA registration initializer (replaces eg. `cardinal-components-entity`) + ------------------------------------------------------ Version 2.7.4 ------------------------------------------------------ diff --git a/src/testmod/java/dev/onyxstudios/componenttest/CardinalComponentsTest.java b/src/testmod/java/dev/onyxstudios/componenttest/CardinalComponentsTest.java index 37c6522b..57dd2361 100644 --- a/src/testmod/java/dev/onyxstudios/componenttest/CardinalComponentsTest.java +++ b/src/testmod/java/dev/onyxstudios/componenttest/CardinalComponentsTest.java @@ -29,7 +29,6 @@ import dev.onyxstudios.cca.api.v3.component.CopyableComponent; import dev.onyxstudios.cca.api.v3.component.sync.AutoSyncedComponent; import dev.onyxstudios.cca.api.v3.util.ComponentContainerMetafactory; -import dev.onyxstudios.cca.internal.base.asm.StaticComponentLoadingException; import dev.onyxstudios.componenttest.vita.BaseVita; import dev.onyxstudios.componenttest.vita.Vita; import net.fabricmc.fabric.api.client.itemgroup.FabricItemGroupBuilder; @@ -112,15 +111,6 @@ public static void init() { assert false : "Only one factory should be created for any given provider type"; } catch (IllegalStateException ignored) { } - try { - LOGGER.info(ComponentContainerMetafactory.metafactory( - TestComponents.CUSTOM_PROVIDER_2, - new TypeToken>() {}, - new TypeToken>() {} - ).apply(UUID.randomUUID(), null)); - assert false : "Registered factory does not return " + AutoSyncedComponent.class; - } catch (StaticComponentLoadingException ignored) { } - LOGGER.info(ComponentContainerMetafactory.metafactory( TestComponents.CUSTOM_PROVIDER_2, new TypeToken>() {}, diff --git a/src/testmod/resources/fabric.mod.json b/src/testmod/resources/fabric.mod.json index 348301b1..34794957 100644 --- a/src/testmod/resources/fabric.mod.json +++ b/src/testmod/resources/fabric.mod.json @@ -15,28 +15,7 @@ "cardinal-components:static-init": [ "dev.onyxstudios.componenttest.TestStaticComponentInitializer" ], - "cardinal-components-block": [ - "dev.onyxstudios.componenttest.TestComponents" - ], - "cardinal-components-chunk": [ - "dev.onyxstudios.componenttest.TestComponents" - ], - "cardinal-components-entity": [ - "dev.onyxstudios.componenttest.TestComponents" - ], - "cardinal-components-item": [ - "dev.onyxstudios.componenttest.TestComponents" - ], - "cardinal-components-level": [ - "dev.onyxstudios.componenttest.TestComponents" - ], - "cardinal-components-scoreboard": [ - "dev.onyxstudios.componenttest.TestComponents" - ], - "cardinal-components-util": [ - "dev.onyxstudios.componenttest.TestComponents" - ], - "cardinal-components-world": [ + "cardinal-components": [ "dev.onyxstudios.componenttest.TestComponents" ] },