Rain no longer appears above clouds (mostly)

This commit is contained in:
Sollace 2024-09-29 04:28:22 +01:00
parent c0d9200101
commit 68820924bf
No known key found for this signature in database
GPG key ID: E52FACE7B5C773DB
6 changed files with 168 additions and 50 deletions

View file

@ -21,7 +21,6 @@ import com.minelittlepony.unicopia.container.*;
import com.minelittlepony.unicopia.entity.player.PlayerCamera; import com.minelittlepony.unicopia.entity.player.PlayerCamera;
import com.minelittlepony.unicopia.entity.player.Pony; import com.minelittlepony.unicopia.entity.player.Pony;
import com.minelittlepony.unicopia.network.handler.ClientNetworkHandlerImpl; import com.minelittlepony.unicopia.network.handler.ClientNetworkHandlerImpl;
import com.minelittlepony.unicopia.server.world.WeatherConditions;
import com.minelittlepony.unicopia.server.world.ZapAppleStageStore; import com.minelittlepony.unicopia.server.world.ZapAppleStageStore;
import com.minelittlepony.unicopia.util.Lerp; import com.minelittlepony.unicopia.util.Lerp;
@ -38,7 +37,6 @@ import net.minecraft.client.world.ClientWorld;
import net.minecraft.entity.player.PlayerEntity; import net.minecraft.entity.player.PlayerEntity;
import net.minecraft.resource.ResourceType; import net.minecraft.resource.ResourceType;
import net.minecraft.text.Text; import net.minecraft.text.Text;
import net.minecraft.util.math.BlockPos;
import net.minecraft.util.math.MathHelper; import net.minecraft.util.math.MathHelper;
import net.minecraft.util.math.Vec3d; import net.minecraft.util.math.Vec3d;
@ -55,9 +53,8 @@ public class UnicopiaClient implements ClientModInitializer {
return Pony.of(MinecraftClient.getInstance().player); return Pony.of(MinecraftClient.getInstance().player);
} }
@Nullable
private Float originalRainGradient;
private final Lerp rainGradient = new Lerp(0); private final Lerp rainGradient = new Lerp(0);
private final Lerp thunderGradient = new Lerp(0);
public final Lerp tangentalSkyAngle = new Lerp(0, true); public final Lerp tangentalSkyAngle = new Lerp(0, true);
public final Lerp skyAngle = new Lerp(0, true); public final Lerp skyAngle = new Lerp(0, true);
@ -157,38 +154,22 @@ public class UnicopiaClient implements ClientModInitializer {
} }
private void onWorldTick(ClientWorld world) { private void onWorldTick(ClientWorld world) {
BlockPos pos = MinecraftClient.getInstance().getCameraEntity().getBlockPos(); /*BlockPos pos = MinecraftClient.getInstance().getCameraEntity().getBlockPos();
float tickDelta = MinecraftClient.getInstance().getTickDelta(); float tickDelta = MinecraftClient.getInstance().getTickDelta();
Float targetRainGradient = getTargetRainGradient(world, pos, tickDelta); Float targetRainGradient = ((WeatherAccess)world).isInRangeOfStorm(pos) ? (Float)1F : ((WeatherAccess)world).isBelowCloudLayer(pos) ? null : (Float)0F;
Float targetThunderGradient = ((WeatherAccess)world).isInRangeOfStorm(pos) ? (Float)1F : null;
if (targetRainGradient != null) { ((WeatherAccess)world).setWeatherOverride(null, null);
rainGradient.update(targetRainGradient, 2000); rainGradient.update(targetRainGradient == null ? world.getRainGradient(tickDelta) : targetRainGradient, 2000);
}
float gradient = rainGradient.getValue(); ((WeatherAccess)world).setWeatherOverride(1F, null);
if (!rainGradient.isFinished()) { thunderGradient.update(targetThunderGradient == null ? world.getThunderGradient(tickDelta) : targetThunderGradient, 2000);
world.setRainGradient(gradient);
world.setThunderGradient(gradient);
}
}
private Float getTargetRainGradient(ClientWorld world, BlockPos pos, float tickDelta) { ((WeatherAccess)world).setWeatherOverride(
if (WeatherConditions.get(world).isInRangeOfStorm(pos)) { rainGradient.isFinished() ? targetRainGradient : (Float)rainGradient.getValue(),
if (originalRainGradient == null) { thunderGradient.isFinished() ? targetThunderGradient : (Float)thunderGradient.getValue()
originalRainGradient = world.getRainGradient(tickDelta); );*/
}
return 1F;
}
if (originalRainGradient != null) {
Float f = originalRainGradient;
originalRainGradient = null;
return f;
}
return null;
} }
private void onScreenInit(Screen screen, ButtonList buttons) { private void onScreenInit(Screen screen, ButtonList buttons) {

View file

@ -690,7 +690,7 @@ public class PlayerPhysics extends EntityPhysics<PlayerEntity> implements Tickab
if (entity.getWorld().hasRain(entity.getBlockPos())) { if (entity.getWorld().hasRain(entity.getBlockPos())) {
applyTurbulance(velocity); applyTurbulance(velocity);
} else { } else {
float targetUpdraft = (float)WeatherConditions.getUpdraft(new BlockPos.Mutable().set(entity.getBlockPos()), entity.getWorld()) / 3F; float targetUpdraft = WeatherConditions.THERMAL_FIELD.getValue(entity.getWorld(), new BlockPos.Mutable().set(entity.getBlockPos())) / 3F;
targetUpdraft *= 1 + motion; targetUpdraft *= 1 + motion;
if (isGravityNegative()) { if (isGravityNegative()) {
targetUpdraft *= -1; targetUpdraft *= -1;

View file

@ -1,21 +1,32 @@
package com.minelittlepony.unicopia.mixin; package com.minelittlepony.unicopia.mixin;
import java.util.function.Supplier; import java.util.function.Supplier;
import org.jetbrains.annotations.Nullable;
import org.spongepowered.asm.mixin.Mixin; import org.spongepowered.asm.mixin.Mixin;
import org.spongepowered.asm.mixin.injection.At; import org.spongepowered.asm.mixin.injection.At;
import org.spongepowered.asm.mixin.injection.Inject; import org.spongepowered.asm.mixin.injection.Inject;
import org.spongepowered.asm.mixin.injection.callback.CallbackInfo; import org.spongepowered.asm.mixin.injection.callback.CallbackInfo;
import org.spongepowered.asm.mixin.injection.callback.CallbackInfoReturnable;
import com.minelittlepony.unicopia.entity.duck.RotatedView; import com.minelittlepony.unicopia.entity.duck.RotatedView;
import com.minelittlepony.unicopia.server.world.BlockDestructionManager; import com.minelittlepony.unicopia.server.world.BlockDestructionManager;
import com.minelittlepony.unicopia.server.world.WeatherAccess;
import net.minecraft.entity.Entity; import net.minecraft.entity.Entity;
import net.minecraft.util.math.BlockPos;
import net.minecraft.world.World; import net.minecraft.world.World;
import net.minecraft.world.WorldAccess; import net.minecraft.world.WorldAccess;
@Mixin(World.class) @Mixin(World.class)
abstract class MixinWorld implements WorldAccess, BlockDestructionManager.Source, RotatedView { abstract class MixinWorld implements WorldAccess, BlockDestructionManager.Source, RotatedView, WeatherAccess {
private final Supplier<BlockDestructionManager> destructions = BlockDestructionManager.create((World)(Object)this); private final Supplier<BlockDestructionManager> destructions = BlockDestructionManager.create((World)(Object)this);
@Nullable
private Float rainGradientOverride;
@Nullable
private Float thunderGradientOverride;
private boolean mirrorEntityStatuses; private boolean mirrorEntityStatuses;
@Override @Override
@ -28,11 +39,36 @@ abstract class MixinWorld implements WorldAccess, BlockDestructionManager.Source
return destructions.get(); return destructions.get();
} }
@Override
public void setWeatherOverride(Float rain, Float thunder) {
rainGradientOverride = rain;
thunderGradientOverride = thunder;
}
@Inject(method = "sendEntityStatus(Lnet/minecraft/entity/Entity;B)V", at = @At("HEAD")) @Inject(method = "sendEntityStatus(Lnet/minecraft/entity/Entity;B)V", at = @At("HEAD"))
private void onSendEntityStatus(Entity entity, byte status, CallbackInfo info) { private void onSendEntityStatus(Entity entity, byte status, CallbackInfo info) {
if (mirrorEntityStatuses) { if (mirrorEntityStatuses) {
entity.handleStatus(status); entity.handleStatus(status);
} }
} }
@Inject(method = "getThunderGradient", at = @At("HEAD"), cancellable = true)
private void onGetThunderGradient(float delta, CallbackInfoReturnable<Float> info) {
if (thunderGradientOverride != null) {
info.setReturnValue(thunderGradientOverride * ((World)(Object)this).getRainGradient(delta));
}
}
@Inject(method = "getRainGradient", at = @At("HEAD"), cancellable = true)
private void onGetRainGradient(float delta, CallbackInfoReturnable<Float> info) {
if (rainGradientOverride != null) {
info.setReturnValue(rainGradientOverride);
}
}
@Inject(method = "hasRain", at = @At("RETURN"), cancellable = true)
private void onHasRain(BlockPos pos, CallbackInfoReturnable<Boolean> info) {
info.setReturnValue((info.getReturnValue() && isBelowCloudLayer(pos)) || isInRangeOfStorm(pos));
}
} }

View file

@ -15,6 +15,8 @@ import org.spongepowered.asm.mixin.injection.callback.CallbackInfo;
import com.minelittlepony.unicopia.client.ClientBlockDestructionManager; import com.minelittlepony.unicopia.client.ClientBlockDestructionManager;
import com.minelittlepony.unicopia.client.UnicopiaClient; import com.minelittlepony.unicopia.client.UnicopiaClient;
import com.minelittlepony.unicopia.server.world.WeatherAccess;
import it.unimi.dsi.fastutil.longs.Long2ObjectMap; import it.unimi.dsi.fastutil.longs.Long2ObjectMap;
import net.minecraft.client.render.BlockBreakingInfo; import net.minecraft.client.render.BlockBreakingInfo;
import net.minecraft.client.render.Camera; import net.minecraft.client.render.Camera;
@ -22,7 +24,10 @@ import net.minecraft.client.render.WorldRenderer;
import net.minecraft.client.util.math.MatrixStack; import net.minecraft.client.util.math.MatrixStack;
import net.minecraft.client.world.ClientWorld; import net.minecraft.client.world.ClientWorld;
import net.minecraft.resource.SynchronousResourceReloader; import net.minecraft.resource.SynchronousResourceReloader;
import net.minecraft.util.math.BlockPos;
import net.minecraft.util.math.RotationAxis; import net.minecraft.util.math.RotationAxis;
import net.minecraft.world.biome.Biome;
import net.minecraft.world.biome.Biome.Precipitation;
@Mixin(value = WorldRenderer.class, priority = 1001) @Mixin(value = WorldRenderer.class, priority = 1001)
abstract class MixinWorldRenderer implements SynchronousResourceReloader, AutoCloseable, ClientBlockDestructionManager.Source { abstract class MixinWorldRenderer implements SynchronousResourceReloader, AutoCloseable, ClientBlockDestructionManager.Source {
@ -80,4 +85,13 @@ abstract class MixinWorldRenderer implements SynchronousResourceReloader, AutoCl
matrices.multiply(RotationAxis.POSITIVE_X.rotationDegrees(UnicopiaClient.getInstance().getSkyAngleDelta(tickDelta))); matrices.multiply(RotationAxis.POSITIVE_X.rotationDegrees(UnicopiaClient.getInstance().getSkyAngleDelta(tickDelta)));
matrices.multiply(RotationAxis.POSITIVE_Y.rotationDegrees(UnicopiaClient.getInstance().tangentalSkyAngle.getValue())); matrices.multiply(RotationAxis.POSITIVE_Y.rotationDegrees(UnicopiaClient.getInstance().tangentalSkyAngle.getValue()));
} }
@Redirect(method = "renderWeather", at = @At(value = "INVOKE", target = "net/minecraft/world/biome/Biome.getPrecipitation(Lnet/minecraft/util/math/BlockPos;)Lnet/minecraft/world/biome/Biome$Precipitation;"))
private Biome.Precipitation modifyPrecipitation(Biome biome, BlockPos pos) {
Biome.Precipitation precipitation = biome.getPrecipitation(pos);
if (!((WeatherAccess)world).isBelowClientCloudLayer(pos)) {
return Precipitation.NONE;
}
return precipitation;
}
} }

View file

@ -0,0 +1,89 @@
package com.minelittlepony.unicopia.server.world;
import com.minelittlepony.unicopia.block.cloud.CloudLike;
import net.fabricmc.api.EnvType;
import net.fabricmc.api.Environment;
import net.minecraft.client.MinecraftClient;
import net.minecraft.util.math.BlockPos;
import net.minecraft.util.math.Direction;
import net.minecraft.util.math.ChunkSectionPos;
import net.minecraft.world.World;
import net.minecraft.world.chunk.Chunk;
public interface WeatherAccess {
void setWeatherOverride(Float rain, Float thunder);
default boolean isInRangeOfStorm(BlockPos pos) {
return WeatherConditions.get((World)this).isInRangeOfStorm(pos);
}
@Environment(EnvType.CLIENT)
default boolean isBelowClientCloudLayer(BlockPos pos) {
int range = MinecraftClient.isFancyGraphicsOrBetter() ? 10 : 5;
if (pos.getY() < 230 - range) {
return true;
}
Chunk chunk = ((World)this).getChunk(pos);
int topSection = chunk.getHighestNonEmptySection();
if (topSection > -1) {
int sectionBottomY = ChunkSectionPos.getBlockCoord(topSection);
if (sectionBottomY >= pos.getY() - 16) {
BlockPos.Mutable mutable = pos.mutableCopy();
BlockPos.Mutable probeMutable = pos.mutableCopy();
int maxDistance = 16;
while (((World)this).isInBuildLimit(mutable)) {
if (--maxDistance <= 0) break;
if (!((World)this).isAir(probeMutable.setY(mutable.getY() + range))) {
mutable.set(pos);
maxDistance = 16;
while (((World)this).isInBuildLimit(mutable)) {
if (--maxDistance <= 0) break;
if (((World)this).getBlockState(probeMutable.setY(mutable.getY())).getBlock() instanceof CloudLike) {
return false;
}
mutable.move(Direction.DOWN);
}
return true;
}
mutable.move(Direction.UP);
}
}
}
return false;
}
default boolean isBelowCloudLayer(BlockPos pos) {
if (pos.getY() < 230) {
return true;
}
Chunk chunk = ((World)this).getChunk(pos);
int topSection = chunk.getHighestNonEmptySection();
if (topSection > -1) {
int sectionBottomY = ChunkSectionPos.getBlockCoord(topSection);
if (sectionBottomY >= pos.getY() - 16) {
BlockPos.Mutable mutable = pos.mutableCopy();
int maxDistance = 32;
while (((World)this).isInBuildLimit(mutable)) {
if (--maxDistance <= 0) break;
if (!((World)this).isAir(mutable)) {
return true;
}
mutable.move(Direction.UP);
}
}
}
return false;
}
}

View file

@ -23,8 +23,21 @@ import net.minecraft.world.PersistentState;
import net.minecraft.world.World; import net.minecraft.world.World;
public class WeatherConditions extends PersistentState implements Tickable { public class WeatherConditions extends PersistentState implements Tickable {
public static final double FIRE_UPDRAFT = 0.13;
public static final double SAND_UPDRAFT = 0.03;
public static final double SOUL_SAND_UPDRAFT = -0.03;
public static final double ICE_UPDRAFT = 0;
public static final double VOID_UPDRAFT = -0.23;
public static final float MAX_UPDRAFT_HEIGHT = 20;
public static final float MAX_TERRAIN_HEIGHT = 50;
public static final float MAX_WIND_HEIGHT = 70;
public static final Plane HEIGHT_MAP_FIELD = (world, pos) -> world.getTopY(Type.WORLD_SURFACE_WG, pos.getX(), pos.getZ()); public static final Plane HEIGHT_MAP_FIELD = (world, pos) -> world.getTopY(Type.WORLD_SURFACE_WG, pos.getX(), pos.getZ());
public static final Plane THERMAL_FIELD = (world, pos) -> (float)getUpdraft(pos, world); public static final Plane THERMAL_FIELD = (world, pos) -> {
double factor = 1 - getScaledDistanceFromTerrain(pos, world, MAX_UPDRAFT_HEIGHT);
return (float)(factor * getMaterialSurfaceTemperature(pos, world));
};
public static final Plane LOCAL_ALTITUDE_FIELD = (world, pos) -> { public static final Plane LOCAL_ALTITUDE_FIELD = (world, pos) -> {
if (!world.isAir(pos)) { if (!world.isAir(pos)) {
return 0; return 0;
@ -36,16 +49,6 @@ public class WeatherConditions extends PersistentState implements Tickable {
return y - pos.getY(); return y - pos.getY();
}; };
public static final double FIRE_UPDRAFT = 0.13;
public static final double SAND_UPDRAFT = 0.03;
public static final double SOUL_SAND_UPDRAFT = -0.03;
public static final double ICE_UPDRAFT = 0;
public static final double VOID_UPDRAFT = -0.23;
public static final float MAX_UPDRAFT_HEIGHT = 20;
public static final float MAX_TERRAIN_HEIGHT = 50;
public static final float MAX_WIND_HEIGHT = 70;
private static final Identifier ID = Unicopia.id("weather_conditions"); private static final Identifier ID = Unicopia.id("weather_conditions");
public static WeatherConditions get(World world) { public static WeatherConditions get(World world) {
@ -176,11 +179,6 @@ public class WeatherConditions extends PersistentState implements Tickable {
.multiply(windFactor); .multiply(windFactor);
} }
public static double getUpdraft(BlockPos.Mutable pos, World world) {
double factor = 1 - getScaledDistanceFromTerrain(pos, world, MAX_UPDRAFT_HEIGHT);
return factor * getMaterialSurfaceTemperature(pos, world);
}
private static float getScaledDistanceFromTerrain(BlockPos.Mutable pos, World world, float maxDistance) { private static float getScaledDistanceFromTerrain(BlockPos.Mutable pos, World world, float maxDistance) {
return Math.min(maxDistance, LOCAL_ALTITUDE_FIELD.getValue(world, pos)) / maxDistance; return Math.min(maxDistance, LOCAL_ALTITUDE_FIELD.getValue(world, pos)) / maxDistance;
} }