diff --git a/src/main/java/com/ishikyoo/leavesly/ColorProvider.java b/src/main/java/com/ishikyoo/leavesly/ColorProvider.java new file mode 100644 index 0000000..54ccb8f --- /dev/null +++ b/src/main/java/com/ishikyoo/leavesly/ColorProvider.java @@ -0,0 +1,144 @@ +package com.ishikyoo.leavesly; + +import com.ishikyoo.leavesly.property.Properties; +import com.ishikyoo.leavesly.support.Support; +import net.fabricmc.fabric.api.client.rendering.v1.ColorProviderRegistry; +import net.minecraft.block.Block; +import net.minecraft.block.BlockState; +import net.minecraft.client.color.world.BiomeColors; +import net.minecraft.state.property.IntProperty; +import net.minecraft.util.math.BlockPos; +import net.minecraft.world.BlockRenderView; +import net.minecraft.world.biome.FoliageColors; + +import java.util.ArrayList; +import java.util.HashMap; +import java.util.List; + +public class ColorProvider { + private static final IntProperty SNOW_LAYER = Properties.SNOW_LAYER; + + private static final Block[] BlockArray = Support.getBlocks(); + + private static final List blockStaticColorsList = new ArrayList<>(); + private static final HashMap blockStaticColorsHashMap = new HashMap<>(); + + private static final List blockFoliageColorsList = new ArrayList<>(); + private static final List blockGrassColorsList = new ArrayList<>(); + private static final HashMap blockColorMasksHashMap = new HashMap<>(); + + public static void initialize() { + initializeColorMasks(); + initializeColorProvides(); + } + + private static void initializeColorMasks() { + for (Block block : BlockArray) { + String blockId = Support.getBlockId(block); + if (blockId.equals("azalea_leaves")) + addBlockStaticColor(block,0xC4FF4F, 0.5725490196); + else if (blockId.equals("birch_leaves")) + addBlockStaticColor(block, FoliageColors.getBirchColor(), 0.72549019607); + else if (blockId.equals("cherry_leaves")) + addBlockStaticColor(block,0xDEFF4C, 0.6); + else if (blockId.equals("dark_oak_leaves")) + addBlockFoliageColor(block, 0.72549019607); + else if (blockId.equals("flowering_azalea_leaves")) + addBlockStaticColor(block, 0xC4FF4F, 0.5725490196); + else if (blockId.equals("jungle_leaves")) + addBlockFoliageColor(block, 0.72549019607); + else if (blockId.equals("mangrove_leaves")) + addBlockStaticColor(block, FoliageColors.getBirchColor(), 0.70980392156); + else if (blockId.equals("oak_leaves")) + addBlockFoliageColor(block, 0.73725490196); + else if (blockId.equals("spruce_leaves")) + addBlockStaticColor(block, FoliageColors.getSpruceColor(), 0.60392156862); + else if (blockId.equals("vine")) + addBlockFoliageColor(block, 0.66666666666); + else if (blockId.equals("short_grass")) + addBlockGrassColor(block, 0.72156862745); + else if (blockId.equals("tall_grass")) + addBlockGrassColor(block, 0.67450980392); + else if (blockId.equals("fern")) + addBlockGrassColor(block, 0.64705882352); + else if (blockId.equals("large_fern")) + addBlockGrassColor(block, 0.67450980392); + } + } + + private static void initializeColorProvides() { + Block[] staticColorBlocks = new Block[blockStaticColorsList.size()]; + blockStaticColorsList.toArray(staticColorBlocks); + + Block[] foliageColorBlocks = new Block[blockFoliageColorsList.size()]; + blockFoliageColorsList.toArray(foliageColorBlocks); + + Block[] grassColorBlocks = new Block[blockGrassColorsList.size()]; + blockGrassColorsList.toArray(grassColorBlocks); + + ColorProviderRegistry.BLOCK.register(ColorProvider::getBlockSnowLayeredStaticColor, + staticColorBlocks + ); + ColorProviderRegistry.BLOCK.register(ColorProvider::getBlockSnowLayeredFoliageColor, + foliageColorBlocks + ); + ColorProviderRegistry.BLOCK.register(ColorProvider::getBlockSnowLayeredGrassColor, + grassColorBlocks + ); + } + + private static int getBlockSnowLayeredStaticColor(BlockState state, BlockRenderView world, BlockPos position, int index) { + Block block = state.getBlock(); + int color = blockStaticColorsHashMap.get(block); + int snowLayer = state.get(SNOW_LAYER); + double leavesSnowLayerMask = (double) snowLayer / SNOW_LAYER.getValues().size(); + return getSnowLayeredColor(color, leavesSnowLayerMask); + } + + private static int getBlockSnowLayeredFoliageColor(BlockState state, BlockRenderView world, BlockPos position, int index) { + Block block = state.getBlock(); + int color = getMaskedColor(BiomeColors.getFoliageColor(world, position), blockColorMasksHashMap.get(block)); + int snowLayer = state.get(SNOW_LAYER); + double leavesSnowLayerMask = (double) snowLayer / SNOW_LAYER.getValues().size(); + return getSnowLayeredColor(color, leavesSnowLayerMask); + } + + private static int getBlockSnowLayeredGrassColor(BlockState state, BlockRenderView world, BlockPos position, int index) { + Block block = state.getBlock(); + int color = getMaskedColor(BiomeColors.getGrassColor(world, position), blockColorMasksHashMap.get(block)); + int snowLayer = state.get(SNOW_LAYER); + double leavesSnowLayerMask = (double) snowLayer / SNOW_LAYER.getValues().size(); + return getSnowLayeredColor(color, leavesSnowLayerMask); + } + + private static void addBlockStaticColor(Block block, int color, double mask) { + blockStaticColorsList.add(block); + blockStaticColorsHashMap.put(block, getMaskedColor(color, mask)); + } + + private static void addBlockFoliageColor(Block block, double mask) { + blockFoliageColorsList.add(block); + blockColorMasksHashMap.put(block, mask); + } + + private static void addBlockGrassColor(Block block, double mask) { + blockGrassColorsList.add(block); + blockColorMasksHashMap.put(block, mask); + } + + private static int getMaskedColor(int color, double mask) { + int r = (int) Math.round((color >> 16 & 0xff) * mask); + int g = (int) Math.round((color >> 8 & 0xff) * mask); + int b = (int) Math.round((color & 0xff) * mask); + return r << 16 | g << 8 | b; + } + private static int getSnowLayeredColor(int color, double mask) { + int r = (color >> 16 & 0xff); + int g = (color >> 8 & 0xff); + int b = (color & 0xff); + r += (int) Math.round((0xff - r) * mask); + g += (int) Math.round((0xff - g) * mask); + b += (int) Math.round((0xff - b) * mask); + return r << 16 | g << 8 | b; + } +} diff --git a/src/main/java/com/ishikyoo/leavesly/Leavesly.java b/src/main/java/com/ishikyoo/leavesly/Leavesly.java index 62488d9..312ef9a 100644 --- a/src/main/java/com/ishikyoo/leavesly/Leavesly.java +++ b/src/main/java/com/ishikyoo/leavesly/Leavesly.java @@ -1,11 +1,13 @@ package com.ishikyoo.leavesly; +import com.ishikyoo.leavesly.support.Support; import net.fabricmc.api.ModInitializer; import net.minecraft.block.Block; import net.minecraft.block.BlockState; import net.minecraft.block.Blocks; import net.minecraft.server.world.ServerWorld; +import net.minecraft.state.property.Properties; import net.minecraft.util.math.BlockPos; import net.minecraft.util.math.random.Random; import net.minecraft.world.LightType; @@ -15,129 +17,14 @@ import net.minecraft.state.property.IntProperty; +import java.net.Inet4Address; + public class Leavesly implements ModInitializer { public static final String MOD_ID = "leavesly"; public static final Logger LOGGER = LoggerFactory.getLogger(MOD_ID); - private static Leavesly instance; - - static final int SKYLIGHT_MAX = 15; - static final int SKYLIGHT_CUTOFF = 9; - static final int SKYLIGHT_RANGE = SKYLIGHT_MAX - SKYLIGHT_CUTOFF; - static final int SNOW_MAX_VALUE = 8 * SKYLIGHT_RANGE - 1; - static final int SNOW_VALUE_TO_CHANGE = (SNOW_MAX_VALUE + 1) / 2; - static final double NEIGHBOURS_INFLUENCE = 0.875; - static final double MAIN_INFLUENCE = Math.abs(NEIGHBOURS_INFLUENCE - 1); - static final int NEIGHBOURS_INFLUENCE_RANGE = 1; - public static final IntProperty SNOW = IntProperty.of("snow", 0, SNOW_MAX_VALUE); - - public static Leavesly getInstance() { return instance; } - - boolean isLeavesBlock(Block block) { - if (block == Blocks.ACACIA_LEAVES) - return true; - else if (block == Blocks.AZALEA_LEAVES) - return true; - else if (block == Blocks.BIRCH_LEAVES) - return true; - else if (block == Blocks.CHERRY_LEAVES) - return true; - else if (block == Blocks.DARK_OAK_LEAVES) - return true; - else if (block == Blocks.FLOWERING_AZALEA_LEAVES) - return true; - else if (block == Blocks.JUNGLE_LEAVES) - return true; - else if (block == Blocks.MANGROVE_LEAVES) - return true; - else if (block == Blocks.OAK_LEAVES) - return true; - else if (block == Blocks.SPRUCE_LEAVES) - return true; - return false; - } - boolean isVineBlock(Block block) { - return block == Blocks.VINE; - } - boolean isPlantBlock(Block block) { - if (block == Blocks.SHORT_GRASS) - return true; - else if (block == Blocks.FERN) - return true; - else if (block == Blocks.TALL_GRASS) - return true; - else if (block == Blocks.LARGE_FERN) - return true; - return false; - } - boolean isValidBlock(Block block) { - return isLeavesBlock(block) | isVineBlock(block) | isPlantBlock(block); - } - - double getNeighboursInfluence(ServerWorld world, BlockPos pos, int range) { - int value = 0; - int blockCount = 0; - for (int x = pos.getX() - range; x <= pos.getX() + range; x++) { - for (int y = pos.getY() - range; y <= pos.getY() + range; y++) { - for (int z = pos.getZ() - range; z <= pos.getZ() + range; z++) { - BlockPos rangePos = new BlockPos(x, y, z); - if (!rangePos.equals(pos)) { - BlockState rangeState = world.getBlockState(rangePos); - Block rangeBlock = rangeState.getBlock(); - if (isValidBlock(rangeBlock)) { - value += rangeState.get(SNOW); - blockCount++; - } - } - } - } - } - return ((double) value / blockCount) / SNOW_MAX_VALUE; - } - @Override public void onInitialize() { - instance = this; - } - - public void tick(BlockState state, ServerWorld world, BlockPos pos, Random random) { - if (isValidBlock(state.getBlock())) { - if (world.getBiome(pos).value().getPrecipitation(pos) == Biome.Precipitation.SNOW) { - int skyLight = world.getLightLevel(LightType.SKY, pos); - - if (skyLight > SKYLIGHT_CUTOFF) { - int blockSnow = state.get(SNOW); - double skyLightN = (double) (skyLight - SKYLIGHT_CUTOFF) / (SKYLIGHT_MAX - SKYLIGHT_CUTOFF); - double neighboursInfluenceN = getNeighboursInfluence(world, pos, NEIGHBOURS_INFLUENCE_RANGE); - double maxSnowPerSkyLight = skyLightN * SNOW_MAX_VALUE; - double mainInfluenceN = skyLightN * MAIN_INFLUENCE; - double mainInfluenceValue = mainInfluenceN * SNOW_VALUE_TO_CHANGE; - - if (world.isRaining()) { - double neighboursInfluenceAddN = (neighboursInfluenceN * skyLightN) * NEIGHBOURS_INFLUENCE; - double neighboursInfluenceValueAdd = neighboursInfluenceAddN * SNOW_VALUE_TO_CHANGE; - - int valueToAdd = (int) Math.floor(mainInfluenceValue + neighboursInfluenceValueAdd); - if (valueToAdd == 0) valueToAdd = 1; - - if (blockSnow < maxSnowPerSkyLight && blockSnow <= SNOW_MAX_VALUE - valueToAdd) - world.setBlockState(pos, state.with(Leavesly.SNOW, blockSnow + valueToAdd)); - else - world.setBlockState(pos, state.with(Leavesly.SNOW, (int) maxSnowPerSkyLight)); - } else { - double neighboursInfluenceSubN = (Math.abs(neighboursInfluenceN - 1) * skyLightN) * NEIGHBOURS_INFLUENCE; - double neighboursInfluenceValueSub = neighboursInfluenceSubN * SNOW_VALUE_TO_CHANGE; - - int valueToSub = (int) Math.floor(mainInfluenceValue + neighboursInfluenceValueSub); - if (valueToSub == 0) valueToSub = 1; - if (blockSnow > 0 && blockSnow >= valueToSub) { - world.setBlockState(pos, state.with(Leavesly.SNOW, blockSnow - valueToSub)); - } else - world.setBlockState(pos, state.with(Leavesly.SNOW, 0)); - } - } - } - } } } \ No newline at end of file diff --git a/src/main/java/com/ishikyoo/leavesly/LeaveslyClient.java b/src/main/java/com/ishikyoo/leavesly/LeaveslyClient.java index c80216e..05742b9 100644 --- a/src/main/java/com/ishikyoo/leavesly/LeaveslyClient.java +++ b/src/main/java/com/ishikyoo/leavesly/LeaveslyClient.java @@ -1,8 +1,11 @@ package com.ishikyoo.leavesly; +import com.ishikyoo.leavesly.property.Properties; +import com.ishikyoo.leavesly.support.Support; import net.fabricmc.api.ClientModInitializer; import net.fabricmc.fabric.api.client.rendering.v1.ColorProviderRegistry; +import net.fabricmc.loader.api.FabricLoader; import net.minecraft.block.Block; import net.minecraft.block.BlockState; import net.minecraft.block.Blocks; @@ -13,120 +16,15 @@ import org.slf4j.Logger; import org.slf4j.LoggerFactory; -public class LeaveslyClient implements ClientModInitializer { +import java.util.ArrayList; +import java.util.List; +public class LeaveslyClient implements ClientModInitializer { public static final Logger LOGGER = LoggerFactory.getLogger(Leavesly.MOD_ID); - private static LeaveslyClient instance; - - public static LeaveslyClient getInstance(){ return instance; } - - static final double SPRUCE_LEAVES_MASK = 0.60392156862; - static final double BIRCH_LEAVES_MASK = 0.72549019607; - static final double MANGROVE_LEAVES_MASK = 0.70980392156; - static final double ACACIA_LEAVES_MASK = 0.70980392156; - static final double DARK_OAK_LEAVES_MASK = 0.72549019607; - static final double JUNGLE_LEAVES_MASK = 0.72549019607; - static final double OAK_LEAVES_MASK = 0.73725490196; - static final double AZALEA_LEAVES_MASK = 0.5725490196; - static final double FLOWERING_AZALEA_LEAVES_MASK = 0.5725490196; - static final double CHERRY_LEAVES_MASK = 0.6; - static final double VINE_MASK = 0.66666666666; - static final double SHORT_GRASS_MASK = 0.72156862745; - static final double FERN_MASK = 0.64705882352; - static final double TALL_GRASS_MASK = 0.67450980392; - static final double LARGE_FERN_MASK = 0.67450980392; - - static final int SPRUCE_LEAVES_COLOR = FoliageColors.getSpruceColor(); - static final int BIRTH_LEAVES_COLOR = FoliageColors.getBirchColor(); - static final int MANGROVE_LEAVES_COLOR = FoliageColors.getMangroveColor(); - static final int AZALEA_LEAVES_COLOR = 0xC4FF4F; - static final int FLOWERING_AZALEA_LEAVES_COLOR = 0xC4FF4F; - static final int CHERRY_LEAVES_COLOR = 0xDEFF4C; - - private int getColorProviderValue(BlockState state, BlockRenderView world, BlockPos position, int index) { - if (state != null && world != null && position != null) { - Block block = state.getBlock(); - int color = getFoliageColor(block, world, position); - int snow = state.get(Leavesly.SNOW); - double leavesSnowMask = (double) snow / Leavesly.SNOW.getValues().size(); - return setFoliageWhiteMask(color, leavesSnowMask); - } - return 0; - } - - private int getFoliageColor(Block block, BlockRenderView world, BlockPos position) { - if (block == Blocks.SPRUCE_LEAVES) { - return getMaskedColor(SPRUCE_LEAVES_COLOR, SPRUCE_LEAVES_MASK); - } else if (block == Blocks.BIRCH_LEAVES) { - return getMaskedColor(BIRTH_LEAVES_COLOR, BIRCH_LEAVES_MASK); - } else if (block == Blocks.MANGROVE_LEAVES) { - return getMaskedColor(MANGROVE_LEAVES_COLOR, MANGROVE_LEAVES_MASK); - } else if (block == Blocks.AZALEA_LEAVES) { - return getMaskedColor(AZALEA_LEAVES_COLOR, AZALEA_LEAVES_MASK); - } else if (block == Blocks.FLOWERING_AZALEA_LEAVES) { - return getMaskedColor(FLOWERING_AZALEA_LEAVES_COLOR, FLOWERING_AZALEA_LEAVES_MASK); - } else if (block == Blocks.ACACIA_LEAVES) { - return getMaskedColor(BiomeColors.getFoliageColor(world, position), ACACIA_LEAVES_MASK); - } else if (block == Blocks.CHERRY_LEAVES) { - return getMaskedColor(CHERRY_LEAVES_COLOR, CHERRY_LEAVES_MASK); - } else if (block == Blocks.DARK_OAK_LEAVES) { - return getMaskedColor(BiomeColors.getFoliageColor(world, position), DARK_OAK_LEAVES_MASK); - } else if (block == Blocks.JUNGLE_LEAVES) { - return getMaskedColor(BiomeColors.getFoliageColor(world, position), JUNGLE_LEAVES_MASK); - } else if (block == Blocks.OAK_LEAVES) { - return getMaskedColor(BiomeColors.getFoliageColor(world, position), OAK_LEAVES_MASK); - } else if (block == Blocks.VINE) { - return getMaskedColor(BiomeColors.getFoliageColor(world, position), VINE_MASK); - } else if (block == Blocks.SHORT_GRASS) { - return getMaskedColor(BiomeColors.getGrassColor(world, position), SHORT_GRASS_MASK); - } else if (block == Blocks.FERN) { - return getMaskedColor(BiomeColors.getGrassColor(world, position), FERN_MASK); - } else if (block == Blocks.TALL_GRASS) { - return getMaskedColor(BiomeColors.getGrassColor(world, position), TALL_GRASS_MASK); - } else if (block == Blocks.LARGE_FERN) { - return getMaskedColor(BiomeColors.getGrassColor(world, position), LARGE_FERN_MASK); - } - return 0; - } - - private int getMaskedColor(int color, double mask) { - int r = (int) Math.round((color >> 16 & 0xff) * mask); - int g = (int) Math.round((color >> 8 & 0xff) * mask); - int b = (int) Math.round((color & 0xff) * mask); - return r << 16 | g << 8 | b; - } - - private int setFoliageWhiteMask(int color, double mask) { - int r = (color >> 16 & 0xff); - int g = (color >> 8 & 0xff); - int b = (color & 0xff); - r += (int) Math.round((0xff - r) * mask); - g += (int) Math.round((0xff - g) * mask); - b += (int) Math.round((0xff - b) * mask); - return r << 16 | g << 8 | b; - } - @Override public void onInitializeClient() { - ColorProviderRegistry.BLOCK.register(this::getColorProviderValue, - Blocks.SPRUCE_LEAVES, - Blocks.BIRCH_LEAVES, - Blocks.MANGROVE_LEAVES, - Blocks.ACACIA_LEAVES, - Blocks.DARK_OAK_LEAVES, - Blocks.JUNGLE_LEAVES, - Blocks.OAK_LEAVES, - Blocks.AZALEA_LEAVES, - Blocks.FLOWERING_AZALEA_LEAVES, - Blocks.CHERRY_LEAVES, - Blocks.VINE, - Blocks.SHORT_GRASS, - Blocks.FERN, - Blocks.TALL_GRASS, - Blocks.LARGE_FERN - ); - instance = this; + ColorProvider.initialize(); } } diff --git a/src/main/java/com/ishikyoo/leavesly/logic/SnowLayerLogic.java b/src/main/java/com/ishikyoo/leavesly/logic/SnowLayerLogic.java new file mode 100644 index 0000000..423c560 --- /dev/null +++ b/src/main/java/com/ishikyoo/leavesly/logic/SnowLayerLogic.java @@ -0,0 +1,101 @@ +package com.ishikyoo.leavesly.logic; + +import com.ishikyoo.leavesly.Leavesly; +import com.ishikyoo.leavesly.support.Support; +import net.minecraft.block.Block; +import net.minecraft.block.BlockState; +import net.minecraft.server.world.ServerWorld; +import net.minecraft.state.StateManager; +import net.minecraft.state.property.IntProperty; +import net.minecraft.util.math.BlockPos; +import net.minecraft.util.math.random.Random; +import com.ishikyoo.leavesly.property.Properties; +import net.minecraft.world.LightType; +import net.minecraft.world.biome.Biome; + +public class SnowLayerLogic { + protected static IntProperty SNOW_LAYER = Properties.SNOW_LAYER; + protected static int SNOW_LAYER_MAX_VALUE = Properties.SNOW_LAYER.getValues().size() - 1; + protected static int SKYLIGHT_MAX_VALUE = 15; + protected static int SKYLIGHT_CUTOFF_VALUE = 9; + protected static int SKYLIGHT_RANGE = SKYLIGHT_MAX_VALUE - SKYLIGHT_CUTOFF_VALUE; + protected static int SNOW_LAYER_VALUE_TO_CHANGE = (SNOW_LAYER_MAX_VALUE + 1) / 2; + protected static double NEIGHBOURS_INFLUENCE = 0.875; + protected static double MAIN_INFLUENCE = Math.abs(NEIGHBOURS_INFLUENCE - 1); + protected static int NEIGHBOURS_INFLUENCE_RANGE = 1; + + public static boolean hasRandomTick(BlockState state) { + return Support.isSupportedBlock(state.getBlock()); + } + + public static void randomTick(BlockState state, ServerWorld world, BlockPos pos, Random random) { + if (world.getBiome(pos).value().getPrecipitation(pos) == Biome.Precipitation.SNOW) { + int skyLight = world.getLightLevel(LightType.SKY, pos); + + if (skyLight > SKYLIGHT_CUTOFF_VALUE) { + int blockSnow = state.get(SNOW_LAYER); + double skyLightN = (double) (skyLight - SKYLIGHT_CUTOFF_VALUE) / (SKYLIGHT_MAX_VALUE - SKYLIGHT_CUTOFF_VALUE); + double neighboursInfluenceN = getNeighboursInfluence(world, pos, NEIGHBOURS_INFLUENCE_RANGE); + double maxSnowPerSkyLight = skyLightN * SNOW_LAYER_MAX_VALUE; + double mainInfluenceN = skyLightN * MAIN_INFLUENCE; + double mainInfluenceValue = mainInfluenceN * SNOW_LAYER_VALUE_TO_CHANGE; + + if (world.isRaining()) { + double neighboursInfluenceAddN = (neighboursInfluenceN * skyLightN) * NEIGHBOURS_INFLUENCE; + double neighboursInfluenceValueAdd = neighboursInfluenceAddN * SNOW_LAYER_VALUE_TO_CHANGE; + + int valueToAdd = (int) Math.floor(mainInfluenceValue + neighboursInfluenceValueAdd); + if (valueToAdd == 0) valueToAdd = 1; + + if (blockSnow < maxSnowPerSkyLight && blockSnow <= SNOW_LAYER_MAX_VALUE - valueToAdd) + world.setBlockState(pos, state.with(SNOW_LAYER, blockSnow + valueToAdd)); + else + world.setBlockState(pos, state.with(SNOW_LAYER, (int) maxSnowPerSkyLight)); + } else { + double neighboursInfluenceSubN = (Math.abs(neighboursInfluenceN - 1) * skyLightN) * NEIGHBOURS_INFLUENCE; + double neighboursInfluenceValueSub = neighboursInfluenceSubN * SNOW_LAYER_VALUE_TO_CHANGE; + + int valueToSub = (int) Math.floor(mainInfluenceValue + neighboursInfluenceValueSub); + if (valueToSub == 0) valueToSub = 1; + + if (blockSnow > 0 && blockSnow >= valueToSub) { + world.setBlockState(pos, state.with(SNOW_LAYER, blockSnow - valueToSub)); + } else + world.setBlockState(pos, state.with(SNOW_LAYER, 0)); + } + } + } + } + + public static void setDefaultState(Block block, StateManager stateManager) { + if (!Support.isSupportedBlockClass(block)) return; + stateManager.getDefaultState().with(SNOW_LAYER, 0); + } + + public static void appendProperties(Block block, StateManager.Builder builder) { + if (Support.isSupportedBlockClass(block)) + builder.add(SNOW_LAYER); + } + + + protected static double getNeighboursInfluence(ServerWorld world, BlockPos pos, int range) { + int value = 0; + int blockCount = 0; + for (int x = pos.getX() - range; x <= pos.getX() + range; x++) { + for (int y = pos.getY() - range; y <= pos.getY() + range; y++) { + for (int z = pos.getZ() - range; z <= pos.getZ() + range; z++) { + BlockPos rangePos = new BlockPos(x, y, z); + if (!rangePos.equals(pos)) { + BlockState rangeState = world.getBlockState(rangePos); + Block rangeBlock = rangeState.getBlock(); + if (Support.isSupportedBlock(rangeBlock)) { + value += rangeState.get(SNOW_LAYER); + blockCount++; + } + } + } + } + } + return ((double) value / blockCount) / SNOW_LAYER_MAX_VALUE; + } +} diff --git a/src/main/java/com/ishikyoo/leavesly/mixin/BlocksMixin.java b/src/main/java/com/ishikyoo/leavesly/mixin/BlocksMixin.java new file mode 100644 index 0000000..00504de --- /dev/null +++ b/src/main/java/com/ishikyoo/leavesly/mixin/BlocksMixin.java @@ -0,0 +1,17 @@ +package com.ishikyoo.leavesly.mixin; + +import com.ishikyoo.leavesly.support.Support; +import net.minecraft.block.Block; +import net.minecraft.block.Blocks; +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(Blocks.class) +public class BlocksMixin { + @Inject(at = @At("RETURN"), method = "register", cancellable = true) + private static void injectRegisterReturn(String id, Block block, CallbackInfoReturnable cir) { + Support.checkSupportedBlock(id, cir.getReturnValue()); + } +} diff --git a/src/main/java/com/ishikyoo/leavesly/mixin/CherryLeavesBlockMixin.java b/src/main/java/com/ishikyoo/leavesly/mixin/CherryLeavesBlockMixin.java deleted file mode 100644 index db1d015..0000000 --- a/src/main/java/com/ishikyoo/leavesly/mixin/CherryLeavesBlockMixin.java +++ /dev/null @@ -1,22 +0,0 @@ -package com.ishikyoo.leavesly.mixin; - -import com.ishikyoo.leavesly.Leavesly; -import net.minecraft.block.*; -import net.minecraft.server.world.ServerWorld; -import net.minecraft.state.StateManager; -import net.minecraft.util.math.BlockPos; -import net.minecraft.util.math.random.Random; -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.CallbackInfo; -import org.spongepowered.asm.mixin.injection.callback.CallbackInfoReturnable; - -@Mixin(CherryLeavesBlock.class) -public abstract class CherryLeavesBlockMixin extends LeavesBlockMixin { - public CherryLeavesBlockMixin(Settings settings) { - super(settings); - //Set default states here - //setDefaultState(this.stateManager.getDefaultState().with(EXAMPLE, EXAMPLE)); - } -} diff --git a/src/main/java/com/ishikyoo/leavesly/mixin/LeavesBlockMixin.java b/src/main/java/com/ishikyoo/leavesly/mixin/LeavesBlockMixin.java index 6300631..c6afc60 100644 --- a/src/main/java/com/ishikyoo/leavesly/mixin/LeavesBlockMixin.java +++ b/src/main/java/com/ishikyoo/leavesly/mixin/LeavesBlockMixin.java @@ -1,6 +1,8 @@ package com.ishikyoo.leavesly.mixin; import com.ishikyoo.leavesly.Leavesly; +import com.ishikyoo.leavesly.logic.SnowLayerLogic; +import com.ishikyoo.leavesly.support.Support; import net.minecraft.block.*; import net.minecraft.server.world.ServerWorld; import net.minecraft.state.StateManager; @@ -16,61 +18,25 @@ public abstract class LeavesBlockMixin extends Block { public LeavesBlockMixin(Settings settings) { super(settings); - if (!isSupportedLeavesBlock()) return; - //Set default states here - setDefaultState(this.stateManager.getDefaultState().with(Leavesly.SNOW, 0)); + } + + @Inject(at = @At("TAIL"), method = "") + private void initInject(AbstractBlock.Settings settings, CallbackInfo ci) { + SnowLayerLogic.setDefaultState(this, this.stateManager); } @Inject(at = @At("TAIL"), method = "appendProperties") protected void injectAppendProperties(StateManager.Builder builder, CallbackInfo ci) { - if (isSupportedLeavesBlock()) - onAppendProperties(builder); - else if (!isKnownLeavesBlock()) - Leavesly.LOGGER.warn("Mixin: Unknown LeavesBlock.class ({}) detected!", this.getClass().getName()); + SnowLayerLogic.appendProperties(this, builder); } @Inject(at = @At("RETURN"), method = "hasRandomTicks", cancellable = true) private void injectHasRandomTicks(BlockState state, CallbackInfoReturnable cir) { - if (isSupportedLeavesBlock()) - cir.setReturnValue(cir.getReturnValue() | onHasRandomTick(state)); + cir.setReturnValue(cir.getReturnValue() | SnowLayerLogic.hasRandomTick(state)); } @Inject(at = @At("HEAD"), method = "randomTick") protected void injectRandomTick(BlockState state, ServerWorld world, BlockPos pos, Random random, CallbackInfo ci) { - if (isSupportedLeavesBlock()) - onRandomTick(state, world, pos, random); - } - - protected boolean onHasRandomTick(BlockState state) { - return isSupportedLeavesBlock(); - } - - protected void onRandomTick(BlockState state, ServerWorld world, BlockPos pos, Random random) { - Leavesly.getInstance().tick(state, world, pos, random); - } - - protected void onAppendProperties(StateManager.Builder builder) { - builder.add(Leavesly.SNOW); - } - - - private boolean isSupportedLeavesBlock() { - return isKnownLeavesBlock(); - } - - private boolean isKnownLeavesBlock() { - return isGenericLeavesBlock() | isCherryLeavesBlock() | isMangroveLeavesBlock(); - } - - private boolean isGenericLeavesBlock() { - return this.getClass().equals(LeavesBlock.class); - } - - private boolean isCherryLeavesBlock() { - return this.getClass().equals(CherryLeavesBlock.class); - } - - private boolean isMangroveLeavesBlock() { - return this.getClass().equals(MangroveLeavesBlock.class); + SnowLayerLogic.randomTick(state, world, pos, random); } -} +} \ No newline at end of file diff --git a/src/main/java/com/ishikyoo/leavesly/mixin/MangroveLeavesBlockMixin.java b/src/main/java/com/ishikyoo/leavesly/mixin/MangroveLeavesBlockMixin.java deleted file mode 100644 index a9b4ecc..0000000 --- a/src/main/java/com/ishikyoo/leavesly/mixin/MangroveLeavesBlockMixin.java +++ /dev/null @@ -1,22 +0,0 @@ -package com.ishikyoo.leavesly.mixin; - -import com.ishikyoo.leavesly.Leavesly; -import net.minecraft.block.*; -import net.minecraft.server.world.ServerWorld; -import net.minecraft.state.StateManager; -import net.minecraft.util.math.BlockPos; -import net.minecraft.util.math.random.Random; -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.CallbackInfo; -import org.spongepowered.asm.mixin.injection.callback.CallbackInfoReturnable; - -@Mixin(MangroveLeavesBlock.class) -public abstract class MangroveLeavesBlockMixin extends LeavesBlockMixin { - public MangroveLeavesBlockMixin(Settings settings) { - super(settings); - //Set default states here - //setDefaultState(this.stateManager.getDefaultState().with(EXAMPLE, EXAMPLE)); - } -} diff --git a/src/main/java/com/ishikyoo/leavesly/mixin/PlantBlockMixin.java b/src/main/java/com/ishikyoo/leavesly/mixin/PlantBlockMixin.java index a512f9e..eed1653 100644 --- a/src/main/java/com/ishikyoo/leavesly/mixin/PlantBlockMixin.java +++ b/src/main/java/com/ishikyoo/leavesly/mixin/PlantBlockMixin.java @@ -1,126 +1,39 @@ package com.ishikyoo.leavesly.mixin; -import com.ishikyoo.leavesly.Leavesly; +import com.ishikyoo.leavesly.logic.SnowLayerLogic; import net.minecraft.block.*; import net.minecraft.server.world.ServerWorld; import net.minecraft.state.StateManager; import net.minecraft.util.math.BlockPos; import net.minecraft.util.math.random.Random; 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.CallbackInfo; @Mixin(PlantBlock.class) public abstract class PlantBlockMixin extends Block { - public PlantBlockMixin(Settings settings) { super(settings); - if (!isSupportedPlantBlock()) return; - //Set default states here - setDefaultState(getDefaultState().with(Leavesly.SNOW, 0)); + } + + @Inject(at = @At("TAIL"), method = "") + private void initInject(AbstractBlock.Settings settings, CallbackInfo ci) { + SnowLayerLogic.setDefaultState(this, this.stateManager); } @Override protected void appendProperties(StateManager.Builder builder) { - if (isSupportedPlantBlock()) - onAppendProperties(builder); - else if (!isKnownPlantBlock()) - Leavesly.LOGGER.warn("Mixin: Unknown PlantBlock.class ({}) detected!", this.getClass().getName()); + SnowLayerLogic.appendProperties(this, builder); } @Override protected boolean hasRandomTicks(BlockState state) { - return onHasRandomTick(state); + return SnowLayerLogic.hasRandomTick(state); } @Override protected void randomTick(BlockState state, ServerWorld world, BlockPos pos, Random random) { - if (isSupportedPlantBlock()) - onRandomTick(state, world, pos, random); - } - - protected void onAppendProperties(StateManager.Builder builder) { - builder.add(Leavesly.SNOW); - } - - protected boolean onHasRandomTick(BlockState state) { - return isSupportedPlantBlock(); - } - - protected void onRandomTick(BlockState state, ServerWorld world, BlockPos pos, Random random) { - Leavesly.getInstance().tick(state, world, pos, random); - } - - - private boolean isKnownPlantBlock() { - return isGenericPlantBlock() | isShortPlantBlock() | isSeagrassBlock() | isFlowerBlock() | - isWitherRoseBlock() | isMushroomPlantBlock() |isLilyPadBlock() | isFungusBlock() | - isRootsBlock() | isSproutsBlock() | isDeadBushBlock() | isAzaleaBlock() | - isTallPlantBlock() | isTallSeagrassBlock() | isTallFlowerBlock() | isPitcherCropBlock(); - } - - private boolean isSupportedPlantBlock() { - return isGenericPlantBlock() | isShortPlantBlock() | isTallPlantBlock(); - } - - private boolean isGenericPlantBlock() { - return this.getClass().equals(PlantBlock.class); - } - - private boolean isShortPlantBlock() { - return this.getClass().equals(ShortPlantBlock.class); - } - - private boolean isSeagrassBlock() { - return this.getClass().equals(SeagrassBlock.class); - } - - private boolean isFlowerBlock() { - return this.getClass().equals(FlowerBlock.class); - } - - private boolean isWitherRoseBlock() { - return this.getClass().equals(WitherRoseBlock.class); - } - - private boolean isMushroomPlantBlock() { - return this.getClass().equals(MushroomPlantBlock.class); - } - - private boolean isLilyPadBlock() { - return this.getClass().equals(LilyPadBlock.class); - } - - private boolean isFungusBlock() { - return this.getClass().equals(FungusBlock.class); - } - - private boolean isRootsBlock() { - return this.getClass().equals(RootsBlock.class); - } - - private boolean isSproutsBlock() { - return this.getClass().equals(SproutsBlock.class); - } - - private boolean isDeadBushBlock() { - return this.getClass().equals(DeadBushBlock.class); - } - - private boolean isAzaleaBlock() { - return this.getClass().equals(AzaleaBlock.class); - } - - private boolean isTallPlantBlock() { - return this.getClass().equals(TallPlantBlock.class); - } - - private boolean isTallSeagrassBlock() { - return this.getClass().equals(TallSeagrassBlock.class); - } - - private boolean isTallFlowerBlock() { - return this.getClass().equals(TallFlowerBlock.class); - } - private boolean isPitcherCropBlock() { - return this.getClass().equals(PitcherCropBlock.class); + SnowLayerLogic.randomTick(state, world, pos, random); } } diff --git a/src/main/java/com/ishikyoo/leavesly/mixin/ShortPlantBlockMixin.java b/src/main/java/com/ishikyoo/leavesly/mixin/ShortPlantBlockMixin.java deleted file mode 100644 index c38961e..0000000 --- a/src/main/java/com/ishikyoo/leavesly/mixin/ShortPlantBlockMixin.java +++ /dev/null @@ -1,12 +0,0 @@ -package com.ishikyoo.leavesly.mixin; - -import net.minecraft.block.ShortPlantBlock; -import org.spongepowered.asm.mixin.Mixin; - -@Mixin(ShortPlantBlock.class) -public abstract class ShortPlantBlockMixin extends PlantBlockMixin { - public ShortPlantBlockMixin(Settings settings) { - super(settings); - //Set default states here - } -} diff --git a/src/main/java/com/ishikyoo/leavesly/mixin/VineBlockMixin.java b/src/main/java/com/ishikyoo/leavesly/mixin/VineBlockMixin.java index ca3e1f1..6633926 100644 --- a/src/main/java/com/ishikyoo/leavesly/mixin/VineBlockMixin.java +++ b/src/main/java/com/ishikyoo/leavesly/mixin/VineBlockMixin.java @@ -1,6 +1,8 @@ package com.ishikyoo.leavesly.mixin; import com.ishikyoo.leavesly.Leavesly; +import com.ishikyoo.leavesly.logic.SnowLayerLogic; +import com.ishikyoo.leavesly.support.Support; import net.minecraft.block.AbstractBlock; import net.minecraft.block.Block; import net.minecraft.block.BlockState; @@ -16,54 +18,27 @@ @Mixin(VineBlock.class) public abstract class VineBlockMixin extends Block { - public VineBlockMixin(Settings settings) { super(settings); - if (!isSupportedVineBlock()) return; - //Set default states here - setDefaultState(this.stateManager.getDefaultState().with(Leavesly.SNOW, 0)); + } + + @Inject(at = @At("TAIL"), method = "") + private void initInject(AbstractBlock.Settings settings, CallbackInfo ci) { + SnowLayerLogic.setDefaultState(this, this.stateManager); } @Inject(at = @At("TAIL"), method = "appendProperties") protected void appendProperties(StateManager.Builder builder, CallbackInfo ci) { - if (isSupportedVineBlock()) - onAppendProperties(builder); - else if (!isKnownVineBlock()) - Leavesly.LOGGER.warn("Mixin: Unknown VineBlock.class ({}) detected!", this.getClass().getName()); + SnowLayerLogic.appendProperties(this, builder); } @Override protected boolean hasRandomTicks(BlockState state) { - return onHasRandomTick(state); + return SnowLayerLogic.hasRandomTick(state); } @Inject(at = @At("HEAD"), method = "randomTick") protected void randomTick(BlockState state, ServerWorld world, BlockPos pos, Random random, CallbackInfo ci) { - if (isSupportedVineBlock()) - onRandomTick(state, world, pos, random); - } - - protected void onAppendProperties(StateManager.Builder builder) { - builder.add(Leavesly.SNOW); - } - - protected boolean onHasRandomTick(BlockState state) { - return isSupportedVineBlock(); - } - - protected void onRandomTick(BlockState state, ServerWorld world, BlockPos pos, Random random) { - Leavesly.getInstance().tick(state, world, pos, random); - } - - private boolean isKnownVineBlock() { - return isVineBlock(); - } - - private boolean isSupportedVineBlock() { - return isVineBlock(); - } - - private boolean isVineBlock() { - return this.getClass().equals(VineBlock.class); + SnowLayerLogic.randomTick(state, world, pos, random); } } diff --git a/src/main/java/com/ishikyoo/leavesly/property/Properties.java b/src/main/java/com/ishikyoo/leavesly/property/Properties.java new file mode 100644 index 0000000..dce5537 --- /dev/null +++ b/src/main/java/com/ishikyoo/leavesly/property/Properties.java @@ -0,0 +1,7 @@ +package com.ishikyoo.leavesly.property; + +import net.minecraft.state.property.IntProperty; + +public class Properties { + public static IntProperty SNOW_LAYER = IntProperty.of("snow_layer", 0, 47); +} diff --git a/src/main/java/com/ishikyoo/leavesly/support/Support.java b/src/main/java/com/ishikyoo/leavesly/support/Support.java new file mode 100644 index 0000000..608dc73 --- /dev/null +++ b/src/main/java/com/ishikyoo/leavesly/support/Support.java @@ -0,0 +1,145 @@ +package com.ishikyoo.leavesly.support; + +import com.ishikyoo.leavesly.Leavesly; +import net.fabricmc.loader.api.FabricLoader; +import net.minecraft.block.*; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import java.util.Arrays; +import java.util.HashMap; +import java.util.HashSet; + +public class Support { + private static final Logger LOGGER = LoggerFactory.getLogger(Leavesly.MOD_ID); + private static final boolean IS_DEVELOPMENT_ENVIRONMENT = FabricLoader.getInstance().isDevelopmentEnvironment(); + public static boolean isToLog = true; + + private final static String[] knownBlockClassNameList = new String[]{ + "LeavesBlock", + "CherryLeavesBlock", + "MangroveLeavesBlock", + "VineBlock", + "PlantBlock", + "ShortPlantBlock", + "DeadBushBlock", + "SeagrassBlock", + "TallSeagrassBlock", + "FlowerBlock", + "WitherRoseBlock", + "MushroomPlantBlock", + "TallFlowerBlock", + "TallPlantBlock", + "PitcherCropBlock", + "FungusBlock", + "RootsBlock", + "SproutsBlock", + "AzaleaBlock", + "LilyPadBlock" + }; + private final static String[] knownObfuscatedBlockClassNameList = { + "class_2397", + "class_8167", + "class_7114", + "class_2541", + "class_2261", + "class_2526", + "class_2311", + "class_2476", + "class_2525", + "class_2356", + "class_2563", + "class_2420", + "class_2521", + "class_2320", + "class_8237", + "class_4771", + "class_4774", + "class_4772", + "class_5800", + "class_2553" + }; + private final static String[] supportedBlockClassNameList = { + "LeavesBlock", + "CherryLeavesBlock", + "MangroveLeavesBlock", + "VineBlock", + "PlantBlock", + "ShortPlantBlock", + "TallPlantBlock", + }; + private final static String[] supportedBlockIdsList = { + "acacia_leaves", + "azalea_leaves", + "birch_leaves", + "cherry_leaves", + "dark_oak_leaves", + "flowering_azalea_leaves", + "jungle_leaves", + "mangrove_leaves", + "oak_leaves", + "spruce_leaves", + "vine", + "short_grass", + "tall_grass", + "fern", + "large_fern", + }; + + private final static HashSet supportedBlockIdsHashSet = new HashSet<>(Arrays.stream(supportedBlockIdsList).toList()); + private final static HashSet supportedBlockClassNameHashSet = new HashSet<>(Arrays.stream(supportedBlockClassNameList).toList()); + + private final static HashSet supportedActiveBlocksHashSet = new HashSet<>(); + private final static HashMap supportedActiveBlocksHashMap = new HashMap<>(); + private final static HashMap supportedActiveBlockIdsHashMaps = new HashMap<>(); + + public static void checkSupportedBlock(String id, Block block) { + if (supportedBlockIdsHashSet.contains(id)) { + supportedActiveBlocksHashSet.add(block); + supportedActiveBlockIdsHashMaps.put(block, id); + supportedActiveBlocksHashMap.put(id, block); + if (isToLog) + LOGGER.info("Leavesly: Supported block (Identifier: {}, Class: {}) detected.", id, getBlockClassName(block)); + } + } + + public static Block getBlock(String id) { + return supportedActiveBlocksHashMap.get(id); + } + + public static String getBlockId(Block block) { + return supportedActiveBlockIdsHashMaps.get(block); + } + + private static String getBlockClassName(Block block) { + if (!IS_DEVELOPMENT_ENVIRONMENT) + return getDeobfuscatedClassName(block.getClass().getSimpleName()); + return block.getClass().getSimpleName(); + } + + private static String getDeobfuscatedClassName(String name) { + for (int i = 0; i < knownObfuscatedBlockClassNameList.length; i++) { + if (knownObfuscatedBlockClassNameList[i].equals(name)) + return knownBlockClassNameList[i]; + } + return name; + } + + public static Block[] getBlocks() { + Block[] blocks = new Block[supportedActiveBlocksHashSet.size()]; + supportedActiveBlocksHashSet.toArray(blocks); + return blocks; + } + + public static boolean isSupportedBlock(Block block) { + return isSupportedBlock(getBlockId(block)); + } + + public static boolean isSupportedBlock(String id) { + return supportedBlockIdsHashSet.contains(id); + } + + public static boolean isSupportedBlockClass(Block block) { + return supportedBlockClassNameHashSet.contains(getBlockClassName(block)); + } +} diff --git a/src/main/resources/fabric.mod.json b/src/main/resources/fabric.mod.json index 9aae62b..65dce45 100644 --- a/src/main/resources/fabric.mod.json +++ b/src/main/resources/fabric.mod.json @@ -40,7 +40,7 @@ "1.21", "1.21.1" ], - "fabric-api": "*" + "fabric": "*" }, "suggests": { "another-mod": "*" diff --git a/src/main/resources/leavesly.mixins.json b/src/main/resources/leavesly.mixins.json index 681e3dd..2e5ba32 100644 --- a/src/main/resources/leavesly.mixins.json +++ b/src/main/resources/leavesly.mixins.json @@ -3,11 +3,9 @@ "package": "com.ishikyoo.leavesly.mixin", "compatibilityLevel": "JAVA_17", "mixins": [ + "BlocksMixin", "LeavesBlockMixin", - "CherryLeavesBlockMixin", - "MangroveLeavesBlockMixin", "PlantBlockMixin", - "ShortPlantBlockMixin", "TallPlantBlockMixin", "VineBlockMixin" ], diff --git a/src/main/resources/quilt.mod.json b/src/main/resources/quilt.mod.json index 6230ecf..e775c0e 100644 --- a/src/main/resources/quilt.mod.json +++ b/src/main/resources/quilt.mod.json @@ -11,10 +11,10 @@ }, "depends": [ "fabricloader", - "fabric-api", + "fabric", { "id": "minecraft", - "versions": { "all": [">=1.19.4", "<1.21.1"] } + "versions": { "all": [">=1.19.4", "<=1.21.1"] } } ], "intermediate_mappings": "net.fabricmc:intermediary",