Skip to content

Commit

Permalink
Implemented the bedrock snow leaves feature (Really buggy)
Browse files Browse the repository at this point in the history
  • Loading branch information
Qzimyion committed Dec 25, 2024
1 parent 2175f15 commit 143a54f
Show file tree
Hide file tree
Showing 4 changed files with 194 additions and 0 deletions.
Original file line number Diff line number Diff line change
@@ -0,0 +1,91 @@
package net.qzimyion.cellulose.mixin.snowing;

import net.minecraft.core.BlockPos;
import net.minecraft.util.RandomSource;
import net.minecraft.world.level.Level;
import net.minecraft.world.level.LightLayer;
import net.minecraft.world.level.block.Block;
import net.minecraft.world.level.block.Blocks;
import net.minecraft.world.level.block.LeavesBlock;
import net.minecraft.world.level.block.state.BlockState;
import net.minecraft.world.level.block.state.properties.BooleanProperty;
import net.minecraft.world.level.levelgen.Heightmap;
import net.qzimyion.cellulose.util.ISnow;
import net.qzimyion.cellulose.util.TintManager;
import org.spongepowered.asm.mixin.Final;
import org.spongepowered.asm.mixin.Mixin;
import org.spongepowered.asm.mixin.Shadow;
import org.spongepowered.asm.mixin.Unique;
import org.spongepowered.asm.mixin.injection.At;
import org.spongepowered.asm.mixin.injection.Inject;
import org.spongepowered.asm.mixin.injection.callback.CallbackInfo;

@Mixin(LeavesBlock.class)
public class LeafBlocksMixin extends Block implements ISnow {

@Shadow
@Final
public static BooleanProperty PERSISTENT;

@Unique
private boolean isSnowing = false;
@Unique
private long lastUpdateTime = 0;

public LeafBlocksMixin(Properties properties) {
super(properties);
}

@Override
public boolean isSnowy(Level level, BlockPos pos) {
return updateSnow(level, pos);
}

@Unique
private boolean updateSnow(Level level, BlockPos pos) {
if (level.getBiome(pos).value().warmEnoughToRain(pos)) return false;

int topY = level.getHeightmapPos(Heightmap.Types.MOTION_BLOCKING_NO_LEAVES, pos).getY();
if (topY > pos.getY()) {
BlockPos checkPos = pos.above();
for (int i = 0; i < topY - pos.getY(); i++) {
if (level.getBrightness(LightLayer.SKY, checkPos) == 15) return true;

Block block = level.getBlockState(checkPos).getBlock();
if (!(block instanceof LeavesBlock) && !block.equals(Blocks.AIR) && !block.equals(Blocks.SNOW) && !block.equals(Blocks.SNOW_BLOCK)) {
return false;
}
checkPos = checkPos.above();
}
}
return true;
}

@Inject(method = "animateTick", at = @At("HEAD"))
public void animateTick(
BlockState state,
Level level,
BlockPos pos,
RandomSource random,
CallbackInfo ci
) {
if (level.getBiome(pos).value().warmEnoughToRain(pos)) return;

boolean isCurrentlySnowing = level.isRaining();
if (isCurrentlySnowing != isSnowing) {
isSnowing = isCurrentlySnowing;
lastUpdateTime = level.getGameTime();
TintManager.updateTint();
}

if (level.getGameTime() - lastUpdateTime > 400) return;

boolean persistent = state.getValue(PERSISTENT);
// if (persistent != isSnowing) {
// level.setBlock(pos, state.setValue(PERSISTENT, isSnowing), 2);
// }
level.setBlockAndUpdate(pos, state.setValue(PERSISTENT, !persistent));
level.setBlockAndUpdate(pos, state.setValue(PERSISTENT, persistent));
}

}
51 changes: 51 additions & 0 deletions src/main/java/net/qzimyion/cellulose/mixin/snowing/LeafRender.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,51 @@
package net.qzimyion.cellulose.mixin.snowing;


import net.minecraft.client.color.block.BlockColors;
import net.minecraft.core.BlockPos;
import net.minecraft.world.level.BlockAndTintGetter;
import net.minecraft.world.level.block.LeavesBlock;
import net.minecraft.world.level.block.state.BlockState;
import net.qzimyion.cellulose.util.TintManager;
import org.jetbrains.annotations.Nullable;
import org.spongepowered.asm.mixin.Mixin;
import org.spongepowered.asm.mixin.Unique;
import org.spongepowered.asm.mixin.injection.At;
import org.spongepowered.asm.mixin.injection.Inject;
import org.spongepowered.asm.mixin.injection.callback.CallbackInfoReturnable;

@Mixin(BlockColors.class)
public class LeafRender {

@Unique
private int adjustColor(int baseColor, float gradient) {
int red = (baseColor >> 16) & 0xFF;
int green = (baseColor >> 8) & 0xFF;
int blue = baseColor & 0xFF;

red += (int) (gradient * (255 - red));
green += (int) (gradient * (255 - green));
blue += (int) (gradient * (255 - blue));

return (red << 16) | (green << 8) | blue;
}

@Inject(
method = "getColor(Lnet/minecraft/world/level/block/state/BlockState;Lnet/minecraft/world/level/BlockAndTintGetter;Lnet/minecraft/core/BlockPos;I)I",
at = @At("RETURN"),
cancellable = true
)
public void getColor(
BlockState state,
net.minecraft.world.level.BlockAndTintGetter tintGetter,
BlockPos pos,
int tintIndex,
CallbackInfoReturnable<Integer> cir
) {
if (pos == null || !(state.getBlock() instanceof LeavesBlock)) return;

int baseColor = cir.getReturnValue();
float gradient = TintManager.getGradient();
cir.setReturnValue(adjustColor(baseColor, gradient));
}
}
8 changes: 8 additions & 0 deletions src/main/java/net/qzimyion/cellulose/util/ISnow.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
package net.qzimyion.cellulose.util;

import net.minecraft.core.BlockPos;
import net.minecraft.world.level.Level;

public interface ISnow {
boolean isSnowy(Level level, BlockPos pos);
}
44 changes: 44 additions & 0 deletions src/main/java/net/qzimyion/cellulose/util/TintManager.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,44 @@
package net.qzimyion.cellulose.util;

import net.minecraft.client.Minecraft;
import net.minecraft.client.multiplayer.ClientLevel;
import net.minecraft.util.Mth;

import java.util.Objects;

public class TintManager {
private static float gradient = 0;
private static long lastUpdateTime = 0;

public static void updateTint() {
Minecraft client = Minecraft.getInstance();
ClientLevel clientLevel = client.level;
if (clientLevel == null) return;

long currentTime = clientLevel.getGameTime();
boolean isSnowing = clientLevel.isRaining() &&
!clientLevel.getBiome(Objects.requireNonNull(client.player).blockPosition())
.value()
.warmEnoughToRain(client.player.blockPosition());

if (isSnowing) {
gradient += (currentTime - lastUpdateTime) / 300.0f;
} else {
gradient -= (currentTime - lastUpdateTime) / 300.0f;
}

gradient = Mth.clamp(gradient, 0, 1);
lastUpdateTime = currentTime;
updateChunks(clientLevel);
}

public static void updateChunks(ClientLevel level) {
if (level != null) {
Minecraft.getInstance().levelRenderer.allChanged();
}
}

public static float getGradient() {
return gradient;
}
}

0 comments on commit 143a54f

Please sign in to comment.