#1335: Add API for in-world structures

By: coll1234567 <joshl5324@gmail.com>
This commit is contained in:
CraftBukkit/Spigot
2024-02-04 10:04:35 +11:00
parent f85f51fcf0
commit 49c217ec31
6 changed files with 148 additions and 5 deletions

View File

@@ -48,6 +48,8 @@ import org.bukkit.craftbukkit.block.CraftBiome;
import org.bukkit.craftbukkit.block.CraftBlock;
import org.bukkit.craftbukkit.block.data.CraftBlockData;
import org.bukkit.entity.Entity;
import org.bukkit.generator.structure.GeneratedStructure;
import org.bukkit.generator.structure.Structure;
import org.bukkit.persistence.PersistentDataContainer;
import org.bukkit.plugin.Plugin;
@@ -363,6 +365,16 @@ public class CraftChunk implements Chunk {
return LoadLevel.values()[chunk.getFullStatus().ordinal()];
}
@Override
public Collection<GeneratedStructure> getStructures() {
return getCraftWorld().getStructures(getX(), getZ());
}
@Override
public Collection<GeneratedStructure> getStructures(Structure structure) {
return getCraftWorld().getStructures(getX(), getZ(), structure);
}
@Override
public boolean equals(Object o) {
if (this == o) return true;

View File

@@ -27,6 +27,8 @@ import java.util.stream.Collectors;
import net.minecraft.core.BlockPosition;
import net.minecraft.core.Holder;
import net.minecraft.core.HolderSet;
import net.minecraft.core.IRegistry;
import net.minecraft.core.registries.Registries;
import net.minecraft.nbt.NBTBase;
import net.minecraft.nbt.NBTTagCompound;
import net.minecraft.network.protocol.game.ClientboundLevelChunkWithLightPacket;
@@ -62,6 +64,7 @@ import net.minecraft.world.level.biome.Climate;
import net.minecraft.world.level.chunk.ChunkStatus;
import net.minecraft.world.level.chunk.IChunkAccess;
import net.minecraft.world.level.chunk.ProtoChunkExtension;
import net.minecraft.world.level.levelgen.structure.StructureStart;
import net.minecraft.world.level.storage.SavedFile;
import net.minecraft.world.phys.AxisAlignedBB;
import net.minecraft.world.phys.MovingObjectPosition;
@@ -100,6 +103,7 @@ import org.bukkit.craftbukkit.block.data.CraftBlockData;
import org.bukkit.craftbukkit.boss.CraftDragonBattle;
import org.bukkit.craftbukkit.entity.CraftEntity;
import org.bukkit.craftbukkit.entity.CraftPlayer;
import org.bukkit.craftbukkit.generator.structure.CraftGeneratedStructure;
import org.bukkit.craftbukkit.generator.structure.CraftStructure;
import org.bukkit.craftbukkit.inventory.CraftItemStack;
import org.bukkit.craftbukkit.metadata.BlockMetadataStore;
@@ -130,6 +134,7 @@ import org.bukkit.event.world.TimeSkipEvent;
import org.bukkit.generator.BiomeProvider;
import org.bukkit.generator.BlockPopulator;
import org.bukkit.generator.ChunkGenerator;
import org.bukkit.generator.structure.GeneratedStructure;
import org.bukkit.generator.structure.Structure;
import org.bukkit.generator.structure.StructureType;
import org.bukkit.inventory.ItemStack;
@@ -1981,6 +1986,30 @@ public class CraftWorld extends CraftRegionAccessor implements World {
return (getHandle().getDragonFight() == null) ? null : new CraftDragonBattle(getHandle().getDragonFight());
}
@Override
public Collection<GeneratedStructure> getStructures(int x, int z) {
return getStructures(x, z, struct -> true);
}
@Override
public Collection<GeneratedStructure> getStructures(int x, int z, Structure structure) {
Preconditions.checkArgument(structure != null, "Structure cannot be null");
IRegistry<net.minecraft.world.level.levelgen.structure.Structure> registry = CraftRegistry.getMinecraftRegistry(Registries.STRUCTURE);
MinecraftKey key = registry.getKey(CraftStructure.bukkitToMinecraft(structure));
return getStructures(x, z, struct -> registry.getKey(struct).equals(key));
}
private List<GeneratedStructure> getStructures(int x, int z, Predicate<net.minecraft.world.level.levelgen.structure.Structure> predicate) {
List<GeneratedStructure> structures = new ArrayList<>();
for (StructureStart start : getHandle().structureManager().startsForStructure(new ChunkCoordIntPair(x, z), predicate)) {
structures.add(new CraftGeneratedStructure(start));
}
return structures;
}
@Override
public PersistentDataContainer getPersistentDataContainer() {
return persistentDataContainer;

View File

@@ -0,0 +1,52 @@
package org.bukkit.craftbukkit.generator.structure;
import com.google.common.collect.ImmutableList;
import java.util.Collection;
import java.util.List;
import net.minecraft.world.level.levelgen.structure.StructureBoundingBox;
import net.minecraft.world.level.levelgen.structure.StructureStart;
import org.bukkit.generator.structure.GeneratedStructure;
import org.bukkit.generator.structure.Structure;
import org.bukkit.generator.structure.StructurePiece;
import org.bukkit.persistence.PersistentDataContainer;
import org.bukkit.util.BoundingBox;
public class CraftGeneratedStructure implements GeneratedStructure {
private final StructureStart handle;
private List<StructurePiece> pieces;
public CraftGeneratedStructure(StructureStart handle) {
this.handle = handle;
}
@Override
public BoundingBox getBoundingBox() {
StructureBoundingBox bb = handle.getBoundingBox();
return new BoundingBox(bb.minX(), bb.minY(), bb.minZ(), bb.maxX(), bb.maxY(), bb.maxZ());
}
@Override
public Structure getStructure() {
return CraftStructure.minecraftToBukkit(handle.getStructure());
}
@Override
public Collection<StructurePiece> getPieces() {
if (pieces == null) { // Cache the pieces on first request
ImmutableList.Builder<StructurePiece> builder = new ImmutableList.Builder<>();
for (net.minecraft.world.level.levelgen.structure.StructurePiece piece : handle.getPieces()) {
builder.add(new CraftStructurePiece(piece));
}
pieces = builder.build();
}
return this.pieces;
}
@Override
public PersistentDataContainer getPersistentDataContainer() {
return handle.persistentDataContainer;
}
}

View File

@@ -0,0 +1,20 @@
package org.bukkit.craftbukkit.generator.structure;
import net.minecraft.world.level.levelgen.structure.StructureBoundingBox;
import org.bukkit.generator.structure.StructurePiece;
import org.bukkit.util.BoundingBox;
public class CraftStructurePiece implements StructurePiece {
private final net.minecraft.world.level.levelgen.structure.StructurePiece handle;
public CraftStructurePiece(net.minecraft.world.level.levelgen.structure.StructurePiece handle) {
this.handle = handle;
}
@Override
public BoundingBox getBoundingBox() {
StructureBoundingBox bb = handle.getBoundingBox();
return new BoundingBox(bb.minX(), bb.minY(), bb.minZ(), bb.maxX(), bb.maxY(), bb.maxZ());
}
}