public WorldFinalValues readWorldData() throws IOException {
    Map<String, Tag> level = new HashMap<String, Tag>();

    File levelFile = new File(dir, "level.dat");
    if (!levelFile.exists()) {
      try {
        levelFile.createNewFile();
      } catch (IOException e) {
        handleWorldException("level.dat", e);
      }
    } else {
      try {
        NBTInputStream in = new NBTInputStream(new FileInputStream(levelFile));
        CompoundTag levelTag = (CompoundTag) in.readTag();
        in.close();
        if (levelTag != null) level.putAll(levelTag.getValue());
      } catch (EOFException e) {
      } catch (IOException e) {
        handleWorldException("level.dat", e);
      }
    }
    UUID uid = null;
    File uuidFile = new File(dir, "uid.dat");
    if (!uuidFile.exists()) {
      try {
        uuidFile.createNewFile();
      } catch (IOException e) {
        handleWorldException("uid.dat", e);
      }
    } else {
      DataInputStream str = null;
      try {
        str = new DataInputStream(new FileInputStream(uuidFile));
        uid = new UUID(str.readLong(), str.readLong());
      } catch (EOFException e) {
      } finally {
        if (str != null) {
          str.close();
        }
      }
    }
    long seed = 0L;
    if (level.containsKey("thundering")) {
      ByteTag thunderTag = (ByteTag) level.remove("thundering");
      world.setThundering(thunderTag.getValue() == 1);
    }
    if (level.containsKey("raining")) {
      ByteTag rainTag = (ByteTag) level.remove("raining");
      world.setStorm(rainTag.getValue() == 1);
    }
    if (level.containsKey("thunderTime")) {
      IntTag thunderTimeTag = (IntTag) level.remove("thunderTime");
      world.setThunderDuration(thunderTimeTag.getValue());
    }
    if (level.containsKey("rainTime")) {
      IntTag rainTimeTag = (IntTag) level.remove("rainTime");
      world.setWeatherDuration(rainTimeTag.getValue());
    }
    if (level.containsKey("RandomSeed")) {
      LongTag seedTag = (LongTag) level.remove("RandomSeed");
      seed = seedTag.getValue();
    }
    if (level.containsKey("Time")) {
      LongTag timeTag = (LongTag) level.remove("Time");
      world.setTime(timeTag.getValue());
    }
    if (level.containsKey("SpawnX") && level.containsKey("SpawnY") && level.containsKey("SpawnZ")) {
      IntTag spawnXTag = (IntTag) level.remove("SpawnX");
      IntTag spawnYTag = (IntTag) level.remove("SpawnY");
      IntTag spawnZTag = (IntTag) level.remove("SpawnZ");
      world.setSpawnLocation(spawnXTag.getValue(), spawnYTag.getValue(), spawnZTag.getValue());
    }
    unknownTags.putAll(level);
    if (uid == null) uid = UUID.randomUUID();
    return new WorldFinalValues(seed, uid);
  }