SPIGOT-7011, SPIGOT-7065: Overhaul of structures

By: DerFrZocker <derrieple@gmail.com>
This commit is contained in:
CraftBukkit/Spigot
2022-07-01 20:41:04 +10:00
parent 8bf76d9868
commit 230282ea44
11 changed files with 397 additions and 57 deletions

View File

@@ -0,0 +1,74 @@
package org.bukkit.craftbukkit;
import java.util.HashMap;
import java.util.Iterator;
import java.util.Map;
import java.util.function.BiFunction;
import java.util.stream.Stream;
import net.minecraft.core.IRegistry;
import net.minecraft.core.IRegistryCustom;
import org.bukkit.Keyed;
import org.bukkit.NamespacedKey;
import org.bukkit.Registry;
import org.bukkit.craftbukkit.generator.strucutre.CraftStructure;
import org.bukkit.craftbukkit.generator.strucutre.CraftStructureType;
import org.bukkit.craftbukkit.util.CraftNamespacedKey;
import org.bukkit.generator.structure.Structure;
import org.bukkit.generator.structure.StructureType;
public class CraftRegistry<B extends Keyed, M> implements Registry<B> {
public static <B extends Keyed> Registry<?> createRegistry(Class<B> bukkitClass, IRegistryCustom registryHolder) {
if (bukkitClass == Structure.class) {
return new CraftRegistry<>(registryHolder.registryOrThrow(IRegistry.STRUCTURE_REGISTRY), CraftStructure::new);
}
if (bukkitClass == StructureType.class) {
return new CraftRegistry<>(IRegistry.STRUCTURE_TYPES, CraftStructureType::new);
}
return null;
}
private final Map<NamespacedKey, B> cache = new HashMap<>();
private final IRegistry<M> minecraftRegistry;
private final BiFunction<NamespacedKey, M, B> minecraftToBukkit;
public CraftRegistry(IRegistry<M> minecraftRegistry, BiFunction<NamespacedKey, M, B> minecraftToBukkit) {
this.minecraftRegistry = minecraftRegistry;
this.minecraftToBukkit = minecraftToBukkit;
}
@Override
public B get(NamespacedKey namespacedKey) {
B cached = cache.get(namespacedKey);
if (cached != null) {
return cached;
}
B bukkit = createBukkit(namespacedKey, minecraftRegistry.getOptional(CraftNamespacedKey.toMinecraft(namespacedKey)).orElse(null));
if (bukkit == null) {
return null;
}
cache.put(namespacedKey, bukkit);
return bukkit;
}
@Override
public Iterator<B> iterator() {
return values().iterator();
}
public B createBukkit(NamespacedKey namespacedKey, M minecraft) {
if (minecraft == null) {
return null;
}
return minecraftToBukkit.apply(namespacedKey, minecraft);
}
public Stream<B> values() {
return minecraftRegistry.keySet().stream().map(minecraftKey -> get(CraftNamespacedKey.fromMinecraft(minecraftKey)));
}
}

View File

