/* * WorldEdit, a Minecraft world manipulation toolkit * Copyright (C) sk89q * Copyright (C) WorldEdit team and contributors * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program. If not, see . */ package com.sk89q.worldedit.world; import com.fastasyncworldedit.core.queue.IChunkCache; import com.fastasyncworldedit.core.queue.IChunkGet; import com.fastasyncworldedit.core.queue.implementation.packet.ChunkPacket; import com.sk89q.worldedit.EditSession; import com.sk89q.worldedit.MaxChangedBlocksException; import com.sk89q.worldedit.WorldEditException; import com.sk89q.worldedit.blocks.BaseItem; import com.sk89q.worldedit.blocks.BaseItemStack; import com.sk89q.worldedit.entity.Player; import com.sk89q.worldedit.extension.platform.Platform; import com.sk89q.worldedit.extent.Extent; import com.sk89q.worldedit.function.mask.Mask; import com.sk89q.worldedit.internal.util.DeprecationUtil; import com.sk89q.worldedit.internal.util.NonAbstractForCompatibility; import com.sk89q.worldedit.math.BlockVector2; import com.sk89q.worldedit.math.BlockVector3; import com.sk89q.worldedit.math.Vector3; import com.sk89q.worldedit.regions.Region; import com.sk89q.worldedit.registry.Keyed; import com.sk89q.worldedit.util.Direction; import com.sk89q.worldedit.util.SideEffect; import com.sk89q.worldedit.util.SideEffectSet; import com.sk89q.worldedit.util.TreeGenerator; import com.sk89q.worldedit.world.biome.BiomeType; import com.sk89q.worldedit.world.block.BlockState; import com.sk89q.worldedit.world.block.BlockStateHolder; import com.sk89q.worldedit.world.block.BlockType; import com.sk89q.worldedit.world.weather.WeatherType; import javax.annotation.Nullable; import java.nio.file.Path; import java.util.Collection; import java.util.Collections; import java.util.Locale; import java.util.Set; /** * Represents a world (dimension). */ //FAWE start - IChunkCache public interface World extends Extent, Keyed, IChunkCache { //FAWE end /** * Get the name of the world. This will error if world has been unloaded by the server. * * @return a name for the world */ String getName(); //FAWE start - allow history to read an unloaded world's name /** * Get the name of the world. If the world referenced has been unloaded, this will still return the name. * * @return a name for the world * @since 2.2.0 */ String getNameUnsafe(); //FAWE end /** * Get the folder in which this world is stored. May return null if unknown * or if this world is not serialized to disk. * * @return world storage path */ @Nullable Path getStoragePath(); /** * Get the minimum Y. * * @return the minimum Y */ int getMinY(); /** * Get the maximum Y. * * @return the maximum Y */ int getMaxY(); /** * Create a mask that matches all liquids. * *

Implementations should override this so that custom liquids * are supported.

