diff --git a/api/src/main/java/dev/lambdaurora/lambdynlights/api/DynamicLightsInitializer.java b/api/src/main/java/dev/lambdaurora/lambdynlights/api/DynamicLightsInitializer.java index 7a6ceb0..bb0e299 100644 --- a/api/src/main/java/dev/lambdaurora/lambdynlights/api/DynamicLightsInitializer.java +++ b/api/src/main/java/dev/lambdaurora/lambdynlights/api/DynamicLightsInitializer.java @@ -9,6 +9,8 @@ package dev.lambdaurora.lambdynlights.api; +import dev.lambdaurora.lambdynlights.api.item.ItemLightSourceManager; + /** * Represents the entrypoint for LambDynamicLights API. * @@ -20,5 +22,5 @@ public interface DynamicLightsInitializer { /** * Called when LambDynamicLights is initialized to register custom dynamic light handlers and item light sources. */ - void onInitializeDynamicLights(); + void onInitializeDynamicLights(ItemLightSourceManager itemLightSourceManager); } diff --git a/api/src/main/java/dev/lambdaurora/lambdynlights/api/item/ItemLightSourceManager.java b/api/src/main/java/dev/lambdaurora/lambdynlights/api/item/ItemLightSourceManager.java index c5ac57f..1d06504 100644 --- a/api/src/main/java/dev/lambdaurora/lambdynlights/api/item/ItemLightSourceManager.java +++ b/api/src/main/java/dev/lambdaurora/lambdynlights/api/item/ItemLightSourceManager.java @@ -9,9 +9,27 @@ package dev.lambdaurora.lambdynlights.api.item; +import dev.yumi.commons.event.Event; +import net.minecraft.advancements.critereon.ItemPredicate; +import net.minecraft.core.RegistryAccess; +import net.minecraft.resources.Identifier; import net.minecraft.world.item.ItemStack; +import net.minecraft.world.level.ItemLike; +/** + * Represents the item light source manager, + * which provides the ability to register light sources to items, and to query the luminance of item stacks. + * + * @author LambdAurora + * @version 3.0.0 + * @since 3.0.0 + */ public interface ItemLightSourceManager { + /** + * {@return the registration event for item light sources} + */ + Event onRegisterEvent(); + /** * {@return the luminance value of the item stack} * @@ -28,4 +46,55 @@ default int getLuminance(ItemStack stack) { * @param submergedInWater {@code true} if the stack is submerged in water, else {@code false} */ int getLuminance(ItemStack stack, boolean submergedInWater); + + /** + * Represents the registration event of item light sources. + */ + @FunctionalInterface + interface OnRegister { + /** + * Called when item light sources are registered. + * + * @param context the registration context + */ + void onRegister(RegisterContext context); + } + + interface RegisterContext { + /** + * {@return the access to registries} + */ + RegistryAccess registryAccess(); + + /** + * Registers the given item light source. + * + * @param itemLightSource the item light source to register + */ + void register(ItemLightSource itemLightSource); + + /** + * Registers a light source of the given item with the given luminance. + * + * @param item the item to light + * @param luminance the luminance of the item + * @see #register(ItemLightSource) + * @see #register(ItemLike, ItemLuminance) + */ + default void register(ItemLike item, int luminance) { + this.register(new ItemLightSource(ItemPredicate.Builder.item().of(item).build(), luminance)); + } + + /** + * Registers a light source of the given item with the given luminance. + * + * @param item the item to light + * @param luminance the luminance of the item + * @see #register(ItemLightSource) + * @see #register(ItemLike, int) + */ + default void register(ItemLike item, ItemLuminance luminance) { + this.register(new ItemLightSource(ItemPredicate.Builder.item().of(item).build(), luminance)); + } + } } diff --git a/build.gradle.kts b/build.gradle.kts index 312230b..547d76a 100644 --- a/build.gradle.kts +++ b/build.gradle.kts @@ -56,7 +56,6 @@ loom { dependencies { implementation(project(":api", configuration = "namedElements")) - implementation(libs.yumi.commons.core) modImplementation(libs.fabric.api) @@ -75,6 +74,8 @@ dependencies { shadow(project(":api", configuration = "namedElements")) shadow(libs.yumi.commons.core) + shadow(libs.yumi.commons.collections) + shadow(libs.yumi.commons.event) shadow(libs.nightconfig.core) shadow(libs.nightconfig.toml) } diff --git a/build_logic/src/main/kotlin/lambdynamiclights.gradle.kts b/build_logic/src/main/kotlin/lambdynamiclights.gradle.kts index 0fb983a..548b616 100644 --- a/build_logic/src/main/kotlin/lambdynamiclights.gradle.kts +++ b/build_logic/src/main/kotlin/lambdynamiclights.gradle.kts @@ -29,6 +29,8 @@ dependencies { mappings("dev.lambdaurora:yalmm:${Constants.mcVersion()}+build.${libs.versions.mappings.yalmm.get()}") }) modImplementation(libs.fabric.loader) + + api(libs.yumi.commons.event) } java { diff --git a/gradle/libs.versions.toml b/gradle/libs.versions.toml index 3a5a2e4..ddc7079 100644 --- a/gradle/libs.versions.toml +++ b/gradle/libs.versions.toml @@ -27,6 +27,8 @@ fabric-api = { module = "net.fabricmc.fabric-api:fabric-api", version.ref = "fab # Dependencies yumi-commons-core = { module = "dev.yumi.commons:yumi-commons-core", version.ref = "yumi-commons" } +yumi-commons-collections = { module = "dev.yumi.commons:yumi-commons-collections", version.ref = "yumi-commons" } +yumi-commons-event = { module = "dev.yumi.commons:yumi-commons-event", version.ref = "yumi-commons" } spruceui = { module = "dev.lambdaurora:spruceui", version.ref = "spruceui" } pridelib = { module = "io.github.queerbric:pridelib", version.ref = "pridelib" } modmenu = { module = "com.terraformersmc:modmenu", version.ref = "modmenu" } diff --git a/src/main/java/dev/lambdaurora/lambdynlights/LambDynLights.java b/src/main/java/dev/lambdaurora/lambdynlights/LambDynLights.java index e6175a6..c410ceb 100644 --- a/src/main/java/dev/lambdaurora/lambdynlights/LambDynLights.java +++ b/src/main/java/dev/lambdaurora/lambdynlights/LambDynLights.java @@ -13,6 +13,7 @@ import dev.lambdaurora.lambdynlights.api.DynamicLightHandlers; import dev.lambdaurora.lambdynlights.api.DynamicLightsInitializer; import dev.lambdaurora.lambdynlights.resource.item.ItemLightSources; +import dev.yumi.commons.event.EventManager; import it.unimi.dsi.fastutil.longs.LongOpenHashSet; import net.fabricmc.api.ClientModInitializer; import net.fabricmc.fabric.api.client.rendering.v1.WorldRenderEvents; @@ -57,6 +58,7 @@ public class LambDynLights implements ClientModInitializer { private static final Logger LOGGER = LoggerFactory.getLogger("LambDynamicLights"); private static final double MAX_RADIUS = 7.75; private static final double MAX_RADIUS_SQUARED = MAX_RADIUS * MAX_RADIUS; + public static final EventManager EVENT_MANAGER = new EventManager<>(Identifier.of(NAMESPACE, "default"), Identifier::parse); private static LambDynLights INSTANCE; public final DynamicLightsConfig config = new DynamicLightsConfig(this); public final ItemLightSources itemLightSources = new ItemLightSources(); @@ -73,8 +75,9 @@ public void onInitializeClient() { this.config.load(); FabricLoader.getInstance().getEntrypointContainers("dynamiclights", DynamicLightsInitializer.class) - .stream().map(EntrypointContainer::getEntrypoint) - .forEach(DynamicLightsInitializer::onInitializeDynamicLights); + .stream() + .map(EntrypointContainer::getEntrypoint) + .forEach(initializer -> initializer.onInitializeDynamicLights(this.itemLightSources)); ResourceManagerHelper.get(ResourceType.CLIENT_RESOURCES).registerReloadListener(new SimpleSynchronousResourceReloadListener() { @Override @@ -96,6 +99,12 @@ public void reload(ResourceManager manager) { DynamicLightHandlers.registerDefaultHandlers(); } + public static boolean isDevMode() { + return FabricLoader.getInstance().getModContainer(NAMESPACE) + .map(modContainer -> modContainer.getMetadata().getVersion().getFriendlyString().endsWith("-local")) + .orElse(true); + } + /** * Updates all light sources. * diff --git a/src/main/java/dev/lambdaurora/lambdynlights/LambDynLightsCompat.java b/src/main/java/dev/lambdaurora/lambdynlights/LambDynLightsCompat.java index 6fddca5..0af49f1 100644 --- a/src/main/java/dev/lambdaurora/lambdynlights/LambDynLightsCompat.java +++ b/src/main/java/dev/lambdaurora/lambdynlights/LambDynLightsCompat.java @@ -17,7 +17,7 @@ * Represents a utility class for compatibility. * * @author LambdAurora - * @version 1.3.3 + * @version 3.0.0 * @since 1.0.0 */ public final class LambDynLightsCompat { @@ -30,26 +30,6 @@ public static boolean isCanvasInstalled() { return FabricLoader.getInstance().isModLoaded("canvas"); } - /** - * Returns whether Lil Tater Reloaded is installed. - * - * @return {@code true} if LTR is installed, else {@code false} - */ - public static boolean isLilTaterReloadedInstalled() { - // Don't even think about it Yog. - return FabricLoader.getInstance().isModLoaded("ltr"); - } - - /** - * Returns whether Sodium 0.1.0 is installed. - * - * @return {@code true} if Sodium 0.1.0 is installed, else {@code false} - */ - public static boolean isSodium010Installed() { - return FabricLoader.getInstance().getModContainer("sodium").map(mod -> mod.getMetadata().getVersion().getFriendlyString().startsWith("0.1.0")) - .orElse(false); - } - public static boolean isSodium05XInstalled() { return FabricLoader.getInstance().getModContainer("sodium").map(mod -> { try { diff --git a/src/main/java/dev/lambdaurora/lambdynlights/LambDynLightsMixinPlugin.java b/src/main/java/dev/lambdaurora/lambdynlights/LambDynLightsMixinPlugin.java index 4eaff0a..7d96e3a 100644 --- a/src/main/java/dev/lambdaurora/lambdynlights/LambDynLightsMixinPlugin.java +++ b/src/main/java/dev/lambdaurora/lambdynlights/LambDynLightsMixinPlugin.java @@ -33,6 +33,8 @@ public LambDynLightsMixinPlugin() { this.conditionalMixins.put("dev.lambdaurora.lambdynlights.mixin.sodium.ArrayLightDataCacheMixin", sodium05XInstalled); this.conditionalMixins.put("dev.lambdaurora.lambdynlights.mixin.sodium.FlatLightPipelineMixin", sodium05XInstalled); this.conditionalMixins.put("dev.lambdaurora.lambdynlights.mixin.sodium.LightDataAccessMixin", sodium05XInstalled); + + this.conditionalMixins.put("dev.lambdaurora.lambdynlights.mixin.DevModeMixin", LambDynLights.isDevMode()); } @Override diff --git a/src/main/java/dev/lambdaurora/lambdynlights/mixin/DevModeMixin.java b/src/main/java/dev/lambdaurora/lambdynlights/mixin/DevModeMixin.java new file mode 100644 index 0000000..8bdf8dd --- /dev/null +++ b/src/main/java/dev/lambdaurora/lambdynlights/mixin/DevModeMixin.java @@ -0,0 +1,39 @@ +/* + * Copyright © 2024 LambdAurora + * + * This file is part of LambDynamicLights. + * + * Licensed under the Lambda License. For more information, + * see the LICENSE file. + */ + +package dev.lambdaurora.lambdynlights.mixin; + +import com.llamalad7.mixinextras.injector.wrapoperation.Operation; +import com.llamalad7.mixinextras.injector.wrapoperation.WrapOperation; +import net.minecraft.client.Minecraft; +import net.minecraft.client.gui.GuiGraphics; +import net.minecraft.client.renderer.GameRenderer; +import org.spongepowered.asm.mixin.Mixin; +import org.spongepowered.asm.mixin.Shadow; +import org.spongepowered.asm.mixin.injection.At; + +@Mixin(GameRenderer.class) +public class DevModeMixin { + @Shadow + private Minecraft minecraft; + + @WrapOperation( + method = "Lnet/minecraft/client/renderer/GameRenderer;render(Lnet/minecraft/client/DeltaTracker;Z)V", + at = @At(value = "INVOKE", target = "Lnet/minecraft/client/gui/GuiGraphics;flush()V") + ) + private void handler(GuiGraphics graphics, Operation original) { + final String text = "[LambDynamicLights Dev Version (Unsupported)]"; + int bottom = this.minecraft.getWindow().getGuiScaledHeight(); + int y = bottom - this.minecraft.font.lineHeight; + + graphics.fill(0, y - 4, this.minecraft.font.width(text) + 4, bottom, 0xaa000000); + graphics.drawShadowedText(this.minecraft.font, text, 2, y - 2, 0xff0000); + original.call(graphics); + } +} diff --git a/src/main/java/dev/lambdaurora/lambdynlights/mixin/sodium/ArrayLightDataCacheMixin.java b/src/main/java/dev/lambdaurora/lambdynlights/mixin/sodium/ArrayLightDataCacheMixin.java index fb2ec7d..1bcf54a 100644 --- a/src/main/java/dev/lambdaurora/lambdynlights/mixin/sodium/ArrayLightDataCacheMixin.java +++ b/src/main/java/dev/lambdaurora/lambdynlights/mixin/sodium/ArrayLightDataCacheMixin.java @@ -19,10 +19,7 @@ import org.spongepowered.asm.mixin.injection.callback.CallbackInfoReturnable; @Pseudo -@Mixin(targets = { - "me.jellysquid.mods.sodium.client.model.light.data.ArrayLightDataCache", - "net.caffeinemc.mods.sodium.client.model.light.data.ArrayLightDataCache" - }, remap = false) +@Mixin(targets = "me.jellysquid.mods.sodium.client.model.light.data.ArrayLightDataCache", remap = false) public abstract class ArrayLightDataCacheMixin { @Dynamic @Inject(method = "get(III)I", at = @At("HEAD"), require = 0) diff --git a/src/main/java/dev/lambdaurora/lambdynlights/mixin/sodium/FlatLightPipelineMixin.java b/src/main/java/dev/lambdaurora/lambdynlights/mixin/sodium/FlatLightPipelineMixin.java index a73c7cb..71c9ba5 100644 --- a/src/main/java/dev/lambdaurora/lambdynlights/mixin/sodium/FlatLightPipelineMixin.java +++ b/src/main/java/dev/lambdaurora/lambdynlights/mixin/sodium/FlatLightPipelineMixin.java @@ -21,10 +21,7 @@ import org.spongepowered.asm.mixin.injection.callback.LocalCapture; @Pseudo -@Mixin(targets = { - "me.jellysquid.mods.sodium.client.model.light.flat.FlatLightPipeline", - "net.caffeinemc.mods.sodium.client.model.light.flat.FlatLightPipeline" -}, remap = false) +@Mixin(targets = "me.jellysquid.mods.sodium.client.model.light.flat.FlatLightPipeline", remap = false) public abstract class FlatLightPipelineMixin { @Dynamic @Inject( diff --git a/src/main/java/dev/lambdaurora/lambdynlights/mixin/sodium/LightDataAccessMixin.java b/src/main/java/dev/lambdaurora/lambdynlights/mixin/sodium/LightDataAccessMixin.java index 42ec56a..7cc54a6 100644 --- a/src/main/java/dev/lambdaurora/lambdynlights/mixin/sodium/LightDataAccessMixin.java +++ b/src/main/java/dev/lambdaurora/lambdynlights/mixin/sodium/LightDataAccessMixin.java @@ -18,10 +18,7 @@ import org.spongepowered.asm.mixin.injection.callback.CallbackInfoReturnable; @Pseudo -@Mixin(targets = { - "me.jellysquid.mods.sodium.client.model.light.data.LightDataAccess", - "net.caffeinemc.mods.sodium.client.model.light.data.LightDataAccess" -}, remap = false) +@Mixin(targets = "me.jellysquid.mods.sodium.client.model.light.data.LightDataAccess", remap = false) public abstract class LightDataAccessMixin { @Dynamic @Inject(method = "getLightmap", at = @At("RETURN"), remap = false, require = 0, cancellable = true) diff --git a/src/main/java/dev/lambdaurora/lambdynlights/resource/item/ItemLightSources.java b/src/main/java/dev/lambdaurora/lambdynlights/resource/item/ItemLightSources.java index 447d9ae..c4a516e 100644 --- a/src/main/java/dev/lambdaurora/lambdynlights/resource/item/ItemLightSources.java +++ b/src/main/java/dev/lambdaurora/lambdynlights/resource/item/ItemLightSources.java @@ -18,6 +18,7 @@ import dev.lambdaurora.lambdynlights.api.item.ItemLightSource; import dev.lambdaurora.lambdynlights.api.item.ItemLightSourceManager; import dev.yumi.commons.TriState; +import dev.yumi.commons.event.Event; import net.fabricmc.loader.api.FabricLoader; import net.minecraft.core.RegistryAccess; import net.minecraft.resources.Identifier; @@ -47,6 +48,8 @@ public final class ItemLightSources implements ItemLightSourceManager { private static final boolean FORCE_LOG_ERRORS = TriState.fromProperty("lambdynamiclights.resource.force_log_errors") .toBooleanOrElse(FabricLoader.getInstance().isDevelopmentEnvironment()); + private final Event onRegisterEvent = LambDynLights.EVENT_MANAGER.create(OnRegister.class); + private final List loadedLightSources = new ArrayList<>(); private final List lightSources = new ArrayList<>(); @@ -73,7 +76,18 @@ public void apply(RegistryAccess registryAccess) { var ops = RegistryOps.create(JsonOps.INSTANCE, registryAccess); this.lightSources.clear(); - this.loadedLightSources.forEach(data -> apply(ops, data)); + this.loadedLightSources.forEach(data -> this.apply(ops, data)); + this.onRegisterEvent.invoker().onRegister(new RegisterContext() { + @Override + public RegistryAccess registryAccess() { + return registryAccess; + } + + @Override + public void register(ItemLightSource itemLightSource) { + ItemLightSources.this.lightSources.add(itemLightSource); + } + }); } private void load(Identifier resourceId, Resource resource) { @@ -116,41 +130,11 @@ private void apply(DynamicOps ops, LoadedItemLightSource loadedData loaded.ifSuccess(this.lightSources::add); } - /** - * Registers an item light source data. - * - * @param data The item light source data. - * - private static void register(ItemLightSource data) { - var other = ITEM_LIGHT_SOURCES.get(data.item()); - - if (other != null) { - LambDynLights.get().warn("Failed to register item light source \"" + data.id() + "\", duplicates item \"" - + BuiltInRegistries.ITEM.getId(data.item()) + "\" found in \"" + other.id() + "\"."); - return; + @Override + public Event onRegisterEvent() { + return this.onRegisterEvent; } - ITEM_LIGHT_SOURCES.put(data.item(), data); - }*/ - - /** - * Registers an item light source data. - * - * @param data the item light source data - *

- * public static void registerItemLightSource(ItemLightSource data) { - * var other = STATIC_ITEM_LIGHT_SOURCES.get(data.item()); - *

- * if (other != null) { - * LambDynLights.get().warn("Failed to register item light source \"" + data.id() + "\", duplicates item \"" - * + BuiltInRegistries.ITEM.getId(data.item()) + "\" found in \"" + other.id() + "\"."); - * return; - * } - *

- * STATIC_ITEM_LIGHT_SOURCES.put(data.item(), data); - * } - */ - @Override public int getLuminance(ItemStack stack, boolean submergedInWater) { boolean shouldCareAboutWater = submergedInWater && LambDynLights.get().config.getWaterSensitiveCheck().get(); diff --git a/src/main/resources/lambdynlights.mixins.json b/src/main/resources/lambdynlights.mixins.json index ffa6eca..d64eb6f 100644 --- a/src/main/resources/lambdynlights.mixins.json +++ b/src/main/resources/lambdynlights.mixins.json @@ -8,6 +8,7 @@ "ClientLevelMixin", "CommonLevelRendererMixin", "DebugScreenOverlayMixin", + "DevModeMixin", "EntityRendererMixin", "EntityTypeMixin", "LevelMixin",