use of ivorius.reccomplex.world.gen.feature.structure.context.StructureSpawnContext in project RecurrentComplex by Ivorforce.
the class TransformerNaturalAir method transform.
@Override
public void transform(InstanceData instanceData, Phase phase, StructureSpawnContext context, IvWorldData worldData, RunTransformer transformer) {
super.transform(instanceData, phase, context, worldData, transformer);
if (phase == Phase.AFTER) {
WorldServer world = context.environment.world;
IvBlockCollection blockCollection = worldData.blockCollection;
int[] areaSize = new int[] { blockCollection.width, blockCollection.height, blockCollection.length };
BlockPos lowerCoord = StructureBoundingBoxes.min(context.boundingBox);
// Remove dying foliage
HashSet<BlockPos> check = instanceData.cloud.keySet().stream().flatMap(pos -> new BlockArea(pos.subtract(new Vec3i(2, 2, 2)), pos.add(new Vec3i(2, 2, 2))).stream()).filter(pos -> !instanceData.cloud.containsKey(pos)).map(pos -> context.transform.apply(pos, areaSize).add(lowerCoord)).collect(Collectors.toCollection(HashSet::new));
Set<BlockPos> remove = new HashSet<>();
HashSet<BlockPos> start = new HashSet<>();
// Do each one separately, since each block needs to be connected to floor separately
check.forEach(checking -> {
start.add(checking);
if (visitRecursively(start, (changed, pos) -> {
IBlockState state = world.getBlockState(pos);
boolean isFoliage = RCBlockLogic.isFoliage(state, world, pos);
if (!RCBlockLogic.canStay(state, world, pos))
context.setBlock(pos, Blocks.AIR.getDefaultState(), 2);
else if (!isFoliage && !state.getBlock().isReplaceable(world, pos))
return false;
else if (isFoliage && remove.size() < MAX_TREE_SIZE && remove.add(pos))
neighbors(pos).forEach(changed::add);
return true;
})) {
remove.forEach(pos -> context.setBlock(pos, Blocks.AIR.getDefaultState(), 2));
}
start.clear();
remove.clear();
});
}
}
use of ivorius.reccomplex.world.gen.feature.structure.context.StructureSpawnContext in project RecurrentComplex by Ivorforce.
the class StructureGenerator method generate.
/**
* @return null when creation failed, empty when no entry was created and an entry when there was
*/
@Nonnull
public GenerationResult generate() {
Optional<S> optionalInstanceData = instanceData();
if (!optionalInstanceData.isPresent())
return failGenerate(GenerationResult.Failure.placement);
S instanceData = optionalInstanceData.get();
StructureSpawnContext spawn = spawn().get();
Structure<S> structure = structure();
String structureID = structureID();
boolean firstTime = spawn.generateMaturity.isFirstTime();
WorldServer world = spawn.environment.world;
StructureBoundingBox boundingBox = spawn.boundingBox;
if (maturity().isSuggest()) {
if (boundingBox.minY < MIN_DIST_TO_LIMIT || boundingBox.maxY > world.getHeight() - 1 - MIN_DIST_TO_LIMIT) {
return failGenerate(GenerationResult.Failure.outOfBounds);
}
if (RCConfig.avoidOverlappingGeneration && !allowOverlaps && !WorldStructureGenerationData.get(world).entriesAt(boundingBox).noneMatch(WorldStructureGenerationData.Entry::blocking)) {
return failGenerate(GenerationResult.Failure.structureOverlap);
}
if (RCEventBus.INSTANCE.post(new StructureGenerationEvent.Suggest(structure, spawn)) || (structureID != null && MinecraftForge.EVENT_BUS.post(new StructureGenerationEventLite.Suggest(world, structureID, boundingBox, spawn.generationLayer, firstTime)))) {
return failGenerate(GenerationResult.Failure.cancel);
}
}
if (firstTime) {
RCEventBus.INSTANCE.post(new StructureGenerationEvent.Pre(structure, spawn));
if (structureID != null)
MinecraftForge.EVENT_BUS.post(new StructureGenerationEventLite.Pre(world, structureID, boundingBox, spawn.generationLayer, firstTime));
}
RCWorldgenMonitor.start("generating " + structureID());
try {
structure.generate(spawn, instanceData, foreignTransformer());
} catch (Exception e) {
return failGenerate(new GenerationResult.Failure.Exception(e));
} finally {
RCWorldgenMonitor.stop();
}
if (!firstTime)
return GenerationResult.Success.complement;
RecurrentComplex.logger.trace(String.format("Generated structure '%s' in %s (%d)", name(structureID), boundingBox, world.provider.getDimension()));
RCEventBus.INSTANCE.post(new StructureGenerationEvent.Post(structure, spawn));
if (structureID != null)
MinecraftForge.EVENT_BUS.post(new StructureGenerationEventLite.Post(world, structureID, boundingBox, spawn.generationLayer, firstTime));
if (structureID == null || !memorize)
return GenerationResult.Success.contemporary;
String generationInfoID = generationType != null ? generationType.id() : null;
WorldStructureGenerationData.StructureEntry structureEntry = WorldStructureGenerationData.StructureEntry.complete(structureID, generationInfoID, boundingBox, spawn.transform, !partially);
structureEntry.blocking = structure.isBlocking();
// Been there done that
structureEntry.firstTime = false;
structureEntry.seed = seed();
try {
structureEntry.instanceData = instanceData.writeToNBT();
} catch (Exception e) {
RecurrentComplex.logger.error(String.format("Error saving instance data for structure %s in %s", structure, boundingBox), e);
}
Collection<ChunkPos> existingChunks = Sets.newHashSet(WorldStructureGenerationData.get(world).addEntry(structureEntry));
// Complement in all chunks that already exist
if (partially) {
maturity(StructureSpawnContext.GenerateMaturity.COMPLEMENT);
StructureBoundingBox oldBB = generationBB;
for (ChunkPos existingChunk : existingChunks) {
generationBB(Structures.chunkBoundingBox(existingChunk, true));
if (oldBB.intersectsWith(generationBB))
// Skip those that we just generated in, especially the same chunk
continue;
RCWorldgenMonitor.start("pre-complementing " + structureID());
structure.generate(spawn().get(), instanceData, RCConfig.getUniversalTransformer());
RCWorldgenMonitor.stop();
}
generationBB(oldBB);
}
return new GenerationResult.Success.New(structureEntry);
}
use of ivorius.reccomplex.world.gen.feature.structure.context.StructureSpawnContext in project RecurrentComplex by Ivorforce.
the class WorldScriptHolder method generate.
@Override
public void generate(StructureSpawnContext context, RunTransformer transformer, NBTNone instanceData, BlockPos pos) {
if (worldData == null) {
return;
}
GenericStructure structure = new GenericStructure();
structure.worldDataCompound = worldData.copy();
int[] strucSize = structure.size();
BlockPos strucCoord = context.transform.apply(origin, new int[] { 1, 1, 1 }).subtract(context.transform.apply(BlockPos.ORIGIN, strucSize)).add(pos);
new StructureGenerator<>(structure).asChild(context).transformer(transformer).lowerCoord(strucCoord).generationPredicate(p -> !p.equals(pos)).generate();
context.setBlock(pos, replaceState, 2);
}
Aggregations