WorldGen

랙 없는 월드 생성을 위한 라이브러리

시작하기에 앞서, 이 라이브러리는 UHC_System 의 월드 생성 코드를 작성하면서 WorldCreator의 단점인 랙을 없애기
위해 만들어진 코드의 일부를 라이브러리로 공개하는 것임을 알려드립니다

WorldCreator의 랙

WorldCreator 및 기타 Bukkit API의 코드는 메인 Thread에서 실행 되어야하고, 이로 인해 사양이 좋지 않은 컴퓨터에서 서버를 돌릴때, 랙이 생기며, 서버가 꺼질 수 있습니다.
이의 단점을 보완하기 위해, level.dat의 생성 만으로, Bukkit API의 블로킹 코드 실행을 대체할 수 있는 프로그램을 제작하기 시작했습니다.

.dat 및 NBT

.dat 형식의 파일은 NBT에 대한 정보를 포함하며, UTF가 아닌 Stream 형태로 저장되어 있어 일반 텍스트 에디터로는 정보를 확인하기 어렵습니다. 따라서, 이를 parsing 해주는 기능이 필요한데,
이 라이브러리가 해주는 것이 바로 그것입니다.

WorldUtils

WorldUtilslevel.dat의 NBT를 수정하여 원하는 level.dat을 생성해주는 기능입니다. minecraft-version-data를 이용해 원하는 마인크래프트 버전의 월드를 생성해줍니다. 또한, 커스텀 seed를 이용해 원하는 월드를 생성해줍니다.

WorldUtils 예제

fun createWorld(worldName: String, seed: Long) {
    val compound = WorldUtils.generateLevelDat(
        Environment.OVERWORLD,
        worldName,
        Bukkit.getVersion(),
        Bukkit.getServer()::class.java.`package`.name,
        seed
    )

    NBTWriter.write("target.dat", compound, true)
}

위 코드는 오버월드이고 이름worldName, seedseed인 월드의 정보을 target.dat 파일에 저장합니다. 만약 파일이 존재하지 않을 경우, 자동으로 생성합니다.
또한, 이 라이브러리는 버킷을 의존성으로 갖지 않기 때문에, 직접 버킷 버전을 위와 같이 설정해 주어야합니다.

월드

마인크래프트의 월드 내부 폴더(region, entities, playerdata 등)의 위치는 환경(오버월드, 네더, 엔드) 마다 다릅니다. 오버월드의 경우,
월드 디렉토리의 루트에 위치됩니다. 따라서 구조는 다음과 비슷할 것입니다.

├── playerdata
│   └── xxxxx
├── region
│   └── r.0.-1.mca
│   └── xxxxx.mca
└── level.dat

네더의 경우, 내부 폴더들은 루트가 아닌 DIM-1 폴더에 저장되므로 구조는 다음과 비슷할 것입니다.

├── DIM-1
│   └── playerdata
│       └── xxxxx
│   └── region
│       └── r.0.-1.mca
│       └── xxxxx.mca
└── level.dat

그리고 엔드의 경우, 내부 폴더들은 루트가 아닌 DIM1 폴더에 저장되므로 구조는 다음과 비슷할 것입니다.

├── DIM1
│   └── playerdata
│       └── xxxxx
│   └── region
│       └── r.0.-1.mca
│       └── xxxxx.mca
└── level.dat

마무리

현재로서는 직접 서버를 처음 실행했을 때 생성되는 월드폴더를 백업해 둔후, 원할 때 클론 해서 level.dat 대체 후 로드해야합니다. 이를 자동화 해주는 코드는 나중에 구현하도록 하겠습니다

GitHub

View Github