Initial sanctuary sources
This commit is contained in:
+208
@@ -0,0 +1,208 @@
|
||||
package fr.koka99cab.dynamic_torches.client;
|
||||
|
||||
import net.minecraft.client.Minecraft;
|
||||
import net.minecraft.client.multiplayer.ClientLevel;
|
||||
import net.minecraft.client.player.LocalPlayer;
|
||||
import net.minecraft.client.renderer.LevelRenderer;
|
||||
import net.minecraft.core.BlockPos;
|
||||
import net.minecraft.core.SectionPos;
|
||||
import net.minecraft.util.LightCoordsUtil;
|
||||
import net.minecraft.world.InteractionHand;
|
||||
import net.minecraft.world.entity.HumanoidArm;
|
||||
import net.minecraft.world.item.BlockItem;
|
||||
import net.minecraft.world.item.Item;
|
||||
import net.minecraft.world.item.ItemStack;
|
||||
import net.minecraft.world.level.BlockAndLightGetter;
|
||||
import net.minecraft.world.level.block.state.BlockState;
|
||||
import net.minecraft.world.phys.Vec3;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
public final class DynamicTorchLights {
|
||||
private static final int MAX_DYNAMIC_LIGHT = 15;
|
||||
private static final int RENDER_RADIUS = MAX_DYNAMIC_LIGHT;
|
||||
private static final double HAND_FORWARD_OFFSET = 0.35D;
|
||||
private static final double HAND_SIDE_OFFSET = 0.35D;
|
||||
private static final double HAND_DOWN_OFFSET = 0.35D;
|
||||
|
||||
private static ClientLevel lastLevel;
|
||||
private static List<LightSource> sources = List.of();
|
||||
|
||||
private DynamicTorchLights() {
|
||||
}
|
||||
|
||||
public static void tick(Minecraft client) {
|
||||
if (client.level == null || client.player == null) {
|
||||
sources = List.of();
|
||||
lastLevel = null;
|
||||
return;
|
||||
}
|
||||
|
||||
if (client.level != lastLevel) {
|
||||
sources = List.of();
|
||||
lastLevel = client.level;
|
||||
}
|
||||
|
||||
List<LightSource> nextSources = collectHeldTorchSources(client.player);
|
||||
if (sameSourceBlocks(sources, nextSources)) {
|
||||
sources = nextSources;
|
||||
return;
|
||||
}
|
||||
|
||||
markSourcesDirty(client.levelRenderer, sources);
|
||||
sources = nextSources;
|
||||
markSourcesDirty(client.levelRenderer, sources);
|
||||
}
|
||||
|
||||
public static int applyDynamicLight(int packedLight, BlockAndLightGetter level, BlockPos pos) {
|
||||
return applyDynamicLight(packedLight, pos);
|
||||
}
|
||||
|
||||
public static int applyDynamicLight(int packedLight, BlockPos pos) {
|
||||
if (sources.isEmpty() || pos == null) {
|
||||
return packedLight;
|
||||
}
|
||||
|
||||
int vanillaBlockLight = LightCoordsUtil.block(packedLight);
|
||||
if (vanillaBlockLight >= 15) {
|
||||
return packedLight;
|
||||
}
|
||||
|
||||
int dynamicBlockLight = applyDynamicBlockLight(vanillaBlockLight, pos);
|
||||
if (dynamicBlockLight <= vanillaBlockLight) {
|
||||
return packedLight;
|
||||
}
|
||||
|
||||
return LightCoordsUtil.withBlock(packedLight, dynamicBlockLight);
|
||||
}
|
||||
|
||||
public static int applyDynamicBlockLight(int blockLight, BlockPos pos) {
|
||||
if (sources.isEmpty() || pos == null || blockLight >= 15) {
|
||||
return blockLight;
|
||||
}
|
||||
|
||||
return Math.max(blockLight, getDynamicBlockLight(pos));
|
||||
}
|
||||
|
||||
public static int applyHeldTorchLight(int packedLight) {
|
||||
if (sources.isEmpty()) {
|
||||
return packedLight;
|
||||
}
|
||||
|
||||
int vanillaBlockLight = LightCoordsUtil.block(packedLight);
|
||||
if (vanillaBlockLight >= 15) {
|
||||
return packedLight;
|
||||
}
|
||||
|
||||
int heldLight = 0;
|
||||
for (LightSource source : sources) {
|
||||
heldLight = Math.max(heldLight, source.lightLevel());
|
||||
}
|
||||
|
||||
if (heldLight <= vanillaBlockLight) {
|
||||
return packedLight;
|
||||
}
|
||||
|
||||
return LightCoordsUtil.withBlock(packedLight, heldLight);
|
||||
}
|
||||
|
||||
private static List<LightSource> collectHeldTorchSources(LocalPlayer player) {
|
||||
List<LightSource> nextSources = new ArrayList<>(2);
|
||||
addHandSource(player, InteractionHand.MAIN_HAND, nextSources);
|
||||
addHandSource(player, InteractionHand.OFF_HAND, nextSources);
|
||||
return List.copyOf(nextSources);
|
||||
}
|
||||
|
||||
private static void addHandSource(LocalPlayer player, InteractionHand hand, List<LightSource> nextSources) {
|
||||
int lightLevel = getHeldLightLevel(player.getItemInHand(hand));
|
||||
if (lightLevel <= 0) {
|
||||
return;
|
||||
}
|
||||
|
||||
HumanoidArm arm = hand == InteractionHand.MAIN_HAND ? player.getMainArm() : player.getMainArm().getOpposite();
|
||||
nextSources.add(new LightSource(handPosition(player, arm), lightLevel));
|
||||
}
|
||||
|
||||
private static int getHeldLightLevel(ItemStack stack) {
|
||||
if (stack.isEmpty()) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
Item item = stack.getItem();
|
||||
if (item instanceof BlockItem blockItem) {
|
||||
BlockState blockState = blockItem.getBlock().defaultBlockState();
|
||||
return Math.min(MAX_DYNAMIC_LIGHT, Math.max(0, blockState.getLightEmission()));
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
private static Vec3 handPosition(LocalPlayer player, HumanoidArm arm) {
|
||||
Vec3 forward = Vec3.directionFromRotation(0.0F, player.getYRot());
|
||||
Vec3 right = Vec3.directionFromRotation(0.0F, player.getYRot() + 90.0F);
|
||||
double sideOffset = arm == HumanoidArm.RIGHT ? HAND_SIDE_OFFSET : -HAND_SIDE_OFFSET;
|
||||
return player.getEyePosition()
|
||||
.add(forward.scale(HAND_FORWARD_OFFSET))
|
||||
.add(right.scale(sideOffset))
|
||||
.add(0.0D, -HAND_DOWN_OFFSET, 0.0D);
|
||||
}
|
||||
|
||||
private static int getDynamicBlockLight(BlockPos pos) {
|
||||
Vec3 blockCenter = pos.getCenter();
|
||||
int bestLight = 0;
|
||||
|
||||
for (LightSource source : sources) {
|
||||
double distance = source.position().distanceTo(blockCenter);
|
||||
if (distance >= source.lightLevel()) {
|
||||
continue;
|
||||
}
|
||||
|
||||
int light = Math.max(0, source.lightLevel() - (int) Math.floor(distance));
|
||||
if (light > bestLight) {
|
||||
bestLight = light;
|
||||
}
|
||||
}
|
||||
|
||||
return Math.min(MAX_DYNAMIC_LIGHT, bestLight);
|
||||
}
|
||||
|
||||
private static boolean sameSourceBlocks(List<LightSource> previous, List<LightSource> next) {
|
||||
if (previous.size() != next.size()) {
|
||||
return false;
|
||||
}
|
||||
|
||||
for (int i = 0; i < previous.size(); i++) {
|
||||
LightSource previousSource = previous.get(i);
|
||||
LightSource nextSource = next.get(i);
|
||||
if (previousSource.lightLevel() != nextSource.lightLevel()) {
|
||||
return false;
|
||||
}
|
||||
if (!BlockPos.containing(previousSource.position()).equals(BlockPos.containing(nextSource.position()))) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
private static void markSourcesDirty(LevelRenderer levelRenderer, List<LightSource> dirtySources) {
|
||||
for (LightSource source : dirtySources) {
|
||||
markSourceDirty(levelRenderer, source);
|
||||
}
|
||||
}
|
||||
|
||||
private static void markSourceDirty(LevelRenderer levelRenderer, LightSource source) {
|
||||
BlockPos center = BlockPos.containing(source.position());
|
||||
int radius = Math.max(RENDER_RADIUS, source.lightLevel());
|
||||
int minSectionX = SectionPos.blockToSectionCoord(center.getX() - radius);
|
||||
int minSectionY = SectionPos.blockToSectionCoord(center.getY() - radius);
|
||||
int minSectionZ = SectionPos.blockToSectionCoord(center.getZ() - radius);
|
||||
int maxSectionX = SectionPos.blockToSectionCoord(center.getX() + radius);
|
||||
int maxSectionY = SectionPos.blockToSectionCoord(center.getY() + radius);
|
||||
int maxSectionZ = SectionPos.blockToSectionCoord(center.getZ() + radius);
|
||||
levelRenderer.setSectionRangeDirty(minSectionX, minSectionY, minSectionZ, maxSectionX, maxSectionY, maxSectionZ);
|
||||
}
|
||||
|
||||
private record LightSource(Vec3 position, int lightLevel) {
|
||||
}
|
||||
}
|
||||
+13
@@ -0,0 +1,13 @@
|
||||
package fr.koka99cab.dynamic_torches.client;
|
||||
|
||||
import fr.koka99cab.dynamic_torches.DynamicTorchesMod;
|
||||
import net.fabricmc.api.ClientModInitializer;
|
||||
import net.fabricmc.fabric.api.client.event.lifecycle.v1.ClientTickEvents;
|
||||
|
||||
public class DynamicTorchesClient implements ClientModInitializer {
|
||||
@Override
|
||||
public void onInitializeClient() {
|
||||
ClientTickEvents.END_CLIENT_TICK.register(DynamicTorchLights::tick);
|
||||
DynamicTorchesMod.LOGGER.info("Dynamic Torches client initialise.");
|
||||
}
|
||||
}
|
||||
+18
@@ -0,0 +1,18 @@
|
||||
package fr.koka99cab.dynamic_torches.mixin.client;
|
||||
|
||||
import fr.koka99cab.dynamic_torches.client.DynamicTorchLights;
|
||||
import net.minecraft.client.renderer.entity.EntityRenderer;
|
||||
import net.minecraft.core.BlockPos;
|
||||
import net.minecraft.world.entity.Entity;
|
||||
import org.spongepowered.asm.mixin.Mixin;
|
||||
import org.spongepowered.asm.mixin.injection.At;
|
||||
import org.spongepowered.asm.mixin.injection.Inject;
|
||||
import org.spongepowered.asm.mixin.injection.callback.CallbackInfoReturnable;
|
||||
|
||||
@Mixin(EntityRenderer.class)
|
||||
public abstract class EntityRendererMixin {
|
||||
@Inject(method = "getBlockLightLevel", at = @At("RETURN"), cancellable = true)
|
||||
private void dynamicTorches$applyEntityLight(Entity entity, BlockPos pos, CallbackInfoReturnable<Integer> cir) {
|
||||
cir.setReturnValue(DynamicTorchLights.applyDynamicBlockLight(cir.getReturnValue(), pos));
|
||||
}
|
||||
}
|
||||
+22
@@ -0,0 +1,22 @@
|
||||
package fr.koka99cab.dynamic_torches.mixin.client;
|
||||
|
||||
import fr.koka99cab.dynamic_torches.client.DynamicTorchLights;
|
||||
import net.minecraft.client.renderer.ItemInHandRenderer;
|
||||
import org.spongepowered.asm.mixin.Mixin;
|
||||
import org.spongepowered.asm.mixin.injection.At;
|
||||
import org.spongepowered.asm.mixin.injection.ModifyArg;
|
||||
|
||||
@Mixin(ItemInHandRenderer.class)
|
||||
public abstract class ItemInHandRendererMixin {
|
||||
@ModifyArg(
|
||||
method = "renderHandsWithItems",
|
||||
at = @At(
|
||||
value = "INVOKE",
|
||||
target = "Lnet/minecraft/client/renderer/ItemInHandRenderer;renderArmWithItem(Lnet/minecraft/client/player/AbstractClientPlayer;FFLnet/minecraft/world/InteractionHand;FLnet/minecraft/world/item/ItemStack;FLcom/mojang/blaze3d/vertex/PoseStack;Lnet/minecraft/client/renderer/SubmitNodeCollector;I)V"
|
||||
),
|
||||
index = 9
|
||||
)
|
||||
private int dynamicTorches$applyHeldTorchLightToHand(int light) {
|
||||
return DynamicTorchLights.applyHeldTorchLight(light);
|
||||
}
|
||||
}
|
||||
+24
@@ -0,0 +1,24 @@
|
||||
package fr.koka99cab.dynamic_torches.mixin.client;
|
||||
|
||||
import fr.koka99cab.dynamic_torches.client.DynamicTorchLights;
|
||||
import net.minecraft.client.renderer.LevelRenderer;
|
||||
import net.minecraft.core.BlockPos;
|
||||
import net.minecraft.world.level.BlockAndLightGetter;
|
||||
import net.minecraft.world.level.block.state.BlockState;
|
||||
import org.spongepowered.asm.mixin.Mixin;
|
||||
import org.spongepowered.asm.mixin.injection.At;
|
||||
import org.spongepowered.asm.mixin.injection.Inject;
|
||||
import org.spongepowered.asm.mixin.injection.callback.CallbackInfoReturnable;
|
||||
|
||||
@Mixin(LevelRenderer.class)
|
||||
public abstract class LevelRendererMixin {
|
||||
@Inject(
|
||||
method = "getLightCoords(Lnet/minecraft/client/renderer/LevelRenderer$BrightnessGetter;Lnet/minecraft/world/level/BlockAndLightGetter;Lnet/minecraft/world/level/block/state/BlockState;Lnet/minecraft/core/BlockPos;)I",
|
||||
at = @At("RETURN"),
|
||||
cancellable = true
|
||||
)
|
||||
private static void dynamicTorches$applyHeldTorchLight(LevelRenderer.BrightnessGetter brightnessGetter, BlockAndLightGetter level,
|
||||
BlockState state, BlockPos pos, CallbackInfoReturnable<Integer> cir) {
|
||||
cir.setReturnValue(DynamicTorchLights.applyDynamicLight(cir.getReturnValue(), level, pos));
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,14 @@
|
||||
{
|
||||
"required": true,
|
||||
"minVersion": "0.8",
|
||||
"package": "fr.koka99cab.dynamic_torches.mixin.client",
|
||||
"compatibilityLevel": "JAVA_25",
|
||||
"client": [
|
||||
"EntityRendererMixin",
|
||||
"ItemInHandRendererMixin",
|
||||
"LevelRendererMixin"
|
||||
],
|
||||
"injectors": {
|
||||
"defaultRequire": 1
|
||||
}
|
||||
}
|
||||
+15
@@ -0,0 +1,15 @@
|
||||
package fr.koka99cab.dynamic_torches;
|
||||
|
||||
import net.fabricmc.api.ModInitializer;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
public class DynamicTorchesMod implements ModInitializer {
|
||||
public static final String MOD_ID = "dynamic_torches";
|
||||
public static final Logger LOGGER = LoggerFactory.getLogger(MOD_ID);
|
||||
|
||||
@Override
|
||||
public void onInitialize() {
|
||||
LOGGER.info("Dynamic Torches charge pour Minecraft 26.1.2.");
|
||||
}
|
||||
}
|
||||
Binary file not shown.
|
After Width: | Height: | Size: 256 KiB |
@@ -0,0 +1,3 @@
|
||||
{
|
||||
"modmenu.descriptionTranslation.dynamic_torches": "Client-side dynamic lighting for luminous items held in either hand."
|
||||
}
|
||||
@@ -0,0 +1,3 @@
|
||||
{
|
||||
"modmenu.descriptionTranslation.dynamic_torches": "Lumiere dynamique cote client pour les objets lumineux tenus en main gauche ou droite."
|
||||
}
|
||||
@@ -0,0 +1,30 @@
|
||||
{
|
||||
"schemaVersion": 1,
|
||||
"id": "dynamic_torches",
|
||||
"version": "${version}",
|
||||
"name": "Dynamic Torches",
|
||||
"description": "Client-side dynamic lighting for luminous items held in either hand.",
|
||||
"authors": [
|
||||
"KOKA99CAB"
|
||||
],
|
||||
"icon": "assets/dynamic_torches/icon.png",
|
||||
"license": "LGPL-3.0-or-later",
|
||||
"environment": "*",
|
||||
"entrypoints": {
|
||||
"main": [
|
||||
"fr.koka99cab.dynamic_torches.DynamicTorchesMod"
|
||||
],
|
||||
"client": [
|
||||
"fr.koka99cab.dynamic_torches.client.DynamicTorchesClient"
|
||||
]
|
||||
},
|
||||
"mixins": [
|
||||
"dynamic_torches.client.mixins.json"
|
||||
],
|
||||
"depends": {
|
||||
"fabricloader": ">=0.19.2",
|
||||
"minecraft": "~26.1.2",
|
||||
"java": ">=25",
|
||||
"fabric-api": "*"
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user