Skip to content

Commit

Permalink
WIP new data-driven item light source system.
Browse files Browse the repository at this point in the history
  • Loading branch information
LambdAurora committed Aug 3, 2024
1 parent 1214a70 commit e39c01e
Show file tree
Hide file tree
Showing 42 changed files with 405 additions and 345 deletions.
4 changes: 4 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -177,6 +177,10 @@

## 3.0.0

- Changed how item light sources are defined in resource packs:
- Now item light sources support a wide-range of selection predicates thanks to data-driven improvements in the base game.
- This means enchanted items can now selectively light up, this should mostly address ([#89](https://github.com/LambdAurora/LambDynamicLights/issues/89)).
- Please refer yourself to the documentation for more details.
- Updated to Minecraft 1.21 ([#227](https://github.com/LambdAurora/LambDynamicLights/pull/227)).
- Updated configuration library.
- Configuration corruption should now be fixed.
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,58 @@
/*
* Copyright © 2024 LambdAurora <[email protected]>
*
* This file is part of LambDynamicLights.
*
* Licensed under the Lambda License. For more information,
* see the LICENSE file.
*/

package dev.lambdaurora.lambdynlights.api.item;

import com.mojang.serialization.Codec;
import com.mojang.serialization.codecs.RecordCodecBuilder;
import net.minecraft.advancements.critereon.ItemPredicate;
import net.minecraft.world.item.ItemStack;
import org.jetbrains.annotations.Range;

/**
* Represents an item light source.
*
* @param predicate the predicate to select which items emits the given luminance
* @param luminance the luminance to emit
* @param waterSensitive {@code true} if this light source is sensitive to water, or {@code false} otherwise
* @author LambdAurora
* @version 3.0.0
* @since 3.0.0
*/
public record ItemLightSource(ItemPredicate predicate, ItemLuminance luminance, boolean waterSensitive) {
public static final Codec<ItemLightSource> CODEC = RecordCodecBuilder.create(
instance -> instance.group(
ItemPredicate.CODEC.fieldOf("match").forGetter(ItemLightSource::predicate),
ItemLuminance.CODEC.fieldOf("luminance").forGetter(ItemLightSource::luminance),
Codec.BOOL.optionalFieldOf("water_sensitive", false).forGetter(ItemLightSource::waterSensitive)
).apply(instance, ItemLightSource::new)
);

public ItemLightSource(ItemPredicate predicate, int luminance) {
this(predicate, new ItemLuminance.Value(luminance));
}

public ItemLightSource(ItemPredicate predicate, ItemLuminance luminance) {
this(predicate, luminance, false);
}

/**
* Gets the luminance of the item.
*
* @param stack the item stack
* @return the luminance value between {@code 0} and {@code 15}
*/
public @Range(from = 0, to = 15) int getLuminance(ItemStack stack) {
if (this.predicate.test(stack)) {
return this.luminance.getLuminance(stack);
}

return 0;
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
/*
* Copyright © 2024 LambdAurora <[email protected]>
*
* This file is part of LambDynamicLights.
*
* Licensed under the Lambda License. For more information,
* see the LICENSE file.
*/

package dev.lambdaurora.lambdynlights.api.item;

import net.minecraft.world.item.ItemStack;

public interface ItemLightSourceManager {


int getLuminance(ItemStack stack);

int getLuminance(ItemStack stack, boolean submergedInWater);
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,163 @@
/*
* Copyright © 2024 LambdAurora <[email protected]>
*
* This file is part of LambDynamicLights.
*
* Licensed under the Lambda License. For more information,
* see the LICENSE file.
*/

package dev.lambdaurora.lambdynlights.api.item;

import com.mojang.serialization.Codec;
import com.mojang.serialization.MapCodec;
import com.mojang.serialization.codecs.RecordCodecBuilder;
import net.minecraft.Util;
import net.minecraft.core.Holder;
import net.minecraft.core.registries.BuiltInRegistries;
import net.minecraft.util.Brightness;
import net.minecraft.world.item.ItemStack;
import net.minecraft.world.level.block.Block;
import org.jetbrains.annotations.Range;

import java.util.HashMap;
import java.util.Map;
import java.util.stream.Stream;

/**
* Represents the luminance value of an item.
*
* @author LambdAurora
* @version 3.0.0
* @since 3.0.0
*/
public sealed interface ItemLuminance permits ItemLuminance.Value, ItemLuminance.BlockReference, ItemLuminance.BlockSelf {
Codec<ItemLuminance> CODEC = Codec.withAlternative(
Type.CODEC.dispatch(ItemLuminance::type, Type::codec),
Value.DIRECT_CODEC
);

/**
* {@return the type of this item luminance}
*/
Type type();

/**
* Gets the luminance of the given item stack.
*
* @param stack the item stack to get the luminance of
* @return the luminance of the given item stack
*/
@Range(from = 0, to = 15)
int getLuminance(ItemStack stack);

/**
* Represents a direct item luminance value.
*
* @param luminance the luminance
*/
record Value(@Range(from = 0, to = 15) int luminance) implements ItemLuminance {
public static final Codec<Value> DIRECT_CODEC = Brightness.LIGHT_VALUE_CODEC.xmap(Value::new, Value::luminance);
public static final MapCodec<Value> CODEC = RecordCodecBuilder.mapCodec(
instance -> instance.group(
Brightness.LIGHT_VALUE_CODEC.fieldOf("value").forGetter(Value::luminance)
).apply(instance, Value::new)
);

@Override
public Type type() {
return Type.VALUE;
}

@Override
public @Range(from = 0, to = 15) int getLuminance(ItemStack stack) {
return this.luminance;
}
}

/**
* Represents an item luminance value that's derived from the referenced block's default state.
*
* @param block the referenced block
*/
record BlockReference(Block block) implements ItemLuminance {
public static final MapCodec<BlockReference> CODEC = RecordCodecBuilder.mapCodec(
instance -> instance.group(
BuiltInRegistries.BLOCK.holderByNameCodec().fieldOf("block").forGetter(BlockReference::blockHolder)
).apply(instance, BlockReference::new)
);

public BlockReference(Holder<Block> block) {
this(block.value());
}

@SuppressWarnings("deprecation")
public Holder<Block> blockHolder() {
return this.block.builtInRegistryHolder();
}

@Override
public Type type() {
return Type.BLOCK_REFERENCE;
}

@Override
public @Range(from = 0, to = 15) int getLuminance(ItemStack stack) {
return this.block.defaultState().getLightEmission();
}
}

/**
* Represents the item luminance value that's derived from the block the item represents.
*/
final class BlockSelf implements ItemLuminance {
public static final BlockSelf INSTANCE = new BlockSelf();
public static final MapCodec<BlockSelf> CODEC = MapCodec.unit(INSTANCE);

private BlockSelf() {}

@Override
public Type type() {
return Type.BLOCK_SELF;
}

@Override
public @Range(from = 0, to = 15) int getLuminance(ItemStack stack) {
return Block.byItem(stack.getItem()).defaultState().getLightEmission();
}
}

/**
* Represents the type of item luminance value.
*/
enum Type {
VALUE("value", Value.CODEC),
BLOCK_REFERENCE("block", BlockReference.CODEC),
BLOCK_SELF("block_self", BlockSelf.CODEC);

private static final Map<String, Type> BY_NAME = Util.make(
() -> Stream.of(values()).collect(HashMap::new, (map, type) -> map.put(type.getName(), type), HashMap::putAll)
);
public static final Codec<Type> CODEC = Codec.stringResolver(Type::getName, Type::byName);

private final String name;
private final MapCodec<? extends ItemLuminance> codec;

Type(String name, MapCodec<? extends ItemLuminance> codec) {
this.name = name;
this.codec = codec;
}

public String getName() {
return this.name;
}

public MapCodec<? extends ItemLuminance> codec() {
return this.codec;
}

public static Type byName(String name) {
return BY_NAME.get(name);
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@
import dev.lambdaurora.lambdynlights.accessor.WorldRendererAccessor;
import dev.lambdaurora.lambdynlights.api.DynamicLightHandlers;
import dev.lambdaurora.lambdynlights.api.DynamicLightsInitializer;
import dev.lambdaurora.lambdynlights.api.item.ItemLightSources;
import dev.lambdaurora.lambdynlights.resource.item.ItemLightSources;
import it.unimi.dsi.fastutil.longs.LongOpenHashSet;
import net.fabricmc.api.ClientModInitializer;
import net.fabricmc.fabric.api.client.rendering.v1.WorldRenderEvents;
Expand Down
Loading

0 comments on commit e39c01e

Please sign in to comment.