Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add new Farmland Mode with light level for crops #55

Merged
merged 12 commits into from
Apr 5, 2024
2 changes: 2 additions & 0 deletions common/src/main/java/dev/schmarrn/lighty/Lighty.java
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@
import dev.schmarrn.lighty.event.KeyBind;
import dev.schmarrn.lighty.mode.BoringCrossMode;
import dev.schmarrn.lighty.mode.CarpetMode;
import dev.schmarrn.lighty.mode.FarmlandMode;
import dev.schmarrn.lighty.mode.NumberMode;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
Expand All @@ -35,6 +36,7 @@ public static void init() {
CarpetMode.init();
NumberMode.init();
BoringCrossMode.init();
FarmlandMode.init();
KeyBind.init();
}

Expand Down
25 changes: 15 additions & 10 deletions common/src/main/java/dev/schmarrn/lighty/api/LightyColors.java
Original file line number Diff line number Diff line change
Expand Up @@ -56,17 +56,22 @@ public static int getDangerARGB() {
}

public static int getARGB(int blockLightLevel, int skyLightLevel) {
int color = LightyColors.getSafeARGB();

if (blockLightLevel <= Config.getBlockThreshold()) {
if (skyLightLevel <= Config.getSkyThreshold()) {
color = LightyColors.getDangerARGB();
} else {
color = LightyColors.getWarningARGB();
}
}
// Artificial light is always safe
if (blockLightLevel > Config.getBlockThreshold()) return LightyColors.getSafeARGB();
// If we don't have artificial lighting, mobs can spawn at night
if (skyLightLevel > Config.getSkyThreshold()) return LightyColors.getWarningARGB();
// Without artificial nor skylight, mobs can always spawn
return LightyColors.getDangerARGB();
}
andi-makes marked this conversation as resolved.
Show resolved Hide resolved

return color;
public static int getGrowthARGB(int blockLightLevel, int skyLightLevel) {
andi-makes marked this conversation as resolved.
Show resolved Hide resolved
int internalLightLevel = Integer.max(blockLightLevel, skyLightLevel);
// Above the growth threshold crops always grow
if (internalLightLevel > Config.getFarmGrowthThreshold()) return LightyColors.getSafeARGB();
// Crops can be planted but won't grow without additional light
if (internalLightLevel < Config.getFarmUprootThreshold()) return LightyColors.getWarningARGB();
// There is insufficient light here; crops will uproot themselves and can't be planted
return LightyColors.getDangerARGB();
}

private LightyColors() {}
Expand Down
38 changes: 25 additions & 13 deletions common/src/main/java/dev/schmarrn/lighty/api/LightyHelper.java
Original file line number Diff line number Diff line change
Expand Up @@ -29,30 +29,42 @@ private static boolean specialCases(Block block) {
return block instanceof CarpetBlock;
}

