use of net.minecraft.server.level.ServerLevel in project SpongeCommon by SpongePowered.
the class TransactionSink method logBlockDrops.
@SuppressWarnings("ConstantConditions")
default EffectTransactor logBlockDrops(final Level serverWorld, final BlockPos pos, final BlockState state, @Nullable final BlockEntity tileEntity) {
final WeakReference<ServerLevel> worldRef = new WeakReference<>((ServerLevel) serverWorld);
final Supplier<ServerLevel> worldSupplier = () -> Objects.requireNonNull(worldRef.get(), "ServerWorld dereferenced");
final SpongeBlockSnapshot original = TrackingUtil.createPooledSnapshot(state, pos, BlockChangeFlags.NONE, Constants.World.DEFAULT_BLOCK_CHANGE_LIMIT, tileEntity, worldSupplier, Optional::empty, Optional::empty);
original.blockChange = BlockChange.MODIFY;
final PrepareBlockDropsTransaction transaction = new PrepareBlockDropsTransaction(pos, state, original);
this.logTransaction(transaction);
return this.pushEffect(new ResultingTransactionBySideEffect(PrepareBlockDrops.getInstance()));
}
use of net.minecraft.server.level.ServerLevel in project SpongeCommon by SpongePowered.
the class TransactionSink method logEntitySpawn.
@SuppressWarnings("ConstantConditions")
default void logEntitySpawn(final PhaseContext<@NonNull ?> current, final TrackedWorldBridge serverWorld, final Entity entityIn) {
final WeakReference<ServerLevel> worldRef = new WeakReference<>((ServerLevel) serverWorld);
final Supplier<ServerLevel> worldSupplier = () -> Objects.requireNonNull(worldRef.get(), "ServerWorld dereferenced");
final Supplier<SpawnType> contextualType = current.getSpawnTypeForTransaction(entityIn);
final SpawnEntityTransaction transaction = new SpawnEntityTransaction(worldSupplier, entityIn, contextualType);
this.logTransaction(transaction);
}
use of net.minecraft.server.level.ServerLevel in project SpongeCommon by SpongePowered.
the class SpongeWorldManager method loadSpawnChunksAsync.
private CompletableFuture<ServerLevel> loadSpawnChunksAsync(final ServerLevel world) {
final BlockPos spawnPoint = world.getSharedSpawnPos();
final ChunkPos chunkPos = new ChunkPos(spawnPoint);
final ServerChunkCache serverChunkProvider = world.getChunkSource();
serverChunkProvider.getLightEngine().setTaskPerBatch(500);
final int borderRadius = 11;
final int diameter = ((borderRadius - 1) * 2) + 1;
final int spawnChunks = diameter * diameter;
serverChunkProvider.addRegionTicket(SpongeWorldManager.SPAWN_CHUNKS, chunkPos, borderRadius, world.dimension().location());
final CompletableFuture<ServerLevel> generationFuture = new CompletableFuture<>();
Sponge.asyncScheduler().submit(Task.builder().plugin(Launch.instance().platformPlugin()).execute(task -> {
if (serverChunkProvider.getTickingGenerated() >= spawnChunks) {
Sponge.server().scheduler().submit(Task.builder().plugin(Launch.instance().platformPlugin()).execute(() -> generationFuture.complete(world)).build());
// Notify the future that we are done
// And cancel this task
task.cancel();
MinecraftServerAccessor.accessor$LOGGER().info("Done preparing start region for world '{}' ({})", world.dimension().location(), RegistryTypes.WORLD_TYPE.get().valueKey((WorldType) world.dimensionType()));
}
}).interval(10, TimeUnit.MILLISECONDS).build());
return generationFuture.thenApply(v -> {
this.updateForcedChunks(world, serverChunkProvider);
serverChunkProvider.getLightEngine().setTaskPerBatch(5);
// Sponge Start - Release the chunk ticket if spawn is not set to be kept loaded...
if (!((PrimaryLevelDataBridge) world.getLevelData()).bridge$performsSpawnLogic()) {
serverChunkProvider.removeRegionTicket(SpongeWorldManager.SPAWN_CHUNKS, chunkPos, 11, world.dimension().location());
}
return world;
});
}
use of net.minecraft.server.level.ServerLevel in project SpongeCommon by SpongePowered.
the class SpongeWorldManager method loadWorld0.
private CompletableFuture<org.spongepowered.api.world.server.ServerWorld> loadWorld0(final net.minecraft.resources.ResourceKey<Level> registryKey, final LevelStem template, final WorldGenSettings generatorSettings) {
final PrimaryLevelData defaultLevelData = (PrimaryLevelData) this.server.getWorldData();
final LevelSettings defaultLevelSettings = ((PrimaryLevelDataAccessor) defaultLevelData).accessor$settings();
final LevelStemBridge templateBridge = (LevelStemBridge) (Object) template;
final ResourceKey worldKey = ((ResourceKeyBridge) templateBridge).bridge$getKey();
final WorldType worldType = (WorldType) template.type();
final ResourceKey worldTypeKey = RegistryTypes.WORLD_TYPE.get().valueKey((WorldType) template.type());
MinecraftServerAccessor.accessor$LOGGER().info("Loading world '{}' ({})", worldKey, worldTypeKey);
final String directoryName = this.getDirectoryName(worldKey);
final boolean isVanillaSubLevel = this.isVanillaSubWorld(directoryName);
final LevelStorageSource.LevelStorageAccess storageSource;
try {
if (isVanillaSubLevel) {
storageSource = LevelStorageSource.createDefault(this.defaultWorldDirectory).createAccess(directoryName);
} else {
storageSource = LevelStorageSource.createDefault(this.customWorldsDirectory).createAccess(worldKey.namespace() + File.separator + worldKey.value());
}
} catch (final IOException e) {
e.printStackTrace();
return FutureUtil.completedWithException(new RuntimeException(String.format("Failed to create level data for world '%s'!", worldKey), e));
}
PrimaryLevelData levelData;
levelData = (PrimaryLevelData) storageSource.getDataTag((DynamicOps<Tag>) BootstrapProperties.worldSettingsAdapter, defaultLevelSettings.getDataPackConfig());
if (levelData == null) {
final LevelSettings levelSettings;
final WorldGenSettings generationSettings;
if (this.server.isDemo()) {
levelSettings = MinecraftServer.DEMO_SETTINGS;
generationSettings = WorldGenSettings.demoSettings(BootstrapProperties.registries);
} else {
levelSettings = new LevelSettings(directoryName, (GameType) (Object) BootstrapProperties.gameMode.get(Sponge.game()), templateBridge.bridge$hardcore().orElse(BootstrapProperties.hardcore), (Difficulty) (Object) BootstrapProperties.difficulty.get(Sponge.game()), templateBridge.bridge$commands().orElse(BootstrapProperties.commands), new GameRules(), defaultLevelData.getDataPackConfig());
generationSettings = generatorSettings;
}
levelData = new PrimaryLevelData(levelSettings, generationSettings, Lifecycle.stable());
}
((PrimaryLevelDataBridge) levelData).bridge$populateFromDimension(template);
final InheritableConfigHandle<WorldConfig> configAdapter = SpongeGameConfigs.createWorld(worldTypeKey, worldKey);
((PrimaryLevelDataBridge) levelData).bridge$configAdapter(configAdapter);
levelData.setModdedInfo(this.server.getServerModName(), this.server.getModdedStatus().isPresent());
final boolean isDebugGeneration = levelData.worldGenSettings().isDebug();
final long seed = BiomeManager.obfuscateSeed(levelData.worldGenSettings().seed());
final ChunkProgressListener chunkStatusListener = ((MinecraftServerAccessor) this.server).accessor$progressListenerFactory().create(11);
final ServerLevel world = new ServerLevel(this.server, ((MinecraftServerAccessor) this.server).accessor$executor(), storageSource, levelData, registryKey, (DimensionType) worldType, chunkStatusListener, template.generator(), isDebugGeneration, seed, ImmutableList.of(), true);
this.worlds.put(registryKey, world);
return SpongeCommon.asyncScheduler().submit(() -> this.prepareWorld(world, isDebugGeneration)).thenApply(w -> {
((MinecraftServerAccessor) this.server).invoker$forceDifficulty();
return w;
}).thenCompose(w -> this.postWorldLoad(w, false)).thenApply(w -> (org.spongepowered.api.world.server.ServerWorld) w);
}
use of net.minecraft.server.level.ServerLevel in project SpongeCommon by SpongePowered.
the class SpongeWorldManager method copyWorld.
@Override
public CompletableFuture<Boolean> copyWorld(final ResourceKey key, final ResourceKey copyKey) {
final net.minecraft.resources.ResourceKey<Level> registryKey = SpongeWorldManager.createRegistryKey(Objects.requireNonNull(key, "key"));
final net.minecraft.resources.ResourceKey<Level> copyRegistryKey = SpongeWorldManager.createRegistryKey(Objects.requireNonNull(copyKey, "copyKey"));
if (Level.OVERWORLD.equals(copyRegistryKey)) {
return CompletableFuture.completedFuture(false);
}
if (!this.worldExists(key)) {
return CompletableFuture.completedFuture(false);
}
if (this.worldExists(copyKey)) {
return CompletableFuture.completedFuture(false);
}
final ServerLevel loadedWorld = this.worlds.get(registryKey);
boolean disableLevelSaving = false;
if (loadedWorld != null) {
disableLevelSaving = loadedWorld.noSave;
loadedWorld.save(null, true, loadedWorld.noSave);
loadedWorld.noSave = true;
}
final boolean isDefaultWorld = this.isDefaultWorld(key);
final boolean isVanillaWorld = this.isVanillaWorld(key);
final String directoryName = this.getDirectoryName(key);
final Path originalDirectory = isDefaultWorld ? this.defaultWorldDirectory : isVanillaWorld ? this.defaultWorldDirectory.resolve(directoryName) : this.customWorldsDirectory.resolve(key.namespace()).resolve(key.value());
final boolean isVanillaCopyWorld = this.isVanillaWorld(copyKey);
final String copyDirectoryName = this.getDirectoryName(copyKey);
final Path copyDirectory = isVanillaCopyWorld ? this.defaultWorldDirectory.resolve(copyDirectoryName) : this.customWorldsDirectory.resolve(copyKey.namespace()).resolve(copyKey.value());
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;
}
// 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;
}
final Path relativize = originalDirectory.relativize(dir);
final Path directory = copyDirectory.resolve(relativize);
Files.createDirectories(directory);
return FileVisitResult.CONTINUE;
}
@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;
}
});
} catch (final IOException e) {
// Bail the whole deal if we hit IO problems!
try {
Files.deleteIfExists(copyDirectory);
} catch (final IOException ignore) {
}
return FutureUtil.completedWithException(e);
}
if (loadedWorld != null) {
loadedWorld.noSave = disableLevelSaving;
}
final Path dimensionTemplate = this.getDataPackFile(key);
final Path copiedDimensionTemplate = this.getDataPackFile(copyKey);
try {
Files.createDirectories(copiedDimensionTemplate.getParent());
Files.copy(dimensionTemplate, copiedDimensionTemplate);
} catch (final IOException e) {
FutureUtil.completedWithException(e);
}
final JsonObject fixedObject;
try (final InputStream stream = Files.newInputStream(copiedDimensionTemplate);
final InputStreamReader reader = new InputStreamReader(stream)) {
final JsonParser parser = new JsonParser();
final JsonElement element = parser.parse(reader);
final JsonObject root = element.getAsJsonObject();
final JsonObject spongeData = root.getAsJsonObject("#sponge");
spongeData.remove("unique_id");
fixedObject = root;
} catch (final IOException e) {
return FutureUtil.completedWithException(e);
}
if (fixedObject != null) {
try (final BufferedWriter writer = Files.newBufferedWriter(copiedDimensionTemplate)) {
writer.write(fixedObject.toString());
} catch (final IOException e) {
FutureUtil.completedWithException(e);
}
}
return CompletableFuture.completedFuture(true);
}
Aggregations