mirror of
https://github.com/JonasunderscoreJones/nicer-skies.git
synced 2025-10-23 03:39:18 +02:00
change: rename package
This commit is contained in:
parent
3c8a7412c8
commit
8af53aa1ff
24 changed files with 52 additions and 52 deletions
19
src/main/java/codes/ztereohype/nicerskies/NicerSkies.java
Normal file
19
src/main/java/codes/ztereohype/nicerskies/NicerSkies.java
Normal file
|
@ -0,0 +1,19 @@
|
|||
package codes.ztereohype.nicerskies;
|
||||
|
||||
import codes.ztereohype.nicerskies.config.ConfigManager;
|
||||
import codes.ztereohype.nicerskies.sky.SkyManager;
|
||||
import net.fabricmc.api.ModInitializer;
|
||||
import net.fabricmc.loader.api.FabricLoader;
|
||||
|
||||
import java.io.File;
|
||||
|
||||
public class NicerSkies implements ModInitializer {
|
||||
public static ConfigManager config = ConfigManager.fromFile(new File(FabricLoader.getInstance()
|
||||
.getConfigDir()
|
||||
.toFile(), "nicerskies.json"));
|
||||
public static SkyManager skyManager = new SkyManager();
|
||||
|
||||
@Override
|
||||
public void onInitialize() {
|
||||
}
|
||||
}
|
37
src/main/java/codes/ztereohype/nicerskies/config/Config.java
Normal file
37
src/main/java/codes/ztereohype/nicerskies/config/Config.java
Normal file
|
@ -0,0 +1,37 @@
|
|||
package codes.ztereohype.nicerskies.config;
|
||||
|
||||
import lombok.Data;
|
||||
|
||||
@Data
|
||||
public class Config {
|
||||
public Config(boolean tweakedLigthmap, boolean twinklingStars, boolean nebulas, String nebulaType, float nebulaStrength, float nebulaNoiseAmount, float nebulaNoiseScale, int baseColourAmount) {
|
||||
this.tweakedLigthmap = tweakedLigthmap;
|
||||
this.twinklingStars = twinklingStars;
|
||||
this.nebulas = nebulas;
|
||||
|
||||
this.nebulaConfig = new NebulaConfig(nebulaType, nebulaStrength, nebulaNoiseAmount, nebulaNoiseScale, baseColourAmount);
|
||||
}
|
||||
|
||||
private boolean tweakedLigthmap;
|
||||
private boolean twinklingStars;
|
||||
private boolean nebulas;
|
||||
|
||||
private final NebulaConfig nebulaConfig;
|
||||
|
||||
@Data
|
||||
public static final class NebulaConfig {
|
||||
public NebulaConfig(String nebulaType, float nebulaStrength, float nebulaNoiseAmount, float nebulaNoiseScale, int baseColourAmount) {
|
||||
this.nebulaType = nebulaType;
|
||||
this.nebulaStrength = nebulaStrength;
|
||||
this.nebulaNoiseAmount = nebulaNoiseAmount;
|
||||
this.nebulaNoiseScale = nebulaNoiseScale;
|
||||
this.baseColourAmount = baseColourAmount;
|
||||
}
|
||||
|
||||
private String nebulaType;
|
||||
private float nebulaStrength;
|
||||
private float nebulaNoiseAmount;
|
||||
private float nebulaNoiseScale;
|
||||
private int baseColourAmount;
|
||||
}
|
||||
}
|
|
@ -0,0 +1,148 @@
|
|||
package codes.ztereohype.nicerskies.config;
|
||||
|
||||
import com.google.gson.Gson;
|
||||
|
||||
import java.io.File;
|
||||
import java.io.FileReader;
|
||||
import java.io.FileWriter;
|
||||
import java.io.IOException;
|
||||
|
||||
public class ConfigManager {
|
||||
public static final Config DEFAULT_CONFIG = new Config(false, true, true, NebulaType.RAINBOW.getTypeString(), 1f, 0.5f, 1f, 128);
|
||||
|
||||
private static final Gson gson = new Gson();
|
||||
private final Config config;
|
||||
private final File file;
|
||||
|
||||
public static ConfigManager fromFile(File file) {
|
||||
Config config;
|
||||
try {
|
||||
if (!file.exists()) {
|
||||
file.getParentFile().mkdirs();
|
||||
file.createNewFile();
|
||||
|
||||
config = cloneConfig(DEFAULT_CONFIG);
|
||||
|
||||
gson.toJson(config, new FileWriter(file));
|
||||
} else {
|
||||
config = gson.fromJson(new FileReader(file), Config.class);
|
||||
|
||||
if (config == null) {
|
||||
throw new IOException("Failed to read config file");
|
||||
}
|
||||
}
|
||||
} catch (IOException e) {
|
||||
// todo setup logger properly
|
||||
e.printStackTrace();
|
||||
config = cloneConfig(DEFAULT_CONFIG);
|
||||
}
|
||||
|
||||
return new ConfigManager(config, file);
|
||||
}
|
||||
|
||||
private ConfigManager(Config config, File file) {
|
||||
this.config = config;
|
||||
this.file = file;
|
||||
save(file);
|
||||
}
|
||||
|
||||
public boolean getLightmapTweaked() {
|
||||
return config.isTweakedLigthmap();
|
||||
}
|
||||
|
||||
public boolean getTwinklingStars() {
|
||||
return config.isTwinklingStars();
|
||||
}
|
||||
|
||||
public boolean getNebulas() {
|
||||
return config.isNebulas();
|
||||
}
|
||||
|
||||
public NebulaType getNebulaType() {
|
||||
return NebulaType.valueOf(config.getNebulaConfig().getNebulaType().toUpperCase());
|
||||
}
|
||||
|
||||
public float getNebulaStrength() {
|
||||
return config.getNebulaConfig().getNebulaStrength();
|
||||
}
|
||||
|
||||
public float getNebulaNoiseAmount() {
|
||||
return config.getNebulaConfig().getNebulaNoiseAmount();
|
||||
}
|
||||
|
||||
public float getNebulaNoiseScale() {
|
||||
return config.getNebulaConfig().getNebulaNoiseScale();
|
||||
}
|
||||
|
||||
public int getNebulaBaseColourAmount() {
|
||||
return config.getNebulaConfig().getBaseColourAmount();
|
||||
}
|
||||
|
||||
public void setLightmapTweaked(boolean tweaked) {
|
||||
config.setTweakedLigthmap(tweaked);
|
||||
save(file);
|
||||
}
|
||||
|
||||
public void setTwinklingStars(boolean twinkling) {
|
||||
config.setTwinklingStars(twinkling);
|
||||
save(file);
|
||||
}
|
||||
|
||||
public void setNebulas(boolean nebulas) {
|
||||
config.setNebulas(nebulas);
|
||||
save(file);
|
||||
}
|
||||
|
||||
public void setNebulaType(NebulaType type) {
|
||||
config.getNebulaConfig().setNebulaType(type.getTypeString());
|
||||
save(file);
|
||||
}
|
||||
|
||||
public void setNebulaStrength(float strength) {
|
||||
config.getNebulaConfig().setNebulaStrength(strength);
|
||||
save(file);
|
||||
}
|
||||
|
||||
public void setNebulaNoiseAmount(float amount) {
|
||||
config.getNebulaConfig().setNebulaNoiseAmount(amount);
|
||||
save(file);
|
||||
}
|
||||
|
||||
public void setNebulaNoiseScale(float scale) {
|
||||
config.getNebulaConfig().setNebulaNoiseScale(scale);
|
||||
save(file);
|
||||
}
|
||||
|
||||
public void setNebulaBaseColourAmount(int amount) {
|
||||
config.getNebulaConfig().setBaseColourAmount(amount);
|
||||
save(file);
|
||||
}
|
||||
|
||||
public void save(File file) {
|
||||
try (FileWriter writer = new FileWriter(file)) {
|
||||
writer.write(gson.toJson(config));
|
||||
// System.out.println("Saved config " + );
|
||||
} catch (IOException e) {
|
||||
e.printStackTrace();
|
||||
// todo setup logger properly
|
||||
// LogManager.getLogManager().getLogger("NicerSkies").warning("Failed to save config file!");
|
||||
}
|
||||
}
|
||||
|
||||
private static Config cloneConfig(Config config) {
|
||||
return gson.fromJson(gson.toJson(config), Config.class);
|
||||
}
|
||||
|
||||
public boolean nebulaConfigEquals(Config config) {
|
||||
return this.config.getNebulaConfig().equals(config.getNebulaConfig());
|
||||
}
|
||||
|
||||
public void resetNebulaSettings() {
|
||||
config.getNebulaConfig().setNebulaType(DEFAULT_CONFIG.getNebulaConfig().getNebulaType());
|
||||
config.getNebulaConfig().setNebulaStrength(DEFAULT_CONFIG.getNebulaConfig().getNebulaStrength());
|
||||
config.getNebulaConfig().setNebulaNoiseAmount(DEFAULT_CONFIG.getNebulaConfig().getNebulaNoiseAmount());
|
||||
config.getNebulaConfig().setNebulaNoiseScale(DEFAULT_CONFIG.getNebulaConfig().getNebulaNoiseScale());
|
||||
config.getNebulaConfig().setBaseColourAmount(DEFAULT_CONFIG.getNebulaConfig().getBaseColourAmount());
|
||||
save(file);
|
||||
}
|
||||
}
|
|
@ -0,0 +1,15 @@
|
|||
package codes.ztereohype.nicerskies.config;
|
||||
|
||||
public enum NebulaType {
|
||||
RAINBOW("Rainbow");
|
||||
|
||||
private final String type;
|
||||
|
||||
NebulaType(String type) {
|
||||
this.type = type;
|
||||
}
|
||||
|
||||
public String getTypeString() {
|
||||
return type;
|
||||
}
|
||||
}
|
59
src/main/java/codes/ztereohype/nicerskies/core/Gradient.java
Normal file
59
src/main/java/codes/ztereohype/nicerskies/core/Gradient.java
Normal file
|
@ -0,0 +1,59 @@
|
|||
package codes.ztereohype.nicerskies.core;
|
||||
|
||||
import java.util.Map;
|
||||
import java.util.TreeMap;
|
||||
|
||||
public class Gradient {
|
||||
private final TreeMap<Double, int[]> gradient;
|
||||
|
||||
public Gradient() {
|
||||
this.gradient = new TreeMap<>();
|
||||
}
|
||||
|
||||
public void add(double index, int red, int green, int blue) {
|
||||
if (index < 0 || index > 1) {
|
||||
throw new IllegalArgumentException("Index must be between 0 and 1");
|
||||
}
|
||||
|
||||
int[] color = {red, green, blue};
|
||||
gradient.put(index, color);
|
||||
}
|
||||
|
||||
public void remove(double index) {
|
||||
gradient.remove(index);
|
||||
}
|
||||
|
||||
public void clear() {
|
||||
gradient.clear();
|
||||
}
|
||||
|
||||
public int[] getAt(double value) {
|
||||
if (value < 0D || value > 1D) {
|
||||
throw new IllegalArgumentException("Value must be between 0 and 1");
|
||||
}
|
||||
|
||||
Map.Entry<Double, int[]> floorEntry, ceilingEntry;
|
||||
|
||||
floorEntry = gradient.floorEntry(value);
|
||||
if (floorEntry == null) { // we're under the lowest, return the lowest
|
||||
return gradient.firstEntry().getValue();
|
||||
}
|
||||
|
||||
ceilingEntry = gradient.ceilingEntry(value);
|
||||
if (ceilingEntry == null) { // we're over the highest, return the highest
|
||||
return gradient.lastEntry().getValue();
|
||||
}
|
||||
|
||||
double ratio = (value - floorEntry.getKey()) / (ceilingEntry.getKey() - floorEntry.getKey());
|
||||
double invRatio = 1 - ratio;
|
||||
|
||||
int[] firstColor = floorEntry.getValue();
|
||||
int[] secondColor = ceilingEntry.getValue();
|
||||
|
||||
long red = Math.round(secondColor[0] * ratio + firstColor[0] * invRatio);
|
||||
long green = Math.round(secondColor[1] * ratio + firstColor[1] * invRatio);
|
||||
long blue = Math.round(secondColor[2] * ratio + firstColor[2] * invRatio);
|
||||
|
||||
return new int[]{(int) red, (int) green, (int) blue};
|
||||
}
|
||||
}
|
|
@ -0,0 +1,21 @@
|
|||
package codes.ztereohype.nicerskies.core;
|
||||
|
||||
import net.minecraft.client.Minecraft;
|
||||
import net.minecraft.world.level.Level;
|
||||
|
||||
import java.util.Objects;
|
||||
|
||||
public class NebulaSeedManager {
|
||||
public static long getSeed() {
|
||||
if (Minecraft.getInstance().hasSingleplayerServer()) {
|
||||
// calculate seed from overworld seed
|
||||
return Objects.hash(Minecraft.getInstance().getSingleplayerServer().getLevel(Level.OVERWORLD).getSeed());
|
||||
} else {
|
||||
return Objects.requireNonNull(Minecraft.getInstance().getCurrentServer()).ip.hashCode();
|
||||
}
|
||||
}
|
||||
|
||||
public static boolean canGetSeed() {
|
||||
return Minecraft.getInstance().hasSingleplayerServer() || Minecraft.getInstance().getCurrentServer() != null;
|
||||
}
|
||||
}
|
181
src/main/java/codes/ztereohype/nicerskies/gui/ConfigScreen.java
Normal file
181
src/main/java/codes/ztereohype/nicerskies/gui/ConfigScreen.java
Normal file
|
@ -0,0 +1,181 @@
|
|||
package codes.ztereohype.nicerskies.gui;
|
||||
|
||||
import codes.ztereohype.nicerskies.NicerSkies;
|
||||
import codes.ztereohype.nicerskies.config.ConfigManager;
|
||||
import codes.ztereohype.nicerskies.core.NebulaSeedManager;
|
||||
import codes.ztereohype.nicerskies.gui.widget.Separator;
|
||||
import com.mojang.blaze3d.vertex.PoseStack;
|
||||
import net.minecraft.client.Minecraft;
|
||||
import net.minecraft.client.gui.components.AbstractSliderButton;
|
||||
import net.minecraft.client.gui.components.Button;
|
||||
import net.minecraft.client.gui.components.Checkbox;
|
||||
import net.minecraft.client.gui.screens.Screen;
|
||||
import net.minecraft.network.chat.Component;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
|
||||
public class ConfigScreen extends Screen {
|
||||
private final Screen lastScreen;
|
||||
private final ConfigManager cm = NicerSkies.config;
|
||||
|
||||
private boolean invalidated = false;
|
||||
|
||||
protected ConfigScreen(Screen lastScreen) {
|
||||
super(Component.literal("Nicer Skies Config"));
|
||||
this.lastScreen = lastScreen;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void init() {
|
||||
addRenderableWidget(new Checkbox(20, 60, 20, 20, Component.literal("Render nebulas"), cm.getNebulas()) {
|
||||
@Override
|
||||
public void onPress() {
|
||||
super.onPress();
|
||||
cm.setNebulas(!cm.getNebulas());
|
||||
}
|
||||
});
|
||||
|
||||
addRenderableWidget(new Checkbox(20, 84, 20, 20, Component.literal("Twinlke Stars"), cm.getTwinklingStars()) {
|
||||
@Override
|
||||
public void onPress() {
|
||||
super.onPress();
|
||||
cm.setTwinklingStars(!cm.getTwinklingStars());
|
||||
}
|
||||
});
|
||||
|
||||
addRenderableWidget(new Checkbox(20, 108, 20, 20, Component.literal("Custom Lightmap"), cm.getLightmapTweaked()) {
|
||||
@Override
|
||||
public void onPress() {
|
||||
super.onPress();
|
||||
cm.setLightmapTweaked(!cm.getLightmapTweaked());
|
||||
Minecraft.getInstance().gameRenderer.lightTexture().tick();
|
||||
}
|
||||
});
|
||||
|
||||
addRenderableOnly(new Separator(this.width / 2, 30, this.height - 70));
|
||||
|
||||
// CycleButton<NebulaType> nebulaType = CycleButton.builder((NebulaType value) -> Component.literal(value.getTypeString()))
|
||||
// .withValues(NebulaType.values())
|
||||
// .create(this.width / 2 + (this.width / 2 - 150) / 2, 60, 150, 20, Component.literal("Nebula Type"), (button, value) -> {
|
||||
// invalidated = true;
|
||||
// NicerSkies.config.setNebulaType(value);
|
||||
// });
|
||||
//
|
||||
// if (NebulaType.values().length < 2)
|
||||
// nebulaType.active = false; // deactivate while theres only one!
|
||||
//
|
||||
// addRenderableWidget(nebulaType);
|
||||
|
||||
float strength = cm.getNebulaStrength();
|
||||
addRenderableWidget(new AbstractSliderButton(this.width / 2 + (this.width / 2 - 150) / 2, 60, 150, 20, Component.literal("Nebula Strength: " + (int) (strength * 100) + "%"), strength) {
|
||||
@Override
|
||||
protected void updateMessage() {
|
||||
this.setMessage(Component.literal("Nebula Strength: " + (int) (this.value * 100) + "%"));
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void applyValue() {
|
||||
NicerSkies.config.setNebulaStrength((float) this.value);
|
||||
}
|
||||
});
|
||||
|
||||
float noiseAmount = cm.getNebulaNoiseAmount();
|
||||
addRenderableWidget(new AbstractSliderButton(this.width / 2 + (this.width / 2 - 150) / 2, 84, 150, 20, Component.literal("Nebula Amount: " + (int) (noiseAmount * 100) + "%"), noiseAmount) {
|
||||
@Override
|
||||
protected void updateMessage() {
|
||||
invalidated = true;
|
||||
this.setMessage(Component.literal("Nebula Amount: " + (int) (this.value * 100) + "%"));
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void applyValue() {
|
||||
NicerSkies.config.setNebulaNoiseAmount((float) this.value);
|
||||
}
|
||||
});
|
||||
|
||||
int baseColourAmount = cm.getNebulaBaseColourAmount();
|
||||
addRenderableWidget(new AbstractSliderButton(this.width / 2 + (this.width / 2 - 150) / 2, 108, 150, 20, Component.literal("Background Strength: " + baseColourAmount), baseColourAmount / 255f) {
|
||||
@Override
|
||||
protected void updateMessage() {
|
||||
invalidated = true;
|
||||
this.setMessage(Component.literal("Background Strength: " + (int) (this.value * 255)));
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void applyValue() {
|
||||
NicerSkies.config.setNebulaBaseColourAmount((int) (this.value * 255));
|
||||
}
|
||||
});
|
||||
|
||||
float nebulaNoiseScale = cm.getNebulaNoiseScale();
|
||||
addRenderableWidget(new AbstractSliderButton(this.width / 2 + (this.width / 2 - 150) / 2, 132, 150, 20, Component.literal("Nebula Scale: " + nebulaNoiseScale), Math.round((nebulaNoiseScale - 0.5f) / 1.5f * 100) / 100f) {
|
||||
@Override
|
||||
protected void updateMessage() {
|
||||
invalidated = true;
|
||||
this.setMessage(Component.literal("Nebula Scale: " + (getNebulaNoiseScale())));
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void applyValue() {
|
||||
NicerSkies.config.setNebulaNoiseScale(getNebulaNoiseScale());
|
||||
}
|
||||
|
||||
private float getNebulaNoiseScale() {
|
||||
return (float) Math.round((this.value * 1.5f + 0.5f) * 100) / 100f;
|
||||
}
|
||||
});
|
||||
|
||||
//reload nebula button
|
||||
addRenderableWidget(new Button(this.width / 2 + (this.width / 2 - 150) / 2, 156, 74, 20, Component.literal("Apply"), (button) -> {
|
||||
NicerSkies.skyManager.generateSky(NebulaSeedManager.getSeed());
|
||||
invalidated = false;
|
||||
}) {
|
||||
@Override
|
||||
public void render(@NotNull PoseStack poseStack, int mouseX, int mouseY, float partialTick) {
|
||||
this.active = invalidated && NebulaSeedManager.canGetSeed();
|
||||
super.render(poseStack, mouseX, mouseY, partialTick);
|
||||
}
|
||||
});
|
||||
|
||||
//reset to default
|
||||
addRenderableWidget(new Button(this.width / 2 + (this.width / 2 - 150) / 2 + 76, 156, 74, 20, Component.literal("Reset"), (button) -> {
|
||||
cm.resetNebulaSettings();
|
||||
// find better way to reload screen
|
||||
this.clearWidgets();
|
||||
this.init();
|
||||
invalidated = true;
|
||||
}) {
|
||||
@Override
|
||||
public void render(@NotNull PoseStack poseStack, int mouseX, int mouseY, float partialTick) {
|
||||
this.active = !isDefaultNebulaSettings();
|
||||
super.render(poseStack, mouseX, mouseY, partialTick);
|
||||
}
|
||||
});
|
||||
|
||||
|
||||
addRenderableWidget(new Button(this.width / 2 - 100, this.height - 30, 200, 20, Component.literal("Back"), (button) -> {
|
||||
this.onClose();
|
||||
}));
|
||||
}
|
||||
|
||||
@Override
|
||||
public void render(@NotNull PoseStack poseStack, int mouseX, int mouseY, float partialTick) {
|
||||
this.renderBackground(poseStack);
|
||||
super.render(poseStack, mouseX, mouseY, partialTick);
|
||||
|
||||
drawCenteredString(poseStack, this.font, this.title, this.width / 2, 10, 16777215);
|
||||
drawCenteredString(poseStack, this.font, "Toggle Features", this.width / 4, 36, 16777215);
|
||||
drawCenteredString(poseStack, this.font, "Nebula Settings", 3 * this.width / 4, 36, 16777215);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onClose() {
|
||||
if (invalidated) {
|
||||
NicerSkies.skyManager.generateSky(NebulaSeedManager.getSeed());
|
||||
}
|
||||
minecraft.setScreen(lastScreen);
|
||||
}
|
||||
|
||||
private boolean isDefaultNebulaSettings() {
|
||||
return cm.nebulaConfigEquals(ConfigManager.DEFAULT_CONFIG);
|
||||
}
|
||||
}
|
|
@ -0,0 +1,14 @@
|
|||
package codes.ztereohype.nicerskies.gui;
|
||||
|
||||
import com.terraformersmc.modmenu.api.ConfigScreenFactory;
|
||||
import com.terraformersmc.modmenu.api.ModMenuApi;
|
||||
import net.fabricmc.api.EnvType;
|
||||
import net.fabricmc.api.Environment;
|
||||
|
||||
@Environment(EnvType.CLIENT)
|
||||
public class ModMenuSettingsApi implements ModMenuApi {
|
||||
@Override
|
||||
public ConfigScreenFactory<?> getModConfigScreenFactory() {
|
||||
return ConfigScreen::new;
|
||||
}
|
||||
}
|
|
@ -0,0 +1,23 @@
|
|||
package codes.ztereohype.nicerskies.gui.widget;
|
||||
|
||||
import com.mojang.blaze3d.vertex.PoseStack;
|
||||
import net.minecraft.client.gui.GuiComponent;
|
||||
import net.minecraft.client.gui.components.Widget;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
|
||||
public class Separator extends GuiComponent implements Widget {
|
||||
private final int x;
|
||||
private final int y;
|
||||
private final int height;
|
||||
|
||||
public Separator(int x, int y, int height) {
|
||||
this.x = x;
|
||||
this.y = y;
|
||||
this.height = height;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void render(@NotNull PoseStack poseStack, int mouseX, int mouseY, float partialTick) {
|
||||
fill(poseStack, x, y, x + 1, y + height, 0xFFFFFFFF);
|
||||
}
|
||||
}
|
|
@ -0,0 +1,17 @@
|
|||
package codes.ztereohype.nicerskies.mixin;
|
||||
|
||||
import codes.ztereohype.nicerskies.NicerSkies;
|
||||
import codes.ztereohype.nicerskies.core.NebulaSeedManager;
|
||||
import net.minecraft.client.Minecraft;
|
||||
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(Minecraft.class)
|
||||
public class MinecraftMixin {
|
||||
@Inject(at = @At("TAIL"), method = "setLevel")
|
||||
private void onWorldLoad(CallbackInfo ci) {
|
||||
NicerSkies.skyManager.generateSky(NebulaSeedManager.getSeed());
|
||||
}
|
||||
}
|
|
@ -0,0 +1,38 @@
|
|||
package codes.ztereohype.nicerskies.mixin;
|
||||
|
||||
import codes.ztereohype.nicerskies.NicerSkies;
|
||||
import com.mojang.math.Vector3f;
|
||||
import net.minecraft.client.multiplayer.ClientLevel;
|
||||
import net.minecraft.client.renderer.LightTexture;
|
||||
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.LocalCapture;
|
||||
|
||||
@Mixin(LightTexture.class)
|
||||
public abstract class MixinLightTexutre {
|
||||
@Inject(
|
||||
method = "updateLightTexture",
|
||||
at = @At(value = "INVOKE", target = "Lcom/mojang/math/Vector3f;clamp(FF)V", shift = At.Shift.BEFORE, ordinal = 2),
|
||||
locals = LocalCapture.CAPTURE_FAILHARD
|
||||
)
|
||||
private void injectWarmLight(float partialTicks, CallbackInfo ci, ClientLevel clientLevel, float f, float g, float h, float i, float j, float l, float k, Vector3f vector3f, float m, Vector3f vector3f2, int n, int o, float p, float q, float r, float s, float t, boolean bl, float v, Vector3f vector3f5) {
|
||||
if (!NicerSkies.config.getLightmapTweaked()) return;
|
||||
Vector3f warmTint = new Vector3f(0.36F, 0.13F, -0.15F);
|
||||
|
||||
float warmness = o / 15f * // increase w/ blocklight
|
||||
(1f - vector3f.x() * (1 - n / 15f)) * // decrease in skylight w/ dayness
|
||||
Math.min((15 - o) / 9f, 1f); // decrease for the 3 highest block light levels
|
||||
|
||||
warmTint.mul(warmness);
|
||||
warmTint.add(1f, 1f, 1f);
|
||||
|
||||
Vector3f dramaticFactor = vector3f2.copy();
|
||||
dramaticFactor.mul(0.20f);
|
||||
dramaticFactor.add(0.80f, 0.80f, 0.81f);
|
||||
|
||||
vector3f2.mul(dramaticFactor.x(), dramaticFactor.y(), dramaticFactor.z());
|
||||
vector3f2.mul(warmTint.x(), warmTint.y(), warmTint.z());
|
||||
}
|
||||
}
|
|
@ -0,0 +1,65 @@
|
|||
package codes.ztereohype.nicerskies.mixin;
|
||||
|
||||
import codes.ztereohype.nicerskies.NicerSkies;
|
||||
import com.mojang.blaze3d.vertex.*;
|
||||
import com.mojang.math.Matrix4f;
|
||||
import net.minecraft.client.Camera;
|
||||
import net.minecraft.client.multiplayer.ClientLevel;
|
||||
import net.minecraft.client.renderer.GameRenderer;
|
||||
import net.minecraft.client.renderer.LevelRenderer;
|
||||
import net.minecraft.client.renderer.ShaderInstance;
|
||||
import net.minecraft.world.level.material.FogType;
|
||||
import net.minecraft.world.phys.Vec3;
|
||||
import org.spongepowered.asm.mixin.Mixin;
|
||||
import org.spongepowered.asm.mixin.Shadow;
|
||||
import org.spongepowered.asm.mixin.injection.At;
|
||||
import org.spongepowered.asm.mixin.injection.Inject;
|
||||
import org.spongepowered.asm.mixin.injection.ModifyArg;
|
||||
import org.spongepowered.asm.mixin.injection.callback.CallbackInfo;
|
||||
import org.spongepowered.asm.mixin.injection.callback.LocalCapture;
|
||||
|
||||
@Mixin(LevelRenderer.class)
|
||||
public abstract class MixinStarRendering {
|
||||
@Shadow private VertexBuffer starBuffer;
|
||||
@Shadow private int ticks;
|
||||
@Shadow private ClientLevel level;
|
||||
|
||||
@Inject(at = @At("HEAD"), method = "createStars", cancellable = true)
|
||||
private void generateStars(CallbackInfo ci) {
|
||||
starBuffer = new VertexBuffer();
|
||||
|
||||
BufferBuilder builder = Tesselator.getInstance().getBuilder();
|
||||
builder.begin(VertexFormat.Mode.QUADS, DefaultVertexFormat.POSITION_COLOR);
|
||||
|
||||
starBuffer.bind();
|
||||
starBuffer.upload(builder.end());
|
||||
|
||||
ci.cancel();
|
||||
}
|
||||
|
||||
@Inject(at = @At("HEAD"), method = "tick")
|
||||
private void tickStars(CallbackInfo ci) {
|
||||
if (!NicerSkies.config.getTwinklingStars() && NicerSkies.skyManager.isInitialized()) return;
|
||||
if (this.level.getStarBrightness(0) < 0.0F) return;
|
||||
NicerSkies.skyManager.tick(ticks, starBuffer);
|
||||
}
|
||||
|
||||
@ModifyArg(
|
||||
method = "renderSky",
|
||||
at = @At(value = "INVOKE", target = "Lcom/mojang/blaze3d/vertex/VertexBuffer;drawWithShader(Lcom/mojang/math/Matrix4f;Lcom/mojang/math/Matrix4f;Lnet/minecraft/client/renderer/ShaderInstance;)V", ordinal = 1),
|
||||
index = 2
|
||||
)
|
||||
private ShaderInstance injectStarColour(ShaderInstance shaderInstance) {
|
||||
return GameRenderer.getPositionColorShader();
|
||||
}
|
||||
|
||||
@Inject(
|
||||
method = "renderSky",
|
||||
at = @At(value = "INVOKE", target = "Lcom/mojang/blaze3d/systems/RenderSystem;disableTexture()V", ordinal = 2, shift = At.Shift.AFTER),
|
||||
locals = LocalCapture.CAPTURE_FAILHARD
|
||||
)
|
||||
private void drawSkybox(PoseStack poseStack, Matrix4f projectionMatrix, float partialTick, Camera camera, boolean bl, Runnable skyFogSetup, CallbackInfo ci, FogType fogType, Vec3 vec3, float f, float g, float h, BufferBuilder bufferBuilder, ShaderInstance shaderInstance, float[] fs, float i, Matrix4f matrix4f2, float k, int r, int s, int m, float t, float o, float p, float q) {
|
||||
if (!NicerSkies.config.getNebulas() || !NicerSkies.skyManager.isInitialized()) return;
|
||||
NicerSkies.skyManager.getSkybox().render(poseStack, projectionMatrix);
|
||||
}
|
||||
}
|
|
@ -0,0 +1,12 @@
|
|||
package codes.ztereohype.nicerskies.mixin.debug;
|
||||
|
||||
import com.mojang.blaze3d.platform.NativeImage;
|
||||
import net.minecraft.client.renderer.LightTexture;
|
||||
import org.spongepowered.asm.mixin.Mixin;
|
||||
import org.spongepowered.asm.mixin.gen.Accessor;
|
||||
|
||||
@Mixin(LightTexture.class)
|
||||
public interface LightTextureInvoker {
|
||||
@Accessor
|
||||
NativeImage getLightPixels();
|
||||
}
|
|
@ -0,0 +1,39 @@
|
|||
package codes.ztereohype.nicerskies.mixin.debug;
|
||||
|
||||
import com.mojang.blaze3d.platform.NativeImage;
|
||||
import com.mojang.blaze3d.vertex.PoseStack;
|
||||
import net.minecraft.client.Minecraft;
|
||||
import net.minecraft.client.gui.GuiComponent;
|
||||
import net.minecraft.client.gui.components.DebugScreenOverlay;
|
||||
import org.spongepowered.asm.mixin.Final;
|
||||
import org.spongepowered.asm.mixin.Mixin;
|
||||
import org.spongepowered.asm.mixin.Shadow;
|
||||
import org.spongepowered.asm.mixin.injection.At;
|
||||
import org.spongepowered.asm.mixin.injection.Inject;
|
||||
import org.spongepowered.asm.mixin.injection.callback.CallbackInfo;
|
||||
|
||||
@Mixin(DebugScreenOverlay.class)
|
||||
public abstract class MixinDebug {
|
||||
@Final @Shadow private Minecraft minecraft;
|
||||
|
||||
@Inject(method = "render(Lcom/mojang/blaze3d/vertex/PoseStack;)V", at = @At("HEAD"))
|
||||
private void injectRender(PoseStack poseStack, CallbackInfo ci) {
|
||||
int pixelSize = 6;
|
||||
|
||||
NativeImage lightPixels = ((LightTextureInvoker) minecraft.gameRenderer.lightTexture()).getLightPixels();
|
||||
for (int x = 0; x < lightPixels.getWidth(); x++) {
|
||||
for (int y = 0; y < lightPixels.getHeight(); y++) {
|
||||
int colour = lightPixels.getPixelRGBA(x, y);
|
||||
|
||||
int b = colour & 0xFF;
|
||||
int g = colour >> 8 & 0xFF;
|
||||
int r = colour >> 16 & 0xFF;
|
||||
|
||||
int xCoord = minecraft.getWindow().getGuiScaledWidth() - (x * pixelSize);
|
||||
int yCoord = minecraft.getWindow().getGuiScaledHeight() - (y * pixelSize);
|
||||
|
||||
GuiComponent.fill(poseStack, xCoord, yCoord, xCoord + pixelSize, yCoord + pixelSize, 0xFF000000 | b << 16 | g << 8 | r);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,21 @@
|
|||
package codes.ztereohype.nicerskies.mixin.debug;
|
||||
|
||||
import codes.ztereohype.nicerskies.NicerSkies;
|
||||
import codes.ztereohype.nicerskies.core.NebulaSeedManager;
|
||||
import net.minecraft.client.KeyboardHandler;
|
||||
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(KeyboardHandler.class)
|
||||
public class MixinKeyboardHandler {
|
||||
@Inject(at = @At("HEAD"), method = "keyPress")
|
||||
private void printKey(long windowPointer, int key, int scanCode, int action, int modifiers, CallbackInfo ci) {
|
||||
// \ key, keydown action
|
||||
if (key == 92 && action == 1) {
|
||||
NicerSkies.skyManager.generateSky(NebulaSeedManager.getSeed());
|
||||
// NicerSkies.toggle = !NicerSkies.toggle;
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,70 @@
|
|||
package codes.ztereohype.nicerskies.sky;
|
||||
|
||||
import codes.ztereohype.nicerskies.NicerSkies;
|
||||
import codes.ztereohype.nicerskies.config.ConfigManager;
|
||||
import codes.ztereohype.nicerskies.core.Gradient;
|
||||
import codes.ztereohype.nicerskies.sky.nebula.NebulaSkyboxPainter;
|
||||
import codes.ztereohype.nicerskies.sky.nebula.Skybox;
|
||||
import codes.ztereohype.nicerskies.sky.star.Starbox;
|
||||
import com.mojang.blaze3d.vertex.VertexBuffer;
|
||||
import lombok.Getter;
|
||||
import net.minecraft.util.RandomSource;
|
||||
import net.minecraft.world.level.levelgen.synth.PerlinNoise;
|
||||
|
||||
import java.util.stream.IntStream;
|
||||
|
||||
public class SkyManager {
|
||||
private @Getter Starbox starbox;
|
||||
private @Getter Skybox skybox;
|
||||
private @Getter boolean isInitialized = false;
|
||||
|
||||
private final Gradient starGradient = new Gradient();
|
||||
private final Gradient nebulaGradient = new Gradient();
|
||||
// private final Gradient starryGradient = new Gradient();
|
||||
|
||||
public void generateSky(long seed) {
|
||||
ConfigManager cm = NicerSkies.config;
|
||||
|
||||
nebulaGradient.clear();
|
||||
starGradient.clear();
|
||||
|
||||
buildGradients();
|
||||
|
||||
RandomSource randomSource = RandomSource.create(seed); //todo: world seed/hash server ip
|
||||
|
||||
PerlinNoise perlinNoise = PerlinNoise.create(randomSource, IntStream.of(1, 2, 3, 4, 5));
|
||||
NebulaSkyboxPainter painter = new NebulaSkyboxPainter(perlinNoise, nebulaGradient, cm.getNebulaNoiseScale(), cm.getNebulaNoiseAmount(), cm.getNebulaBaseColourAmount());
|
||||
|
||||
// StarSkyboxPainter painter = new StarSkyboxPainter(perlinNoise, starryGradient);
|
||||
|
||||
this.starbox = new Starbox(randomSource, starGradient);
|
||||
this.skybox = new Skybox(painter);
|
||||
}
|
||||
|
||||
public void tick(int ticks, VertexBuffer starBuffer) {
|
||||
this.starbox.updateStars(ticks, starBuffer);
|
||||
this.isInitialized = true;
|
||||
}
|
||||
|
||||
public void buildGradients() {
|
||||
starGradient.add(0.0f, 255, 179, 97);
|
||||
starGradient.add(0.2f, 255, 249, 253);
|
||||
starGradient.add(1.0f, 175, 199, 255);
|
||||
|
||||
// nebulaGradient.add(0.21f, 255, 0, 0);
|
||||
|
||||
nebulaGradient.add(0.2f, 41, 98, 146);
|
||||
// nebulaGradient.add(0.2f, 0, 0, 0);
|
||||
nebulaGradient.add(0.5f, 120, 59, 93);
|
||||
nebulaGradient.add(0.7f, 209, 72, 103);
|
||||
nebulaGradient.add(0.8f, 255, 200, 123);
|
||||
// nebulaGradient.add(1.0f, 30, 20, 20);
|
||||
nebulaGradient.add(1.0f, 253, 243, 220);
|
||||
|
||||
// starryGradient.add(0.0f, 128, 128, 200);
|
||||
// nebula_gradient.add(0.4f, 128, 0, 0);
|
||||
// nebula_gradient.add(0.5f, 128, 0, 0);
|
||||
// nebula_gradient.add(0.7f, 128, 0, 0);
|
||||
// nebula_gradient.add(1.0f, 128, 128, 128);
|
||||
}
|
||||
}
|
|
@ -0,0 +1,74 @@
|
|||
package codes.ztereohype.nicerskies.sky.nebula;
|
||||
|
||||
import codes.ztereohype.nicerskies.core.Gradient;
|
||||
import net.minecraft.util.FastColor;
|
||||
import net.minecraft.util.Mth;
|
||||
import net.minecraft.world.level.levelgen.synth.PerlinNoise;
|
||||
|
||||
public class NebulaSkyboxPainter extends SkyboxPainter {
|
||||
private final float scalingFactor;
|
||||
private final float noiseAmount; // the amount of base noise to keep
|
||||
private final int baseColourStrength;
|
||||
|
||||
private final Gradient nebulaGradient;
|
||||
|
||||
public NebulaSkyboxPainter(PerlinNoise noise, Gradient nebulaGradient, float scalingFactor, float noiseAmount, int baseColourStrength) {
|
||||
super(noise);
|
||||
this.nebulaGradient = nebulaGradient;
|
||||
|
||||
this.scalingFactor = scalingFactor;
|
||||
this.noiseAmount = noiseAmount;
|
||||
this.baseColourStrength = baseColourStrength;
|
||||
}
|
||||
|
||||
@Override
|
||||
int getColour(float x, float y, float z) {
|
||||
// Get projection
|
||||
float[] projCoords = this.projectOnSphere(x, y, z);
|
||||
x = projCoords[0];
|
||||
y = projCoords[1];
|
||||
z = projCoords[2];
|
||||
|
||||
// Get offset
|
||||
float offset = (float) noise.getValue(x * scalingFactor * 3, y * scalingFactor * 3, z * scalingFactor * 3);
|
||||
x = Mth.clamp(x + offset / 5f, -1f, 1f);
|
||||
y = Mth.clamp(y + offset / 5f, -1f, 1f);
|
||||
z = Mth.clamp(z + offset / 5f, -1f, 1f);
|
||||
|
||||
// Value of noise at coord, 0..1
|
||||
double noiseValue = Mth.clamp(noise.getValue(x * scalingFactor, y * scalingFactor, z * scalingFactor) + 0.5, 0, 1);
|
||||
|
||||
// Value to be subtracted from noise at coord, 0..1
|
||||
double subtractionValue = Mth.clamp(noise.getOctaveNoise(1)
|
||||
.noise(x * scalingFactor, y * scalingFactor, z * scalingFactor) + 0.5, 0D, 1D);
|
||||
|
||||
double[] ds = new double[3];
|
||||
noise.getOctaveNoise(0).noiseWithDerivative(x * scalingFactor, y * scalingFactor, z * scalingFactor, ds);
|
||||
|
||||
// Find a base background colour to use (xyz interpoaltion across sky, gamer mode)
|
||||
int baseB = (int) ((x / 2 + 0.5) * baseColourStrength);
|
||||
int baseG = (int) ((y / 2 + 0.5) * baseColourStrength);
|
||||
int baseR = (int) ((z / 2 + 0.5) * baseColourStrength);
|
||||
|
||||
// Turn off nebula rendering if noiseAmount is 0. (user expected behaviour)
|
||||
double nebulaFactor;
|
||||
if (noiseAmount != 0) {
|
||||
nebulaFactor = (Mth.clamp((noiseValue * (1D / noiseAmount) - (1D / noiseAmount - 1)), 0, 0.99));
|
||||
} else {
|
||||
nebulaFactor = 0;
|
||||
}
|
||||
|
||||
int[] nebula = nebulaGradient.getAt(nebulaFactor);
|
||||
double bgFactor = Mth.clamp(Math.log10(-nebulaFactor + 1) + 1, 0, 1);
|
||||
|
||||
// todo: try and reduce brownish colours by reducing the green channel smoothly [failed attempt]
|
||||
|
||||
int r = Mth.clamp((int) ((nebulaFactor * nebula[0]) + baseR * bgFactor) - (int) (ds[0] * nebulaFactor * 128), 0, 255);
|
||||
int g = Mth.clamp((int) ((nebulaFactor * nebula[1]) + baseG * bgFactor) - (int) (ds[1] * nebulaFactor * 64 * subtractionValue), 0, 255);
|
||||
int b = Mth.clamp((int) ((nebulaFactor * nebula[2]) + baseB * bgFactor) - (int) (ds[2] * nebulaFactor * 128), 0, 255);
|
||||
|
||||
int alpha = Mth.clamp((int) ((1 - bgFactor) * 255), 50, 255);
|
||||
|
||||
return FastColor.ARGB32.color(alpha, b, g, r);
|
||||
}
|
||||
}
|
174
src/main/java/codes/ztereohype/nicerskies/sky/nebula/Skybox.java
Normal file
174
src/main/java/codes/ztereohype/nicerskies/sky/nebula/Skybox.java
Normal file
|
@ -0,0 +1,174 @@
|
|||
package codes.ztereohype.nicerskies.sky.nebula;
|
||||
|
||||
import codes.ztereohype.nicerskies.NicerSkies;
|
||||
import com.mojang.blaze3d.platform.NativeImage;
|
||||
import com.mojang.blaze3d.systems.RenderSystem;
|
||||
import com.mojang.blaze3d.vertex.*;
|
||||
import com.mojang.math.Matrix4f;
|
||||
import lombok.Getter;
|
||||
import net.minecraft.client.Minecraft;
|
||||
import net.minecraft.client.multiplayer.ClientLevel;
|
||||
import net.minecraft.client.renderer.GameRenderer;
|
||||
import net.minecraft.client.renderer.texture.DynamicTexture;
|
||||
import net.minecraft.util.Mth;
|
||||
|
||||
public class Skybox {
|
||||
public static final int RESOLUTION = 512;
|
||||
|
||||
private final DynamicTexture skyTexture = new DynamicTexture(RESOLUTION * 4, RESOLUTION * 4, false);
|
||||
|
||||
private final @Getter VertexBuffer skyboxBuffer = new VertexBuffer();
|
||||
|
||||
public Skybox(SkyboxPainter painter) {
|
||||
generateVertices();
|
||||
paint(painter);
|
||||
}
|
||||
|
||||
@SuppressWarnings("ConstantConditions")
|
||||
public void render(PoseStack poseStack, Matrix4f projectionMatrix) {
|
||||
RenderSystem.setShader(GameRenderer::getPositionTexShader);
|
||||
RenderSystem.setShaderTexture(0, skyTexture.getId());
|
||||
|
||||
float alpha = getSkyboxBrightness(Minecraft.getInstance().level);
|
||||
|
||||
RenderSystem.setShaderColor(1.0F, 1.0F, 1.0F, alpha);
|
||||
|
||||
this.skyboxBuffer.bind();
|
||||
this.skyboxBuffer.drawWithShader(poseStack.last()
|
||||
.pose(), projectionMatrix, GameRenderer.getPositionTexShader());
|
||||
}
|
||||
|
||||
// todo: maybe multithread the hecc out of the generation to sped up the loading time
|
||||
public void paint(SkyboxPainter painter) {
|
||||
NativeImage skyNativeTex = this.skyTexture.getPixels();
|
||||
|
||||
// top face
|
||||
for (int texY = 0; texY < RESOLUTION; texY++) {
|
||||
for (int texX = 0; texX < RESOLUTION; texX++) {
|
||||
float x = (texX / (float) RESOLUTION) * 2 - 1;
|
||||
float y = 1;
|
||||
float z = (texY / (float) RESOLUTION) * 2 - 1;
|
||||
|
||||
skyNativeTex.setPixelRGBA(texX + 2 * RESOLUTION, texY, painter.getColour(x, y, z));
|
||||
}
|
||||
}
|
||||
|
||||
// bottom face
|
||||
for (int texY = 0; texY < RESOLUTION; texY++) {
|
||||
for (int texX = 0; texX < RESOLUTION; texX++) {
|
||||
float x = (texX / (float) RESOLUTION) * 2 - 1;
|
||||
float y = -1;
|
||||
float z = (texY / (float) RESOLUTION) * 2 - 1;
|
||||
|
||||
skyNativeTex.setPixelRGBA(texX + 2 * RESOLUTION, texY + 2 * RESOLUTION, painter.getColour(x, y, z));
|
||||
}
|
||||
}
|
||||
|
||||
// -x face
|
||||
for (int texY = 0; texY < RESOLUTION; texY++) {
|
||||
for (int texX = 0; texX < RESOLUTION; texX++) {
|
||||
float x = -1;
|
||||
float y = (texY / (float) RESOLUTION) * 2 - 1;
|
||||
float z = (texX / (float) RESOLUTION) * 2 - 1;
|
||||
|
||||
skyNativeTex.setPixelRGBA(texX, texY + RESOLUTION, painter.getColour(x, y, z));
|
||||
}
|
||||
}
|
||||
|
||||
// +x face
|
||||
for (int texY = 0; texY < RESOLUTION; texY++) {
|
||||
for (int texX = 0; texX < RESOLUTION; texX++) {
|
||||
float x = 1;
|
||||
float y = (texY / (float) RESOLUTION) * 2 - 1;
|
||||
float z = (texX / (float) RESOLUTION) * 2 - 1;
|
||||
|
||||
skyNativeTex.setPixelRGBA(texX + 2 * RESOLUTION, texY + RESOLUTION, painter.getColour(x, y, z));
|
||||
}
|
||||
}
|
||||
|
||||
// +z face
|
||||
for (int texY = 0; texY < RESOLUTION; texY++) {
|
||||
for (int texX = 0; texX < RESOLUTION; texX++) {
|
||||
float x = (texX / (float) RESOLUTION) * 2 - 1;
|
||||
float y = (texY / (float) RESOLUTION) * 2 - 1;
|
||||
float z = 1;
|
||||
|
||||
skyNativeTex.setPixelRGBA(texX + RESOLUTION, texY + RESOLUTION, painter.getColour(x, y, z));
|
||||
}
|
||||
}
|
||||
|
||||
// -z face
|
||||
for (int texY = 0; texY < RESOLUTION; texY++) {
|
||||
for (int texX = 0; texX < RESOLUTION; texX++) {
|
||||
float x = (texX / (float) RESOLUTION) * 2 - 1;
|
||||
float y = (texY / (float) RESOLUTION) * 2 - 1;
|
||||
float z = -1;
|
||||
|
||||
skyNativeTex.setPixelRGBA(texX + 3 * RESOLUTION, texY + RESOLUTION, painter.getColour(x, y, z));
|
||||
}
|
||||
}
|
||||
|
||||
this.skyTexture.upload();
|
||||
}
|
||||
|
||||
private void generateVertices() {
|
||||
BufferBuilder skyboxBuilder = Tesselator.getInstance().getBuilder();
|
||||
skyboxBuilder.begin(VertexFormat.Mode.QUADS, DefaultVertexFormat.POSITION_TEX);
|
||||
|
||||
// +z face
|
||||
skyboxBuilder.vertex(-80F, -80F, 80F).uv(0.25f, 0.25f).endVertex();
|
||||
skyboxBuilder.vertex(-80F, 80F, 80F).uv(0.25f, 0.5f).endVertex();
|
||||
skyboxBuilder.vertex(80F, 80F, 80F).uv(0.5f, 0.5f).endVertex();
|
||||
skyboxBuilder.vertex(80F, -80F, 80F).uv(0.5f, 0.25f).endVertex();
|
||||
|
||||
// -z face
|
||||
skyboxBuilder.vertex(-80F, -80F, -80F).uv(0.75f, 0.25f).endVertex();
|
||||
skyboxBuilder.vertex(80F, -80F, -80F).uv(1f, 0.25f).endVertex();
|
||||
skyboxBuilder.vertex(80F, 80F, -80F).uv(1f, 0.5f).endVertex();
|
||||
skyboxBuilder.vertex(-80F, 80F, -80F).uv(0.75f, 0.5f).endVertex();
|
||||
|
||||
// bottom face
|
||||
skyboxBuilder.vertex(-80F, -80F, -80F).uv(0.5f, 0.5f).endVertex();
|
||||
skyboxBuilder.vertex(-80F, -80F, 80F).uv(0.5f, 0.75f).endVertex();
|
||||
skyboxBuilder.vertex(80F, -80F, 80F).uv(0.75f, 0.75f).endVertex();
|
||||
skyboxBuilder.vertex(80F, -80F, -80F).uv(0.75f, 0.5f).endVertex();
|
||||
|
||||
// skyboxBuilder.vertex(-1F, -1F, -1F).uv(0f, 0f).endVertex();
|
||||
// skyboxBuilder.vertex(-1F, -1F, 1F).uv(0f, 1f).endVertex();
|
||||
// skyboxBuilder.vertex(1F, -1F, 1F).uv(1f, 1f).endVertex();
|
||||
// skyboxBuilder.vertex(1F, -1F, -1F).uv(1f, 0f).endVertex();
|
||||
|
||||
// top face
|
||||
skyboxBuilder.vertex(-80F, 80F, -80F).uv(0.5f, 0f).endVertex();
|
||||
skyboxBuilder.vertex(80F, 80F, -80F).uv(0.75f, 0f).endVertex();
|
||||
skyboxBuilder.vertex(80F, 80F, 80F).uv(0.75f, 0.25f).endVertex();
|
||||
skyboxBuilder.vertex(-80F, 80F, 80F).uv(0.5f, 0.25f).endVertex();
|
||||
|
||||
// +x face
|
||||
skyboxBuilder.vertex(80F, -80F, -80F).uv(0.5f, 0.25f).endVertex();
|
||||
skyboxBuilder.vertex(80F, -80F, 80F).uv(0.75f, 0.25f).endVertex();
|
||||
skyboxBuilder.vertex(80F, 80F, 80F).uv(0.75f, 0.5f).endVertex();
|
||||
skyboxBuilder.vertex(80F, 80F, -80F).uv(0.5f, 0.5f).endVertex();
|
||||
|
||||
// -x face
|
||||
skyboxBuilder.vertex(-80F, -80F, -80F).uv(0f, 0.25f).endVertex();
|
||||
skyboxBuilder.vertex(-80F, 80F, -80F).uv(0f, 0.5f).endVertex();
|
||||
skyboxBuilder.vertex(-80F, 80F, 80F).uv(0.25f, 0.5f).endVertex();
|
||||
skyboxBuilder.vertex(-80F, -80F, 80F).uv(0.25f, 0.25f).endVertex();
|
||||
|
||||
skyboxBuffer.bind();
|
||||
skyboxBuffer.upload(skyboxBuilder.end());
|
||||
}
|
||||
|
||||
private float getSkyboxBrightness(ClientLevel level) {
|
||||
float config = NicerSkies.config.getNebulaStrength();
|
||||
|
||||
float timeOfDay = level.getTimeOfDay(0);
|
||||
float nightness = 1.0F - (Mth.cos(timeOfDay * (float) (Math.PI * 2)) * 4.0F + 0.5F);
|
||||
nightness = Mth.clamp(nightness, 0.0F, 1.0F);
|
||||
|
||||
float rain = level.getRainLevel(0);
|
||||
|
||||
return nightness * (1f - rain) * config;
|
||||
}
|
||||
}
|
|
@ -0,0 +1,25 @@
|
|||
package codes.ztereohype.nicerskies.sky.nebula;
|
||||
|
||||
import net.minecraft.util.Mth;
|
||||
import net.minecraft.world.level.levelgen.synth.PerlinNoise;
|
||||
|
||||
public abstract class SkyboxPainter {
|
||||
protected final PerlinNoise noise;
|
||||
|
||||
SkyboxPainter(PerlinNoise noise) {
|
||||
this.noise = noise;
|
||||
}
|
||||
|
||||
abstract int getColour(float x, float y, float z);
|
||||
|
||||
public float[] projectOnSphere(float x, float y, float z) {
|
||||
float invDistance = Mth.fastInvSqrt(x * x + y * y + z * z);
|
||||
|
||||
//divide by distance to get projection on sphere (shorten the vector)
|
||||
x *= invDistance;
|
||||
y *= invDistance;
|
||||
z *= invDistance;
|
||||
|
||||
return new float[] {x, y, z};
|
||||
}
|
||||
}
|
|
@ -0,0 +1,52 @@
|
|||
package codes.ztereohype.nicerskies.sky.nebula;
|
||||
|
||||
import codes.ztereohype.nicerskies.core.Gradient;
|
||||
import net.minecraft.util.FastColor;
|
||||
import net.minecraft.util.Mth;
|
||||
import net.minecraft.world.level.levelgen.synth.PerlinNoise;
|
||||
|
||||
public class StarSkyboxPainter extends SkyboxPainter {
|
||||
private static final float SCALING_FACTOR = 1.5f;
|
||||
private static final float BASE_NOISE_AMOUNT = 0.45f; // the amount of base noise to keep
|
||||
|
||||
private final Gradient starryGradient;
|
||||
|
||||
public StarSkyboxPainter(PerlinNoise noise, Gradient starryGradient) {
|
||||
super(noise);
|
||||
this.starryGradient = starryGradient;
|
||||
}
|
||||
|
||||
@Override
|
||||
int getColour(float x, float y, float z) {
|
||||
float[] projCoords = this.projectOnSphere(x, y, z);
|
||||
x = projCoords[0];
|
||||
y = projCoords[1];
|
||||
z = projCoords[2];
|
||||
|
||||
// float offset = (float) noise.getValue(x * SCALING_FACTOR * 3, y * SCALING_FACTOR * 3, z * SCALING_FACTOR * 3);
|
||||
//
|
||||
// x += offset/10f;
|
||||
// y += offset/10f;
|
||||
// z += offset/10f;
|
||||
|
||||
// 0..1
|
||||
double noiseValue = Mth.clamp(noise.getValue(x * SCALING_FACTOR, y * SCALING_FACTOR, z * SCALING_FACTOR) + 0.5, 0D, 1D);
|
||||
|
||||
// 0..1
|
||||
// double subtractionValue = Mth.clamp(noise.getOctaveNoise(1).noise(x * SCALING_FACTOR, y * SCALING_FACTOR, z * SCALING_FACTOR) + 0.5, 0D, 1D);
|
||||
|
||||
// double[] derivates = new double[3];
|
||||
// noise.getOctaveNoise(0).noiseWithDerivative(x * SCALING_FACTOR, y * SCALING_FACTOR, z * SCALING_FACTOR, derivates);
|
||||
// double maxDerivative = Mth.clamp(Math.max(Math.max(derivates[0], derivates[1]), derivates[2]) * 0.5 + 0.5, 0, 0);
|
||||
|
||||
int alpha = (int) (Mth.clamp((noiseValue * (1D / BASE_NOISE_AMOUNT) - (1D / BASE_NOISE_AMOUNT - 1)) * 35D, 1D, 255.99D)); // otherwise death occurs
|
||||
|
||||
// alpha = (int) Mth.clamp(alpha - subtractionValue * 128, 0, 255); //todo subtract colour channels separately
|
||||
|
||||
double colourValue = Mth.clamp((alpha / 255D), 0D, 1D);
|
||||
|
||||
int[] color = starryGradient.getAt(colourValue);
|
||||
|
||||
return FastColor.ARGB32.color(alpha, color[2], color[1], color[0]);
|
||||
}
|
||||
}
|
133
src/main/java/codes/ztereohype/nicerskies/sky/star/Star.java
Normal file
133
src/main/java/codes/ztereohype/nicerskies/sky/star/Star.java
Normal file
|
@ -0,0 +1,133 @@
|
|||
package codes.ztereohype.nicerskies.sky.star;
|
||||
|
||||
import com.mojang.blaze3d.vertex.BufferBuilder;
|
||||
import lombok.Getter;
|
||||
import net.minecraft.util.Mth;
|
||||
|
||||
public class Star {
|
||||
private final float xCoord;
|
||||
private final float yCoord;
|
||||
private final float zCoord;
|
||||
|
||||
private final float longitudeSin;
|
||||
private final float longitudeCos;
|
||||
|
||||
private final float latitudeSin;
|
||||
private final float latitudeCos;
|
||||
|
||||
private final float resizeSpeed;
|
||||
private final float spinSpeed;
|
||||
|
||||
private final float minRadius;
|
||||
private final float maxRadius;
|
||||
|
||||
private final int r;
|
||||
private final int g;
|
||||
private final int b;
|
||||
|
||||
private float currentAngle;
|
||||
private @Getter float currentRadius;
|
||||
|
||||
public Star(float randX, float randY, float randZ, float size, int[] color, float resizeSpeed, float spinSpeed) {
|
||||
this.r = color[0];
|
||||
this.g = color[1];
|
||||
this.b = color[2];
|
||||
|
||||
float invsqrtDistance = Mth.fastInvSqrt(randX * randX + randY * randY + randZ * randZ);
|
||||
this.xCoord = randX * invsqrtDistance * 100.0F;
|
||||
this.yCoord = randY * invsqrtDistance * 100.0F;
|
||||
this.zCoord = randZ * invsqrtDistance * 100.0F;
|
||||
|
||||
double polarAngle = Math.atan2(randX, randZ);
|
||||
this.longitudeSin = (float) Math.sin(polarAngle);
|
||||
this.longitudeCos = (float) Math.cos(polarAngle);
|
||||
|
||||
double proj = Math.atan2(Math.sqrt(randX * randX + randZ * randZ), randY);
|
||||
this.latitudeSin = (float) Math.sin(proj);
|
||||
this.latitudeCos = (float) Math.cos(proj);
|
||||
|
||||
this.spinSpeed = spinSpeed;
|
||||
this.resizeSpeed = resizeSpeed;
|
||||
|
||||
this.minRadius = size - 0.15f;
|
||||
this.maxRadius = size + 0.15f;
|
||||
this.currentRadius = size;
|
||||
this.currentAngle = (spinSpeed + 0.01f) * 628.3f; // random angle from 0 to 2π
|
||||
}
|
||||
|
||||
public void tick(int ticks) {
|
||||
currentAngle += spinSpeed;
|
||||
currentRadius = Mth.lerp(Mth.sin(ticks * resizeSpeed), minRadius, maxRadius);
|
||||
}
|
||||
|
||||
//return 4*3 coords for 4 vertices
|
||||
// public void setVertices(BufferBuilder bufferBuilder) {
|
||||
// float cosRot = Mth.cos(currentAngle);
|
||||
// float sinRot = Mth.sin(currentAngle);
|
||||
//
|
||||
// for (int v = 0; v < 4; ++v) {
|
||||
// // shift the vector to the 4 corners:
|
||||
// // vec 0, 1 --> -rad; vec 2, 3 --> +rad
|
||||
// float xShift = ((v & 2) - 1) * currentRadius;
|
||||
// // vec 1, 2 --> +rad; vec 3, 0 --> -rad
|
||||
// float yShift = (((v + 1) & 2) - 1) * currentRadius;
|
||||
//
|
||||
// float unprojectedVerticalOffset = xShift * cosRot - yShift * sinRot;
|
||||
// float unprojectedHorizontalOffset = yShift * cosRot + xShift * sinRot;
|
||||
// float latitudeCorrectedUnprojectedVerticalOffset = -unprojectedVerticalOffset * latitudeCos; // max negative +2pi, max positive -2pi
|
||||
//
|
||||
// float yOffset = unprojectedVerticalOffset * latitudeSin; // at ±pi should be max, squished at poles
|
||||
// float xOffset = latitudeCorrectedUnprojectedVerticalOffset * longitudeSin - unprojectedHorizontalOffset * longitudeCos;
|
||||
// float zOffset = unprojectedHorizontalOffset * longitudeSin + latitudeCorrectedUnprojectedVerticalOffset * longitudeCos;
|
||||
//
|
||||
// bufferBuilder.vertex(xCoord + xOffset, yCoord + yOffset, zCoord + zOffset)
|
||||
// .color(r, g, b, 255)
|
||||
// .endVertex();
|
||||
// }
|
||||
// }
|
||||
|
||||
public void setVertices(BufferBuilder bufferBuilder) {
|
||||
float horizontalVertexDistance = currentRadius * Mth.cos(currentAngle);
|
||||
float verticalVertexDistance = currentRadius * Mth.sin(currentAngle);
|
||||
|
||||
float firstVertexDistance = -horizontalVertexDistance + verticalVertexDistance;
|
||||
float secondVertexDistance = -horizontalVertexDistance - verticalVertexDistance;
|
||||
float thirdVertexDistance = horizontalVertexDistance - verticalVertexDistance;
|
||||
float fourthVertexDistance = horizontalVertexDistance + verticalVertexDistance;
|
||||
|
||||
float ae1 = thirdVertexDistance * latitudeCos;
|
||||
float ae2 = fourthVertexDistance * latitudeCos;
|
||||
float ae3 = firstVertexDistance * latitudeCos;
|
||||
float ae4 = secondVertexDistance * latitudeCos;
|
||||
|
||||
// 0
|
||||
bufferBuilder.vertex(xCoord + ae1 * longitudeSin - secondVertexDistance * longitudeCos, yCoord + firstVertexDistance * latitudeSin, zCoord + secondVertexDistance * longitudeSin + ae1 * longitudeCos)
|
||||
.color(r, g, b, 255)
|
||||
.endVertex();
|
||||
// 1
|
||||
bufferBuilder.vertex(xCoord + ae2 * longitudeSin - thirdVertexDistance * longitudeCos, yCoord + secondVertexDistance * latitudeSin, zCoord + thirdVertexDistance * longitudeSin + ae2 * longitudeCos)
|
||||
.color(r, g, b, 255)
|
||||
.endVertex();
|
||||
|
||||
bufferBuilder.vertex(xCoord + ae3 * longitudeSin - fourthVertexDistance * longitudeCos, yCoord + thirdVertexDistance * latitudeSin, zCoord + fourthVertexDistance * longitudeSin + ae3 * longitudeCos)
|
||||
.color(r, g, b, 255)
|
||||
.endVertex();
|
||||
|
||||
// 3
|
||||
bufferBuilder.vertex(xCoord + ae4 * longitudeSin - firstVertexDistance * longitudeCos, yCoord + fourthVertexDistance * latitudeSin, zCoord + firstVertexDistance * longitudeSin + ae4 * longitudeCos)
|
||||
.color(r, g, b, 255)
|
||||
.endVertex();
|
||||
// // 1
|
||||
// bufferBuilder.vertex(xCoord + ae2 * longitudeSin - thirdVertexDistance * longitudeCos, yCoord + secondVertexDistance * latitudeSin, zCoord + thirdVertexDistance * longitudeSin + ae2 * longitudeCos)
|
||||
// .color(r, g, b, 255)
|
||||
// .endVertex();
|
||||
// // 2
|
||||
// bufferBuilder.vertex(xCoord + ae3 * longitudeSin - fourthVertexDistance * longitudeCos, yCoord + thirdVertexDistance * latitudeSin, zCoord + fourthVertexDistance * longitudeSin + ae3 * longitudeCos)
|
||||
// .color(r, g, b, 255)
|
||||
// .endVertex();
|
||||
// // 3
|
||||
// bufferBuilder.vertex(xCoord + ae4 * longitudeSin - firstVertexDistance * longitudeCos, yCoord + fourthVertexDistance * latitudeSin, zCoord + firstVertexDistance * longitudeSin + ae4 * longitudeCos)
|
||||
// .color(r, g, b, 255)
|
||||
// .endVertex();
|
||||
}
|
||||
}
|
|
@ -0,0 +1,63 @@
|
|||
package codes.ztereohype.nicerskies.sky.star;
|
||||
|
||||
import codes.ztereohype.nicerskies.core.Gradient;
|
||||
import com.mojang.blaze3d.vertex.*;
|
||||
import net.minecraft.util.RandomSource;
|
||||
import net.minecraft.world.level.levelgen.synth.ImprovedNoise;
|
||||
|
||||
import java.util.ArrayList;
|
||||
|
||||
public class Starbox {
|
||||
private static final BufferBuilder STAR_BUFFER_BUILDER = Tesselator.getInstance().getBuilder();
|
||||
|
||||
private final int stars = 1500;
|
||||
private Gradient starGradient;
|
||||
|
||||
private ArrayList<Star> starList = new ArrayList<>();
|
||||
|
||||
public Starbox(RandomSource randomSource, Gradient starGradient) {
|
||||
this.generate(randomSource, starGradient);
|
||||
}
|
||||
|
||||
public void generate(RandomSource randomSource, Gradient starGradient) {
|
||||
starList.clear();
|
||||
this.starGradient = starGradient;
|
||||
generateStars(randomSource);
|
||||
}
|
||||
|
||||
private void generateStars(RandomSource randomSource) {
|
||||
ImprovedNoise noise = new ImprovedNoise(randomSource);
|
||||
|
||||
for (int i = 0; i < this.stars; ++i) {
|
||||
float randX = randomSource.nextFloat() * 2.0F - 1.0F;
|
||||
float randY = randomSource.nextFloat() * 2.0F - 1.0F;
|
||||
float randZ = randomSource.nextFloat() * 2.0F - 1.0F;
|
||||
|
||||
float resizeSpeed = 0.03f + randomSource.nextFloat() * 0.04f;
|
||||
float spinSpeed = randomSource.nextFloat() * 0.02f - 0.01f;
|
||||
|
||||
int[] starColor = starGradient.getAt(randomSource.nextFloat());
|
||||
|
||||
float starRadius = 0.15F + randomSource.nextFloat() * 0.15F;
|
||||
double starValue = noise.noise(randX * 2.5f, randY * 2.5f, randZ * 2.5f) + 0.5;
|
||||
|
||||
float squaredDistance = randX * randX + randY * randY + randZ * randZ;
|
||||
if (squaredDistance < 1.0 && squaredDistance > 0.01 && starValue > 0.2) {
|
||||
starList.add(new Star(randX, randY, randZ, starRadius, starColor, resizeSpeed, spinSpeed));
|
||||
} else --i;
|
||||
}
|
||||
}
|
||||
|
||||
public void updateStars(int ticks, VertexBuffer starBuffer) {
|
||||
STAR_BUFFER_BUILDER.begin(VertexFormat.Mode.QUADS, DefaultVertexFormat.POSITION_COLOR);
|
||||
|
||||
for (Star star : starList) {
|
||||
star.tick(ticks);
|
||||
star.setVertices(STAR_BUFFER_BUILDER);
|
||||
}
|
||||
|
||||
starBuffer.bind();
|
||||
starBuffer.upload(STAR_BUFFER_BUILDER.end());
|
||||
}
|
||||
}
|
||||
|
Loading…
Add table
Add a link
Reference in a new issue