use of net.minecraft.server.level.ServerLevel in project SpongeCommon by SpongePowered.
the class SpongeWorldManager method unloadWorld0.
private void unloadWorld0(final ServerLevel world) throws IOException {
final net.minecraft.resources.ResourceKey<Level> registryKey = world.dimension();
if (world.getPlayers(p -> true).size() != 0) {
throw new IOException(String.format("World '%s' was told to unload but players remain.", registryKey.location()));
}
SpongeCommon.logger().info("Unloading world '{}' ({})", registryKey.location(), RegistryTypes.WORLD_TYPE.get().valueKey((WorldType) world.dimensionType()));
SpongeCommon.post(SpongeEventFactory.createUnloadWorldEvent(PhaseTracker.getCauseStackManager().currentCause(), (org.spongepowered.api.world.server.ServerWorld) world));
final BlockPos spawnPoint = world.getSharedSpawnPos();
world.getChunkSource().removeRegionTicket(SpongeWorldManager.SPAWN_CHUNKS, new ChunkPos(spawnPoint), 11, registryKey.location());
((PrimaryLevelDataBridge) world.getLevelData()).bridge$configAdapter().save();
((ServerLevelBridge) world).bridge$setManualSave(true);
try {
world.save(null, true, world.noSave);
world.close();
((ServerLevelBridge) world).bridge$getLevelSave().close();
} catch (final Exception ex) {
throw new IOException(ex);
}
this.worlds.remove(registryKey);
}
use of net.minecraft.server.level.ServerLevel in project SpongeCommon by SpongePowered.
the class SpongeWorldManager method deleteWorld.
@Override
public CompletableFuture<Boolean> deleteWorld(final ResourceKey key) {
final net.minecraft.resources.ResourceKey<Level> registryKey = SpongeWorldManager.createRegistryKey(Objects.requireNonNull(key, "key"));
if (Level.OVERWORLD.equals(registryKey)) {
return CompletableFuture.completedFuture(false);
}
if (!this.worldExists(key)) {
return CompletableFuture.completedFuture(false);
}
final ServerLevel loadedWorld = this.worlds.get(registryKey);
if (loadedWorld != null) {
final boolean disableLevelSaving = loadedWorld.noSave;
loadedWorld.noSave = true;
try {
this.unloadWorld0(loadedWorld);
} catch (final IOException e) {
loadedWorld.noSave = disableLevelSaving;
return FutureUtil.completedWithException(e);
}
}
final boolean isVanillaWorld = this.isVanillaWorld(key);
final String directoryName = this.getDirectoryName(key);
final Path directory = isVanillaWorld ? this.defaultWorldDirectory.resolve(directoryName) : this.customWorldsDirectory.resolve(key.namespace()).resolve(key.value());
if (Files.exists(directory)) {
try {
for (final Path path : Files.walk(directory).sorted(Comparator.reverseOrder()).collect(Collectors.toList())) {
Files.deleteIfExists(path);
}
} catch (final IOException e) {
return FutureUtil.completedWithException(e);
}
}
final Path configFile = SpongeCommon.spongeConfigDirectory().resolve(Launch.instance().id()).resolve("worlds").resolve(key.namespace()).resolve(key.value() + ".conf");
try {
Files.deleteIfExists(configFile);
} catch (final IOException e) {
return FutureUtil.completedWithException(e);
}
final Path dimensionTemplate = this.getDataPackFile(key);
try {
Files.deleteIfExists(dimensionTemplate);
} catch (final IOException e) {
FutureUtil.completedWithException(e);
}
return CompletableFuture.completedFuture(true);
}
use of net.minecraft.server.level.ServerLevel in project SpongeCommon by SpongePowered.
the class SpongeWorldManager method moveWorld.
@Override
public CompletableFuture<Boolean> moveWorld(final ResourceKey key, final ResourceKey movedKey) {
final net.minecraft.resources.ResourceKey<Level> registryKey = SpongeWorldManager.createRegistryKey(Objects.requireNonNull(key, "key"));
if (Level.OVERWORLD.equals(registryKey)) {
return CompletableFuture.completedFuture(false);
}
if (!this.worldExists(key)) {
return CompletableFuture.completedFuture(false);
}
if (this.worldExists(movedKey)) {
return CompletableFuture.completedFuture(false);
}
final ServerLevel loadedWorld = this.worlds.get(registryKey);
if (loadedWorld != null) {
try {
this.unloadWorld0(loadedWorld);
} catch (final IOException e) {
return FutureUtil.completedWithException(e);
}
}
final boolean isVanillaWorld = this.isVanillaWorld(key);
final String directoryName = this.getDirectoryName(key);
final Path originalDirectory = isVanillaWorld ? this.defaultWorldDirectory.resolve(directoryName) : this.customWorldsDirectory.resolve(key.namespace()).resolve(key.value());
final boolean isVanillaMoveWorld = this.isVanillaWorld(movedKey);
final String moveDirectoryName = this.getDirectoryName(movedKey);
final Path moveDirectory = isVanillaMoveWorld ? this.defaultWorldDirectory.resolve(moveDirectoryName) : this.customWorldsDirectory.resolve(key.namespace()).resolve(key.value());
try {
Files.createDirectories(moveDirectory);
Files.move(originalDirectory, moveDirectory, StandardCopyOption.REPLACE_EXISTING);
} catch (final IOException e) {
return FutureUtil.completedWithException(e);
}
final Path configFile = SpongeCommon.spongeConfigDirectory().resolve(Launch.instance().id()).resolve("worlds").resolve(key.namespace()).resolve(key.value() + ".conf");
final Path copiedConfigFile = SpongeCommon.spongeConfigDirectory().resolve(Launch.instance().id()).resolve("worlds").resolve(movedKey.namespace()).resolve(movedKey.value() + ".conf");
try {
Files.createDirectories(copiedConfigFile.getParent());
Files.move(configFile, copiedConfigFile, StandardCopyOption.REPLACE_EXISTING);
} catch (final IOException e) {
return FutureUtil.completedWithException(e);
}
final Path dimensionTemplate = this.getDataPackFile(key);
final Path copiedDimensionTemplate = this.getDataPackFile(movedKey);
try {
Files.createDirectories(copiedDimensionTemplate.getParent());
Files.move(dimensionTemplate, copiedDimensionTemplate, StandardCopyOption.REPLACE_EXISTING);
} catch (final IOException e) {
FutureUtil.completedWithException(e);
}
return CompletableFuture.completedFuture(true);
}
use of net.minecraft.server.level.ServerLevel in project SpongeCommon by SpongePowered.
the class ServerLevelMixin_Tracker method shadow$addBlockEntity.
@SuppressWarnings({ "ConstantConditions", "RedundantCast" })
@Override
public boolean shadow$addBlockEntity(final net.minecraft.world.level.block.entity.BlockEntity tileEntity) {
if (this.bridge$isFake() || PhaseTracker.SERVER.getSidedThread() != Thread.currentThread()) {
// out whoever is trying to remove tile entities asynchronously....
return super.shadow$addBlockEntity(tileEntity);
}
// Otherwise, let's go on and check if we're recording transactions,
// and if so, log the tile entity removal (may associate with an existing transaction,
// or create a new transaction.
final PhaseContext<@NonNull ?> current = PhaseTracker.SERVER.getPhaseContext();
if (current.doesBlockEventTracking()) {
final BlockPos immutable = tileEntity.getBlockPos().immutable();
if (tileEntity.getLevel() != (ServerLevel) (Object) this) {
tileEntity.setLevelAndPosition((ServerLevel) (Object) this, immutable);
}
final ChunkAccess iChunk = this.shadow$getChunk(immutable.getX() >> 4, immutable.getZ() >> 4, ChunkStatus.FULL, false);
if (!(iChunk instanceof LevelChunk)) {
return super.shadow$addBlockEntity(tileEntity);
}
final LevelChunk chunk = this.shadow$getChunkAt(immutable);
if (current.getTransactor().logTileAddition(tileEntity, () -> (ServerLevel) (Object) this, chunk)) {
final TileEntityPipeline pipeline = TileEntityPipeline.kickOff((ServerLevel) (Object) this, immutable).addEffect(AddTileEntityToWorldWhileProcessingEffect.getInstance()).addEffect(AddTileEntityToLoadedListInWorldEffect.getInstance()).addEffect(AddTileEntityToTickableListEffect.getInstance()).addEffect(TileOnLoadDuringAddToWorldEffect.getInstance()).build();
return pipeline.processEffects(current, new PipelineCursor(tileEntity.getBlockState(), 0, immutable, tileEntity, (Entity) null, Constants.World.DEFAULT_BLOCK_CHANGE_LIMIT));
}
}
return super.shadow$addBlockEntity(tileEntity);
}
use of net.minecraft.server.level.ServerLevel in project SpongeCommon by SpongePowered.
the class ServerLevelMixin_Tracker method shadow$setBlockEntity.
@SuppressWarnings({ "RedundantCast", "ConstantConditions" })
@Override
public void shadow$setBlockEntity(final BlockPos pos, final net.minecraft.world.level.block.entity.@Nullable BlockEntity proposed) {
final BlockPos immutable = pos.immutable();
if (this.bridge$isFake() || PhaseTracker.SERVER.getSidedThread() != Thread.currentThread()) {
// If we're fake or not on the server thread, well, we could effectively call
// out whoever is trying to remove tile entities asynchronously....
super.shadow$setBlockEntity(pos, proposed);
return;
}
if (proposed != null) {
if (proposed.getLevel() != (ServerLevel) (Object) this) {
proposed.setLevelAndPosition((ServerLevel) (Object) this, immutable);
} else {
proposed.setPosition(pos);
}
}
// Otherwise, let's go on and check if we're recording transactions,
// and if so, log the tile entity removal (may associate with an existing transaction,
// or create a new transaction.
final PhaseContext<@NonNull ?> current = PhaseTracker.SERVER.getPhaseContext();
if (current.doesBlockEventTracking()) {
final net.minecraft.world.level.block.entity.@Nullable BlockEntity existing = this.shadow$getChunkAt(immutable).getBlockEntity(immutable);
if (current.getTransactor().logTileReplacement(immutable, existing, proposed, () -> (ServerLevel) (Object) this)) {
final TileEntityPipeline pipeline = TileEntityPipeline.kickOff((ServerLevel) (Object) this, immutable).addEffect(RemoveProposedTileEntitiesDuringSetIfWorldProcessingEffect.getInstance()).addEffect(ReplaceTileEntityInWorldEffect.getInstance()).build();
pipeline.processEffects(current, new PipelineCursor(proposed.getBlockState(), 0, immutable, proposed, (Entity) null, Constants.World.DEFAULT_BLOCK_CHANGE_LIMIT));
return;
}
}
super.shadow$setBlockEntity(immutable, proposed);
}
Aggregations