From c041dd90b9465ceb4a964ea7dace260cfa66114d Mon Sep 17 00:00:00 2001 From: Luke Bemish Date: Sun, 7 Jan 2024 20:56:38 -0600 Subject: [PATCH] Hopefully set up snowrealmagic compat --- common/build.gradle | 5 + .../dev/lukebemish/tempest/impl/Services.java | 97 ++++++++++++++++++- .../snowrealmagic/SnowRealMagicCompat.java | 69 +++++++++++++ .../impl/data/world/WeatherChunkData.java | 66 +++++++------ .../tempest/tags/blocks/snow_passthrough.json | 10 +- fabriquilt/build.gradle | 3 +- .../SnowRealMagicPlatformImpl.java | 27 ++++++ forge/build.gradle | 2 +- .../SnowRealMagicPlatformImpl.java | 27 ++++++ gradle/libs.versions.toml | 2 + 10 files changed, 274 insertions(+), 34 deletions(-) create mode 100644 common/src/main/java/dev/lukebemish/tempest/impl/compat/snowrealmagic/SnowRealMagicCompat.java create mode 100644 fabriquilt/src/main/java/dev/lukebemish/tempest/impl/fabriquilt/compat/snowrealmagic/SnowRealMagicPlatformImpl.java create mode 100644 forge/src/main/java/dev/lukebemish/tempest/impl/forge/compat/snowrealmagic/SnowRealMagicPlatformImpl.java diff --git a/common/build.gradle b/common/build.gradle index 7b133cb..9b243a2 100644 --- a/common/build.gradle +++ b/common/build.gradle @@ -33,7 +33,12 @@ dependencies { minecraft libs.minecraft modImplementation libs.fabric.loader + compileOnly libs.autoservice + annotationProcessor libs.autoservice + implementation libs.mixinextras.common + + modCompileOnly libs.snowrealmagic.fabric } artifacts { diff --git a/common/src/main/java/dev/lukebemish/tempest/impl/Services.java b/common/src/main/java/dev/lukebemish/tempest/impl/Services.java index 04c2473..1a14685 100644 --- a/common/src/main/java/dev/lukebemish/tempest/impl/Services.java +++ b/common/src/main/java/dev/lukebemish/tempest/impl/Services.java @@ -1,26 +1,121 @@ package dev.lukebemish.tempest.impl; import dev.lukebemish.tempest.impl.data.world.WeatherChunkData; +import net.minecraft.core.BlockPos; import net.minecraft.core.Registry; import net.minecraft.resources.ResourceLocation; +import net.minecraft.server.level.ServerLevel; +import net.minecraft.world.level.block.state.BlockState; import net.minecraft.world.level.chunk.LevelChunk; +import org.jetbrains.annotations.Nullable; +import java.util.ArrayList; +import java.util.List; import java.util.ServiceLoader; import java.util.function.Supplier; -public class Services { +public final class Services { + private Services() {} + public static final Platform PLATFORM = load(Platform.class); + private static final List SNOWERS; + private static final List MELTERS; + + public static boolean snow(ServerLevel level, BlockPos pos, BlockState original) { + for (var snower : SNOWERS) { + if (snower.snow(level, pos, original)) { + return true; + } + } + return false; + } + + public static boolean melt(ServerLevel level, BlockPos pos, BlockState original) { + for (var melter : MELTERS) { + if (melter.melt(level, pos, original)) { + return true; + } + } + return false; + } + public static T load(Class clazz) { return ServiceLoader.load(clazz) .findFirst() .orElseThrow(() -> new NullPointerException("Failed to load service for " + clazz.getName())); } + static { + var melters = new ArrayList(); + var snowers = new ArrayList(); + for (var provider : ServiceLoader.load(CompatProvider.class)) { + if (provider.shouldLoad()) { + var melter = provider.melter(); + if (melter != null) { + melters.add(new Melter() { + boolean valid = true; + + @Override + public boolean melt(ServerLevel level, BlockPos pos, BlockState original) { + if (valid) { + try { + return melter.melt(level, pos, original); + } catch (Throwable t) { + valid = false; + Constants.LOGGER.error("Failed to melt block at {} with provider {}", pos, provider.getClass().getName(), t); + } + } + return false; + } + }); + } + var snower = provider.snower(); + if (snower != null) { + snowers.add(new Snower() { + boolean valid = true; + + @Override + public boolean snow(ServerLevel level, BlockPos pos, BlockState original) { + if (valid) { + try { + return snower.snow(level, pos, original); + } catch (Throwable t) { + valid = false; + Constants.LOGGER.error("Failed to snow block at {} with provider {}", pos, provider.getClass().getName(), t); + } + } + return false; + } + }); + } + } + } + MELTERS = List.copyOf(melters); + SNOWERS = List.copyOf(snowers); + } + public interface Platform { WeatherChunkData getChunkData(LevelChunk chunk); Supplier register(Supplier supplier, ResourceLocation location, Registry registry); boolean modLoaded(String modId); } + + @FunctionalInterface + public interface Melter { + boolean melt(ServerLevel level, BlockPos pos, BlockState original); + } + + @FunctionalInterface + public interface Snower { + boolean snow(ServerLevel level, BlockPos pos, BlockState original); + } + + public interface CompatProvider { + @Nullable Melter melter(); + @Nullable Snower snower(); + + boolean shouldLoad(); + } } diff --git a/common/src/main/java/dev/lukebemish/tempest/impl/compat/snowrealmagic/SnowRealMagicCompat.java b/common/src/main/java/dev/lukebemish/tempest/impl/compat/snowrealmagic/SnowRealMagicCompat.java new file mode 100644 index 0000000..b9c4b26 --- /dev/null +++ b/common/src/main/java/dev/lukebemish/tempest/impl/compat/snowrealmagic/SnowRealMagicCompat.java @@ -0,0 +1,69 @@ +package dev.lukebemish.tempest.impl.compat.snowrealmagic; + +import com.google.auto.service.AutoService; +import dev.lukebemish.tempest.impl.Services; +import net.minecraft.core.BlockPos; +import net.minecraft.core.Direction; +import net.minecraft.world.item.ItemStack; +import net.minecraft.world.item.context.DirectionalPlaceContext; +import net.minecraft.world.level.Level; +import net.minecraft.world.level.block.Block; +import net.minecraft.world.level.block.state.BlockState; +import org.jetbrains.annotations.Nullable; +import snownee.snow.Hooks; + +@AutoService(Services.CompatProvider.class) +public class SnowRealMagicCompat implements Services.CompatProvider { + public interface SnowRealMagicPlatform { + SnowRealMagicPlatform INSTANCE = Services.load(SnowRealMagicPlatform.class); + + boolean isVariant(Block snowVariant); + + BlockState decreaseLayer(Block snowVariant, BlockState original, Level level, BlockPos pos, boolean flag); + int layers(BlockState original, Level level, BlockPos pos); + } + + @Override + public Services.@Nullable Melter melter() { + return (level, pos, original) -> { + Block snowVariant = original.getBlock(); + if (SnowRealMagicPlatform.INSTANCE.isVariant(snowVariant)) { + try { + BlockState newState = SnowRealMagicPlatform.INSTANCE.decreaseLayer(snowVariant, original, level, pos, false); + if (newState != original) { + level.setBlockAndUpdate(pos, newState); + return true; + } + } catch (Throwable e) { + throw new RuntimeException(e); + } + } + return false; + }; + } + + @Override + public Services.@Nullable Snower snower() { + return (level, pos, original) -> { + var mutablePos = pos.mutable(); + for (int i = 0; i < 16; i++) { + mutablePos.move(Direction.DOWN); + var newState = level.getBlockState(mutablePos); + if ( + !( + (SnowRealMagicPlatform.INSTANCE.isVariant(newState.getBlock()) && SnowRealMagicPlatform.INSTANCE.layers(newState, level, mutablePos) < 8) || + Hooks.canContainState(newState) + ) && Hooks.canSnowSurvive(newState, level, mutablePos.above())) { + var finalPos = mutablePos.above(); + return Hooks.placeLayersOn(level, finalPos, 1, false, new DirectionalPlaceContext(level, finalPos, Direction.UP, ItemStack.EMPTY, Direction.DOWN), false, true); + } + } + return false; + }; + } + + @Override + public boolean shouldLoad() { + return Services.PLATFORM.modLoaded("snowrealmagic"); + } +} diff --git a/common/src/main/java/dev/lukebemish/tempest/impl/data/world/WeatherChunkData.java b/common/src/main/java/dev/lukebemish/tempest/impl/data/world/WeatherChunkData.java index b4740ee..45e97e7 100644 --- a/common/src/main/java/dev/lukebemish/tempest/impl/data/world/WeatherChunkData.java +++ b/common/src/main/java/dev/lukebemish/tempest/impl/data/world/WeatherChunkData.java @@ -2,6 +2,7 @@ import dev.lukebemish.tempest.api.WeatherStatus; import dev.lukebemish.tempest.impl.Constants; +import dev.lukebemish.tempest.impl.Services; import dev.lukebemish.tempest.impl.data.WeatherCategory; import dev.lukebemish.tempest.impl.data.WeatherMapData; import dev.lukebemish.tempest.impl.util.QuasiRandomChunkVisitor; @@ -408,35 +409,7 @@ private boolean tryFreezeBlock(ServerLevel level, BlockPos toFreeze) { return level.random.nextFloat() < precip; } else if (isSnowing(temp, precip, thunder)) { BlockPos toSnow = toFreeze.above(); - var state = level.getBlockState(toSnow); - if (state.getBlock() == Blocks.SNOW) { - int levels = state.getValue(SnowLayerBlock.LAYERS); - BlockState newState; - if (levels < 7) { - newState = state.setValue(SnowLayerBlock.LAYERS, levels + 1); - } else { - if (level.random.nextFloat() < 0.75f) { - newState = Blocks.SNOW_BLOCK.defaultBlockState(); - } else { - newState = Blocks.POWDER_SNOW.defaultBlockState(); - } - } - level.setBlockAndUpdate(toSnow, newState); - Block.pushEntitiesUp(state, newState, level, toSnow); - } else if (state.canBeReplaced() && Blocks.SNOW.defaultBlockState().canSurvive(level, toSnow)) { - if (hasSpaceForSnow(level, toSnow)) { - level.setBlockAndUpdate(toSnow, Blocks.SNOW.defaultBlockState()); - } - } else if (state.getBlock() == Blocks.POWDER_SNOW) { - BlockPos aboveSnow = toSnow.above(); - BlockState upState = level.getBlockState(aboveSnow); - level.setBlockAndUpdate(toSnow, Blocks.SNOW_BLOCK.defaultBlockState()); - if (upState.canBeReplaced() && Blocks.SNOW.defaultBlockState().canSurvive(level, aboveSnow)) { - if (hasSpaceForSnow(level, aboveSnow)) { - level.setBlockAndUpdate(aboveSnow, Blocks.SNOW.defaultBlockState()); - } - } - } + processSnow(level, toSnow); return level.random.nextFloat() < precip; } } @@ -445,6 +418,34 @@ private boolean tryFreezeBlock(ServerLevel level, BlockPos toFreeze) { return level.random.nextFloat() < (level.random.nextBoolean() ? -temp : precip); } + @SuppressWarnings("StatementWithEmptyBody") + private static void processSnow(ServerLevel level, BlockPos toSnow) { + var state = level.getBlockState(toSnow); + if (state.getBlock() == Blocks.SNOW) { + int levels = state.getValue(SnowLayerBlock.LAYERS); + BlockState newState; + if (levels < 7) { + newState = state.setValue(SnowLayerBlock.LAYERS, levels + 1); + } else { + if (level.random.nextFloat() < 0.75f) { + newState = Blocks.SNOW_BLOCK.defaultBlockState(); + } else { + newState = Blocks.POWDER_SNOW.defaultBlockState(); + } + } + level.setBlockAndUpdate(toSnow, newState); + Block.pushEntitiesUp(state, newState, level, toSnow); + } else if (hasSpaceForSnow(level, toSnow) && Services.snow(level, toSnow, state)) { + + } else if (hasSpaceForSnow(level, toSnow) && Blocks.SNOW.defaultBlockState().canSurvive(level, toSnow) && state.canBeReplaced()) { + level.setBlockAndUpdate(toSnow, Blocks.SNOW.defaultBlockState()); + } else if (state.getBlock() == Blocks.POWDER_SNOW) { + BlockPos aboveSnow = toSnow.above(); + level.setBlockAndUpdate(toSnow, Blocks.SNOW_BLOCK.defaultBlockState()); + processSnow(level, aboveSnow); + } + } + public boolean canSeeWindSnow(BlockPos pos) { var mutablePos = new BlockPos.MutableBlockPos(); for (BlockPos check : windCheckPositions) { @@ -544,6 +545,7 @@ public WeatherStatus makeApiStatus(WeatherStatusAssembler assembler, BlockPos po return assembler.assemble(kind, Mth.sqrt(Mth.clamp(precip, 0, 1)), temp, thunder > 0f, new Vec2(windX, windZ)); } + @SuppressWarnings("StatementWithEmptyBody") private void tryMeltBlock(ServerLevel level, BlockPos toMelt) { if (validBlock(level, toMelt)) { var state = level.getBlockState(toMelt); @@ -576,7 +578,9 @@ private void tryMeltBlock(ServerLevel level, BlockPos toMelt) { var above = toMelt.above(); var stateAbove = level.getBlockState(above); - if (stateAbove.getBlock() == Blocks.SNOW) { + if (Services.melt(level, above, stateAbove)) { + + } else if (stateAbove.getBlock() == Blocks.SNOW) { int levels = stateAbove.getValue(SnowLayerBlock.LAYERS); if (levels > 1) { var newState = stateAbove.setValue(SnowLayerBlock.LAYERS, levels - 1); @@ -586,6 +590,8 @@ private void tryMeltBlock(ServerLevel level, BlockPos toMelt) { } } else if (stateAbove.getBlock() == Blocks.POWDER_SNOW) { level.setBlockAndUpdate(above, Blocks.SNOW.defaultBlockState().setValue(SnowLayerBlock.LAYERS, 7)); + } else if (!Services.melt(level, toMelt, state)) { + } else if (state.getBlock() == Blocks.SNOW_BLOCK || state.getBlock() == Blocks.POWDER_SNOW) { level.setBlockAndUpdate(toMelt, Blocks.SNOW.defaultBlockState().setValue(SnowLayerBlock.LAYERS, 7)); } diff --git a/common/src/main/resources/data/tempest/tags/blocks/snow_passthrough.json b/common/src/main/resources/data/tempest/tags/blocks/snow_passthrough.json index 5fb0da9..f3e9025 100644 --- a/common/src/main/resources/data/tempest/tags/blocks/snow_passthrough.json +++ b/common/src/main/resources/data/tempest/tags/blocks/snow_passthrough.json @@ -2,6 +2,14 @@ "values": [ "minecraft:powder_snow", "minecraft:snow_block", - "minecraft:snow" + "minecraft:snow", + { + "id": "#minecraft:snow", + "required": false + }, + { + "id": "#snowrealmagic:snowy_setting", + "required": false + } ] } diff --git a/fabriquilt/build.gradle b/fabriquilt/build.gradle index 9462bf4..bc297dd 100644 --- a/fabriquilt/build.gradle +++ b/fabriquilt/build.gradle @@ -43,7 +43,8 @@ dependencies { // Compat - modLocalRuntime libs.snowrealmagic.fabric + modCompileOnly libs.snowrealmagic.fabric + modCompileOnly libs.kiwi.fabric } // Publishing diff --git a/fabriquilt/src/main/java/dev/lukebemish/tempest/impl/fabriquilt/compat/snowrealmagic/SnowRealMagicPlatformImpl.java b/fabriquilt/src/main/java/dev/lukebemish/tempest/impl/fabriquilt/compat/snowrealmagic/SnowRealMagicPlatformImpl.java new file mode 100644 index 0000000..40794ff --- /dev/null +++ b/fabriquilt/src/main/java/dev/lukebemish/tempest/impl/fabriquilt/compat/snowrealmagic/SnowRealMagicPlatformImpl.java @@ -0,0 +1,27 @@ +package dev.lukebemish.tempest.impl.fabriquilt.compat.snowrealmagic; + +import com.google.auto.service.AutoService; +import dev.lukebemish.tempest.impl.compat.snowrealmagic.SnowRealMagicCompat; +import net.minecraft.core.BlockPos; +import net.minecraft.world.level.Level; +import net.minecraft.world.level.block.Block; +import net.minecraft.world.level.block.state.BlockState; +import snownee.snow.block.SnowVariant; + +@AutoService(SnowRealMagicCompat.SnowRealMagicPlatform.class) +public class SnowRealMagicPlatformImpl implements SnowRealMagicCompat.SnowRealMagicPlatform { + @Override + public boolean isVariant(Block snowVariant) { + return snowVariant instanceof SnowVariant; + } + + @Override + public BlockState decreaseLayer(Block snowVariant, BlockState original, Level level, BlockPos pos, boolean flag) { + return ((SnowVariant) snowVariant).decreaseLayer(original, level, pos, flag); + } + + @Override + public int layers(BlockState original, Level level, BlockPos pos) { + return ((SnowVariant) original.getBlock()).layers(original, level, pos); + } +} diff --git a/forge/build.gradle b/forge/build.gradle index 30e495b..0819b40 100644 --- a/forge/build.gradle +++ b/forge/build.gradle @@ -50,7 +50,7 @@ dependencies { modCompileOnly libs.embeddium //modLocalRuntime libs.embeddium - modLocalRuntime libs.snowrealmagic.forge + modCompileOnly libs.snowrealmagic.forge } // Publishing diff --git a/forge/src/main/java/dev/lukebemish/tempest/impl/forge/compat/snowrealmagic/SnowRealMagicPlatformImpl.java b/forge/src/main/java/dev/lukebemish/tempest/impl/forge/compat/snowrealmagic/SnowRealMagicPlatformImpl.java new file mode 100644 index 0000000..f449a90 --- /dev/null +++ b/forge/src/main/java/dev/lukebemish/tempest/impl/forge/compat/snowrealmagic/SnowRealMagicPlatformImpl.java @@ -0,0 +1,27 @@ +package dev.lukebemish.tempest.impl.forge.compat.snowrealmagic; + +import com.google.auto.service.AutoService; +import dev.lukebemish.tempest.impl.compat.snowrealmagic.SnowRealMagicCompat; +import net.minecraft.core.BlockPos; +import net.minecraft.world.level.Level; +import net.minecraft.world.level.block.Block; +import net.minecraft.world.level.block.state.BlockState; +import snownee.snow.block.SnowVariant; + +@AutoService(SnowRealMagicCompat.SnowRealMagicPlatform.class) +public class SnowRealMagicPlatformImpl implements SnowRealMagicCompat.SnowRealMagicPlatform { + @Override + public boolean isVariant(Block snowVariant) { + return snowVariant instanceof SnowVariant; + } + + @Override + public BlockState decreaseLayer(Block snowVariant, BlockState original, Level level, BlockPos pos, boolean flag) { + return ((SnowVariant) snowVariant).decreaseLayer(original, level, pos, flag); + } + + @Override + public int layers(BlockState original, Level level, BlockPos pos) { + return ((SnowVariant) original.getBlock()).layers(original, level, pos); + } +} diff --git a/gradle/libs.versions.toml b/gradle/libs.versions.toml index 7b1f5fe..b4ddc23 100644 --- a/gradle/libs.versions.toml +++ b/gradle/libs.versions.toml @@ -28,6 +28,7 @@ cca = "5.2.2" embeddium = "0.2.12-git.170afb8+mc1.20.1" snowrealmagic_forge = "S9gp2AyE" snowrealmagic_fabric = "eNt5cULd" +kiwi_fabric = "kyG6D8vz" [libraries] minecraft = { module = "com.mojang:minecraft", version.ref = "minecraft" } @@ -51,6 +52,7 @@ cca-chunk = { module = "dev.onyxstudios.cardinal-components-api:cardinal-compone embeddium = { module = "org.embeddedt:embeddium-1.20.1", version.ref = "embeddium" } snowrealmagic_forge = { module = "maven.modrinth:snow-real-magic", version.ref = "snowrealmagic_forge" } snowrealmagic_fabric = { module = "maven.modrinth:snow-real-magic", version.ref = "snowrealmagic_fabric" } +kiwi_fabric = { module = "maven.modrinth:kiwi", version.ref = "kiwi_fabric" } [plugins]