use of org.spongepowered.common.world.volume.buffer.archetype.SpongeArchetypeVolume in project SpongeCommon by SpongePowered.
the class VolumeTransformationTest method testTransformationsOfPositions.
@MethodSource("testTransformationsOfPositions")
@ParameterizedTest
void testTransformationsOfPositions(final Vector3i min, final Vector3i max, final Vector3i origin, final Vector3i testForRoundTrip, final int rotationCount, final StubRotations wanted) {
final SpongeArchetypeVolume volume = VolumeTransformationTest.fillVolume(min, max, origin);
final Vector3i size = volume.size();
final Vector3i relativeMin = volume.min();
final Vector3d center = volume.logicalCenter();
ArchetypeVolume intermediary = volume;
for (int i = 0; i < rotationCount; i++) {
intermediary = intermediary.transform(Transformation.builder().origin(center).rotate(wanted).build());
}
Rotation expected = Rotations.NONE.get();
for (int i = 0; i < rotationCount; i++) {
expected = expected.and(wanted);
}
final Transformation expectedTransform = Transformation.builder().origin(center).rotate(expected).build();
final Transformation inverse = expectedTransform.inverse();
final ArchetypeVolume rotated = intermediary;
if (rotationCount > 0) {
final Vector3d preliminaryTransformed = expectedTransform.transformPosition(testForRoundTrip.toDouble());
Vector3i unTransformed = preliminaryTransformed.round().toInt();
for (int i = 0; i < rotationCount; i++) {
unTransformed = ((AbstractReferentArchetypeVolume) rotated).inverseTransform(unTransformed.x(), unTransformed.y(), unTransformed.z());
}
Assertions.assertEquals(testForRoundTrip, unTransformed);
}
for (int x = 0; x < size.x(); x++) {
for (int y = 0; y < size.y(); y++) {
for (int z = 0; z < size.z(); z++) {
final int relativeX = x + relativeMin.x();
final int relativeY = y + relativeMin.y();
final int relativeZ = z + relativeMin.z();
final Vector3d rawRelativePosition = new Vector3d(relativeX, relativeY, relativeZ);
final BlockState untransformedState = volume.block(relativeX, relativeY, relativeZ);
final Vector3i transformedPosition = expectedTransform.transformPosition(rawRelativePosition).toInt();
final BlockState transformedState = rotated.block(transformedPosition.x(), transformedPosition.y(), transformedPosition.z());
Assertions.assertEquals(untransformedState, transformedState, () -> String.format("Block Check Failed!\nOriginal(%d, %d, %d): %s\nTransformed(%d, %d, %d): %s\n", relativeX, relativeY, relativeZ, untransformedState, transformedPosition.x(), transformedPosition.y(), transformedPosition.z(), transformedState));
}
}
}
if (rotationCount < 0) {
return;
}
// At this point, we should have an abstract referent volume at least
rotated.blockStateStream(rotated.min(), rotated.max(), StreamOptions.lazily()).forEach((rotatedRef, type, x, y, z) -> {
final Vector3d transformedPos = new Vector3d(x, y, z);
// We have this offset in the stream, so we have to undo it here.
final Vector3d invertedTransformedPos = inverse.transformPosition(transformedPos.add(VolumePositionTranslators.BLOCK_OFFSET)).sub(VolumePositionTranslators.BLOCK_OFFSET);
final Vector3i invertedBlockPos = invertedTransformedPos.toInt();
final Vector3i expectedPos;
Assertions.assertTrue(type instanceof StubState, () -> String.format("expected state to be a stub state for pos: [%f, %f, %f] but got %s", x, y, z, type));
Assertions.assertNotEquals(((StubState) type).deducedPos, VolumeTransformationTest.INVALID_STUB_POSITION, () -> String.format("expected to have a positioned stub state: [%f, %f, %f] but got %s", x, y, z, type));
expectedPos = ((StubState) type).deducedPos;
Assertions.assertEquals(expectedPos, invertedBlockPos, () -> String.format("expected untransformed position %s for state %s does not match reverse transformed position: %s", expectedPos, type, invertedBlockPos));
final BlockState block = volume.block(expectedPos.x(), expectedPos.y(), expectedPos.z());
Assertions.assertEquals(type, block, () -> String.format("Expected deduced state to be equal from the original target volume but had a mismatch: Original target %s does not match %s", block, type));
});
}
use of org.spongepowered.common.world.volume.buffer.archetype.SpongeArchetypeVolume in project SpongeCommon by SpongePowered.
the class VolumeTransformationTest method fillVolume.
private static SpongeArchetypeVolume fillVolume(final Vector3i min, final Vector3i max, final Vector3i origin) {
final Vector3i rawMin = min.min(max);
final Vector3i rawMax = max.max(min);
final Vector3i size = rawMax.sub(rawMin).add(Vector3i.ONE);
final Vector3i relativeMin = rawMin.sub(origin);
final RegistryHolder holder = Sponge.game();
final SpongeArchetypeVolume volume = new SpongeArchetypeVolume(relativeMin, size, holder);
final StubbedRegistry<BlockType> blockRegistry = (StubbedRegistry<BlockType>) RegistryTypes.BLOCK_TYPE.get();
final Vector3i volMax = volume.max().add(Vector3i.ONE);
IntStream.range(relativeMin.x(), volMax.x()).forEach(x -> IntStream.range(relativeMin.z(), volMax.z()).forEach(z -> IntStream.range(relativeMin.y(), volMax.y()).forEach(y -> {
final BlockType block = blockRegistry.createEntry("minecraft", String.format("volumetest{%d, %d, %d}", x, y, z));
final BlockState blockState = block.defaultState();
volume.setBlock(x, y, z, blockState);
})));
return volume;
}
use of org.spongepowered.common.world.volume.buffer.archetype.SpongeArchetypeVolume in project SpongeCommon by SpongePowered.
the class LevelMixin_API method createArchetypeVolume.
@Override
public ArchetypeVolume createArchetypeVolume(final Vector3i min, final Vector3i max, final Vector3i origin) {
final Vector3i rawVolMin = Objects.requireNonNull(min, "min").min(Objects.requireNonNull(max, "max"));
final Vector3i volMax = max.max(min);
final Vector3i size = volMax.sub(rawVolMin).add(1, 1, 1);
final Vector3i relativeMin = rawVolMin.sub(Objects.requireNonNull(origin, "origin"));
final SpongeArchetypeVolume volume = new SpongeArchetypeVolume(relativeMin, size, this);
this.blockStateStream(min, max, StreamOptions.lazily()).apply(VolumeCollectors.of(volume, VolumePositionTranslators.offset(origin), VolumeApplicators.applyBlocks()));
this.blockEntityStream(min, max, StreamOptions.lazily()).map((world, blockEntity, x, y, z) -> blockEntity.get().createArchetype()).apply(VolumeCollectors.of(volume, VolumePositionTranslators.offset(origin), VolumeApplicators.applyBlockEntityArchetypes()));
this.biomeStream(min, max, StreamOptions.lazily()).apply(VolumeCollectors.of(volume, VolumePositionTranslators.offset(origin), VolumeApplicators.applyBiomes()));
this.entityStream(min, max, StreamOptions.lazily()).filter((world, entity, x, y, z) -> ((EntityAccessor) entity.get()).invoker$getEncodeId() != null || entity.get().type() == HumanEntity.TYPE).map((world, entity, x, y, z) -> entity.get().createArchetype()).apply(VolumeCollectors.of(volume, VolumePositionTranslators.offset(origin), VolumeApplicators.applyEntityArchetypes()));
return volume;
}
use of org.spongepowered.common.world.volume.buffer.archetype.SpongeArchetypeVolume 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.common.world.volume.buffer.archetype.SpongeArchetypeVolume 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");
}
Aggregations