use of org.spongepowered.math.vector.Vector3i in project SpongeCommon by SpongePowered.
the class SchematicTranslator method translate.
@Override
public Schematic translate(final DataView unprocessed) throws InvalidDataException {
if (SchematicTranslator.VANILLA_FIXER == null) {
SchematicTranslator.VANILLA_FIXER = SpongeCommon.server().getFixerUpper();
}
final DataView schematicView = unprocessed.getView(Constants.Sponge.Schematic.SCHEMATIC).orElse(unprocessed);
final int version = schematicView.getInt(Constants.Sponge.Schematic.VERSION).get();
if (version > Constants.Sponge.Schematic.CURRENT_VERSION) {
throw new InvalidDataException(String.format("Unknown schematic version %d (current version is %d)", version, Constants.Sponge.Schematic.CURRENT_VERSION));
} else if (version == 1) {
SchematicTranslator.V2_TO_3.update(SchematicTranslator.V1_TO_2.update(schematicView));
} else if (version == 2) {
SchematicTranslator.V2_TO_3.update(schematicView);
}
final int dataVersion = schematicView.getInt(Constants.Sponge.Schematic.DATA_VERSION).get();
// DataFixer will be able to upgrade entity and tile entity data if and only if we're running a valid server and
// the data version is outdated.
final boolean needsFixers = dataVersion < SharedConstants.getCurrentVersion().getWorldVersion() && SchematicTranslator.VANILLA_FIXER != null;
final DataView updatedView;
if (needsFixers) {
final CompoundTag compound = NBTTranslator.INSTANCE.translate(schematicView);
final CompoundTag updated = NbtUtils.update(SchematicTranslator.VANILLA_FIXER, DataFixTypes.CHUNK, compound, dataVersion);
updatedView = NBTTranslator.INSTANCE.translate(updated);
} else {
updatedView = schematicView;
}
final SpongeSchematicBuilder builder = new SpongeSchematicBuilder();
final Optional<DataView> metadataView = updatedView.getView(Constants.Sponge.Schematic.METADATA);
metadataView.ifPresent(metadata -> {
metadata.getView(DataQuery.of(".")).ifPresent(data -> {
for (final DataQuery key : data.keys(false)) {
if (!metadata.contains(key)) {
metadata.set(key, data.get(key).get());
}
}
});
final String schematicName = metadata.getString(Constants.Sponge.Schematic.NAME).orElse("unknown");
metadata.getStringList(Constants.Sponge.Schematic.REQUIRED_MODS).ifPresent(mods -> {
for (final String modId : mods) {
if (!Sponge.pluginManager().plugin(modId).isPresent()) {
if (SchematicTranslator.MISSING_MOD_IDS.add(modId)) {
SpongeCommon.logger().warn("When attempting to load the Schematic: {} there is a missing modid {} some blocks/tiles/entities may not load correctly.", schematicName, modId);
}
}
}
});
final DataContainer meta = DataContainer.createNew(DataView.SafetyMode.NO_DATA_CLONED);
for (final DataQuery key : metadata.keys(false)) {
meta.set(key, metadata.get(key).get());
}
builder.metadata(meta);
});
final int width = updatedView.getShort(Constants.Sponge.Schematic.WIDTH).orElseThrow(() -> new InvalidDataException("Missing value for: " + Constants.Sponge.Schematic.WIDTH));
final int height = updatedView.getShort(Constants.Sponge.Schematic.HEIGHT).orElseThrow(() -> new InvalidDataException("Missing value for: " + Constants.Sponge.Schematic.HEIGHT));
final int length = updatedView.getShort(Constants.Sponge.Schematic.LENGTH).orElseThrow(() -> new InvalidDataException("Missing value for: " + Constants.Sponge.Schematic.LENGTH));
if (width <= 0 || height <= 0 || length <= 0) {
throw new InvalidDataException(String.format("Schematic is larger than maximum allowable size (found: (%d, %d, %d) max: (%d, %<d, %<d)", width, height, length, Constants.Sponge.Schematic.MAX_SIZE));
}
final int[] offsetArray = (int[]) updatedView.get(Constants.Sponge.Schematic.OFFSET).orElse(new int[3]);
if (offsetArray.length != 3) {
throw new InvalidDataException("Schematic offset was not of length 3");
}
final Vector3i offset = new Vector3i(offsetArray[0], offsetArray[1], offsetArray[2]);
final SpongeArchetypeVolume archetypeVolume = new SpongeArchetypeVolume(offset, new Vector3i(width, height, length), Sponge.server());
updatedView.getView(Constants.Sponge.Schematic.BLOCK_CONTAINER).ifPresent(blocks -> SchematicTranslator.deserializeBlockContainer(blocks, archetypeVolume, width, length, offset, needsFixers));
updatedView.getView(Constants.Sponge.Schematic.BIOME_CONTAINER).ifPresent(biomes -> SchematicTranslator.deserializeBiomeContainer(biomes, archetypeVolume, width, length, offset));
updatedView.getViewList(Constants.Sponge.Schematic.ENTITIES).map(List::stream).orElse(Stream.of()).filter(entity -> entity.contains(Constants.Sponge.Schematic.ENTITIES_POS, Constants.Sponge.Schematic.ENTITIES_ID)).map(SchematicTranslator.deserializeEntityArchetype()).filter(Optional::isPresent).map(Optional::get).forEach(archetypeVolume::addEntity);
builder.volume(archetypeVolume);
return builder.build();
}
use of org.spongepowered.math.vector.Vector3i in project SpongeCommon by SpongePowered.
the class SchematicTranslator method addTo.
@Override
public DataView addTo(final Schematic schematic, final DataView data) {
final int xMin = schematic.min().x();
final int yMin = schematic.min().y();
final int zMin = schematic.min().z();
final int width = schematic.size().x();
final int height = schematic.size().y();
final int length = schematic.size().z();
if (width > Constants.Sponge.Schematic.MAX_SIZE || height > Constants.Sponge.Schematic.MAX_SIZE || length > Constants.Sponge.Schematic.MAX_SIZE) {
throw new IllegalArgumentException(String.format("Schematic is larger than maximum allowable size (found: (%d, %d, %d) max: (%d, %<d, %<d)", width, height, length, Constants.Sponge.Schematic.MAX_SIZE));
}
data.set(Constants.Sponge.Schematic.WIDTH, (short) width);
data.set(Constants.Sponge.Schematic.HEIGHT, (short) height);
data.set(Constants.Sponge.Schematic.LENGTH, (short) length);
data.set(Constants.Sponge.Schematic.VERSION, Constants.Sponge.Schematic.CURRENT_VERSION);
data.set(Constants.Sponge.Schematic.DATA_VERSION, SharedConstants.getCurrentVersion().getWorldVersion());
for (final DataQuery metaKey : schematic.metadata().keys(false)) {
data.set(Constants.Sponge.Schematic.METADATA.then(metaKey), schematic.metadata().get(metaKey).get());
}
final Set<String> requiredMods = new HashSet<>();
final int[] offset = new int[] { xMin, yMin, zMin };
data.set(Constants.Sponge.Schematic.OFFSET, offset);
// Check if we have blocks to store
if (schematic.blockPalette().highestId() != 0) {
final DataView blockData = data.createView(Constants.Sponge.Schematic.BLOCK_CONTAINER);
final Palette.Mutable<BlockState, BlockType> palette = schematic.blockPalette().asMutable(Sponge.server());
try (final ByteArrayOutputStream buffer = new ByteArrayOutputStream(width * height * length)) {
for (int y = 0; y < height; y++) {
final int y0 = yMin + y;
for (int z = 0; z < length; z++) {
final int z0 = zMin + z;
for (int x = 0; x < width; x++) {
final int x0 = xMin + x;
final BlockState state = schematic.block(x0, y0, z0);
SchematicTranslator.writeIdToBuffer(buffer, palette.orAssign(state));
}
}
}
blockData.set(Constants.Sponge.Schematic.BLOCK_DATA, buffer.toByteArray());
} catch (final IOException e) {
// should never reach here
}
final Registry<BlockType> blockRegistry = VolumeStreamUtils.nativeToSpongeRegistry(net.minecraft.core.Registry.BLOCK);
SchematicTranslator.writePaletteToView(blockData, palette, blockRegistry, Constants.Sponge.Schematic.BLOCK_PALETTE, BlockState::type, requiredMods);
final List<DataView> blockEntities = schematic.blockEntityArchetypes().entrySet().stream().map(entry -> {
final DataContainer container = DataContainer.createNew(DataView.SafetyMode.NO_DATA_CLONED);
final Vector3i pos = entry.getKey();
final BlockEntityArchetype archetype = entry.getValue();
final DataContainer entityData = archetype.blockEntityData();
final int[] apos = new int[] { pos.x() - xMin, pos.y() - yMin, pos.z() - zMin };
container.set(Constants.Sponge.Schematic.BLOCKENTITY_POS, apos);
container.set(Constants.Sponge.Schematic.BLOCKENTITY_DATA, entityData);
final ResourceKey key = archetype.blockEntityType().key(RegistryTypes.BLOCK_ENTITY_TYPE);
container.set(Constants.Sponge.Schematic.ENTITIES_ID, key.asString());
final String namespace = key.namespace();
if (!ResourceKey.MINECRAFT_NAMESPACE.equals(namespace)) {
requiredMods.add(namespace);
}
return container;
}).collect(Collectors.toList());
blockData.set(Constants.Sponge.Schematic.BLOCKENTITY_CONTAINER, blockEntities);
}
if (schematic.biomePalette().highestId() != 0) {
final DataView biomeContainer = data.createView(Constants.Sponge.Schematic.BIOME_CONTAINER);
final Palette.Mutable<Biome, Biome> biomePalette = schematic.biomePalette().asMutable(Sponge.game());
try (final ByteArrayOutputStream buffer = new ByteArrayOutputStream(width * height * length)) {
for (int y = 0; y < height; y++) {
final int y0 = yMin + y;
for (int z = 0; z < length; z++) {
final int z0 = zMin + z;
for (int x = 0; x < width; x++) {
final int x0 = xMin + x;
final Biome state = schematic.biome(x0, y0, z0);
SchematicTranslator.writeIdToBuffer(buffer, biomePalette.orAssign(state));
}
}
}
biomeContainer.set(Constants.Sponge.Schematic.BIOME_DATA, buffer.toByteArray());
} catch (final IOException e) {
// Should never reach here.
}
final Registry<Biome> biomeRegistry = VolumeStreamUtils.nativeToSpongeRegistry(BuiltinRegistries.BIOME);
SchematicTranslator.writePaletteToView(biomeContainer, biomePalette, biomeRegistry, Constants.Sponge.Schematic.BIOME_PALETTE, Function.identity(), requiredMods);
}
final List<DataView> entities = schematic.entityArchetypesByPosition().stream().map(entry -> {
final DataContainer container = DataContainer.createNew(DataView.SafetyMode.NO_DATA_CLONED);
final List<Double> entityPosition = new ArrayList<>();
entityPosition.add(entry.position().x());
entityPosition.add(entry.position().y());
entityPosition.add(entry.position().z());
container.set(Constants.Sponge.Schematic.ENTITIES_POS, entityPosition);
final ResourceKey key = entry.archetype().type().key(RegistryTypes.ENTITY_TYPE);
if (!ResourceKey.MINECRAFT_NAMESPACE.equals(key.namespace())) {
requiredMods.add(key.namespace());
}
container.set(Constants.Sponge.Schematic.ENTITIES_ID, key.toString());
final DataContainer entityData = entry.archetype().entityData();
container.set(Constants.Sponge.Schematic.BLOCKENTITY_DATA, entityData);
return container;
}).collect(Collectors.toList());
data.set(Constants.Sponge.Schematic.ENTITIES, entities);
if (!requiredMods.isEmpty()) {
data.set(Constants.Sponge.Schematic.METADATA.then(Constants.Sponge.Schematic.REQUIRED_MODS), requiredMods);
}
return data;
}
use of org.spongepowered.math.vector.Vector3i in project SpongeCommon by SpongePowered.
the class SpongeSchematicBuilder method build.
@Override
public Schematic build() throws IllegalArgumentException {
if (this.volume instanceof SpongeArchetypeVolume) {
final SpongeArchetypeVolume archetypeVolume = (SpongeArchetypeVolume) this.volume;
final Vector3i start = archetypeVolume.min();
final Vector3i blockSize = archetypeVolume.size();
return new SpongeSchematic(start, blockSize, archetypeVolume, this.metadata == null ? new MemoryDataContainer() : this.metadata);
}
throw new IllegalThreadStateException("Unimplemented");
}
use of org.spongepowered.math.vector.Vector3i in project SpongeCommon by SpongePowered.
the class VolumeStreamUtils method generateStream.
public static <R extends Volume, API, MC, Section, KeyReference> VolumeStream<R, API> generateStream(final Vector3i min, final Vector3i max, final StreamOptions options, final R ref, final BiConsumer<KeyReference, MC> identityFunction, final BiFunction<R, ChunkPos, Section> chunkAccessor, final BiFunction<BlockPos, MC, KeyReference> entityToKey, final Function<Section, Stream<Map.Entry<BlockPos, MC>>> entityAccessor, final BiFunction<KeyReference, R, Tuple<BlockPos, MC>> filteredPositionEntityAccessor) {
final Supplier<R> worldSupplier = VolumeStreamUtils.createWeaklyReferencedSupplier(ref, "World");
final BlockPos chunkMin = new BlockPos(min.x() >> 4, 0, min.z() >> 4);
final BlockPos chunkMax = new BlockPos(max.x() >> 4, 0, max.z() >> 4);
// Generate the chunk position stream to iterate on, whether they're accessed immediately
// or lazily is up to the stream options.
final Stream<Section> sectionStream = IntStream.range(chunkMin.getX(), chunkMax.getX() + 1).mapToObj(x -> IntStream.range(chunkMin.getZ(), chunkMax.getZ() + 1).mapToObj(z -> new ChunkPos(x, z))).flatMap(Function.identity()).map(pos -> chunkAccessor.apply(ref, pos));
return VolumeStreamUtils.generateStreamInternal(options, identityFunction, entityToKey, entityAccessor, filteredPositionEntityAccessor, worldSupplier, sectionStream);
}
use of org.spongepowered.math.vector.Vector3i in project SpongeCommon by SpongePowered.
the class VolumeStreamUtils method generateBlockStream.
public static <W extends Region<W>> VolumeStream<W, org.spongepowered.api.block.BlockState> generateBlockStream(final LevelReader reader, final Vector3i min, final Vector3i max, final StreamOptions options) {
VolumeStreamUtils.validateStreamArgs(Objects.requireNonNull(min, "min"), Objects.requireNonNull(max, "max"), Objects.requireNonNull(options, "options"));
final boolean shouldCarbonCopy = options.carbonCopy();
final Vector3i size = max.sub(min).add(1, 1, 1);
@MonotonicNonNull final ArrayMutableBlockBuffer backingVolume;
if (shouldCarbonCopy) {
backingVolume = new ArrayMutableBlockBuffer(min, size);
} else {
backingVolume = null;
}
return VolumeStreamUtils.<W, org.spongepowered.api.block.BlockState, net.minecraft.world.level.block.state.BlockState, ChunkAccess, BlockPos>generateStream(min, max, options, // Ref
(W) reader, // IdentityFunction
VolumeStreamUtils.getOrCopyBlockState(shouldCarbonCopy, backingVolume), // ChunkAccessor
VolumeStreamUtils.getChunkAccessorByStatus(reader, options.loadingStyle().generateArea()), // Biome by block position
(key, biome) -> key, // Entity Accessor
VolumeStreamUtils.getBlockStatesForSections(min, max), // Filtered Position Entity Accessor
VolumeStreamUtils.getBlockStateFromThisOrCopiedVolume(shouldCarbonCopy, backingVolume));
}
Aggregations