diff --git a/build.gradle b/build.gradle index 5d8ac006b..b1fd3587d 100644 --- a/build.gradle +++ b/build.gradle @@ -24,10 +24,10 @@ plugins { id "de.undercouch.download" version "5.0.1" } -version '2.1.3-1.18.2' // Needs to be version specific -def nmsVersion = "1.18.2" -def apiVersion = '1.18' -def spigotJarVersion = '1.18.2-R0.1-SNAPSHOT' +version '2.2.1-1.19' // Needs to be version specific +def nmsVersion = "1.19" +def apiVersion = '1.19' +def spigotJarVersion = '1.19-R0.1-SNAPSHOT' def name = getRootProject().getName() // Defined in settings.gradle def main = 'com.volmit.iris.Iris' @@ -38,7 +38,7 @@ registerCustomOutputTask('Psycho', 'D://Dan/MinecraftDevelopment/server/plugins' registerCustomOutputTask('ArcaneArts', 'C://Users/arcane/Documents/development/server/plugins') registerCustomOutputTask('Coco', 'D://Documents/MC/plugins') registerCustomOutputTask('Strange', 'D://Servers/1.17 Test Server/plugins') -registerCustomOutputTask('Vatuu', 'D://Minecraft/Servers/1.18.2/plugins') +registerCustomOutputTask('Vatuu', 'D://Minecraft/Servers/1.19/plugins') // ========================== UNIX ============================== registerCustomOutputTaskUnix('CyberpwnLT', '/Users/danielmills/development/server/plugins') registerCustomOutputTaskUnix('PsychoLT', '/Users/brianfopiano/Desktop/REMOTES/RemoteMinecraft/plugins') @@ -122,20 +122,20 @@ configurations.all { */ dependencies { // Provided or Classpath - compileOnly 'org.projectlombok:lombok:1.18.22' - annotationProcessor 'org.projectlombok:lombok:1.18.22' - implementation 'org.spigotmc:spigot-api:1.18.2-R0.1-SNAPSHOT' + compileOnly 'org.projectlombok:lombok:1.18.24' + annotationProcessor 'org.projectlombok:lombok:1.18.24' + implementation 'org.spigotmc:spigot-api:1.19-R0.1-SNAPSHOT' implementation 'me.clip:placeholderapi:2.11.1' implementation 'io.th0rgal:oraxen:1.94.0' - implementation 'org.bukkit:craftbukkit:1.18.2-R0.1-SNAPSHOT:remapped-mojang' + implementation 'org.bukkit:craftbukkit:1.19-R0.1-SNAPSHOT:remapped-mojang' implementation 'com.github.LoneDev6:api-itemsadder:3.1.0b' // Shaded implementation 'com.dfsek:Paralithic:0.4.0' implementation 'io.papermc:paperlib:1.0.5' - implementation "net.kyori:adventure-text-minimessage:4.2.0-SNAPSHOT" - implementation 'net.kyori:adventure-platform-bukkit:4.0.1' // Dont upgrade yet - implementation 'net.kyori:adventure-api:4.9.3' // Dont upgrade yet + implementation "net.kyori:adventure-text-minimessage:4.11.0" + implementation 'net.kyori:adventure-platform-bukkit:4.1.0' + implementation 'net.kyori:adventure-api:4.11.0' // Dynamically Loaded implementation 'io.timeandspace:smoothie-map:2.0.2' @@ -267,6 +267,10 @@ task specialSourceRemap(type: JavaExec) tasks.compileJava.dependsOn(executeBuildTools) +compileJava { + options.encoding = "UTF-8" +} + task setup() { group("iris") diff --git a/src/main/java/com/volmit/iris/Iris.java b/src/main/java/com/volmit/iris/Iris.java index f3216a1e0..2ab745545 100644 --- a/src/main/java/com/volmit/iris/Iris.java +++ b/src/main/java/com/volmit/iris/Iris.java @@ -21,7 +21,6 @@ package com.volmit.iris; import com.google.gson.JsonObject; import com.google.gson.JsonParseException; import com.google.gson.JsonParser; -import com.google.gson.stream.JsonReader; import com.volmit.iris.core.IrisSettings; import com.volmit.iris.core.ServerConfigurator; import com.volmit.iris.core.link.*; diff --git a/src/main/java/com/volmit/iris/core/ServerConfigurator.java b/src/main/java/com/volmit/iris/core/ServerConfigurator.java index 4e3ae4950..0d08255e2 100644 --- a/src/main/java/com/volmit/iris/core/ServerConfigurator.java +++ b/src/main/java/com/volmit/iris/core/ServerConfigurator.java @@ -55,7 +55,7 @@ public class ServerConfigurator { } private static void increaseKeepAliveSpigot() throws IOException, InvalidConfigurationException { - File spigotConfig = new File("spigot.yml"); + File spigotConfig = new File("config/spigot.yml"); FileConfiguration f = new YamlConfiguration(); f.load(spigotConfig); long tt = f.getLong("settings.timeout-time"); @@ -69,15 +69,15 @@ public class ServerConfigurator { } private static void increasePaperWatchdog() throws IOException, InvalidConfigurationException { - File spigotConfig = new File("paper.yml"); + File spigotConfig = new File("config/paper-global.yml"); FileConfiguration f = new YamlConfiguration(); f.load(spigotConfig); - long tt = f.getLong("settings.watchdog.early-warning-delay"); + long tt = f.getLong("watchdog.early-warning-delay"); if(tt < TimeUnit.MINUTES.toMillis(3)) { Iris.warn("Updating paper.yml watchdog early-warning-delay: " + tt + " -> " + TimeUnit.MINUTES.toMillis(3) + " (3 minutes)"); Iris.warn("You can disable this change (autoconfigureServer) in Iris settings, then change back the value."); - f.set("settings.watchdog.early-warning-delay", TimeUnit.MINUTES.toMillis(3)); + f.set("watchdog.early-warning-delay", TimeUnit.MINUTES.toMillis(3)); f.save(spigotConfig); } } diff --git a/src/main/java/com/volmit/iris/core/commands/CommandIris.java b/src/main/java/com/volmit/iris/core/commands/CommandIris.java index 568137c4b..80c35e463 100644 --- a/src/main/java/com/volmit/iris/core/commands/CommandIris.java +++ b/src/main/java/com/volmit/iris/core/commands/CommandIris.java @@ -163,7 +163,7 @@ public class CommandIris implements DecreeExecutor { public void download( @Param(name = "pack", description = "The pack to download", defaultValue = "overworld", aliases = "project") String pack, - @Param(name = "branch", description = "The branch to download from", defaultValue = "master") + @Param(name = "branch", description = "The branch to download from", defaultValue = "main") String branch, @Param(name = "trim", description = "Whether or not to download a trimmed version (do not enable when editing)", defaultValue = "false") boolean trim, diff --git a/src/main/java/com/volmit/iris/core/commands/CommandObject.java b/src/main/java/com/volmit/iris/core/commands/CommandObject.java index c58cab46c..4f6c2d15e 100644 --- a/src/main/java/com/volmit/iris/core/commands/CommandObject.java +++ b/src/main/java/com/volmit/iris/core/commands/CommandObject.java @@ -18,7 +18,6 @@ package com.volmit.iris.core.commands; -import com.mojang.datafixers.util.Pair; import com.volmit.iris.Iris; import com.volmit.iris.core.link.WorldEditLink; import com.volmit.iris.core.loader.IrisData; diff --git a/src/main/java/com/volmit/iris/core/nms/INMS.java b/src/main/java/com/volmit/iris/core/nms/INMS.java index 4228dc965..89d7ab4ab 100644 --- a/src/main/java/com/volmit/iris/core/nms/INMS.java +++ b/src/main/java/com/volmit/iris/core/nms/INMS.java @@ -20,7 +20,7 @@ package com.volmit.iris.core.nms; import com.volmit.iris.Iris; import com.volmit.iris.core.IrisSettings; -import com.volmit.iris.core.nms.v18_2.NMSBinding18_2; +import com.volmit.iris.core.nms.v19_1.NMSBinding19_1; import com.volmit.iris.core.nms.v1X.NMSBinding1X; import com.volmit.iris.util.collection.KMap; import org.bukkit.Bukkit; @@ -28,7 +28,7 @@ import org.bukkit.Bukkit; public class INMS { //@builder private static final KMap> bindings = new KMap>() - .qput("v1_18_R2", NMSBinding18_2.class); + .qput("v1_19_R1", NMSBinding19_1.class); //@done private static final INMSBinding binding = bind(); diff --git a/src/main/java/com/volmit/iris/core/nms/NMSVersion.java b/src/main/java/com/volmit/iris/core/nms/NMSVersion.java index a4268495d..532562b20 100644 --- a/src/main/java/com/volmit/iris/core/nms/NMSVersion.java +++ b/src/main/java/com/volmit/iris/core/nms/NMSVersion.java @@ -24,6 +24,7 @@ import java.util.ArrayList; import java.util.List; public enum NMSVersion { + R1_19_1, R1_18_2, R1_18, R1_17, @@ -102,6 +103,9 @@ public enum NMSVersion { if(tryVersion("1_18_R2")) { return R1_18_2; } + if(tryVersion("1_19_R1")) { + return R1_19_1; + } return null; } diff --git a/src/main/java/com/volmit/iris/core/nms/v18_2/NMSBinding18_2.java b/src/main/java/com/volmit/iris/core/nms/v19_1/NMSBinding19_1.java similarity index 82% rename from src/main/java/com/volmit/iris/core/nms/v18_2/NMSBinding18_2.java rename to src/main/java/com/volmit/iris/core/nms/v19_1/NMSBinding19_1.java index 21316ce62..2e2713488 100644 --- a/src/main/java/com/volmit/iris/core/nms/v18_2/NMSBinding18_2.java +++ b/src/main/java/com/volmit/iris/core/nms/v19_1/NMSBinding19_1.java @@ -16,7 +16,7 @@ * along with this program. If not, see . */ -package com.volmit.iris.core.nms.v18_2; +package com.volmit.iris.core.nms.v19_1; import com.volmit.iris.Iris; @@ -39,10 +39,15 @@ import it.unimi.dsi.fastutil.objects.Object2IntMap; import net.minecraft.core.*; import net.minecraft.nbt.NbtIo; import net.minecraft.resources.ResourceLocation; +import net.minecraft.util.BitStorage; +import net.minecraft.util.Mth; import net.minecraft.world.level.block.Block; import net.minecraft.world.level.block.entity.BlockEntity; import net.minecraft.world.level.block.state.BlockState; import net.minecraft.world.level.chunk.ChunkAccess; +import net.minecraft.world.level.chunk.LevelChunkSection; +import net.minecraft.world.level.chunk.Palette; +import net.minecraft.world.level.chunk.PalettedContainer; import org.bukkit.Bukkit; import org.bukkit.Location; import org.bukkit.Material; @@ -50,9 +55,10 @@ import org.bukkit.World; import org.bukkit.block.Biome; import org.bukkit.block.data.BlockData; -import org.bukkit.craftbukkit.v1_18_R2.CraftServer; -import org.bukkit.craftbukkit.v1_18_R2.CraftWorld; -import org.bukkit.craftbukkit.v1_18_R2.block.data.CraftBlockData; + +import org.bukkit.craftbukkit.v1_19_R1.CraftServer; +import org.bukkit.craftbukkit.v1_19_R1.CraftWorld; +import org.bukkit.craftbukkit.v1_19_R1.block.data.CraftBlockData; import org.bukkit.entity.Entity; import org.bukkit.generator.ChunkGenerator; import org.jetbrains.annotations.NotNull; @@ -68,7 +74,7 @@ import java.util.Iterator; import java.util.List; import java.util.concurrent.atomic.AtomicInteger; -public class NMSBinding18_2 implements INMSBinding { +public class NMSBinding19_1 implements INMSBinding { private final KMap baseBiomeCache = new KMap<>(); private final BlockData AIR = Material.AIR.createBlockData(); @@ -231,13 +237,13 @@ public class NMSBinding18_2 implements INMSBinding { return v; } //noinspection unchecked - v = org.bukkit.craftbukkit.v1_18_R2.block.CraftBlock.biomeToBiomeBase((Registry) registry, biome); + v = org.bukkit.craftbukkit.v1_19_R1.block.CraftBlock.biomeToBiomeBase((Registry) registry, biome); if(v == null) { // Ok so there is this new biome name called "CUSTOM" in Paper's new releases. // But, this does NOT exist within CraftBukkit which makes it return an error. // So, we will just return the ID that the plains biome returns instead. //noinspection unchecked - return org.bukkit.craftbukkit.v1_18_R2.block.CraftBlock.biomeToBiomeBase((Registry) registry, Biome.PLAINS); + return org.bukkit.craftbukkit.v1_19_R1.block.CraftBlock.biomeToBiomeBase((Registry) registry, Biome.PLAINS); } baseBiomeCache.put(biome, v); return v; @@ -336,13 +342,46 @@ public class NMSBinding18_2 implements INMSBinding { public void forceBiomeInto(int x, int y, int z, Object somethingVeryDirty, ChunkGenerator.BiomeGrid chunk) { try { ChunkAccess s = (ChunkAccess) getFieldForBiomeStorage(chunk).get(chunk); - s.setBiome(x, y, z, (Holder) somethingVeryDirty); // probably not safe? it said it wanted a holder, so i made it a holder... + Holder biome = (Holder) somethingVeryDirty; + s.setBiome(x, y, z, biome); + /*int l = QuartPos.fromBlock(s.getMinBuildHeight()); + int i1 = l + QuartPos.fromBlock(s.getHeight()) - 1; + PalettedContainer> palette = getPalette(s, s.getSectionIndex(QuartPos.toBlock(Mth.clamp(y, l, i1)))); + int index = getPaletteIndex(x, y, z, s, palette); + int data = getPaletteDataId(palette, biome); + setPaletteData(palette, index, data);*/ } catch(IllegalAccessException e) { Iris.reportError(e); e.printStackTrace(); } } + private PalettedContainer> getPalette(ChunkAccess ca, int index) { + LevelChunkSection[] sections = fieldForClass(LevelChunkSection[].class, ChunkAccess.class, ca); + return fieldForClass(PalettedContainer.class, LevelChunkSection.class, sections[index]); + } + + private int getPaletteIndex(int x, int y, int z, ChunkAccess s, PalettedContainer palette) { + int l = QuartPos.fromBlock(s.getMinBuildHeight()); + int i1 = l + QuartPos.fromBlock(s.getHeight()) - 1; + int j1 = Mth.clamp(y, l, i1); + return fieldForClass(PalettedContainer.Strategy.class, PalettedContainer.class, palette).getIndex(x & 3, j1 & 3, z & 3); + } + + private > int getPaletteDataId(PalettedContainer palette, T data) throws ClassNotFoundException { + Class dataType = getClassType(PalettedContainer.class, 1); + Object paletteData = fieldFor(dataType, palette); + Palette fuckinFinally = fieldForClass(Palette.class,dataType, paletteData); + return fuckinFinally.idFor(data); + } + + private void setPaletteData(PalettedContainer palette, int index, int data) throws ClassNotFoundException { + Class dataType = getClassType(PalettedContainer.class, 1); + Object paletteData = fieldFor(dataType, palette); + BitStorage storage = fieldForClass(BitStorage.class, dataType, paletteData); + storage.set(index, data); + } + private Field getFieldForBiomeStorage(Object storage) { Field f = biomeStorageCache; @@ -404,7 +443,7 @@ public class NMSBinding18_2 implements INMSBinding { if(i.getReturnType().equals(returns)) { i.setAccessible(true); try { - Iris.info("[NMS] Found " + returns.getSimpleName() + " in " + in.getClass().getSimpleName() + "." + i.getName() + "()"); + Iris.debug("[NMS] Found " + returns.getSimpleName() + " in " + in.getClass().getSimpleName() + "." + i.getName() + "()"); return i.invoke(in); } catch(Throwable e) { e.printStackTrace(); @@ -421,16 +460,21 @@ public class NMSBinding18_2 implements INMSBinding { @SuppressWarnings("unchecked") private static T fieldForClass(Class returnType, Class sourceType, Object in) { - for(Field i : sourceType.getFields()) + for(Field i : sourceType.getDeclaredFields()) { if(i.getType().equals(returnType)) { i.setAccessible(true); try { - Iris.info("[NMS] Found " + returnType.getSimpleName() + " in " + sourceType.getSimpleName() + "." + i.getName()); - return (T)i.get(in); + Iris.debug("[NMS] Found " + returnType.getSimpleName() + " in " + sourceType.getSimpleName() + "." + i.getName()); + return (T) i.get(in); } catch(IllegalAccessException e) { e.printStackTrace(); } } + } return null; } + + private static Class getClassType(Class type, int ordinal) { + return type.getDeclaredClasses()[ordinal]; + } } diff --git a/src/main/java/com/volmit/iris/engine/IrisComplex.java b/src/main/java/com/volmit/iris/engine/IrisComplex.java index d2647003f..6776a6773 100644 --- a/src/main/java/com/volmit/iris/engine/IrisComplex.java +++ b/src/main/java/com/volmit/iris/engine/IrisComplex.java @@ -112,8 +112,8 @@ public class IrisComplex implements DataProvider { .getAllBiomes(this).forEach((b) -> b .getGenerators() .forEach((c) -> registerGenerator(c.getCachedGenerator(this))))); - overlayStream = ProceduralStream.ofDouble((x, z) -> 0D); - engine.getDimension().getOverlayNoise().forEach((i) -> overlayStream.add((x, z) -> i.get(rng, getData(), x, z))); + overlayStream = ProceduralStream.ofDouble((x, z) -> 0.0D); + engine.getDimension().getOverlayNoise().forEach(i -> overlayStream = overlayStream.add((x, z) -> i.get(rng, getData(), x, z))); rockStream = engine.getDimension().getRockPalette().getLayerGenerator(rng.nextParallelRNG(45), data).stream() .select(engine.getDimension().getRockPalette().getBlockData(data)); fluidStream = engine.getDimension().getFluidPalette().getLayerGenerator(rng.nextParallelRNG(78), data).stream() diff --git a/src/main/java/com/volmit/iris/engine/actuator/IrisBiomeActuator.java b/src/main/java/com/volmit/iris/engine/actuator/IrisBiomeActuator.java index c93fd739d..d3634c91e 100644 --- a/src/main/java/com/volmit/iris/engine/actuator/IrisBiomeActuator.java +++ b/src/main/java/com/volmit/iris/engine/actuator/IrisBiomeActuator.java @@ -32,6 +32,7 @@ import com.volmit.iris.util.math.RNG; import com.volmit.iris.util.parallel.BurstExecutor; import com.volmit.iris.util.scheduling.ChronoLatch; import com.volmit.iris.util.scheduling.PrecisionStopwatch; +import io.papermc.lib.PaperLib; import org.bukkit.block.Biome; import org.bukkit.generator.ChunkGenerator; @@ -67,7 +68,7 @@ public class IrisBiomeActuator extends EngineAssignedActuator { @Override public void onActuate(int x, int z, Hunk h, boolean multicore) { PrecisionStopwatch p = PrecisionStopwatch.start(); - BurstExecutor burst = burst().burst(multicore); + BurstExecutor burst = burst().burst(PaperLib.isPaper() && multicore); for(int xf = 0; xf < h.getWidth(); xf++) { int finalXf = xf; diff --git a/src/main/java/com/volmit/iris/engine/actuator/IrisTerrainNormalActuator.java b/src/main/java/com/volmit/iris/engine/actuator/IrisTerrainNormalActuator.java index 1e40a28d7..23624d976 100644 --- a/src/main/java/com/volmit/iris/engine/actuator/IrisTerrainNormalActuator.java +++ b/src/main/java/com/volmit/iris/engine/actuator/IrisTerrainNormalActuator.java @@ -101,7 +101,6 @@ public class IrisTerrainNormalActuator extends EngineAssignedActuator KList blocks = null; KList fblocks = null; int depth, fdepth; - for(int i = hf; i >= 0; i--) { if(i >= h.getHeight()) { continue; diff --git a/src/main/java/com/volmit/iris/engine/object/IrisDimension.java b/src/main/java/com/volmit/iris/engine/object/IrisDimension.java index c3a539bd3..c41a1bf17 100644 --- a/src/main/java/com/volmit/iris/engine/object/IrisDimension.java +++ b/src/main/java/com/volmit/iris/engine/object/IrisDimension.java @@ -228,8 +228,6 @@ public class IrisDimension extends IrisRegistrant { private IrisMaterialPalette rockPalette = new IrisMaterialPalette().qclear().qadd("stone"); @Desc("The palette of blocks for 'water'") private IrisMaterialPalette fluidPalette = new IrisMaterialPalette().qclear().qadd("water"); -// @Desc("Cartographer map trade overrides") -// private IrisVillagerOverride patchCartographers = new IrisVillagerOverride().setDisableTrade(false); @Desc("Remove cartographers so they do not crash the server (Iris worlds only)") private boolean removeCartographersDueToCrash = true; @Desc("Notify players of cancelled cartographer villager in this radius in blocks (set to -1 to disable, -2 for everyone)") @@ -418,7 +416,7 @@ public class IrisDimension extends IrisRegistrant { { "pack": { "description": "Iris Data Pack. This pack contains all installed Iris Packs' resources.", - "pack_format": 9 + "pack_format": 10 } } """); @@ -481,6 +479,8 @@ public class IrisDimension extends IrisRegistrant { "bed_works": true, "respawn_anchor_works": false, "has_raids": true, + "monster_spawn_block_light_limit": 7, + "monster_spawn_light_level": 1, "infiniburn": "#minecraft:infiniburn_overworld", "effects": "minecraft:overworld" }"""; diff --git a/src/main/java/com/volmit/iris/engine/object/IrisGeneratorStyle.java b/src/main/java/com/volmit/iris/engine/object/IrisGeneratorStyle.java index 1ebb2f203..123a1d247 100644 --- a/src/main/java/com/volmit/iris/engine/object/IrisGeneratorStyle.java +++ b/src/main/java/com/volmit/iris/engine/object/IrisGeneratorStyle.java @@ -35,6 +35,8 @@ import lombok.Data; import lombok.NoArgsConstructor; import lombok.experimental.Accessors; +import java.util.Objects; + @Snippet("style") @Accessors(chain = true) @NoArgsConstructor @@ -70,6 +72,10 @@ public class IrisGeneratorStyle { @MaxNumber(64) @Desc("The exponent") private double exponent = 1; + @MinNumber(0) + @MaxNumber(8192) + @Desc("If the cache size is set above 0, this generator will be cached") + private int cacheSize = 0; public IrisGeneratorStyle(NoiseStyle s) { this.style = s; @@ -81,6 +87,18 @@ public class IrisGeneratorStyle { } public CNG createNoCache(RNG rng, IrisData data) { + return createNoCache(rng, data, false); + } + + + private int hash() + { + return Objects.hash(expression, imageMap, multiplier, axialFracturing, fracture != null ? fracture.hash() : 0, exponent, cacheSize, zoom, cellularZoom, cellularFrequency, style); + } + + public CNG createNoCache(RNG rng, IrisData data, boolean actuallyCached) { + String cacheKey = hash() + ""; + if(getExpression() != null) { IrisExpression e = data.getExpressionLoader().load(getExpression()); @@ -134,7 +152,7 @@ public class IrisGeneratorStyle { } public CNG create(RNG rng, IrisData data) { - return cng.aquire(() -> createNoCache(rng, data)); + return cng.aquire(() -> createNoCache(rng, data, true)); } @SuppressWarnings("BooleanMethodIsAlwaysInverted") diff --git a/src/main/java/com/volmit/iris/engine/object/IrisLoot.java b/src/main/java/com/volmit/iris/engine/object/IrisLoot.java index 958c955a3..fecc68100 100644 --- a/src/main/java/com/volmit/iris/engine/object/IrisLoot.java +++ b/src/main/java/com/volmit/iris/engine/object/IrisLoot.java @@ -46,7 +46,7 @@ import net.minecraft.nbt.TagParser; import org.bukkit.DyeColor; import org.bukkit.Material; import org.bukkit.NamespacedKey; -import org.bukkit.craftbukkit.v1_18_R2.inventory.CraftItemStack; +import org.bukkit.craftbukkit.v1_19_R1.inventory.CraftItemStack; import org.bukkit.inventory.ItemFlag; import org.bukkit.inventory.ItemStack; import org.bukkit.inventory.meta.Damageable; diff --git a/src/main/java/com/volmit/iris/engine/object/IrisObject.java b/src/main/java/com/volmit/iris/engine/object/IrisObject.java index 45af93400..5a5c2c059 100644 --- a/src/main/java/com/volmit/iris/engine/object/IrisObject.java +++ b/src/main/java/com/volmit/iris/engine/object/IrisObject.java @@ -506,7 +506,9 @@ public class IrisObject extends IrisRegistrant { } boolean warped = !config.getWarp().isFlat(); - boolean stilting = (config.getMode().equals(ObjectPlaceMode.STILT) || config.getMode().equals(ObjectPlaceMode.FAST_STILT)); + boolean stilting = (config.getMode().equals(ObjectPlaceMode.STILT) || config.getMode().equals(ObjectPlaceMode.FAST_STILT) || + config.getMode() == ObjectPlaceMode.MIN_STILT || config.getMode() == ObjectPlaceMode.FAST_MIN_STILT || + config.getMode() == ObjectPlaceMode.CENTER_STILT); KMap heightmap = config.getSnow() > 0 ? new KMap<>() : null; int spinx = rng.imax() / 1000; int spiny = rng.imax() / 1000; @@ -520,7 +522,7 @@ public class IrisObject extends IrisRegistrant { boolean bail = false; if(yv < 0) { - if(config.getMode().equals(ObjectPlaceMode.CENTER_HEIGHT)) { + if(config.getMode().equals(ObjectPlaceMode.CENTER_HEIGHT) || config.getMode() == ObjectPlaceMode.CENTER_STILT) { y = (c != null ? c.getSurface() : placer.getHighest(x, z, getLoader(), config.isUnderwater())) + rty; if(placer.isCarved(x, y, z) || placer.isCarved(x, y - 1, z) || placer.isCarved(x, y - 2, z) || placer.isCarved(x, y - 3, z)) { bail = true; @@ -548,6 +550,7 @@ public class IrisObject extends IrisRegistrant { } else if(config.getMode().equals(ObjectPlaceMode.FAST_MAX_HEIGHT) || config.getMode().equals(ObjectPlaceMode.FAST_STILT)) { BlockVector offset = new BlockVector(config.getTranslate().getX(), config.getTranslate().getY(), config.getTranslate().getZ()); BlockVector rotatedDimensions = config.getRotation().rotate(new BlockVector(getW(), getH(), getD()), spinx, spiny, spinz).clone(); + int xRadius = (rotatedDimensions.getBlockX() / 2); int xLength = xRadius + offset.getBlockX(); int minX = Math.min(x - xLength, x + xLength); @@ -556,6 +559,7 @@ public class IrisObject extends IrisRegistrant { int zLength = zRadius + offset.getBlockZ(); int minZ = Math.min(z - zLength, z + zLength); int maxZ = Math.max(z - zLength, z + zLength); + for(int i = minX; i <= maxX; i += Math.abs(xRadius) + 1) { for(int ii = minZ; ii <= maxZ; ii += Math.abs(zRadius) + 1) { int h = placer.getHighest(i, ii, getLoader(), config.isUnderwater()) + rty; @@ -567,15 +571,21 @@ public class IrisObject extends IrisRegistrant { y = h; } } - } else if(config.getMode().equals(ObjectPlaceMode.MIN_HEIGHT)) { + } else if(config.getMode().equals(ObjectPlaceMode.MIN_HEIGHT) || config.getMode() == ObjectPlaceMode.MIN_STILT) { y = rdata.getEngine().getHeight() + 1; BlockVector offset = new BlockVector(config.getTranslate().getX(), config.getTranslate().getY(), config.getTranslate().getZ()); BlockVector rotatedDimensions = config.getRotation().rotate(new BlockVector(getW(), getH(), getD()), spinx, spiny, spinz).clone(); - for(int i = x - (rotatedDimensions.getBlockX() / 2) + offset.getBlockX(); i <= x + (rotatedDimensions.getBlockX() / 2) + offset.getBlockX(); i++) { - for(int j = z - (rotatedDimensions.getBlockZ() / 2) + offset.getBlockZ(); j <= z + (rotatedDimensions.getBlockZ() / 2) + offset.getBlockZ(); j++) { - int h = placer.getHighest(i, j, getLoader(), config.isUnderwater()) + rty; - if(placer.isCarved(i, h, j) || placer.isCarved(i, h - 1, j) || placer.isCarved(i, h - 2, j) || placer.isCarved(i, h - 3, j)) { + int xLength = (rotatedDimensions.getBlockX() / 2) + offset.getBlockX(); + int minX = Math.min(x - xLength, x + xLength); + int maxX = Math.max(x - xLength, x + xLength); + int zLength = (rotatedDimensions.getBlockZ() / 2) + offset.getBlockZ(); + int minZ = Math.min(z - zLength, z + zLength); + int maxZ = Math.max(z - zLength, z + zLength); + for(int i = minX; i <= maxX; i++) { + for(int ii = minZ; ii <= maxZ; ii++) { + int h = placer.getHighest(i, ii, getLoader(), config.isUnderwater()) + rty; + if(placer.isCarved(i, h, ii) || placer.isCarved(i, h - 1, ii) || placer.isCarved(i, h - 2, ii) || placer.isCarved(i, h - 3, ii)) { bail = true; break; } @@ -584,15 +594,24 @@ public class IrisObject extends IrisRegistrant { } } } - } else if(config.getMode().equals(ObjectPlaceMode.FAST_MIN_HEIGHT)) { + } else if(config.getMode().equals(ObjectPlaceMode.FAST_MIN_HEIGHT) || config.getMode() == ObjectPlaceMode.FAST_MIN_STILT) { y = rdata.getEngine().getHeight() + 1; BlockVector offset = new BlockVector(config.getTranslate().getX(), config.getTranslate().getY(), config.getTranslate().getZ()); BlockVector rotatedDimensions = config.getRotation().rotate(new BlockVector(getW(), getH(), getD()), spinx, spiny, spinz).clone(); - for(int i = x - (rotatedDimensions.getBlockX() / 2) + offset.getBlockX(); i <= x + (rotatedDimensions.getBlockX() / 2) + offset.getBlockX(); i += (rotatedDimensions.getBlockX() / 2) + 1) { - for(int j = z - (rotatedDimensions.getBlockZ() / 2) + offset.getBlockZ(); j <= z + (rotatedDimensions.getBlockZ() / 2) + offset.getBlockZ(); j += (rotatedDimensions.getBlockZ() / 2) + 1) { - int h = placer.getHighest(i, j, getLoader(), config.isUnderwater()) + rty; - if(placer.isCarved(i, h, j) || placer.isCarved(i, h - 1, j) || placer.isCarved(i, h - 2, j) || placer.isCarved(i, h - 3, j)) { + int xRadius = (rotatedDimensions.getBlockX() / 2); + int xLength = xRadius + offset.getBlockX(); + int minX = Math.min(x - xLength, x + xLength); + int maxX = Math.max(x - xLength, x + xLength); + int zRadius = (rotatedDimensions.getBlockZ() / 2); + int zLength = zRadius + offset.getBlockZ(); + int minZ = Math.min(z - zLength, z + zLength); + int maxZ = Math.max(z - zLength, z + zLength); + + for(int i = minX; i <= maxX; i += Math.abs(xRadius) + 1) { + for(int ii = minZ; ii <= maxZ; ii += Math.abs(zRadius) + 1) { + int h = placer.getHighest(i, ii, getLoader(), config.isUnderwater()) + rty; + if(placer.isCarved(i, h, ii) || placer.isCarved(i, h - 1, ii) || placer.isCarved(i, h - 2, ii) || placer.isCarved(i, h - 3, ii)) { bail = true; break; } @@ -806,21 +825,26 @@ public class IrisObject extends IrisRegistrant { if(stilting) { readLock.lock(); + IrisStiltSettings settings = config.getStiltSettings(); for(BlockVector g : getBlocks().keySet()) { BlockData d; - try { - d = getBlocks().get(g); - } catch(Throwable e) { - Iris.reportError(e); - Iris.warn("Failed to read block node " + g.getBlockX() + "," + g.getBlockY() + "," + g.getBlockZ() + " in object " + getLoadKey() + " (stilt cme)"); - d = AIR; - } + if(settings == null || settings.getPalette() == null) { + try { + d = getBlocks().get(g); + } catch(Throwable e) { + Iris.reportError(e); + Iris.warn("Failed to read block node " + g.getBlockX() + "," + g.getBlockY() + "," + g.getBlockZ() + " in object " + getLoadKey() + " (stilt cme)"); + d = AIR; + } + + if(d == null) { + Iris.warn("Failed to read block node " + g.getBlockX() + "," + g.getBlockY() + "," + g.getBlockZ() + " in object " + getLoadKey() + " (stilt null)"); + d = AIR; + } + } else + d = config.getStiltSettings().getPalette().get(rng, x, y, z, rdata); - if(d == null) { - Iris.warn("Failed to read block node " + g.getBlockX() + "," + g.getBlockY() + "," + g.getBlockZ() + " in object " + getLoadKey() + " (stilt null)"); - d = AIR; - } BlockVector i = g.clone(); i = config.getRotation().rotate(i.clone(), spinx, spiny, spinz).clone(); @@ -856,15 +880,21 @@ public class IrisObject extends IrisRegistrant { zz += config.warp(rng, i.getZ() + z, i.getY() + y, i.getX() + x, getLoader()); } - int yg = placer.getHighest(xx, zz, getLoader(), true); + int highest = placer.getHighest(xx, zz, getLoader(), true); - if(config.isWaterloggable() && yg <= placer.getFluidHeight() && d instanceof Waterlogged) + if(config.isWaterloggable() && highest <= placer.getFluidHeight() && d instanceof Waterlogged) ((Waterlogged) d).setWaterlogged(true); if(yv >= 0 && config.isBottom()) y += Math.floorDiv(h, 2); - for(int j = lowest + y; j > yg - config.getOverStilt() - 1; j--) + int lowerBound = highest - 1; + if(settings != null) { + lowerBound -= config.getStiltSettings().getOverStilt() - rng.i(0, config.getStiltSettings().getYRand()); + if(settings.getYMax() != 0) + lowerBound -= Math.min(config.getStiltSettings().getYMax() - (lowest + y - highest), 0); + } + for(int j = lowest + y; j > lowerBound; j--) placer.set(xx, j, zz, d); } diff --git a/src/main/java/com/volmit/iris/engine/object/IrisObjectPlacement.java b/src/main/java/com/volmit/iris/engine/object/IrisObjectPlacement.java index 8e449e797..a60508096 100644 --- a/src/main/java/com/volmit/iris/engine/object/IrisObjectPlacement.java +++ b/src/main/java/com/volmit/iris/engine/object/IrisObjectPlacement.java @@ -75,10 +75,8 @@ public class IrisObjectPlacement { private int density = 1; @Desc("If the chance check passes, and you specify this, it picks a number in the range based on noise, and 'density' is ignored.") private IrisStyledRange densityStyle = null; - @MaxNumber(64) - @MinNumber(0) - @Desc("If the place mode is set to stilt, you can over-stilt it even further into the ground. Especially useful when using fast stilt due to inaccuracies.") - private int overStilt = 0; + @Desc("When stilting is enabled, this object will define various properties related to it.") + private IrisStiltSettings stiltSettings; @MaxNumber(64) @MinNumber(0) @Desc("When bore is enabled, expand max-y of the cuboid it removes") @@ -146,7 +144,7 @@ public class IrisObjectPlacement { p.setUnderwater(underwater); p.setBoreExtendMaxY(boreExtendMaxY); p.setBoreExtendMinY(boreExtendMinY); - p.setOverStilt(overStilt); + p.setStiltSettings(stiltSettings); p.setDensity(density); p.setChance(chance); p.setSnow(snow); diff --git a/src/main/java/com/volmit/iris/engine/object/IrisObjectTranslate.java b/src/main/java/com/volmit/iris/engine/object/IrisObjectTranslate.java index 886ba4cc1..53a3392e8 100644 --- a/src/main/java/com/volmit/iris/engine/object/IrisObjectTranslate.java +++ b/src/main/java/com/volmit/iris/engine/object/IrisObjectTranslate.java @@ -44,7 +44,7 @@ public class IrisObjectTranslate { @Required @MinNumber(-128) // TODO: WARNING HEIGHT @MaxNumber(128) // TODO: WARNING HEIGHT - @Desc("The x shift in blocks") + @Desc("The y shift in blocks") private int y = 0; @MinNumber(-128) // TODO: WARNING HEIGHT @@ -54,7 +54,7 @@ public class IrisObjectTranslate { @MinNumber(-128) // TODO: WARNING HEIGHT @MaxNumber(128) // TODO: WARNING HEIGHT - @Desc("The x shift in blocks") + @Desc("The z shift in blocks") private int z = 0; public boolean canTranslate() { diff --git a/src/main/java/com/volmit/iris/engine/object/IrisStiltSettings.java b/src/main/java/com/volmit/iris/engine/object/IrisStiltSettings.java new file mode 100644 index 000000000..ca4bd55a6 --- /dev/null +++ b/src/main/java/com/volmit/iris/engine/object/IrisStiltSettings.java @@ -0,0 +1,34 @@ +package com.volmit.iris.engine.object; + +import com.volmit.iris.engine.object.annotations.Desc; +import com.volmit.iris.engine.object.annotations.MaxNumber; +import com.volmit.iris.engine.object.annotations.MinNumber; +import com.volmit.iris.engine.object.annotations.Snippet; +import lombok.AllArgsConstructor; +import lombok.Data; +import lombok.NoArgsConstructor; +import lombok.experimental.Accessors; + +@Snippet("stilt-settings") +@Accessors(chain = true) +@NoArgsConstructor +@AllArgsConstructor +@Desc("Defines stilting behaviour.") +@Data +public class IrisStiltSettings { + @MinNumber(0) + @MaxNumber(64) + @Desc("Defines the maximum amount of blocks the object stilts verticially before overstilting and randomRange.") + private int yMax; + @MinNumber(0) + @MaxNumber(64) + @Desc("Defines the upper boundary for additional blocks after overstilting and/or maxStiltRange.") + private int yRand; + @MaxNumber(64) + @MinNumber(0) + @Desc("If the place mode is set to stilt, you can over-stilt it even further into the ground. Especially useful when using fast stilt due to inaccuracies.") + private int overStilt; + @Desc("If defined, stilting will be done using this block palette rather than the last layer of the object.") + private IrisMaterialPalette palette; + +} diff --git a/src/main/java/com/volmit/iris/engine/object/ObjectPlaceMode.java b/src/main/java/com/volmit/iris/engine/object/ObjectPlaceMode.java index 474807f5f..b632406e1 100644 --- a/src/main/java/com/volmit/iris/engine/object/ObjectPlaceMode.java +++ b/src/main/java/com/volmit/iris/engine/object/ObjectPlaceMode.java @@ -50,6 +50,18 @@ public enum ObjectPlaceMode { FAST_STILT, + @Desc("Stilting is MIN_HEIGHT but it repeats the bottom most block of your object until it hits the surface. This is expensive because it has to first sample every height value for each x,z position of your object. Avoid using this unless its structures for performance reasons.") + + MIN_STILT, + + @Desc("Just like MIN_STILT but very inaccurate. Useful for stilting a lot of objects without too much care on accuracy (you can use the over-stilt value to force stilts under ground further)") + + FAST_MIN_STILT, + + @Desc("Stilting is CENTER_HEIGHT but it repeats the bottom most block of your object until it hits the surface. This is expensive because it has to first sample every height value for each x,z position of your object. Avoid using this unless its structures for performance reasons.") + + CENTER_STILT, + @Desc("Samples the height of the terrain at every x,z position of your object and pushes it down to the surface. It's pretty much like a melt function over the terrain.") PAINT diff --git a/src/main/java/com/volmit/iris/engine/platform/BukkitChunkGenerator.java b/src/main/java/com/volmit/iris/engine/platform/BukkitChunkGenerator.java index e9216efb9..d12028f25 100644 --- a/src/main/java/com/volmit/iris/engine/platform/BukkitChunkGenerator.java +++ b/src/main/java/com/volmit/iris/engine/platform/BukkitChunkGenerator.java @@ -31,11 +31,15 @@ import com.volmit.iris.engine.object.StudioMode; import com.volmit.iris.engine.platform.studio.StudioGenerator; import com.volmit.iris.util.collection.KList; import com.volmit.iris.util.data.IrisBiomeStorage; +import com.volmit.iris.util.format.Form; import com.volmit.iris.util.hunk.Hunk; +import com.volmit.iris.util.hunk.view.BiomeGridHunkHolder; +import com.volmit.iris.util.hunk.view.ChunkDataHunkHolder; import com.volmit.iris.util.io.ReactiveFolder; import com.volmit.iris.util.scheduling.ChronoLatch; import com.volmit.iris.util.scheduling.J; import com.volmit.iris.util.scheduling.Looper; +import com.volmit.iris.util.scheduling.PrecisionStopwatch; import lombok.Data; import lombok.EqualsAndHashCode; import lombok.Setter; @@ -278,9 +282,11 @@ public class BukkitChunkGenerator extends ChunkGenerator implements PlatformChun if(studioGenerator != null) { studioGenerator.generateChunk(getEngine(), tc, x, z); } else { - Hunk blocks = Hunk.view(tc); - Hunk biomes = Hunk.view(tc, tc.getMinHeight(), tc.getMaxHeight()); + ChunkDataHunkHolder blocks = new ChunkDataHunkHolder(tc); + BiomeGridHunkHolder biomes = new BiomeGridHunkHolder(tc, tc.getMinHeight(), tc.getMaxHeight()); getEngine().generate(x << 4, z << 4, blocks, biomes, true); + blocks.apply(); + biomes.apply(); } ChunkData c = tc.getRaw(); diff --git a/src/main/java/com/volmit/iris/util/cache/ArrayCache.java b/src/main/java/com/volmit/iris/util/cache/ArrayCache.java new file mode 100644 index 000000000..8b578898e --- /dev/null +++ b/src/main/java/com/volmit/iris/util/cache/ArrayCache.java @@ -0,0 +1,82 @@ +/* + * Iris is a World Generator for Minecraft Bukkit Servers + * Copyright (c) 2022 Arcane Arts (Volmit Software) + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + +package com.volmit.iris.util.cache; + +import com.volmit.iris.engine.data.cache.Cache; +import com.volmit.iris.util.hunk.bits.Writable; + +import java.io.DataInput; +import java.io.DataInputStream; +import java.io.DataOutputStream; +import java.io.IOException; + +public interface ArrayCache extends Writable { + T get(int i); + + void set(int i, T t); + + void iset(int i, int v); + + int getWidth(); + + int getHeight(); + + void writeCache(DataOutputStream dos) throws IOException; + + static int zigZag(int coord, int size) + { + if(coord < 0) + { + coord = Math.abs(coord); + } + + if(coord % (size * 2) >= size) + { + return (size) - (coord % size) - 1; + } + + else { + return coord % size; + } + } + + default void set(int x, int y, T v) + { + set((zigZag(y, getHeight()) * getWidth()) + zigZag(x, getWidth()), v); + } + + default T get(int x, int y) + { + try + { + return get((zigZag(y, getHeight()) * getWidth()) + zigZag(x, getWidth())); + } + + catch(Throwable e) + { + e.printStackTrace(); + throw e; + } + } + + default void iset(int x, int y, int v) + { + iset((zigZag(y, getHeight()) * getWidth()) + zigZag(x, getWidth()), v); + } +} diff --git a/src/main/java/com/volmit/iris/util/cache/ByteBitCache.java b/src/main/java/com/volmit/iris/util/cache/ByteBitCache.java new file mode 100644 index 000000000..eb701973f --- /dev/null +++ b/src/main/java/com/volmit/iris/util/cache/ByteBitCache.java @@ -0,0 +1,44 @@ +/* + * Iris is a World Generator for Minecraft Bukkit Servers + * Copyright (c) 2022 Arcane Arts (Volmit Software) + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + +package com.volmit.iris.util.cache; + +import java.io.DataInputStream; +import java.io.DataOutputStream; +import java.io.IOException; + +public class ByteBitCache extends DataBitCache { + public ByteBitCache(int width, int height) { + super(width, height); + } + + @Override + public Integer readNodeData(DataInputStream din) throws IOException { + return (int) din.readByte(); + } + + @Override + public void writeNodeData(DataOutputStream dos, Integer integer) throws IOException { + dos.writeByte(integer); + } + + @Override + public void iset(int i, int v) { + set(i, v); + } +} diff --git a/src/main/java/com/volmit/iris/util/cache/ByteCache.java b/src/main/java/com/volmit/iris/util/cache/ByteCache.java new file mode 100644 index 000000000..7c9421b3a --- /dev/null +++ b/src/main/java/com/volmit/iris/util/cache/ByteCache.java @@ -0,0 +1,76 @@ +/* + * Iris is a World Generator for Minecraft Bukkit Servers + * Copyright (c) 2022 Arcane Arts (Volmit Software) + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + +package com.volmit.iris.util.cache; + +import lombok.Getter; + +import java.io.DataInputStream; +import java.io.DataOutputStream; +import java.io.IOException; + +public class ByteCache implements ArrayCache { + @Getter + private final int width; + @Getter + private final int height; + private final byte[] cache; + + public ByteCache(int width, int height) + { + this.width = width; + this.height = height; + cache = new byte[width * height]; + } + + public void set(int i, Integer v) + { + cache[i] = v.byteValue(); + } + + public Integer get(int i) + { + return (int)cache[i]; + } + + @Override + public void writeCache(DataOutputStream dos) throws IOException { + dos.writeInt(width); + dos.writeInt(height); + + for(int i = 0; i < width * height; i++) + { + dos.writeByte(get(i)); + } + } + + @Override + public Integer readNodeData(DataInputStream din) throws IOException { + return (int) din.readByte(); + } + + @Override + public void writeNodeData(DataOutputStream dos, Integer integer) throws IOException { + dos.writeByte(integer); + } + + @Override + public void iset(int i, int v) { + set(i, v); + } +} diff --git a/src/main/java/com/volmit/iris/util/cache/DataBitCache.java b/src/main/java/com/volmit/iris/util/cache/DataBitCache.java new file mode 100644 index 000000000..ba8ff7ebf --- /dev/null +++ b/src/main/java/com/volmit/iris/util/cache/DataBitCache.java @@ -0,0 +1,58 @@ +/* + * Iris is a World Generator for Minecraft Bukkit Servers + * Copyright (c) 2022 Arcane Arts (Volmit Software) + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + +package com.volmit.iris.util.cache; + +import com.volmit.iris.util.hunk.bits.DataContainer; +import lombok.Getter; + +import java.io.DataInputStream; +import java.io.DataOutputStream; +import java.io.IOException; + +public abstract class DataBitCache implements ArrayCache { + @Getter + private final int width; + @Getter + private final int height; + private final DataContainer cache; + + public DataBitCache(int width, int height) + { + this.width = width; + this.height = height; + cache = new DataContainer<>(this, width * height); + } + + public void set(int i, T v) + { + cache.set(i, v); + } + + public T get(int i) + { + return cache.get(i); + } + + @Override + public void writeCache(DataOutputStream dos) throws IOException { + dos.writeInt(width); + dos.writeInt(height); + cache.writeDos(dos); + } +} diff --git a/src/main/java/com/volmit/iris/util/cache/FloatBitCache.java b/src/main/java/com/volmit/iris/util/cache/FloatBitCache.java new file mode 100644 index 000000000..4d0473dfc --- /dev/null +++ b/src/main/java/com/volmit/iris/util/cache/FloatBitCache.java @@ -0,0 +1,44 @@ +/* + * Iris is a World Generator for Minecraft Bukkit Servers + * Copyright (c) 2022 Arcane Arts (Volmit Software) + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + +package com.volmit.iris.util.cache; + +import java.io.DataInputStream; +import java.io.DataOutputStream; +import java.io.IOException; + +public class FloatBitCache extends DataBitCache { + public FloatBitCache(int width, int height) { + super(width, height); + } + + @Override + public Float readNodeData(DataInputStream din) throws IOException { + return din.readFloat(); + } + + @Override + public void writeNodeData(DataOutputStream dos, Float integer) throws IOException { + dos.writeFloat(integer); + } + + @Override + public void iset(int i, int v) { + set(i, (float)v); + } +} diff --git a/src/main/java/com/volmit/iris/util/cache/FloatCache.java b/src/main/java/com/volmit/iris/util/cache/FloatCache.java new file mode 100644 index 000000000..334922a52 --- /dev/null +++ b/src/main/java/com/volmit/iris/util/cache/FloatCache.java @@ -0,0 +1,93 @@ +/* + * Iris is a World Generator for Minecraft Bukkit Servers + * Copyright (c) 2022 Arcane Arts (Volmit Software) + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + +package com.volmit.iris.util.cache; + +import lombok.Getter; + +import java.io.DataInputStream; +import java.io.DataOutputStream; +import java.io.File; +import java.io.FileInputStream; +import java.io.FileNotFoundException; +import java.io.IOException; + +public class FloatCache implements ArrayCache { + @Getter + private final int width; + @Getter + private final int height; + private final float[] cache; + + + public FloatCache(File file) throws IOException { + this(new DataInputStream(new FileInputStream(file))); + } + + public FloatCache(DataInputStream din) throws IOException { + this(din.readInt(), din.readInt()); + for(int i = 0; i < width * height; i++) + { + cache[i] = din.readFloat(); + } + din.close(); + } + + public FloatCache(int width, int height) + { + this.width = width; + this.height = height; + cache = new float[width * height]; + } + + public void set(int i, Float v) + { + cache[i] = v; + } + + public Float get(int i) + { + return cache[i]; + } + + @Override + public void writeCache(DataOutputStream dos) throws IOException { + dos.writeInt(width); + dos.writeInt(height); + + for(int i = 0; i < width * height; i++) + { + dos.writeFloat(get(i)); + } + } + + @Override + public Float readNodeData(DataInputStream din) throws IOException { + return din.readFloat(); + } + + @Override + public void writeNodeData(DataOutputStream dos, Float integer) throws IOException { + dos.writeFloat(integer); + } + + @Override + public void iset(int i, int v) { + set(i, (float) v); + } +} diff --git a/src/main/java/com/volmit/iris/util/cache/IntBitCache.java b/src/main/java/com/volmit/iris/util/cache/IntBitCache.java new file mode 100644 index 000000000..c06e62682 --- /dev/null +++ b/src/main/java/com/volmit/iris/util/cache/IntBitCache.java @@ -0,0 +1,44 @@ +/* + * Iris is a World Generator for Minecraft Bukkit Servers + * Copyright (c) 2022 Arcane Arts (Volmit Software) + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + +package com.volmit.iris.util.cache; + +import java.io.DataInputStream; +import java.io.DataOutputStream; +import java.io.IOException; + +public class IntBitCache extends DataBitCache { + public IntBitCache(int width, int height) { + super(width, height); + } + + @Override + public Integer readNodeData(DataInputStream din) throws IOException { + return din.readInt(); + } + + @Override + public void writeNodeData(DataOutputStream dos, Integer integer) throws IOException { + dos.writeInt(integer); + } + + @Override + public void iset(int i, int v) { + set(i, v); + } +} diff --git a/src/main/java/com/volmit/iris/util/cache/IntCache.java b/src/main/java/com/volmit/iris/util/cache/IntCache.java new file mode 100644 index 000000000..63509466e --- /dev/null +++ b/src/main/java/com/volmit/iris/util/cache/IntCache.java @@ -0,0 +1,78 @@ +/* + * Iris is a World Generator for Minecraft Bukkit Servers + * Copyright (c) 2022 Arcane Arts (Volmit Software) + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + +package com.volmit.iris.util.cache; + +import com.volmit.iris.util.hunk.bits.DataContainer; +import com.volmit.iris.util.hunk.bits.Writable; +import lombok.Getter; + +import java.io.DataInputStream; +import java.io.DataOutputStream; +import java.io.IOException; + +public class IntCache implements ArrayCache { + @Getter + private final int width; + @Getter + private final int height; + private final int[] cache; + + public IntCache(int width, int height) + { + this.width = width; + this.height = height; + cache = new int[width * height]; + } + + public void set(int i, Integer v) + { + cache[i] = v; + } + + public Integer get(int i) + { + return cache[i]; + } + + @Override + public void writeCache(DataOutputStream dos) throws IOException { + dos.writeInt(width); + dos.writeInt(height); + + for(int i = 0; i < width * height; i++) + { + dos.writeInt(get(i)); + } + } + + @Override + public Integer readNodeData(DataInputStream din) throws IOException { + return din.readInt(); + } + + @Override + public void writeNodeData(DataOutputStream dos, Integer integer) throws IOException { + dos.writeInt(integer); + } + + @Override + public void iset(int i, int v) { + set(i, v); + } +} diff --git a/src/main/java/com/volmit/iris/util/cache/ShortBitCache.java b/src/main/java/com/volmit/iris/util/cache/ShortBitCache.java new file mode 100644 index 000000000..4bb01d053 --- /dev/null +++ b/src/main/java/com/volmit/iris/util/cache/ShortBitCache.java @@ -0,0 +1,44 @@ +/* + * Iris is a World Generator for Minecraft Bukkit Servers + * Copyright (c) 2022 Arcane Arts (Volmit Software) + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + +package com.volmit.iris.util.cache; + +import java.io.DataInputStream; +import java.io.DataOutputStream; +import java.io.IOException; + +public class ShortBitCache extends DataBitCache { + public ShortBitCache(int width, int height) { + super(width, height); + } + + @Override + public Short readNodeData(DataInputStream din) throws IOException { + return din.readShort(); + } + + @Override + public void writeNodeData(DataOutputStream dos, Short integer) throws IOException { + dos.writeShort(integer); + } + + @Override + public void iset(int i, int v) { + set(i, (short) v); + } +} diff --git a/src/main/java/com/volmit/iris/util/cache/ShortCache.java b/src/main/java/com/volmit/iris/util/cache/ShortCache.java new file mode 100644 index 000000000..b25f3981d --- /dev/null +++ b/src/main/java/com/volmit/iris/util/cache/ShortCache.java @@ -0,0 +1,76 @@ +/* + * Iris is a World Generator for Minecraft Bukkit Servers + * Copyright (c) 2022 Arcane Arts (Volmit Software) + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + +package com.volmit.iris.util.cache; + +import lombok.Getter; + +import java.io.DataInputStream; +import java.io.DataOutputStream; +import java.io.IOException; + +public class ShortCache implements ArrayCache { + @Getter + private final int width; + @Getter + private final int height; + private final short[] cache; + + public ShortCache(int width, int height) + { + this.width = width; + this.height = height; + cache = new short[width * height]; + } + + public void set(int i, Short v) + { + cache[i] = v; + } + + public Short get(int i) + { + return cache[i]; + } + + @Override + public void writeCache(DataOutputStream dos) throws IOException { + dos.writeInt(width); + dos.writeInt(height); + + for(int i = 0; i < width * height; i++) + { + dos.writeShort(get(i)); + } + } + + @Override + public Short readNodeData(DataInputStream din) throws IOException { + return din.readShort(); + } + + @Override + public void writeNodeData(DataOutputStream dos, Short integer) throws IOException { + dos.writeShort(integer); + } + + @Override + public void iset(int i, int v) { + set(i, (short) v); + } +} diff --git a/src/main/java/com/volmit/iris/util/cache/UByteBitCache.java b/src/main/java/com/volmit/iris/util/cache/UByteBitCache.java new file mode 100644 index 000000000..4a1309f7b --- /dev/null +++ b/src/main/java/com/volmit/iris/util/cache/UByteBitCache.java @@ -0,0 +1,40 @@ +/* + * Iris is a World Generator for Minecraft Bukkit Servers + * Copyright (c) 2022 Arcane Arts (Volmit Software) + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + +package com.volmit.iris.util.cache; + +public class UByteBitCache extends ByteBitCache { + public UByteBitCache(int width, int height) { + super(width, height); + } + + @Override + public void set(int i, Integer v) { + super.set(i, v + Byte.MIN_VALUE); + } + + @Override + public Integer get(int i) { + return super.get(i) - Byte.MIN_VALUE; + } + + @Override + public void iset(int i, int v) { + set(i, v); + } +} diff --git a/src/main/java/com/volmit/iris/util/cache/UByteCache.java b/src/main/java/com/volmit/iris/util/cache/UByteCache.java new file mode 100644 index 000000000..81f5c23cc --- /dev/null +++ b/src/main/java/com/volmit/iris/util/cache/UByteCache.java @@ -0,0 +1,40 @@ +/* + * Iris is a World Generator for Minecraft Bukkit Servers + * Copyright (c) 2022 Arcane Arts (Volmit Software) + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + +package com.volmit.iris.util.cache; + +public class UByteCache extends ByteCache { + public UByteCache(int width, int height) { + super(width, height); + } + + @Override + public void set(int i, Integer v) { + super.set(i, v + Byte.MIN_VALUE); + } + + @Override + public Integer get(int i) { + return super.get(i) - Byte.MIN_VALUE; + } + + @Override + public void iset(int i, int v) { + set(i, v); + } +} diff --git a/src/main/java/com/volmit/iris/util/hunk/view/BiomeGridHunkHolder.java b/src/main/java/com/volmit/iris/util/hunk/view/BiomeGridHunkHolder.java new file mode 100644 index 000000000..a7b066526 --- /dev/null +++ b/src/main/java/com/volmit/iris/util/hunk/view/BiomeGridHunkHolder.java @@ -0,0 +1,86 @@ +/* + * Iris is a World Generator for Minecraft Bukkit Servers + * Copyright (c) 2022 Arcane Arts (Volmit Software) + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + +package com.volmit.iris.util.hunk.view; + +import com.volmit.iris.core.nms.INMS; +import com.volmit.iris.engine.data.chunk.LinkedTerrainChunk; +import com.volmit.iris.util.hunk.storage.AtomicHunk; +import lombok.Getter; +import org.bukkit.block.Biome; +import org.bukkit.generator.ChunkGenerator.BiomeGrid; + +@SuppressWarnings("ClassCanBeRecord") +public class BiomeGridHunkHolder extends AtomicHunk { + @Getter + private final BiomeGrid chunk; + private final int minHeight; + private final int maxHeight; + + public BiomeGridHunkHolder(BiomeGrid chunk, int minHeight, int maxHeight) { + super(16, maxHeight - minHeight, 16); + this.chunk = chunk; + this.minHeight = minHeight; + this.maxHeight = maxHeight; + } + + @Override + public int getWidth() { + return 16; + } + + @Override + public int getDepth() { + return 16; + } + + @Override + public int getHeight() { + return maxHeight - minHeight; + } + + public void apply() { + for(int i = 0; i < getHeight(); i++) { + for(int j = 0; j < getWidth(); j++) { + for(int k = 0; k < getDepth(); k++) { + Biome b = super.getRaw(j, i, k); + + if(b != null) + { + chunk.setBiome(j, i + minHeight, k, b); + } + } + } + } + } + + @Override + public Biome getRaw(int x, int y, int z) { + Biome b = super.getRaw(x, y, z); + + return b != null ? b : Biome.PLAINS; + } + + public void forceBiomeBaseInto(int x, int y, int z, Object somethingVeryDirty) { + if(chunk instanceof LinkedTerrainChunk) { + INMS.get().forceBiomeInto(x, y + minHeight, z, somethingVeryDirty, ((LinkedTerrainChunk) chunk).getRawBiome()); + return; + } + INMS.get().forceBiomeInto(x, y + minHeight, z, somethingVeryDirty, chunk); + } +} diff --git a/src/main/java/com/volmit/iris/util/hunk/view/BiomeGridHunkView.java b/src/main/java/com/volmit/iris/util/hunk/view/BiomeGridHunkView.java index c205162ee..ce1654acd 100644 --- a/src/main/java/com/volmit/iris/util/hunk/view/BiomeGridHunkView.java +++ b/src/main/java/com/volmit/iris/util/hunk/view/BiomeGridHunkView.java @@ -18,6 +18,7 @@ package com.volmit.iris.util.hunk.view; +import com.volmit.iris.Iris; import com.volmit.iris.core.nms.INMS; import com.volmit.iris.engine.data.chunk.LinkedTerrainChunk; import com.volmit.iris.util.hunk.Hunk; @@ -31,6 +32,7 @@ public class BiomeGridHunkView implements Hunk { private final BiomeGrid chunk; private final int minHeight; private final int maxHeight; + private int highest = -1000; public BiomeGridHunkView(BiomeGrid chunk, int minHeight, int maxHeight) { this.chunk = chunk; @@ -56,6 +58,12 @@ public class BiomeGridHunkView implements Hunk { @Override public void setRaw(int x, int y, int z, Biome t) { chunk.setBiome(x, y + minHeight, z, t); + + if(y > highest) + { + highest = y; + Iris.info("Highest = " + highest); + } } @Override diff --git a/src/main/java/com/volmit/iris/util/hunk/view/ChunkDataHunkHolder.java b/src/main/java/com/volmit/iris/util/hunk/view/ChunkDataHunkHolder.java new file mode 100644 index 000000000..cec67eb41 --- /dev/null +++ b/src/main/java/com/volmit/iris/util/hunk/view/ChunkDataHunkHolder.java @@ -0,0 +1,76 @@ +/* + * Iris is a World Generator for Minecraft Bukkit Servers + * Copyright (c) 2022 Arcane Arts (Volmit Software) + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + +package com.volmit.iris.util.hunk.view; + +import com.volmit.iris.util.hunk.Hunk; +import com.volmit.iris.util.hunk.storage.AtomicHunk; +import org.bukkit.Bukkit; +import org.bukkit.Material; +import org.bukkit.block.data.BlockData; +import org.bukkit.generator.ChunkGenerator.ChunkData; + +import java.util.concurrent.atomic.AtomicReferenceArray; + +@SuppressWarnings("ClassCanBeRecord") +public class ChunkDataHunkHolder extends AtomicHunk { + private static final BlockData AIR = Material.AIR.createBlockData(); + private final ChunkData chunk; + + public ChunkDataHunkHolder(ChunkData chunk) { + super(16, chunk.getMaxHeight() - chunk.getMinHeight(), 16); + this.chunk = chunk; + } + + @Override + public int getWidth() { + return 16; + } + + @Override + public int getDepth() { + return 16; + } + + @Override + public int getHeight() { + return chunk.getMaxHeight() - chunk.getMinHeight(); + } + + @Override + public BlockData getRaw(int x, int y, int z) { + BlockData b = super.getRaw(x, y, z); + + return b != null ? b : AIR; + } + + public void apply() { + for(int i = 0; i < getHeight(); i++) { + for(int j = 0; j < getWidth(); j++) { + for(int k = 0; k < getDepth(); k++) { + BlockData b = super.getRaw(j, i, k); + + if(b != null) + { + chunk.setBlock(j, i + chunk.getMinHeight(), k, b); + } + } + } + } + } +} diff --git a/src/main/java/com/volmit/iris/util/noise/CNG.java b/src/main/java/com/volmit/iris/util/noise/CNG.java index 356ca36a2..2c4b069b2 100644 --- a/src/main/java/com/volmit/iris/util/noise/CNG.java +++ b/src/main/java/com/volmit/iris/util/noise/CNG.java @@ -22,6 +22,8 @@ import com.volmit.iris.Iris; import com.volmit.iris.engine.data.cache.AtomicCache; import com.volmit.iris.engine.object.IRare; import com.volmit.iris.engine.object.NoiseStyle; +import com.volmit.iris.util.cache.FloatBitCache; +import com.volmit.iris.util.cache.FloatCache; import com.volmit.iris.util.collection.KList; import com.volmit.iris.util.format.Form; import com.volmit.iris.util.function.NoiseInjector; @@ -33,6 +35,11 @@ import com.volmit.iris.util.stream.arithmetic.FittedStream; import com.volmit.iris.util.stream.sources.CNGStream; import lombok.Data; +import java.io.DataOutputStream; +import java.io.File; +import java.io.FileNotFoundException; +import java.io.FileOutputStream; +import java.io.IOException; import java.util.List; @Data @@ -56,6 +63,7 @@ public class CNG { private boolean trueFracturing = false; private KList children; private CNG fracture; + private FloatCache cache; private NoiseGenerator generator; private NoiseInjector injector; private RNG rng; @@ -134,14 +142,55 @@ public class CNG { }, 1D, 1); } - public CNG cached(int size) + public CNG cached(int size, String key, File cacheFolder) { if(size <= 0) { return this; } - generator = new CachedNoise(generator, size); + cache = null; + + File f = new File(new File(cacheFolder, ".cache"), key + ".cnm"); + FloatCache fbc; + boolean cached = false; + if(f.exists()) + { + try { + fbc = new FloatCache(f); + cached = true; + } catch(IOException e) { + fbc = new FloatCache(size, size); + } + } + + else { + fbc = new FloatCache(size, size); + } + + if(!cached) + { + for(int i = 0; i < size; i++) + { + for(int j = 0; j < size; j++) + { + fbc.set(i, j, (float) noise(i, j)); + } + } + + try { + f.getParentFile().mkdirs(); + FileOutputStream fos = new FileOutputStream(f); + DataOutputStream dos = new DataOutputStream(fos); + fbc.writeCache(dos); + dos.close(); + Iris.info("Saved Noise Cache " + f.getName()); + } catch(IOException e) { + throw new RuntimeException(e); + } + } + + cache = fbc; return this; } @@ -436,6 +485,11 @@ public class CNG { } public double noise(double... dim) { + if(cache != null && dim.length == 2) + { + return cache.get((int)dim[0], (int)dim[1]); + } + double n = getNoise(dim); n = power != 1D ? (n < 0 ? -Math.pow(Math.abs(n), power) : Math.pow(n, power)) : n; double m = 1; diff --git a/src/main/java/com/volmit/iris/util/plugin/VolmitSender.java b/src/main/java/com/volmit/iris/util/plugin/VolmitSender.java index 25c6b363b..51864039a 100644 --- a/src/main/java/com/volmit/iris/util/plugin/VolmitSender.java +++ b/src/main/java/com/volmit/iris/util/plugin/VolmitSender.java @@ -51,6 +51,7 @@ import java.util.concurrent.ExecutionException; import java.util.concurrent.atomic.AtomicBoolean; import java.util.concurrent.atomic.AtomicInteger; import java.util.concurrent.atomic.AtomicReference; +import java.util.function.Function; /** * Represents a volume sender. A command sender with extra crap in it @@ -230,7 +231,7 @@ public class VolmitSender implements CommandSender { Iris.audiences.player(player()).showTitle(Title.title( createComponent(title), createComponent(subtitle), - Title.Times.of(Duration.ofMillis(i), Duration.ofMillis(s), Duration.ofMillis(o)))); + Title.Times.times(Duration.ofMillis(i), Duration.ofMillis(s), Duration.ofMillis(o)))); } public void sendProgress(double percent, String thing) { @@ -260,43 +261,43 @@ public class VolmitSender implements CommandSender { Iris.audiences.player(player()).showTitle(Title.title( createNoPrefixComponent(" "), createNoPrefixComponent(subtitle), - Title.Times.of(Duration.ofMillis(i), Duration.ofMillis(s), Duration.ofMillis(o)))); + Title.Times.times(Duration.ofMillis(i), Duration.ofMillis(s), Duration.ofMillis(o)))); } private Component createNoPrefixComponent(String message) { if(!IrisSettings.get().getGeneral().canUseCustomColors(this)) { - String t = C.translateAlternateColorCodes('&', MiniMessage.get().stripTokens(message)); - return MiniMessage.get().parse(t); + String t = C.translateAlternateColorCodes('&', MiniMessage.miniMessage().stripTags(message)); + return MiniMessage.miniMessage().deserialize(t); } String t = C.translateAlternateColorCodes('&', message); String a = C.aura(t, IrisSettings.get().getGeneral().getSpinh(), IrisSettings.get().getGeneral().getSpins(), IrisSettings.get().getGeneral().getSpinb(), 0.36); - return MiniMessage.get().parse(a); + return MiniMessage.miniMessage().deserialize(a); } private Component createNoPrefixComponentNoProcessing(String message) { - return MiniMessage.get().parse(message); + return MiniMessage.builder().postProcessor(c -> c).build().deserialize(message); } private Component createComponent(String message) { if(!IrisSettings.get().getGeneral().canUseCustomColors(this)) { - String t = C.translateAlternateColorCodes('&', MiniMessage.get().stripTokens(getTag() + message)); - return MiniMessage.get().parse(t); + String t = C.translateAlternateColorCodes('&', MiniMessage.miniMessage().stripTags(getTag() + message)); + return MiniMessage.miniMessage().deserialize(t); } String t = C.translateAlternateColorCodes('&', getTag() + message); String a = C.aura(t, IrisSettings.get().getGeneral().getSpinh(), IrisSettings.get().getGeneral().getSpins(), IrisSettings.get().getGeneral().getSpinb()); - return MiniMessage.get().parse(a); + return MiniMessage.miniMessage().deserialize(a); } private Component createComponentRaw(String message) { if(!IrisSettings.get().getGeneral().canUseCustomColors(this)) { - String t = C.translateAlternateColorCodes('&', MiniMessage.get().stripTokens(getTag() + message)); - return MiniMessage.get().parse(t); + String t = C.translateAlternateColorCodes('&', MiniMessage.miniMessage().stripTags(getTag() + message)); + return MiniMessage.miniMessage().deserialize(t); } String t = C.translateAlternateColorCodes('&', getTag() + message); - return MiniMessage.get().parse(t); + return MiniMessage.miniMessage().deserialize(t); } public void showWaiting(String passive, CompletableFuture f) { diff --git a/src/main/java/com/volmit/iris/util/uniques/U.java b/src/main/java/com/volmit/iris/util/uniques/U.java new file mode 100644 index 000000000..97f559104 --- /dev/null +++ b/src/main/java/com/volmit/iris/util/uniques/U.java @@ -0,0 +1,14 @@ +package com.volmit.iris.util.uniques; + +import java.io.File; + +public class U { + public static void main(String[] a) + { + UniqueRenderer r = new UniqueRenderer("helloworld", 2560 , 1440); + + r.writeCollectionFrames(new File("collection"), 1, 1024); + + System.exit(0); + } +} diff --git a/src/main/java/com/volmit/iris/util/uniques/UBufferedImage.java b/src/main/java/com/volmit/iris/util/uniques/UBufferedImage.java new file mode 100644 index 000000000..3211d49a2 --- /dev/null +++ b/src/main/java/com/volmit/iris/util/uniques/UBufferedImage.java @@ -0,0 +1,51 @@ +package com.volmit.iris.util.uniques; + +import java.awt.*; +import java.awt.image.BufferedImage; +import java.awt.image.ColorModel; +import java.awt.image.WritableRaster; + +public class UBufferedImage implements UImage { + private final BufferedImage buf; + + public UBufferedImage(BufferedImage buf) + { + this.buf = buf; + } + + @Override + public int getWidth() { + return buf.getWidth(); + } + + @Override + public int getHeight() { + return buf.getHeight(); + } + + @Override + public UImage copy() { + ColorModel cm = buf.getColorModel(); + boolean isAlphaPremultiplied = cm.isAlphaPremultiplied(); + WritableRaster raster = buf.copyData(null); + return new UBufferedImage(new BufferedImage(cm, raster, isAlphaPremultiplied, null)); + } + + @Override + public Color get(int x, int y) { + return new Color(buf.getRGB(x, y)); + } + + @Override + public void set(int x, int y, Color color) { + try + { + buf.setRGB(x, y, color.getRGB()); + } + + catch(Throwable e) + { + + } + } +} diff --git a/src/main/java/com/volmit/iris/util/uniques/UFeature.java b/src/main/java/com/volmit/iris/util/uniques/UFeature.java new file mode 100644 index 000000000..a06ccd00b --- /dev/null +++ b/src/main/java/com/volmit/iris/util/uniques/UFeature.java @@ -0,0 +1,77 @@ +package com.volmit.iris.util.uniques; + +import com.volmit.iris.engine.object.NoiseStyle; +import com.volmit.iris.util.function.Function2; +import com.volmit.iris.util.function.NoiseInjector; +import com.volmit.iris.util.interpolation.InterpolationMethod; +import com.volmit.iris.util.math.RNG; +import com.volmit.iris.util.noise.CNG; +import com.volmit.iris.util.stream.ProceduralStream; +import com.volmit.iris.util.stream.interpolation.Interpolated; + +import java.awt.*; +import java.awt.image.BufferedImage; +import java.util.List; +import java.util.function.Consumer; + +public interface UFeature { + List injectors = List.of( + CNG.ADD, + CNG.DST_MOD, + CNG.DST_POW, + CNG.DST_SUBTRACT, + CNG.MAX, + CNG.MIN, + CNG.SRC_MOD, + CNG.SRC_POW, + CNG.SRC_SUBTRACT, + CNG.MULTIPLY + ); + + void render(UImage image, RNG rng, double time, Consumer progressor, UFeatureMeta meta); + + default Color color(CNG hue, CNG saturation, CNG brightness, double x, double y, double t) + { + return Color.getHSBColor((float)hue.fitDouble(0, 1, x + t, y + t), + (float)saturation.fitDouble(0, 1, x + t, y + t), + (float)brightness.fitDouble(0, 1, x + t, y + t)); + } + + default InterpolationMethod interpolator(RNG rng) + { + return rng.pick( + UniqueRenderer.renderer.getInterpolators() + ); + } + + default CNG generator(String key, RNG rng, double scaleMod, long salt, UFeatureMeta meta) + { + return generator(key, rng, scaleMod, rng.i(1, 3), rng.i(1, 5), salt, meta); + } + + default CNG generator(String key, RNG rng, double scaleMod, int fractures, int composites, long salt, UFeatureMeta meta) + { + RNG rngg = rng.nextParallelRNG(salt); + CNG cng = rng.pick(UniqueRenderer.renderer.getStyles()).create(rngg).oct(rng.i(1, 5)); + RNG rngf = rngg.nextParallelRNG(-salt); + cng.scale(rngf.d(0.33 * scaleMod, 1.66 * scaleMod)); + + if(fractures > 0) + { + cng.fractureWith(generator(null, rngf.nextParallelRNG(salt + fractures), scaleMod / rng.d(4, 17), fractures-1, composites, salt + fractures + 55, null), scaleMod * rngf.nextDouble(16, 256)); + } + + for(int i = 0; i < composites; i++) + { + CNG sub = generator(null, rngf.nextParallelRNG(salt + fractures), scaleMod * rngf.d(0.4, 3.3), fractures / 3, 0, salt + fractures + composites + 78, null); + sub.setInjector(rng.pick(injectors)); + cng.child(sub); + } + + if(key != null && meta != null) + { + meta.registerGenerator(key, cng); + } + return cng; + } +} diff --git a/src/main/java/com/volmit/iris/util/uniques/UFeatureMeta.java b/src/main/java/com/volmit/iris/util/uniques/UFeatureMeta.java new file mode 100644 index 000000000..faa87fef1 --- /dev/null +++ b/src/main/java/com/volmit/iris/util/uniques/UFeatureMeta.java @@ -0,0 +1,102 @@ +package com.volmit.iris.util.uniques; + +import com.volmit.iris.engine.object.NoiseStyle; +import com.volmit.iris.util.collection.KList; +import com.volmit.iris.util.collection.KMap; +import com.volmit.iris.util.function.NoiseInjector; +import com.volmit.iris.util.interpolation.InterpolationMethod; +import com.volmit.iris.util.interpolation.IrisInterpolation; +import com.volmit.iris.util.noise.CNG; +import lombok.AllArgsConstructor; +import lombok.Data; +import lombok.NoArgsConstructor; + +import java.util.List; + +@Data +@NoArgsConstructor +public class UFeatureMeta { + private KMap interpolators; + private KMap generators; + private String feature; + + public void registerInterpolator(String key, InterpolationMethod method, double radius) + { + if(interpolators == null) + { + interpolators = new KMap<>(); + } + interpolators.put(key, new UFeatureMetaInterpolator(method, radius)); + } + + public void registerGenerator(String key, CNG cng) + { + if(generators == null) + { + generators = new KMap<>(); + } + generators.put(key, buildGenerator(cng)); + } + + public UFeatureMetaGenerator buildGenerator(CNG cng) + { + UFeatureMetaGenerator g = new UFeatureMetaGenerator(); + g.setScale(cng.getScale()); + g.setOctaves(cng.getOct()); + + if(cng.getFracture() != null) + { + g.setFracture(buildGenerator(cng.getFracture())); + g.setFractureMultiplier(cng.getFscale()); + } + + if(cng.getChildren() != null && cng.getChildren().isNotEmpty()) + { + g.setChildren(new KList<>()); + + for(CNG i : cng.getChildren()) + { + g.getChildren().add(buildGenerator(i)); + } + } + + if(cng.getInjector() == CNG.ADD){g.setParentInject("add");} + else if(cng.getInjector() == CNG.SRC_SUBTRACT){g.setParentInject("src_subtract");} + else if(cng.getInjector() == CNG.DST_SUBTRACT){g.setParentInject("dst_subtract");} + else if(cng.getInjector() == CNG.MULTIPLY ){g.setParentInject("multiply");} + else if(cng.getInjector() == CNG.MAX){g.setParentInject("max");} + else if(cng.getInjector() == CNG.MIN){g.setParentInject("min");} + else if(cng.getInjector() == CNG.SRC_MOD ){g.setParentInject("src_mod");} + else if(cng.getInjector() == CNG.SRC_POW ){g.setParentInject("src_pow");} + else if(cng.getInjector() == CNG.DST_MOD ){g.setParentInject("dst_mod");} + else if(cng.getInjector() == CNG.DST_POW){g.setParentInject("dst_pow");} + + return g; + } + + public boolean isEmpty() { + return (interpolators == null || interpolators.isEmpty()) && (generators == null || generators.isEmpty()); + } + + @Data + @NoArgsConstructor + @AllArgsConstructor + static class UFeatureMetaInterpolator + { + private InterpolationMethod interpolator; + private double radius; + } + + @Data + @NoArgsConstructor + static class UFeatureMetaGenerator + { + private NoiseStyle style; + private int octaves = 1; + private double scale = 1; + private String parentInject; + private UFeatureMetaGenerator fracture; + private Double fractureMultiplier; + private List children; + } +} diff --git a/src/main/java/com/volmit/iris/util/uniques/UImage.java b/src/main/java/com/volmit/iris/util/uniques/UImage.java new file mode 100644 index 000000000..821584a64 --- /dev/null +++ b/src/main/java/com/volmit/iris/util/uniques/UImage.java @@ -0,0 +1,20 @@ +package com.volmit.iris.util.uniques; + +import java.awt.*; + +public interface UImage { + int getWidth(); + + int getHeight(); + + default boolean isInBounds(int x, int y) + { + return x >= 0 && x < getWidth() && y >= 0 && y < getHeight(); + } + + UImage copy(); + + Color get(int x, int y); + + void set(int x, int y, Color color); +} diff --git a/src/main/java/com/volmit/iris/util/uniques/UMeta.java b/src/main/java/com/volmit/iris/util/uniques/UMeta.java new file mode 100644 index 000000000..f5ba9aae6 --- /dev/null +++ b/src/main/java/com/volmit/iris/util/uniques/UMeta.java @@ -0,0 +1,56 @@ +package com.volmit.iris.util.uniques; + +import com.google.gson.Gson; +import com.google.gson.GsonBuilder; +import com.volmit.iris.engine.object.NoiseStyle; +import com.volmit.iris.util.collection.KList; +import com.volmit.iris.util.collection.KMap; +import com.volmit.iris.util.interpolation.InterpolationMethod; +import com.volmit.iris.util.io.IO; +import com.volmit.iris.util.noise.CNG; +import lombok.AllArgsConstructor; +import lombok.Data; +import lombok.NoArgsConstructor; + +import javax.imageio.ImageIO; +import java.awt.image.BufferedImage; +import java.io.File; +import java.io.IOException; +import java.util.List; + +@Data +@NoArgsConstructor +public class UMeta { + private transient BufferedImage image; + private KMap features; + private long id; + private double time; + private int width; + private int height; + + public void registerFeature(String key, UFeatureMeta feature) + { + if(features == null) + { + features = new KMap<>(); + } + + features.put(key, feature); + } + + public void export(File destination) throws IOException { + + for(String i : features.k()) + { + if(features.get(i).isEmpty()) + { + features.remove(i); + } + } + + width = image.getWidth(); + height = image.getHeight(); + ImageIO.write(image, "PNG", destination); + IO.writeAll(new File(destination.getParentFile(), destination.getName() + ".json"), new GsonBuilder().setPrettyPrinting().create().toJson(this)); + } +} diff --git a/src/main/java/com/volmit/iris/util/uniques/UniqueRenderer.java b/src/main/java/com/volmit/iris/util/uniques/UniqueRenderer.java new file mode 100644 index 000000000..a8b80e3fe --- /dev/null +++ b/src/main/java/com/volmit/iris/util/uniques/UniqueRenderer.java @@ -0,0 +1,338 @@ +package com.volmit.iris.util.uniques; + +import com.volmit.iris.Iris; +import com.volmit.iris.engine.object.NoiseStyle; +import com.volmit.iris.util.collection.KList; +import com.volmit.iris.util.collection.KMap; +import com.volmit.iris.util.format.Form; +import com.volmit.iris.util.function.NoiseProvider; +import com.volmit.iris.util.interpolation.InterpolationMethod; +import com.volmit.iris.util.interpolation.IrisInterpolation; +import com.volmit.iris.util.math.RNG; +import com.volmit.iris.util.noise.CNG; +import com.volmit.iris.util.parallel.BurstExecutor; +import com.volmit.iris.util.parallel.MultiBurst; +import com.volmit.iris.util.scheduling.ChronoLatch; +import com.volmit.iris.util.scheduling.J; +import com.volmit.iris.util.scheduling.PrecisionStopwatch; +import com.volmit.iris.util.stream.ProceduralStream; +import com.volmit.iris.util.uniques.features.*; + +import javax.imageio.ImageIO; +import java.awt.*; +import java.awt.image.BufferedImage; +import java.io.File; +import java.util.List; +import java.util.Locale; +import java.util.concurrent.ExecutorService; +import java.util.concurrent.Executors; +import java.util.concurrent.atomic.AtomicInteger; + +public class UniqueRenderer { + static UniqueRenderer renderer; + + static final List backgrounds = List.of(new UFWarpedBackground()); + static final List interpolators = List.of(new UFInterpolator(), new UFNOOP()); + static final List features = List.of(new UFWarpedLines(), new UFWarpedDisc(), new UFWarpedDots(), new UFWarpedCircle()); + private final String seed; + private final ProceduralStream spatialSeed; + private final int width; + private final int height; + private final KMap writing = new KMap<>(); + private KList sortedStyles = new KList(); + private KList sortedInterpolators = new KList(); + int cores = Runtime.getRuntime().availableProcessors(); + private final ExecutorService executor = Executors.newFixedThreadPool(Runtime.getRuntime().availableProcessors() * 2); + + public UniqueRenderer(String seed, int width, int height) + { + renderer = this; + computeNoiseStyles(3000, 2); + computeInterpolationMethods(3000, 2); + this.seed = seed; + this.width = width; + this.height = height; + spatialSeed = NoiseStyle.FRACTAL_WATER.stream(new RNG(seed)).convert((d) -> new RNG(Math.round(seed.hashCode() + (d * 934321234D)))); + new Thread(() -> { + while(true) + { + J.sleep(5000); + + if(!writing.isEmpty()) + { + System.out.println(Form.repeat("\n", 60)); + System.out.println(Form.memSize(Runtime.getRuntime().totalMemory() - Runtime.getRuntime().freeMemory(), 2) + " of " + Form.memSize(Runtime.getRuntime().totalMemory(), 2)); + KMap c = writing.copy(); + + for(String i : writing.k().sort()) + { + String prog = ""; + String f = writing.get(i); + + if(f.contains("%")) + { + String v = f.split("\\Q%\\E")[0]; + try + { + prog = drawProgress(Double.valueOf(Integer.parseInt(v.substring(v.length() - 2))) / 100D, 30); + } + + catch(Throwable e) + { + try + { + prog = drawProgress(Double.valueOf(Integer.parseInt(v.substring(v.length() - 1))) / 100D, 30); + } + + catch(Throwable ee) + { + try + { + prog = drawProgress(Double.valueOf(Integer.parseInt(v.substring(v.length() - 3))) / 100D, 30); + } + + catch(Throwable eee) + { + + } + } + } + } + + System.out.println(prog + " " + i + " => " + f); + } + } + } + }).start(); + } + + public UMeta renderFrameBuffer(long id, double t) + { + UMeta meta = new UMeta(); + meta.setId(id); + meta.setTime(t); + RNG rng = spatialSeed.get(id, id + ((id * id) % (id / 3D))); + RNG rngbg = spatialSeed.get(id, -id + ((id * id) % (id / 4D))); + BufferedImage buf = new BufferedImage(width, height, BufferedImage.TYPE_INT_ARGB); + BufferedImage bufFG = new BufferedImage(width, height, BufferedImage.TYPE_INT_ARGB); + UImage image = new UBufferedImage(buf); + UImage imageFG = new UBufferedImage(bufFG); + ChronoLatch cl = new ChronoLatch(250); + UFeature background = rng.pick(backgrounds); + UFeature interpolator = rng.pick(interpolators); + UFeature foreground = rng.pick(features); + UFeature foregroundInterpolator = rng.pick(interpolators); + UFeatureMeta backgroundMeta = new UFeatureMeta(); + UFeatureMeta foregroundMeta = new UFeatureMeta(); + UFeatureMeta backgroundInterpolatorMeta = new UFeatureMeta(); + UFeatureMeta foregroundInterpolatorMeta = new UFeatureMeta(); + background.render(image, rngbg, t, (p) -> { + if(cl.flip()) + { + writing.put("#" + id + ":" + t, Form.pc(p / 4D) + " [" + background.getClass().getSimpleName() + " " + Form.pc(p) + "]"); + } + }, backgroundMeta); + backgroundMeta.setFeature(background.getClass().getSimpleName()); + meta.registerFeature("background", backgroundMeta); + interpolator.render(image, rng, t, (p) -> { + if(cl.flip()) + { + writing.put("#" + id + ":" + t, Form.pc(0.25 + (p / 4d)) + " [" + interpolator.getClass().getSimpleName() + " " + Form.pc(p) + "]"); + } + }, backgroundInterpolatorMeta); + backgroundInterpolatorMeta.setFeature(interpolator.getClass().getSimpleName()); + meta.registerFeature("backgroundInterpolator", backgroundInterpolatorMeta); + foreground.render(imageFG, rng, t, (p) -> { + if(cl.flip()) + { + writing.put("#" + id + ":" + t, Form.pc(0.5 + (p / 4d)) + " [" + foreground.getClass().getSimpleName() + " " + Form.pc(p) + "]"); + } + }, foregroundMeta); + foregroundMeta.setFeature(foreground.getClass().getSimpleName()); + meta.registerFeature("foreground", foregroundMeta); + overlay(imageFG, bufFG, image); + foregroundInterpolator.render(image, rng, t, (p) -> { + if(cl.flip()) + { + writing.put("#" + id + ":" + t, Form.pc(0.75 + (p / 4d)) + " [" + interpolator.getClass().getSimpleName() + " " + Form.pc(p) + "]"); + } + }, foregroundInterpolatorMeta); + foregroundInterpolatorMeta.setFeature(foregroundInterpolator.getClass().getSimpleName()); + meta.registerFeature("foregroundInterpolator", foregroundInterpolatorMeta); + overlay(imageFG, bufFG, image); + meta.setImage(buf); + writing.remove("#" + id + ":" + t); + return meta; + } + +private void overlay(UImage layer, BufferedImage layerBuf, UImage onto) +{ + for(int i = 0; i < onto.getWidth(); i++) + { + for(int j = 0; j < onto.getHeight(); j++) + { + if(layerBuf.getRGB(i, j) != 0) + { + onto.set(i, j, layer.get(i, j)); + } + } + } +} + + private String drawProgress(double progress, int len) + { + int max = len; + int in = (int) Math.round(progress * max); + max -= in; + + return "[" + Form.repeat("=", in) + Form.repeat(" ", max)+ "]"; + } + + private void computeNoiseStyles(double time, double scope) { + List allowedStyles = new KList<>(NoiseStyle.values()); + allowedStyles.remove(NoiseStyle.FLAT); + KMap speeds = new KMap<>(); + double allocateMS = time; + double maxTestDuration = allocateMS / allowedStyles.size(); + System.out.println("Running Noise Style Benchmark for " + Form.duration(allocateMS, 0) + "."); + System.out.println("Benchmarking " + allowedStyles.size() + " + Noise Styles for " + Form.duration(maxTestDuration, 1) + " each."); + System.out.println(); + + for(NoiseStyle i : allowedStyles) + { + int score = 0; + CNG cng = i.create(new RNG("renderspeedtest")); + PrecisionStopwatch p = PrecisionStopwatch.start(); + double g = 0; + while(p.getMilliseconds() < maxTestDuration) + { + cng.noise(g, -g * 2); + g+= 0.1; + g *= 1.25; + score++; + } + + speeds.put(i, score); + } + + for(NoiseStyle i : speeds.sortKNumber()) + { + System.out.println(Form.capitalizeWords(i.name().toLowerCase(Locale.ROOT).replaceAll("\\Q_\\E", " ")) + " => " + Form.f(speeds.get(i))); + } + System.out.println(); + int takeUpTo = (int) Math.max(1, scope * speeds.size()); + System.out.println("Choosing the fastest " + Form.pc(scope) + " styles (" + takeUpTo + ")"); + + for(NoiseStyle i : speeds.sortKNumber().reverse()) + { + if(takeUpTo-- <= 0) + { + break; + } + + sortedStyles.add(i); + System.out.println("- " + Form.capitalizeWords(i.name().toLowerCase(Locale.ROOT).replaceAll("\\Q_\\E", " "))); + } + } + + private void computeInterpolationMethods(double time, double scope) { + List allowedStyles = new KList<>(InterpolationMethod.values()); + allowedStyles.remove(InterpolationMethod.NONE); + KMap speeds = new KMap<>(); + double allocateMS = time; + double maxTestDuration = allocateMS / allowedStyles.size(); + System.out.println("Running Interpolation Method Benchmark for " + Form.duration(allocateMS, 0) + "."); + System.out.println("Benchmarking " + allowedStyles.size() + " + Interpolation Methods for " + Form.duration(maxTestDuration, 1) + " each."); + System.out.println(); + + RNG r = new RNG("renderspeedtestinterpolation"); + CNG cng = NoiseStyle.SIMPLEX.create(r); + NoiseProvider np = (x, z) -> cng.noise(x, z); + + for(InterpolationMethod i : allowedStyles) + { + int score = 0; + + PrecisionStopwatch p = PrecisionStopwatch.start(); + double g = 0; + while(p.getMilliseconds() < maxTestDuration) + { + IrisInterpolation.getNoise(i, (int) g, (int) (-g * 2.225), r.d(4, 64), np); + cng.noise(g, -g * 2); + g+= 1.1; + g *= 1.25; + score++; + } + + speeds.put(i, score); + } + + for(InterpolationMethod i : speeds.sortKNumber()) + { + System.out.println(Form.capitalizeWords(i.name().toLowerCase(Locale.ROOT).replaceAll("\\Q_\\E", " ")) + " => " + Form.f(speeds.get(i))); + } + System.out.println(); + int takeUpTo = (int) Math.max(1, scope * speeds.size()); + System.out.println("Choosing the fastest " + Form.pc(scope) + " interpolators (" + takeUpTo + ")"); + + for(InterpolationMethod i : speeds.sortKNumber().reverse()) + { + if(takeUpTo-- <= 0) + { + break; + } + + sortedInterpolators.add(i); + System.out.println("- " + Form.capitalizeWords(i.name().toLowerCase(Locale.ROOT).replaceAll("\\Q_\\E", " "))); + } + } + + public void writeCollectionFrames(File folder, int fromId, int toId) + { + folder.mkdirs(); + BurstExecutor burst = new BurstExecutor(executor, Math.min(toId - fromId, 1000)); + burst.setMulticore(true); + AtomicInteger ai = new AtomicInteger(0); + int max = toId - fromId; + + for(int i = fromId; i <= toId; i++) + { + int ii = i; + burst.queue(() -> { + + writing.put("!#[" + fromId + "-" + toId + "] Collection", ai.get() + " of " + max + " (" + Form.pc(ai.get() / (double)max, 0) + ")"); + writeFrame(new File(folder, ii + ".png"), ii, 0); + ai.incrementAndGet(); + writing.put("!#[" + fromId + "-" + toId + "] Collection", ai.get() + " of " + max + " (" + Form.pc(ai.get() /(double) max, 0) + ")"); + }); + } + + burst.complete(); + writing.remove("!#[" + fromId + "-" + toId + "] Collection"); + } + + public void writeFrame(File destination, long id, double t) { + try + { + renderFrameBuffer(id, t).export(destination); + } + + catch(Throwable e) + { + e.printStackTrace(); + } + } + + public void report(String s) + { + System.out.println(s); + } + + public KList getStyles() { + return sortedStyles; + } + + public List getInterpolators() { + return sortedInterpolators; + } +} diff --git a/src/main/java/com/volmit/iris/util/uniques/features/UFInterpolator.java b/src/main/java/com/volmit/iris/util/uniques/features/UFInterpolator.java new file mode 100644 index 000000000..e2cfecf8f --- /dev/null +++ b/src/main/java/com/volmit/iris/util/uniques/features/UFInterpolator.java @@ -0,0 +1,64 @@ +package com.volmit.iris.util.uniques.features; + +import com.volmit.iris.util.function.NoiseProvider; +import com.volmit.iris.util.interpolation.InterpolationMethod; +import com.volmit.iris.util.interpolation.IrisInterpolation; +import com.volmit.iris.util.math.M; +import com.volmit.iris.util.math.RNG; +import com.volmit.iris.util.noise.CNG; +import com.volmit.iris.util.uniques.UFeature; +import com.volmit.iris.util.uniques.UFeatureMeta; +import com.volmit.iris.util.uniques.UImage; +import com.volmit.iris.util.uniques.UniqueRenderer; + +import java.awt.*; +import java.util.function.Consumer; + +public class UFInterpolator implements UFeature { + @Override + public void render(UImage image, RNG rng, double t, Consumer progressor, UFeatureMeta meta) { + UImage ref = image.copy(); + CNG rmod = generator("interpolator_radius", rng, 1, 33004, meta); + + NoiseProvider nHue = (x, y) -> { + int ix = Math.abs(((int)x)%ref.getWidth()); + int iy = Math.abs(((int)y)%ref.getHeight()); + Color color = ref.get(ix, iy); + float[] hsv = new float[3]; + Color.RGBtoHSB(color.getRed(), color.getGreen(), color.getGreen(), hsv); + return hsv[0]; + }; + NoiseProvider nSat = (x, y) -> { + int ix = Math.abs(((int)x)%ref.getWidth()); + int iy = Math.abs(((int)y)%ref.getHeight()); + Color color = ref.get(ix, iy); + float[] hsv = new float[3]; + Color.RGBtoHSB(color.getRed(), color.getGreen(), color.getGreen(), hsv); + return hsv[1]; + }; + NoiseProvider nBri = (x, y) -> { + int ix = Math.abs(((int)x)%ref.getWidth()); + int iy = Math.abs(((int)y)%ref.getHeight()); + Color color = ref.get(ix, iy); + float[] hsv = new float[3]; + Color.RGBtoHSB(color.getRed(), color.getGreen(), color.getGreen(), hsv); + return hsv[2]; + }; + InterpolationMethod method = interpolator(rng); + int sizeMin = Math.min(image.getWidth(), image.getHeight()); + double radius = Math.max(4, rmod.fit(sizeMin / 256, sizeMin / 4, t * rng.d(0.03, 1.25), t * rng.d(0.01, 2.225))); + for(int i = 0; i < image.getWidth(); i++) + { + for(int j = 0; j < image.getHeight(); j++) + { + image.set(i, j, Color.getHSBColor( + (float)Math.max(Math.min(1D, IrisInterpolation.getNoise(method, i, j, radius, nHue)), 0D), + (float)Math.max(Math.min(1D, IrisInterpolation.getNoise(method, i, j, radius, nSat)), 0D), + (float)Math.max(Math.min(1D, IrisInterpolation.getNoise(method, i, j, radius, nBri)), 0D) + )); + } + + progressor.accept(i / (double)image.getWidth()); + } + } +} diff --git a/src/main/java/com/volmit/iris/util/uniques/features/UFNOOP.java b/src/main/java/com/volmit/iris/util/uniques/features/UFNOOP.java new file mode 100644 index 000000000..76c4db56b --- /dev/null +++ b/src/main/java/com/volmit/iris/util/uniques/features/UFNOOP.java @@ -0,0 +1,16 @@ +package com.volmit.iris.util.uniques.features; + +import com.volmit.iris.util.math.RNG; +import com.volmit.iris.util.noise.CNG; +import com.volmit.iris.util.uniques.UFeature; +import com.volmit.iris.util.uniques.UFeatureMeta; +import com.volmit.iris.util.uniques.UImage; + +import java.awt.*; +import java.util.function.Consumer; + +public class UFNOOP implements UFeature { + @Override + public void render(UImage image, RNG rng, double t, Consumer progressor, UFeatureMeta meta) { + } +} diff --git a/src/main/java/com/volmit/iris/util/uniques/features/UFWarpedBackground.java b/src/main/java/com/volmit/iris/util/uniques/features/UFWarpedBackground.java new file mode 100644 index 000000000..da5f0e411 --- /dev/null +++ b/src/main/java/com/volmit/iris/util/uniques/features/UFWarpedBackground.java @@ -0,0 +1,30 @@ +package com.volmit.iris.util.uniques.features; + +import com.volmit.iris.util.math.RNG; +import com.volmit.iris.util.noise.CNG; +import com.volmit.iris.util.uniques.UFeature; +import com.volmit.iris.util.uniques.UFeatureMeta; +import com.volmit.iris.util.uniques.UImage; + +import java.awt.*; +import java.util.function.Consumer; + +public class UFWarpedBackground implements UFeature { + @Override + public void render(UImage image, RNG rng, double t, Consumer progressor, UFeatureMeta meta) { + CNG hue = generator("color_hue", rng, rng.d(0.001, rng.d(2, 5)), rng.i(0, 3) ,rng.i(0, 3), 31007, meta); + CNG sat = generator("color_sat", rng, rng.d(0.001, rng.d(2, 5)), rng.i(0, 2) ,rng.i(0, 2), 33004, meta); + CNG bri = generator("color_bri", rng, rng.d(0.001, rng.d(2, 5)), rng.i(0, 1) ,rng.i(0, 1), 32005, meta).patch(0.145); + double tcf = rng.d(0.15, 0.55); + + for(int i = 0; i < image.getWidth(); i++) + { + for(int j = 0; j < image.getHeight(); j++) + { + image.set(i, j, color(hue, sat, bri, i, j, tcf * t)); + } + + progressor.accept(i / (double)image.getWidth()); + } + } +} diff --git a/src/main/java/com/volmit/iris/util/uniques/features/UFWarpedCircle.java b/src/main/java/com/volmit/iris/util/uniques/features/UFWarpedCircle.java new file mode 100644 index 000000000..2d73ee01b --- /dev/null +++ b/src/main/java/com/volmit/iris/util/uniques/features/UFWarpedCircle.java @@ -0,0 +1,50 @@ +package com.volmit.iris.util.uniques.features; + +import com.volmit.iris.util.math.RNG; +import com.volmit.iris.util.noise.CNG; +import com.volmit.iris.util.uniques.UFeature; +import com.volmit.iris.util.uniques.UFeatureMeta; +import com.volmit.iris.util.uniques.UImage; + +import java.awt.*; +import java.awt.image.BufferedImage; +import java.util.function.Consumer; + +public class UFWarpedCircle implements UFeature { + @Override + public void render(UImage image, RNG rng, double t, Consumer progressor, UFeatureMeta meta) { + double r = Math.min(image.getWidth(), image.getHeight()) / 2.5D; + double i, angle, x1, y1; + CNG xShift = generator("x_warp", rng, 0.6, 1001, meta); + CNG yShift = generator("y_warp", rng, 0.6, 1002, meta); + CNG hue = generator("color_hue", rng, rng.d(0.25, 2.5), 1003, meta); + CNG sat = generator("color_sat",rng, rng.d(0.25, 2.5), 1004, meta); + CNG bri = generator("color_bri",rng, rng.d(0.25, 2.5), 1005, meta); + double tcf = rng.d(0.75, 11.25); + double rcf = rng.d(7.75, 16.25); + int x = image.getWidth()/2; + int y = image.getHeight()/2; + + for(int d = 0; d < 256; d++) + { + r -= Math.min(image.getWidth(), image.getHeight()) / 300D; + + if(r <= 0) + { + return; + } + + for(i = 0; i < 360; i += 0.1) + { + angle = i; + x1 = r * Math.cos(angle * Math.PI / 180); + y1 = r * Math.sin(angle * Math.PI / 180); + image.set((int)Math.round(x + x1 + xShift.fit(-r/2, r/2, x1 + (t+ (d * 8)), -y1 + (t+ (d * 8)))), + (int)Math.round(y + y1 + yShift.fit(-r/2, r/2, y1 + (t+ (d * 8)), -x1 + (t+ (d * 8)))), + color(hue, sat, bri, x1, y1, (t * tcf) + (d * rcf))); + } + + progressor.accept(d / 256D); + } + } +} diff --git a/src/main/java/com/volmit/iris/util/uniques/features/UFWarpedDisc.java b/src/main/java/com/volmit/iris/util/uniques/features/UFWarpedDisc.java new file mode 100644 index 000000000..b394f2c7c --- /dev/null +++ b/src/main/java/com/volmit/iris/util/uniques/features/UFWarpedDisc.java @@ -0,0 +1,39 @@ +package com.volmit.iris.util.uniques.features; + +import com.volmit.iris.util.math.RNG; +import com.volmit.iris.util.noise.CNG; +import com.volmit.iris.util.uniques.UFeature; +import com.volmit.iris.util.uniques.UFeatureMeta; +import com.volmit.iris.util.uniques.UImage; + +import java.util.function.Consumer; + +public class UFWarpedDisc implements UFeature { + @Override + public void render(UImage image, RNG rng, double t, Consumer progressor, UFeatureMeta meta) { + double r = Math.min(image.getWidth(), image.getHeight()) / 3D; + CNG xShift = generator("x_warp", rng, 0.6, 1001, meta); + CNG yShift = generator("y_warp",rng, 0.6, 1002, meta); + CNG hue = generator("color_hue",rng, rng.d(0.25, 2.5), 1003, meta); + CNG sat = generator("color_sat",rng, rng.d(0.25, 2.5), 1004, meta); + CNG bri = generator("color_bri",rng, rng.d(0.25, 2.5), 1005, meta); + double tcf = rng.d(0.75, 11.25); + int x = image.getWidth()/2; + int y = image.getHeight()/2; + + for(int i = (int)( x - r); i < x+r; i++) + { + for(int j =(int)( y - r); j < y+r; j++) + { + if(image.isInBounds(i, j) && Math.pow(x - i, 2) + Math.pow(y - j, 2) <= r*r) + { + image.set(Math.round(i + xShift.fit(-r/2, r/2, i+t, -j+t)), + Math.round(j + yShift.fit(-r/2, r/2, j+t, -i+t)), + color(hue, sat, bri, i, j, tcf * t)); + } + } + + progressor.accept(i / (x + r)); + } + } +} diff --git a/src/main/java/com/volmit/iris/util/uniques/features/UFWarpedDots.java b/src/main/java/com/volmit/iris/util/uniques/features/UFWarpedDots.java new file mode 100644 index 000000000..a9670600e --- /dev/null +++ b/src/main/java/com/volmit/iris/util/uniques/features/UFWarpedDots.java @@ -0,0 +1,48 @@ +package com.volmit.iris.util.uniques.features; + +import com.volmit.iris.util.math.RNG; +import com.volmit.iris.util.noise.CNG; +import com.volmit.iris.util.uniques.UFeature; +import com.volmit.iris.util.uniques.UFeatureMeta; +import com.volmit.iris.util.uniques.UImage; + +import java.awt.*; +import java.util.function.Consumer; + +public class UFWarpedDots implements UFeature { + @Override + public void render(UImage image, RNG rng, double t, Consumer progressor, UFeatureMeta meta) { + CNG genX = generator("x_pos", rng, 4, 2000, meta); + CNG genY = generator("y_pos", rng, 4, 2001, meta); + + double tcf = rng.d(0.75, 11.25); + + for(int i = 1; i <= 8; i++) + { + CNG xShift = generator("x_warp_" + i, rng, 2, 2006+i, meta); + CNG yShift = generator("y_warp_" + i,rng, 2, 2007+i, meta); + CNG hue = generator("color_hue_" + i,rng, rng.d(0.55, 3.5), 2003+i, meta); + CNG sat = generator("color_sat_" + i,rng, rng.d(0.55, 3.5), 2004+i, meta); + CNG bri = generator("color_bri_" + i,rng, rng.d(0.55, 3.5), 2005+i, meta); + int x = genX.fit(0, image.getWidth(), i * 128, i * 5855); + int y = genY.fit(0, image.getHeight(), i * 128, i * 5855); + Color color = color(hue, sat, bri, x, y, t); + double r = Math.max(genX.fit(image.getWidth() / 10, image.getWidth() / 6, x, y), genY.fit(image.getHeight() / 10, image.getHeight() / 6, x, y)); + + for(int j = (int)(x - r); j < x + r; j++) + { + for(int k = (int)(y - r); k < y + r; k++) + { + if(image.isInBounds(j, k) && Math.pow(x - j, 2) + Math.pow(y - k, 2) <= r*r) + { + image.set(Math.round(j + xShift.fit(-r/2, r/2, j+t, -k+t)), + Math.round(k + yShift.fit(-r/2, r/2, k+t, -j+t)), + color(hue, sat, bri, j, k, tcf * t)); + } + } + } + + progressor.accept(i / 32D); + } + } +} diff --git a/src/main/java/com/volmit/iris/util/uniques/features/UFWarpedLines.java b/src/main/java/com/volmit/iris/util/uniques/features/UFWarpedLines.java new file mode 100644 index 000000000..badfdb79e --- /dev/null +++ b/src/main/java/com/volmit/iris/util/uniques/features/UFWarpedLines.java @@ -0,0 +1,47 @@ +package com.volmit.iris.util.uniques.features; + +import com.volmit.iris.util.math.RNG; +import com.volmit.iris.util.noise.CNG; +import com.volmit.iris.util.uniques.UFeature; +import com.volmit.iris.util.uniques.UFeatureMeta; +import com.volmit.iris.util.uniques.UImage; + +import java.util.function.Consumer; + +public class UFWarpedLines implements UFeature { + @Override + public void render(UImage image, RNG rng, double t, Consumer progressor, UFeatureMeta meta) { + for(int g = 1; g < 5; g++) + { + CNG xShift = generator("x_warp_"+g, rng, 0.6, 1001 * g, meta); + CNG yShift = generator("y_warp_"+g, rng, 0.6, 1002 * g, meta); + CNG cX = generator("x_clip_"+g, rng, rng.d(0.035, 0.6), 77001 * g, meta); + CNG cY = generator("y_clip"+g, rng, rng.d(0.035, 0.6), 77002, meta); + CNG hue = generator("color_hue_"+g, rng, rng.d(0.25, 2.5), 1003 * g, meta); + CNG sat = generator("color_sat_"+g, rng, rng.d(0.25, 2.5), 1004 * g, meta); + CNG bri = generator("color_bri_"+g, rng, rng.d(0.25, 2.5), 1005 * g, meta); + double tcf = rng.d(0.75, 11.25 + (g * 4)); + double rcf = rng.d(7.75, 16.25 + (g * 5)); + double xcf = rng.d(0.15, 0.55 + (g * 0.645)); + double w = rng.d(64, 186 + (g * 8)); + double ww = image.getWidth() / rng.d(3, 9); + double hh = image.getHeight() / rng.d(3, 9); + boolean wh = rng.nextBoolean(); + double sa = rng.d(0.35, 0.66); + double sb = rng.d(0.35, 0.66); + + for(int i = 0; i < image.getWidth(); i+= (wh ? image.getWidth() / w : 1)) + { + for(int j = 0; j < image.getHeight(); j+= (!wh ? image.getHeight() / w : 1)) + { + if(cX.fitDouble(0, 1, i, -j, t * xcf) > sa && cY.fitDouble(0, 1, -j, i, t * xcf) > sb) + { + image.set(Math.round(i + xShift.fit(-ww, ww, i, j, (t * rcf))), + Math.round(j + yShift.fit(-hh, hh, -j, i, (t * rcf))), + color(hue, sat, bri, i, j, (t * tcf))); + } + } + } + } + } +}