All Downloads are FREE. Search and download functionalities are using the official Maven repository.

cn.nukkit.level.generator.Generator Maven / Gradle / Ivy

There is a newer version: 1.20.40-r1
Show newest version
package cn.nukkit.level.generator;

import cn.nukkit.api.PowerNukkitXDifference;
import cn.nukkit.api.PowerNukkitXOnly;
import cn.nukkit.api.Since;
import cn.nukkit.block.BlockID;
import cn.nukkit.level.ChunkManager;
import cn.nukkit.level.DimensionData;
import cn.nukkit.level.DimensionEnum;
import cn.nukkit.level.Level;
import cn.nukkit.level.generator.populator.type.PopulatorStructure;
import cn.nukkit.math.NukkitRandom;
import cn.nukkit.math.Vector3;

import java.lang.reflect.InvocationTargetException;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

/**
 * @author MagicDroidX (Nukkit Project)
 */
public abstract class Generator implements BlockID {

    public static final int TYPE_OLD = 0;
    public static final int TYPE_INFINITE = 1;
    public static final int TYPE_FLAT = 2;
    public static final int TYPE_NETHER = 3;
    public static final int TYPE_THE_END = 4;

    @PowerNukkitXOnly
    @Since("1.19.21-r2")
    protected Level level;

    @Since("1.19.21-r2")
    protected ChunkManager chunkManager;

    @PowerNukkitXOnly
    @Since("1.19.21-r2")
    protected NukkitRandom random;

    @PowerNukkitXOnly
    @Since("1.19.21-r2")
    protected List structurePopulators = new ArrayList<>();

    {
        if (shouldGenerateStructures()) {
            try {
                for (Class cz : PopulatorStructure.getPopulators()) {
                    structurePopulators.add(cz.getConstructor().newInstance());
                }
            } catch (InstantiationException | NoSuchMethodException | InvocationTargetException |
                     IllegalAccessException e) {
                throw new RuntimeException(e);
            }
        }
    }

    public abstract int getId();

    @PowerNukkitXOnly
    @Since("1.19.21-r2")
    public List getStructurePopulators() {
        return structurePopulators;
    }

    public DimensionData getDimensionData() {
        DimensionData dimensionData = DimensionEnum.getDataFromId(this.getDimension());
        if (dimensionData == null) {
            dimensionData = DimensionEnum.OVERWORLD.getDimensionData();
        }
        return dimensionData;
    }

    /**
     * 返回此生成器实例绑定的世界
     * 你不应该将此方法的返回值用于{@link cn.nukkit.level.generator.populator.type.Populator}上,而是使用{@code getChunkManager()}方法
     * 以更好地利用多线程
     *
     * @return {@link cn.nukkit.level.generator.populator.type.Populator}
     */
    @PowerNukkitXOnly
    @Since("1.19.21-r2")
    public Level getLevel() {
        return level;
    }

    @PowerNukkitXOnly
    @Since("1.19.21-r2")
    public NukkitRandom getRandom() {
        return random;
    }

    /**
     * 返回生成器的目标区块管理器
     * 实际为{@link PopChunkManager}
     *
     * @return {@link ChunkManager}
     */
    @PowerNukkitXDifference
    @Since("1.19.21-r2")
    public ChunkManager getChunkManager() {
        return chunkManager;
    }

    @PowerNukkitXOnly
    @Since("1.19.21-r2")
    public void setLevel(Level level) {
        this.level = level;
    }

    @PowerNukkitXOnly
    @Since("1.19.21-r2")
    public void setChunkManager(ChunkManager chunkManager) {
        this.chunkManager = chunkManager;
    }

    @PowerNukkitXOnly
    @Since("1.19.21-r2")
    public void setRandom(NukkitRandom random) {
        this.random = random;
    }

    @Deprecated
    public int getDimension() {
        return Level.DIMENSION_OVERWORLD;
    }

    private static final Map> nameList = new HashMap<>();

    private static final Map> typeList = new HashMap<>();

    public static boolean addGenerator(Class clazz, String name, int type) {
        name = name.toLowerCase();
        if (clazz != null && !Generator.nameList.containsKey(name)) {
            Generator.nameList.put(name, clazz);
            if (!Generator.typeList.containsKey(type)) {
                Generator.typeList.put(type, clazz);
            }
            return true;
        }
        return false;
    }

    /**
     * 注册未知类型的生成器(Terra)
     */
    @PowerNukkitXOnly
    @Since("1.19.50-r1")
    public static boolean addGenerator(Class clazz, String name) {
        name = name.toLowerCase();
        if (clazz != null && !Generator.nameList.containsKey(name)) {
            Generator.nameList.put(name, clazz);
            return true;
        }
        return false;
    }

    public static String[] getGeneratorList() {
        String[] keys = new String[Generator.nameList.size()];
        return Generator.nameList.keySet().toArray(keys);
    }

    public static Class getGenerator(String name) {
        name = name.toLowerCase();
        if (Generator.nameList.containsKey(name)) {
            return Generator.nameList.get(name);
        }
        return Normal.class;
    }

    public static Class getGenerator(int type) {
        if (Generator.typeList.containsKey(type)) {
            return Generator.typeList.get(type);
        }
        return Normal.class;
    }

    public static String getGeneratorName(Class c) {
        for (var entry : Generator.nameList.entrySet()) {
            if (entry.getValue().equals(c)) {
                return entry.getKey();
            }
        }
        return "unknown";
    }

    public static int getGeneratorType(Class c) {
        for (var entry : Generator.typeList.entrySet()) {
            if (entry.getValue().equals(c)) {
                return entry.getKey();
            }
        }
        return Generator.TYPE_INFINITE;
    }

    public abstract void init(ChunkManager chunkManager, NukkitRandom random);

    public abstract void generateChunk(int chunkX, int chunkZ);

    public abstract void populateChunk(int chunkX, int chunkZ);


    /**
     * 在指定区块上尝试生成结构
     *
     * @param chunkX
     * @param chunkZ
     */
    @PowerNukkitXOnly
    @Since("1.19.21-r2")
    public void populateStructure(int chunkX, int chunkZ) {
        //这里不能使用chunkManager而是使用level
        //因为在这个方法调用时,区块地形生成工作已完成,chunkManager(实际为PopChunkManager)内所有区块已清空
        var chunk = level.getChunk(chunkX, chunkZ);
        for (PopulatorStructure populator : structurePopulators) {
//            if (populator.isAsync()) Server.getInstance().getScheduler().scheduleAsyncTask(null, new ChunkPopulationTask(level, chunk, populator));
//            else populator.populate(level, chunkX, chunkZ, random, chunk);
            //todo: 临时解决Level::generators.get()的性能问题,有待进一步处理
            populator.populate(level, chunkX, chunkZ, random, chunk);
        }
    }

    public abstract Map getSettings();

    public abstract String getName();

    public abstract Vector3 getSpawn();

    /**
     * 若返回值为true,则将会在区块地形生成完毕后调用 {@link Generator} 的 populateStructure(int chunkX, int chunkZ) 方法
     *
     * @return 是否需要生成结构
     */
    @PowerNukkitXOnly
    @Since("1.19.21-r2")
    public boolean shouldGenerateStructures() {
        return false;
    }
}




© 2015 - 2024 Weber Informatics LLC | Privacy Policy