the world spawn is now read from the level.dat file

master
Stefan Dollase 2016-01-15 22:36:48 +01:00
parent c6a0c2661e
commit 885ecbe1ac
9 changed files with 119 additions and 27 deletions

View File

@ -5,10 +5,12 @@ import org.jnbt.CompoundTag;
import amidst.documentation.Immutable;
import amidst.mojangapi.file.MojangApiParsingException;
import amidst.mojangapi.world.WorldType;
import amidst.mojangapi.world.coordinates.CoordinatesInWorld;
@Immutable
public class LevelDatNbt {
private final long seed;
private final CoordinatesInWorld worldSpawn;
private final WorldType worldType;
private final String generatorOptions;
private final boolean hasPlayer;
@ -17,6 +19,8 @@ public class LevelDatNbt {
try {
CompoundTag dataTag = readDataTag(root);
this.seed = readRandomSeed(dataTag);
this.worldSpawn = CoordinatesInWorld.from(readSpawnX(dataTag),
readSpawnZ(dataTag));
if (hasGeneratorName(dataTag)) {
this.worldType = WorldType.from(readGeneratorName(dataTag));
if (worldType == WorldType.CUSTOMIZED) {
@ -39,8 +43,18 @@ public class LevelDatNbt {
}
private long readRandomSeed(CompoundTag dataTag) {
return (Long) dataTag.getValue().get(NBTTagKeys.TAG_KEY_RANDOM_SEED)
.getValue();
return NBTUtils.getLongValue(dataTag.getValue().get(
NBTTagKeys.TAG_KEY_RANDOM_SEED));
}
private long readSpawnX(CompoundTag dataTag) {
return NBTUtils.getLongValue(dataTag.getValue().get(
NBTTagKeys.TAG_KEY_SPAWN_X));
}
private long readSpawnZ(CompoundTag dataTag) {
return NBTUtils.getLongValue(dataTag.getValue().get(
NBTTagKeys.TAG_KEY_SPAWN_Z));
}
private boolean hasGeneratorName(CompoundTag dataTag) {
@ -65,6 +79,10 @@ public class LevelDatNbt {
return seed;
}
public CoordinatesInWorld getWorldSpawn() {
return worldSpawn;
}
public WorldType getWorldType() {
return worldType;
}

View File

@ -8,6 +8,8 @@ public class NBTTagKeys {
public static final String TAG_KEY_DATA = "Data";
public static final String TAG_KEY_POS = "Pos";
public static final String TAG_KEY_PLAYER = "Player";
public static final String TAG_KEY_SPAWN_X = "SpawnX";
public static final String TAG_KEY_SPAWN_Z = "SpawnZ";
public static final String TAG_KEY_DIMENSION = "Dimension";
public static final String TAG_KEY_RANDOM_SEED = "RandomSeed";
public static final String TAG_KEY_GENERATOR_NAME = "generatorName";

View File

@ -10,6 +10,7 @@ import java.io.IOException;
import org.jnbt.CompoundTag;
import org.jnbt.NBTInputStream;
import org.jnbt.NBTOutputStream;
import org.jnbt.Tag;
import amidst.documentation.Immutable;
@ -41,4 +42,15 @@ public enum NBTUtils {
return new NBTOutputStream(new BufferedOutputStream(
new FileOutputStream(file)));
}
public static long getLongValue(Tag tag) {
Object value = tag.getValue();
if (value instanceof Number) {
return ((Number) value).longValue();
} else {
throw new IllegalArgumentException(
"cannot read long value from the class '"
+ tag.getClass().getName() + "'");
}
}
}

View File

@ -26,7 +26,10 @@ import amidst.mojangapi.world.icon.type.TempleWorldIconTypeProvider;
import amidst.mojangapi.world.oracle.BiomeDataOracle;
import amidst.mojangapi.world.oracle.EndIsland;
import amidst.mojangapi.world.oracle.EndIslandOracle;
import amidst.mojangapi.world.oracle.HeuristicWorldSpawnOracle;
import amidst.mojangapi.world.oracle.ImmutableWorldSpawnOracle;
import amidst.mojangapi.world.oracle.SlimeChunkOracle;
import amidst.mojangapi.world.oracle.WorldSpawnOracle;
import amidst.mojangapi.world.player.MovablePlayerList;
import amidst.mojangapi.world.player.PlayerInformationCache;
import amidst.mojangapi.world.player.WorldPlayerType;
@ -47,10 +50,21 @@ public class WorldBuilder {
public World fromSeed(MinecraftInterface minecraftInterface,
WorldSeed worldSeed, WorldType worldType)
throws MinecraftInterfaceException {
return create(minecraftInterface, worldSeed, worldType, "",
BiomeDataOracle biomeDataOracle = new BiomeDataOracle(
minecraftInterface);
VersionFeatures versionFeatures = DefaultVersionFeatures
.create(minecraftInterface.getRecognisedVersion());
return create(
minecraftInterface,
worldSeed,
worldType,
"",
MovablePlayerList.dummy(),
DefaultVersionFeatures.create(minecraftInterface
.getRecognisedVersion()));
versionFeatures,
biomeDataOracle,
new HeuristicWorldSpawnOracle(worldSeed.getLong(),
biomeDataOracle, versionFeatures
.getValidBiomesForStructure_Spawn()));
}
public World fromFile(MinecraftInterface minecraftInterface,
@ -66,18 +80,21 @@ public class WorldBuilder {
return create(minecraftInterface,
WorldSeed.fromFile(levelDat.getSeed()),
levelDat.getWorldType(), levelDat.getGeneratorOptions(),
movablePlayerList, versionFeatures);
movablePlayerList, versionFeatures, new BiomeDataOracle(
minecraftInterface), new ImmutableWorldSpawnOracle(
levelDat.getWorldSpawn()));
}
private World create(MinecraftInterface minecraftInterface,
WorldSeed worldSeed, WorldType worldType, String generatorOptions,
MovablePlayerList movablePlayerList, VersionFeatures versionFeatures)
MovablePlayerList movablePlayerList,
VersionFeatures versionFeatures, BiomeDataOracle biomeDataOracle,
WorldSpawnOracle worldSpawnOracle)
throws MinecraftInterfaceException {
seedHistoryLogger.log(worldSeed);
long seed = worldSeed.getLong();
// @formatter:off
minecraftInterface.createWorld(seed, worldType, generatorOptions);
BiomeDataOracle biomeDataOracle = new BiomeDataOracle(minecraftInterface);
return new World(
worldSeed,
worldType,
@ -87,7 +104,7 @@ public class WorldBuilder {
biomeDataOracle,
EndIslandOracle.from( seed),
new SlimeChunkOracle( seed),
new SpawnProducer( seed, biomeDataOracle, versionFeatures.getValidBiomesForStructure_Spawn()),
new SpawnProducer(worldSpawnOracle),
new StrongholdProducer(seed, biomeDataOracle, versionFeatures.getValidBiomesAtMiddleOfChunk_Stronghold(), versionFeatures.getNumberOfStrongholds()),
new PlayerProducer(movablePlayerList),
new StructureProducer<Void>(

View File

@ -2,28 +2,21 @@ package amidst.mojangapi.world.icon.producer;
import java.util.Arrays;
import java.util.List;
import java.util.Random;
import amidst.documentation.ThreadSafe;
import amidst.logging.Log;
import amidst.mojangapi.world.Dimension;
import amidst.mojangapi.world.biome.Biome;
import amidst.mojangapi.world.coordinates.CoordinatesInWorld;
import amidst.mojangapi.world.icon.WorldIcon;
import amidst.mojangapi.world.icon.type.DefaultWorldIconTypes;
import amidst.mojangapi.world.oracle.BiomeDataOracle;
import amidst.mojangapi.world.oracle.WorldSpawnOracle;
@ThreadSafe
public class SpawnProducer extends CachedWorldIconProducer {
private final long seed;
private final BiomeDataOracle biomeDataOracle;
private final List<Biome> validBiomes;
private final WorldSpawnOracle oracle;
public SpawnProducer(long seed, BiomeDataOracle biomeDataOracle,
List<Biome> validBiomes) {
this.seed = seed;
this.biomeDataOracle = biomeDataOracle;
this.validBiomes = validBiomes;
public SpawnProducer(WorldSpawnOracle oracle) {
this.oracle = oracle;
}
@Override
@ -32,7 +25,7 @@ public class SpawnProducer extends CachedWorldIconProducer {
}
private WorldIcon createSpawnWorldIcon() {
CoordinatesInWorld spawnLocation = getSpawnCenterInWorldCoordinates();
CoordinatesInWorld spawnLocation = oracle.get();
if (spawnLocation != null) {
return createWorldIcon(spawnLocation);
} else {
@ -49,9 +42,4 @@ public class SpawnProducer extends CachedWorldIconProducer {
DefaultWorldIconTypes.SPAWN.getImage(), Dimension.OVERWORLD,
false);
}
private CoordinatesInWorld getSpawnCenterInWorldCoordinates() {
return biomeDataOracle.findValidLocation(0, 0, 256, validBiomes,
new Random(seed));
}
}

View File

@ -19,7 +19,7 @@ public enum DefaultWorldIconTypes {
JUNGLE("Jungle Temple"),
DESERT("Desert Temple"),
VILLAGE("Village"),
SPAWN("Default World Spawn"),
SPAWN("World Spawn"),
WITCH("Witch Hut"),
OCEAN_MONUMENT("Ocean Monument"),
IGLOO("Igloo"),

View File

@ -0,0 +1,28 @@
package amidst.mojangapi.world.oracle;
import java.util.List;
import java.util.Random;
import amidst.documentation.ThreadSafe;
import amidst.mojangapi.world.biome.Biome;
import amidst.mojangapi.world.coordinates.CoordinatesInWorld;
@ThreadSafe
public class HeuristicWorldSpawnOracle implements WorldSpawnOracle {
private final long seed;
private final BiomeDataOracle biomeDataOracle;
private final List<Biome> validBiomes;
public HeuristicWorldSpawnOracle(long seed,
BiomeDataOracle biomeDataOracle, List<Biome> validBiomes) {
this.seed = seed;
this.biomeDataOracle = biomeDataOracle;
this.validBiomes = validBiomes;
}
@Override
public CoordinatesInWorld get() {
return biomeDataOracle.findValidLocation(0, 0, 256, validBiomes,
new Random(seed));
}
}

View File

@ -0,0 +1,18 @@
package amidst.mojangapi.world.oracle;
import amidst.documentation.Immutable;
import amidst.mojangapi.world.coordinates.CoordinatesInWorld;
@Immutable
public class ImmutableWorldSpawnOracle implements WorldSpawnOracle {
private final CoordinatesInWorld worldSpawn;
public ImmutableWorldSpawnOracle(CoordinatesInWorld worldSpawn) {
this.worldSpawn = worldSpawn;
}
@Override
public CoordinatesInWorld get() {
return worldSpawn;
}
}

View File

@ -0,0 +1,9 @@
package amidst.mojangapi.world.oracle;
import amidst.documentation.ThreadSafe;
import amidst.mojangapi.world.coordinates.CoordinatesInWorld;
@ThreadSafe
public interface WorldSpawnOracle {
CoordinatesInWorld get();
}