use of com.telepathicgrunt.repurposedstructures.mixin.structures.TemplateAccessor in project RepurposedStructures by TelepathicGrunt.
the class NbtDungeon method place.
@Override
public boolean place(FeaturePlaceContext<NbtDungeonConfig> context) {
if (GeneralUtils.isBlacklistedForWorld(context.level(), context.config().cfID))
return false;
BlockPos position = context.origin().above(-1);
ResourceLocation nbtRL = GeneralUtils.getRandomEntry(context.config().nbtResourcelocationsAndWeights, context.random());
StructureManager structureManager = context.level().getLevel().getStructureManager();
Optional<StructureTemplate> template = structureManager.get(nbtRL);
if (template.isEmpty()) {
RepurposedStructures.LOGGER.error("Identifier to the specified nbt file was not found! : {}", nbtRL);
return false;
}
Rotation rotation = Rotation.getRandom(context.random());
BlockPos size = new BlockPos(template.get().getSize());
// For proper offsetting the dungeon so it rotate properly around position parameter.
BlockPos halfLengths = new BlockPos(size.getX() / 2, size.getY() / 2, size.getZ() / 2);
// Rotated blockpos for the nbt's sizes to be used later.
BlockPos fullLengths = new BlockPos(Math.abs(size.rotate(rotation).getX()), Math.abs(size.rotate(rotation).getY()), Math.abs(size.rotate(rotation).getZ()));
// For post processing spawners and chests for rotated dungeon.
BlockPos halfLengthsRotated = new BlockPos(fullLengths.getX() / 2, fullLengths.getY() / 2, fullLengths.getZ() / 2);
BlockPos.MutableBlockPos mutable = new BlockPos.MutableBlockPos().set(position);
ChunkAccess cachedChunk = context.level().getChunk(mutable);
int xMin = -halfLengthsRotated.getX();
int xMax = halfLengthsRotated.getX();
int zMin = -halfLengthsRotated.getZ();
int zMax = halfLengthsRotated.getZ();
int wallOpenings = 0;
int ceilingOpenings = 0;
int ceiling = size.getY();
for (int x = xMin; x <= xMax; x++) {
for (int z = zMin; z <= zMax; z++) {
for (int y = 0; y <= ceiling; y++) {
mutable.set(position).move(x, y, z);
if (mutable.getX() >> 4 != cachedChunk.getPos().x || mutable.getZ() >> 4 != cachedChunk.getPos().z)
cachedChunk = context.level().getChunk(mutable);
BlockState state = cachedChunk.getBlockState(mutable);
// Dungeons cannot touch fluids if set to air mode and reverse if opposite
if (context.config().airRequirementIsNowWater ? state.isAir() || state.getFluidState().is(FluidTags.LAVA) : !state.getFluidState().isEmpty()) {
return false;
} else // Floor must be complete
if (!GeneralUtils.isFullCube(context.level(), mutable, state)) {
if (y == 0 && !state.getMaterial().isSolid()) {
return false;
} else if (state.is(BlockTags.LEAVES)) {
// ignore leaves
continue;
} else if (y == ceiling) {
ceilingOpenings++;
}
}
// Check only along wall bottoms for openings
if ((x == xMin || x == xMax || z == zMin || z == zMax) && y == 1 && isValidNonSolidBlock(context.config(), state)) {
BlockState aboveState = cachedChunk.getBlockState(mutable);
if (context.config().airRequirementIsNowWater ? !aboveState.getFluidState().isEmpty() : aboveState.isAir()) {
wallOpenings++;
}
}
// Too much open space. Quit
if (wallOpenings > context.config().maxAirSpace || ceilingOpenings > context.config().maxAirSpace) {
return false;
}
}
}
}
// Check if we meet minimum for open space.
if (wallOpenings >= context.config().minAirSpace) {
// offset the dungeon such as ocean dungeons down 1
position = position.above(context.config().structureYOffset);
// RepurposedStructures.LOGGER.log(Level.INFO, nbtRL + " at X: "+position.getX() +", "+position.getY()+", "+position.getZ());
StructurePlaceSettings placementsettings = (new StructurePlaceSettings()).setRotation(rotation).setRotationPivot(halfLengths).setIgnoreEntities(false);
Optional<StructureProcessorList> processor = context.level().getLevel().getServer().registryAccess().registryOrThrow(Registry.PROCESSOR_LIST_REGISTRY).getOptional(context.config().processor);
// add all processors
processor.orElse(ProcessorLists.EMPTY.value()).list().forEach(placementsettings::addProcessor);
BlockPos finalPos = mutable.set(position).move(-halfLengths.getX(), 0, -halfLengths.getZ());
template.get().placeInWorld(context.level(), finalPos, finalPos, placementsettings, context.random(), Block.UPDATE_CLIENTS);
// Post-processors
// For all processors that are sensitive to neighboring blocks such as vines.
// Post processors will place the blocks themselves so we will not do anything with the return of Structure.process
placementsettings.clearProcessors();
Optional<StructureProcessorList> postProcessor = context.level().getLevel().getServer().registryAccess().registryOrThrow(Registry.PROCESSOR_LIST_REGISTRY).getOptional(context.config().postProcessor);
// add all post processors
postProcessor.orElse(ProcessorLists.EMPTY.value()).list().forEach(placementsettings::addProcessor);
List<StructureTemplate.StructureBlockInfo> list = placementsettings.getRandomPalette(((TemplateAccessor) template.get()).repurposedstructures_getPalettes(), mutable).blocks();
StructureTemplate.processBlockInfos(context.level(), mutable, mutable, placementsettings, list, template.get());
spawnLootBlocks(context.level(), context.random(), position, context.config(), fullLengths, halfLengthsRotated, mutable);
return true;
}
return false;
}
Aggregations