@@ -28,6 +28,7 @@ import java.nio.charset.StandardCharsets;
import java.util.ArrayList;
import java.util.Base64;
import java.util.Collections;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Iterator;
import java.util.LinkedHashMap;
@@ -117,6 +118,7 @@ import org.bukkit.Keyed;
import org.bukkit.Location;
import org.bukkit.NamespacedKey;
import org.bukkit.OfflinePlayer;
import org.bukkit.Registry;
import org.bukkit.Server;
import org.bukkit.StructureType;
import org.bukkit.UnsafeValues;
@@ -257,6 +259,7 @@ public final class CraftServer implements Server {
protected final DedicatedServer console;
protected final DedicatedPlayerList playerList;
private final Map<String, World> worlds = new LinkedHashMap<String, World>();
private final Map<Class<?>, Registry<?>> registries = new HashMap<>();
private YamlConfiguration configuration;
private YamlConfiguration commandsConfiguration;
private final Yaml yaml = new Yaml(new SafeConstructor());
@@ -2260,6 +2263,11 @@ public final class CraftServer implements Server {
return structureManager;
}
@Override
public <T extends Keyed> Registry<T> getRegistry(Class<T> aClass) {
return (Registry<T>) registries.computeIfAbsent(aClass, key -> CraftRegistry.createRegistry(aClass, console.registryHolder));
}
@Deprecated
@Override
public UnsafeValues getUnsafe() {

View File

@@ -4,6 +4,7 @@ import com.google.common.base.Preconditions;
import com.google.common.base.Predicates;
import com.google.common.collect.ImmutableList;
import com.google.common.collect.ImmutableMap;
import com.mojang.datafixers.util.Pair;
import it.unimi.dsi.fastutil.longs.Long2ObjectLinkedOpenHashMap;
import it.unimi.dsi.fastutil.longs.Long2ObjectMap;
import it.unimi.dsi.fastutil.objects.Object2IntOpenHashMap;
@@ -25,7 +26,7 @@ import java.util.function.Predicate;
import java.util.stream.Collectors;
import net.minecraft.core.BlockPosition;
import net.minecraft.core.Holder;
import net.minecraft.core.IRegistry;
import net.minecraft.core.HolderSet;
import net.minecraft.nbt.NBTBase;
import net.minecraft.nbt.NBTTagCompound;
import net.minecraft.network.protocol.game.ClientboundLevelChunkWithLightPacket;
@@ -79,8 +80,8 @@ import org.bukkit.Location;
import org.bukkit.NamespacedKey;
import org.bukkit.Particle;
import org.bukkit.Raid;
import org.bukkit.Registry;
import org.bukkit.Sound;
import org.bukkit.StructureType;
import org.bukkit.TreeType;
import org.bukkit.World;
import org.bukkit.WorldBorder;
@@ -95,6 +96,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.strucutre.CraftStructure;
import org.bukkit.craftbukkit.inventory.CraftItemStack;
import org.bukkit.craftbukkit.metadata.BlockMetadataStore;
import org.bukkit.craftbukkit.persistence.CraftPersistentDataContainer;
@@ -104,6 +106,7 @@ import org.bukkit.craftbukkit.util.CraftMagicNumbers;
import org.bukkit.craftbukkit.util.CraftNamespacedKey;
import org.bukkit.craftbukkit.util.CraftRayTraceResult;
import org.bukkit.craftbukkit.util.CraftSpawnCategory;
import org.bukkit.craftbukkit.util.CraftStructureSearchResult;
import org.bukkit.entity.AbstractArrow;
import org.bukkit.entity.Arrow;
import org.bukkit.entity.Entity;
@@ -122,6 +125,8 @@ 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.Structure;
import org.bukkit.generator.structure.StructureType;
import org.bukkit.inventory.ItemStack;
import org.bukkit.material.MaterialData;
import org.bukkit.metadata.MetadataValue;
@@ -133,6 +138,7 @@ import org.bukkit.potion.PotionType;
import org.bukkit.util.BoundingBox;
import org.bukkit.util.Consumer;
import org.bukkit.util.RayTraceResult;
import org.bukkit.util.StructureSearchResult;
import org.bukkit.util.Vector;
public class CraftWorld extends CraftRegionAccessor implements World {
@@ -1776,11 +1782,84 @@ public class CraftWorld extends CraftRegionAccessor implements World {
}
@Deprecated
@Override
public Location locateNearestStructure(Location origin, StructureType structureType, int radius, boolean findUnexplored) {
public Location locateNearestStructure(Location origin, org.bukkit.StructureType structureType, int radius, boolean findUnexplored) {
StructureSearchResult result = null;
// Manually map the mess of the old StructureType to the new StructureType and normal Structure
if (org.bukkit.StructureType.MINESHAFT == structureType) {
result = locateNearestStructure(origin, StructureType.MINESHAFT, radius, findUnexplored);
} else if (org.bukkit.StructureType.VILLAGE == structureType) {
result = locateNearestStructure(origin, List.of(Structure.VILLAGE_DESERT, Structure.VILLAGE_PLAINS, Structure.VILLAGE_SAVANNA, Structure.VILLAGE_SNOWY, Structure.VILLAGE_TAIGA), radius, findUnexplored);
} else if (org.bukkit.StructureType.NETHER_FORTRESS == structureType) {
result = locateNearestStructure(origin, StructureType.FORTRESS, radius, findUnexplored);
} else if (org.bukkit.StructureType.STRONGHOLD == structureType) {
result = locateNearestStructure(origin, StructureType.STRONGHOLD, radius, findUnexplored);
} else if (org.bukkit.StructureType.JUNGLE_PYRAMID == structureType) {
result = locateNearestStructure(origin, StructureType.JUNGLE_TEMPLE, radius, findUnexplored);
} else if (org.bukkit.StructureType.OCEAN_RUIN == structureType) {
result = locateNearestStructure(origin, StructureType.OCEAN_RUIN, radius, findUnexplored);
} else if (org.bukkit.StructureType.DESERT_PYRAMID == structureType) {
result = locateNearestStructure(origin, StructureType.DESERT_PYRAMID, radius, findUnexplored);
} else if (org.bukkit.StructureType.IGLOO == structureType) {
result = locateNearestStructure(origin, StructureType.IGLOO, radius, findUnexplored);
} else if (org.bukkit.StructureType.SWAMP_HUT == structureType) {
result = locateNearestStructure(origin, StructureType.SWAMP_HUT, radius, findUnexplored);
} else if (org.bukkit.StructureType.OCEAN_MONUMENT == structureType) {
result = locateNearestStructure(origin, StructureType.OCEAN_MONUMENT, radius, findUnexplored);
} else if (org.bukkit.StructureType.END_CITY == structureType) {
result = locateNearestStructure(origin, StructureType.END_CITY, radius, findUnexplored);
} else if (org.bukkit.StructureType.WOODLAND_MANSION == structureType) {
result = locateNearestStructure(origin, StructureType.WOODLAND_MANSION, radius, findUnexplored);
} else if (org.bukkit.StructureType.BURIED_TREASURE == structureType) {
result = locateNearestStructure(origin, StructureType.BURIED_TREASURE, radius, findUnexplored);
} else if (org.bukkit.StructureType.SHIPWRECK == structureType) {
result = locateNearestStructure(origin, StructureType.SHIPWRECK, radius, findUnexplored);
} else if (org.bukkit.StructureType.PILLAGER_OUTPOST == structureType) {
result = locateNearestStructure(origin, Structure.PILLAGER_OUTPOST, radius, findUnexplored);
} else if (org.bukkit.StructureType.NETHER_FOSSIL == structureType) {
result = locateNearestStructure(origin, StructureType.NETHER_FOSSIL, radius, findUnexplored);
} else if (org.bukkit.StructureType.RUINED_PORTAL == structureType) {
result = locateNearestStructure(origin, StructureType.RUINED_PORTAL, radius, findUnexplored);
} else if (org.bukkit.StructureType.BASTION_REMNANT == structureType) {
result = locateNearestStructure(origin, Structure.BASTION_REMNANT, radius, findUnexplored);
}
return (result == null) ? null : result.getLocation();
}
@Override
public StructureSearchResult locateNearestStructure(Location origin, StructureType structureType, int radius, boolean findUnexplored) {
List<Structure> structures = new ArrayList<>();
for (Structure structure : Registry.STRUCTURE) {
if (structure.getStructureType() == structureType) {
structures.add(structure);
}
}
return locateNearestStructure(origin, structures, radius, findUnexplored);
}
@Override
public StructureSearchResult locateNearestStructure(Location origin, Structure structure, int radius, boolean findUnexplored) {
return locateNearestStructure(origin, List.of(structure), radius, findUnexplored);
}
public StructureSearchResult locateNearestStructure(Location origin, List<Structure> structures, int radius, boolean findUnexplored) {
BlockPosition originPos = new BlockPosition(origin.getX(), origin.getY(), origin.getZ());
BlockPosition nearest = getHandle().findNearestMapStructure(TagKey.create(IRegistry.STRUCTURE_REGISTRY, CraftNamespacedKey.toMinecraft(structureType.getKey())), originPos, radius, findUnexplored);
return (nearest == null) ? null : new Location(this, nearest.getX(), nearest.getY(), nearest.getZ());
List<Holder<net.minecraft.world.level.levelgen.structure.Structure>> holders = new ArrayList<>();
for (Structure structure : structures) {
holders.add(Holder.direct(CraftStructure.bukkitToMinecraft(structure)));
}
Pair<BlockPosition, Holder<net.minecraft.world.level.levelgen.structure.Structure>> found = getHandle().getChunkSource().getGenerator().findNearestMapStructure(getHandle(), HolderSet.direct(holders), originPos, radius, findUnexplored);
if (found == null) {
return null;
}
return new CraftStructureSearchResult(CraftStructure.minecraftToBukkit(found.getSecond().value(), getHandle().registryAccess()), new Location(this, found.getFirst().getX(), found.getFirst().getY(), found.getFirst().getZ()));
}
@Override

View File

@@ -0,0 +1,52 @@
package org.bukkit.craftbukkit.generator.strucutre;
import net.minecraft.core.IRegistry;
import net.minecraft.core.IRegistryCustom;
import org.bukkit.NamespacedKey;
import org.bukkit.Registry;
import org.bukkit.craftbukkit.util.CraftNamespacedKey;
import org.bukkit.generator.structure.Structure;
import org.bukkit.generator.structure.StructureType;
public class CraftStructure extends Structure {
public static Structure minecraftToBukkit(net.minecraft.world.level.levelgen.structure.Structure minecraft, IRegistryCustom registryHolder) {
if (minecraft == null) {
return null;
}
return Registry.STRUCTURE.get(CraftNamespacedKey.fromMinecraft(registryHolder.registryOrThrow(IRegistry.STRUCTURE_REGISTRY).getKey(minecraft)));
}
public static net.minecraft.world.level.levelgen.structure.Structure bukkitToMinecraft(Structure bukkit) {
if (bukkit == null) {
return null;
}
return ((CraftStructure) bukkit).getHandle();
}
private final NamespacedKey key;
private final net.minecraft.world.level.levelgen.structure.Structure structure;
private final StructureType structureType;
public CraftStructure(NamespacedKey key, net.minecraft.world.level.levelgen.structure.Structure structure) {
this.key = key;
this.structure = structure;
this.structureType = CraftStructureType.minecraftToBukkit(structure.type());
}
public net.minecraft.world.level.levelgen.structure.Structure getHandle() {
return structure;
}
@Override
public StructureType getStructureType() {
return structureType;
}
@Override
public NamespacedKey getKey() {
return key;
}
}

View File

@@ -0,0 +1,43 @@
package org.bukkit.craftbukkit.generator.strucutre;
import net.minecraft.core.IRegistry;
import org.bukkit.NamespacedKey;
import org.bukkit.Registry;
import org.bukkit.craftbukkit.util.CraftNamespacedKey;
import org.bukkit.generator.structure.StructureType;
public class CraftStructureType extends StructureType {
public static StructureType minecraftToBukkit(net.minecraft.world.level.levelgen.structure.StructureType<?> minecraft) {
if (minecraft == null) {
return null;
}
return Registry.STRUCTURE_TYPE.get(CraftNamespacedKey.fromMinecraft(IRegistry.STRUCTURE_TYPES.getKey(minecraft)));
}
public static net.minecraft.world.level.levelgen.structure.StructureType<?> bukkitToMinecraft(StructureType bukkit) {
if (bukkit == null) {
return null;
}
return ((CraftStructureType) bukkit).getHandle();
}
private final NamespacedKey key;
private final net.minecraft.world.level.levelgen.structure.StructureType<?> structureType;
public CraftStructureType(NamespacedKey key, net.minecraft.world.level.levelgen.structure.StructureType<?> structureType) {
this.key = key;
this.structureType = structureType;
}
public net.minecraft.world.level.levelgen.structure.StructureType<?> getHandle() {
return structureType;
}
@Override
public NamespacedKey getKey() {
return key;
}
}

View File

@@ -0,0 +1,24 @@
package org.bukkit.craftbukkit.util;
import org.bukkit.Location;
import org.bukkit.generator.structure.Structure;
import org.bukkit.util.StructureSearchResult;
public class CraftStructureSearchResult implements StructureSearchResult {
private final Structure structure;
private final Location location;
public CraftStructureSearchResult(Structure structure, Location location) {
this.structure = structure;
this.location = location;
}
public Structure getStructure() {
return structure;
}
public Location getLocation() {
return location;
}
}