581 lines
16 KiB
Java
581 lines
16 KiB
Java
package net.minecraft.world.level.storage;
|
|
|
|
import com.google.common.collect.ImmutableSet;
|
|
import com.google.common.collect.Sets;
|
|
import com.mojang.logging.LogUtils;
|
|
import com.mojang.serialization.Dynamic;
|
|
import com.mojang.serialization.DynamicOps;
|
|
import com.mojang.serialization.Lifecycle;
|
|
import java.util.HashSet;
|
|
import java.util.Set;
|
|
import java.util.UUID;
|
|
import java.util.stream.Collectors;
|
|
import net.minecraft.CrashReportCategory;
|
|
import net.minecraft.SharedConstants;
|
|
import net.minecraft.Util;
|
|
import net.minecraft.core.BlockPos;
|
|
import net.minecraft.core.RegistryAccess;
|
|
import net.minecraft.core.UUIDUtil;
|
|
import net.minecraft.nbt.CompoundTag;
|
|
import net.minecraft.nbt.ListTag;
|
|
import net.minecraft.nbt.NbtOps;
|
|
import net.minecraft.nbt.NbtUtils;
|
|
import net.minecraft.nbt.StringTag;
|
|
import net.minecraft.nbt.Tag;
|
|
import net.minecraft.server.MinecraftServer;
|
|
import net.minecraft.world.Difficulty;
|
|
import net.minecraft.world.level.GameRules;
|
|
import net.minecraft.world.level.GameType;
|
|
import net.minecraft.world.level.LevelHeightAccessor;
|
|
import net.minecraft.world.level.LevelSettings;
|
|
import net.minecraft.world.level.WorldDataConfiguration;
|
|
import net.minecraft.world.level.border.WorldBorder;
|
|
import net.minecraft.world.level.dimension.end.EndDragonFight;
|
|
import net.minecraft.world.level.levelgen.WorldGenSettings;
|
|
import net.minecraft.world.level.levelgen.WorldOptions;
|
|
import net.minecraft.world.level.timers.TimerCallbacks;
|
|
import net.minecraft.world.level.timers.TimerQueue;
|
|
import org.jetbrains.annotations.Nullable;
|
|
import org.slf4j.Logger;
|
|
|
|
public class PrimaryLevelData implements ServerLevelData, WorldData {
|
|
private static final Logger LOGGER = LogUtils.getLogger();
|
|
public static final String LEVEL_NAME = "LevelName";
|
|
protected static final String PLAYER = "Player";
|
|
protected static final String WORLD_GEN_SETTINGS = "WorldGenSettings";
|
|
private LevelSettings settings;
|
|
private final WorldOptions worldOptions;
|
|
private final PrimaryLevelData.SpecialWorldProperty specialWorldProperty;
|
|
private final Lifecycle worldGenSettingsLifecycle;
|
|
private BlockPos spawnPos;
|
|
private float spawnAngle;
|
|
private long gameTime;
|
|
private long dayTime;
|
|
@Nullable
|
|
private final CompoundTag loadedPlayerTag;
|
|
private final int version;
|
|
private int clearWeatherTime;
|
|
private boolean raining;
|
|
private int rainTime;
|
|
private boolean thundering;
|
|
private int thunderTime;
|
|
private boolean initialized;
|
|
private boolean difficultyLocked;
|
|
private WorldBorder.Settings worldBorder;
|
|
private EndDragonFight.Data endDragonFightData;
|
|
@Nullable
|
|
private CompoundTag customBossEvents;
|
|
private int wanderingTraderSpawnDelay;
|
|
private int wanderingTraderSpawnChance;
|
|
@Nullable
|
|
private UUID wanderingTraderId;
|
|
private final Set<String> knownServerBrands;
|
|
private boolean wasModded;
|
|
private final Set<String> removedFeatureFlags;
|
|
private final TimerQueue<MinecraftServer> scheduledEvents;
|
|
|
|
private PrimaryLevelData(
|
|
@Nullable CompoundTag loadedPlayerTag,
|
|
boolean wasModded,
|
|
BlockPos spawnPos,
|
|
float spawnAngle,
|
|
long gameTime,
|
|
long dayTime,
|
|
int version,
|
|
int clearWeatherTime,
|
|
int rainTime,
|
|
boolean raining,
|
|
int thunderTime,
|
|
boolean thundering,
|
|
boolean initialized,
|
|
boolean difficultyLocked,
|
|
WorldBorder.Settings worldBorder,
|
|
int wanderingTraderSpawnDelay,
|
|
int wanderingTraderSpawnChance,
|
|
@Nullable UUID wanderingTraderId,
|
|
Set<String> knownServerBrands,
|
|
Set<String> removedFeatureFlags,
|
|
TimerQueue<MinecraftServer> scheduledEvents,
|
|
@Nullable CompoundTag customBossEvents,
|
|
EndDragonFight.Data endDragonFightData,
|
|
LevelSettings settings,
|
|
WorldOptions worldOptions,
|
|
PrimaryLevelData.SpecialWorldProperty specialWorldProperty,
|
|
Lifecycle worldGenSettingsLifecycle
|
|
) {
|
|
this.wasModded = wasModded;
|
|
this.spawnPos = spawnPos;
|
|
this.spawnAngle = spawnAngle;
|
|
this.gameTime = gameTime;
|
|
this.dayTime = dayTime;
|
|
this.version = version;
|
|
this.clearWeatherTime = clearWeatherTime;
|
|
this.rainTime = rainTime;
|
|
this.raining = raining;
|
|
this.thunderTime = thunderTime;
|
|
this.thundering = thundering;
|
|
this.initialized = initialized;
|
|
this.difficultyLocked = difficultyLocked;
|
|
this.worldBorder = worldBorder;
|
|
this.wanderingTraderSpawnDelay = wanderingTraderSpawnDelay;
|
|
this.wanderingTraderSpawnChance = wanderingTraderSpawnChance;
|
|
this.wanderingTraderId = wanderingTraderId;
|
|
this.knownServerBrands = knownServerBrands;
|
|
this.removedFeatureFlags = removedFeatureFlags;
|
|
this.loadedPlayerTag = loadedPlayerTag;
|
|
this.scheduledEvents = scheduledEvents;
|
|
this.customBossEvents = customBossEvents;
|
|
this.endDragonFightData = endDragonFightData;
|
|
this.settings = settings;
|
|
this.worldOptions = worldOptions;
|
|
this.specialWorldProperty = specialWorldProperty;
|
|
this.worldGenSettingsLifecycle = worldGenSettingsLifecycle;
|
|
}
|
|
|
|
public PrimaryLevelData(
|
|
LevelSettings settings, WorldOptions worldOptions, PrimaryLevelData.SpecialWorldProperty specialWorldProperty, Lifecycle worldGenSettingsLifecycle
|
|
) {
|
|
this(
|
|
null,
|
|
false,
|
|
BlockPos.ZERO,
|
|
0.0F,
|
|
0L,
|
|
0L,
|
|
19133,
|
|
0,
|
|
0,
|
|
false,
|
|
0,
|
|
false,
|
|
false,
|
|
false,
|
|
WorldBorder.DEFAULT_SETTINGS,
|
|
0,
|
|
0,
|
|
null,
|
|
Sets.<String>newLinkedHashSet(),
|
|
new HashSet(),
|
|
new TimerQueue<>(TimerCallbacks.SERVER_CALLBACKS),
|
|
null,
|
|
EndDragonFight.Data.DEFAULT,
|
|
settings.copy(),
|
|
worldOptions,
|
|
specialWorldProperty,
|
|
worldGenSettingsLifecycle
|
|
);
|
|
}
|
|
|
|
public static <T> PrimaryLevelData parse(
|
|
Dynamic<T> tag,
|
|
LevelSettings levelSettings,
|
|
PrimaryLevelData.SpecialWorldProperty specialWorldProperty,
|
|
WorldOptions worldOptions,
|
|
Lifecycle worldGenSettingsLifecycle
|
|
) {
|
|
long l = tag.get("Time").asLong(0L);
|
|
return new PrimaryLevelData(
|
|
(CompoundTag)tag.get("Player").flatMap(CompoundTag.CODEC::parse).result().orElse(null),
|
|
tag.get("WasModded").asBoolean(false),
|
|
new BlockPos(tag.get("SpawnX").asInt(0), tag.get("SpawnY").asInt(0), tag.get("SpawnZ").asInt(0)),
|
|
tag.get("SpawnAngle").asFloat(0.0F),
|
|
l,
|
|
tag.get("DayTime").asLong(l),
|
|
LevelVersion.parse(tag).levelDataVersion(),
|
|
tag.get("clearWeatherTime").asInt(0),
|
|
tag.get("rainTime").asInt(0),
|
|
tag.get("raining").asBoolean(false),
|
|
tag.get("thunderTime").asInt(0),
|
|
tag.get("thundering").asBoolean(false),
|
|
tag.get("initialized").asBoolean(true),
|
|
tag.get("DifficultyLocked").asBoolean(false),
|
|
WorldBorder.Settings.read(tag, WorldBorder.DEFAULT_SETTINGS),
|
|
tag.get("WanderingTraderSpawnDelay").asInt(0),
|
|
tag.get("WanderingTraderSpawnChance").asInt(0),
|
|
(UUID)tag.get("WanderingTraderId").read(UUIDUtil.CODEC).result().orElse(null),
|
|
(Set<String>)tag.get("ServerBrands")
|
|
.asStream()
|
|
.flatMap(dynamic -> dynamic.asString().result().stream())
|
|
.collect(Collectors.toCollection(Sets::newLinkedHashSet)),
|
|
(Set<String>)tag.get("removed_features").asStream().flatMap(dynamic -> dynamic.asString().result().stream()).collect(Collectors.toSet()),
|
|
new TimerQueue<>(TimerCallbacks.SERVER_CALLBACKS, tag.get("ScheduledEvents").asStream()),
|
|
(CompoundTag)tag.get("CustomBossEvents").orElseEmptyMap().getValue(),
|
|
(EndDragonFight.Data)tag.get("DragonFight").read(EndDragonFight.Data.CODEC).resultOrPartial(LOGGER::error).orElse(EndDragonFight.Data.DEFAULT),
|
|
levelSettings,
|
|
worldOptions,
|
|
specialWorldProperty,
|
|
worldGenSettingsLifecycle
|
|
);
|
|
}
|
|
|
|
@Override
|
|
public CompoundTag createTag(RegistryAccess registries, @Nullable CompoundTag hostPlayerNBT) {
|
|
if (hostPlayerNBT == null) {
|
|
hostPlayerNBT = this.loadedPlayerTag;
|
|
}
|
|
|
|
CompoundTag compoundTag = new CompoundTag();
|
|
this.setTagData(registries, compoundTag, hostPlayerNBT);
|
|
return compoundTag;
|
|
}
|
|
|
|
private void setTagData(RegistryAccess registry, CompoundTag nbt, @Nullable CompoundTag playerNBT) {
|
|
nbt.put("ServerBrands", stringCollectionToTag(this.knownServerBrands));
|
|
nbt.putBoolean("WasModded", this.wasModded);
|
|
if (!this.removedFeatureFlags.isEmpty()) {
|
|
nbt.put("removed_features", stringCollectionToTag(this.removedFeatureFlags));
|
|
}
|
|
|
|
CompoundTag compoundTag = new CompoundTag();
|
|
compoundTag.putString("Name", SharedConstants.getCurrentVersion().getName());
|
|
compoundTag.putInt("Id", SharedConstants.getCurrentVersion().getDataVersion().getVersion());
|
|
compoundTag.putBoolean("Snapshot", !SharedConstants.getCurrentVersion().isStable());
|
|
compoundTag.putString("Series", SharedConstants.getCurrentVersion().getDataVersion().getSeries());
|
|
nbt.put("Version", compoundTag);
|
|
NbtUtils.addCurrentDataVersion(nbt);
|
|
DynamicOps<Tag> dynamicOps = registry.createSerializationContext(NbtOps.INSTANCE);
|
|
WorldGenSettings.encode(dynamicOps, this.worldOptions, registry)
|
|
.resultOrPartial(Util.prefix("WorldGenSettings: ", LOGGER::error))
|
|
.ifPresent(tag -> nbt.put("WorldGenSettings", tag));
|
|
nbt.putInt("GameType", this.settings.gameType().getId());
|
|
nbt.putInt("SpawnX", this.spawnPos.getX());
|
|
nbt.putInt("SpawnY", this.spawnPos.getY());
|
|
nbt.putInt("SpawnZ", this.spawnPos.getZ());
|
|
nbt.putFloat("SpawnAngle", this.spawnAngle);
|
|
nbt.putLong("Time", this.gameTime);
|
|
nbt.putLong("DayTime", this.dayTime);
|
|
nbt.putLong("LastPlayed", Util.getEpochMillis());
|
|
nbt.putString("LevelName", this.settings.levelName());
|
|
nbt.putInt("version", 19133);
|
|
nbt.putInt("clearWeatherTime", this.clearWeatherTime);
|
|
nbt.putInt("rainTime", this.rainTime);
|
|
nbt.putBoolean("raining", this.raining);
|
|
nbt.putInt("thunderTime", this.thunderTime);
|
|
nbt.putBoolean("thundering", this.thundering);
|
|
nbt.putBoolean("hardcore", this.settings.hardcore());
|
|
nbt.putBoolean("allowCommands", this.settings.allowCommands());
|
|
nbt.putBoolean("initialized", this.initialized);
|
|
this.worldBorder.write(nbt);
|
|
nbt.putByte("Difficulty", (byte)this.settings.difficulty().getId());
|
|
nbt.putBoolean("DifficultyLocked", this.difficultyLocked);
|
|
nbt.put("GameRules", this.settings.gameRules().createTag());
|
|
nbt.store("DragonFight", EndDragonFight.Data.CODEC, this.endDragonFightData);
|
|
if (playerNBT != null) {
|
|
nbt.put("Player", playerNBT);
|
|
}
|
|
|
|
nbt.store(WorldDataConfiguration.MAP_CODEC, this.settings.getDataConfiguration());
|
|
if (this.customBossEvents != null) {
|
|
nbt.put("CustomBossEvents", this.customBossEvents);
|
|
}
|
|
|
|
nbt.put("ScheduledEvents", this.scheduledEvents.store());
|
|
nbt.putInt("WanderingTraderSpawnDelay", this.wanderingTraderSpawnDelay);
|
|
nbt.putInt("WanderingTraderSpawnChance", this.wanderingTraderSpawnChance);
|
|
nbt.storeNullable("WanderingTraderId", UUIDUtil.CODEC, this.wanderingTraderId);
|
|
}
|
|
|
|
private static ListTag stringCollectionToTag(Set<String> stringCollection) {
|
|
ListTag listTag = new ListTag();
|
|
stringCollection.stream().map(StringTag::valueOf).forEach(listTag::add);
|
|
return listTag;
|
|
}
|
|
|
|
@Override
|
|
public BlockPos getSpawnPos() {
|
|
return this.spawnPos;
|
|
}
|
|
|
|
@Override
|
|
public float getSpawnAngle() {
|
|
return this.spawnAngle;
|
|
}
|
|
|
|
@Override
|
|
public long getGameTime() {
|
|
return this.gameTime;
|
|
}
|
|
|
|
@Override
|
|
public long getDayTime() {
|
|
return this.dayTime;
|
|
}
|
|
|
|
@Nullable
|
|
@Override
|
|
public CompoundTag getLoadedPlayerTag() {
|
|
return this.loadedPlayerTag;
|
|
}
|
|
|
|
@Override
|
|
public void setGameTime(long time) {
|
|
this.gameTime = time;
|
|
}
|
|
|
|
@Override
|
|
public void setDayTime(long time) {
|
|
this.dayTime = time;
|
|
}
|
|
|
|
@Override
|
|
public void setSpawn(BlockPos spawnPoint, float spawnAngle) {
|
|
this.spawnPos = spawnPoint.immutable();
|
|
this.spawnAngle = spawnAngle;
|
|
}
|
|
|
|
@Override
|
|
public String getLevelName() {
|
|
return this.settings.levelName();
|
|
}
|
|
|
|
@Override
|
|
public int getVersion() {
|
|
return this.version;
|
|
}
|
|
|
|
@Override
|
|
public int getClearWeatherTime() {
|
|
return this.clearWeatherTime;
|
|
}
|
|
|
|
@Override
|
|
public void setClearWeatherTime(int time) {
|
|
this.clearWeatherTime = time;
|
|
}
|
|
|
|
@Override
|
|
public boolean isThundering() {
|
|
return this.thundering;
|
|
}
|
|
|
|
@Override
|
|
public void setThundering(boolean thundering) {
|
|
this.thundering = thundering;
|
|
}
|
|
|
|
@Override
|
|
public int getThunderTime() {
|
|
return this.thunderTime;
|
|
}
|
|
|
|
@Override
|
|
public void setThunderTime(int time) {
|
|
this.thunderTime = time;
|
|
}
|
|
|
|
@Override
|
|
public boolean isRaining() {
|
|
return this.raining;
|
|
}
|
|
|
|
@Override
|
|
public void setRaining(boolean raining) {
|
|
this.raining = raining;
|
|
}
|
|
|
|
@Override
|
|
public int getRainTime() {
|
|
return this.rainTime;
|
|
}
|
|
|
|
@Override
|
|
public void setRainTime(int time) {
|
|
this.rainTime = time;
|
|
}
|
|
|
|
@Override
|
|
public GameType getGameType() {
|
|
return this.settings.gameType();
|
|
}
|
|
|
|
@Override
|
|
public void setGameType(GameType type) {
|
|
this.settings = this.settings.withGameType(type);
|
|
}
|
|
|
|
@Override
|
|
public boolean isHardcore() {
|
|
return this.settings.hardcore();
|
|
}
|
|
|
|
@Override
|
|
public boolean isAllowCommands() {
|
|
return this.settings.allowCommands();
|
|
}
|
|
|
|
@Override
|
|
public boolean isInitialized() {
|
|
return this.initialized;
|
|
}
|
|
|
|
@Override
|
|
public void setInitialized(boolean initialized) {
|
|
this.initialized = initialized;
|
|
}
|
|
|
|
@Override
|
|
public GameRules getGameRules() {
|
|
return this.settings.gameRules();
|
|
}
|
|
|
|
@Override
|
|
public WorldBorder.Settings getWorldBorder() {
|
|
return this.worldBorder;
|
|
}
|
|
|
|
@Override
|
|
public void setWorldBorder(WorldBorder.Settings serializer) {
|
|
this.worldBorder = serializer;
|
|
}
|
|
|
|
@Override
|
|
public Difficulty getDifficulty() {
|
|
return this.settings.difficulty();
|
|
}
|
|
|
|
@Override
|
|
public void setDifficulty(Difficulty difficulty) {
|
|
this.settings = this.settings.withDifficulty(difficulty);
|
|
}
|
|
|
|
@Override
|
|
public boolean isDifficultyLocked() {
|
|
return this.difficultyLocked;
|
|
}
|
|
|
|
@Override
|
|
public void setDifficultyLocked(boolean locked) {
|
|
this.difficultyLocked = locked;
|
|
}
|
|
|
|
@Override
|
|
public TimerQueue<MinecraftServer> getScheduledEvents() {
|
|
return this.scheduledEvents;
|
|
}
|
|
|
|
@Override
|
|
public void fillCrashReportCategory(CrashReportCategory crashReportCategory, LevelHeightAccessor level) {
|
|
ServerLevelData.super.fillCrashReportCategory(crashReportCategory, level);
|
|
WorldData.super.fillCrashReportCategory(crashReportCategory);
|
|
}
|
|
|
|
@Override
|
|
public WorldOptions worldGenOptions() {
|
|
return this.worldOptions;
|
|
}
|
|
|
|
@Override
|
|
public boolean isFlatWorld() {
|
|
return this.specialWorldProperty == PrimaryLevelData.SpecialWorldProperty.FLAT;
|
|
}
|
|
|
|
@Override
|
|
public boolean isDebugWorld() {
|
|
return this.specialWorldProperty == PrimaryLevelData.SpecialWorldProperty.DEBUG;
|
|
}
|
|
|
|
@Override
|
|
public Lifecycle worldGenSettingsLifecycle() {
|
|
return this.worldGenSettingsLifecycle;
|
|
}
|
|
|
|
@Override
|
|
public EndDragonFight.Data endDragonFightData() {
|
|
return this.endDragonFightData;
|
|
}
|
|
|
|
@Override
|
|
public void setEndDragonFightData(EndDragonFight.Data endDragonFightData) {
|
|
this.endDragonFightData = endDragonFightData;
|
|
}
|
|
|
|
@Override
|
|
public WorldDataConfiguration getDataConfiguration() {
|
|
return this.settings.getDataConfiguration();
|
|
}
|
|
|
|
@Override
|
|
public void setDataConfiguration(WorldDataConfiguration dataConfiguration) {
|
|
this.settings = this.settings.withDataConfiguration(dataConfiguration);
|
|
}
|
|
|
|
@Nullable
|
|
@Override
|
|
public CompoundTag getCustomBossEvents() {
|
|
return this.customBossEvents;
|
|
}
|
|
|
|
@Override
|
|
public void setCustomBossEvents(@Nullable CompoundTag nbt) {
|
|
this.customBossEvents = nbt;
|
|
}
|
|
|
|
@Override
|
|
public int getWanderingTraderSpawnDelay() {
|
|
return this.wanderingTraderSpawnDelay;
|
|
}
|
|
|
|
@Override
|
|
public void setWanderingTraderSpawnDelay(int delay) {
|
|
this.wanderingTraderSpawnDelay = delay;
|
|
}
|
|
|
|
@Override
|
|
public int getWanderingTraderSpawnChance() {
|
|
return this.wanderingTraderSpawnChance;
|
|
}
|
|
|
|
@Override
|
|
public void setWanderingTraderSpawnChance(int chance) {
|
|
this.wanderingTraderSpawnChance = chance;
|
|
}
|
|
|
|
@Nullable
|
|
@Override
|
|
public UUID getWanderingTraderId() {
|
|
return this.wanderingTraderId;
|
|
}
|
|
|
|
@Override
|
|
public void setWanderingTraderId(UUID id) {
|
|
this.wanderingTraderId = id;
|
|
}
|
|
|
|
@Override
|
|
public void setModdedInfo(String name, boolean isModded) {
|
|
this.knownServerBrands.add(name);
|
|
this.wasModded |= isModded;
|
|
}
|
|
|
|
@Override
|
|
public boolean wasModded() {
|
|
return this.wasModded;
|
|
}
|
|
|
|
@Override
|
|
public Set<String> getKnownServerBrands() {
|
|
return ImmutableSet.copyOf(this.knownServerBrands);
|
|
}
|
|
|
|
@Override
|
|
public Set<String> getRemovedFeatureFlags() {
|
|
return Set.copyOf(this.removedFeatureFlags);
|
|
}
|
|
|
|
@Override
|
|
public ServerLevelData overworldData() {
|
|
return this;
|
|
}
|
|
|
|
@Override
|
|
public LevelSettings getLevelSettings() {
|
|
return this.settings.copy();
|
|
}
|
|
|
|
@Deprecated
|
|
public static enum SpecialWorldProperty {
|
|
NONE,
|
|
FLAT,
|
|
DEBUG;
|
|
}
|
|
}
|