diff --git a/src/main/java/ru/betterend/integration/byg/biomes/BYGBiomes.java b/src/main/java/ru/betterend/integration/byg/biomes/BYGBiomes.java index 8d426eb2..0211415c 100644 --- a/src/main/java/ru/betterend/integration/byg/biomes/BYGBiomes.java +++ b/src/main/java/ru/betterend/integration/byg/biomes/BYGBiomes.java @@ -7,12 +7,14 @@ import ru.betterend.world.biome.EndBiome; public class BYGBiomes { // New Biomes public static final EndBiome OLD_BULBIS_GARDENS = EndBiomes.registerSubBiomeIntegration(new OldBulbisGardens()); + public static final EndBiome NIGHTSHADE_REDWOODS = EndBiomes.registerSubBiomeIntegration(new NightshadeRedwoods()); //public static final EndBiome ETHERIAL_GROVE = EndBiomes.registerSubBiomeIntegration(new EterialGrove()); public static void register() {} public static void addBiomes() { EndBiomes.addSubBiomeIntegration(OLD_BULBIS_GARDENS, Integrations.BYG.getID("bulbis_gardens")); + EndBiomes.addSubBiomeIntegration(NIGHTSHADE_REDWOODS, Integrations.BYG.getID("nightshade_forest")); //EndBiomes.addSubBiomeIntegration(ETHERIAL_GROVE, Integrations.BYG.getID("ethereal_islands")); } } diff --git a/src/main/java/ru/betterend/integration/byg/biomes/NightshadeRedwoods.java b/src/main/java/ru/betterend/integration/byg/biomes/NightshadeRedwoods.java new file mode 100644 index 00000000..bdc95139 --- /dev/null +++ b/src/main/java/ru/betterend/integration/byg/biomes/NightshadeRedwoods.java @@ -0,0 +1,56 @@ +package ru.betterend.integration.byg.biomes; + +import java.util.List; + +import net.minecraft.entity.SpawnGroup; +import net.minecraft.particle.ParticleTypes; +import net.minecraft.sound.SoundEvent; +import net.minecraft.world.biome.Biome; +import net.minecraft.world.biome.BiomeEffects; +import net.minecraft.world.biome.SpawnSettings.SpawnEntry; +import ru.betterend.BetterEnd; +import ru.betterend.integration.Integrations; +import ru.betterend.integration.byg.features.BYGFeatures; +import ru.betterend.registry.EndFeatures; +import ru.betterend.world.biome.BiomeDefinition; +import ru.betterend.world.biome.EndBiome; + +public class NightshadeRedwoods extends EndBiome { + public NightshadeRedwoods() { + super(makeDef()); + } + + private static BiomeDefinition makeDef() { + Biome biome = Integrations.BYG.getBiome("nightshade_forest"); + BiomeEffects effects = biome.getEffects(); + + BiomeDefinition def = new BiomeDefinition("nightshade_redwoods") + .setFogColor(140, 108, 47) + .setFogDensity(1.5F) + .setWaterAndFogColor(55, 70, 186) + .setFoliageColor(122, 17, 155) + .setParticles(ParticleTypes.REVERSE_PORTAL, 0.002F) + .setSurface(biome.getGenerationSettings().getSurfaceBuilder().get()) + .setGrassColor(48, 13, 89) + .setPlantsColor(200, 125, 9) + .addFeature(EndFeatures.END_LAKE_RARE) + .addFeature(BYGFeatures.NIGHTSHADE_REDWOOD_TREE); + + if (BetterEnd.isClient()) { + SoundEvent loop = effects.getLoopSound().get(); + SoundEvent music = effects.getMusic().get().getSound(); + SoundEvent additions = effects.getAdditionsSound().get().getSound(); + SoundEvent mood = effects.getMoodSound().get().getSound(); + def.setLoop(loop).setMusic(music).setAdditions(additions).setMood(mood); + } + + for (SpawnGroup group: SpawnGroup.values()) { + List list = biome.getSpawnSettings().getSpawnEntry(group); + list.forEach((entry) -> { + def.addMobSpawn(entry); + }); + } + + return def; + } +} diff --git a/src/main/java/ru/betterend/integration/byg/features/BYGFeatures.java b/src/main/java/ru/betterend/integration/byg/features/BYGFeatures.java index 8388142f..28b28ece 100644 --- a/src/main/java/ru/betterend/integration/byg/features/BYGFeatures.java +++ b/src/main/java/ru/betterend/integration/byg/features/BYGFeatures.java @@ -18,6 +18,7 @@ public class BYGFeatures { public static final EndFeature BULBIS_ODDITY = new EndFeature("bulbis_oddity", new SinglePlantFeature(Integrations.BYG.getBlock("bulbis_oddity"), 4, 4), 5); public static final EndFeature PURPLE_BULBIS_ODDITY = new EndFeature("purple_bulbis_oddity", new SinglePlantFeature(Integrations.BYG.getBlock("purple_bulbis_oddity"), 4, 4), 5); + public static final EndFeature NIGHTSHADE_REDWOOD_TREE = new EndFeature("nightshade_redwood_tree", new NightshadeRedwoodTreeFeature(), 1); public static final EndFeature BIG_ETHER_TREE = new EndFeature("big_ether_tree", new BigEtherTreeFeature(), 1); public static final ConfiguredFeature BULBIS_TREES = Integrations.BYG.getConfiguredFeature("rs_sparse_bulbis_tree"); diff --git a/src/main/java/ru/betterend/integration/byg/features/NightshadeRedwoodTreeFeature.java b/src/main/java/ru/betterend/integration/byg/features/NightshadeRedwoodTreeFeature.java new file mode 100644 index 00000000..554d2002 --- /dev/null +++ b/src/main/java/ru/betterend/integration/byg/features/NightshadeRedwoodTreeFeature.java @@ -0,0 +1,165 @@ +package ru.betterend.integration.byg.features; + +import java.util.List; +import java.util.Random; + +import com.google.common.base.Function; +import com.google.common.collect.Lists; + +import net.minecraft.block.BlockState; +import net.minecraft.block.Blocks; +import net.minecraft.block.LeavesBlock; +import net.minecraft.block.Material; +import net.minecraft.client.util.math.Vector3f; +import net.minecraft.util.math.BlockPos; +import net.minecraft.util.math.BlockPos.Mutable; +import net.minecraft.world.StructureWorldAccess; +import net.minecraft.world.gen.chunk.ChunkGenerator; +import net.minecraft.world.gen.feature.DefaultFeatureConfig; +import ru.betterend.integration.Integrations; +import ru.betterend.registry.EndTags; +import ru.betterend.util.MHelper; +import ru.betterend.util.SplineHelper; +import ru.betterend.util.sdf.PosInfo; +import ru.betterend.util.sdf.SDF; +import ru.betterend.util.sdf.operator.SDFFlatWave; +import ru.betterend.util.sdf.operator.SDFSmoothUnion; +import ru.betterend.util.sdf.primitive.SDFCappedCone; +import ru.betterend.util.sdf.primitive.SDFSphere; +import ru.betterend.world.features.DefaultFeature; + +public class NightshadeRedwoodTreeFeature extends DefaultFeature { + private static final List BRANCH; + + @Override + public boolean generate(StructureWorldAccess world, ChunkGenerator chunkGenerator, Random random, BlockPos pos, DefaultFeatureConfig config) { + if (!world.getBlockState(pos.down()).getBlock().isIn(EndTags.END_GROUND)) return false; + + BlockState log = Integrations.BYG.getDefaultState("nightshade_log"); + BlockState wood = Integrations.BYG.getDefaultState("nightshade_wood"); + BlockState leaves = Integrations.BYG.getDefaultState("nightshade_leaves"); + //BlockState leaves_flower = Integrations.BYG.getDefaultState("flowering_nightshade_leaves"); + + Function splinePlacer = (bpos) -> { return log; }; + Function replace = (state) -> { + return state.isIn(EndTags.END_GROUND) || state.getMaterial().equals(Material.PLANT) || state.getMaterial().isReplaceable(); + }; + Function post = (info) -> { + if (info.getState().equals(log) && (!info.getStateUp().equals(log) || !info.getStateDown().equals(log))) { + return wood; + } + return info.getState(); + }; + Function ignore = (state) -> { + return state.equals(log) || state.equals(wood); + }; + + int height = MHelper.randRange(40, 60, random); + List trunk = SplineHelper.makeSpline(0, 0, 0, 0, height, 0, height / 4); + SplineHelper.offsetParts(trunk, random, 0.8F, 0, 0.8F); + + if (!SplineHelper.canGenerate(trunk, pos, world, replace)) { + return false; + } + + int count = height >> 2; + float start = trunk.size() / 3F; + float delta = trunk.size() * 0.6F; + float max = height - 7; + //SDF leavesSDF = null; + for (int i = 0; i < count; i++) { + float scale = (float) (count - i) / count * 15; + Vector3f offset = SplineHelper.getPos(trunk, (float) i / count * delta + start); + if (offset.getY() > max) { + break; + } + List branch = SplineHelper.copySpline(BRANCH); + SplineHelper.rotateSpline(branch, i * 1.3F); + SplineHelper.scale(branch, scale); + SplineHelper.offsetParts(branch, random, 0.3F, 0.3F, 0.3F); + SplineHelper.offset(branch, offset); + SplineHelper.fillSpline(branch, world, wood, pos, replace); + + /*SDF leaf = null; + for (int j = 2; j < 5; j++) { + Vector3f point = branch.get(j); + float radius = (float) (j - 2) / 3F; + radius = (1F - radius) * 3F; + SDF sphere = new SDFSphere().setRadius(radius).setBlock(leaves); + sphere = new SDFTranslate().setTranslate(point.getX(), point.getY(), point.getZ()).setSource(sphere); + leaf = leaf == null ? sphere : new SDFUnion().setSourceA(leaf).setSourceB(leaf); + }*/ + + /*SDF leaf = SplineHelper.buildSDF(branch, (del) -> { + float radius = 1 - del; + radius = radius * radius * 2 - 1; + radius *= radius; + radius = (1 - radius) * 2; + return radius; + }, (bpos) -> { + return leaves; + });*/ + //leavesSDF = leavesSDF == null ? leaf : new SDFUnion().setSourceA(leavesSDF).setSourceB(leaf); + } + + SDF sdf = SplineHelper.buildSDF(trunk, 2.3F, 0.8F, splinePlacer); + SDF roots = new SDFSphere().setRadius(2F).setBlock(log); + roots = new SDFFlatWave().setIntensity(2F).setRaysCount(MHelper.randRange(5, 7, random)).setAngle(random.nextFloat() * MHelper.PI2).setSource(roots); + sdf = new SDFSmoothUnion().setRadius(2F).setSourceA(sdf).setSourceB(roots); + sdf.setReplaceFunction(replace).setPostProcess(post).fillRecursive(world, pos); + + /*if (leavesSDF != null) { + leavesSDF.fillArea(world, pos, new Box(pos).expand(20, 80, 20)); + }*/ + + Mutable mut = new Mutable(); + Function leavesPost = (info) -> { + if (info.getState().equals(log) || info.getState().equals(wood)) { + for (int x = -6; x < 7; x++) { + int ax = Math.abs(x); + mut.setX(x + info.getPos().getX()); + for (int z = -6; z < 7; z++) { + int az = Math.abs(z); + mut.setZ(z + info.getPos().getZ()); + for (int y = -6; y < 7; y++) { + int ay = Math.abs(y); + int d = ax + ay + az; + if (d < 7) { + mut.setY(y + info.getPos().getY()); + BlockState state = info.getState(mut); + if (state.getBlock() instanceof LeavesBlock) { + int distance = state.get(LeavesBlock.DISTANCE); + if (d < distance) { + info.setState(mut, state.with(LeavesBlock.DISTANCE, d)); + } + } + } + } + } + } + } + else if (info.getState().getBlock() instanceof LeavesBlock) { + int distance = info.getState().get(LeavesBlock.DISTANCE); + return distance > MHelper.randRange(3, 5, random) ? Blocks.AIR.getDefaultState() : info.getState(); + } + return info.getState(); + }; + + SDF canopy = new SDFCappedCone().setRadius1(12F).setRadius2(3f).setHeight(height * 0.3F).setBlock(leaves); + canopy.setPostProcess(leavesPost ).fillRecursiveIgnore(world, pos.add(0, height * 0.75, 0), ignore); + + return true; + } + + //private void makeLeavesSphere(StructureWorldAccess world, BlockPos pos, BlockState leaves, Function ignore) { + // + //} + + static { + BRANCH = Lists.newArrayList(new Vector3f(0, 0, 0), + new Vector3f(0.25F, 0.1F, 0), + new Vector3f(0.40F, 0.2F, 0), + new Vector3f(0.50F, 0.4F, 0), + new Vector3f(0.55F, 0.6F, 0)); + } +} diff --git a/src/main/java/ru/betterend/util/SplineHelper.java b/src/main/java/ru/betterend/util/SplineHelper.java index a5092018..b15ac46b 100644 --- a/src/main/java/ru/betterend/util/SplineHelper.java +++ b/src/main/java/ru/betterend/util/SplineHelper.java @@ -74,6 +74,25 @@ public class SplineHelper { return result; } + public static SDF buildSDF(List spline, Function radiusFunction, Function placerFunction) { + int count = spline.size(); + float max = count - 2; + SDF result = null; + Vector3f start = spline.get(0); + for (int i = 1; i < count; i++) { + Vector3f pos = spline.get(i); + float delta = (float) (i - 1) / max; + SDF line = new SDFLine() + .setRadius(radiusFunction.apply(delta)) + .setStart(start.getX(), start.getY(), start.getZ()) + .setEnd(pos.getX(), pos.getY(), pos.getZ()) + .setBlock(placerFunction); + result = result == null ? line : new SDFUnion().setSourceA(result).setSourceB(line); + start = pos; + } + return result; + } + public static boolean fillSpline(List spline, StructureWorldAccess world, BlockState state, BlockPos pos, Function replace) { Vector3f startPos = spline.get(0); for (int i = 1; i < spline.size(); i++) { diff --git a/src/main/java/ru/betterend/world/generator/GeneratorOptions.java b/src/main/java/ru/betterend/world/generator/GeneratorOptions.java index 45da95c7..fa07784e 100644 --- a/src/main/java/ru/betterend/world/generator/GeneratorOptions.java +++ b/src/main/java/ru/betterend/world/generator/GeneratorOptions.java @@ -13,14 +13,14 @@ public class GeneratorOptions { private static boolean removeChorusFromVanillaBiomes; public static void init() { - biomeSizeLand = Configs.GENERATOR_CONFIG.getIntRoot("biomeSizeLand", 256); - biomeSizeVoid = Configs.GENERATOR_CONFIG.getIntRoot("biomeSizeVoid", 256); + biomeSizeLand = Configs.GENERATOR_CONFIG.getInt("biomeMap", "biomeSizeLand", 256); + biomeSizeVoid = Configs.GENERATOR_CONFIG.getInt("biomeMap", "biomeSizeVoid", 256); hasPortal = Configs.GENERATOR_CONFIG.getBooleanRoot("hasPortal", true); hasPillars = Configs.GENERATOR_CONFIG.getBooleanRoot("hasPillars", true); hasDragonFights = Configs.GENERATOR_CONFIG.getBooleanRoot("hasDragonFights", true); swapOverworldToEnd = Configs.GENERATOR_CONFIG.getBooleanRoot("swapOverworldToEnd", false); - changeChorusPlant = Configs.GENERATOR_CONFIG.getBooleanRoot("changeChorusPlant", true); - removeChorusFromVanillaBiomes = Configs.GENERATOR_CONFIG.getBooleanRoot("removeChorusFromVanillaBiomes", true); + changeChorusPlant = Configs.GENERATOR_CONFIG.getBoolean("chorusPlant", "changeChorusPlant", true); + removeChorusFromVanillaBiomes = Configs.GENERATOR_CONFIG.getBoolean("chorusPlant", "removeChorusFromVanillaBiomes", true); } public static int getBiomeSizeLand() { diff --git a/src/main/java/ru/betterend/world/generator/TerrainGenerator.java b/src/main/java/ru/betterend/world/generator/TerrainGenerator.java index 2623bd2b..93cd0b2a 100644 --- a/src/main/java/ru/betterend/world/generator/TerrainGenerator.java +++ b/src/main/java/ru/betterend/world/generator/TerrainGenerator.java @@ -23,8 +23,8 @@ public class TerrainGenerator { private static boolean noRingVoid; public static void init() { - newGenerator = Configs.GENERATOR_CONFIG.getBooleanRoot("useNewGenerator", false); - noRingVoid = Configs.GENERATOR_CONFIG.getBooleanRoot("noRingVoid", false); + newGenerator = Configs.GENERATOR_CONFIG.getBoolean("customGenerator", "useNewGenerator", false); + noRingVoid = Configs.GENERATOR_CONFIG.getBoolean("customGenerator", "noRingVoid", false); } public static void initNoise(long seed) {