Skip to content

Commit

Permalink
Hopefully set up snowrealmagic compat
Browse files Browse the repository at this point in the history
  • Loading branch information
lukebemish committed Jan 8, 2024
1 parent f7c2e75 commit c041dd9
Show file tree
Hide file tree
Showing 10 changed files with 274 additions and 34 deletions.
5 changes: 5 additions & 0 deletions common/build.gradle
Original file line number Diff line number Diff line change
Expand Up @@ -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 {
Expand Down
97 changes: 96 additions & 1 deletion common/src/main/java/dev/lukebemish/tempest/impl/Services.java
Original file line number Diff line number Diff line change
@@ -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<Snower> SNOWERS;
private static final List<Melter> 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> T load(Class<T> clazz) {
return ServiceLoader.load(clazz)
.findFirst()
.orElseThrow(() -> new NullPointerException("Failed to load service for " + clazz.getName()));
}

static {
var melters = new ArrayList<Melter>();
var snowers = new ArrayList<Snower>();
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);
<S, T extends S> Supplier<T> register(Supplier<T> supplier, ResourceLocation location, Registry<S> 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();
}
}
Original file line number Diff line number Diff line change
@@ -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");
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand Down Expand Up @@ -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;
}
}
Expand All @@ -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) {
Expand Down Expand Up @@ -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);
Expand Down Expand Up @@ -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);
Expand All @@ -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));
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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
}
]
}
3 changes: 2 additions & 1 deletion fabriquilt/build.gradle
Original file line number Diff line number Diff line change
Expand Up @@ -43,7 +43,8 @@ dependencies {

// Compat

modLocalRuntime libs.snowrealmagic.fabric
modCompileOnly libs.snowrealmagic.fabric
modCompileOnly libs.kiwi.fabric
}

// Publishing
Expand Down
Original file line number Diff line number Diff line change
@@ -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);
}
}
2 changes: 1 addition & 1 deletion forge/build.gradle
Original file line number Diff line number Diff line change
Expand Up @@ -50,7 +50,7 @@ dependencies {
modCompileOnly libs.embeddium
//modLocalRuntime libs.embeddium

modLocalRuntime libs.snowrealmagic.forge
modCompileOnly libs.snowrealmagic.forge
}

// Publishing
Expand Down
Loading

0 comments on commit c041dd9

Please sign in to comment.