net.minecraft.world.level.storage
This commit is contained in:
@@ -0,0 +1,20 @@
|
||||
--- a/net/minecraft/world/level/storage/DimensionDataStorage.java
|
||||
+++ b/net/minecraft/world/level/storage/DimensionDataStorage.java
|
||||
@@ -139,7 +_,7 @@
|
||||
} else {
|
||||
int i = Util.maxAllowedExecutorThreads();
|
||||
int size = map.size();
|
||||
- if (size > i) {
|
||||
+ if (false && size > i) { // Paper - Separate dimension data IO pool; just throw them into the fixed pool queue
|
||||
this.pendingWriteFuture = this.pendingWriteFuture.thenCompose(object -> {
|
||||
List<CompletableFuture<?>> list = new ArrayList<>(i);
|
||||
int i1 = Mth.positiveCeilDiv(size, i);
|
||||
@@ -160,7 +_,7 @@
|
||||
object -> CompletableFuture.allOf(
|
||||
map.entrySet()
|
||||
.stream()
|
||||
- .map(entry -> CompletableFuture.runAsync(() -> tryWrite(entry.getKey(), entry.getValue()), Util.ioPool()))
|
||||
+ .map(entry -> CompletableFuture.runAsync(() -> tryWrite(entry.getKey(), entry.getValue()), Util.DIMENSION_DATA_IO_POOL)) // Paper - Separate dimension data IO pool
|
||||
.toArray(CompletableFuture[]::new)
|
||||
)
|
||||
);
|
||||
@@ -0,0 +1,86 @@
|
||||
--- a/net/minecraft/world/level/storage/LevelStorageSource.java
|
||||
+++ b/net/minecraft/world/level/storage/LevelStorageSource.java
|
||||
@@ -66,7 +_,6 @@
|
||||
import net.minecraft.world.level.Level;
|
||||
import net.minecraft.world.level.LevelSettings;
|
||||
import net.minecraft.world.level.WorldDataConfiguration;
|
||||
-import net.minecraft.world.level.dimension.DimensionType;
|
||||
import net.minecraft.world.level.dimension.LevelStem;
|
||||
import net.minecraft.world.level.levelgen.WorldDimensions;
|
||||
import net.minecraft.world.level.levelgen.WorldGenSettings;
|
||||
@@ -145,6 +_,7 @@
|
||||
PrimaryLevelData primaryLevelData = PrimaryLevelData.parse(
|
||||
dynamic, levelSettings, complete.specialWorldProperty(), worldGenSettings.options(), lifecycle
|
||||
);
|
||||
+ primaryLevelData.pdc = dynamic.castTyped(NbtOps.INSTANCE).getElement("BukkitValues", null); // CraftBukkit - Add PDC to world
|
||||
return new LevelDataAndDimensions(primaryLevelData, complete);
|
||||
}
|
||||
|
||||
@@ -340,25 +_,39 @@
|
||||
return this.backupDir;
|
||||
}
|
||||
|
||||
- public LevelStorageSource.LevelStorageAccess validateAndCreateAccess(String saveName) throws IOException, ContentValidationException {
|
||||
+ public LevelStorageSource.LevelStorageAccess validateAndCreateAccess(String saveName, ResourceKey<LevelStem> dimensionType) throws IOException, ContentValidationException { // CraftBukkit
|
||||
Path levelPath = this.getLevelPath(saveName);
|
||||
- List<ForbiddenSymlinkInfo> list = this.worldDirValidator.validateDirectory(levelPath, true);
|
||||
+ List<ForbiddenSymlinkInfo> list = Boolean.getBoolean("paper.disableWorldSymlinkValidation") ? List.of() : this.worldDirValidator.validateDirectory(levelPath, true); // Paper - add skipping of symlinks scan
|
||||
if (!list.isEmpty()) {
|
||||
throw new ContentValidationException(levelPath, list);
|
||||
} else {
|
||||
- return new LevelStorageSource.LevelStorageAccess(saveName, levelPath);
|
||||
+ return new LevelStorageSource.LevelStorageAccess(saveName, levelPath, dimensionType); // CraftBukkit
|
||||
}
|
||||
}
|
||||
|
||||
- public LevelStorageSource.LevelStorageAccess createAccess(String saveName) throws IOException {
|
||||
+ public LevelStorageSource.LevelStorageAccess createAccess(String saveName, ResourceKey<LevelStem> dimensionType) throws IOException { // CraftBukkit
|
||||
Path levelPath = this.getLevelPath(saveName);
|
||||
- return new LevelStorageSource.LevelStorageAccess(saveName, levelPath);
|
||||
+ return new LevelStorageSource.LevelStorageAccess(saveName, levelPath, dimensionType); // CraftBukkit
|
||||
}
|
||||
|
||||
public DirectoryValidator getWorldDirValidator() {
|
||||
return this.worldDirValidator;
|
||||
}
|
||||
|
||||
+ // CraftBukkit start
|
||||
+ public static Path getStorageFolder(Path path, ResourceKey<LevelStem> dimensionType) {
|
||||
+ if (dimensionType == LevelStem.OVERWORLD) {
|
||||
+ return path;
|
||||
+ } else if (dimensionType == LevelStem.NETHER) {
|
||||
+ return path.resolve("DIM-1");
|
||||
+ } else if (dimensionType == LevelStem.END) {
|
||||
+ return path.resolve("DIM1");
|
||||
+ } else {
|
||||
+ return path.resolve("dimensions").resolve(dimensionType.location().getNamespace()).resolve(dimensionType.location().getPath());
|
||||
+ }
|
||||
+ }
|
||||
+ // CraftBukkit end
|
||||
+
|
||||
public record LevelCandidates(List<LevelStorageSource.LevelDirectory> levels) implements Iterable<LevelStorageSource.LevelDirectory> {
|
||||
public boolean isEmpty() {
|
||||
return this.levels.isEmpty();
|
||||
@@ -409,8 +_,12 @@
|
||||
public final LevelStorageSource.LevelDirectory levelDirectory;
|
||||
private final String levelId;
|
||||
private final Map<LevelResource, Path> resources = Maps.newHashMap();
|
||||
+ // CraftBukkit start
|
||||
+ public final ResourceKey<LevelStem> dimensionType;
|
||||
|
||||
- LevelStorageAccess(final String levelId, final Path levelDir) throws IOException {
|
||||
+ LevelStorageAccess(final String levelId, final Path levelDir, final ResourceKey<LevelStem> dimensionType) throws IOException {
|
||||
+ this.dimensionType = dimensionType;
|
||||
+ // CraftBukkit end
|
||||
this.levelId = levelId;
|
||||
this.levelDirectory = new LevelStorageSource.LevelDirectory(levelDir);
|
||||
this.lock = DirectoryLock.create(levelDir);
|
||||
@@ -453,7 +_,7 @@
|
||||
}
|
||||
|
||||
public Path getDimensionPath(ResourceKey<Level> dimensionPath) {
|
||||
- return DimensionType.getStorageFolder(dimensionPath, this.levelDirectory.path());
|
||||
+ return getStorageFolder(this.levelDirectory.path(), this.dimensionType); // CraftBukkit
|
||||
}
|
||||
|
||||
private void checkLock() {
|
||||
@@ -0,0 +1,122 @@
|
||||
--- a/net/minecraft/world/level/storage/PlayerDataStorage.java
|
||||
+++ b/net/minecraft/world/level/storage/PlayerDataStorage.java
|
||||
@@ -14,8 +_,10 @@
|
||||
import net.minecraft.nbt.NbtAccounter;
|
||||
import net.minecraft.nbt.NbtIo;
|
||||
import net.minecraft.nbt.NbtUtils;
|
||||
+import net.minecraft.server.level.ServerPlayer;
|
||||
import net.minecraft.util.datafix.DataFixTypes;
|
||||
import net.minecraft.world.entity.player.Player;
|
||||
+import org.bukkit.craftbukkit.entity.CraftPlayer;
|
||||
import org.slf4j.Logger;
|
||||
|
||||
public class PlayerDataStorage {
|
||||
@@ -31,6 +_,7 @@
|
||||
}
|
||||
|
||||
public void save(Player player) {
|
||||
+ if (org.spigotmc.SpigotConfig.disablePlayerDataSaving) return; // Spigot
|
||||
try {
|
||||
CompoundTag compoundTag = player.saveWithoutId(new CompoundTag());
|
||||
Path path = this.playerDir.toPath();
|
||||
@@ -40,30 +_,46 @@
|
||||
Path path3 = path.resolve(player.getStringUUID() + ".dat_old");
|
||||
Util.safeReplaceFile(path2, path1, path3);
|
||||
} catch (Exception var7) {
|
||||
- LOGGER.warn("Failed to save player data for {}", player.getName().getString());
|
||||
+ LOGGER.warn("Failed to save player data for {}", player.getScoreboardName(), var7); // Paper - Print exception
|
||||
}
|
||||
}
|
||||
|
||||
- private void backup(Player player, String suffix) {
|
||||
+ private void backup(String name, String stringUuid, String suffix) { // CraftBukkit
|
||||
Path path = this.playerDir.toPath();
|
||||
- Path path1 = path.resolve(player.getStringUUID() + suffix);
|
||||
- Path path2 = path.resolve(player.getStringUUID() + "_corrupted_" + LocalDateTime.now().format(FORMATTER) + suffix);
|
||||
+ Path path1 = path.resolve(stringUuid + suffix); // CraftBukkit
|
||||
+ Path path2 = path.resolve(stringUuid + "_corrupted_" + LocalDateTime.now().format(FORMATTER) + suffix); // CraftBukkit
|
||||
if (Files.isRegularFile(path1)) {
|
||||
try {
|
||||
Files.copy(path1, path2, StandardCopyOption.REPLACE_EXISTING, StandardCopyOption.COPY_ATTRIBUTES);
|
||||
} catch (Exception var7) {
|
||||
- LOGGER.warn("Failed to copy the player.dat file for {}", player.getName().getString(), var7);
|
||||
+ LOGGER.warn("Failed to copy the player.dat file for {}", name, var7); // CraftBukkit
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
- private Optional<CompoundTag> load(Player player, String suffix) {
|
||||
- File file = new File(this.playerDir, player.getStringUUID() + suffix);
|
||||
+ private Optional<CompoundTag> load(String name, String stringUuid, String suffix) { // CraftBukkit
|
||||
+ File file = new File(this.playerDir, stringUuid + suffix); // CraftBukkit
|
||||
+ // Spigot Start
|
||||
+ boolean usingWrongFile = false;
|
||||
+ if (org.bukkit.Bukkit.getOnlineMode() && !file.exists()) { // Paper - Check online mode first
|
||||
+ file = new File(file, java.util.UUID.nameUUIDFromBytes(("OfflinePlayer:" + name).getBytes(java.nio.charset.StandardCharsets.UTF_8)).toString() + suffix);
|
||||
+ if (file.exists()) {
|
||||
+ usingWrongFile = true;
|
||||
+ org.bukkit.Bukkit.getServer().getLogger().warning("Using offline mode UUID file for player " + name + " as it is the only copy we can find.");
|
||||
+ }
|
||||
+ }
|
||||
+ // Spigot End
|
||||
if (file.exists() && file.isFile()) {
|
||||
try {
|
||||
- return Optional.of(NbtIo.readCompressed(file.toPath(), NbtAccounter.unlimitedHeap()));
|
||||
+ // Spigot Start
|
||||
+ Optional<CompoundTag> optional = Optional.of(NbtIo.readCompressed(file.toPath(), NbtAccounter.unlimitedHeap()));
|
||||
+ if (usingWrongFile) {
|
||||
+ file.renameTo(new File(file.getPath() + ".offline-read"));
|
||||
+ }
|
||||
+ return optional;
|
||||
+ // Spigot End
|
||||
} catch (Exception var5) {
|
||||
- LOGGER.warn("Failed to load player data for {}", player.getName().getString());
|
||||
+ LOGGER.warn("Failed to load player data for {}", name); // CraftBukkit
|
||||
}
|
||||
}
|
||||
|
||||
@@ -71,16 +_,40 @@
|
||||
}
|
||||
|
||||
public Optional<CompoundTag> load(Player player) {
|
||||
- Optional<CompoundTag> optional = this.load(player, ".dat");
|
||||
+ // CraftBukkit start
|
||||
+ return this.load(player.getName().getString(), player.getStringUUID()).map((tag) -> {
|
||||
+ if (player instanceof ServerPlayer) {
|
||||
+ CraftPlayer player1 = (CraftPlayer) player.getBukkitEntity();
|
||||
+ // Only update first played if it is older than the one we have
|
||||
+ long modified = new File(this.playerDir, player.getStringUUID() + ".dat").lastModified();
|
||||
+ if (modified < player1.getFirstPlayed()) {
|
||||
+ player1.setFirstPlayed(modified);
|
||||
+ }
|
||||
+ }
|
||||
+
|
||||
+ player.load(tag); // From below
|
||||
+ return tag;
|
||||
+ });
|
||||
+ }
|
||||
+
|
||||
+ public Optional<CompoundTag> load(String name, String uuid) {
|
||||
+ // CraftBukkit end
|
||||
+ Optional<CompoundTag> optional = this.load(name, uuid, ".dat"); // CraftBukkit
|
||||
if (optional.isEmpty()) {
|
||||
- this.backup(player, ".dat");
|
||||
+ this.backup(name, uuid, ".dat"); // CraftBukkit
|
||||
}
|
||||
|
||||
- return optional.or(() -> this.load(player, ".dat_old")).map(compoundTag -> {
|
||||
+ return optional.or(() -> this.load(name, uuid, ".dat_old")).map(compoundTag -> { // CraftBukkit
|
||||
int dataVersion = NbtUtils.getDataVersion(compoundTag, -1);
|
||||
compoundTag = DataFixTypes.PLAYER.updateToCurrentVersion(this.fixerUpper, compoundTag, dataVersion);
|
||||
- player.load(compoundTag);
|
||||
+ // player.load(compoundTag); // CraftBukkit - handled above
|
||||
return compoundTag;
|
||||
});
|
||||
}
|
||||
+
|
||||
+ // CraftBukkit start
|
||||
+ public File getPlayerDir() {
|
||||
+ return this.playerDir;
|
||||
+ }
|
||||
+ // CraftBukkit end
|
||||
}
|
||||
@@ -0,0 +1,123 @@
|
||||
--- a/net/minecraft/world/level/storage/PrimaryLevelData.java
|
||||
+++ b/net/minecraft/world/level/storage/PrimaryLevelData.java
|
||||
@@ -74,6 +_,21 @@
|
||||
private final Set<String> removedFeatureFlags;
|
||||
private final TimerQueue<MinecraftServer> scheduledEvents;
|
||||
|
||||
+ // CraftBukkit start - Add world and pdc
|
||||
+ public net.minecraft.core.Registry<net.minecraft.world.level.dimension.LevelStem> customDimensions;
|
||||
+ private net.minecraft.server.level.ServerLevel world;
|
||||
+ protected net.minecraft.nbt.Tag pdc;
|
||||
+
|
||||
+ public void setWorld(net.minecraft.server.level.ServerLevel world) {
|
||||
+ if (this.world != null) {
|
||||
+ return;
|
||||
+ }
|
||||
+ this.world = world;
|
||||
+ world.getWorld().readBukkitValues(this.pdc);
|
||||
+ this.pdc = null;
|
||||
+ }
|
||||
+ // CraftBukkit end
|
||||
+
|
||||
private PrimaryLevelData(
|
||||
@Nullable CompoundTag loadedPlayerTag,
|
||||
boolean wasModded,
|
||||
@@ -237,7 +_,7 @@
|
||||
nbt.put("Version", compoundTag);
|
||||
NbtUtils.addCurrentDataVersion(nbt);
|
||||
DynamicOps<Tag> dynamicOps = registry.createSerializationContext(NbtOps.INSTANCE);
|
||||
- WorldGenSettings.encode(dynamicOps, this.worldOptions, registry)
|
||||
+ WorldGenSettings.encode(dynamicOps, this.worldOptions, new net.minecraft.world.level.levelgen.WorldDimensions(this.customDimensions != null ? this.customDimensions : registry.lookupOrThrow(net.minecraft.core.registries.Registries.LEVEL_STEM))) // CraftBukkit
|
||||
.resultOrPartial(Util.prefix("WorldGenSettings: ", LOGGER::error))
|
||||
.ifPresent(worldOptionsTag -> nbt.put("WorldGenSettings", worldOptionsTag));
|
||||
nbt.putInt("GameType", this.settings.gameType().getId());
|
||||
@@ -281,6 +_,8 @@
|
||||
if (this.wanderingTraderId != null) {
|
||||
nbt.putUUID("WanderingTraderId", this.wanderingTraderId);
|
||||
}
|
||||
+ nbt.putString("Bukkit.Version", org.bukkit.Bukkit.getName() + "/" + org.bukkit.Bukkit.getVersion() + "/" + org.bukkit.Bukkit.getBukkitVersion()); // CraftBukkit
|
||||
+ this.world.getWorld().storeBukkitValues(nbt); // CraftBukkit - add pdc
|
||||
}
|
||||
|
||||
private static ListTag stringCollectionToTag(Set<String> stringCollection) {
|
||||
@@ -358,6 +_,25 @@
|
||||
|
||||
@Override
|
||||
public void setThundering(boolean thundering) {
|
||||
+ // Paper start - Add cause to Weather/ThunderChangeEvents
|
||||
+ this.setThundering(thundering, org.bukkit.event.weather.ThunderChangeEvent.Cause.UNKNOWN);
|
||||
+ }
|
||||
+ public void setThundering(boolean thundering, org.bukkit.event.weather.ThunderChangeEvent.Cause cause) {
|
||||
+ // Paper end - Add cause to Weather/ThunderChangeEvents
|
||||
+ // CraftBukkit start
|
||||
+ if (this.thundering == thundering) {
|
||||
+ return;
|
||||
+ }
|
||||
+
|
||||
+ org.bukkit.World world = org.bukkit.Bukkit.getWorld(this.getLevelName());
|
||||
+ if (world != null) {
|
||||
+ org.bukkit.event.weather.ThunderChangeEvent thunder = new org.bukkit.event.weather.ThunderChangeEvent(world, thundering, cause); // Paper - Add cause to Weather/ThunderChangeEvents
|
||||
+ org.bukkit.Bukkit.getServer().getPluginManager().callEvent(thunder);
|
||||
+ if (thunder.isCancelled()) {
|
||||
+ return;
|
||||
+ }
|
||||
+ }
|
||||
+ // CraftBukkit end
|
||||
this.thundering = thundering;
|
||||
}
|
||||
|
||||
@@ -378,6 +_,26 @@
|
||||
|
||||
@Override
|
||||
public void setRaining(boolean isRaining) {
|
||||
+ // Paper start - Add cause to Weather/ThunderChangeEvents
|
||||
+ this.setRaining(isRaining, org.bukkit.event.weather.WeatherChangeEvent.Cause.UNKNOWN);
|
||||
+ }
|
||||
+
|
||||
+ public void setRaining(boolean isRaining, org.bukkit.event.weather.WeatherChangeEvent.Cause cause) {
|
||||
+ // Paper end - Add cause to Weather/ThunderChangeEvents
|
||||
+ // CraftBukkit start
|
||||
+ if (this.raining == isRaining) {
|
||||
+ return;
|
||||
+ }
|
||||
+
|
||||
+ org.bukkit.World world = org.bukkit.Bukkit.getWorld(this.getLevelName());
|
||||
+ if (world != null) {
|
||||
+ org.bukkit.event.weather.WeatherChangeEvent weather = new org.bukkit.event.weather.WeatherChangeEvent(world, isRaining, cause); // Paper - Add cause to Weather/ThunderChangeEvents
|
||||
+ org.bukkit.Bukkit.getServer().getPluginManager().callEvent(weather);
|
||||
+ if (weather.isCancelled()) {
|
||||
+ return;
|
||||
+ }
|
||||
+ }
|
||||
+ // CraftBukkit end
|
||||
this.raining = isRaining;
|
||||
}
|
||||
|
||||
@@ -444,6 +_,12 @@
|
||||
@Override
|
||||
public void setDifficulty(Difficulty difficulty) {
|
||||
this.settings = this.settings.withDifficulty(difficulty);
|
||||
+ // CraftBukkit start
|
||||
+ net.minecraft.network.protocol.game.ClientboundChangeDifficultyPacket packet = new net.minecraft.network.protocol.game.ClientboundChangeDifficultyPacket(this.getDifficulty(), this.isDifficultyLocked());
|
||||
+ for (net.minecraft.server.level.ServerPlayer player : (java.util.List<net.minecraft.server.level.ServerPlayer>) (java.util.List) this.world.players()) {
|
||||
+ player.connection.send(packet);
|
||||
+ }
|
||||
+ // CraftBukkit end
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -579,6 +_,14 @@
|
||||
public LevelSettings getLevelSettings() {
|
||||
return this.settings.copy();
|
||||
}
|
||||
+
|
||||
+ // CraftBukkit start - Check if the name stored in NBT is the correct one
|
||||
+ public void checkName(String name) {
|
||||
+ if (!this.settings.levelName.equals(name)) {
|
||||
+ this.settings.levelName = name;
|
||||
+ }
|
||||
+ }
|
||||
+ // CraftBukkit end
|
||||
|
||||
@Deprecated
|
||||
public static enum SpecialWorldProperty {
|
||||
Reference in New Issue
Block a user