public static float getOffset(BlockState block, BlockPos pos, ClientLevel world) {
float offset = 0;
if (block.getBlock() instanceof SnowLayerBlock) { // snow layers
int layer = world.getBlockState(pos).getValue(SnowLayerBlock.LAYERS);
public static float getOffset(BlockState blockState, BlockPos pos, ClientLevel world) {
// Returns the offset of blocks that aren't 16 pixels high, for example snow layers or farmland.

Block block = blockState.getBlock();
if (block instanceof FarmBlock) { // farmland
// FarmBlocks are 15 pixels high
return -1f/16f;
}

BlockState blockStateUp = world.getBlockState(pos.above());
Block blockUp = blockStateUp.getBlock();
if (blockUp instanceof SnowLayerBlock) { // snow layers
int layer = blockStateUp.getValue(SnowLayerBlock.LAYERS);
if (layer != 1) {
// Mobs cannot spawn on those blocks
return -1;
}
// One layer of snow is two pixels high, with one pixel being 1/16
offset = 2f / 16f * layer;
return 2f / 16f * layer;
}
return offset;

return 0f;
}

public static boolean isBlocked(BlockState block, BlockState up, ClientLevel world, BlockPos pos, BlockPos upPos) {
public static boolean isBlocked(BlockState block, BlockPos pos, ClientLevel world) {
BlockPos posUp = pos.above();
BlockState blockStateUp = world.getBlockState(posUp);
// Resource: https://minecraft.fandom.com/wiki/Tutorials/Spawn-proofing
return (up.isCollisionShapeFullBlock(world, upPos) || // Full blocks are not spawnable in
return (blockStateUp.isCollisionShapeFullBlock(world, posUp) || // Full blocks are not spawnable in
!block.isFaceSturdy(world, pos, Direction.UP) || // Block below needs to be sturdy
isRedstone(up.getBlock()) || // Mobs don't spawn in redstone
specialCases(up.getBlock()) || // Carpets and snow
isRedstone(blockStateUp.getBlock()) || // Mobs don't spawn in redstone
specialCases(blockStateUp.getBlock()) || // Carpets and snow
!protectedIsValidSpawnCheck(block, pos, world) || // use minecraft internal isValidSpawn check
!up.getFluidState().isEmpty()) || // don't spawn in fluidlogged stuff (Kelp, Seagrass, Growlichen)
!up.getBlock().isPossibleToRespawnInThis(up) ||
up.is(BlockTags.PREVENT_MOB_SPAWNING_INSIDE); // As of 1.20.1, only contains rails, don't know if it is even really available on the client
!blockStateUp.getFluidState().isEmpty()) || // don't spawn in fluidlogged stuff (Kelp, Seagrass, Growlichen)
!blockStateUp.getBlock().isPossibleToRespawnInThis(blockStateUp) ||
blockStateUp.is(BlockTags.PREVENT_MOB_SPAWNING_INSIDE); // As of 1.20.1, only contains rails, don't know if it is even really available on the client
}

public static boolean isSafe(int blockLightLevel) {
Expand Down
24 changes: 24 additions & 0 deletions common/src/main/java/dev/schmarrn/lighty/config/Config.java
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,8 @@ public class Config {
private static final String LAST_USED_MODE = "lighty.last_used_mode";
private static final String SKY_THRESHOLD = "lighty.sky_threshold";
private static final String BLOCK_THRESHOLD = "lighty.block_threshold";
private static final String FARM_GROWTH_THRESHOLD = "lighty.farm_growth_threshold";
private static final String FARM_UPROOT_THRESHOLD = "lighty.farm_uproot_threshold";
private static final String OVERLAY_DISTANCE = "lighty.overlay_distance";
private static final String OVERLAY_BRIGHTNESS = "lighty.overlay_brightness";
private static final String SHOW_SAFE = "lighty.show_safe";
Expand All @@ -50,6 +52,8 @@ private Config() {
properties.putIfAbsent(LAST_USED_MODE, "lighty:carpet_mode");
properties.putIfAbsent(SKY_THRESHOLD, "0");
properties.putIfAbsent(BLOCK_THRESHOLD, "0");
properties.putIfAbsent(FARM_GROWTH_THRESHOLD, "8");
properties.putIfAbsent(FARM_UPROOT_THRESHOLD, "8");
properties.putIfAbsent(OVERLAY_DISTANCE, "2");
properties.putIfAbsent(OVERLAY_BRIGHTNESS, "10");
properties.putIfAbsent(SHOW_SAFE, String.valueOf(true));
Expand All @@ -63,6 +67,8 @@ private Config() {
properties.setProperty(LAST_USED_MODE, "lighty:carpet_mode");
properties.setProperty(SKY_THRESHOLD, "0");
properties.setProperty(BLOCK_THRESHOLD, "0");
properties.setProperty(FARM_GROWTH_THRESHOLD, "8");
properties.setProperty(FARM_UPROOT_THRESHOLD, "8");
properties.setProperty(OVERLAY_DISTANCE, "2");
properties.setProperty(OVERLAY_BRIGHTNESS, "10");
properties.setProperty(SHOW_SAFE, String.valueOf(true));
Expand Down Expand Up @@ -93,6 +99,14 @@ public static int getBlockThreshold() {
return Integer.parseInt(config.properties.getProperty(BLOCK_THRESHOLD, "0"));
}

public static int getFarmGrowthThreshold() {
return Integer.parseInt(config.properties.getProperty(FARM_GROWTH_THRESHOLD, "8"));
}

public static int getFarmUprootThreshold() {
return Integer.parseInt(config.properties.getProperty(FARM_UPROOT_THRESHOLD, "8"));
}

public static int getOverlayDistance() {
return Integer.parseInt(config.properties.getProperty(OVERLAY_DISTANCE, "2"));
}
Expand Down Expand Up @@ -123,6 +137,16 @@ public static void setBlockThreshold(int i) {
config.write();
}

public static void setFarmGrowthThreshold(int i) {
config.properties.setProperty(FARM_GROWTH_THRESHOLD, String.valueOf(i));
config.write();
}

public static void setFarmUprootThreshold(int i) {
config.properties.setProperty(FARM_UPROOT_THRESHOLD, String.valueOf(i));
config.write();
}

public static void setOverlayDistance(int i) {
config.properties.setProperty(OVERLAY_DISTANCE, String.valueOf(i));
config.write();
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,7 @@
import net.minecraft.core.BlockPos;
import net.minecraft.resources.ResourceLocation;
import net.minecraft.world.level.LightLayer;
import net.minecraft.world.level.block.state.BlockState;

public class BoringCrossMode extends LightyMode {

Expand All @@ -40,7 +41,8 @@ public void beforeCompute(BufferBuilder builder) {

@Override
public void compute(ClientLevel world, BlockPos pos, BufferBuilder builder) {
if (!LightyHelper.isBlocked(world.getBlockState(pos.below()), world.getBlockState(pos), world, pos.below(), pos)) {
BlockState blockState = world.getBlockState(pos);
if (!LightyHelper.isBlocked(world.getBlockState(pos.below()), pos, world)) {
int blockLightLevel = world.getBrightness(LightLayer.BLOCK, pos);
int skyLightLevel = world.getBrightness(LightLayer.SKY, pos);

Expand All @@ -50,7 +52,7 @@ public void compute(ClientLevel world, BlockPos pos, BufferBuilder builder) {

int color = LightyColors.getARGB(blockLightLevel, skyLightLevel);

float offset = LightyHelper.getOffset(world.getBlockState(pos), pos, world);
float offset = LightyHelper.getOffset(blockState, pos, world);
if (offset == -1f) {
return;
}
Expand Down
8 changes: 3 additions & 5 deletions common/src/main/java/dev/schmarrn/lighty/mode/CarpetMode.java
Original file line number Diff line number Diff line change
Expand Up @@ -44,10 +44,9 @@ public void beforeCompute(BufferBuilder builder) {
@Override
public void compute(ClientLevel world, BlockPos pos, BufferBuilder builder) {
BlockPos posUp = pos.above();
BlockState up = world.getBlockState(posUp);
BlockState block = world.getBlockState(pos);
BlockState blockState = world.getBlockState(pos);

if (LightyHelper.isBlocked(block, up, world, pos, posUp)) {
if (LightyHelper.isBlocked(blockState, pos, world)) {
return;
}

Expand All @@ -60,8 +59,7 @@ public void compute(ClientLevel world, BlockPos pos, BufferBuilder builder) {

int color = LightyColors.getARGB(blockLightLevel, skyLightLevel);

double offset = LightyHelper.getOffset(up, posUp, world);

double offset = LightyHelper.getOffset(blockState, pos, world);
if (offset == -1f) {
return;
}
Expand Down
90 changes: 90 additions & 0 deletions common/src/main/java/dev/schmarrn/lighty/mode/FarmlandMode.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,90 @@
package dev.schmarrn.lighty.mode;

import com.mojang.blaze3d.vertex.BufferBuilder;
import dev.schmarrn.lighty.Lighty;
import dev.schmarrn.lighty.api.LightyColors;
import dev.schmarrn.lighty.api.LightyHelper;
import dev.schmarrn.lighty.api.ModeManager;
import dev.schmarrn.lighty.config.Config;
import net.minecraft.client.multiplayer.ClientLevel;
import net.minecraft.client.renderer.LightTexture;
import net.minecraft.core.BlockPos;
import net.minecraft.core.Direction;
import net.minecraft.resources.ResourceLocation;
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.FarmBlock;
import net.minecraft.world.level.block.state.BlockState;

/**
* Extending CarpetMode because the code is largely identical
*/
public class FarmlandMode extends CarpetMode {
@Override
public void compute(ClientLevel world, BlockPos pos, BufferBuilder builder) {
BlockPos posUp = pos.above();
BlockState blockState = world.getBlockState(pos);

if (!(blockState.getBlock() instanceof FarmBlock)) {
return;
}

int blockLightLevel = world.getBrightness(LightLayer.BLOCK, posUp);
int skyLightLevel = world.getBrightness(LightLayer.SKY, posUp);
int color = LightyColors.getGrowthARGB(blockLightLevel, skyLightLevel);

double offset = LightyHelper.getOffset(blockState, pos, world);
if (offset == -1f) {
return;
}

double x = pos.getX();
double y = pos.getY() + 1 + offset;
double z = pos.getZ();
int overlayBrightness = Config.getOverlayBrightness();
// the first parameter corresponds to the blockLightLevel, the second to the skyLightLevel
int lightmap = LightTexture.pack(overlayBrightness, overlayBrightness);
//TOP
builder.vertex(x, y + 1 / 16f, z).color(color).uv(0, 0).uv2(lightmap).normal(0f, 1f, 0f).endVertex();
builder.vertex(x, y + 1 / 16f, z + 1).color(color).uv(0, 1).uv2(lightmap).normal(0f, 1f, 0f).endVertex();
builder.vertex(x + 1, y + 1 / 16f, z + 1).color(color).uv(1, 1).uv2(lightmap).normal(0f, 1f, 0f).endVertex();
builder.vertex(x + 1, y + 1 / 16f, z).color(color).uv(1, 0).uv2(lightmap).normal(0f, 1f, 0f).endVertex();
if (offset > 0.001f) {
//if it renders above it should check if the block above culls the faces
pos = pos.above();
}
//NORTH
if (Block.shouldRenderFace(Blocks.STONE.defaultBlockState(), world, pos, Direction.SOUTH, pos.relative(Direction.SOUTH))) {
builder.vertex(x, y + 1 / 16f, z + 1).color(color).uv(0, 1f / 16).uv2(lightmap).normal(0f, 0f, -1f).endVertex();
builder.vertex(x, y, z + 1).color(color).uv(0, 0).uv2(lightmap).normal(0f, 0f, -1f).endVertex();
builder.vertex(x + 1, y, z + 1).color(color).uv(1, 0).uv2(lightmap).normal(0f, 0f, -1f).endVertex();
builder.vertex(x + 1, y + 1 / 16f, z + 1).color(color).uv(1, 1f / 16).uv2(lightmap).normal(0f, 0f, -1f).endVertex();
}
//EAST
if (Block.shouldRenderFace(Blocks.STONE.defaultBlockState(), world, pos, Direction.WEST, pos.relative(Direction.WEST))) {
builder.vertex(x, y + 1/16f, z).color(color).uv(0,1f/16).uv2(lightmap).normal(-1f, 0f, 0f).endVertex();
builder.vertex(x, y, z).color(color).uv(0, 0).uv2(lightmap).normal(-1f, 0f, 0f).endVertex();
builder.vertex(x, y, z + 1).color(color).uv(1, 0).uv2(lightmap).normal(-1f, 0f, 0f).endVertex();
builder.vertex(x, y + 1/16f, z + 1).color(color).uv(1, 1f/16).uv2(lightmap).normal(-1f, 0f, 0f).endVertex();
}
//SOUTH
if (Block.shouldRenderFace(Blocks.STONE.defaultBlockState(), world, pos, Direction.NORTH, pos.relative(Direction.NORTH))) {
builder.vertex(x+1, y + 1/16f, z).color(color).uv(0,1f/16).uv2(lightmap).normal(0f, 0f, 1f).endVertex();
builder.vertex(x+1, y, z).color(color).uv(0, 0).uv2(lightmap).normal(0f, 0f, -1f).endVertex();
builder.vertex(x, y, z).color(color).uv(1, 0).uv2(lightmap).normal(0f, 0f, -1f).endVertex();
builder.vertex(x, y + 1/16f, z).color(color).uv(1, 1f/16).uv2(lightmap).normal(0f, 0f, -1f).endVertex();
}
//WEST
if (Block.shouldRenderFace(Blocks.STONE.defaultBlockState(), world, pos, Direction.EAST, pos.relative(Direction.EAST))) {
builder.vertex(x+1, y + 1/16f, z+1).color(color).uv(0,1f/16).uv2(lightmap).normal(1f, 0f, 0f).endVertex();
builder.vertex(x+1, y, z+1).color(color).uv(0, 0).uv2(lightmap).normal(1f, 0f, 0f).endVertex();
builder.vertex(x+1, y, z).color(color).uv(1, 0).uv2(lightmap).normal(1f, 0f, 0f).endVertex();
builder.vertex(x+1, y + 1/16f, z).color(color).uv(1, 1f/16).uv2(lightmap).normal(1f, 0f, 0f).endVertex();
}
}

public static void init() {
ModeManager.registerMode(new ResourceLocation(Lighty.MOD_ID, "farmland_mode"), new FarmlandMode());
}
}
7 changes: 3 additions & 4 deletions common/src/main/java/dev/schmarrn/lighty/mode/NumberMode.java
Original file line number Diff line number Diff line change
Expand Up @@ -87,9 +87,8 @@ private static void renderNumber(BufferBuilder builder, int number, float x, flo
@Override
public void compute(ClientLevel world, BlockPos pos, BufferBuilder builder) {
BlockPos posUp = pos.above();
BlockState up = world.getBlockState(posUp);
BlockState block = world.getBlockState(pos);
if (LightyHelper.isBlocked(block, up, world, pos, posUp)) {
BlockState blockState = world.getBlockState(pos);
if (LightyHelper.isBlocked(blockState, pos, world)) {
return;
}

Expand All @@ -102,7 +101,7 @@ public void compute(ClientLevel world, BlockPos pos, BufferBuilder builder) {

int color = LightyColors.getARGB(blockLightLevel, skyLightLevel);

float offset = LightyHelper.getOffset(up, posUp, world);
float offset = LightyHelper.getOffset(blockState, pos, world);
if (offset == -1f) {
return;
}
Expand Down
21 changes: 18 additions & 3 deletions common/src/main/java/dev/schmarrn/lighty/ui/SettingsScreen.java
Original file line number Diff line number Diff line change
Expand Up @@ -21,16 +21,13 @@
import net.minecraft.client.Options;
import net.minecraft.client.gui.GuiGraphics;
import net.minecraft.client.gui.components.Button;
import net.minecraft.client.gui.components.Checkbox;
import net.minecraft.client.gui.components.OptionsList;
import net.minecraft.client.gui.components.Tooltip;
import net.minecraft.client.gui.screens.Screen;
import net.minecraft.network.chat.CommonComponents;
import net.minecraft.network.chat.Component;
import org.jetbrains.annotations.NotNull;

import java.util.ArrayList;

andi-makes marked this conversation as resolved.
Show resolved Hide resolved
public class SettingsScreen extends Screen {
public SettingsScreen() {
super(Component.translatable("settings.lighty.title"));
Expand Down Expand Up @@ -83,6 +80,24 @@ protected void init() {
Config.getSkyThreshold(),
Config::setSkyThreshold
),
new OptionInstance<>(
"lighty.options.farm_growth_threshold",
object -> Tooltip.create(Component.translatable("lighty.options.farm_growth_threshold.tooltip", object)),
(component, integer) -> Options.genericValueLabel(component, Component.literal(integer.toString())),
new OptionInstance.IntRange(0, 15),
Codec.intRange(0, 15),
Config.getFarmGrowthThreshold(),
Config::setFarmGrowthThreshold
),
new OptionInstance<>(
"lighty.options.farm_uproot_threshold",
object -> Tooltip.create(Component.translatable("lighty.options.farm_uproot_threshold.tooltip", object)),
(component, integer) -> Options.genericValueLabel(component, Component.literal(integer.toString())),
new OptionInstance.IntRange(0, 15),
Codec.intRange(0, 15),
Config.getFarmUprootThreshold(),
Config::setFarmUprootThreshold
),
OptionInstance.createBoolean(
"lighty.options.show_safe",
object -> Tooltip.create(Component.translatable("lighty.options.show_safe.tooltip", object)),
Expand Down
Loading
Loading