* * @return a mask */ Mask createLiquidMask(); /** * Use the given item on the block at the given location on the given side. * * @param item The item * @param face The face * @return Whether it succeeded */ boolean useItem(BlockVector3 position, BaseItem item, Direction face); /** * Similar to {@link Extent#setBlock(BlockVector3, BlockStateHolder)} but a * {@code notifyAndLight} parameter indicates whether adjacent blocks * should be notified that changes have been made and lighting operations * should be executed. * *

If it's not possible to skip lighting, or if it's not possible to * avoid notifying adjacent blocks, then attempt to meet the * specification as best as possible.

* *

On implementations where the world is not simulated, the * {@code notifyAndLight} parameter has no effect either way.

* * @param position position of the block * @param block block to set * @param notifyAndLight true to to notify and light * @return true if the block was successfully set (return value may not be accurate) */ @Deprecated default > boolean setBlock(BlockVector3 position, B block, boolean notifyAndLight) throws WorldEditException { return setBlock(position, block, notifyAndLight ? SideEffectSet.defaults() : SideEffectSet.none()); } /** * Similar to {@link Extent#setBlock(BlockVector3, BlockStateHolder)} but a * {@code sideEffects} parameter indicates which side effects should be applied * to the block. This includes block updates, lighting, and others. See {@link SideEffect} * for a full list. * *

Not all implementations support all side effects. Use * {@link Platform#getSupportedSideEffects()} for a list of supported side effects. * Non-supported side effects will be ignored.

* * @param position position of the block * @param block block to set * @param sideEffects which side effects to perform * @return true if the block was successfully set (return value may not be accurate) */ > boolean setBlock(BlockVector3 position, B block, SideEffectSet sideEffects) throws WorldEditException; /** * Notifies the simulation that the block at the given location has * been changed and it must be re-lighted (and issue other events). * * @param position position of the block * @param previousType the type of the previous block that was there * @return true if the block was successfully notified */ @Deprecated default boolean notifyAndLightBlock(BlockVector3 position, BlockState previousType) throws WorldEditException { return !applySideEffects(position, previousType, SideEffectSet.defaults()).isEmpty(); } /** * Applies a set of side effects on the given block. * * @param position position of the block * @param previousType the type of the previous block that was there * @param sideEffectSet which side effects to perform * @return a set of side effects that were applied */ Set applySideEffects(BlockVector3 position, BlockState previousType, SideEffectSet sideEffectSet) throws WorldEditException; /** * Get the light level at the given block. * * @param position the position * @return the light level (0-15) */ default int getBlockLightLevel(BlockVector3 position) { return getBlock(position).getMaterial().getLightValue(); } /** * Clear a chest's contents. * * @param position the position * @return true if the container was cleared */ boolean clearContainerBlockContents(BlockVector3 position); /** * Drop an item at the given position. * * @param position the position * @param item the item to drop * @param count the number of individual stacks to drop (number of item entities) */ void dropItem(Vector3 position, BaseItemStack item, int count); /** * Drop one stack of the item at the given position. * * @param position the position * @param item the item to drop * @see #dropItem(Vector3, BaseItemStack, int) shortcut method to specify the number of stacks */ void dropItem(Vector3 position, BaseItemStack item); /** * Simulate a block being mined at the given position. * * @param position the position */ void simulateBlockMine(BlockVector3 position); //FAWE start /** * Return items that may drop by destroying this block. * * @param position the position * @return Block drops */ default Collection getBlockDrops(BlockVector3 position) { return Collections.emptyList(); } //FAWE end /** * Gets whether the given {@link BlockState} can be placed here. * * @param position The position * @param blockState The blockstate * @return If it can be placed */ default boolean canPlaceAt(BlockVector3 position, BlockState blockState) { return true; } /** * Regenerate an area. * * @param region the region * @param editSession the {@link EditSession} * @return true if re-generation was successful */ default boolean regenerate(Region region, EditSession editSession) { return regenerate(region, editSession, RegenOptions.builder().build()); } /** * Regenerate an area. * * @param region the region * @param extent the {@link Extent} * @return true if re-generation was successful */ default boolean regenerate(Region region, Extent extent) { return regenerate(region, extent, RegenOptions.builder().build()); } /** * Regenerate an area. * * @param region the region * @param extent the {@link Extent} * @param options the regeneration options * @return true if regeneration was successful */ @NonAbstractForCompatibility( delegateName = "regenerate", delegateParams = {Region.class, EditSession.class} ) default boolean regenerate(Region region, Extent extent, RegenOptions options) { DeprecationUtil.checkDelegatingOverride(getClass()); if (extent instanceof EditSession) { return regenerate(region, (EditSession) extent); } throw new UnsupportedOperationException("This World class (" + getClass().getName() + ") does not implement the general Extent variant of this method"); } /** * Generate a tree at the given position. * * @param type the tree type * @param editSession the {@link EditSession} * @param position the position * @return true if generation was successful * @throws MaxChangedBlocksException thrown if too many blocks were changed */ boolean generateTree(TreeGenerator.TreeType type, EditSession editSession, BlockVector3 position) throws MaxChangedBlocksException; /** * Load the chunk at the given position if it isn't loaded. * * @param position the position */ void checkLoadedChunk(BlockVector3 position); /** * Fix the given chunks after fast mode was used. * *

Fast mode makes calls to {@link #setBlock(BlockVector3, BlockStateHolder, boolean)} * with {@code false} for the {@code notifyAndLight} parameter, which * may causes lighting errors to accumulate. Use of this method, if * it is implemented by the underlying world, corrects those lighting * errors and may trigger block change notifications.

* * @param chunks a list of chunk coordinates to fix */ void fixAfterFastMode(Iterable chunks); /** * Relight the given chunks if possible. * * @param chunks a list of chunk coordinates to fix */ void fixLighting(Iterable chunks); /** * Play the given effect. * * @param position the position * @param type the effect type * @param data the effect data * @return true if the effect was played */ boolean playEffect(Vector3 position, int type, int data); //FAWE start - allow block break effect of non-legacy blocks /** * Play a block break effect. * * @param position the position * @param type the effect block type * @return true if the effect was played */ boolean playBlockBreakEffect(Vector3 position, BlockType type); //FAWE end /** * Queue a block break effect. * * @param server the server * @param position the position * @param blockType the block type * @param priority the priority * @return true if the effect was played */ boolean queueBlockBreakEffect(Platform server, BlockVector3 position, BlockType blockType, double priority); /** * Gets the weather type of the world. * * @return The weather */ WeatherType getWeather(); /** * Gets the remaining weather duration. * * @return The weather duration */ long getRemainingWeatherDuration(); /** * Sets the weather type of the world. * * @param weatherType The weather type */ void setWeather(WeatherType weatherType); /** * Sets the weather type of the world. * * @param weatherType The weather type * @param duration The duration of the weather */ void setWeather(WeatherType weatherType, long duration); /** * Gets the spawn position of this world. * * @return The spawn position */ BlockVector3 getSpawnPosition(); @Override boolean equals(Object other); @Override int hashCode(); //FAWE start @Override default boolean isWorld() { return true; } @Override default String getId() { return getName().replace(" ", "_").toLowerCase(Locale.ROOT); } /** * Refresh a specific chunk. * Note: only 0 is guaranteed to send all tiles / entities * Note: Only 65535 is guaranteed to send all blocks */ void refreshChunk(final int chunkX, final int chunkZ); @Override IChunkGet get(int x, int z); /** * Send a fake chunk to a player. * * @param player may be null to send to everyone * @param packet the chunk packet */ void sendFakeChunk(@Nullable Player player, ChunkPacket packet); @Override @Nullable default BiomeType getBiome(BlockVector3 position) { return null; } @Override default boolean setBiome(int x, int y, int z, BiomeType biome) { return false; } @Override default boolean setBiome(BlockVector3 position, BiomeType biome) { return false; } void flush(); //FAWE end }