Skip to content

Commit

Permalink
Merge remote-tracking branch 'origin/api-12' into api-13
Browse files Browse the repository at this point in the history
  • Loading branch information
aromaa committed Oct 30, 2024
2 parents 363a1af + 08a7c2c commit 705c820
Show file tree
Hide file tree
Showing 4 changed files with 147 additions and 126 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -78,8 +78,8 @@ PhaseContext<?> pop() {

PhaseStack push(IPhaseState<?> state, PhaseContext<?> context) {
Objects.requireNonNull(context, "Tuple cannot be null!");
Preconditions.checkArgument(context.state == state, String.format("Illegal IPhaseState not matching PhaseContext: %s", context));
Preconditions.checkArgument(context.isComplete(), String.format("Phase context must be complete: %s", context));
Preconditions.checkArgument(context.state == state, () -> String.format("Illegal IPhaseState not matching PhaseContext: %s", context));
Preconditions.checkArgument(context.isComplete(), () -> String.format("Phase context must be complete: %s", context));
this.phases.push(context);
return this;
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -122,6 +122,7 @@ public FlatGeneratorConfig.Builder reset() {

@Override
public FlatGeneratorConfig.Builder from(final FlatGeneratorConfig value) {
this.biome = value.biome();
this.layers.addAll(value.layers());
this.performDecoration = value.performDecoration();
this.populateLakes = value.populateLakes();
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -56,9 +56,12 @@
import net.minecraft.world.level.LevelSettings;
import net.minecraft.world.level.WorldDataConfiguration;
import net.minecraft.world.level.biome.BiomeManager;
import net.minecraft.world.level.chunk.ChunkGenerator;
import net.minecraft.world.level.dimension.BuiltinDimensionTypes;
import net.minecraft.world.level.dimension.DimensionType;
import net.minecraft.world.level.dimension.LevelStem;
import net.minecraft.world.level.levelgen.DebugLevelSource;
import net.minecraft.world.level.levelgen.FlatLevelSource;
import net.minecraft.world.level.levelgen.PatrolSpawner;
import net.minecraft.world.level.levelgen.PhantomSpawner;
import net.minecraft.world.level.levelgen.WorldOptions;
Expand Down Expand Up @@ -123,6 +126,7 @@
import java.util.Optional;
import java.util.UUID;
import java.util.concurrent.CompletableFuture;
import java.util.concurrent.CompletionException;
import java.util.concurrent.CompletionStage;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.Executor;
Expand Down Expand Up @@ -477,87 +481,91 @@ public CompletableFuture<Boolean> copyWorld(final ResourceKey key, final Resourc
}

final ServerLevel loadedWorld = this.worlds.get(registryKey);
boolean disableLevelSaving = false;
final boolean disableLevelSaving;

if (loadedWorld != null) {
disableLevelSaving = loadedWorld.noSave;
loadedWorld.save(null, true, loadedWorld.noSave);
loadedWorld.noSave = true;
} else {
disableLevelSaving = false;
}

final boolean isDefaultWorld = DefaultWorldKeys.DEFAULT.equals(key);

final Path originalDirectory = this.getDirectory(key);
final Path copyDirectory = this.getDirectory(copyKey);

try {
Files.walkFileTree(originalDirectory, new SimpleFileVisitor<Path>() {
@Override
public FileVisitResult preVisitDirectory(final Path dir, final BasicFileAttributes attrs) throws IOException {
// Silly recursion if the default world is being copied
if (dir.getFileName().toString().equals(Constants.Sponge.World.DIMENSIONS_DIRECTORY)) {
return FileVisitResult.SKIP_SUBTREE;
}
return CompletableFuture.runAsync(() -> {
final Path originalDirectory = this.getDirectory(key);
final Path copyDirectory = this.getDirectory(copyKey);

// Silly copying of vanilla sub worlds if the default world is being copied
if (isDefaultWorld && SpongeWorldManager.this.isVanillaSubWorld(dir.getFileName().toString())) {
return FileVisitResult.SKIP_SUBTREE;
}
try {
Files.walkFileTree(originalDirectory, new SimpleFileVisitor<Path>() {
@Override
public FileVisitResult preVisitDirectory(final Path dir, final BasicFileAttributes attrs) throws IOException {
// Silly recursion if the default world is being copied
if (dir.getFileName().toString().equals(Constants.Sponge.World.DIMENSIONS_DIRECTORY)) {
return FileVisitResult.SKIP_SUBTREE;
}

final Path relativize = originalDirectory.relativize(dir);
final Path directory = copyDirectory.resolve(relativize);
Files.createDirectories(directory);
// Silly copying of vanilla sub worlds if the default world is being copied
if (isDefaultWorld && SpongeWorldManager.this.isVanillaSubWorld(dir.getFileName().toString())) {
return FileVisitResult.SKIP_SUBTREE;
}

return FileVisitResult.CONTINUE;
}
final Path relativize = originalDirectory.relativize(dir);
final Path directory = copyDirectory.resolve(relativize);
Files.createDirectories(directory);

@Override
public FileVisitResult visitFile(final Path file, final BasicFileAttributes attrs) throws IOException {
final String fileName = file.getFileName().toString();
// Do not copy backups (not relevant anymore)
if (fileName.equals(Constants.Sponge.World.LEVEL_SPONGE_DAT_OLD)) {
return FileVisitResult.CONTINUE;
}
if (fileName.equals(Constants.World.LEVEL_DAT_OLD)) {
return FileVisitResult.CONTINUE;
}
Files.copy(file, copyDirectory.resolve(originalDirectory.relativize(file)), StandardCopyOption.COPY_ATTRIBUTES,

@Override
public FileVisitResult visitFile(final Path file, final BasicFileAttributes attrs) throws IOException {
final String fileName = file.getFileName().toString();
// Do not copy backups (not relevant anymore)
if (fileName.equals(Constants.Sponge.World.LEVEL_SPONGE_DAT_OLD)) {
return FileVisitResult.CONTINUE;
}
if (fileName.equals(Constants.World.LEVEL_DAT_OLD)) {
return FileVisitResult.CONTINUE;
}
Files.copy(file, copyDirectory.resolve(originalDirectory.relativize(file)), StandardCopyOption.COPY_ATTRIBUTES,
StandardCopyOption.REPLACE_EXISTING);

return FileVisitResult.CONTINUE;
return FileVisitResult.CONTINUE;
}
});
} catch (final IOException e) {
// Bail the whole deal if we hit IO problems!
try {
Files.walkFileTree(copyDirectory, DeleteFileVisitor.INSTANCE);
} catch (final IOException ignore) {
}
});
} catch (final IOException e) {
// Bail the whole deal if we hit IO problems!
try {
Files.walkFileTree(copyDirectory, DeleteFileVisitor.INSTANCE);
} catch (final IOException ignore) {
}

return FutureUtil.completedWithException(e);
}

if (loadedWorld != null) {
loadedWorld.noSave = disableLevelSaving;
}
throw new CompletionException(e);
}

final Path configFile = this.getConfigFile(key);
final Path copyConfigFile = this.getConfigFile(copyKey);
if (loadedWorld != null) {
loadedWorld.noSave = disableLevelSaving;
}

try {
Files.createDirectories(copyConfigFile.getParent());
Files.copy(configFile, copyConfigFile, StandardCopyOption.REPLACE_EXISTING);
} catch (final IOException e) {
return FutureUtil.completedWithException(e);
}
final Path configFile = this.getConfigFile(key);
final Path copyConfigFile = this.getConfigFile(copyKey);

try {
this.server().dataPackManager().copy(this.findPack(key), key, copyKey);
} catch (final IOException e) {
return FutureUtil.completedWithException(e);
}
try {
Files.createDirectories(copyConfigFile.getParent());
Files.copy(configFile, copyConfigFile, StandardCopyOption.REPLACE_EXISTING);
} catch (final IOException e) {
throw new CompletionException(e);
}
}).thenApplyAsync($ -> {
try {
this.server().dataPackManager().copy(this.findPack(key), key, copyKey);
} catch (final IOException e) {
throw new CompletionException(e);
}

return CompletableFuture.completedFuture(true);
return true;
}, SpongeCommon.server());
}

@Override
Expand Down Expand Up @@ -585,33 +593,35 @@ public CompletableFuture<Boolean> moveWorld(final ResourceKey key, final Resourc
}
}

final Path originalDirectory = this.getDirectory(key);
final Path movedDirectory = this.getDirectory(movedKey);

try {
Files.createDirectories(movedDirectory);
Files.move(originalDirectory, movedDirectory, StandardCopyOption.REPLACE_EXISTING);
} catch (final IOException e) {
return FutureUtil.completedWithException(e);
}
return CompletableFuture.runAsync(() -> {
final Path originalDirectory = this.getDirectory(key);
final Path movedDirectory = this.getDirectory(movedKey);

final Path configFile = this.getConfigFile(key);
final Path movedConfigFile = this.getConfigFile(movedKey);
try {
Files.createDirectories(movedDirectory);
Files.move(originalDirectory, movedDirectory, StandardCopyOption.REPLACE_EXISTING);
} catch (final IOException e) {
throw new CompletionException(e);
}

try {
Files.createDirectories(movedConfigFile.getParent());
Files.move(configFile, movedConfigFile, StandardCopyOption.REPLACE_EXISTING);
} catch (final IOException e) {
return FutureUtil.completedWithException(e);
}
final Path configFile = this.getConfigFile(key);
final Path movedConfigFile = this.getConfigFile(movedKey);

try {
this.server().dataPackManager().move(this.findPack(key), key, movedKey);
} catch (final IOException e) {
return FutureUtil.completedWithException(e);
}
try {
Files.createDirectories(movedConfigFile.getParent());
Files.move(configFile, movedConfigFile, StandardCopyOption.REPLACE_EXISTING);
} catch (final IOException e) {
throw new CompletionException(e);
}
}).thenApplyAsync($ -> {
try {
this.server().dataPackManager().move(this.findPack(key), key, movedKey);
} catch (final IOException e) {
throw new CompletionException(e);
}

return CompletableFuture.completedFuture(true);
return true;
}, SpongeCommon.server());
}

@Override
Expand All @@ -638,44 +648,44 @@ public CompletableFuture<Boolean> deleteWorld(final ResourceKey key) {
}
}

final Path directory = this.getDirectory(key);
if (Files.exists(directory)) {
return CompletableFuture.runAsync(() -> {
final Path directory = this.getDirectory(key);
if (Files.exists(directory)) {
try {
Files.walkFileTree(directory, DeleteFileVisitor.INSTANCE);
} catch (final IOException e) {
throw new CompletionException(e);
}
}

final Path configFile = this.getConfigFile(key);
try {
Files.walkFileTree(directory, DeleteFileVisitor.INSTANCE);
Files.deleteIfExists(configFile);
} catch (final IOException e) {
return FutureUtil.completedWithException(e);
throw new CompletionException(e);
}
}).thenApplyAsync($ -> {
try {
this.server().dataPackManager().delete(this.findPack(key), key);
} catch (final IOException e) {
throw new CompletionException(e);
}
}

final Path configFile = this.getConfigFile(key);
try {
Files.deleteIfExists(configFile);
} catch (final IOException e) {
return FutureUtil.completedWithException(e);
}

try {
this.server().dataPackManager().delete(this.findPack(key), key);
} catch (final IOException e) {
return FutureUtil.completedWithException(e);
}

//After vanilla has detected a new dimension from a data pack it "promotes" it
//to the overworld's level data where the level persist even when the data pack is removed.
//This forcible removes it from there too.
Registry<LevelStem> registry = SpongeCommon.vanillaRegistry(Registries.LEVEL_STEM);
((MappedRegistryBridge<LevelStem>) registry).bridge$forceRemoveValue(Registries.levelToLevelStem(registryKey));
//After vanilla has detected a new dimension from a data pack it "promotes" it
//to the overworld's level data where the level persist even when the data pack is removed.
//This forcible removes it from there too.
final Registry<LevelStem> levelStemRegistry = SpongeCommon.vanillaRegistry(Registries.LEVEL_STEM);
final net.minecraft.resources.ResourceKey<net.minecraft.world.level.dimension.LevelStem> levelStemKey = Registries.levelToLevelStem(registryKey);
if (levelStemRegistry.containsKey(levelStemKey)) {
((MappedRegistryBridge<LevelStem>) levelStemRegistry).bridge$forceRemoveValue(Registries.levelToLevelStem(registryKey));
}

try {
(((MinecraftServerAccessor) this.server).accessor$storageSource()).saveDataTag(
SpongeCommon.server().registryAccess(),
(PrimaryLevelData) SpongeCommon.server().overworld().getLevelData(),
SpongeCommon.server().getPlayerList().getSingleplayerData());
} catch (final Exception ex) {
return FutureUtil.completedWithException(ex);
}
final LevelStorageSource.LevelStorageAccess storageSource = ((MinecraftServerAccessor) this.server).accessor$storageSource();
final PrimaryLevelData levelData = (PrimaryLevelData) this.server.getWorldData();
storageSource.saveDataTag(SpongeCommon.server().registryAccess(), levelData, null);

return CompletableFuture.completedFuture(true);
return true;
}, SpongeCommon.server());
}

private DataPack<WorldTemplate> findPack(ResourceKey key) {
Expand Down Expand Up @@ -791,7 +801,7 @@ private PrimaryLevelData getOrCreateLevelData(@Nullable final Dynamic<?> dynamic
}

if (this.server.isDemo()) {
return new PrimaryLevelData(MinecraftServer.DEMO_SETTINGS, WorldOptions.DEMO_OPTIONS, PrimaryLevelData.SpecialWorldProperty.NONE, Lifecycle.stable());
return new PrimaryLevelData(MinecraftServer.DEMO_SETTINGS, WorldOptions.DEMO_OPTIONS, SpongeWorldManager.specialWorldProperty(levelStem), Lifecycle.stable());
}

final LevelSettings levelSettings = this.createLevelSettings(defaultLevelData, levelStem, directoryName);
Expand All @@ -801,9 +811,9 @@ private PrimaryLevelData getOrCreateLevelData(@Nullable final Dynamic<?> dynamic
final WorldOptions generationSettings = ((WorldOptionsBridge) defaultLevelData.worldGenOptions()).bridge$withSeed(customSeed);
// TODO generateStructures?
// TODO bonusChest?
return new PrimaryLevelData(levelSettings, generationSettings, PrimaryLevelData.SpecialWorldProperty.NONE, Lifecycle.stable());
return new PrimaryLevelData(levelSettings, generationSettings, SpongeWorldManager.specialWorldProperty(levelStem), Lifecycle.stable());
}
return new PrimaryLevelData(levelSettings, defaultLevelData.worldGenOptions(), PrimaryLevelData.SpecialWorldProperty.NONE, Lifecycle.stable());
return new PrimaryLevelData(levelSettings, defaultLevelData.worldGenOptions(), SpongeWorldManager.specialWorldProperty(levelStem), Lifecycle.stable());
}

private PrimaryLevelData loadLevelData(final RegistryAccess.Frozen access, final WorldDataConfiguration datapackConfig, final Dynamic<?> dataTag) {
Expand Down Expand Up @@ -1090,4 +1100,14 @@ private Path getConfigFile(final ResourceKey key) {
return SpongeCommon.spongeConfigDirectory().resolve(Launch.instance().id()).resolve("worlds").resolve(key.namespace())
.resolve(key.value() + ".conf");
}

private static PrimaryLevelData.SpecialWorldProperty specialWorldProperty(final LevelStem stem) {
//Copied from WorldDimensions#specialWorldProperty
final ChunkGenerator $$1 = stem.generator();
if ($$1 instanceof DebugLevelSource) {
return PrimaryLevelData.SpecialWorldProperty.DEBUG;
} else {
return $$1 instanceof FlatLevelSource ? PrimaryLevelData.SpecialWorldProperty.FLAT : PrimaryLevelData.SpecialWorldProperty.NONE;
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -61,7 +61,6 @@
import net.minecraft.world.level.dimension.LevelStem;
import net.minecraft.world.level.dimension.end.EndDragonFight;
import net.minecraft.world.level.gameevent.GameEvent;
import net.minecraft.world.level.levelgen.WorldOptions;
import net.minecraft.world.level.material.Fluid;
import net.minecraft.world.level.storage.LevelStorageSource;
import net.minecraft.world.level.storage.PrimaryLevelData;
Expand Down Expand Up @@ -182,11 +181,6 @@ public abstract class ServerLevelMixin extends LevelMixin implements ServerLevel
}
}

@Redirect(method = "getSeed", at = @At(value = "INVOKE", target = "Lnet/minecraft/world/level/storage/WorldData;worldGenOptions()Lnet/minecraft/world/level/levelgen/WorldOptions;"))
public WorldOptions impl$onGetSeed(final WorldData iServerConfiguration) {
return ((PrimaryLevelData) this.serverLevelData).worldGenOptions();
}

@Override
public LevelStorageSource.LevelStorageAccess bridge$getLevelSave() {
return this.impl$levelSave;
Expand Down Expand Up @@ -330,8 +324,14 @@ public abstract class ServerLevelMixin extends LevelMixin implements ServerLevel
return this.impl$recentTickTimes;
}

@Redirect(method = "saveLevelData", at = @At(value = "INVOKE", target = "Lnet/minecraft/server/MinecraftServer;getWorldData()Lnet/minecraft/world/level/storage/WorldData;"))
private WorldData impl$usePerWorldLevelDataForDragonFight(final MinecraftServer server) {
@Redirect(method = {
"saveLevelData",
"findNearestMapStructure",
"isFlat",
"getSeed",
"enabledFeatures"
}, at = @At(value = "INVOKE", target = "Lnet/minecraft/server/MinecraftServer;getWorldData()Lnet/minecraft/world/level/storage/WorldData;"))
private WorldData impl$usePerWorldLevelData(final MinecraftServer server) {
return (WorldData) this.shadow$getLevelData();
}

Expand Down

0 comments on commit 705c820

Please sign in to comment.