Merge branch 'master' of https://github.com/paulevsGitch/BetterEnd
This commit is contained in:
commit
8066d9c990
20 changed files with 791 additions and 75 deletions
|
@ -14,6 +14,7 @@ import ru.betterend.registry.FeatureRegistry;
|
|||
import ru.betterend.registry.ItemRegistry;
|
||||
import ru.betterend.registry.ItemTagRegistry;
|
||||
import ru.betterend.registry.SoundRegistry;
|
||||
import ru.betterend.registry.StructureRegistry;
|
||||
import ru.betterend.util.Logger;
|
||||
import ru.betterend.world.generator.BetterEndBiomeSource;
|
||||
import ru.betterend.world.surface.DoubleBlockSurfaceBuilder;
|
||||
|
@ -38,6 +39,7 @@ public class BetterEnd implements ModInitializer {
|
|||
BlockTagRegistry.register();
|
||||
CraftingRecipes.register();
|
||||
AlloyingRecipes.register();
|
||||
StructureRegistry.register();
|
||||
}
|
||||
|
||||
public static Identifier makeID(String path) {
|
||||
|
|
|
@ -0,0 +1,45 @@
|
|||
package ru.betterend.mixin.common;
|
||||
|
||||
import org.spongepowered.asm.mixin.Final;
|
||||
import org.spongepowered.asm.mixin.Mixin;
|
||||
import org.spongepowered.asm.mixin.Shadow;
|
||||
import org.spongepowered.asm.mixin.injection.At;
|
||||
import org.spongepowered.asm.mixin.injection.Inject;
|
||||
import org.spongepowered.asm.mixin.injection.callback.CallbackInfoReturnable;
|
||||
|
||||
import com.mojang.brigadier.exceptions.CommandSyntaxException;
|
||||
import com.mojang.brigadier.exceptions.SimpleCommandExceptionType;
|
||||
|
||||
import net.minecraft.server.command.LocateCommand;
|
||||
import net.minecraft.server.command.ServerCommandSource;
|
||||
import net.minecraft.util.math.BlockPos;
|
||||
import net.minecraft.world.World;
|
||||
import net.minecraft.world.gen.feature.StructureFeature;
|
||||
import ru.betterend.util.StructureHelper;
|
||||
|
||||
@Mixin(LocateCommand.class)
|
||||
public class LocateCommandMixin {
|
||||
@Shadow
|
||||
@Final
|
||||
private static SimpleCommandExceptionType FAILED_EXCEPTION;
|
||||
|
||||
@Shadow
|
||||
public static int sendCoordinates(ServerCommandSource source, String structure, BlockPos sourcePos,
|
||||
BlockPos structurePos, String successMessage) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
@Inject(method = "execute", at = @At("HEAD"), cancellable = true)
|
||||
private static void execute(ServerCommandSource source, StructureFeature<?> structureFeature, CallbackInfoReturnable<Integer> info) throws CommandSyntaxException {
|
||||
if (source.getWorld().getRegistryKey() == World.END) {
|
||||
BlockPos blockPos = new BlockPos(source.getPosition());
|
||||
BlockPos blockPos2 = StructureHelper.getNearestStructure(structureFeature, source.getWorld(), blockPos, 100);
|
||||
if (blockPos2 == null) {
|
||||
throw FAILED_EXCEPTION.create();
|
||||
} else {
|
||||
info.setReturnValue(sendCoordinates(source, structureFeature.getName(), blockPos, blockPos2, "commands.locate.success"));
|
||||
info.cancel();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
21
src/main/java/ru/betterend/registry/StructureRegistry.java
Normal file
21
src/main/java/ru/betterend/registry/StructureRegistry.java
Normal file
|
@ -0,0 +1,21 @@
|
|||
package ru.betterend.registry;
|
||||
|
||||
import net.minecraft.structure.StructurePieceType;
|
||||
import net.minecraft.util.registry.Registry;
|
||||
import net.minecraft.world.gen.GenerationStep.Feature;
|
||||
import ru.betterend.BetterEnd;
|
||||
import ru.betterend.world.structures.EndStructureFeature;
|
||||
import ru.betterend.world.structures.features.StructureGiantMossyGlowshroom;
|
||||
import ru.betterend.world.structures.piece.VoxelPiece;
|
||||
|
||||
public class StructureRegistry {
|
||||
public static final StructurePieceType VOXEL_PIECE = register("voxel", VoxelPiece::new);
|
||||
|
||||
public static final EndStructureFeature GIANT_MOSSY_GLOWSHROOM = new EndStructureFeature("giant_mossy_glowshroom", new StructureGiantMossyGlowshroom(), Feature.SURFACE_STRUCTURES, 16, 8);
|
||||
|
||||
public static void register() {}
|
||||
|
||||
private static StructurePieceType register(String id, StructurePieceType pieceType) {
|
||||
return Registry.register(Registry.STRUCTURE_PIECE, BetterEnd.makeID(id), pieceType);
|
||||
}
|
||||
}
|
62
src/main/java/ru/betterend/util/StructureHelper.java
Normal file
62
src/main/java/ru/betterend/util/StructureHelper.java
Normal file
|
@ -0,0 +1,62 @@
|
|||
package ru.betterend.util;
|
||||
|
||||
import java.util.HashSet;
|
||||
import java.util.Iterator;
|
||||
import java.util.Set;
|
||||
|
||||
import net.minecraft.server.world.ServerWorld;
|
||||
import net.minecraft.util.math.BlockPos;
|
||||
import net.minecraft.util.math.ChunkPos;
|
||||
import net.minecraft.world.gen.ChunkRandom;
|
||||
import net.minecraft.world.gen.chunk.StructureConfig;
|
||||
import net.minecraft.world.gen.feature.StructureFeature;
|
||||
|
||||
public class StructureHelper {
|
||||
private static final Set<ChunkPos> POSITIONS = new HashSet<ChunkPos>(64);
|
||||
|
||||
private static void collectNearby(ServerWorld world, StructureFeature<?> feature, int chunkX, int chunkZ, int radius, StructureConfig config, long worldSeed, ChunkRandom chunkRandom) {
|
||||
int x1 = chunkX - radius;
|
||||
int x2 = chunkX + radius;
|
||||
int z1 = chunkZ - radius;
|
||||
int z2 = chunkZ + radius;
|
||||
|
||||
POSITIONS.clear();
|
||||
for (int x = x1; x <= x2; x += 8) {
|
||||
for (int z = z1; z <= z2; z += 8) {
|
||||
ChunkPos chunk = feature.getStartChunk(config, worldSeed, chunkRandom, x, z);
|
||||
if (world.getBiome(chunk.getStartPos()).getGenerationSettings().hasStructureFeature(feature))
|
||||
POSITIONS.add(chunk);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private static long sqr(int x) {
|
||||
return (long) x * (long) x;
|
||||
}
|
||||
|
||||
public static BlockPos getNearestStructure(StructureFeature<?> feature, ServerWorld world, BlockPos pos, int radius) {
|
||||
int cx = pos.getX() >> 4;
|
||||
int cz = pos.getZ() >> 4;
|
||||
|
||||
StructureConfig config = world.getChunkManager().getChunkGenerator().getStructuresConfig().getForType(feature);
|
||||
if (config == null)
|
||||
return null;
|
||||
|
||||
collectNearby(world, feature, cx, cz, radius, config, world.getSeed(), new ChunkRandom());
|
||||
Iterator<ChunkPos> iterator = POSITIONS.iterator();
|
||||
if (iterator.hasNext()) {
|
||||
ChunkPos nearest = POSITIONS.iterator().next();
|
||||
long d = sqr(nearest.x - cx) + sqr(nearest.z - cz);
|
||||
while (iterator.hasNext()) {
|
||||
ChunkPos n = iterator.next();
|
||||
long d2 = sqr(n.x - cx) + sqr(n.z - cz);
|
||||
if (d2 < d) {
|
||||
d = d2;
|
||||
nearest = n;
|
||||
}
|
||||
}
|
||||
return nearest.getStartPos();
|
||||
}
|
||||
return null;
|
||||
}
|
||||
}
|
|
@ -7,18 +7,20 @@ import net.minecraft.block.Blocks;
|
|||
import net.minecraft.util.math.BlockPos;
|
||||
import net.minecraft.util.math.Direction;
|
||||
|
||||
public class PosInfo {
|
||||
public class PosInfo implements Comparable<PosInfo> {
|
||||
private static final BlockState AIR = Blocks.AIR.getDefaultState();
|
||||
private final Map<BlockPos, PosInfo> blocks;
|
||||
private final Map<BlockPos, PosInfo> add;
|
||||
private final BlockPos pos;
|
||||
private BlockState state;
|
||||
|
||||
public static PosInfo create(Map<BlockPos, PosInfo> blocks, BlockPos pos) {
|
||||
return new PosInfo(blocks, pos);
|
||||
public static PosInfo create(Map<BlockPos, PosInfo> blocks, Map<BlockPos, PosInfo> add, BlockPos pos) {
|
||||
return new PosInfo(blocks, add, pos);
|
||||
}
|
||||
|
||||
private PosInfo(Map<BlockPos, PosInfo> blocks, BlockPos pos) {
|
||||
private PosInfo(Map<BlockPos, PosInfo> blocks, Map<BlockPos, PosInfo> add, BlockPos pos) {
|
||||
this.blocks = blocks;
|
||||
this.add = add;
|
||||
this.pos = pos;
|
||||
blocks.put(pos, this);
|
||||
}
|
||||
|
@ -33,6 +35,15 @@ public class PosInfo {
|
|||
|
||||
public BlockState getState(Direction dir) {
|
||||
PosInfo info = blocks.get(pos.offset(dir));
|
||||
if (info == null) {
|
||||
info = add.get(pos.offset(dir));
|
||||
return info == null ? AIR : info.getState();
|
||||
}
|
||||
return info.getState();
|
||||
}
|
||||
|
||||
public BlockState getState(Direction dir, int distance) {
|
||||
PosInfo info = blocks.get(pos.offset(dir, distance));
|
||||
if (info == null) {
|
||||
return AIR;
|
||||
}
|
||||
|
@ -47,14 +58,31 @@ public class PosInfo {
|
|||
return getState(Direction.DOWN);
|
||||
}
|
||||
|
||||
@Override
|
||||
public int hashCode() {
|
||||
return pos.hashCode();
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean equals(Object obj) {
|
||||
if (!(obj instanceof PosInfo)) {
|
||||
return false;
|
||||
}
|
||||
return pos.equals(((PosInfo) obj).pos);
|
||||
}
|
||||
|
||||
@Override
|
||||
public int compareTo(PosInfo info) {
|
||||
return this.pos.getY() - info.pos.getY();
|
||||
}
|
||||
|
||||
public BlockPos getPos() {
|
||||
return pos;
|
||||
}
|
||||
|
||||
public void setBlockPos(BlockPos pos, BlockState state) {
|
||||
PosInfo info = new PosInfo(blocks, add, pos);
|
||||
info.state = state;
|
||||
add.put(pos, info);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,5 +1,8 @@
|
|||
package ru.betterend.util.sdf;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collections;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Set;
|
||||
import java.util.function.Function;
|
||||
|
@ -12,6 +15,7 @@ import net.minecraft.util.math.BlockPos;
|
|||
import net.minecraft.util.math.Direction;
|
||||
import net.minecraft.world.ServerWorldAccess;
|
||||
import ru.betterend.util.BlocksHelper;
|
||||
import ru.betterend.world.structures.StructureWorld;
|
||||
|
||||
public abstract class SDF {
|
||||
private Function<PosInfo, BlockState> postProcess = (info) -> {
|
||||
|
@ -35,8 +39,9 @@ public abstract class SDF {
|
|||
return this;
|
||||
}
|
||||
|
||||
public Set<BlockPos> fillRecursive(ServerWorldAccess world, BlockPos start, int dx, int dy, int dz) {
|
||||
public void fillRecursive(ServerWorldAccess world, BlockPos start, int dx, int dy, int dz) {
|
||||
Map<BlockPos, PosInfo> mapWorld = Maps.newHashMap();
|
||||
Map<BlockPos, PosInfo> addInfo = Maps.newHashMap();
|
||||
Set<BlockPos> blocks = Sets.newHashSet();
|
||||
Set<BlockPos> ends = Sets.newHashSet();
|
||||
Set<BlockPos> add = Sets.newHashSet();
|
||||
|
@ -56,7 +61,7 @@ public abstract class SDF {
|
|||
if (!blocks.contains(pos) && canReplace.apply(world.getBlockState(wpos))) {
|
||||
if (this.getDistance(pos.getX(), pos.getY(), pos.getZ()) < 0) {
|
||||
BlockState state = getBlockState(wpos);
|
||||
PosInfo.create(mapWorld, wpos).setState(state);
|
||||
PosInfo.create(mapWorld, addInfo, wpos).setState(state);
|
||||
if (Math.abs(pos.getX()) < dx && Math.abs(pos.getY()) < dy && Math.abs(pos.getZ()) < dz) {
|
||||
add.add(pos);
|
||||
}
|
||||
|
@ -73,16 +78,29 @@ public abstract class SDF {
|
|||
run &= !ends.isEmpty();
|
||||
}
|
||||
|
||||
mapWorld.forEach((pos, info) -> {
|
||||
BlockState state = postProcess.apply(info);
|
||||
BlocksHelper.setWithoutUpdate(world, pos, state);
|
||||
});
|
||||
List<PosInfo> infos = new ArrayList<PosInfo>(mapWorld.values());
|
||||
if (infos.size() > 0) {
|
||||
Collections.sort(infos);
|
||||
infos.forEach((info) -> {
|
||||
BlockState state = postProcess.apply(info);
|
||||
BlocksHelper.setWithoutUpdate(world, info.getPos(), state);
|
||||
});
|
||||
|
||||
return mapWorld.keySet();
|
||||
infos.clear();
|
||||
infos.addAll(addInfo.values());
|
||||
Collections.sort(infos);
|
||||
infos.forEach((info) -> {
|
||||
if (canReplace.apply(world.getBlockState(info.getPos()))) {
|
||||
BlockState state = postProcess.apply(info);
|
||||
BlocksHelper.setWithoutUpdate(world, info.getPos(), state);
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
public Set<BlockPos> fillRecursive(ServerWorldAccess world, BlockPos start) {
|
||||
public void fillRecursive(ServerWorldAccess world, BlockPos start) {
|
||||
Map<BlockPos, PosInfo> mapWorld = Maps.newHashMap();
|
||||
Map<BlockPos, PosInfo> addInfo = Maps.newHashMap();
|
||||
Set<BlockPos> blocks = Sets.newHashSet();
|
||||
Set<BlockPos> ends = Sets.newHashSet();
|
||||
Set<BlockPos> add = Sets.newHashSet();
|
||||
|
@ -98,7 +116,7 @@ public abstract class SDF {
|
|||
if (!blocks.contains(pos) && canReplace.apply(world.getBlockState(wpos))) {
|
||||
if (this.getDistance(pos.getX(), pos.getY(), pos.getZ()) < 0) {
|
||||
BlockState state = getBlockState(wpos);
|
||||
PosInfo.create(mapWorld, wpos).setState(state);
|
||||
PosInfo.create(mapWorld, addInfo, wpos).setState(state);
|
||||
add.add(pos);
|
||||
}
|
||||
}
|
||||
|
@ -113,11 +131,72 @@ public abstract class SDF {
|
|||
run &= !ends.isEmpty();
|
||||
}
|
||||
|
||||
mapWorld.forEach((pos, info) -> {
|
||||
List<PosInfo> infos = new ArrayList<PosInfo>(mapWorld.values());
|
||||
if (infos.size() > 0) {
|
||||
Collections.sort(infos);
|
||||
infos.forEach((info) -> {
|
||||
BlockState state = postProcess.apply(info);
|
||||
BlocksHelper.setWithoutUpdate(world, info.getPos(), state);
|
||||
});
|
||||
|
||||
infos.clear();
|
||||
infos.addAll(addInfo.values());
|
||||
Collections.sort(infos);
|
||||
infos.forEach((info) -> {
|
||||
if (canReplace.apply(world.getBlockState(info.getPos()))) {
|
||||
BlockState state = postProcess.apply(info);
|
||||
BlocksHelper.setWithoutUpdate(world, info.getPos(), state);
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
public void fillRecursive(StructureWorld world, BlockPos start) {
|
||||
Map<BlockPos, PosInfo> mapWorld = Maps.newHashMap();
|
||||
Map<BlockPos, PosInfo> addInfo = Maps.newHashMap();
|
||||
Set<BlockPos> blocks = Sets.newHashSet();
|
||||
Set<BlockPos> ends = Sets.newHashSet();
|
||||
Set<BlockPos> add = Sets.newHashSet();
|
||||
ends.add(new BlockPos(0, 0, 0));
|
||||
boolean run = true;
|
||||
|
||||
while (run) {
|
||||
for (BlockPos center: ends) {
|
||||
for (Direction dir: Direction.values()) {
|
||||
BlockPos pos = center.offset(dir);
|
||||
BlockPos wpos = pos.add(start);
|
||||
|
||||
if (!blocks.contains(pos)) {
|
||||
if (this.getDistance(pos.getX(), pos.getY(), pos.getZ()) < 0) {
|
||||
BlockState state = getBlockState(wpos);
|
||||
PosInfo.create(mapWorld, addInfo, wpos).setState(state);
|
||||
add.add(pos);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
blocks.addAll(ends);
|
||||
ends.clear();
|
||||
ends.addAll(add);
|
||||
add.clear();
|
||||
|
||||
run &= !ends.isEmpty();
|
||||
}
|
||||
|
||||
List<PosInfo> infos = new ArrayList<PosInfo>(mapWorld.values());
|
||||
Collections.sort(infos);
|
||||
infos.forEach((info) -> {
|
||||
BlockState state = postProcess.apply(info);
|
||||
BlocksHelper.setWithoutUpdate(world, pos, state);
|
||||
world.setBlock(info.getPos(), state);
|
||||
});
|
||||
|
||||
return mapWorld.keySet();
|
||||
infos.clear();
|
||||
infos.addAll(addInfo.values());
|
||||
Collections.sort(infos);
|
||||
infos.forEach((info) -> {
|
||||
BlockState state = postProcess.apply(info);
|
||||
world.setBlock(info.getPos(), state);
|
||||
});
|
||||
}
|
||||
}
|
||||
|
|
15
src/main/java/ru/betterend/util/sdf/operator/SDFRound.java
Normal file
15
src/main/java/ru/betterend/util/sdf/operator/SDFRound.java
Normal file
|
@ -0,0 +1,15 @@
|
|||
package ru.betterend.util.sdf.operator;
|
||||
|
||||
public class SDFRound extends SDFUnary {
|
||||
private float radius;
|
||||
|
||||
public SDFRound setRadius(float radius) {
|
||||
this.radius = radius;
|
||||
return this;
|
||||
}
|
||||
|
||||
@Override
|
||||
public float getDistance(float x, float y, float z) {
|
||||
return this.source.getDistance(x, y, z) - radius;
|
||||
}
|
||||
}
|
|
@ -32,4 +32,8 @@ public abstract class SDFPrimitive extends SDF {
|
|||
public BlockState getBlockState(BlockPos pos) {
|
||||
return placerFunction.apply(pos);
|
||||
}
|
||||
|
||||
/*public abstract CompoundTag toNBT(CompoundTag root) {
|
||||
|
||||
}*/
|
||||
}
|
||||
|
|
|
@ -33,6 +33,7 @@ import net.minecraft.world.gen.surfacebuilder.TernarySurfaceConfig;
|
|||
import ru.betterend.BetterEnd;
|
||||
import ru.betterend.util.MHelper;
|
||||
import ru.betterend.world.features.EndFeature;
|
||||
import ru.betterend.world.structures.EndStructureFeature;
|
||||
import ru.betterend.world.surface.DoubleBlockSurfaceBuilder;
|
||||
|
||||
public class BiomeDefinition {
|
||||
|
@ -112,6 +113,11 @@ public class BiomeDefinition {
|
|||
return this;
|
||||
}
|
||||
|
||||
public BiomeDefinition addStructureFeature(EndStructureFeature feature) {
|
||||
structures.add(feature.getFeatureConfigured());
|
||||
return this;
|
||||
}
|
||||
|
||||
public BiomeDefinition addFeature(EndFeature feature) {
|
||||
FeatureInfo info = new FeatureInfo();
|
||||
info.featureStep = feature.getFeatureStep();
|
||||
|
|
|
@ -6,6 +6,7 @@ import ru.betterend.registry.EntityRegistry;
|
|||
import ru.betterend.registry.FeatureRegistry;
|
||||
import ru.betterend.registry.ParticleRegistry;
|
||||
import ru.betterend.registry.SoundRegistry;
|
||||
import ru.betterend.registry.StructureRegistry;
|
||||
|
||||
public class BiomeFoggyMushroomland extends EndBiome {
|
||||
public BiomeFoggyMushroomland() {
|
||||
|
@ -18,6 +19,7 @@ public class BiomeFoggyMushroomland extends EndBiome {
|
|||
.setParticles(ParticleRegistry.GLOWING_SPHERE, 0.001F)
|
||||
.setLoop(SoundRegistry.AMBIENT_FOGGY_MUSHROOMLAND)
|
||||
.setMusic(SoundRegistry.MUSIC_FOGGY_MUSHROOMLAND)
|
||||
.addStructureFeature(StructureRegistry.GIANT_MOSSY_GLOWSHROOM)
|
||||
.addFeature(FeatureRegistry.ENDER_ORE)
|
||||
.addFeature(FeatureRegistry.END_LAKE)
|
||||
.addFeature(FeatureRegistry.MOSSY_GLOWSHROOM)
|
||||
|
|
|
@ -2,7 +2,6 @@ package ru.betterend.world.features;
|
|||
|
||||
import java.util.List;
|
||||
import java.util.Random;
|
||||
import java.util.Set;
|
||||
import java.util.function.Function;
|
||||
|
||||
import net.minecraft.block.BlockState;
|
||||
|
@ -23,7 +22,6 @@ import ru.betterend.registry.BlockTagRegistry;
|
|||
import ru.betterend.util.BlocksHelper;
|
||||
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.SDFBinary;
|
||||
import ru.betterend.util.sdf.operator.SDFCoordModify;
|
||||
|
@ -39,7 +37,6 @@ import ru.betterend.util.sdf.primitive.SDFPrimitive;
|
|||
import ru.betterend.util.sdf.primitive.SDFSphere;
|
||||
|
||||
public class MossyGlowshroomFeature extends DefaultFeature {
|
||||
private static final Function<PosInfo, BlockState> POST_PROCESS;
|
||||
private static final Function<BlockState, Boolean> REPLACE;
|
||||
private static final Vector3f CENTER = new Vector3f();
|
||||
private static final SDFBinary FUNCTION;
|
||||
|
@ -112,38 +109,44 @@ public class MossyGlowshroomFeature extends DefaultFeature {
|
|||
ROOTS_ROT.setAngle(random.nextFloat() * MHelper.PI2);
|
||||
FUNCTION.setSourceA(sdf);
|
||||
|
||||
Set<BlockPos> blocks = new SDFScale()
|
||||
.setScale(scale)
|
||||
new SDFScale().setScale(scale)
|
||||
.setSource(FUNCTION)
|
||||
.setReplaceFunction(REPLACE)
|
||||
.setPostProcess(POST_PROCESS)
|
||||
.setPostProcess((info) -> {
|
||||
if (BlockRegistry.MOSSY_GLOWSHROOM.isTreeLog(info.getState())) {
|
||||
if (random.nextBoolean() && info.getStateUp().getBlock() == BlockRegistry.MOSSY_GLOWSHROOM_CAP) {
|
||||
info.setState(BlockRegistry.MOSSY_GLOWSHROOM_CAP.getDefaultState().with(BlockMossyGlowshroomCap.TRANSITION, true));
|
||||
return info.getState();
|
||||
}
|
||||
else if (!BlockRegistry.MOSSY_GLOWSHROOM.isTreeLog(info.getStateUp()) || !BlockRegistry.MOSSY_GLOWSHROOM.isTreeLog(info.getStateDown())) {
|
||||
info.setState(BlockRegistry.MOSSY_GLOWSHROOM.bark.getDefaultState());
|
||||
return info.getState();
|
||||
}
|
||||
}
|
||||
else if (info.getState().getBlock() == BlockRegistry.MOSSY_GLOWSHROOM_CAP) {
|
||||
if (BlockRegistry.MOSSY_GLOWSHROOM.isTreeLog(info.getStateDown().getBlock())) {
|
||||
info.setState(BlockRegistry.MOSSY_GLOWSHROOM_CAP.getDefaultState().with(BlockMossyGlowshroomCap.TRANSITION, true));
|
||||
return info.getState();
|
||||
}
|
||||
|
||||
info.setState(BlockRegistry.MOSSY_GLOWSHROOM_CAP.getDefaultState());
|
||||
return info.getState();
|
||||
}
|
||||
else if (info.getState().getBlock() == BlockRegistry.MOSSY_GLOWSHROOM_HYMENOPHORE) {
|
||||
for (Direction dir: BlocksHelper.HORIZONTAL) {
|
||||
if (info.getState(dir) == AIR) {
|
||||
info.setBlockPos(info.getPos().offset(dir), BlockRegistry.MOSSY_GLOWSHROOM_FUR.getDefaultState().with(BlockGlowingFur.FACING, dir));
|
||||
}
|
||||
}
|
||||
|
||||
if (info.getStateDown().getBlock() != BlockRegistry.MOSSY_GLOWSHROOM_HYMENOPHORE) {
|
||||
info.setBlockPos(info.getPos().down(), BlockRegistry.MOSSY_GLOWSHROOM_FUR.getDefaultState().with(BlockGlowingFur.FACING, Direction.DOWN));
|
||||
}
|
||||
}
|
||||
return info.getState();
|
||||
})
|
||||
.fillRecursive(world, blockPos);
|
||||
|
||||
for (BlockPos bpos: blocks) {
|
||||
BlockState state = world.getBlockState(bpos);
|
||||
if (state.getBlock() == BlockRegistry.MOSSY_GLOWSHROOM_HYMENOPHORE) {
|
||||
if (world.isAir(bpos.north())) {
|
||||
BlocksHelper.setWithoutUpdate(world, bpos.north(), BlockRegistry.MOSSY_GLOWSHROOM_FUR.getDefaultState().with(BlockGlowingFur.FACING, Direction.NORTH));
|
||||
}
|
||||
if (world.isAir(bpos.east())) {
|
||||
BlocksHelper.setWithoutUpdate(world, bpos.east(), BlockRegistry.MOSSY_GLOWSHROOM_FUR.getDefaultState().with(BlockGlowingFur.FACING, Direction.EAST));
|
||||
}
|
||||
if (world.isAir(bpos.south())) {
|
||||
BlocksHelper.setWithoutUpdate(world, bpos.south(), BlockRegistry.MOSSY_GLOWSHROOM_FUR.getDefaultState().with(BlockGlowingFur.FACING, Direction.SOUTH));
|
||||
}
|
||||
if (world.isAir(bpos.west())) {
|
||||
BlocksHelper.setWithoutUpdate(world, bpos.west(), BlockRegistry.MOSSY_GLOWSHROOM_FUR.getDefaultState().with(BlockGlowingFur.FACING, Direction.WEST));
|
||||
}
|
||||
if (world.getBlockState(bpos.down()).getMaterial().isReplaceable()) {
|
||||
BlocksHelper.setWithoutUpdate(world, bpos.down(), BlockRegistry.MOSSY_GLOWSHROOM_FUR.getDefaultState().with(BlockGlowingFur.FACING, Direction.DOWN));
|
||||
}
|
||||
}
|
||||
else if (BlockRegistry.MOSSY_GLOWSHROOM.isTreeLog(state) && random.nextBoolean() && world.getBlockState(bpos.up()).getBlock() == BlockRegistry.MOSSY_GLOWSHROOM_CAP) {
|
||||
BlocksHelper.setWithoutUpdate(world, bpos, BlockRegistry.MOSSY_GLOWSHROOM_CAP.getDefaultState().with(BlockMossyGlowshroomCap.TRANSITION, true));
|
||||
BlocksHelper.setWithoutUpdate(world, bpos.up(), BlockRegistry.MOSSY_GLOWSHROOM_CAP);
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
|
@ -151,7 +154,7 @@ public class MossyGlowshroomFeature extends DefaultFeature {
|
|||
SDFCapedCone cone1 = new SDFCapedCone().setHeight(2.5F).setRadius1(1.5F).setRadius2(2.5F);
|
||||
SDFCapedCone cone2 = new SDFCapedCone().setHeight(3F).setRadius1(2.5F).setRadius2(13F);
|
||||
SDF posedCone2 = new SDFTranslate().setTranslate(0, 5, 0).setSource(cone2);
|
||||
SDF posedCone3 = new SDFTranslate().setTranslate(0, 7F, 0).setSource(cone2);
|
||||
SDF posedCone3 = new SDFTranslate().setTranslate(0, 12F, 0).setSource(new SDFScale().setScale(2).setSource(cone2));
|
||||
SDF upCone = new SDFSubtraction().setSourceA(posedCone2).setSourceB(posedCone3);
|
||||
SDF wave = new SDFFlatWave().setRaysCount(12).setIntensity(1.3F).setSource(upCone);
|
||||
SDF cones = new SDFSmoothUnion().setRadius(3).setSourceA(cone1).setSourceB(wave);
|
||||
|
@ -195,30 +198,5 @@ public class MossyGlowshroomFeature extends DefaultFeature {
|
|||
}
|
||||
return state.getMaterial().isReplaceable();
|
||||
};
|
||||
|
||||
POST_PROCESS = (info) -> {
|
||||
if (BlockRegistry.MOSSY_GLOWSHROOM.isTreeLog(info.getState())) {
|
||||
if (!BlockRegistry.MOSSY_GLOWSHROOM.isTreeLog(info.getStateUp()) || !BlockRegistry.MOSSY_GLOWSHROOM.isTreeLog(info.getStateDown())) {
|
||||
return BlockRegistry.MOSSY_GLOWSHROOM.bark.getDefaultState();
|
||||
}
|
||||
}
|
||||
else if (info.getState().getBlock() == BlockRegistry.MOSSY_GLOWSHROOM_CAP) {
|
||||
if (BlockRegistry.MOSSY_GLOWSHROOM.isTreeLog(info.getStateDown())) {
|
||||
return info.getState().with(BlockMossyGlowshroomCap.TRANSITION, true);
|
||||
}
|
||||
|
||||
int air = 0;
|
||||
for (Direction dir: Direction.values()) {
|
||||
if (info.getState(dir).isAir()) {
|
||||
air ++;
|
||||
}
|
||||
}
|
||||
if (air > 4) {
|
||||
info.setState(AIR);
|
||||
return AIR;
|
||||
}
|
||||
}
|
||||
return info.getState();
|
||||
};
|
||||
}
|
||||
}
|
||||
|
|
|
@ -21,7 +21,7 @@ public class VineFeature extends InvertedScatterFeature {
|
|||
|
||||
@Override
|
||||
public boolean canGenerate(StructureWorldAccess world, Random random, BlockPos center, BlockPos blockPos, float radius) {
|
||||
return vineBlock.canPlaceAt(AIR, world, blockPos);
|
||||
return world.isAir(blockPos) && vineBlock.canPlaceAt(AIR, world, blockPos);
|
||||
}
|
||||
|
||||
@Override
|
||||
|
|
|
@ -0,0 +1,45 @@
|
|||
package ru.betterend.world.structures;
|
||||
|
||||
import java.util.Random;
|
||||
|
||||
import net.fabricmc.fabric.api.structure.v1.FabricStructureBuilder;
|
||||
import net.minecraft.util.Identifier;
|
||||
import net.minecraft.util.registry.BuiltinRegistries;
|
||||
import net.minecraft.world.gen.GenerationStep;
|
||||
import net.minecraft.world.gen.feature.ConfiguredStructureFeature;
|
||||
import net.minecraft.world.gen.feature.DefaultFeatureConfig;
|
||||
import net.minecraft.world.gen.feature.StructureFeature;
|
||||
import ru.betterend.BetterEnd;
|
||||
|
||||
public class EndStructureFeature {
|
||||
private static final Random RANDOM = new Random(354);
|
||||
private final StructureFeature<DefaultFeatureConfig> structure;
|
||||
private final ConfiguredStructureFeature<?, ?> featureConfigured;
|
||||
private final GenerationStep.Feature featureStep;
|
||||
|
||||
public EndStructureFeature(String name, StructureFeature<DefaultFeatureConfig> structure, GenerationStep.Feature step, int spacing, int separation) {
|
||||
Identifier id = BetterEnd.makeID(name);
|
||||
|
||||
this.featureStep = step;
|
||||
this.structure = FabricStructureBuilder.create(id, structure)
|
||||
.step(step)
|
||||
.defaultConfig(spacing, separation, RANDOM.nextInt(8192))
|
||||
.register();
|
||||
|
||||
this.featureConfigured = this.structure.configure(DefaultFeatureConfig.DEFAULT);
|
||||
|
||||
BuiltinRegistries.add(BuiltinRegistries.CONFIGURED_STRUCTURE_FEATURE, id, this.featureConfigured);
|
||||
}
|
||||
|
||||
public StructureFeature<DefaultFeatureConfig> getStructure() {
|
||||
return structure;
|
||||
}
|
||||
|
||||
public ConfiguredStructureFeature<?, ?> getFeatureConfigured() {
|
||||
return featureConfigured;
|
||||
}
|
||||
|
||||
public GenerationStep.Feature getFeatureStep() {
|
||||
return featureStep;
|
||||
}
|
||||
}
|
139
src/main/java/ru/betterend/world/structures/StructureWorld.java
Normal file
139
src/main/java/ru/betterend/world/structures/StructureWorld.java
Normal file
|
@ -0,0 +1,139 @@
|
|||
package ru.betterend.world.structures;
|
||||
|
||||
import java.util.Map;
|
||||
|
||||
import com.google.common.collect.Maps;
|
||||
|
||||
import net.minecraft.block.Block;
|
||||
import net.minecraft.block.BlockState;
|
||||
import net.minecraft.nbt.CompoundTag;
|
||||
import net.minecraft.nbt.ListTag;
|
||||
import net.minecraft.nbt.NbtHelper;
|
||||
import net.minecraft.util.math.BlockBox;
|
||||
import net.minecraft.util.math.BlockPos;
|
||||
import net.minecraft.util.math.ChunkPos;
|
||||
import net.minecraft.world.StructureWorldAccess;
|
||||
import net.minecraft.world.chunk.Chunk;
|
||||
|
||||
public class StructureWorld {
|
||||
private Map<ChunkPos, Part> parts = Maps.newHashMap();
|
||||
private int minX = Integer.MAX_VALUE;
|
||||
private int minY = Integer.MAX_VALUE;
|
||||
private int minZ = Integer.MAX_VALUE;
|
||||
private int maxX = Integer.MIN_VALUE;
|
||||
private int maxY = Integer.MIN_VALUE;
|
||||
private int maxZ = Integer.MIN_VALUE;
|
||||
|
||||
public StructureWorld() {}
|
||||
|
||||
public StructureWorld(CompoundTag tag) {
|
||||
minX = tag.getInt("minX");
|
||||
maxX = tag.getInt("maxX");
|
||||
minY = tag.getInt("minY");
|
||||
maxY = tag.getInt("maxY");
|
||||
minZ = tag.getInt("minZ");
|
||||
maxZ = tag.getInt("maxZ");
|
||||
|
||||
ListTag map = tag.getList("parts", 10);
|
||||
map.forEach((element) -> {
|
||||
CompoundTag compound = (CompoundTag) element;
|
||||
Part part = new Part(compound);
|
||||
int x = compound.getInt("x");
|
||||
int z = compound.getInt("z");
|
||||
parts.put(new ChunkPos(x, z), part);
|
||||
});
|
||||
}
|
||||
|
||||
public void setBlock(BlockPos pos, BlockState state) {
|
||||
ChunkPos cPos = new ChunkPos(pos);
|
||||
Part part = parts.get(cPos);
|
||||
if (part == null) {
|
||||
part = new Part();
|
||||
parts.put(cPos, part);
|
||||
|
||||
if (cPos.x < minX) minX = cPos.x;
|
||||
if (cPos.x > maxX) maxX = cPos.x;
|
||||
if (cPos.z < minZ) minZ = cPos.z;
|
||||
if (cPos.z > maxZ) maxZ = cPos.z;
|
||||
}
|
||||
if (pos.getY() < minY) minY = pos.getY();
|
||||
if (pos.getY() > maxY) maxY = pos.getY();
|
||||
part.addBlock(pos, state);
|
||||
}
|
||||
|
||||
public boolean placeChunk(StructureWorldAccess world, ChunkPos chunkPos) {
|
||||
Part part = parts.get(chunkPos);
|
||||
if (part != null) {
|
||||
Chunk chunk = world.getChunk(chunkPos.x, chunkPos.z);
|
||||
part.placeChunk(chunk);
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
public CompoundTag toBNT() {
|
||||
CompoundTag tag = new CompoundTag();
|
||||
tag.putInt("minX", minX);
|
||||
tag.putInt("maxX", maxX);
|
||||
tag.putInt("minY", minY);
|
||||
tag.putInt("maxY", maxY);
|
||||
tag.putInt("minZ", minZ);
|
||||
tag.putInt("maxZ", maxZ);
|
||||
ListTag map = new ListTag();
|
||||
tag.put("parts", map);
|
||||
parts.forEach((pos, part) -> {
|
||||
map.add(part.toNBT(pos.x, pos.z));
|
||||
});
|
||||
return tag;
|
||||
}
|
||||
|
||||
public BlockBox getBounds() {
|
||||
if (minX == Integer.MAX_VALUE || maxX == Integer.MIN_VALUE || minZ == Integer.MAX_VALUE || maxZ == Integer.MIN_VALUE) {
|
||||
return BlockBox.empty();
|
||||
}
|
||||
return new BlockBox(minX << 4, minY, minZ << 4, (maxX << 4) | 15, maxY, (maxZ << 4) | 15);
|
||||
}
|
||||
|
||||
private static final class Part {
|
||||
Map<BlockPos, BlockState> blocks = Maps.newHashMap();
|
||||
|
||||
public Part() {}
|
||||
|
||||
public Part(CompoundTag tag) {
|
||||
ListTag map = tag.getList("blocks", 10);
|
||||
map.forEach((element) -> {
|
||||
CompoundTag block = (CompoundTag) element;
|
||||
BlockPos pos = NbtHelper.toBlockPos(block.getCompound("pos"));
|
||||
BlockState state = Block.getStateFromRawId(block.getInt("state"));
|
||||
blocks.put(pos, state);
|
||||
});
|
||||
}
|
||||
|
||||
void addBlock(BlockPos pos, BlockState state) {
|
||||
BlockPos inner = new BlockPos(pos.getX() & 15, pos.getY(), pos.getZ() & 15);
|
||||
blocks.put(inner, state);
|
||||
}
|
||||
|
||||
void placeChunk(Chunk chunk) {
|
||||
blocks.forEach((pos, state) -> {
|
||||
//if (pos.getY() > 10)
|
||||
chunk.setBlockState(pos, state, false);
|
||||
});
|
||||
}
|
||||
|
||||
CompoundTag toNBT(int x, int z) {
|
||||
CompoundTag tag = new CompoundTag();
|
||||
tag.putInt("x", x);
|
||||
tag.putInt("z", z);
|
||||
ListTag map = new ListTag();
|
||||
tag.put("blocks", map);
|
||||
blocks.forEach((pos, state) -> {
|
||||
CompoundTag block = new CompoundTag();
|
||||
block.put("pos", NbtHelper.fromBlockPos(pos));
|
||||
block.putInt("state", Block.getRawIdFromState(state));
|
||||
map.add(block);
|
||||
});
|
||||
return tag;
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,46 @@
|
|||
package ru.betterend.world.structures.features;
|
||||
|
||||
import java.util.Random;
|
||||
|
||||
import net.minecraft.structure.StructureManager;
|
||||
import net.minecraft.structure.StructureStart;
|
||||
import net.minecraft.util.math.BlockBox;
|
||||
import net.minecraft.util.math.BlockPos;
|
||||
import net.minecraft.util.registry.DynamicRegistryManager;
|
||||
import net.minecraft.world.Heightmap.Type;
|
||||
import net.minecraft.world.biome.Biome;
|
||||
import net.minecraft.world.gen.chunk.ChunkGenerator;
|
||||
import net.minecraft.world.gen.feature.DefaultFeatureConfig;
|
||||
import net.minecraft.world.gen.feature.StructureFeature;
|
||||
import ru.betterend.util.MHelper;
|
||||
import ru.betterend.util.sdf.SDF;
|
||||
import ru.betterend.world.structures.piece.VoxelPiece;
|
||||
|
||||
public abstract class SDFStructureFeature extends StructureFeatureBase {
|
||||
|
||||
protected abstract SDF getSDF(BlockPos pos, Random random);
|
||||
|
||||
@Override
|
||||
public StructureFeature.StructureStartFactory<DefaultFeatureConfig> getStructureStartFactory() {
|
||||
return SDFStructureStart::new;
|
||||
}
|
||||
|
||||
public static class SDFStructureStart extends StructureStart<DefaultFeatureConfig> {
|
||||
public SDFStructureStart(StructureFeature<DefaultFeatureConfig> feature, int chunkX, int chunkZ, BlockBox box, int references, long seed) {
|
||||
super(feature, chunkX, chunkZ, box, references, seed);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void init(DynamicRegistryManager registryManager, ChunkGenerator chunkGenerator, StructureManager manager, int chunkX, int chunkZ, Biome biome, DefaultFeatureConfig config) {
|
||||
int x = (chunkX << 4) | MHelper.randRange(4, 12, random);
|
||||
int z = (chunkZ << 4) | MHelper.randRange(4, 12, random);
|
||||
int y = chunkGenerator.getHeight(x, z, Type.WORLD_SURFACE_WG);
|
||||
if (y > 5) {
|
||||
BlockPos start = new BlockPos(x, y, z);
|
||||
VoxelPiece piece = new VoxelPiece((world) -> { ((SDFStructureFeature) this.getFeature()).getSDF(start, this.random).fillRecursive(world, start); }, random.nextInt());
|
||||
this.children.add(piece);
|
||||
}
|
||||
this.setBoundingBoxFromChildren();
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,50 @@
|
|||
package ru.betterend.world.structures.features;
|
||||
|
||||
import java.util.Random;
|
||||
|
||||
import net.minecraft.block.BlockState;
|
||||
import net.minecraft.block.Blocks;
|
||||
import net.minecraft.util.BlockRotation;
|
||||
import net.minecraft.util.math.ChunkPos;
|
||||
import net.minecraft.world.Heightmap;
|
||||
import net.minecraft.world.biome.Biome;
|
||||
import net.minecraft.world.biome.source.BiomeSource;
|
||||
import net.minecraft.world.gen.ChunkRandom;
|
||||
import net.minecraft.world.gen.chunk.ChunkGenerator;
|
||||
import net.minecraft.world.gen.feature.DefaultFeatureConfig;
|
||||
import net.minecraft.world.gen.feature.StructureFeature;
|
||||
|
||||
public abstract class StructureFeatureBase extends StructureFeature<DefaultFeatureConfig> {
|
||||
protected static final BlockState AIR = Blocks.AIR.getDefaultState();
|
||||
|
||||
public StructureFeatureBase() {
|
||||
super(DefaultFeatureConfig.CODEC);
|
||||
}
|
||||
|
||||
protected boolean shouldStartAt(ChunkGenerator chunkGenerator, BiomeSource biomeSource, long worldSeed, ChunkRandom chunkRandom, int chunkX, int chunkZ, Biome biome, ChunkPos chunkPos, DefaultFeatureConfig featureConfig) {
|
||||
return getGenerationHeight(chunkX, chunkZ, chunkGenerator) >= 50;
|
||||
}
|
||||
|
||||
private static int getGenerationHeight(int chunkX, int chunkZ, ChunkGenerator chunkGenerator) {
|
||||
Random random = new Random((long) (chunkX + chunkZ * 10387313));
|
||||
BlockRotation blockRotation = BlockRotation.random(random);
|
||||
int i = 5;
|
||||
int j = 5;
|
||||
if (blockRotation == BlockRotation.CLOCKWISE_90) {
|
||||
i = -5;
|
||||
} else if (blockRotation == BlockRotation.CLOCKWISE_180) {
|
||||
i = -5;
|
||||
j = -5;
|
||||
} else if (blockRotation == BlockRotation.COUNTERCLOCKWISE_90) {
|
||||
j = -5;
|
||||
}
|
||||
|
||||
int k = (chunkX << 4) + 7;
|
||||
int l = (chunkZ << 4) + 7;
|
||||
int m = chunkGenerator.getHeightInGround(k, l, Heightmap.Type.WORLD_SURFACE_WG);
|
||||
int n = chunkGenerator.getHeightInGround(k, l + j, Heightmap.Type.WORLD_SURFACE_WG);
|
||||
int o = chunkGenerator.getHeightInGround(k + i, l, Heightmap.Type.WORLD_SURFACE_WG);
|
||||
int p = chunkGenerator.getHeightInGround(k + i, l + j, Heightmap.Type.WORLD_SURFACE_WG);
|
||||
return Math.min(Math.min(m, n), Math.min(o, p));
|
||||
}
|
||||
}
|
|
@ -0,0 +1,127 @@
|
|||
package ru.betterend.world.structures.features;
|
||||
|
||||
import java.util.List;
|
||||
import java.util.Random;
|
||||
|
||||
import net.minecraft.client.util.math.Vector3f;
|
||||
import net.minecraft.util.math.BlockPos;
|
||||
import net.minecraft.util.math.Direction;
|
||||
import ru.betterend.blocks.BlockMossyGlowshroomCap;
|
||||
import ru.betterend.blocks.basis.BlockGlowingFur;
|
||||
import ru.betterend.noise.OpenSimplexNoise;
|
||||
import ru.betterend.registry.BlockRegistry;
|
||||
import ru.betterend.util.BlocksHelper;
|
||||
import ru.betterend.util.MHelper;
|
||||
import ru.betterend.util.SplineHelper;
|
||||
import ru.betterend.util.sdf.SDF;
|
||||
import ru.betterend.util.sdf.operator.SDFBinary;
|
||||
import ru.betterend.util.sdf.operator.SDFCoordModify;
|
||||
import ru.betterend.util.sdf.operator.SDFFlatWave;
|
||||
import ru.betterend.util.sdf.operator.SDFRound;
|
||||
import ru.betterend.util.sdf.operator.SDFScale;
|
||||
import ru.betterend.util.sdf.operator.SDFScale3D;
|
||||
import ru.betterend.util.sdf.operator.SDFSmoothUnion;
|
||||
import ru.betterend.util.sdf.operator.SDFSubtraction;
|
||||
import ru.betterend.util.sdf.operator.SDFTranslate;
|
||||
import ru.betterend.util.sdf.operator.SDFUnion;
|
||||
import ru.betterend.util.sdf.primitive.SDFCapedCone;
|
||||
import ru.betterend.util.sdf.primitive.SDFPrimitive;
|
||||
import ru.betterend.util.sdf.primitive.SDFSphere;
|
||||
|
||||
public class StructureGiantMossyGlowshroom extends SDFStructureFeature {
|
||||
@Override
|
||||
protected SDF getSDF(BlockPos center, Random random) {
|
||||
System.out.println(center);
|
||||
|
||||
SDFCapedCone cone1 = new SDFCapedCone().setHeight(2.5F).setRadius1(1.5F).setRadius2(2.5F);
|
||||
SDFCapedCone cone2 = new SDFCapedCone().setHeight(3F).setRadius1(2.5F).setRadius2(13F);
|
||||
SDF posedCone2 = new SDFTranslate().setTranslate(0, 5, 0).setSource(cone2);
|
||||
SDF posedCone3 = new SDFTranslate().setTranslate(0, 12F, 0).setSource(new SDFScale().setScale(2).setSource(cone2));
|
||||
SDF upCone = new SDFSubtraction().setSourceA(posedCone2).setSourceB(posedCone3);
|
||||
SDF wave = new SDFFlatWave().setRaysCount(12).setIntensity(1.3F).setSource(upCone);
|
||||
SDF cones = new SDFSmoothUnion().setRadius(3).setSourceA(cone1).setSourceB(wave);
|
||||
|
||||
SDF innerCone = new SDFTranslate().setTranslate(0, 1.25F, 0).setSource(upCone);
|
||||
innerCone = new SDFScale3D().setScale(1.2F, 1F, 1.2F).setSource(innerCone);
|
||||
cones = new SDFUnion().setSourceA(cones).setSourceB(innerCone);
|
||||
|
||||
SDF glowCone = new SDFCapedCone().setHeight(3F).setRadius1(2F).setRadius2(12.5F);
|
||||
SDFPrimitive priGlowCone = (SDFPrimitive) glowCone;
|
||||
glowCone = new SDFTranslate().setTranslate(0, 4.25F, 0).setSource(glowCone);
|
||||
glowCone = new SDFSubtraction().setSourceA(glowCone).setSourceB(posedCone3);
|
||||
|
||||
cones = new SDFUnion().setSourceA(cones).setSourceB(glowCone);
|
||||
|
||||
OpenSimplexNoise noise = new OpenSimplexNoise(1234);
|
||||
cones = new SDFCoordModify().setFunction((pos) -> {
|
||||
float dist = MHelper.length(pos.getX(), pos.getZ());
|
||||
float y = pos.getY() + (float) noise.eval(pos.getX() * 0.1 + center.getX(), pos.getZ() * 0.1 + center.getZ()) * dist * 0.3F - dist * 0.15F;
|
||||
pos.set(pos.getX(), y, pos.getZ());
|
||||
}).setSource(cones);
|
||||
|
||||
SDFTranslate HEAD_POS = (SDFTranslate) new SDFTranslate().setSource(new SDFTranslate().setTranslate(0, 2.5F, 0).setSource(cones));
|
||||
|
||||
SDF roots = new SDFSphere().setRadius(4F);
|
||||
SDFPrimitive primRoots = (SDFPrimitive) roots;
|
||||
roots = new SDFScale3D().setScale(1, 0.7F, 1).setSource(roots);
|
||||
SDFFlatWave rotRoots = (SDFFlatWave) new SDFFlatWave().setRaysCount(5).setIntensity(1.5F).setSource(roots);
|
||||
|
||||
SDFBinary function = new SDFSmoothUnion().setRadius(4).setSourceB(new SDFUnion().setSourceA(HEAD_POS).setSourceB(rotRoots));
|
||||
|
||||
cone1.setBlock(BlockRegistry.MOSSY_GLOWSHROOM_CAP);
|
||||
cone2.setBlock(BlockRegistry.MOSSY_GLOWSHROOM_CAP);
|
||||
priGlowCone.setBlock(BlockRegistry.MOSSY_GLOWSHROOM_HYMENOPHORE);
|
||||
primRoots.setBlock(BlockRegistry.MOSSY_GLOWSHROOM.bark);
|
||||
|
||||
float height = MHelper.randRange(10F, 25F, random);
|
||||
int count = MHelper.floor(height / 4);
|
||||
List<Vector3f> spline = SplineHelper.makeSpline(0, 0, 0, 0, height, 0, count);
|
||||
SplineHelper.offsetParts(spline, random, 1F, 0, 1F);
|
||||
SDF sdf = SplineHelper.buildSDF(spline, 2.1F, 1.5F, (pos) -> {
|
||||
return BlockRegistry.MOSSY_GLOWSHROOM.log.getDefaultState();
|
||||
});
|
||||
Vector3f pos = spline.get(spline.size() - 1);
|
||||
float scale = MHelper.randRange(2F, 3.5F, random);
|
||||
|
||||
HEAD_POS.setTranslate(pos.getX(), pos.getY(), pos.getZ());
|
||||
rotRoots.setAngle(random.nextFloat() * MHelper.PI2);
|
||||
function.setSourceA(sdf);
|
||||
|
||||
return new SDFRound().setRadius(1.5F).setSource(new SDFScale()
|
||||
.setScale(scale)
|
||||
.setSource(function))
|
||||
.setPostProcess((info) -> {
|
||||
if (BlockRegistry.MOSSY_GLOWSHROOM.isTreeLog(info.getState())) {
|
||||
if (random.nextBoolean() && info.getStateUp().getBlock() == BlockRegistry.MOSSY_GLOWSHROOM_CAP) {
|
||||
info.setState(BlockRegistry.MOSSY_GLOWSHROOM_CAP.getDefaultState().with(BlockMossyGlowshroomCap.TRANSITION, true));
|
||||
return info.getState();
|
||||
}
|
||||
else if (!BlockRegistry.MOSSY_GLOWSHROOM.isTreeLog(info.getStateUp()) || !BlockRegistry.MOSSY_GLOWSHROOM.isTreeLog(info.getStateDown())) {
|
||||
info.setState(BlockRegistry.MOSSY_GLOWSHROOM.bark.getDefaultState());
|
||||
return info.getState();
|
||||
}
|
||||
}
|
||||
else if (info.getState().getBlock() == BlockRegistry.MOSSY_GLOWSHROOM_CAP) {
|
||||
if (BlockRegistry.MOSSY_GLOWSHROOM.isTreeLog(info.getStateDown().getBlock())) {
|
||||
info.setState(BlockRegistry.MOSSY_GLOWSHROOM_CAP.getDefaultState().with(BlockMossyGlowshroomCap.TRANSITION, true));
|
||||
return info.getState();
|
||||
}
|
||||
|
||||
info.setState(BlockRegistry.MOSSY_GLOWSHROOM_CAP.getDefaultState());
|
||||
return info.getState();
|
||||
}
|
||||
else if (info.getState().getBlock() == BlockRegistry.MOSSY_GLOWSHROOM_HYMENOPHORE) {
|
||||
for (Direction dir: BlocksHelper.HORIZONTAL) {
|
||||
if (info.getState(dir) == AIR) {
|
||||
info.setBlockPos(info.getPos().offset(dir), BlockRegistry.MOSSY_GLOWSHROOM_FUR.getDefaultState().with(BlockGlowingFur.FACING, dir));
|
||||
}
|
||||
}
|
||||
|
||||
if (info.getStateDown().getBlock() != BlockRegistry.MOSSY_GLOWSHROOM_HYMENOPHORE) {
|
||||
info.setBlockPos(info.getPos().down(), BlockRegistry.MOSSY_GLOWSHROOM_FUR.getDefaultState().with(BlockGlowingFur.FACING, Direction.DOWN));
|
||||
}
|
||||
}
|
||||
return info.getState();
|
||||
});
|
||||
}
|
||||
}
|
|
@ -0,0 +1,18 @@
|
|||
package ru.betterend.world.structures.piece;
|
||||
|
||||
import net.minecraft.nbt.CompoundTag;
|
||||
import net.minecraft.structure.StructurePiece;
|
||||
import net.minecraft.structure.StructurePieceType;
|
||||
|
||||
public abstract class BasePiece extends StructurePiece {
|
||||
protected BasePiece(StructurePieceType type, int i) {
|
||||
super(type, i);
|
||||
}
|
||||
|
||||
protected BasePiece(StructurePieceType type, CompoundTag tag) {
|
||||
super(type, tag);
|
||||
fromNbt(tag);
|
||||
}
|
||||
|
||||
protected abstract void fromNbt(CompoundTag tag);
|
||||
}
|
|
@ -0,0 +1,48 @@
|
|||
package ru.betterend.world.structures.piece;
|
||||
|
||||
import java.util.Random;
|
||||
import java.util.function.Consumer;
|
||||
|
||||
import net.minecraft.nbt.CompoundTag;
|
||||
import net.minecraft.structure.StructureManager;
|
||||
import net.minecraft.util.math.BlockBox;
|
||||
import net.minecraft.util.math.BlockPos;
|
||||
import net.minecraft.util.math.ChunkPos;
|
||||
import net.minecraft.world.StructureWorldAccess;
|
||||
import net.minecraft.world.gen.StructureAccessor;
|
||||
import net.minecraft.world.gen.chunk.ChunkGenerator;
|
||||
import ru.betterend.registry.StructureRegistry;
|
||||
import ru.betterend.world.structures.StructureWorld;
|
||||
|
||||
public class VoxelPiece extends BasePiece {
|
||||
private StructureWorld world;
|
||||
|
||||
public VoxelPiece(Consumer<StructureWorld> function, int id) {
|
||||
super(StructureRegistry.VOXEL_PIECE, id);
|
||||
world = new StructureWorld();
|
||||
function.accept(world);
|
||||
this.boundingBox = world.getBounds();
|
||||
System.out.println(this.boundingBox);
|
||||
}
|
||||
|
||||
public VoxelPiece(StructureManager manager, CompoundTag tag) {
|
||||
super(StructureRegistry.VOXEL_PIECE, tag);
|
||||
this.boundingBox = world.getBounds();
|
||||
System.out.println(this.boundingBox);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void toNbt(CompoundTag tag) {
|
||||
tag.put("world", world.toBNT());
|
||||
}
|
||||
|
||||
protected void fromNbt(CompoundTag tag) {
|
||||
world = new StructureWorld(tag.getCompound("world"));
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean generate(StructureWorldAccess world, StructureAccessor arg, ChunkGenerator chunkGenerator, Random random, BlockBox blockBox, ChunkPos chunkPos, BlockPos blockPos) {
|
||||
this.world.placeChunk(world, chunkPos);
|
||||
return true;
|
||||
}
|
||||
}
|
|
@ -14,7 +14,8 @@
|
|||
"AbstractBlockMixin",
|
||||
"LivingEntityMixin",
|
||||
"BiomeMixin",
|
||||
"SlimeEntityMixin"
|
||||
"SlimeEntityMixin",
|
||||
"LocateCommandMixin"
|
||||
],
|
||||
"injectors": {
|
||||
"defaultRequire": 1
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue