2010-10-02 21:52:42 +00:00
/ *
2014-03-31 23:55:58 +00:00
* WorldEdit , a Minecraft world manipulation toolkit
* Copyright ( C ) sk89q < http : //www.sk89q.com>
* Copyright ( C ) WorldEdit team and contributors
2010-10-02 21:52:42 +00:00
*
2020-08-25 01:31:47 +00:00
* 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
2010-10-02 21:52:42 +00:00
* ( at your option ) any later version .
*
2020-08-25 01:31:47 +00:00
* 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 .
2010-10-02 21:52:42 +00:00
*
2020-08-25 01:31:47 +00:00
* You should have received a copy of the GNU General Public License
* along with this program . If not , see < https : //www.gnu.org/licenses/>.
2011-01-01 18:33:18 +00:00
* /
2014-03-31 23:55:58 +00:00
2011-01-01 01:06:42 +00:00
package com.sk89q.worldedit ;
2021-08-17 11:07:48 +00:00
import com.fastasyncworldedit.core.Fawe ;
2021-07-01 20:16:25 +00:00
import com.fastasyncworldedit.core.FaweCache ;
import com.fastasyncworldedit.core.configuration.Caption ;
import com.fastasyncworldedit.core.configuration.Settings ;
2021-07-23 15:48:51 +00:00
import com.fastasyncworldedit.core.extent.FaweRegionExtent ;
2021-07-24 15:34:05 +00:00
import com.fastasyncworldedit.core.extent.PassthroughExtent ;
2021-07-23 15:48:51 +00:00
import com.fastasyncworldedit.core.extent.ProcessedWEExtent ;
import com.fastasyncworldedit.core.extent.ResettableExtent ;
import com.fastasyncworldedit.core.extent.SingleRegionExtent ;
import com.fastasyncworldedit.core.extent.SourceMaskExtent ;
2021-07-24 15:34:05 +00:00
import com.fastasyncworldedit.core.extent.clipboard.WorldCopyClipboard ;
import com.fastasyncworldedit.core.extent.processor.lighting.NullRelighter ;
import com.fastasyncworldedit.core.extent.processor.lighting.Relighter ;
2021-07-23 15:48:51 +00:00
import com.fastasyncworldedit.core.function.SurfaceRegionFunction ;
2021-07-24 15:34:05 +00:00
import com.fastasyncworldedit.core.function.generator.GenBase ;
import com.fastasyncworldedit.core.function.generator.OreGen ;
import com.fastasyncworldedit.core.function.generator.SchemGen ;
import com.fastasyncworldedit.core.function.mask.BlockMaskBuilder ;
import com.fastasyncworldedit.core.function.mask.MaskUnion ;
2021-07-23 15:48:51 +00:00
import com.fastasyncworldedit.core.function.mask.ResettableMask ;
2021-07-24 15:34:05 +00:00
import com.fastasyncworldedit.core.function.mask.SingleBlockTypeMask ;
import com.fastasyncworldedit.core.function.mask.WallMakeMask ;
2021-07-23 15:48:51 +00:00
import com.fastasyncworldedit.core.function.pattern.ExistingPattern ;
2021-07-24 15:34:05 +00:00
import com.fastasyncworldedit.core.function.visitor.DirectionalVisitor ;
import com.fastasyncworldedit.core.history.changeset.AbstractChangeSet ;
import com.fastasyncworldedit.core.history.changeset.BlockBagChangeSet ;
import com.fastasyncworldedit.core.math.LocalBlockVectorSet ;
import com.fastasyncworldedit.core.math.MutableBlockVector2 ;
import com.fastasyncworldedit.core.math.MutableBlockVector3 ;
2021-09-18 16:42:58 +00:00
import com.fastasyncworldedit.core.math.MutableVector3 ;
import com.fastasyncworldedit.core.math.random.SimplexNoise ;
2021-07-24 15:34:05 +00:00
import com.fastasyncworldedit.core.object.FaweLimit ;
2021-08-17 14:38:47 +00:00
import com.fastasyncworldedit.core.queue.implementation.preloader.Preloader ;
2021-07-24 15:34:05 +00:00
import com.fastasyncworldedit.core.regions.RegionWrapper ;
2021-07-01 20:16:25 +00:00
import com.fastasyncworldedit.core.util.ExtentTraverser ;
import com.fastasyncworldedit.core.util.MaskTraverser ;
import com.fastasyncworldedit.core.util.MathMan ;
import com.fastasyncworldedit.core.util.TaskManager ;
2021-07-24 15:34:05 +00:00
import com.fastasyncworldedit.core.util.task.RunnableVal ;
2020-07-03 17:52:55 +00:00
import com.sk89q.worldedit.entity.BaseEntity ;
2020-07-01 17:28:38 +00:00
import com.sk89q.worldedit.entity.Entity ;
2019-09-14 03:05:16 +00:00
import com.sk89q.worldedit.entity.Player ;
2014-04-03 01:57:25 +00:00
import com.sk89q.worldedit.event.extent.EditSessionEvent ;
2021-09-19 20:02:41 +00:00
import com.sk89q.worldedit.extension.platform.Actor ;
2018-08-12 14:03:07 +00:00
import com.sk89q.worldedit.extent.AbstractDelegateExtent ;
2014-04-23 07:33:00 +00:00
import com.sk89q.worldedit.extent.ChangeSetExtent ;
import com.sk89q.worldedit.extent.Extent ;
import com.sk89q.worldedit.extent.MaskingExtent ;
2021-09-19 20:02:41 +00:00
import com.sk89q.worldedit.extent.TracingExtent ;
2021-07-16 09:43:15 +00:00
import com.sk89q.worldedit.extent.clipboard.Clipboard ;
2014-04-23 07:33:00 +00:00
import com.sk89q.worldedit.extent.inventory.BlockBag ;
2014-04-03 02:08:50 +00:00
import com.sk89q.worldedit.extent.inventory.BlockBagExtent ;
2014-04-23 07:33:00 +00:00
import com.sk89q.worldedit.extent.world.SurvivalModeExtent ;
2019-09-05 05:50:14 +00:00
import com.sk89q.worldedit.extent.world.WatchdogTickingExtent ;
2014-03-28 23:49:01 +00:00
import com.sk89q.worldedit.function.GroundFunction ;
2014-03-28 23:15:40 +00:00
import com.sk89q.worldedit.function.block.BlockReplace ;
2014-03-30 01:32:10 +00:00
import com.sk89q.worldedit.function.block.Naturalizer ;
2020-12-16 19:23:41 +00:00
import com.sk89q.worldedit.function.block.SnowSimulator ;
2019-03-21 01:05:11 +00:00
import com.sk89q.worldedit.function.generator.ForestGenerator ;
2014-03-28 23:15:40 +00:00
import com.sk89q.worldedit.function.generator.GardenPatchGenerator ;
2020-07-03 12:49:17 +00:00
import com.sk89q.worldedit.function.mask.BlockStateMask ;
2019-07-06 00:46:48 +00:00
import com.sk89q.worldedit.function.mask.BlockTypeMask ;
import com.sk89q.worldedit.function.mask.BoundedHeightMask ;
import com.sk89q.worldedit.function.mask.ExistingBlockMask ;
import com.sk89q.worldedit.function.mask.Mask ;
import com.sk89q.worldedit.function.mask.MaskIntersection ;
import com.sk89q.worldedit.function.mask.Masks ;
import com.sk89q.worldedit.function.mask.NoiseFilter2D ;
import com.sk89q.worldedit.function.mask.RegionMask ;
2018-06-19 07:03:09 +00:00
import com.sk89q.worldedit.function.operation.ChangeSetExecutor ;
import com.sk89q.worldedit.function.operation.ForwardExtentCopy ;
import com.sk89q.worldedit.function.operation.Operations ;
2018-06-15 05:41:37 +00:00
import com.sk89q.worldedit.function.pattern.Pattern ;
2019-06-12 21:12:12 +00:00
import com.sk89q.worldedit.function.pattern.WaterloggedRemover ;
2014-03-28 23:49:01 +00:00
import com.sk89q.worldedit.function.util.RegionOffset ;
2018-06-19 07:03:09 +00:00
import com.sk89q.worldedit.function.visitor.DownwardVisitor ;
2019-04-03 05:53:34 +00:00
import com.sk89q.worldedit.function.visitor.FlatRegionVisitor ;
2018-06-19 07:03:09 +00:00
import com.sk89q.worldedit.function.visitor.LayerVisitor ;
import com.sk89q.worldedit.function.visitor.NonRisingVisitor ;
import com.sk89q.worldedit.function.visitor.RecursiveVisitor ;
import com.sk89q.worldedit.function.visitor.RegionVisitor ;
2014-03-31 05:33:16 +00:00
import com.sk89q.worldedit.history.UndoContext ;
2014-03-31 23:55:58 +00:00
import com.sk89q.worldedit.history.changeset.ChangeSet ;
2019-11-19 22:07:30 +00:00
import com.sk89q.worldedit.internal.expression.EvaluationException ;
2014-04-23 07:33:00 +00:00
import com.sk89q.worldedit.internal.expression.Expression ;
import com.sk89q.worldedit.internal.expression.ExpressionException ;
2020-01-03 20:38:30 +00:00
import com.sk89q.worldedit.internal.expression.ExpressionTimeoutException ;
import com.sk89q.worldedit.internal.expression.LocalSlot.Variable ;
2021-03-29 13:29:16 +00:00
import com.sk89q.worldedit.internal.util.LogManagerCompat ;
2018-10-14 10:40:53 +00:00
import com.sk89q.worldedit.math.BlockVector2 ;
import com.sk89q.worldedit.math.BlockVector3 ;
2019-08-06 15:29:09 +00:00
import com.sk89q.worldedit.math.MathUtils ;
2020-12-16 19:23:41 +00:00
import com.sk89q.worldedit.math.Vector2 ;
2018-10-14 10:40:53 +00:00
import com.sk89q.worldedit.math.Vector3 ;
2014-03-30 19:13:45 +00:00
import com.sk89q.worldedit.math.interpolation.Interpolation ;
import com.sk89q.worldedit.math.interpolation.KochanekBartelsInterpolation ;
import com.sk89q.worldedit.math.interpolation.Node ;
2014-03-30 08:36:02 +00:00
import com.sk89q.worldedit.math.noise.RandomNoise ;
2014-03-30 10:08:56 +00:00
import com.sk89q.worldedit.math.transform.AffineTransform ;
2018-06-19 07:03:09 +00:00
import com.sk89q.worldedit.regions.CuboidRegion ;
2020-12-16 19:23:41 +00:00
import com.sk89q.worldedit.regions.CylinderRegion ;
2018-06-19 07:03:09 +00:00
import com.sk89q.worldedit.regions.EllipsoidRegion ;
import com.sk89q.worldedit.regions.FlatRegion ;
2021-01-10 14:59:21 +00:00
import com.sk89q.worldedit.regions.NullRegion ;
2018-06-19 07:03:09 +00:00
import com.sk89q.worldedit.regions.Region ;
2021-01-10 14:59:21 +00:00
import com.sk89q.worldedit.regions.RegionIntersection ;
2018-06-19 07:03:09 +00:00
import com.sk89q.worldedit.regions.Regions ;
2014-04-03 02:08:50 +00:00
import com.sk89q.worldedit.regions.shape.ArbitraryBiomeShape ;
import com.sk89q.worldedit.regions.shape.ArbitraryShape ;
import com.sk89q.worldedit.regions.shape.RegionShape ;
import com.sk89q.worldedit.regions.shape.WorldEditExpressionEnvironment ;
2021-07-16 09:43:15 +00:00
import com.sk89q.worldedit.session.ClipboardHolder ;
2018-06-19 07:03:09 +00:00
import com.sk89q.worldedit.util.Countable ;
2018-12-23 16:19:33 +00:00
import com.sk89q.worldedit.util.Direction ;
2020-07-03 17:52:55 +00:00
import com.sk89q.worldedit.util.Location ;
2020-03-08 06:09:36 +00:00
import com.sk89q.worldedit.util.SideEffectSet ;
2018-06-19 07:03:09 +00:00
import com.sk89q.worldedit.util.TreeGenerator ;
2021-09-19 20:02:41 +00:00
import com.sk89q.worldedit.util.collection.BlockMap ;
2014-04-03 01:57:25 +00:00
import com.sk89q.worldedit.util.eventbus.EventBus ;
2021-09-19 20:02:41 +00:00
import com.sk89q.worldedit.util.formatting.text.TextComponent ;
2014-04-05 09:59:38 +00:00
import com.sk89q.worldedit.world.World ;
2019-02-16 07:27:00 +00:00
import com.sk89q.worldedit.world.biome.BiomeType ;
2019-06-25 13:00:44 +00:00
import com.sk89q.worldedit.world.block.BaseBlock ;
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.block.BlockTypes ;
2019-11-20 00:11:54 +00:00
import com.sk89q.worldedit.world.registry.LegacyMapper ;
2021-03-29 13:29:16 +00:00
import org.apache.logging.log4j.Logger ;
2021-07-24 15:34:05 +00:00
2021-07-24 13:52:08 +00:00
import javax.annotation.Nonnull ;
import javax.annotation.Nullable ;
2020-02-06 00:43:50 +00:00
import java.io.IOException ;
2019-06-25 13:00:44 +00:00
import java.util.ArrayList ;
2019-07-18 06:56:57 +00:00
import java.util.Collection ;
2019-06-25 13:00:44 +00:00
import java.util.Collections ;
2020-07-03 12:49:17 +00:00
import java.util.HashMap ;
2019-07-18 06:56:57 +00:00
import java.util.HashSet ;
import java.util.Iterator ;
2021-09-19 20:02:41 +00:00
import java.util.LinkedHashSet ;
2019-06-25 13:00:44 +00:00
import java.util.List ;
import java.util.Map ;
import java.util.Set ;
2020-09-11 19:13:31 +00:00
import java.util.UUID ;
2021-09-18 16:42:58 +00:00
import java.util.concurrent.ThreadLocalRandom ;
2021-01-06 16:57:59 +00:00
import java.util.concurrent.atomic.AtomicInteger ;
2021-09-19 20:02:41 +00:00
import java.util.stream.Collectors ;
2020-07-14 02:50:59 +00:00
import static com.google.common.base.Preconditions.checkArgument ;
import static com.google.common.base.Preconditions.checkNotNull ;
2020-12-16 19:23:41 +00:00
import static com.sk89q.worldedit.function.block.SnowSimulator.snowy ;
2020-07-14 02:50:59 +00:00
import static com.sk89q.worldedit.regions.Regions.asFlatRegion ;
import static com.sk89q.worldedit.regions.Regions.maximumBlockY ;
import static com.sk89q.worldedit.regions.Regions.minimumBlockY ;
2018-08-12 14:03:07 +00:00
2010-10-02 21:52:42 +00:00
/ * *
2014-03-31 23:55:58 +00:00
* An { @link Extent } that handles history , { @link BlockBag } s , change limits ,
* block re - ordering , and much more . Most operations in WorldEdit use this class .
2019-04-02 22:21:02 +00:00
*
2014-07-29 14:57:45 +00:00
* < p > Most of the actual functionality is implemented with a number of other
2014-03-31 23:55:58 +00:00
* { @link Extent } s that are chained together . For example , history is logged
2014-07-29 14:57:45 +00:00
* using the { @link ChangeSetExtent } . < / p >
2010-10-02 21:52:42 +00:00
* /
2019-06-04 15:48:30 +00:00
@SuppressWarnings ( { " FieldCanBeLocal " } )
2021-07-23 15:48:51 +00:00
/ * FAWE start - extends PassthroughExtent > implements Extent
Make sure , that all edits go thru it , else history etc . can have issues .
PassthroughExtent has some for loops that then delegate to methods editsession overrides .
* /
2019-08-18 01:09:09 +00:00
public class EditSession extends PassthroughExtent implements AutoCloseable {
2021-07-23 15:48:51 +00:00
//FAWE end
2011-08-07 00:40:48 +00:00
2021-03-29 13:29:16 +00:00
private static final Logger LOGGER = LogManagerCompat . getLogger ( ) ;
2011-09-24 19:32:03 +00:00
2010-10-05 07:40:50 +00:00
/ * *
2018-12-23 16:19:33 +00:00
* Used by { @link EditSession # setBlock ( BlockVector3 , BlockStateHolder , Stage ) } to
2014-03-31 23:55:58 +00:00
* determine which { @link Extent } s should be bypassed .
2010-10-05 07:40:50 +00:00
* /
2019-04-03 11:28:57 +00:00
public enum Stage {
BEFORE_HISTORY ,
BEFORE_REORDER ,
BEFORE_CHANGE
}
2019-06-04 15:48:30 +00:00
/ * *
2020-10-05 17:41:41 +00:00
* Reorder mode for { @link EditSession # setReorderMode ( ReorderMode ) } . NOT FUNCTIONAL IN FAWE
2019-06-04 15:48:30 +00:00
*
2020-10-05 17:41:41 +00:00
* < p >
2019-06-04 15:48:30 +00:00
* MULTI_STAGE = Multi stage reorder , may not be great with mods .
* FAST = Use the fast mode . Good for mods .
* NONE = Place blocks without worrying about placement order .
2020-10-05 17:41:41 +00:00
* < / p >
2019-06-04 15:48:30 +00:00
* /
public enum ReorderMode {
MULTI_STAGE ( " multi " ) ,
FAST ( " fast " ) ,
NONE ( " none " ) ;
2020-04-23 16:07:01 +00:00
private final String displayName ;
2019-06-04 15:48:30 +00:00
ReorderMode ( String displayName ) {
this . displayName = displayName ;
}
public String getDisplayName ( ) {
return this . displayName ;
}
}
2019-11-21 07:57:32 +00:00
2020-01-03 20:38:30 +00:00
@SuppressWarnings ( " ProtectedField " )
protected final World world ;
2021-09-19 20:02:41 +00:00
private final @Nullable
Actor actor ;
2021-07-23 15:48:51 +00:00
//FAWE start
2019-07-18 06:56:57 +00:00
private final FaweLimit originalLimit ;
private final FaweLimit limit ;
2020-01-06 08:36:16 +00:00
private AbstractChangeSet changeSet ;
2019-10-23 04:23:52 +00:00
private boolean history ;
2018-08-12 14:03:07 +00:00
2021-07-23 15:48:51 +00:00
private final MutableBlockVector3 mutableBlockVector3 = new MutableBlockVector3 ( ) ;
2018-08-12 14:03:07 +00:00
2020-05-13 21:45:11 +00:00
private int changes = 0 ;
2019-07-18 06:56:57 +00:00
private final BlockBag blockBag ;
2011-09-24 19:32:03 +00:00
2020-04-23 16:07:01 +00:00
private final Extent bypassHistory ;
2021-07-23 15:48:51 +00:00
private final Extent bypassAll ;
2020-01-03 20:38:30 +00:00
2021-04-09 20:59:31 +00:00
private final int minY ;
2018-08-12 14:03:07 +00:00
private final int maxY ;
2021-07-23 15:48:51 +00:00
//FAWE end
2020-03-04 02:41:51 +00:00
private final List < WatchdogTickingExtent > watchdogExtents = new ArrayList < > ( 2 ) ;
2021-09-19 20:02:41 +00:00
@Nullable
private final List < TracingExtent > tracingExtents ;
2020-03-04 02:41:51 +00:00
2021-07-23 15:48:51 +00:00
//FAWE start
2021-01-11 19:29:16 +00:00
private final Relighter relighter ;
2021-01-09 21:27:55 +00:00
private final boolean wnaMode ;
2021-01-10 14:59:21 +00:00
@Nullable
private final Region [ ] allowedRegions ;
2021-09-19 20:02:41 +00:00
@Deprecated ( forRemoval = true )
2021-07-24 15:34:05 +00:00
public EditSession (
2021-09-19 20:02:41 +00:00
@Nonnull EventBus bus , World world , @Nullable Player actor ,
2021-07-24 15:34:05 +00:00
@Nullable FaweLimit limit , @Nullable AbstractChangeSet changeSet ,
@Nullable RegionWrapper [ ] allowedRegions , @Nullable Boolean autoQueue ,
@Nullable Boolean fastmode , @Nullable Boolean checkMemory , @Nullable Boolean combineStages ,
@Nullable BlockBag blockBag , @Nullable EditSessionEvent event
) {
2021-09-19 20:02:41 +00:00
this ( new EditSessionBuilder ( bus ) . world ( world ) . actor ( actor )
2021-07-24 15:34:05 +00:00
. limit ( limit )
. changeSet ( changeSet )
. allowedRegions ( allowedRegions )
2021-09-19 20:02:41 +00:00
. fastMode ( fastmode )
2021-07-24 15:34:05 +00:00
. checkMemory ( checkMemory )
. combineStages ( combineStages )
. blockBag ( blockBag )
. event ( event ) ) ;
2020-02-12 21:18:36 +00:00
}
2021-07-23 15:48:51 +00:00
//FAWE end
2020-08-18 19:48:31 +00:00
2020-02-12 21:18:36 +00:00
/ * *
* Construct the object with a maximum number of blocks and a block bag .
*
2021-07-24 15:34:05 +00:00
* @param eventBus the event bus
* @param world the world
2020-02-12 21:18:36 +00:00
* @param maxBlocks the maximum number of blocks that can be changed , or - 1 to use no limit
2021-07-24 15:34:05 +00:00
* @param blockBag an optional { @link BlockBag } to use , otherwise null
* @param event the event to call with the extent
2020-02-12 21:18:36 +00:00
* /
2021-07-23 15:48:51 +00:00
//FAWE start - EditSessionEvent
2021-09-19 20:02:41 +00:00
@Deprecated ( forRemoval = true )
2021-07-24 15:34:05 +00:00
public EditSession (
@Nonnull EventBus eventBus ,
World world ,
int maxBlocks ,
@Nullable BlockBag blockBag ,
EditSessionEvent event
) {
2020-02-12 21:18:36 +00:00
this ( eventBus , world , null , null , null , null , true , null , null , null , blockBag , event ) ;
2019-07-18 06:56:57 +00:00
}
2019-06-25 13:00:44 +00:00
2021-09-19 20:02:41 +00:00
EditSession ( EditSessionBuilder builder ) {
2019-07-18 06:56:57 +00:00
super ( builder . compile ( ) . getExtent ( ) ) ;
this . world = builder . getWorld ( ) ;
this . bypassHistory = builder . getBypassHistory ( ) ;
this . bypassAll = builder . getBypassAll ( ) ;
this . originalLimit = builder . getLimit ( ) ;
this . limit = builder . getLimit ( ) . copy ( ) ;
2021-09-19 20:02:41 +00:00
this . actor = builder . getActor ( ) ;
2020-01-03 20:38:30 +00:00
this . changeSet = builder . getChangeTask ( ) ;
2021-04-09 20:59:31 +00:00
this . minY = world . getMinY ( ) ;
2020-02-16 20:14:34 +00:00
this . maxY = world . getMaxY ( ) ;
2019-07-18 06:56:57 +00:00
this . blockBag = builder . getBlockBag ( ) ;
2020-01-03 20:38:30 +00:00
this . history = changeSet ! = null ;
2021-01-11 19:29:16 +00:00
this . relighter = builder . getRelighter ( ) ;
2021-01-09 21:27:55 +00:00
this . wnaMode = builder . isWNAMode ( ) ;
2021-09-19 20:02:41 +00:00
if ( builder . isTracing ( ) ) {
this . tracingExtents = new ArrayList < > ( ) ;
checkNotNull ( actor , " A player is required while tracing " ) ;
} else {
this . tracingExtents = null ;
}
this . allowedRegions = builder . getAllowedRegions ( ) ! = null ? builder . getAllowedRegions ( ) . clone ( ) : null ;
}
@Deprecated ( forRemoval = true )
public EditSession ( com . fastasyncworldedit . core . util . EditSessionBuilder builder ) {
super ( builder . compile ( ) . getExtent ( ) ) ;
this . world = builder . getWorld ( ) ;
this . bypassHistory = builder . getBypassHistory ( ) ;
this . bypassAll = builder . getBypassAll ( ) ;
this . originalLimit = builder . getLimit ( ) ;
this . limit = builder . getLimit ( ) . copy ( ) ;
this . actor = builder . getPlayer ( ) ;
this . changeSet = builder . getChangeTask ( ) ;
this . minY = world . getMinY ( ) ;
this . maxY = world . getMaxY ( ) ;
this . blockBag = builder . getBlockBag ( ) ;
this . history = changeSet ! = null ;
this . relighter = builder . getRelighter ( ) ;
this . wnaMode = builder . isWNAMode ( ) ;
this . tracingExtents = null ;
2021-01-10 17:14:40 +00:00
this . allowedRegions = builder . getAllowedRegions ( ) ! = null ? builder . getAllowedRegions ( ) . clone ( ) : null ;
2018-08-12 14:03:07 +00:00
}
/ * *
2020-10-05 17:41:41 +00:00
* The limit for this specific edit ( blocks etc ) .
2018-08-12 14:03:07 +00:00
*
2020-04-23 16:07:01 +00:00
* @return The limit
2018-08-12 14:03:07 +00:00
* /
public FaweLimit getLimit ( ) {
return originalLimit ;
}
2010-12-31 22:31:49 +00:00
2018-08-12 14:03:07 +00:00
public void resetLimit ( ) {
this . limit . set ( this . originalLimit ) ;
2019-07-18 06:56:57 +00:00
ExtentTraverser < ProcessedWEExtent > find = new ExtentTraverser < > ( getExtent ( ) ) . find ( ProcessedWEExtent . class ) ;
2018-08-12 14:03:07 +00:00
if ( find ! = null & & find . get ( ) ! = null ) {
find . get ( ) . setLimit ( this . limit ) ;
}
}
/ * *
2020-10-05 17:41:41 +00:00
* Returns a new limit representing how much of this edit ' s limit has been used so far .
2018-08-12 14:03:07 +00:00
*
2020-04-23 16:07:01 +00:00
* @return Limit remaining
2018-08-12 14:03:07 +00:00
* /
public FaweLimit getLimitUsed ( ) {
FaweLimit newLimit = new FaweLimit ( ) ;
newLimit . MAX_ACTIONS = originalLimit . MAX_ACTIONS - limit . MAX_ACTIONS ;
newLimit . MAX_CHANGES = originalLimit . MAX_CHANGES - limit . MAX_CHANGES ;
newLimit . MAX_FAILS = originalLimit . MAX_FAILS - limit . MAX_FAILS ;
newLimit . MAX_CHECKS = originalLimit . MAX_CHECKS - limit . MAX_CHECKS ;
newLimit . MAX_ITERATIONS = originalLimit . MAX_ITERATIONS - limit . MAX_ITERATIONS ;
newLimit . MAX_BLOCKSTATES = originalLimit . MAX_BLOCKSTATES - limit . MAX_BLOCKSTATES ;
newLimit . MAX_ENTITIES = originalLimit . MAX_ENTITIES - limit . MAX_ENTITIES ;
newLimit . MAX_HISTORY = limit . MAX_HISTORY ;
return newLimit ;
}
/ * *
2020-10-05 17:41:41 +00:00
* Returns the remaining limits .
2018-08-12 14:03:07 +00:00
*
2020-04-23 16:07:01 +00:00
* @return remaining limits
2018-08-12 14:03:07 +00:00
* /
public FaweLimit getLimitLeft ( ) {
return limit ;
}
/ * *
2021-01-10 14:59:21 +00:00
* Returns the RegionExtent that will restrict an edit , or null .
2018-08-12 14:03:07 +00:00
*
* @return FaweRegionExtent ( may be null )
* /
public FaweRegionExtent getRegionExtent ( ) {
2019-07-18 06:56:57 +00:00
ExtentTraverser < FaweRegionExtent > traverser = new ExtentTraverser < > ( getExtent ( ) ) . find ( FaweRegionExtent . class ) ;
2018-08-12 14:03:07 +00:00
return traverser = = null ? null : traverser . get ( ) ;
}
public Extent getBypassAll ( ) {
return bypassAll ;
}
2020-10-05 17:41:41 +00:00
2018-08-12 14:03:07 +00:00
public Extent getBypassHistory ( ) {
return bypassHistory ;
}
public void setExtent ( AbstractDelegateExtent extent ) {
2019-12-16 09:07:51 +00:00
new ExtentTraverser ( this ) . setNext ( extent ) ;
2018-08-12 14:03:07 +00:00
}
2021-09-19 20:02:41 +00:00
//FAWE Start
2018-08-12 14:03:07 +00:00
/ * *
2021-09-19 20:02:41 +00:00
* Get the Actor or null .
2018-08-12 14:03:07 +00:00
*
2021-09-19 20:02:41 +00:00
* @return the actor
2018-08-12 14:03:07 +00:00
* /
@Nullable
2021-09-19 20:02:41 +00:00
public Actor getActor ( ) {
return actor ;
}
//FAWE End
private Extent traceIfNeeded ( Extent input ) {
Extent output = input ;
if ( tracingExtents ! = null ) {
TracingExtent newExtent = new TracingExtent ( input ) ;
output = newExtent ;
tracingExtents . add ( newExtent ) ;
}
return output ;
2018-08-12 14:03:07 +00:00
}
2018-11-04 05:22:43 +00:00
// pkg private for TracedEditSession only, may later become public API
boolean commitRequired ( ) {
2021-09-19 20:02:41 +00:00
//FAWE start
2018-11-04 05:22:43 +00:00
return false ;
2018-10-31 01:39:51 +00:00
}
2021-07-23 15:48:51 +00:00
//FAWE end
2018-10-31 01:39:51 +00:00
2021-09-19 20:02:41 +00:00
/ * *
* Get the current list of active tracing extents .
* /
private List < TracingExtent > getActiveTracingExtents ( ) {
if ( tracingExtents = = null ) {
return List . of ( ) ;
}
return tracingExtents . stream ( )
. filter ( TracingExtent : : isActive )
. collect ( Collectors . toList ( ) ) ;
}
2018-10-04 17:37:58 +00:00
/ * *
* Turns on specific features for a normal WorldEdit session , such as
2018-12-09 05:11:11 +00:00
* { @link # setBatchingChunks ( boolean )
2018-10-04 17:37:58 +00:00
* chunk batching } .
* /
public void enableStandardMode ( ) {
2020-02-06 21:33:31 +00:00
setBatchingChunks ( true ) ;
2018-10-04 17:37:58 +00:00
}
2019-06-04 15:48:30 +00:00
/ * *
* Sets the { @link ReorderMode } of this EditSession , and flushes the session .
*
* @param reorderMode The reorder mode
* /
public void setReorderMode ( ReorderMode reorderMode ) {
2021-07-23 15:48:51 +00:00
//FAWE start - we don't do physics so we don't need this
2019-07-18 16:07:31 +00:00
switch ( reorderMode ) {
case MULTI_STAGE :
enableQueue ( ) ;
break ;
case NONE : // Functionally the same, since FAWE doesn't perform physics
case FAST :
disableQueue ( ) ;
break ;
default :
throw new UnsupportedOperationException ( " Not implemented: " + reorderMode ) ;
}
2021-07-23 15:48:51 +00:00
//FAWE end
2019-06-04 15:48:30 +00:00
}
/ * *
* Get the reorder mode .
*
* @return the reorder mode
* /
public ReorderMode getReorderMode ( ) {
2019-07-18 16:07:31 +00:00
if ( isQueueEnabled ( ) ) {
return ReorderMode . MULTI_STAGE ;
}
return ReorderMode . FAST ;
2019-06-04 15:48:30 +00:00
}
2010-10-11 08:22:47 +00:00
/ * *
2014-03-31 23:55:58 +00:00
* Get the world .
2011-09-24 19:32:03 +00:00
*
2014-03-31 23:55:58 +00:00
* @return the world
2010-10-11 08:22:47 +00:00
* /
2014-04-05 09:59:38 +00:00
public World getWorld ( ) {
2019-03-28 19:02:37 +00:00
return world ;
2010-10-05 07:40:50 +00:00
}
2011-03-13 00:37:07 +00:00
/ * *
2014-03-31 05:33:16 +00:00
* Get the underlying { @link ChangeSet } .
2011-09-24 19:32:03 +00:00
*
2014-03-31 05:33:16 +00:00
* @return the change set
2011-03-13 00:37:07 +00:00
* /
2014-03-31 05:33:16 +00:00
public ChangeSet getChangeSet ( ) {
2020-01-03 20:38:30 +00:00
return changeSet ;
2018-08-12 14:03:07 +00:00
}
/ * *
* Set the ChangeSet without hooking into any recording mechanism or triggering any actions . < br / >
* Used internally to set the ChangeSet during completion to record custom changes which aren ' t normally recorded
2021-07-24 15:34:05 +00:00
*
2020-04-23 16:07:01 +00:00
* @param set The ChangeSet to set
2018-08-12 14:03:07 +00:00
* /
2020-01-06 08:36:16 +00:00
public void setRawChangeSet ( @Nullable AbstractChangeSet set ) {
2020-01-03 20:38:30 +00:00
changeSet = set ;
2018-08-12 14:03:07 +00:00
changes + + ;
2014-03-31 05:33:16 +00:00
}
2011-03-13 00:37:07 +00:00
2018-08-12 14:03:07 +00:00
/ * *
2019-06-04 15:48:30 +00:00
* Get the maximum number of blocks that can be changed . - 1 will be returned
* if it the limit disabled .
*
2014-07-29 21:23:00 +00:00
* @return the limit ( & gt ; = 0 ) or - 1 for no limit
2018-08-12 14:03:07 +00:00
* @see # getLimit ( )
2011-02-18 23:14:43 +00:00
* /
2018-08-12 14:03:07 +00:00
@Deprecated
2014-03-31 23:55:58 +00:00
public int getBlockChangeLimit ( ) {
2018-08-12 14:03:07 +00:00
return originalLimit . MAX_CHANGES ;
2011-02-18 23:14:43 +00:00
}
2010-10-13 05:38:05 +00:00
/ * *
2014-03-31 23:55:58 +00:00
* Set the maximum number of blocks that can be changed .
2011-09-24 19:32:03 +00:00
*
2014-07-29 21:23:00 +00:00
* @param limit the limit ( & gt ; = 0 ) or - 1 for no limit
2010-10-13 05:38:05 +00:00
* /
2019-06-04 15:48:30 +00:00
public void setBlockChangeLimit ( int limit ) {
2019-11-21 07:57:32 +00:00
this . limit . MAX_CHANGES = limit ;
2010-10-13 05:38:05 +00:00
}
2010-10-05 07:40:50 +00:00
/ * *
2014-03-31 23:55:58 +00:00
* Returns queue status .
2011-09-24 19:32:03 +00:00
*
2014-03-31 23:55:58 +00:00
* @return whether the queue is enabled
2019-06-12 21:12:12 +00:00
* @deprecated Use { @link EditSession # getReorderMode ( ) } with MULTI_STAGE instead .
2010-10-05 07:40:50 +00:00
* /
2019-03-28 19:02:37 +00:00
@Deprecated
2014-03-31 23:55:58 +00:00
public boolean isQueueEnabled ( ) {
2021-07-23 15:48:51 +00:00
//FAWE start - see reorder comment, we don't need this
2018-08-12 14:03:07 +00:00
return true ;
2021-07-23 15:48:51 +00:00
//FAWE end
2010-10-02 21:52:42 +00:00
}
/ * *
2020-10-05 17:41:41 +00:00
* Queue certain types of block for better reproduction of those blocks . Uses
* { @link ReorderMode # MULTI_STAGE } .
2019-06-12 21:12:12 +00:00
*
* @deprecated Use { @link EditSession # setReorderMode ( ReorderMode ) } with MULTI_STAGE instead .
2010-10-02 21:52:42 +00:00
* /
2019-03-28 19:02:37 +00:00
@Deprecated
2014-03-31 23:55:58 +00:00
public void enableQueue ( ) {
2021-07-23 15:48:51 +00:00
//FAWE start - see reorder comment, we don't need this
2019-07-18 16:07:31 +00:00
super . enableQueue ( ) ;
2021-07-23 15:48:51 +00:00
//FAWE end
2010-10-11 08:22:47 +00:00
}
2011-01-31 06:15:08 +00:00
/ * *
2018-08-12 14:03:07 +00:00
* Disable the queue . This will close the queue .
2011-01-31 06:15:08 +00:00
* /
2019-03-28 19:02:37 +00:00
@Deprecated
2014-03-31 23:55:58 +00:00
public void disableQueue ( ) {
2021-07-23 15:48:51 +00:00
//FAWE start - see reorder comment, we don't need this
2019-07-18 16:07:31 +00:00
super . disableQueue ( ) ;
2021-07-23 15:48:51 +00:00
//FAWE end
2011-07-15 07:00:48 +00:00
}
2011-11-23 01:29:48 +00:00
2010-10-11 08:22:47 +00:00
/ * *
2014-03-31 23:55:58 +00:00
* Get the mask .
2011-09-24 19:32:03 +00:00
*
2014-03-31 23:55:58 +00:00
* @return mask , may be null
2010-10-11 08:22:47 +00:00
* /
2014-03-31 23:55:58 +00:00
public Mask getMask ( ) {
2021-07-23 15:48:51 +00:00
//FAWE start - ExtendTraverser & MaskingExtents
2019-07-18 06:56:57 +00:00
ExtentTraverser < MaskingExtent > maskingExtent = new ExtentTraverser < > ( getExtent ( ) ) . find ( MaskingExtent . class ) ;
2018-08-12 14:03:07 +00:00
return maskingExtent ! = null ? maskingExtent . get ( ) . getMask ( ) : null ;
2021-07-23 15:48:51 +00:00
//FAWE end
2018-08-12 14:03:07 +00:00
}
2021-07-23 15:48:51 +00:00
//FAWE start
2021-07-24 15:34:05 +00:00
2018-08-12 14:03:07 +00:00
/ * *
2021-07-23 15:48:51 +00:00
* Get the source mask .
2018-08-12 14:03:07 +00:00
*
2021-07-23 15:48:51 +00:00
* @return source mask , may be null
2018-08-12 14:03:07 +00:00
* /
public Mask getSourceMask ( ) {
2019-07-18 06:56:57 +00:00
ExtentTraverser < SourceMaskExtent > maskingExtent = new ExtentTraverser < > ( getExtent ( ) ) . find ( SourceMaskExtent . class ) ;
2018-08-12 14:03:07 +00:00
return maskingExtent ! = null ? maskingExtent . get ( ) . getMask ( ) : null ;
}
2021-01-10 14:59:21 +00:00
@Nullable
public Region [ ] getAllowedRegions ( ) {
return allowedRegions ;
}
2018-08-12 14:03:07 +00:00
public void addTransform ( ResettableExtent transform ) {
2019-07-18 06:56:57 +00:00
checkNotNull ( transform ) ;
transform . setExtent ( getExtent ( ) ) ;
2019-12-16 09:07:51 +00:00
new ExtentTraverser ( this ) . setNext ( transform ) ;
2018-08-12 14:03:07 +00:00
}
2020-10-05 17:41:41 +00:00
@Nullable
public ResettableExtent getTransform ( ) {
2019-07-18 06:56:57 +00:00
ExtentTraverser < ResettableExtent > traverser = new ExtentTraverser < > ( getExtent ( ) ) . find ( ResettableExtent . class ) ;
2018-08-12 14:03:07 +00:00
if ( traverser ! = null ) {
2019-07-18 06:56:57 +00:00
return traverser . get ( ) ;
2018-08-12 14:03:07 +00:00
}
return null ;
}
2021-07-23 15:48:51 +00:00
//FAWE end
2018-08-12 14:03:07 +00:00
2021-07-23 15:48:51 +00:00
//FAWE start - use source mast > mask
2021-07-24 15:34:05 +00:00
2018-08-12 14:03:07 +00:00
/ * *
* Set a mask .
*
* @param mask mask or null
* /
public void setSourceMask ( Mask mask ) {
if ( mask = = null ) {
mask = Masks . alwaysTrue ( ) ;
} else {
new MaskTraverser ( mask ) . reset ( this ) ;
}
2019-07-18 06:56:57 +00:00
ExtentTraverser < SourceMaskExtent > maskingExtent = new ExtentTraverser < > ( getExtent ( ) ) . find ( SourceMaskExtent . class ) ;
2018-08-12 14:03:07 +00:00
if ( maskingExtent ! = null & & maskingExtent . get ( ) ! = null ) {
Mask oldMask = maskingExtent . get ( ) . getMask ( ) ;
if ( oldMask instanceof ResettableMask ) {
( ( ResettableMask ) oldMask ) . reset ( ) ;
}
maskingExtent . get ( ) . setMask ( mask ) ;
} else if ( mask ! = Masks . alwaysTrue ( ) ) {
2019-07-18 06:56:57 +00:00
SourceMaskExtent next = new SourceMaskExtent ( getExtent ( ) , mask ) ;
2019-12-16 09:07:51 +00:00
new ExtentTraverser ( this ) . setNext ( next ) ;
2018-08-12 14:03:07 +00:00
}
}
public void addSourceMask ( Mask mask ) {
checkNotNull ( mask ) ;
Mask existing = getSourceMask ( ) ;
if ( existing ! = null ) {
if ( existing instanceof MaskIntersection ) {
2019-07-18 06:56:57 +00:00
Collection < Mask > masks = new HashSet < > ( ( ( MaskIntersection ) existing ) . getMasks ( ) ) ;
masks . add ( mask ) ;
mask = new MaskIntersection ( masks ) ;
2018-08-12 14:03:07 +00:00
} else {
2019-07-18 06:56:57 +00:00
mask = new MaskIntersection ( existing , mask ) ;
2018-08-12 14:03:07 +00:00
}
2019-07-18 06:56:57 +00:00
mask = mask . optimize ( ) ;
2018-08-12 14:03:07 +00:00
}
setSourceMask ( mask ) ;
2010-10-02 21:52:42 +00:00
}
2021-07-23 15:48:51 +00:00
//FAWE end
2010-10-02 21:52:42 +00:00
2021-07-23 15:48:51 +00:00
//FAWE start - use MaskingExtent & ExtentTraverser
2021-07-24 15:34:05 +00:00
2010-10-02 21:52:42 +00:00
/ * *
2014-03-31 23:55:58 +00:00
* Set a mask .
2011-09-24 19:32:03 +00:00
*
2014-03-31 23:55:58 +00:00
* @param mask mask or null
2010-10-02 21:52:42 +00:00
* /
2014-03-31 23:55:58 +00:00
public void setMask ( Mask mask ) {
if ( mask = = null ) {
2018-08-12 14:03:07 +00:00
mask = Masks . alwaysTrue ( ) ;
2014-03-31 23:55:58 +00:00
} else {
2018-08-12 14:03:07 +00:00
new MaskTraverser ( mask ) . reset ( this ) ;
}
2019-07-18 06:56:57 +00:00
ExtentTraverser < MaskingExtent > maskingExtent = new ExtentTraverser < > ( getExtent ( ) ) . find ( MaskingExtent . class ) ;
2018-08-12 14:03:07 +00:00
if ( maskingExtent ! = null & & maskingExtent . get ( ) ! = null ) {
Mask oldMask = maskingExtent . get ( ) . getMask ( ) ;
if ( oldMask instanceof ResettableMask ) {
( ( ResettableMask ) oldMask ) . reset ( ) ;
}
maskingExtent . get ( ) . setMask ( mask ) ;
} else if ( mask ! = Masks . alwaysTrue ( ) ) {
2019-12-16 09:07:51 +00:00
addProcessor ( new MaskingExtent ( getExtent ( ) , mask ) ) ;
2014-06-28 02:55:38 +00:00
}
}
2021-07-23 15:48:51 +00:00
//FAWE end
2014-06-28 02:55:38 +00:00
2021-07-23 15:48:51 +00:00
//FAWE start - ExtentTraverser
2021-07-24 15:34:05 +00:00
2014-04-23 07:33:00 +00:00
/ * *
* Get the { @link SurvivalModeExtent } .
*
* @return the survival simulation extent
* /
public SurvivalModeExtent getSurvivalExtent ( ) {
2019-07-18 06:56:57 +00:00
ExtentTraverser < SurvivalModeExtent > survivalExtent = new ExtentTraverser < > ( getExtent ( ) ) . find ( SurvivalModeExtent . class ) ;
2018-08-12 14:03:07 +00:00
if ( survivalExtent ! = null ) {
return survivalExtent . get ( ) ;
2021-06-18 22:48:23 +00:00
} else { // Kind of a bad way of doing it, but equally I (dords) hate the way upstream does it by just adding ALL possible extents to an edit and only "enabling" when required
SurvivalModeExtent survival = new SurvivalModeExtent ( getExtent ( ) , getWorld ( ) ) ;
setExtent ( survival ) ;
2018-08-12 14:03:07 +00:00
return survival ;
}
2014-04-23 07:33:00 +00:00
}
2021-07-23 15:48:51 +00:00
//FAWE end
2014-04-23 07:33:00 +00:00
2021-07-23 15:48:51 +00:00
//FAWE start - our fastmode works different to upstream
2021-07-24 15:34:05 +00:00
2010-10-02 21:52:42 +00:00
/ * *
2014-03-31 23:55:58 +00:00
* Set whether fast mode is enabled .
2019-06-04 15:48:30 +00:00
*
2014-07-29 18:04:04 +00:00
* < p > Fast mode may skip lighting checks or adjacent block
* notification . < / p >
2011-09-24 19:32:03 +00:00
*
2014-03-31 23:55:58 +00:00
* @param enabled true to enable
2010-10-02 21:52:42 +00:00
* /
2020-02-12 21:18:36 +00:00
@Deprecated
2019-06-25 13:00:44 +00:00
public void setFastMode ( boolean enabled ) {
2018-08-12 14:03:07 +00:00
disableHistory ( enabled ) ;
}
2021-07-23 15:48:51 +00:00
//FAWE end
2018-08-12 14:03:07 +00:00
2021-07-23 15:48:51 +00:00
//FAWE start - we don't use this (yet)
2021-07-24 15:34:05 +00:00
2020-03-08 06:09:36 +00:00
/ * *
* Set which block updates should occur .
*
* @param sideEffectSet side effects to enable
* /
public void setSideEffectApplier ( SideEffectSet sideEffectSet ) {
//Do nothing; TODO: SideEffects currently not fully implemented in FAWE.
}
public SideEffectSet getSideEffectApplier ( ) {
//Do nothing; TODO: SideEffects currently not fully implemented in FAWE.
return SideEffectSet . defaults ( ) ;
}
2021-07-23 15:48:51 +00:00
//FAWE end
2020-03-08 06:09:36 +00:00
2021-07-23 15:48:51 +00:00
//FAWE start
2021-07-24 15:34:05 +00:00
2018-08-12 14:03:07 +00:00
/ * *
* Disable history ( or re - enable )
*
2020-04-23 16:07:01 +00:00
* @param disableHistory whether to enable or disable .
2018-08-12 14:03:07 +00:00
* /
2020-02-12 21:18:36 +00:00
@Deprecated
2018-08-12 14:03:07 +00:00
public void disableHistory ( boolean disableHistory ) {
if ( disableHistory ) {
2019-10-23 04:23:52 +00:00
if ( this . history ) {
disableHistory ( ) ;
this . history = false ;
2018-08-12 14:03:07 +00:00
}
2019-10-23 04:23:52 +00:00
} else {
if ( this . history ) {
2020-01-03 20:38:30 +00:00
if ( this . changeSet = = null ) {
2019-10-23 04:23:52 +00:00
throw new IllegalArgumentException ( " History was never provided, cannot enable " ) ;
}
2020-01-03 20:38:30 +00:00
enableHistory ( this . changeSet ) ;
2018-08-12 14:03:07 +00:00
}
2014-04-06 04:49:25 +00:00
}
2010-10-02 21:52:42 +00:00
}
2021-07-23 15:48:51 +00:00
//FAWE end
2010-10-02 21:52:42 +00:00
2021-07-23 15:48:51 +00:00
//FAWE start - See comment on setFastMode
2021-07-24 15:34:05 +00:00
2010-10-02 21:52:42 +00:00
/ * *
2014-03-31 23:55:58 +00:00
* Return fast mode status .
2018-12-20 16:00:27 +00:00
*
2014-07-29 18:04:04 +00:00
* < p > Fast mode may skip lighting checks or adjacent block
* notification . < / p >
2011-09-24 19:32:03 +00:00
*
2014-03-31 23:55:58 +00:00
* @return true if enabled
2010-10-02 21:52:42 +00:00
* /
2020-02-12 21:18:36 +00:00
@Deprecated
2014-03-31 23:55:58 +00:00
public boolean hasFastMode ( ) {
2018-08-12 14:03:07 +00:00
return getChangeSet ( ) = = null ;
2010-10-02 21:52:42 +00:00
}
2021-07-23 15:48:51 +00:00
//FAWE end
2010-10-04 23:39:35 +00:00
2021-07-23 15:48:51 +00:00
//FAWE start - Don't use blockBagExtent
2021-07-24 15:34:05 +00:00
2010-10-04 23:39:35 +00:00
/ * *
2014-03-31 23:55:58 +00:00
* Get the { @link BlockBag } is used .
2011-09-24 19:32:03 +00:00
*
2014-03-31 23:55:58 +00:00
* @return a block bag or null
2010-10-04 23:39:35 +00:00
* /
2014-03-31 23:55:58 +00:00
public BlockBag getBlockBag ( ) {
2018-08-12 14:03:07 +00:00
return this . blockBag ;
2010-10-04 23:39:35 +00:00
}
2021-07-23 15:48:51 +00:00
//FAWE end
2010-10-04 23:39:35 +00:00
2021-07-23 15:48:51 +00:00
//FAWE start
2021-07-24 15:34:05 +00:00
2010-10-04 23:39:35 +00:00
/ * *
2014-03-31 23:55:58 +00:00
* Set a { @link BlockBag } to use .
2011-09-24 19:32:03 +00:00
*
2014-03-31 23:55:58 +00:00
* @param blockBag the block bag to set , or null to use none
2010-10-04 23:39:35 +00:00
* /
2019-06-04 15:48:30 +00:00
public void setBlockBag ( BlockBag blockBag ) {
2020-01-03 20:38:30 +00:00
//Not Supported in FAWE
2019-07-18 06:56:57 +00:00
throw new UnsupportedOperationException ( " TODO - this is never called anyway " ) ;
2018-08-12 14:03:07 +00:00
}
2021-07-23 15:48:51 +00:00
//FAWE end
2018-08-12 14:03:07 +00:00
2021-07-23 15:48:51 +00:00
//FAWE start
2018-08-12 14:03:07 +00:00
@Override
public String toString ( ) {
2019-07-18 06:56:57 +00:00
return super . toString ( ) + " : " + getExtent ( ) ;
2010-10-04 23:39:35 +00:00
}
2010-10-05 07:40:50 +00:00
/ * *
2014-03-31 23:55:58 +00:00
* Gets the list of missing blocks and clears the list for the next
* operation .
2011-09-24 19:32:03 +00:00
*
2014-03-31 23:55:58 +00:00
* @return a map of missing blocks
2010-10-05 07:40:50 +00:00
* /
2019-07-06 00:46:48 +00:00
public Map < BlockType , Integer > popMissingBlocks ( ) {
2018-08-12 14:03:07 +00:00
BlockBag bag = getBlockBag ( ) ;
if ( bag ! = null ) {
bag . flushChanges ( ) ;
2019-07-06 00:46:48 +00:00
Map < BlockType , Integer > missingBlocks ;
2018-08-12 14:03:07 +00:00
ChangeSet changeSet = getChangeSet ( ) ;
if ( changeSet instanceof BlockBagChangeSet ) {
missingBlocks = ( ( BlockBagChangeSet ) changeSet ) . popMissing ( ) ;
} else {
2019-07-18 06:56:57 +00:00
ExtentTraverser < BlockBagExtent > find = new ExtentTraverser < > ( getExtent ( ) ) . find ( BlockBagExtent . class ) ;
2018-08-12 14:03:07 +00:00
if ( find ! = null & & find . get ( ) ! = null ) {
missingBlocks = find . get ( ) . popMissing ( ) ;
} else {
missingBlocks = null ;
}
}
if ( missingBlocks ! = null & & ! missingBlocks . isEmpty ( ) ) {
StringBuilder str = new StringBuilder ( ) ;
int size = missingBlocks . size ( ) ;
int i = 0 ;
for ( Map . Entry < BlockType , Integer > entry : missingBlocks . entrySet ( ) ) {
BlockType type = entry . getKey ( ) ;
int amount = entry . getValue ( ) ;
str . append ( ( type . getName ( ) ) ) . append ( ( amount ! = 1 ? " x " + amount : " " ) ) ;
+ + i ;
if ( i ! = size ) {
str . append ( " , " ) ;
}
}
2021-09-19 20:02:41 +00:00
actor . print ( Caption . of ( " fawe.error.worldedit.some.fails.blockbag " , str . toString ( ) ) ) ;
2018-08-12 14:03:07 +00:00
}
}
2019-04-10 08:32:21 +00:00
return Collections . emptyMap ( ) ;
2010-10-05 07:40:50 +00:00
}
2021-07-23 15:48:51 +00:00
//FAWE end
2011-08-07 00:40:48 +00:00
2021-07-23 15:48:51 +00:00
//FAWE start - We don't use this method
2021-07-24 15:34:05 +00:00
2018-10-21 01:54:58 +00:00
/ * *
* Returns chunk batching status .
*
* @return whether chunk batching is enabled
* /
2018-10-04 17:37:58 +00:00
public boolean isBatchingChunks ( ) {
2019-04-03 05:53:34 +00:00
return false ;
2018-10-04 17:37:58 +00:00
}
2021-07-23 15:48:51 +00:00
//FAWE end
2018-10-04 17:37:58 +00:00
2018-10-21 01:54:58 +00:00
/ * *
2020-10-05 17:41:41 +00:00
* Enable or disable chunk batching . Disabling will flush the session .
2018-10-21 01:54:58 +00:00
*
* @param batchingChunks { @code true } to enable , { @code false } to disable
* /
2018-10-04 17:37:58 +00:00
public void setBatchingChunks ( boolean batchingChunks ) {
2021-07-23 15:48:51 +00:00
//FAWE start - altered by our lifecycle
2019-07-18 16:07:31 +00:00
if ( batchingChunks ) {
enableQueue ( ) ;
} else {
disableQueue ( ) ;
}
2021-07-23 15:48:51 +00:00
//FAWE end
2018-10-04 17:37:58 +00:00
}
2019-06-04 15:48:30 +00:00
/ * *
* Disable all buffering extents .
*
2019-06-25 13:00:44 +00:00
* @see # setReorderMode ( ReorderMode )
2019-06-04 15:48:30 +00:00
* @see # setBatchingChunks ( boolean )
* /
2018-10-21 01:54:58 +00:00
public void disableBuffering ( ) {
2021-07-23 15:48:51 +00:00
//FAWE start - see comment on reorder mode
2019-07-18 16:07:31 +00:00
disableQueue ( ) ;
2021-07-23 15:48:51 +00:00
//FAWE end
2018-10-21 01:54:58 +00:00
}
2019-09-05 05:50:14 +00:00
/ * *
* Check if this session will tick the watchdog .
*
* @return { @code true } if any watchdog extent is enabled
* /
public boolean isTickingWatchdog ( ) {
return watchdogExtents . stream ( ) . anyMatch ( WatchdogTickingExtent : : isEnabled ) ;
}
/ * *
* Set all watchdog extents to the given mode .
* /
public void setTickingWatchdog ( boolean active ) {
for ( WatchdogTickingExtent extent : watchdogExtents ) {
extent . setEnabled ( active ) ;
}
}
2011-06-04 17:30:45 +00:00
/ * *
2014-03-31 23:55:58 +00:00
* Get the number of blocks changed , including repeated block changes .
2019-06-04 15:48:30 +00:00
*
2014-07-29 18:04:04 +00:00
* < p > This number may not be accurate . < / p >
2011-09-24 19:32:03 +00:00
*
2014-03-31 23:55:58 +00:00
* @return the number of block changes
2011-06-04 17:30:45 +00:00
* /
2014-03-31 23:55:58 +00:00
public int getBlockChangeCount ( ) {
2018-08-12 14:03:07 +00:00
return this . changes ;
2011-06-04 17:30:45 +00:00
}
2011-08-07 00:40:48 +00:00
2014-07-17 07:21:13 +00:00
@Override
2020-09-12 13:31:42 +00:00
public boolean fullySupports3DBiomes ( ) {
return this . getExtent ( ) . fullySupports3DBiomes ( ) ;
}
@Override
public BiomeType getBiome ( BlockVector3 position ) {
return this . getExtent ( ) . getBiome ( position ) ;
}
@Override
public boolean setBiome ( BlockVector3 position , BiomeType biome ) {
2021-07-23 15:48:51 +00:00
//FAWE start - use extent
2021-04-09 20:59:31 +00:00
if ( position . getY ( ) < this . minY | | position . getY ( ) > this . maxY ) {
return false ;
}
2018-08-12 14:03:07 +00:00
this . changes + + ;
2019-07-18 06:56:57 +00:00
return this . getExtent ( ) . setBiome ( position , biome ) ;
2021-07-23 15:48:51 +00:00
//FAWE end
2014-07-17 07:21:13 +00:00
}
2014-03-31 23:55:58 +00:00
@Override
2019-04-03 05:53:34 +00:00
public boolean setBiome ( int x , int y , int z , BiomeType biome ) {
2021-07-23 15:48:51 +00:00
//FAWE start - use extent
2021-04-09 20:59:31 +00:00
if ( y < this . minY | | y > this . maxY ) {
return false ;
}
2018-08-12 14:03:07 +00:00
this . changes + + ;
2019-07-18 06:56:57 +00:00
return this . getExtent ( ) . setBiome ( x , y , z , biome ) ;
2021-07-23 15:48:51 +00:00
//FAWE end
2018-08-12 14:03:07 +00:00
}
2011-11-01 13:54:32 +00:00
/ * *
2018-07-02 14:45:38 +00:00
* Returns the highest solid ' terrain ' block .
2011-11-01 13:54:32 +00:00
*
2021-07-24 15:34:05 +00:00
* @param x the X coordinate
* @param z the Z coordinate
2011-11-01 13:54:32 +00:00
* @param minY minimal height
* @param maxY maximal height
* @return height of highest block found or ' minY '
* /
2018-12-23 16:19:33 +00:00
public int getHighestTerrainBlock ( int x , int z , int minY , int maxY ) {
2021-07-23 15:48:51 +00:00
//FAWE start - check movement blocker
2019-06-28 14:01:51 +00:00
for ( int y = maxY ; y > = minY ; - - y ) {
if ( getBlock ( x , y , z ) . getBlockType ( ) . getMaterial ( ) . isMovementBlocker ( ) ) {
return y ;
}
2021-07-23 15:48:51 +00:00
//FAWE end
2019-06-28 14:01:51 +00:00
}
return minY ;
2019-03-28 19:02:37 +00:00
}
/ * *
* Returns the highest solid ' terrain ' block .
*
2021-07-24 15:34:05 +00:00
* @param x the X coordinate
* @param z the Z coordinate
* @param minY minimal height
* @param maxY maximal height
2019-03-28 19:02:37 +00:00
* @param filter a mask of blocks to consider , or null to consider any solid ( movement - blocking ) block
* @return height of highest block found or ' minY '
* /
public int getHighestTerrainBlock ( int x , int z , int minY , int maxY , Mask filter ) {
2018-12-23 16:19:33 +00:00
for ( int y = maxY ; y > = minY ; - - y ) {
2021-07-23 15:48:51 +00:00
//FAWE start - get position from mutable vector
if ( filter . test ( mutableBlockVector3 . setComponents ( x , y , z ) ) ) {
2021-07-24 15:34:05 +00:00
//FAWE end
2018-12-23 16:19:33 +00:00
return y ;
}
}
2019-09-14 03:05:16 +00:00
2018-12-23 16:19:33 +00:00
return minY ;
}
2021-07-23 15:48:51 +00:00
//FAWE start
2018-08-12 14:03:07 +00:00
public BlockType getBlockType ( int x , int y , int z ) {
2019-07-18 06:56:57 +00:00
return getBlock ( x , y , z ) . getBlockType ( ) ;
2011-11-01 13:54:32 +00:00
}
2021-07-23 15:48:51 +00:00
//FAWE end
2011-11-01 13:54:32 +00:00
/ * *
2014-03-31 23:55:58 +00:00
* Set a block , bypassing both history and block re - ordering .
2011-11-01 13:54:32 +00:00
*
2014-03-31 23:55:58 +00:00
* @param position the position to set the block at
2021-07-24 15:34:05 +00:00
* @param block the block
* @param stage the level
2014-03-31 23:55:58 +00:00
* @return whether the block changed
2014-07-29 21:23:00 +00:00
* @throws WorldEditException thrown on a set error
2021-09-19 20:02:41 +00:00
* @deprecated Deprecated as may perform differently in FAWE .
2014-03-31 23:55:58 +00:00
* /
2020-04-23 16:07:01 +00:00
@Deprecated
2021-07-24 15:34:05 +00:00
public < B extends BlockStateHolder < B > > boolean setBlock ( BlockVector3 position , B block , Stage stage ) throws
WorldEditException {
2021-07-23 15:48:51 +00:00
//FAWE start - accumulate changes
2021-04-09 20:59:31 +00:00
if ( position . getBlockY ( ) < this . minY | | position . getBlockY ( ) > this . maxY ) {
2020-02-29 22:42:00 +00:00
return false ;
}
2018-08-12 14:03:07 +00:00
this . changes + + ;
2014-04-04 01:24:06 +00:00
switch ( stage ) {
case BEFORE_HISTORY :
2019-07-18 06:56:57 +00:00
return this . getExtent ( ) . setBlock ( position , block ) ;
2014-04-04 01:24:06 +00:00
case BEFORE_CHANGE :
2019-06-30 18:56:32 +00:00
return bypassHistory . setBlock ( position , block ) ;
2014-04-04 01:24:06 +00:00
case BEFORE_REORDER :
2019-06-30 18:56:32 +00:00
return bypassAll . setBlock ( position , block ) ;
2014-03-31 23:55:58 +00:00
}
2021-07-23 15:48:51 +00:00
//FAWE end
2014-03-31 23:55:58 +00:00
throw new RuntimeException ( " New enum entry added that is unhandled here " ) ;
}
2021-07-23 15:48:51 +00:00
//FAWE start - see former comment
2021-07-24 15:34:05 +00:00
2019-03-28 19:02:37 +00:00
/ * *
* Set a block , bypassing both history and block re - ordering .
*
* @param position the position to set the block at
2021-07-24 15:34:05 +00:00
* @param block the block
2019-03-28 19:02:37 +00:00
* @return whether the block changed
2021-09-19 20:02:41 +00:00
* @deprecated Deprecated as may perform differently in FAWE .
2019-03-28 19:02:37 +00:00
* /
2020-04-23 16:07:01 +00:00
@Deprecated
2018-12-27 00:39:10 +00:00
public < B extends BlockStateHolder < B > > boolean rawSetBlock ( BlockVector3 position , B block ) {
2021-04-09 20:59:31 +00:00
if ( position . getBlockY ( ) < this . minY | | position . getBlockY ( ) > this . maxY ) {
2020-02-29 22:42:00 +00:00
return false ;
}
2019-04-03 05:53:34 +00:00
this . changes + + ;
2018-12-23 16:19:33 +00:00
try {
2019-06-30 18:56:32 +00:00
return bypassAll . setBlock ( position , block ) ;
2019-03-28 19:02:37 +00:00
} catch ( WorldEditException e ) {
2018-12-23 16:19:33 +00:00
throw new RuntimeException ( " Unexpected exception " , e ) ;
}
}
2021-07-23 15:48:51 +00:00
//FAWE end
2019-06-04 15:48:30 +00:00
2021-07-23 15:48:51 +00:00
//FAWE start - we use this
2021-07-24 15:34:05 +00:00
2011-11-01 13:54:32 +00:00
/ * *
2018-08-12 14:03:07 +00:00
* Set a block , bypassing history but still utilizing block re - ordering .
2014-03-31 23:55:58 +00:00
*
* @param position the position to set the block at
2021-07-24 15:34:05 +00:00
* @param block the block
2014-03-31 23:55:58 +00:00
* @return whether the block changed
2011-11-01 13:54:32 +00:00
* /
2018-12-27 00:39:10 +00:00
public < B extends BlockStateHolder < B > > boolean smartSetBlock ( BlockVector3 position , B block ) {
2021-04-09 20:59:31 +00:00
if ( position . getBlockY ( ) < this . minY | | position . getBlockY ( ) > this . maxY ) {
2020-02-29 22:42:00 +00:00
return false ;
}
2019-04-03 05:53:34 +00:00
this . changes + + ;
2018-08-12 14:03:07 +00:00
try {
2018-12-23 16:19:33 +00:00
return setBlock ( position , block , Stage . BEFORE_REORDER ) ;
} catch ( WorldEditException e ) {
2018-08-12 14:03:07 +00:00
throw new RuntimeException ( " Unexpected exception " , e ) ;
}
}
2020-10-05 17:41:41 +00:00
@Override
@Deprecated
2018-12-27 00:39:10 +00:00
public < B extends BlockStateHolder < B > > boolean setBlock ( BlockVector3 position , B block ) throws MaxChangedBlocksException {
2021-04-09 20:59:31 +00:00
if ( position . getBlockY ( ) < this . minY | | position . getBlockY ( ) > this . maxY ) {
2020-02-29 22:42:00 +00:00
return false ;
}
2018-08-17 09:21:45 +00:00
this . changes + + ;
2014-03-31 23:55:58 +00:00
try {
2019-07-18 06:56:57 +00:00
return this . getExtent ( ) . setBlock ( position , block ) ;
2018-08-12 14:03:07 +00:00
} catch ( MaxChangedBlocksException e ) {
throw e ;
2014-03-31 23:55:58 +00:00
} catch ( WorldEditException e ) {
throw new RuntimeException ( " Unexpected exception " , e ) ;
}
2011-11-01 13:54:32 +00:00
}
2019-06-30 18:56:32 +00:00
2019-07-06 00:46:48 +00:00
@Override
2020-02-29 22:42:00 +00:00
public < B extends BlockStateHolder < B > > boolean setBlock ( int x , int y , int z , B block ) {
2021-04-09 20:59:31 +00:00
if ( y < this . minY | | y > this . maxY ) {
2020-02-29 22:42:00 +00:00
return false ;
}
2018-08-12 14:03:07 +00:00
this . changes + + ;
2014-03-31 23:55:58 +00:00
try {
2019-07-18 06:56:57 +00:00
return this . getExtent ( ) . setBlock ( x , y , z , block ) ;
2014-03-31 23:55:58 +00:00
} catch ( WorldEditException e ) {
throw new RuntimeException ( " Unexpected exception " , e ) ;
}
2011-11-01 13:54:32 +00:00
}
2019-06-30 18:56:32 +00:00
/ * *
2019-11-21 07:57:32 +00:00
* Sets the block at a position , subject to both history and block re - ordering .
2019-06-30 18:56:32 +00:00
*
2021-07-24 15:34:05 +00:00
* @param x the x coordinate
* @param y the y coordinate
* @param z the z coordinate
2019-06-30 18:56:32 +00:00
* @param pattern a pattern to use
* @return Whether the block changed - - not entirely dependable
* @throws MaxChangedBlocksException thrown if too many blocks are changed
* /
2018-08-12 14:03:07 +00:00
public boolean setBlock ( int x , int y , int z , Pattern pattern ) {
2021-04-09 20:59:31 +00:00
if ( y < this . minY | | y > this . maxY ) {
2020-02-29 22:42:00 +00:00
return false ;
}
2018-08-12 14:03:07 +00:00
this . changes + + ;
2014-03-31 23:55:58 +00:00
try {
2021-07-23 15:48:51 +00:00
BlockVector3 bv = mutableBlockVector3 . setComponents ( x , y , z ) ;
2019-07-18 06:56:57 +00:00
return pattern . apply ( getExtent ( ) , bv , bv ) ;
2014-03-31 23:55:58 +00:00
} catch ( WorldEditException e ) {
throw new RuntimeException ( " Unexpected exception " , e ) ;
}
2011-11-01 13:54:32 +00:00
}
2018-08-12 14:03:07 +00:00
2019-06-30 18:56:32 +00:00
/ * *
* Sets the block at a position , subject to both history and block re - ordering .
*
* @param position the position
2021-07-24 15:34:05 +00:00
* @param pattern a pattern to use
2019-06-30 18:56:32 +00:00
* @return Whether the block changed - - not entirely dependable
* @throws MaxChangedBlocksException thrown if too many blocks are changed
* /
public boolean setBlock ( BlockVector3 position , Pattern pattern ) throws MaxChangedBlocksException {
2021-04-09 20:59:31 +00:00
if ( position . getBlockY ( ) < this . minY | | position . getBlockY ( ) > this . maxY ) {
2020-02-29 22:42:00 +00:00
return false ;
}
2018-08-12 14:03:07 +00:00
this . changes + + ;
try {
2019-07-18 06:56:57 +00:00
return pattern . apply ( this . getExtent ( ) , position , position ) ;
2018-08-12 14:03:07 +00:00
} catch ( WorldEditException e ) {
throw new RuntimeException ( e ) ;
}
}
2020-10-05 17:41:41 +00:00
@Override
public < B extends BlockStateHolder < B > > int setBlocks ( Region region , B block ) throws MaxChangedBlocksException {
return this . changes = super . setBlocks ( region , block ) ;
}
@Override
public int setBlocks ( Region region , Pattern pattern ) throws MaxChangedBlocksException {
return this . changes = super . setBlocks ( region , pattern ) ;
}
2021-07-23 15:48:51 +00:00
//FAWE end
2020-10-05 17:41:41 +00:00
2021-07-23 15:48:51 +00:00
//FAWE start
2021-07-24 15:34:05 +00:00
2014-03-31 23:55:58 +00:00
/ * *
* Restores all blocks to their initial state .
*
2014-04-01 01:49:39 +00:00
* @param editSession a new { @link EditSession } to perform the undo in
2014-03-31 23:55:58 +00:00
* /
2019-06-04 15:48:30 +00:00
public void undo ( EditSession editSession ) {
UndoContext context = new UndoContext ( ) ;
2021-07-23 15:48:51 +00:00
//FAWE start - listen for inventory, flush & prepare changeset
2018-08-12 14:03:07 +00:00
context . setExtent ( editSession . bypassAll ) ;
ChangeSet changeSet = getChangeSet ( ) ;
2019-07-18 16:07:31 +00:00
setChangeSet ( null ) ;
2021-07-24 15:34:05 +00:00
Operations . completeBlindly ( ChangeSetExecutor . create (
changeSet ,
context ,
ChangeSetExecutor . Type . UNDO ,
editSession . getBlockBag ( ) ,
editSession . getLimit ( ) . INVENTORY_MODE
) ) ;
2018-08-12 14:03:07 +00:00
flushQueue ( ) ;
editSession . changes = 1 ;
}
2021-07-23 15:48:51 +00:00
//FAWE start
2018-08-12 14:03:07 +00:00
public void setBlocks ( ChangeSet changeSet , ChangeSetExecutor . Type type ) {
final UndoContext context = new UndoContext ( ) ;
2019-10-23 04:23:52 +00:00
context . setExtent ( bypassAll ) ;
2018-08-12 14:03:07 +00:00
Operations . completeBlindly ( ChangeSetExecutor . create ( changeSet , context , type , getBlockBag ( ) , getLimit ( ) . INVENTORY_MODE ) ) ;
flushQueue ( ) ;
changes = 1 ;
2014-03-31 23:55:58 +00:00
}
2021-07-23 15:48:51 +00:00
//FAWE end
2011-10-24 02:04:45 +00:00
2014-03-31 23:55:58 +00:00
/ * *
* Sets to new state .
*
2014-04-01 01:49:39 +00:00
* @param editSession a new { @link EditSession } to perform the redo in
2014-03-31 23:55:58 +00:00
* /
2019-06-04 15:48:30 +00:00
public void redo ( EditSession editSession ) {
UndoContext context = new UndoContext ( ) ;
2021-07-23 15:48:51 +00:00
//FAWE start - listen for inventory, flush & prepare changeset
2018-08-12 14:03:07 +00:00
context . setExtent ( editSession . bypassAll ) ;
ChangeSet changeSet = getChangeSet ( ) ;
2019-07-18 16:07:31 +00:00
setChangeSet ( null ) ;
2021-07-24 15:34:05 +00:00
Operations . completeBlindly ( ChangeSetExecutor . create (
changeSet ,
context ,
ChangeSetExecutor . Type . REDO ,
editSession . getBlockBag ( ) ,
editSession . getLimit ( ) . INVENTORY_MODE
) ) ;
2018-08-12 14:03:07 +00:00
flushQueue ( ) ;
editSession . changes = 1 ;
2014-03-31 23:55:58 +00:00
}
2021-07-23 15:48:51 +00:00
//FAWE end
2011-10-24 02:04:45 +00:00
2014-03-31 23:55:58 +00:00
/ * *
* Get the number of changed blocks .
*
* @return the number of changes
* /
public int size ( ) {
2019-03-28 19:02:37 +00:00
return getBlockChangeCount ( ) ;
2018-08-12 14:03:07 +00:00
}
2021-08-17 21:13:51 +00:00
@Override
public BlockVector3 getMinimumPoint ( ) {
return getWorld ( ) . getMinimumPoint ( ) ;
}
@Override
public BlockVector3 getMaximumPoint ( ) {
return getWorld ( ) . getMaximumPoint ( ) ;
}
2021-07-23 15:48:51 +00:00
//FAWE start
2018-08-12 14:03:07 +00:00
public void setSize ( int size ) {
this . changes = size ;
2014-03-31 23:55:58 +00:00
}
2021-07-23 15:48:51 +00:00
//FAWE end
2011-10-24 02:04:45 +00:00
2019-02-27 14:01:07 +00:00
/ * *
2020-10-05 17:41:41 +00:00
* Closing an EditSession flushes its buffers to the world , and performs other
* cleanup tasks .
2019-02-27 14:01:07 +00:00
* /
@Override
public void close ( ) {
2021-09-19 20:02:41 +00:00
flushQueue ( ) ;
dumpTracingInformation ( ) ;
}
private void dumpTracingInformation ( ) {
if ( this . tracingExtents = = null ) {
return ;
}
List < TracingExtent > tracingExtents = getActiveTracingExtents ( ) ;
assert actor ! = null ;
if ( tracingExtents . isEmpty ( ) ) {
actor . printError ( TextComponent . of ( " worldedit.trace.no-tracing-extents " ) ) ;
return ;
}
// find the common stacks
Set < List < TracingExtent > > stacks = new LinkedHashSet < > ( ) ;
Map < List < TracingExtent > , BlockVector3 > stackToPosition = new HashMap < > ( ) ;
Set < BlockVector3 > touchedLocations = Collections . newSetFromMap ( BlockMap . create ( ) ) ;
for ( TracingExtent tracingExtent : tracingExtents ) {
touchedLocations . addAll ( tracingExtent . getTouchedLocations ( ) ) ;
}
for ( BlockVector3 loc : touchedLocations ) {
List < TracingExtent > stack = tracingExtents . stream ( )
. filter ( it - > it . getTouchedLocations ( ) . contains ( loc ) )
. collect ( Collectors . toList ( ) ) ;
boolean anyFailed = stack . stream ( )
. anyMatch ( it - > it . getFailedActions ( ) . containsKey ( loc ) ) ;
if ( anyFailed & & stacks . add ( stack ) ) {
stackToPosition . put ( stack , loc ) ;
}
}
stackToPosition . forEach ( ( stack , position ) - > {
// stack can never be empty, something has to have touched the position
TracingExtent failure = stack . get ( 0 ) ;
actor . printDebug ( Caption . of (
" worldedit.trace.action-failed " ,
failure . getFailedActions ( ) . get ( position ) . toString ( ) ,
position . toString ( ) ,
failure . getExtent ( ) . getClass ( ) . getName ( )
) ) ;
} ) ;
2019-02-27 14:01:07 +00:00
}
/ * *
* Communicate to the EditSession that all block changes are complete ,
* and that it should apply them to the world .
2020-10-05 17:41:41 +00:00
*
* @deprecated Replace with { @link # close ( ) } for proper cleanup behavior .
2019-02-27 14:01:07 +00:00
* /
2020-10-05 17:41:41 +00:00
@Deprecated
2019-02-27 14:01:07 +00:00
public void flushSession ( ) {
2019-04-03 11:28:57 +00:00
flushQueue ( ) ;
2019-02-27 14:01:07 +00:00
}
2021-07-23 15:48:51 +00:00
//FAWE start
2021-07-24 15:34:05 +00:00
2014-03-31 23:55:58 +00:00
/ * *
* Finish off the queue .
* /
public void flushQueue ( ) {
2014-04-01 23:21:27 +00:00
Operations . completeBlindly ( commit ( ) ) ;
2018-08-12 14:03:07 +00:00
// Check fails
FaweLimit used = getLimitUsed ( ) ;
if ( used . MAX_FAILS > 0 ) {
if ( used . MAX_CHANGES > 0 | | used . MAX_ENTITIES > 0 ) {
2021-09-19 20:02:41 +00:00
actor . print ( Caption . of ( " fawe.error.worldedit.some.fails " , used . MAX_FAILS ) ) ;
2020-10-05 17:41:41 +00:00
} else if ( new ExtentTraverser < > ( getExtent ( ) ) . findAndGet ( FaweRegionExtent . class ) ! = null ) {
2021-09-19 20:02:41 +00:00
actor . print ( Caption . of ( " fawe.cancel.worldedit.cancel.reason.outside.region " ) ) ;
2018-08-12 14:03:07 +00:00
} else {
2021-09-19 20:02:41 +00:00
actor . print ( Caption . of ( " fawe.cancel.worldedit.cancel.reason.outside.level " ) ) ;
2018-08-12 14:03:07 +00:00
}
}
2021-01-09 21:27:55 +00:00
if ( wnaMode ) {
getWorld ( ) . flush ( ) ;
}
2018-08-12 14:03:07 +00:00
// Reset limit
limit . set ( originalLimit ) ;
2021-01-11 19:29:16 +00:00
try {
if ( relighter ! = null & & ! ( relighter instanceof NullRelighter ) ) {
2021-01-13 17:24:14 +00:00
// Don't relight twice!
if ( ! relighter . isFinished ( ) & & relighter . getLock ( ) . tryLock ( ) ) {
try {
if ( Settings . IMP . LIGHTING . REMOVE_FIRST ) {
relighter . removeAndRelight ( true ) ;
} else {
relighter . fixLightingSafe ( true ) ;
}
} finally {
2021-01-13 17:09:44 +00:00
relighter . getLock ( ) . unlock ( ) ;
}
2021-01-11 19:29:16 +00:00
}
}
} catch ( Throwable e ) {
2021-09-19 20:02:41 +00:00
actor . print ( Caption . of ( " fawe.error.lighting " ) ) ;
2021-01-11 19:29:16 +00:00
e . printStackTrace ( ) ;
}
2021-08-17 11:07:48 +00:00
// Cancel any preloader associated with the actor if present
2021-09-19 20:02:41 +00:00
if ( getActor ( ) instanceof Player ) {
2021-08-17 14:38:47 +00:00
Preloader preloader = Fawe . imp ( ) . getPreloader ( false ) ;
if ( preloader ! = null ) {
2021-09-19 20:02:41 +00:00
preloader . cancel ( getActor ( ) ) ;
2021-08-17 14:38:47 +00:00
}
2021-08-17 11:07:48 +00:00
}
2018-08-12 14:03:07 +00:00
// Enqueue it
if ( getChangeSet ( ) ! = null ) {
if ( Settings . IMP . HISTORY . COMBINE_STAGES ) {
2020-01-06 08:36:16 +00:00
( ( AbstractChangeSet ) getChangeSet ( ) ) . closeAsync ( ) ;
2018-08-12 14:03:07 +00:00
} else {
2019-11-16 00:20:14 +00:00
try {
2020-04-23 16:07:01 +00:00
getChangeSet ( ) . close ( ) ;
2019-11-16 00:20:14 +00:00
} catch ( IOException e ) {
throw new RuntimeException ( e ) ;
}
2018-08-12 14:03:07 +00:00
}
}
2014-03-31 23:55:58 +00:00
}
2011-10-24 02:04:45 +00:00
2019-09-22 01:00:45 +00:00
public < B extends BlockStateHolder < B > > int fall ( final Region region , boolean fullHeight , final B replace ) {
2018-08-12 14:03:07 +00:00
FlatRegion flat = asFlatRegion ( region ) ;
final int startPerformY = region . getMinimumPoint ( ) . getBlockY ( ) ;
2021-08-17 21:13:51 +00:00
final int startCheckY = fullHeight ? getMinY ( ) : startPerformY ;
2018-08-12 14:03:07 +00:00
final int endY = region . getMaximumPoint ( ) . getBlockY ( ) ;
2020-04-23 16:07:01 +00:00
RegionVisitor visitor = new RegionVisitor ( flat , pos - > {
int x = pos . getX ( ) ;
int z = pos . getZ ( ) ;
int freeSpot = startCheckY ;
for ( int y = startCheckY ; y < = endY ; y + + ) {
if ( y < startPerformY ) {
if ( ! getBlockType ( x , y , z ) . getMaterial ( ) . isAir ( ) ) {
freeSpot = y + 1 ;
2018-08-12 14:03:07 +00:00
}
2020-04-23 16:07:01 +00:00
continue ;
}
BlockType block = getBlockType ( x , y , z ) ;
if ( ! block . getMaterial ( ) . isAir ( ) ) {
if ( freeSpot ! = y ) {
setBlock ( x , freeSpot , z , block ) ;
setBlock ( x , y , z , replace ) ;
2018-08-12 14:03:07 +00:00
}
2020-04-23 16:07:01 +00:00
freeSpot + + ;
2018-08-12 14:03:07 +00:00
}
2020-04-23 16:07:01 +00:00
}
return true ;
2021-07-24 14:47:22 +00:00
} , this ) ;
2018-08-12 14:03:07 +00:00
Operations . completeBlindly ( visitor ) ;
return this . changes ;
2010-10-05 07:40:50 +00:00
}
2010-10-11 08:22:47 +00:00
2020-05-07 16:29:18 +00:00
@Override
2021-07-24 15:34:05 +00:00
public < B extends BlockStateHolder < B > > int replaceBlocks ( Region region , Set < BaseBlock > filter , B replacement ) throws
MaxChangedBlocksException {
2020-05-07 16:29:18 +00:00
return this . changes = super . replaceBlocks ( region , filter , replacement ) ;
}
@Override
public int replaceBlocks ( Region region , Set < BaseBlock > filter , Pattern pattern ) throws MaxChangedBlocksException {
return this . changes = super . replaceBlocks ( region , filter , pattern ) ;
}
@Override
public int replaceBlocks ( Region region , Mask mask , Pattern pattern ) throws MaxChangedBlocksException {
return this . changes = super . replaceBlocks ( region , mask , pattern ) ;
}
2010-10-11 08:22:47 +00:00
/ * *
* Fills an area recursively in the X / Z directions .
2011-09-24 19:32:03 +00:00
*
2021-07-24 15:34:05 +00:00
* @param origin the location to start from
* @param pattern the block to fill with
* @param radius the radius of the spherical area to fill
* @param depth the maximum depth , starting from the origin
2018-08-12 14:03:07 +00:00
* @param direction the direction to fill
2020-06-13 18:41:36 +00:00
* @return the number of blocks affected
2018-08-12 14:03:07 +00:00
* @throws MaxChangedBlocksException thrown if too many blocks are changed
* /
2021-07-24 15:34:05 +00:00
public int fillDirection (
final BlockVector3 origin ,
final Pattern pattern ,
final double radius ,
final int depth ,
BlockVector3 direction
) throws MaxChangedBlocksException {
2018-08-12 14:03:07 +00:00
checkNotNull ( origin ) ;
checkNotNull ( pattern ) ;
checkArgument ( radius > = 0 , " radius >= 0 " ) ;
checkArgument ( depth > = 1 , " depth >= 1 " ) ;
2021-08-11 13:56:10 +00:00
if ( direction . equals ( BlockVector3 . UNIT_MINUS_Y ) ) {
2018-08-12 14:03:07 +00:00
return fillXZ ( origin , pattern , radius , depth , false ) ;
}
2021-07-24 15:34:05 +00:00
Mask mask = new MaskIntersection (
new RegionMask ( new EllipsoidRegion ( null , origin , Vector3 . at ( radius , radius , radius ) ) ) ,
Masks . negate ( new ExistingBlockMask ( EditSession . this ) )
) ;
2018-08-12 14:03:07 +00:00
// Want to replace blocks
final BlockReplace replace = new BlockReplace ( EditSession . this , pattern ) ;
// Pick how we're going to visit blocks
2021-08-17 21:13:51 +00:00
RecursiveVisitor visitor = new DirectionalVisitor ( mask , replace , origin , direction , ( int ) ( radius * 2 + 1 ) , minY , maxY ) ;
2018-08-12 14:03:07 +00:00
// Start at the origin
visitor . visit ( origin ) ;
// Execute
Operations . completeBlindly ( visitor ) ;
return this . changes = visitor . getAffected ( ) ;
}
2021-07-23 15:48:51 +00:00
//FAWE end
2018-08-12 14:03:07 +00:00
/ * *
* Fills an area recursively in the X / Z directions .
*
2021-07-24 15:34:05 +00:00
* @param origin the location to start from
* @param block the block to fill with
* @param radius the radius of the spherical area to fill
* @param depth the maximum depth , starting from the origin
2014-03-27 06:10:47 +00:00
* @param recursive whether a breadth - first search should be performed
2010-10-11 15:56:19 +00:00
* @return number of blocks affected
2014-03-27 06:10:47 +00:00
* @throws MaxChangedBlocksException thrown if too many blocks are changed
2010-10-11 08:22:47 +00:00
* /
2021-07-24 15:34:05 +00:00
public < B extends BlockStateHolder < B > > int fillXZ (
BlockVector3 origin ,
B block ,
double radius ,
int depth ,
boolean recursive
) throws MaxChangedBlocksException {
2019-09-02 19:22:43 +00:00
return fillXZ ( origin , ( Pattern ) block , radius , depth , recursive ) ;
2010-10-11 08:22:47 +00:00
}
2019-06-04 15:48:30 +00:00
2010-11-16 22:07:52 +00:00
/ * *
* Fills an area recursively in the X / Z directions .
2011-09-24 19:32:03 +00:00
*
2021-07-24 15:34:05 +00:00
* @param origin the origin to start the fill from
* @param pattern the pattern to fill with
* @param radius the radius of the spherical area to fill , with 0 as the smallest radius
* @param depth the maximum depth , starting from the origin , with 1 as the smallest depth
2014-03-27 06:10:47 +00:00
* @param recursive whether a breadth - first search should be performed
2010-11-16 22:07:52 +00:00
* @return number of blocks affected
2014-03-27 06:10:47 +00:00
* @throws MaxChangedBlocksException thrown if too many blocks are changed
2010-11-16 22:07:52 +00:00
* /
2021-07-24 15:34:05 +00:00
public int fillXZ ( BlockVector3 origin , Pattern pattern , double radius , int depth , boolean recursive ) throws
MaxChangedBlocksException {
2014-03-28 07:41:00 +00:00
checkNotNull ( origin ) ;
checkNotNull ( pattern ) ;
2014-03-28 03:48:36 +00:00
checkArgument ( radius > = 0 , " radius >= 0 " ) ;
checkArgument ( depth > = 1 , " depth >= 1 " ) ;
2019-06-04 15:48:30 +00:00
2020-01-04 10:11:13 +00:00
Mask mask = new MaskIntersection (
2019-06-04 15:48:30 +00:00
new RegionMask ( new EllipsoidRegion ( null , origin , Vector3 . at ( radius , radius , radius ) ) ) ,
new BoundedHeightMask (
2021-08-17 21:13:51 +00:00
Math . max ( origin . getBlockY ( ) - depth + 1 , minY ) ,
Math . min ( maxY , origin . getBlockY ( ) )
2021-07-24 15:34:05 +00:00
) ,
Masks . negate ( new ExistingBlockMask ( this ) )
) ;
2020-10-05 17:41:41 +00:00
2014-03-27 06:10:47 +00:00
// Want to replace blocks
2019-03-28 19:02:37 +00:00
BlockReplace replace = new BlockReplace ( this , pattern ) ;
2010-11-16 22:07:52 +00:00
2014-03-27 06:10:47 +00:00
// Pick how we're going to visit blocks
RecursiveVisitor visitor ;
2021-08-17 21:13:51 +00:00
//FAWE start - provide extent for preloading, min/max y
2014-03-27 06:10:47 +00:00
if ( recursive ) {
2021-08-17 21:13:51 +00:00
visitor = new RecursiveVisitor ( mask , replace , ( int ) ( radius * 2 + 1 ) , minY , maxY , this ) ;
2014-03-27 06:10:47 +00:00
} else {
2021-08-17 21:13:51 +00:00
visitor = new DownwardVisitor ( mask , replace , origin . getBlockY ( ) , ( int ) ( radius * 2 + 1 ) , minY , maxY , this ) ;
2010-11-16 22:07:52 +00:00
}
2021-08-17 00:47:09 +00:00
//FAWE end
2010-11-16 22:07:52 +00:00
2014-03-27 06:10:47 +00:00
// Start at the origin
visitor . visit ( origin ) ;
2010-11-16 22:07:52 +00:00
2014-03-27 06:10:47 +00:00
// Execute
2020-06-13 18:41:36 +00:00
Operations . completeLegacy ( visitor ) ;
2019-06-04 15:48:30 +00:00
2021-07-23 15:48:51 +00:00
//FAWE start
2018-08-12 14:03:07 +00:00
return this . changes = visitor . getAffected ( ) ;
2021-07-23 15:48:51 +00:00
//FAWE end
2010-11-16 22:07:52 +00:00
}
2010-10-11 08:22:47 +00:00
/ * *
2014-03-28 02:57:24 +00:00
* Remove a cuboid above the given position with a given apothem and a given height .
2011-09-24 19:32:03 +00:00
*
2014-03-28 02:57:24 +00:00
* @param position base position
2021-07-24 15:34:05 +00:00
* @param apothem an apothem of the cuboid ( on the XZ plane ) , where the minimum is 1
* @param height the height of the cuboid , where the minimum is 1
2010-10-11 15:56:19 +00:00
* @return number of blocks affected
2014-03-28 03:48:36 +00:00
* @throws MaxChangedBlocksException thrown if too many blocks are changed
2010-10-11 08:22:47 +00:00
* /
2018-12-23 16:19:33 +00:00
public int removeAbove ( BlockVector3 position , int apothem , int height ) throws MaxChangedBlocksException {
2014-03-28 07:41:00 +00:00
checkNotNull ( position ) ;
2014-03-28 02:57:24 +00:00
checkArgument ( apothem > = 1 , " apothem >= 1 " ) ;
checkArgument ( height > = 1 , " height >= 1 " ) ;
2010-10-11 08:22:47 +00:00
2019-04-03 03:36:32 +00:00
Region region = new CuboidRegion (
getWorld ( ) , // Causes clamping of Y range
2019-06-04 15:48:30 +00:00
position . add ( - apothem + 1 , 0 , - apothem + 1 ) ,
2021-07-24 15:34:05 +00:00
position . add ( apothem - 1 , height - 1 , apothem - 1 )
) ;
2019-07-28 22:20:00 +00:00
return setBlocks ( region , BlockTypes . AIR . getDefaultState ( ) ) ;
2010-10-11 08:22:47 +00:00
}
/ * *
2014-03-28 02:57:24 +00:00
* Remove a cuboid below the given position with a given apothem and a given height .
2011-09-24 19:32:03 +00:00
*
2014-03-28 02:57:24 +00:00
* @param position base position
2021-07-24 15:34:05 +00:00
* @param apothem an apothem of the cuboid ( on the XZ plane ) , where the minimum is 1
* @param height the height of the cuboid , where the minimum is 1
2010-10-11 15:56:19 +00:00
* @return number of blocks affected
2014-03-28 03:48:36 +00:00
* @throws MaxChangedBlocksException thrown if too many blocks are changed
2010-10-11 08:22:47 +00:00
* /
2018-12-23 16:19:33 +00:00
public int removeBelow ( BlockVector3 position , int apothem , int height ) throws MaxChangedBlocksException {
2014-03-28 07:41:00 +00:00
checkNotNull ( position ) ;
2014-03-28 02:57:24 +00:00
checkArgument ( apothem > = 1 , " apothem >= 1 " ) ;
checkArgument ( height > = 1 , " height >= 1 " ) ;
2010-11-06 22:09:32 +00:00
2019-06-04 15:48:30 +00:00
Region region = new CuboidRegion (
getWorld ( ) , // Causes clamping of Y range
position . add ( - apothem + 1 , 0 , - apothem + 1 ) ,
2021-07-24 15:34:05 +00:00
position . add ( apothem - 1 , - height + 1 , apothem - 1 )
) ;
2019-09-22 01:00:45 +00:00
return setBlocks ( region , BlockTypes . AIR . getDefaultState ( ) ) ;
2010-10-11 08:22:47 +00:00
}
2019-06-25 13:00:44 +00:00
/ * *
* Remove blocks of a certain type nearby a given position .
*
* @param position center position of cuboid
2021-07-24 15:34:05 +00:00
* @param mask the mask to match
* @param apothem an apothem of the cuboid , where the minimum is 1
2019-06-25 13:00:44 +00:00
* @return number of blocks affected
* @throws MaxChangedBlocksException thrown if too many blocks are changed
* /
2019-11-19 21:23:47 +00:00
public int removeNear ( BlockVector3 position , Mask mask , int apothem ) throws MaxChangedBlocksException {
2018-12-23 16:19:33 +00:00
checkNotNull ( position ) ;
checkArgument ( apothem > = 1 , " apothem >= 1 " ) ;
BlockVector3 adjustment = BlockVector3 . ONE . multiply ( apothem - 1 ) ;
Region region = new CuboidRegion (
getWorld ( ) , // Causes clamping of Y range
position . add ( adjustment . multiply ( - 1 ) ) ,
2021-07-24 15:34:05 +00:00
position . add ( adjustment )
) ;
2019-09-14 03:05:16 +00:00
return replaceBlocks ( region , mask , BlockTypes . AIR . getDefaultState ( ) ) ;
}
2019-08-06 15:29:09 +00:00
/ * *
* Sets the blocks at the center of the given region to the given pattern .
* If the center sits between two blocks on a certain axis , then two blocks
* will be placed to mark the center .
*
2021-07-24 15:34:05 +00:00
* @param region the region to find the center of
2019-08-06 15:29:09 +00:00
* @param pattern the replacement pattern
* @return the number of blocks placed
* @throws MaxChangedBlocksException thrown if too many blocks are changed
* /
public int center ( Region region , Pattern pattern ) throws MaxChangedBlocksException {
checkNotNull ( region ) ;
checkNotNull ( pattern ) ;
Vector3 center = region . getCenter ( ) ;
Region centerRegion = new CuboidRegion (
2019-09-14 03:05:16 +00:00
getWorld ( ) , // Causes clamping of Y range
BlockVector3 . at ( ( ( int ) center . getX ( ) ) , ( ( int ) center . getY ( ) ) , ( ( int ) center . getZ ( ) ) ) ,
BlockVector3 . at (
MathUtils . roundHalfUp ( center . getX ( ) ) ,
MathUtils . roundHalfUp ( center . getY ( ) ) ,
2021-07-24 15:34:05 +00:00
MathUtils . roundHalfUp ( center . getZ ( ) )
)
) ;
2019-08-06 15:29:09 +00:00
return setBlocks ( centerRegion , pattern ) ;
}
2010-10-11 08:22:47 +00:00
/ * *
2014-03-28 07:40:04 +00:00
* Make the faces of the given region as if it was a { @link CuboidRegion } .
2011-09-24 19:32:03 +00:00
*
2014-03-28 07:40:04 +00:00
* @param region the region
2021-07-24 15:34:05 +00:00
* @param block the block to place
2010-10-11 15:56:19 +00:00
* @return number of blocks affected
2014-07-29 21:23:00 +00:00
* @throws MaxChangedBlocksException thrown if too many blocks are changed
2020-10-05 17:41:41 +00:00
* @deprecated Use { @link EditSession # makeCuboidFaces ( Region , Pattern ) } .
2010-10-11 08:22:47 +00:00
* /
2020-10-05 17:41:41 +00:00
@Deprecated
2019-06-04 15:48:30 +00:00
public < B extends BlockStateHolder < B > > int makeCuboidFaces ( Region region , B block ) throws MaxChangedBlocksException {
2020-11-13 21:42:03 +00:00
return makeCuboidFaces ( region , ( Pattern ) block ) ;
2010-10-11 08:22:47 +00:00
}
2011-08-24 22:27:18 +00:00
/ * *
2014-03-28 07:40:04 +00:00
* Make the faces of the given region as if it was a { @link CuboidRegion } .
2011-08-22 06:55:50 +00:00
*
2021-07-24 15:34:05 +00:00
* @param region the region
2014-03-28 07:40:04 +00:00
* @param pattern the pattern to place
2011-08-22 06:55:50 +00:00
* @return number of blocks affected
2014-03-28 07:40:04 +00:00
* @throws MaxChangedBlocksException thrown if too many blocks are changed
2011-08-22 06:55:50 +00:00
* /
2019-06-25 13:00:44 +00:00
public int makeCuboidFaces ( Region region , Pattern pattern ) throws MaxChangedBlocksException {
2014-03-28 07:40:04 +00:00
checkNotNull ( region ) ;
checkNotNull ( pattern ) ;
2011-08-22 06:55:50 +00:00
2019-06-04 15:48:30 +00:00
CuboidRegion cuboid = CuboidRegion . makeCuboid ( region ) ;
Region faces = cuboid . getFaces ( ) ;
return setBlocks ( faces , pattern ) ;
2011-08-22 06:55:50 +00:00
}
2010-10-11 08:22:47 +00:00
2013-11-01 18:05:49 +00:00
/ * *
2014-03-28 07:40:04 +00:00
* Make the faces of the given region . The method by which the faces are found
* may be inefficient , because there may not be an efficient implementation supported
* for that specific shape .
2013-11-01 18:05:49 +00:00
*
2021-07-24 15:34:05 +00:00
* @param region the region
2014-03-28 07:40:04 +00:00
* @param pattern the pattern to place
2013-11-01 18:05:49 +00:00
* @return number of blocks affected
2014-03-28 07:40:04 +00:00
* @throws MaxChangedBlocksException thrown if too many blocks are changed
2013-11-01 18:05:49 +00:00
* /
2019-06-04 15:48:30 +00:00
public int makeFaces ( final Region region , Pattern pattern ) throws MaxChangedBlocksException {
2014-03-28 07:40:04 +00:00
checkNotNull ( region ) ;
checkNotNull ( pattern ) ;
if ( region instanceof CuboidRegion ) {
2019-06-04 15:48:30 +00:00
return makeCuboidFaces ( region , pattern ) ;
2014-03-28 07:40:04 +00:00
} else {
return new RegionShape ( region ) . generate ( this , pattern , true ) ;
}
2013-11-01 18:05:49 +00:00
}
2018-12-20 16:00:27 +00:00
2010-10-18 17:45:03 +00:00
/ * *
2014-03-28 07:40:04 +00:00
* Make the walls ( all faces but those parallel to the X - Z plane ) of the given region
* as if it was a { @link CuboidRegion } .
2011-09-24 19:32:03 +00:00
*
2014-03-28 07:40:04 +00:00
* @param region the region
2021-07-24 15:34:05 +00:00
* @param block the block to place
2010-10-18 17:45:03 +00:00
* @return number of blocks affected
2014-07-29 21:23:00 +00:00
* @throws MaxChangedBlocksException thrown if too many blocks are changed
2010-10-18 17:45:03 +00:00
* /
2019-06-04 15:48:30 +00:00
public < B extends BlockStateHolder < B > > int makeCuboidWalls ( Region region , B block ) throws MaxChangedBlocksException {
2019-09-14 03:05:16 +00:00
return makeCuboidWalls ( region , ( Pattern ) block ) ;
2010-10-18 17:45:03 +00:00
}
2011-08-22 06:55:50 +00:00
/ * *
2014-03-28 07:40:04 +00:00
* Make the walls ( all faces but those parallel to the X - Z plane ) of the given region
* as if it was a { @link CuboidRegion } .
2011-08-22 06:55:50 +00:00
*
2021-07-24 15:34:05 +00:00
* @param region the region
2014-03-28 07:40:04 +00:00
* @param pattern the pattern to place
2011-08-22 06:55:50 +00:00
* @return number of blocks affected
2014-03-28 07:40:04 +00:00
* @throws MaxChangedBlocksException thrown if too many blocks are changed
2011-08-22 06:55:50 +00:00
* /
2019-06-04 15:48:30 +00:00
public int makeCuboidWalls ( Region region , Pattern pattern ) throws MaxChangedBlocksException {
2014-03-28 07:40:04 +00:00
checkNotNull ( region ) ;
checkNotNull ( pattern ) ;
2011-08-22 06:55:50 +00:00
2021-07-23 15:48:51 +00:00
//FAWE start
2020-02-29 23:52:50 +00:00
int blocksChanged = 0 ;
for ( Region wall : CuboidRegion . makeCuboid ( region ) . getWalls ( ) . getRegions ( ) ) {
blocksChanged + = setBlocks ( wall , pattern ) ;
}
return blocksChanged ;
2021-07-23 15:48:51 +00:00
//FAWE end
2011-08-22 06:55:50 +00:00
}
2021-07-23 15:48:51 +00:00
//FAWE start
2021-07-24 15:34:05 +00:00
2013-11-01 18:05:49 +00:00
/ * *
2014-03-28 07:40:04 +00:00
* Make the walls of the given region . The method by which the walls are found
* may be inefficient , because there may not be an efficient implementation supported
* for that specific shape .
2013-11-01 18:05:49 +00:00
*
2021-07-24 15:34:05 +00:00
* @param region the region
2014-03-28 07:40:04 +00:00
* @param pattern the pattern to place
2013-11-01 18:05:49 +00:00
* @return number of blocks affected
2014-03-28 07:40:04 +00:00
* @throws MaxChangedBlocksException thrown if too many blocks are changed
2013-11-01 18:05:49 +00:00
* /
2019-06-25 13:00:44 +00:00
public int makeWalls ( final Region region , Pattern pattern ) throws MaxChangedBlocksException {
2014-03-28 07:40:04 +00:00
checkNotNull ( region ) ;
checkNotNull ( pattern ) ;
2013-11-03 09:15:28 +00:00
2014-03-28 07:40:04 +00:00
if ( region instanceof CuboidRegion ) {
2019-06-04 15:48:30 +00:00
return makeCuboidWalls ( region , pattern ) ;
2014-03-28 07:40:04 +00:00
} else {
2020-09-25 14:00:42 +00:00
replaceBlocks ( region , new WallMakeMask ( region ) , pattern ) ;
2014-03-28 07:40:04 +00:00
}
2018-09-13 16:42:55 +00:00
return changes ;
2013-11-01 18:05:49 +00:00
}
2021-07-23 15:48:51 +00:00
//FAWE end
2013-11-01 18:05:49 +00:00
2010-10-11 08:22:47 +00:00
/ * *
2014-03-28 23:49:01 +00:00
* Places a layer of blocks on top of ground blocks in the given region
* ( as if it were a cuboid ) .
2011-09-24 19:32:03 +00:00
*
2014-03-28 23:49:01 +00:00
* @param region the region
2021-07-24 15:34:05 +00:00
* @param block the placed block
2010-10-11 15:56:19 +00:00
* @return number of blocks affected
2014-03-28 23:49:01 +00:00
* @throws MaxChangedBlocksException thrown if too many blocks are changed
2020-10-05 17:41:41 +00:00
* @deprecated Use { @link EditSession # overlayCuboidBlocks ( Region , Pattern ) } .
2010-10-11 08:22:47 +00:00
* /
2020-10-05 17:41:41 +00:00
@Deprecated
2018-12-27 00:39:10 +00:00
public < B extends BlockStateHolder < B > > int overlayCuboidBlocks ( Region region , B block ) throws MaxChangedBlocksException {
2014-03-28 23:49:01 +00:00
checkNotNull ( block ) ;
2019-09-14 03:05:16 +00:00
return overlayCuboidBlocks ( region , ( Pattern ) block ) ;
2011-01-30 08:47:02 +00:00
}
/ * *
2014-03-28 23:49:01 +00:00
* Places a layer of blocks on top of ground blocks in the given region
* ( as if it were a cuboid ) .
2011-09-24 19:32:03 +00:00
*
2021-07-24 15:34:05 +00:00
* @param region the region
2014-03-28 23:49:01 +00:00
* @param pattern the placed block pattern
2011-01-30 08:47:02 +00:00
* @return number of blocks affected
2014-03-28 23:49:01 +00:00
* @throws MaxChangedBlocksException thrown if too many blocks are changed
2011-01-30 08:47:02 +00:00
* /
2019-06-04 15:48:30 +00:00
public int overlayCuboidBlocks ( Region region , Pattern pattern ) throws MaxChangedBlocksException {
2014-03-28 23:49:01 +00:00
checkNotNull ( region ) ;
checkNotNull ( pattern ) ;
2019-06-25 13:00:44 +00:00
2019-06-04 15:48:30 +00:00
BlockReplace replace = new BlockReplace ( this , pattern ) ;
RegionOffset offset = new RegionOffset ( BlockVector3 . UNIT_Y , replace ) ;
2021-07-23 15:48:51 +00:00
//FAWE start
2018-08-12 14:03:07 +00:00
int minY = region . getMinimumPoint ( ) . getBlockY ( ) ;
int maxY = Math . min ( getMaximumPoint ( ) . getBlockY ( ) , region . getMaximumPoint ( ) . getBlockY ( ) + 1 ) ;
SurfaceRegionFunction surface = new SurfaceRegionFunction ( this , offset , minY , maxY ) ;
2021-08-17 00:47:09 +00:00
FlatRegionVisitor visitor = new FlatRegionVisitor ( asFlatRegion ( region ) , surface , this ) ;
2021-07-23 15:48:51 +00:00
//FAWE end
2018-08-12 14:03:07 +00:00
Operations . completeBlindly ( visitor ) ;
return this . changes = visitor . getAffected ( ) ;
2010-10-11 08:22:47 +00:00
}
2011-08-02 22:46:11 +00:00
/ * *
* Turns the first 3 layers into dirt / grass and the bottom layers
* into rock , like a natural Minecraft mountain .
*
2014-03-30 01:32:10 +00:00
* @param region the region to affect
2011-08-02 22:46:11 +00:00
* @return number of blocks affected
2014-03-30 01:32:10 +00:00
* @throws MaxChangedBlocksException thrown if too many blocks are changed
2011-08-02 22:46:11 +00:00
* /
2019-06-04 15:48:30 +00:00
public int naturalizeCuboidBlocks ( Region region ) throws MaxChangedBlocksException {
2014-03-30 01:32:10 +00:00
checkNotNull ( region ) ;
2019-06-04 15:48:30 +00:00
Naturalizer naturalizer = new Naturalizer ( this ) ;
FlatRegion flatRegion = Regions . asFlatRegion ( region ) ;
2021-08-17 00:47:09 +00:00
//FAWE start - provide extent for preloading
LayerVisitor visitor = new LayerVisitor ( flatRegion , minimumBlockY ( region ) , maximumBlockY ( region ) , naturalizer , this ) ;
//FAWE end
2018-08-12 14:03:07 +00:00
Operations . completeBlindly ( visitor ) ;
return this . changes = naturalizer . getAffected ( ) ;
}
2011-08-02 22:46:11 +00:00
2010-10-11 17:27:18 +00:00
/ * *
2019-11-20 00:11:54 +00:00
* Stack a cuboid region . For compatibility , entities are copied by biomes are not .
* Use { @link # stackCuboidRegion ( Region , BlockVector3 , int , boolean , boolean , Mask ) } to fine tune .
*
2021-07-24 15:34:05 +00:00
* @param region the region to stack
* @param dir the direction to stack
* @param count the number of times to stack
2019-11-20 00:11:54 +00:00
* @param copyAir true to also copy air blocks
* @return number of blocks affected
* @throws MaxChangedBlocksException thrown if too many blocks are changed
* /
public int stackCuboidRegion ( Region region , BlockVector3 dir , int count , boolean copyAir ) throws MaxChangedBlocksException {
return stackCuboidRegion ( region , dir , count , true , false , copyAir ? null : new ExistingBlockMask ( this ) ) ;
}
2021-07-23 15:48:51 +00:00
//FAWE start
2021-07-24 15:34:05 +00:00
2019-11-20 00:11:54 +00:00
/ * *
* Stack a cuboid region .
2011-09-24 19:32:03 +00:00
*
2021-07-24 15:34:05 +00:00
* @param region the region to stack
2021-09-19 20:02:41 +00:00
* @param offset how far to move the contents each stack . Is directional .
2021-07-24 15:34:05 +00:00
* @param count the number of times to stack
2019-08-03 16:59:24 +00:00
* @param copyEntities true to copy entities
2021-07-24 15:34:05 +00:00
* @param copyBiomes true to copy biomes
* @param mask source mask for the operation ( only matching blocks are copied )
2010-10-11 17:27:18 +00:00
* @return number of blocks affected
2014-03-30 10:08:56 +00:00
* @throws MaxChangedBlocksException thrown if too many blocks are changed
2010-10-11 17:27:18 +00:00
* /
2021-07-24 15:34:05 +00:00
public int stackCuboidRegion (
2021-09-19 20:02:41 +00:00
Region region , BlockVector3 offset , int count ,
2021-07-24 15:34:05 +00:00
boolean copyEntities , boolean copyBiomes , Mask mask
) throws MaxChangedBlocksException {
2014-03-30 10:08:56 +00:00
checkNotNull ( region ) ;
2021-09-19 20:02:41 +00:00
checkNotNull ( offset ) ;
2014-03-30 10:08:56 +00:00
checkArgument ( count > = 1 , " count >= 1 required " ) ;
2019-06-25 13:00:44 +00:00
2019-06-04 15:48:30 +00:00
BlockVector3 size = region . getMaximumPoint ( ) . subtract ( region . getMinimumPoint ( ) ) . add ( 1 , 1 , 1 ) ;
BlockVector3 to = region . getMinimumPoint ( ) ;
ForwardExtentCopy copy = new ForwardExtentCopy ( this , region , this , to ) ;
2014-03-30 10:08:56 +00:00
copy . setRepetitions ( count ) ;
2021-09-19 20:02:41 +00:00
copy . setTransform ( new AffineTransform ( ) . translate ( offset . multiply ( size ) ) ) ;
2020-03-21 01:39:40 +00:00
copy . setCopyingEntities ( copyEntities ) ;
copy . setCopyingBiomes ( copyBiomes ) ;
2021-01-10 14:59:21 +00:00
final Region allowedRegion ;
if ( allowedRegions = = null | | allowedRegions . length = = 0 ) {
allowedRegion = new NullRegion ( ) ;
} else {
allowedRegion = new RegionIntersection ( allowedRegions ) ;
}
mask = MaskIntersection . of ( getSourceMask ( ) , mask , new RegionMask ( allowedRegion ) ) . optimize ( ) ;
2019-11-20 00:11:54 +00:00
if ( mask ! = Masks . alwaysTrue ( ) ) {
2018-08-12 14:03:07 +00:00
setSourceMask ( null ) ;
2019-11-20 00:11:54 +00:00
copy . setSourceMask ( mask ) ;
2010-10-11 08:22:47 +00:00
}
2020-04-10 17:22:28 +00:00
Operations . completeLegacy ( copy ) ;
2018-08-12 14:03:07 +00:00
return this . changes = copy . getAffected ( ) ;
2010-10-11 08:22:47 +00:00
}
2021-07-23 15:48:51 +00:00
//FAWE end
2010-10-11 18:17:32 +00:00
2020-03-21 01:39:40 +00:00
/ * *
* Move the blocks in a region a certain direction .
*
2021-07-24 15:34:05 +00:00
* @param region the region to move
2021-09-19 20:02:41 +00:00
* @param offset the offset . Is directional .
* @param multiplier the number to multiply the offset by
2021-07-24 15:34:05 +00:00
* @param copyAir true to copy air blocks
2020-03-21 01:39:40 +00:00
* @param moveEntities true to move entities
2021-07-24 15:34:05 +00:00
* @param copyBiomes true to copy biomes
* @param replacement the replacement pattern to fill in after moving , or null to use air
2020-03-21 01:39:40 +00:00
* @return number of blocks moved
* @throws MaxChangedBlocksException thrown if too many blocks are changed
* /
2021-07-24 15:34:05 +00:00
public int moveRegion (
Region region ,
2021-09-19 20:02:41 +00:00
BlockVector3 offset ,
int multiplier ,
2021-07-24 15:34:05 +00:00
boolean copyAir ,
boolean moveEntities ,
boolean copyBiomes ,
Pattern replacement
) throws MaxChangedBlocksException {
2021-07-23 15:48:51 +00:00
//FAWE start
2019-11-19 22:07:30 +00:00
Mask mask = null ;
if ( ! copyAir ) {
mask = new ExistingBlockMask ( this ) ;
}
2021-09-19 20:02:41 +00:00
return moveRegion ( region , offset , multiplier , moveEntities , copyBiomes , mask , replacement ) ;
2021-07-23 15:48:51 +00:00
//FAWE end
2019-11-19 22:07:30 +00:00
}
2013-08-03 23:22:29 +00:00
/ * *
2014-03-30 17:29:00 +00:00
* Move the blocks in a region a certain direction .
2013-08-03 23:22:29 +00:00
*
2021-07-24 15:34:05 +00:00
* @param region the region to move
2021-09-19 20:02:41 +00:00
* @param offset the offset . Is directional .
* @param multiplier the number to multiply the offset by
2019-08-03 16:59:24 +00:00
* @param moveEntities true to move entities
2021-07-24 15:34:05 +00:00
* @param copyBiomes true to copy biomes ( source biome is unchanged )
* @param mask source mask for the operation ( only matching blocks are moved )
* @param replacement the replacement pattern to fill in after moving , or null to use air
2013-08-03 23:22:29 +00:00
* @return number of blocks moved
2014-03-30 17:29:00 +00:00
* @throws MaxChangedBlocksException thrown if too many blocks are changed
2021-07-24 15:34:05 +00:00
* @throws IllegalArgumentException thrown if the region is not a flat region , but copyBiomes is true
2013-08-03 23:22:29 +00:00
* /
2021-07-24 15:34:05 +00:00
public int moveRegion (
2021-09-19 20:02:41 +00:00
Region region , BlockVector3 offset , int multiplier ,
2021-07-24 15:34:05 +00:00
boolean moveEntities , boolean copyBiomes , Mask mask , Pattern replacement
) throws MaxChangedBlocksException {
2014-03-30 17:29:00 +00:00
checkNotNull ( region ) ;
2021-09-19 20:02:41 +00:00
checkNotNull ( offset ) ;
checkArgument ( multiplier > = 1 , " distance >= 1 required " ) ;
2019-09-14 03:05:16 +00:00
checkArgument ( ! copyBiomes | | region instanceof FlatRegion , " can't copy biomes from non-flat region " ) ;
2021-07-23 15:48:51 +00:00
//FAWE start - add up distance
2021-09-19 20:02:41 +00:00
BlockVector3 to = region . getMinimumPoint ( ) . add ( offset . multiply ( multiplier ) ) ;
2013-08-03 23:22:29 +00:00
2021-09-19 20:02:41 +00:00
final BlockVector3 displace = offset . multiply ( multiplier ) ;
2018-12-23 16:19:33 +00:00
final BlockVector3 size = region . getMaximumPoint ( ) . subtract ( region . getMinimumPoint ( ) ) . add ( 1 , 1 , 1 ) ;
2013-08-03 23:22:29 +00:00
2018-12-23 16:19:33 +00:00
BlockVector3 disAbs = displace . abs ( ) ;
2014-03-30 17:29:00 +00:00
2018-08-12 14:03:07 +00:00
if ( disAbs . getBlockX ( ) < size . getBlockX ( ) & & disAbs . getBlockY ( ) < size . getBlockY ( ) & & disAbs . getBlockZ ( ) < size . getBlockZ ( ) ) {
// Buffer if overlapping
2021-01-10 13:22:47 +00:00
enableQueue ( ) ;
2013-08-03 23:22:29 +00:00
}
2019-06-04 15:48:30 +00:00
ForwardExtentCopy copy = new ForwardExtentCopy ( this , region , this , to ) ;
2014-03-30 17:29:00 +00:00
2020-10-05 17:41:41 +00:00
if ( replacement = = null ) {
replacement = BlockTypes . AIR . getDefaultState ( ) ;
}
2019-07-06 00:46:48 +00:00
BlockReplace remove = replacement instanceof ExistingPattern ? null : new BlockReplace ( this , replacement ) ;
2019-06-25 13:00:44 +00:00
copy . setSourceFunction ( remove ) ; // Remove
2019-09-14 03:05:16 +00:00
copy . setCopyingEntities ( moveEntities ) ;
copy . setRemovingEntities ( moveEntities ) ;
copy . setCopyingBiomes ( copyBiomes ) ;
2018-08-12 14:03:07 +00:00
copy . setRepetitions ( 1 ) ;
2021-01-10 14:59:21 +00:00
final Region allowedRegion ;
if ( allowedRegions = = null | | allowedRegions . length = = 0 ) {
allowedRegion = new NullRegion ( ) ;
} else {
allowedRegion = new RegionIntersection ( allowedRegions ) ;
}
2021-01-10 17:36:41 +00:00
Mask sourceMask = this . getSourceMask ( ) ;
mask = MaskIntersection . of ( sourceMask , mask , new RegionMask ( allowedRegion ) ) . optimize ( ) ;
2021-01-10 14:59:21 +00:00
if ( mask ! = Masks . alwaysTrue ( ) ) {
2019-11-19 22:07:30 +00:00
copy . setSourceMask ( mask ) ;
2021-01-10 17:36:41 +00:00
if ( sourceMask ! = null & & sourceMask . equals ( mask ) ) {
2019-11-19 22:07:30 +00:00
setSourceMask ( null ) ;
}
2018-08-12 14:03:07 +00:00
}
Operations . completeBlindly ( copy ) ;
return this . changes = copy . getAffected ( ) ;
2021-07-23 15:48:51 +00:00
//FAWE end
2013-08-03 23:22:29 +00:00
}
2010-10-18 20:51:43 +00:00
/ * *
2014-03-30 20:56:12 +00:00
* Move the blocks in a region a certain direction .
2011-09-24 19:32:03 +00:00
*
2021-07-24 15:34:05 +00:00
* @param region the region to move
* @param dir the direction
* @param distance the distance to move
* @param copyAir true to copy air blocks
2018-12-22 07:26:02 +00:00
* @param replacement the replacement pattern to fill in after moving , or null to use air
2010-10-18 20:51:43 +00:00
* @return number of blocks moved
2014-03-30 20:56:12 +00:00
* @throws MaxChangedBlocksException thrown if too many blocks are changed
2010-10-18 20:51:43 +00:00
* /
2021-07-24 15:34:05 +00:00
public int moveCuboidRegion ( Region region , BlockVector3 dir , int distance , boolean copyAir , Pattern replacement ) throws
MaxChangedBlocksException {
2019-06-04 15:48:30 +00:00
return moveRegion ( region , dir , distance , copyAir , true , false , replacement ) ;
2010-10-18 20:51:43 +00:00
}
2010-10-11 18:17:32 +00:00
/ * *
* Drain nearby pools of water or lava .
2011-09-24 19:32:03 +00:00
*
2014-03-30 21:10:01 +00:00
* @param origin the origin to drain from , which will search a 3x3 area
* @param radius the radius of the removal , where a value should be 0 or greater
2010-10-11 18:17:32 +00:00
* @return number of blocks affected
2014-03-30 21:46:50 +00:00
* @throws MaxChangedBlocksException thrown if too many blocks are changed
2010-10-11 18:17:32 +00:00
* /
2019-06-04 15:48:30 +00:00
public int drainArea ( BlockVector3 origin , double radius ) throws MaxChangedBlocksException {
2019-02-12 21:39:09 +00:00
return drainArea ( origin , radius , false ) ;
}
2019-06-04 15:48:30 +00:00
/ * *
* Drain nearby pools of water or lava , optionally removed waterlogged states from blocks .
*
2021-07-24 15:34:05 +00:00
* @param origin the origin to drain from , which will search a 3x3 area
* @param radius the radius of the removal , where a value should be 0 or greater
2019-06-04 15:48:30 +00:00
* @param waterlogged true to make waterlogged blocks non - waterlogged as well
* @return number of blocks affected
* @throws MaxChangedBlocksException thrown if too many blocks are changed
* /
public int drainArea ( BlockVector3 origin , double radius , boolean waterlogged ) throws MaxChangedBlocksException {
2020-07-03 13:01:16 +00:00
return drainArea ( origin , radius , waterlogged , false ) ;
}
/ * *
* Drain nearby pools of water or lava , optionally removed waterlogged states from blocks .
*
2021-07-24 15:34:05 +00:00
* @param origin the origin to drain from , which will search a 3x3 area
* @param radius the radius of the removal , where a value should be 0 or greater
2020-07-03 13:01:16 +00:00
* @param waterlogged true to make waterlogged blocks non - waterlogged as well
2021-07-24 15:34:05 +00:00
* @param plants true to remove underwater plants
2020-07-03 13:01:16 +00:00
* @return number of blocks affected
* @throws MaxChangedBlocksException thrown if too many blocks are changed
* /
2021-07-24 15:34:05 +00:00
public int drainArea ( BlockVector3 origin , double radius , boolean waterlogged , boolean plants ) throws
MaxChangedBlocksException {
2014-03-30 21:10:01 +00:00
checkNotNull ( origin ) ;
checkArgument ( radius > = 0 , " radius >= 0 required " ) ;
2019-06-25 13:00:44 +00:00
2021-07-23 15:48:51 +00:00
//FAWE start - liquidmask
2020-07-03 13:01:16 +00:00
Mask liquidMask ;
if ( plants ) {
2020-10-05 17:41:41 +00:00
liquidMask = new BlockTypeMask ( this , BlockTypes . LAVA , BlockTypes . WATER ,
2021-07-24 15:34:05 +00:00
BlockTypes . KELP_PLANT , BlockTypes . KELP , BlockTypes . SEAGRASS , BlockTypes . TALL_SEAGRASS
) ;
2020-07-03 13:01:16 +00:00
} else {
2021-07-23 15:48:51 +00:00
liquidMask = new BlockMaskBuilder ( )
. addTypes ( BlockTypes . WATER , BlockTypes . LAVA )
. build ( this ) ;
2020-07-03 13:01:16 +00:00
}
2021-07-23 15:48:51 +00:00
//FAWE end
2020-07-03 12:49:17 +00:00
if ( waterlogged ) {
Map < String , String > stateMap = new HashMap < > ( ) ;
stateMap . put ( " waterlogged " , " true " ) ;
2021-07-23 15:48:51 +00:00
//FAWE start
2020-07-03 12:49:17 +00:00
liquidMask = new MaskUnion ( liquidMask , new BlockStateMask ( this , stateMap , true ) ) ;
2021-07-23 15:48:51 +00:00
//FAWE end
2020-07-03 12:49:17 +00:00
}
2020-01-04 10:11:13 +00:00
Mask mask = new MaskIntersection (
2021-08-17 21:13:51 +00:00
new BoundedHeightMask ( minY , maxY ) ,
2021-07-24 15:34:05 +00:00
new RegionMask ( new EllipsoidRegion ( null , origin , Vector3 . at ( radius , radius , radius ) ) ) ,
//FAWE start
liquidMask
) ;
2021-07-23 15:48:51 +00:00
//FAWE end
2019-06-12 21:12:12 +00:00
BlockReplace replace ;
if ( waterlogged ) {
replace = new BlockReplace ( this , new WaterloggedRemover ( this ) ) ;
} else {
2019-07-06 00:46:48 +00:00
replace = new BlockReplace ( this , BlockTypes . AIR . getDefaultState ( ) ) ;
2019-06-12 21:12:12 +00:00
}
2021-08-17 21:13:51 +00:00
//FAWE start - provide extent for preloading, min/max y
RecursiveVisitor visitor = new RecursiveVisitor ( mask , replace , ( int ) ( radius * 2 + 1 ) , minY , maxY , this ) ;
2021-08-17 00:47:09 +00:00
//FAWE end
2014-03-30 21:10:01 +00:00
// Around the origin in a 3x3 block
2019-06-04 15:48:30 +00:00
for ( BlockVector3 position : CuboidRegion . fromCenter ( origin , 1 ) ) {
2020-09-11 19:13:31 +00:00
if ( mask . test ( position ) ) {
2014-03-30 21:10:01 +00:00
visitor . visit ( position ) ;
2010-10-11 18:17:32 +00:00
}
}
2014-04-01 23:21:27 +00:00
Operations . completeLegacy ( visitor ) ;
2019-06-25 13:00:44 +00:00
2021-07-23 15:48:51 +00:00
//FAWE start
2018-08-12 14:03:07 +00:00
return this . changes = visitor . getAffected ( ) ;
2021-07-23 15:48:51 +00:00
//FAWE end
2010-10-15 08:07:48 +00:00
}
/ * *
2014-03-30 21:46:50 +00:00
* Fix liquids so that they turn into stationary blocks and extend outward .
2011-09-24 19:32:03 +00:00
*
2018-12-20 16:00:27 +00:00
* @param origin the original position
* @param radius the radius to fix
2021-07-24 15:34:05 +00:00
* @param fluid the type of the fluid
2010-10-15 08:07:48 +00:00
* @return number of blocks affected
2014-03-30 21:46:50 +00:00
* @throws MaxChangedBlocksException thrown if too many blocks are changed
2010-10-15 08:07:48 +00:00
* /
2019-06-04 15:48:30 +00:00
public int fixLiquid ( BlockVector3 origin , double radius , BlockType fluid ) throws MaxChangedBlocksException {
2014-03-30 21:45:42 +00:00
checkNotNull ( origin ) ;
checkArgument ( radius > = 0 , " radius >= 0 required " ) ;
2010-10-15 08:07:48 +00:00
2019-04-09 03:29:43 +00:00
// Our origins can only be liquids
2019-11-14 17:57:43 +00:00
Mask liquidMask = new SingleBlockTypeMask ( this , fluid ) ;
2019-04-09 03:29:43 +00:00
// But we will also visit air blocks
MaskIntersection blockMask = new MaskUnion ( liquidMask , Masks . negate ( new ExistingBlockMask ( this ) ) ) ;
2014-03-30 21:45:42 +00:00
// There are boundaries that the routine needs to stay in
2020-02-06 00:43:50 +00:00
Mask mask = new MaskIntersection (
2021-09-08 15:39:43 +00:00
new BoundedHeightMask ( minY , Math . min ( origin . getBlockY ( ) , maxY ) ) ,
2018-10-19 20:13:32 +00:00
new RegionMask ( new EllipsoidRegion ( null , origin , Vector3 . at ( radius , radius , radius ) ) ) ,
2019-06-04 15:48:30 +00:00
blockMask
2020-09-11 19:13:31 +00:00
) ;
2020-10-05 17:41:41 +00:00
2019-07-06 00:46:48 +00:00
BlockReplace replace = new BlockReplace ( this , fluid . getDefaultState ( ) ) ;
2021-08-17 21:13:51 +00:00
//FAWE start - provide extent for preloading, world min/maxY
NonRisingVisitor visitor = new NonRisingVisitor ( mask , replace , Integer . MAX_VALUE , minY , maxY , this ) ;
2021-08-17 00:47:09 +00:00
//FAWE end
2011-09-24 19:32:03 +00:00
2019-11-21 07:57:32 +00:00
// Around the origin in a 3x3 block
2018-12-23 16:19:33 +00:00
for ( BlockVector3 position : CuboidRegion . fromCenter ( origin , 1 ) ) {
2020-09-11 19:13:31 +00:00
if ( liquidMask . test ( position ) ) {
2014-03-30 21:45:42 +00:00
visitor . visit ( position ) ;
2010-10-15 08:07:48 +00:00
}
}
2010-10-11 18:17:32 +00:00
2019-04-09 03:29:43 +00:00
Operations . completeLegacy ( visitor ) ;
2019-06-04 15:48:30 +00:00
2019-04-09 03:29:43 +00:00
return visitor . getAffected ( ) ;
2010-10-11 18:17:32 +00:00
}
2010-10-18 00:22:29 +00:00
/ * *
2011-10-26 20:50:46 +00:00
* Makes a cylinder .
2011-09-24 19:32:03 +00:00
*
2021-07-24 15:34:05 +00:00
* @param pos Center of the cylinder
* @param block The block pattern to use
2011-10-26 20:50:46 +00:00
* @param radius The cylinder ' s radius
* @param height The cylinder ' s up / down extent . If negative , extend downward .
* @param filled If false , only a shell will be generated .
* @return number of blocks changed
2014-07-29 21:23:00 +00:00
* @throws MaxChangedBlocksException thrown if too many blocks are changed
2011-10-26 20:50:46 +00:00
* /
2021-07-24 15:34:05 +00:00
public int makeCylinder ( BlockVector3 pos , Pattern block , double radius , int height , boolean filled ) throws
MaxChangedBlocksException {
2019-03-28 19:02:37 +00:00
return makeCylinder ( pos , block , radius , radius , height , filled ) ;
2011-10-26 20:50:46 +00:00
}
/ * *
* Makes a cylinder .
*
2021-07-24 15:34:05 +00:00
* @param pos Center of the cylinder
* @param block The block pattern to use
2011-10-28 18:16:19 +00:00
* @param radiusX The cylinder ' s largest north / south extent
* @param radiusZ The cylinder ' s largest east / west extent
2021-07-24 15:34:05 +00:00
* @param height The cylinder ' s up / down extent . If negative , extend downward .
* @param filled If false , only a shell will be generated .
2011-10-28 18:16:19 +00:00
* @return number of blocks changed
2014-07-29 21:23:00 +00:00
* @throws MaxChangedBlocksException thrown if too many blocks are changed
2010-10-18 00:22:29 +00:00
* /
2021-07-24 15:34:05 +00:00
public int makeCylinder ( BlockVector3 pos , Pattern block , double radiusX , double radiusZ , int height , boolean filled ) throws
MaxChangedBlocksException {
2018-08-12 14:03:07 +00:00
return makeCylinder ( pos , block , radiusX , radiusZ , height , 0 , filled ) ;
}
2011-01-01 18:33:18 +00:00
2021-07-23 15:48:51 +00:00
//FAWE start
2021-07-24 15:34:05 +00:00
public int makeHollowCylinder (
BlockVector3 pos ,
final Pattern block ,
double radiusX ,
double radiusZ ,
int height ,
double thickness
) throws MaxChangedBlocksException {
2018-08-12 14:03:07 +00:00
return makeCylinder ( pos , block , radiusX , radiusZ , height , thickness , false ) ;
}
2021-07-23 15:48:51 +00:00
//FAWE end
2018-08-12 14:03:07 +00:00
2021-07-24 15:34:05 +00:00
public int makeCylinder (
BlockVector3 pos ,
Pattern block ,
double radiusX ,
double radiusZ ,
int height ,
double thickness ,
boolean filled
) throws MaxChangedBlocksException {
2011-10-28 18:16:19 +00:00
radiusX + = 0 . 5 ;
radiusZ + = 0 . 5 ;
2019-06-25 13:00:44 +00:00
2021-07-23 15:48:51 +00:00
//FAWE start
MutableBlockVector3 mutableBlockVector3 = new MutableBlockVector3 ( pos ) ;
//FAWE end
2010-10-18 00:39:20 +00:00
if ( height = = 0 ) {
2019-06-25 13:00:44 +00:00
return 0 ;
2010-10-18 00:39:20 +00:00
} else if ( height < 0 ) {
height = - height ;
2021-07-23 15:48:51 +00:00
//FAWE start
mutableBlockVector3 . mutY ( mutableBlockVector3 . getY ( ) - height ) ;
//FAWE end
2010-10-18 00:39:20 +00:00
}
2021-07-23 15:48:51 +00:00
//FAWE start
if ( mutableBlockVector3 . getBlockY ( ) < getWorld ( ) . getMinY ( ) ) {
mutableBlockVector3 . mutY ( world . getMinY ( ) ) ;
} else if ( mutableBlockVector3 . getBlockY ( ) + height - 1 > maxY ) {
height = maxY - mutableBlockVector3 . getBlockY ( ) + 1 ;
2010-10-18 00:39:20 +00:00
}
2021-07-23 15:48:51 +00:00
//FAWE end
2010-10-18 00:39:20 +00:00
2019-07-06 00:46:48 +00:00
final double invRadiusX = 1 / radiusX ;
final double invRadiusZ = 1 / radiusZ ;
2018-08-12 14:03:07 +00:00
2021-07-23 15:48:51 +00:00
//FAWE start
int px = mutableBlockVector3 . getBlockX ( ) ;
int py = mutableBlockVector3 . getBlockY ( ) ;
int pz = mutableBlockVector3 . getBlockZ ( ) ;
2018-08-12 14:03:07 +00:00
final int ceilRadiusX = ( int ) Math . ceil ( radiusX ) ;
final int ceilRadiusZ = ( int ) Math . ceil ( radiusZ ) ;
2019-09-14 03:05:16 +00:00
2020-10-05 17:41:41 +00:00
double xSqr ;
double zSqr ;
2019-07-06 00:46:48 +00:00
double distanceSq ;
2018-08-12 14:03:07 +00:00
double nextXn = 0 ;
if ( thickness ! = 0 ) {
double nextMinXn = 0 ;
final double minInvRadiusX = 1 / ( radiusX - thickness ) ;
final double minInvRadiusZ = 1 / ( radiusZ - thickness ) ;
2021-07-24 15:34:05 +00:00
forX :
for ( int x = 0 ; x < = ceilRadiusX ; + + x ) {
2018-08-12 14:03:07 +00:00
final double xn = nextXn ;
double dx2 = nextMinXn * nextMinXn ;
nextXn = ( x + 1 ) * invRadiusX ;
nextMinXn = ( x + 1 ) * minInvRadiusX ;
double nextZn = 0 ;
double nextMinZn = 0 ;
2019-07-17 16:31:13 +00:00
xSqr = xn * xn ;
2021-07-24 15:34:05 +00:00
forZ :
for ( int z = 0 ; z < = ceilRadiusZ ; + + z ) {
2018-08-12 14:03:07 +00:00
final double zn = nextZn ;
double dz2 = nextMinZn * nextMinZn ;
nextZn = ( z + 1 ) * invRadiusZ ;
nextMinZn = ( z + 1 ) * minInvRadiusZ ;
2019-07-17 16:31:13 +00:00
zSqr = zn * zn ;
distanceSq = xSqr + zSqr ;
2019-07-06 00:46:48 +00:00
if ( distanceSq > 1 ) {
2018-08-12 14:03:07 +00:00
if ( z = = 0 ) {
break forX ;
}
break forZ ;
}
if ( ( dz2 + nextMinXn * nextMinXn < = 1 ) & & ( nextMinZn * nextMinZn + dx2 < = 1 ) ) {
continue ;
}
for ( int y = 0 ; y < height ; + + y ) {
2021-08-11 13:00:12 +00:00
this . setBlock ( mutableBlockVector3 . setComponents ( px + x , py + y , pz + z ) , block ) ;
this . setBlock ( mutableBlockVector3 . setComponents ( px - x , py + y , pz + z ) , block ) ;
this . setBlock ( mutableBlockVector3 . setComponents ( px + x , py + y , pz - z ) , block ) ;
this . setBlock ( mutableBlockVector3 . setComponents ( px - x , py + y , pz - z ) , block ) ;
2018-08-12 14:03:07 +00:00
}
}
}
} else {
2021-07-23 15:48:51 +00:00
//FAWE end
2021-07-24 15:34:05 +00:00
forX :
for ( int x = 0 ; x < = ceilRadiusX ; + + x ) {
2018-08-12 14:03:07 +00:00
final double xn = nextXn ;
nextXn = ( x + 1 ) * invRadiusX ;
double nextZn = 0 ;
2019-07-17 16:31:13 +00:00
xSqr = xn * xn ;
2021-07-24 15:34:05 +00:00
forZ :
for ( int z = 0 ; z < = ceilRadiusZ ; + + z ) {
2018-08-12 14:03:07 +00:00
final double zn = nextZn ;
nextZn = ( z + 1 ) * invRadiusZ ;
2019-07-17 16:31:13 +00:00
zSqr = zn * zn ;
distanceSq = xSqr + zSqr ;
2019-07-06 00:46:48 +00:00
if ( distanceSq > 1 ) {
2018-08-12 14:03:07 +00:00
if ( z = = 0 ) {
break forX ;
}
break forZ ;
}
if ( ! filled ) {
2019-07-17 16:31:13 +00:00
if ( ( zSqr + nextXn * nextXn < = 1 ) & & ( nextZn * nextZn + xSqr < = 1 ) ) {
2018-08-12 14:03:07 +00:00
continue ;
}
}
for ( int y = 0 ; y < height ; + + y ) {
2021-07-23 15:48:51 +00:00
//FAWE start - mutable
2021-08-11 13:00:12 +00:00
this . setBlock ( mutableBlockVector3 . setComponents ( px + x , py + y , pz + z ) , block ) ;
this . setBlock ( mutableBlockVector3 . setComponents ( px - x , py + y , pz + z ) , block ) ;
this . setBlock ( mutableBlockVector3 . setComponents ( px + x , py + y , pz - z ) , block ) ;
this . setBlock ( mutableBlockVector3 . setComponents ( px - x , py + y , pz - z ) , block ) ;
2021-07-23 15:48:51 +00:00
//FAWE end
2018-08-12 14:03:07 +00:00
}
}
}
}
2021-07-23 15:48:51 +00:00
//FAWE start
2018-08-12 14:03:07 +00:00
return this . changes ;
2021-07-23 15:48:51 +00:00
//FAWE end
2018-08-12 14:03:07 +00:00
}
2010-10-18 00:22:29 +00:00
/ * *
2019-11-19 21:23:47 +00:00
* Move the blocks in a region a certain direction .
2011-09-24 19:32:03 +00:00
*
2021-07-24 15:34:05 +00:00
* @param region the region to move
* @param dir the direction
* @param distance the distance to move
* @param copyAir true to copy air blocks
2019-11-19 21:23:47 +00:00
* @param replacement the replacement pattern to fill in after moving , or null to use air
* @return number of blocks moved
2014-07-29 21:23:00 +00:00
* @throws MaxChangedBlocksException thrown if too many blocks are changed
2011-10-26 20:50:46 +00:00
* /
2021-07-24 15:34:05 +00:00
public int moveRegion ( Region region , BlockVector3 dir , int distance , boolean copyAir , Pattern replacement ) throws
MaxChangedBlocksException {
2019-11-19 21:23:47 +00:00
return moveRegion ( region , dir , distance , true , false , copyAir ? new ExistingBlockMask ( this ) : null , replacement ) ;
2011-10-26 20:50:46 +00:00
}
2021-07-23 15:48:51 +00:00
//FAWE start
2021-07-24 15:34:05 +00:00
public int makeCircle (
BlockVector3 pos ,
final Pattern block ,
double radiusX ,
double radiusY ,
double radiusZ ,
boolean filled ,
Vector3 normal
) throws MaxChangedBlocksException {
2018-08-12 14:03:07 +00:00
radiusX + = 0 . 5 ;
radiusY + = 0 . 5 ;
radiusZ + = 0 . 5 ;
normal = normal . normalize ( ) ;
double nx = normal . getX ( ) ;
double ny = normal . getY ( ) ;
double nz = normal . getZ ( ) ;
2011-10-28 18:16:19 +00:00
final double invRadiusX = 1 / radiusX ;
2018-08-12 14:03:07 +00:00
final double invRadiusY = 1 / radiusY ;
2011-10-28 18:16:19 +00:00
final double invRadiusZ = 1 / radiusZ ;
2010-10-18 00:22:29 +00:00
2018-08-12 14:03:07 +00:00
int px = pos . getBlockX ( ) ;
int py = pos . getBlockY ( ) ;
int pz = pos . getBlockZ ( ) ;
2019-03-31 16:09:20 +00:00
MutableBlockVector3 mutable = new MutableBlockVector3 ( ) ;
2018-08-12 14:03:07 +00:00
2011-10-28 18:16:19 +00:00
final int ceilRadiusX = ( int ) Math . ceil ( radiusX ) ;
2018-08-12 14:03:07 +00:00
final int ceilRadiusY = ( int ) Math . ceil ( radiusY ) ;
2011-10-28 18:16:19 +00:00
final int ceilRadiusZ = ( int ) Math . ceil ( radiusZ ) ;
2010-10-18 00:22:29 +00:00
2018-08-12 14:03:07 +00:00
double threshold = 0 . 5 ;
2011-10-28 18:16:19 +00:00
double nextXn = 0 ;
2020-10-05 17:41:41 +00:00
double dx ;
double dy ;
double dz ;
double dxy ;
double dxyz ;
2018-08-12 14:03:07 +00:00
forX :
for ( int x = 0 ; x < = ceilRadiusX ; + + x ) {
2011-10-28 18:16:19 +00:00
final double xn = nextXn ;
2018-08-12 14:03:07 +00:00
dx = xn * xn ;
2011-10-28 18:16:19 +00:00
nextXn = ( x + 1 ) * invRadiusX ;
2018-08-12 14:03:07 +00:00
double nextYn = 0 ;
forY :
for ( int y = 0 ; y < = ceilRadiusY ; + + y ) {
final double yn = nextYn ;
dy = yn * yn ;
dxy = dx + dy ;
nextYn = ( y + 1 ) * invRadiusY ;
double nextZn = 0 ;
forZ :
for ( int z = 0 ; z < = ceilRadiusZ ; + + z ) {
final double zn = nextZn ;
dz = zn * zn ;
dxyz = dxy + dz ;
nextZn = ( z + 1 ) * invRadiusZ ;
if ( dxyz > 1 ) {
if ( z = = 0 ) {
if ( y = = 0 ) {
break forX ;
}
break forY ;
}
break forZ ;
2011-10-28 18:16:19 +00:00
}
2018-08-12 14:03:07 +00:00
if ( ! filled ) {
if ( nextXn * nextXn + dy + dz < = 1 & & nextYn * nextYn + dx + dz < = 1 & & nextZn * nextZn + dx + dy < = 1 ) {
continue ;
}
2011-10-28 18:16:19 +00:00
}
2020-10-05 17:41:41 +00:00
if ( Math . abs ( ( x ) * nx + ( y ) * ny + ( z ) * nz ) < threshold ) {
2019-03-31 16:09:20 +00:00
setBlock ( mutable . setComponents ( px + x , py + y , pz + z ) , block ) ;
2020-10-05 17:41:41 +00:00
}
if ( Math . abs ( ( - x ) * nx + ( y ) * ny + ( z ) * nz ) < threshold ) {
2019-03-31 16:09:20 +00:00
setBlock ( mutable . setComponents ( px - x , py + y , pz + z ) , block ) ;
2020-10-05 17:41:41 +00:00
}
if ( Math . abs ( ( x ) * nx + ( - y ) * ny + ( z ) * nz ) < threshold ) {
2019-03-31 16:09:20 +00:00
setBlock ( mutable . setComponents ( px + x , py - y , pz + z ) , block ) ;
2020-10-05 17:41:41 +00:00
}
if ( Math . abs ( ( x ) * nx + ( y ) * ny + ( - z ) * nz ) < threshold ) {
2019-03-31 16:09:20 +00:00
setBlock ( mutable . setComponents ( px + x , py + y , pz - z ) , block ) ;
2020-10-05 17:41:41 +00:00
}
if ( Math . abs ( ( - x ) * nx + ( - y ) * ny + ( z ) * nz ) < threshold ) {
2019-03-31 16:09:20 +00:00
setBlock ( mutable . setComponents ( px - x , py - y , pz + z ) , block ) ;
2020-10-05 17:41:41 +00:00
}
if ( Math . abs ( ( x ) * nx + ( - y ) * ny + ( - z ) * nz ) < threshold ) {
2019-03-31 16:09:20 +00:00
setBlock ( mutable . setComponents ( px + x , py - y , pz - z ) , block ) ;
2020-10-05 17:41:41 +00:00
}
if ( Math . abs ( ( - x ) * nx + ( y ) * ny + ( - z ) * nz ) < threshold ) {
2019-03-31 16:09:20 +00:00
setBlock ( mutable . setComponents ( px - x , py + y , pz - z ) , block ) ;
2020-10-05 17:41:41 +00:00
}
if ( Math . abs ( ( - x ) * nx + ( - y ) * ny + ( - z ) * nz ) < threshold ) {
2019-03-31 16:09:20 +00:00
setBlock ( mutable . setComponents ( px - x , py - y , pz - z ) , block ) ;
2020-10-05 17:41:41 +00:00
}
2010-10-18 00:22:29 +00:00
}
}
}
2018-08-12 14:03:07 +00:00
return changes ;
2010-10-18 00:22:29 +00:00
}
2021-07-23 15:48:51 +00:00
//FAWE end
2010-10-18 00:22:29 +00:00
2011-10-26 20:50:46 +00:00
/ * *
2021-07-24 15:34:05 +00:00
* Makes a sphere .
*
* @param pos Center of the sphere or ellipsoid
* @param block The block pattern to use
* @param radius The sphere ' s radius
* @param filled If false , only a shell will be generated .
* @return number of blocks changed
* @throws MaxChangedBlocksException thrown if too many blocks are changed
* /
2019-06-04 15:48:30 +00:00
public int makeSphere ( BlockVector3 pos , Pattern block , double radius , boolean filled ) throws MaxChangedBlocksException {
2018-12-20 16:00:27 +00:00
return makeSphere ( pos , block , radius , radius , radius , filled ) ;
2011-10-26 20:50:46 +00:00
}
2010-10-18 17:39:32 +00:00
/ * *
2011-09-02 19:38:38 +00:00
* Makes a sphere or ellipsoid .
2011-09-24 19:32:03 +00:00
*
2021-07-24 15:34:05 +00:00
* @param pos Center of the sphere or ellipsoid
* @param block The block pattern to use
2011-09-02 19:38:38 +00:00
* @param radiusX The sphere / ellipsoid ' s largest north / south extent
* @param radiusY The sphere / ellipsoid ' s largest up / down extent
* @param radiusZ The sphere / ellipsoid ' s largest east / west extent
2021-07-24 15:34:05 +00:00
* @param filled If false , only a shell will be generated .
2010-10-18 17:39:32 +00:00
* @return number of blocks changed
2014-07-29 21:23:00 +00:00
* @throws MaxChangedBlocksException thrown if too many blocks are changed
2010-10-18 17:39:32 +00:00
* /
2021-07-24 15:34:05 +00:00
public int makeSphere ( BlockVector3 pos , Pattern block , double radiusX , double radiusY , double radiusZ , boolean filled ) throws
MaxChangedBlocksException {
2011-09-02 19:38:38 +00:00
radiusX + = 0 . 5 ;
radiusY + = 0 . 5 ;
radiusZ + = 0 . 5 ;
final double invRadiusX = 1 / radiusX ;
final double invRadiusY = 1 / radiusY ;
final double invRadiusZ = 1 / radiusZ ;
2018-08-12 14:03:07 +00:00
int px = pos . getBlockX ( ) ;
int py = pos . getBlockY ( ) ;
int pz = pos . getBlockZ ( ) ;
2011-09-02 19:38:38 +00:00
final int ceilRadiusX = ( int ) Math . ceil ( radiusX ) ;
final int ceilRadiusY = ( int ) Math . ceil ( radiusY ) ;
final int ceilRadiusZ = ( int ) Math . ceil ( radiusZ ) ;
2021-07-23 15:48:51 +00:00
//FAWE start
2019-12-21 05:20:17 +00:00
int yy ;
2021-07-23 15:48:51 +00:00
//FAWE end
2019-12-21 05:20:17 +00:00
2020-12-17 15:26:17 +00:00
double nextXn = 0 ;
2021-07-24 15:34:05 +00:00
forX :
for ( int x = 0 ; x < = ceilRadiusX ; + + x ) {
2011-09-02 19:38:38 +00:00
final double xn = nextXn ;
2019-07-17 16:31:13 +00:00
double dx = xn * xn ;
2011-09-03 16:54:20 +00:00
nextXn = ( x + 1 ) * invRadiusX ;
2020-12-17 15:26:17 +00:00
double nextZn = 0 ;
2021-07-24 15:34:05 +00:00
forZ :
for ( int z = 0 ; z < = ceilRadiusZ ; + + z ) {
2019-04-16 15:12:09 +00:00
final double zn = nextZn ;
2019-06-25 13:00:44 +00:00
double dz = zn * zn ;
2019-07-17 16:31:13 +00:00
double dxz = dx + dz ;
2019-04-16 15:12:09 +00:00
nextZn = ( z + 1 ) * invRadiusZ ;
2020-12-17 15:26:17 +00:00
double nextYn = 0 ;
2019-04-16 15:12:09 +00:00
2021-07-24 15:34:05 +00:00
forY :
for ( int y = 0 ; y < = ceilRadiusY ; + + y ) {
2019-04-16 15:12:09 +00:00
final double yn = nextYn ;
2019-07-17 16:31:13 +00:00
double dy = yn * yn ;
double dxyz = dxz + dy ;
2019-04-16 15:12:09 +00:00
nextYn = ( y + 1 ) * invRadiusY ;
2018-08-12 14:03:07 +00:00
if ( dxyz > 1 ) {
2019-04-16 15:12:09 +00:00
if ( y = = 0 ) {
if ( z = = 0 ) {
2011-09-02 19:38:38 +00:00
break forX ;
2011-09-03 16:54:20 +00:00
}
2019-04-16 15:12:09 +00:00
break forZ ;
2011-09-02 19:38:38 +00:00
}
2019-04-16 15:12:09 +00:00
break forY ;
2011-09-02 19:38:38 +00:00
}
2011-08-12 06:16:53 +00:00
if ( ! filled ) {
2020-12-23 17:26:26 +00:00
if ( nextXn * nextXn + dy + dz < = 1 & & nextYn * nextYn + dx + dz < = 1 & & nextZn * nextZn + dx + dy < = 1 ) {
2011-08-12 06:16:53 +00:00
continue ;
2011-09-03 16:54:20 +00:00
}
2011-08-12 06:16:53 +00:00
}
2021-07-23 15:48:51 +00:00
//FAWE start
2019-12-21 05:20:17 +00:00
yy = py + y ;
if ( yy < = maxY ) {
this . setBlock ( px + x , py + y , pz + z , block ) ;
2020-10-05 17:41:41 +00:00
if ( x ! = 0 ) {
this . setBlock ( px - x , py + y , pz + z , block ) ;
}
2019-12-21 05:20:17 +00:00
if ( z ! = 0 ) {
this . setBlock ( px + x , py + y , pz - z , block ) ;
2020-10-05 17:41:41 +00:00
if ( x ! = 0 ) {
this . setBlock ( px - x , py + y , pz - z , block ) ;
}
2019-12-21 05:20:17 +00:00
}
2019-04-16 15:12:09 +00:00
}
2021-08-17 21:13:51 +00:00
if ( y ! = 0 & & ( yy = py - y ) > = minY ) {
2019-12-21 05:20:17 +00:00
this . setBlock ( px + x , yy , pz + z , block ) ;
2020-10-05 17:41:41 +00:00
if ( x ! = 0 ) {
this . setBlock ( px - x , yy , pz + z , block ) ;
}
2019-04-16 15:12:09 +00:00
if ( z ! = 0 ) {
2019-12-21 05:20:17 +00:00
this . setBlock ( px + x , yy , pz - z , block ) ;
2020-10-05 17:41:41 +00:00
if ( x ! = 0 ) {
this . setBlock ( px - x , yy , pz - z , block ) ;
}
2019-04-16 15:12:09 +00:00
}
}
2010-10-18 17:39:32 +00:00
}
}
}
2018-08-12 14:03:07 +00:00
return changes ;
2021-07-23 15:48:51 +00:00
//FAWE end
2010-10-18 17:39:32 +00:00
}
2011-08-07 00:40:48 +00:00
/ * *
* Makes a pyramid .
2011-09-24 19:32:03 +00:00
*
2014-07-29 18:04:04 +00:00
* @param position a position
2021-07-24 15:34:05 +00:00
* @param block a block
* @param size size of pyramid
* @param filled true if filled
2011-08-07 00:40:48 +00:00
* @return number of blocks changed
2014-07-29 21:23:00 +00:00
* @throws MaxChangedBlocksException thrown if too many blocks are changed
2011-08-07 00:40:48 +00:00
* /
2019-03-28 19:02:37 +00:00
public int makePyramid ( BlockVector3 position , Pattern block , int size , boolean filled ) throws MaxChangedBlocksException {
2021-07-23 15:48:51 +00:00
//FAWE start - abbreviated logic
2019-06-28 14:01:51 +00:00
int bx = position . getX ( ) ;
int by = position . getY ( ) ;
int bz = position . getZ ( ) ;
2019-06-04 15:48:30 +00:00
2019-03-28 19:02:37 +00:00
int height = size ;
2011-09-24 19:32:03 +00:00
2011-08-07 00:40:48 +00:00
for ( int y = 0 ; y < = height ; + + y ) {
size - - ;
for ( int x = 0 ; x < = size ; + + x ) {
for ( int z = 0 ; z < = size ; + + z ) {
2019-06-04 15:48:30 +00:00
2019-03-28 19:02:37 +00:00
if ( ( filled & & z < = size & & x < = size ) | | z = = size | | x = = size ) {
2019-06-28 14:01:51 +00:00
setBlock ( x + bx , y + by , z + bz , block ) ;
setBlock ( - x + bx , y + by , z + bz , block ) ;
setBlock ( x + bx , y + by , - z + bz , block ) ;
setBlock ( - x + bx , y + by , - z + bz , block ) ;
2011-08-07 00:40:48 +00:00
}
}
}
}
2018-08-12 14:03:07 +00:00
return changes ;
2021-07-23 15:48:51 +00:00
//FAWE end
2011-08-07 00:40:48 +00:00
}
2011-01-08 19:40:18 +00:00
/ * *
2014-07-29 18:04:04 +00:00
* Thaw blocks in a radius .
2011-09-24 19:32:03 +00:00
*
2014-07-29 18:04:04 +00:00
* @param position the position
2021-07-24 15:34:05 +00:00
* @param radius the radius
2011-01-08 19:40:18 +00:00
* @return number of blocks affected
2014-07-29 21:23:00 +00:00
* @throws MaxChangedBlocksException thrown if too many blocks are changed
2020-12-16 19:23:41 +00:00
* @deprecated Use { @link # thaw ( BlockVector3 , double , int ) } .
2011-01-08 19:40:18 +00:00
* /
2020-10-05 17:41:41 +00:00
@Deprecated
2019-03-28 19:02:37 +00:00
public int thaw ( BlockVector3 position , double radius )
2021-07-24 15:34:05 +00:00
throws MaxChangedBlocksException {
2020-12-16 19:23:41 +00:00
return thaw ( position , radius ,
2021-07-24 15:34:05 +00:00
WorldEdit . getInstance ( ) . getConfiguration ( ) . defaultVerticalHeight
) ;
2020-12-16 19:23:41 +00:00
}
/ * *
* Thaw blocks in a cylinder .
*
* @param position the position
2021-07-24 15:34:05 +00:00
* @param radius the radius
* @param height the height ( upwards and downwards )
2020-12-16 19:23:41 +00:00
* @return number of blocks affected
* @throws MaxChangedBlocksException thrown if too many blocks are changed
* /
public int thaw ( BlockVector3 position , double radius , int height )
2021-07-24 15:34:05 +00:00
throws MaxChangedBlocksException {
2018-12-23 16:19:33 +00:00
int affected = 0 ;
double radiusSq = radius * radius ;
2011-01-08 19:40:18 +00:00
2019-03-28 19:02:37 +00:00
int ox = position . getBlockX ( ) ;
int oy = position . getBlockY ( ) ;
int oz = position . getBlockZ ( ) ;
2019-06-04 15:48:30 +00:00
2019-03-28 19:02:37 +00:00
BlockState air = BlockTypes . AIR . getDefaultState ( ) ;
BlockState water = BlockTypes . WATER . getDefaultState ( ) ;
2019-06-04 15:48:30 +00:00
2021-08-17 21:13:51 +00:00
int centerY = Math . max ( minY , Math . min ( maxY , oy ) ) ;
int minY = Math . max ( this . minY , centerY - height ) ;
int maxY = Math . min ( this . maxY , centerY + height ) ;
2020-12-16 19:23:41 +00:00
2021-08-11 13:56:10 +00:00
//FAWE start - mutable
MutableBlockVector3 mutable = new MutableBlockVector3 ( ) ;
MutableBlockVector3 mutable2 = new MutableBlockVector3 ( ) ;
//FAWE end
2019-03-28 19:02:37 +00:00
int ceilRadius = ( int ) Math . ceil ( radius ) ;
for ( int x = ox - ceilRadius ; x < = ox + ceilRadius ; + + x ) {
for ( int z = oz - ceilRadius ; z < = oz + ceilRadius ; + + z ) {
2021-08-11 13:56:10 +00:00
//FAWE start - mutable
if ( ( mutable . setComponents ( x , oy , z ) ) . distanceSq ( position ) > radiusSq ) {
//FAWE end
2011-01-08 19:40:18 +00:00
continue ;
}
2019-06-04 15:48:30 +00:00
2020-12-16 19:23:41 +00:00
for ( int y = maxY ; y > minY ; - - y ) {
2021-08-11 13:56:10 +00:00
//FAWE start - mutable
mutable . setComponents ( x , y , z ) ;
mutable2 . setComponents ( x , y - 1 , z ) ;
BlockType id = getBlock ( mutable ) . getBlockType ( ) ;
2019-03-28 19:02:37 +00:00
if ( id = = BlockTypes . ICE ) {
2021-08-11 13:56:10 +00:00
if ( setBlock ( mutable , water ) ) {
2019-03-28 19:02:37 +00:00
+ + affected ;
}
} else if ( id = = BlockTypes . SNOW ) {
2021-08-17 21:13:51 +00:00
//FAWE start
2021-08-11 13:56:10 +00:00
if ( setBlock ( mutable , air ) ) {
2021-08-17 21:13:51 +00:00
if ( y > getMinY ( ) ) {
2021-08-11 13:56:10 +00:00
BlockState block = getBlock ( mutable2 ) ;
2020-12-16 19:23:41 +00:00
if ( block . getStates ( ) . containsKey ( snowy ) ) {
2021-08-11 13:56:10 +00:00
if ( setBlock ( mutable2 , block . with ( snowy , false ) ) ) {
2020-12-16 19:23:41 +00:00
affected + + ;
}
}
}
2021-07-23 15:48:51 +00:00
//FAWE end
2019-03-28 19:02:37 +00:00
+ + affected ;
}
} else if ( id . getMaterial ( ) . isAir ( ) ) {
2019-06-04 15:48:30 +00:00
continue ;
2011-01-08 19:40:18 +00:00
}
2019-06-04 15:48:30 +00:00
2011-09-05 01:53:39 +00:00
break ;
2011-01-08 19:40:18 +00:00
}
}
}
2020-12-16 19:23:41 +00:00
return affected ;
2011-01-08 19:40:18 +00:00
}
2010-11-07 04:26:52 +00:00
/ * *
2014-07-29 18:04:04 +00:00
* Make snow in a radius .
2011-09-24 19:32:03 +00:00
*
2014-07-29 18:04:04 +00:00
* @param position a position
2021-07-24 15:34:05 +00:00
* @param radius a radius
2010-11-07 04:26:52 +00:00
* @return number of blocks affected
2014-07-29 21:23:00 +00:00
* @throws MaxChangedBlocksException thrown if too many blocks are changed
2020-12-16 19:23:41 +00:00
* @deprecated Use { @link # simulateSnow ( BlockVector3 , double , int ) } .
2010-11-07 04:26:52 +00:00
* /
2020-10-05 17:41:41 +00:00
@Deprecated
2019-03-28 19:02:37 +00:00
public int simulateSnow ( BlockVector3 position , double radius ) throws MaxChangedBlocksException {
2020-12-16 19:23:41 +00:00
return simulateSnow ( position , radius ,
2021-07-24 15:34:05 +00:00
WorldEdit . getInstance ( ) . getConfiguration ( ) . defaultVerticalHeight
) ;
2020-12-16 19:23:41 +00:00
}
2019-03-28 19:02:37 +00:00
2020-12-16 19:23:41 +00:00
/ * *
* Make snow in a cylinder .
*
* @param position a position
2021-07-24 15:34:05 +00:00
* @param radius a radius
* @param height the height ( upwards and downwards )
2020-12-16 19:23:41 +00:00
* @return number of blocks affected
* @throws MaxChangedBlocksException thrown if too many blocks are changed
* /
public int simulateSnow ( BlockVector3 position , double radius , int height )
2021-07-24 15:34:05 +00:00
throws MaxChangedBlocksException {
2011-01-01 18:33:18 +00:00
2020-12-16 19:23:41 +00:00
return simulateSnow ( new CylinderRegion ( position , Vector2 . at ( radius , radius ) , position . getBlockY ( ) , height ) , false ) ;
}
2011-09-05 01:53:39 +00:00
2020-12-16 19:23:41 +00:00
/ * *
* Make snow in a region .
*
* @param region the region to simulate snow in
2021-07-24 15:34:05 +00:00
* @param stack whether it should stack existing snow
2020-12-16 19:23:41 +00:00
* @return number of blocks affected
* @throws MaxChangedBlocksException thrown if too many blocks are changed
* /
public int simulateSnow ( FlatRegion region , boolean stack )
2021-07-24 15:34:05 +00:00
throws MaxChangedBlocksException {
2020-12-16 19:23:41 +00:00
checkNotNull ( region ) ;
2010-11-07 04:26:52 +00:00
2020-12-16 19:23:41 +00:00
SnowSimulator snowSimulator = new SnowSimulator ( this , stack ) ;
2021-08-17 00:47:09 +00:00
//FAWE start - provide extent for preloading
LayerVisitor layerVisitor = new LayerVisitor ( region , region . getMinimumY ( ) , region . getMaximumY ( ) , snowSimulator , this ) ;
//FAWE end
2020-12-16 19:23:41 +00:00
Operations . completeLegacy ( layerVisitor ) ;
return snowSimulator . getAffected ( ) ;
2010-11-07 04:26:52 +00:00
}
2021-07-24 15:34:05 +00:00
2013-12-29 17:28:42 +00:00
/ * *
2014-07-29 18:04:04 +00:00
* Make dirt green .
2013-12-29 17:28:42 +00:00
*
2021-07-24 15:34:05 +00:00
* @param position a position
* @param radius a radius
2020-06-13 18:41:36 +00:00
* @param onlyNormalDirt only affect normal dirt ( all default properties )
2013-12-29 17:28:42 +00:00
* @return number of blocks affected
2014-07-29 21:23:00 +00:00
* @throws MaxChangedBlocksException thrown if too many blocks are changed
2020-12-16 19:23:41 +00:00
* @deprecated Use { @link # green ( BlockVector3 , double , int , boolean ) } .
2013-12-29 17:28:42 +00:00
* /
2020-06-13 18:41:36 +00:00
@Deprecated
2019-07-06 00:46:48 +00:00
public int green ( BlockVector3 position , double radius , boolean onlyNormalDirt )
2021-07-24 15:34:05 +00:00
throws MaxChangedBlocksException {
2020-12-16 19:23:41 +00:00
return green ( position , radius ,
2021-07-24 15:34:05 +00:00
WorldEdit . getInstance ( ) . getConfiguration ( ) . defaultVerticalHeight , onlyNormalDirt
) ;
2020-12-16 19:23:41 +00:00
}
/ * *
* Make dirt green in a cylinder .
*
2021-07-24 15:34:05 +00:00
* @param position the position
* @param radius the radius
* @param height the height
2020-12-16 19:23:41 +00:00
* @param onlyNormalDirt only affect normal dirt ( all default properties )
* @return number of blocks affected
* @throws MaxChangedBlocksException thrown if too many blocks are changed
* /
public int green ( BlockVector3 position , double radius , int height , boolean onlyNormalDirt )
2021-07-24 15:34:05 +00:00
throws MaxChangedBlocksException {
2020-12-16 19:23:41 +00:00
int affected = 0 ;
2011-12-10 11:16:57 +00:00
final double radiusSq = radius * radius ;
2011-08-16 16:43:13 +00:00
2014-07-29 18:04:04 +00:00
final int ox = position . getBlockX ( ) ;
2020-12-16 19:23:41 +00:00
final int oy = position . getBlockY ( ) ;
2014-07-29 18:04:04 +00:00
final int oz = position . getBlockZ ( ) ;
2011-08-16 16:43:13 +00:00
2019-06-04 15:48:30 +00:00
final BlockState grass = BlockTypes . GRASS_BLOCK . getDefaultState ( ) ;
2021-08-17 21:13:51 +00:00
final int centerY = Math . max ( minY , Math . min ( maxY , oy ) ) ;
final int minY = Math . max ( this . minY , centerY - height ) ;
final int maxY = Math . min ( this . maxY , centerY + height ) ;
2020-12-16 19:23:41 +00:00
2021-08-11 13:56:10 +00:00
//FAWE start - mutable
MutableBlockVector3 mutable = new MutableBlockVector3 ( ) ;
//FAWE end
2011-12-10 11:16:57 +00:00
final int ceilRadius = ( int ) Math . ceil ( radius ) ;
2019-06-04 15:48:30 +00:00
for ( int x = ox - ceilRadius ; x < = ox + ceilRadius ; + + x ) {
2019-07-06 00:46:48 +00:00
for ( int z = oz - ceilRadius ; z < = oz + ceilRadius ; + + z ) {
2021-08-11 13:56:10 +00:00
//FAWE start - mutable
if ( mutable . setComponents ( x , oy , z ) . distanceSq ( position ) > radiusSq ) {
//FAWE end
2011-08-16 16:43:13 +00:00
continue ;
}
2020-12-16 19:23:41 +00:00
for ( int y = maxY ; y > minY ; - - y ) {
2021-08-11 13:56:10 +00:00
//FAWE start - mutable
final BlockState block = getBlock ( mutable . mutY ( y ) ) ;
//FAWE end
2020-12-16 19:23:41 +00:00
if ( block . getBlockType ( ) = = BlockTypes . DIRT
2021-07-24 15:34:05 +00:00
| | ( ! onlyNormalDirt & & block . getBlockType ( ) = = BlockTypes . COARSE_DIRT ) ) {
2021-08-11 13:56:10 +00:00
//FAWE start - mutable
if ( setBlock ( mutable . mutY ( y ) , grass ) ) {
//FAWE end
2020-12-16 19:23:41 +00:00
+ + affected ;
}
break ;
} else if ( block . getBlockType ( ) = = BlockTypes . WATER | | block . getBlockType ( ) = = BlockTypes . LAVA ) {
break ;
} else if ( block . getBlockType ( ) . getMaterial ( ) . isMovementBlocker ( ) ) {
break ;
2011-08-16 16:43:13 +00:00
}
}
}
}
2020-12-16 19:23:41 +00:00
return affected ;
2011-08-16 16:43:13 +00:00
}
2018-08-17 08:27:48 +00:00
/ * *
* Makes pumpkin patches randomly in an area around the given position .
*
* @param position the base position
2021-07-24 15:34:05 +00:00
* @param apothem the apothem of the ( square ) area
2018-08-17 08:27:48 +00:00
* @return number of patches created
* @throws MaxChangedBlocksException thrown if too many blocks are changed
* /
2019-11-21 07:57:32 +00:00
public int makePumpkinPatches ( BlockVector3 position , int apothem ) throws MaxChangedBlocksException {
return makePumpkinPatches ( position , apothem , 0 . 02 ) ;
}
2021-07-23 15:48:51 +00:00
//FAWE start - support density
2019-07-06 00:46:48 +00:00
public int makePumpkinPatches ( BlockVector3 position , int apothem , double density ) throws MaxChangedBlocksException {
2014-03-01 23:41:40 +00:00
// We want to generate pumpkins
2019-06-04 15:48:30 +00:00
GardenPatchGenerator generator = new GardenPatchGenerator ( this ) ;
2014-03-01 23:41:40 +00:00
generator . setPlant ( GardenPatchGenerator . getPumpkinPattern ( ) ) ;
2010-10-31 01:20:15 +00:00
2014-03-01 23:41:40 +00:00
// In a region of the given radius
2019-06-04 15:48:30 +00:00
FlatRegion region = new CuboidRegion (
getWorld ( ) , // Causes clamping of Y range
position . add ( - apothem , - 5 , - apothem ) ,
2021-07-24 15:34:05 +00:00
position . add ( apothem , 10 , apothem )
) ;
2018-08-12 14:03:07 +00:00
2019-06-04 15:48:30 +00:00
GroundFunction ground = new GroundFunction ( new ExistingBlockMask ( this ) , generator ) ;
2021-08-17 00:47:09 +00:00
LayerVisitor visitor = new LayerVisitor ( region , minimumBlockY ( region ) , maximumBlockY ( region ) , ground , this ) ;
2014-03-30 01:51:33 +00:00
visitor . setMask ( new NoiseFilter2D ( new RandomNoise ( ) , density ) ) ;
2020-06-13 18:41:36 +00:00
Operations . completeLegacy ( visitor ) ;
2018-08-12 14:03:07 +00:00
return this . changes = ground . getAffected ( ) ;
2010-10-31 01:20:15 +00:00
}
2021-07-23 15:48:51 +00:00
//FAWE end
2010-10-31 01:20:15 +00:00
2010-10-13 05:38:05 +00:00
/ * *
2010-11-07 04:03:34 +00:00
* Makes a forest .
2011-09-24 19:32:03 +00:00
*
2014-07-29 18:04:04 +00:00
* @param basePosition a position
2021-07-24 15:34:05 +00:00
* @param size a size
* @param density between 0 and 1 , inclusive
* @param treeType the tree type
2010-10-13 05:38:05 +00:00
* @return number of trees created
2014-07-29 21:23:00 +00:00
* @throws MaxChangedBlocksException thrown if too many blocks are changed
2010-10-13 05:38:05 +00:00
* /
2021-07-24 15:34:05 +00:00
public int makeForest ( BlockVector3 basePosition , int size , double density , TreeGenerator . TreeType treeType ) throws
MaxChangedBlocksException {
2019-11-21 07:57:32 +00:00
return makeForest ( CuboidRegion . fromCenter ( basePosition , size ) , density , treeType ) ;
2010-10-13 05:38:05 +00:00
}
2010-11-07 04:03:34 +00:00
2019-03-21 01:05:11 +00:00
/ * *
* Makes a forest .
*
2021-07-24 15:34:05 +00:00
* @param region the region to generate trees in
* @param density between 0 and 1 , inclusive
2019-03-21 01:05:11 +00:00
* @param treeType the tree type
* @return number of trees created
* @throws MaxChangedBlocksException thrown if too many blocks are changed
* /
public int makeForest ( Region region , double density , TreeGenerator . TreeType treeType ) throws MaxChangedBlocksException {
ForestGenerator generator = new ForestGenerator ( this , treeType ) ;
GroundFunction ground = new GroundFunction ( new ExistingBlockMask ( this ) , generator ) ;
2021-08-17 00:47:09 +00:00
//FAWE start - provide extent for preloading
LayerVisitor visitor = new LayerVisitor ( asFlatRegion ( region ) , minimumBlockY ( region ) , maximumBlockY ( region ) , ground , this ) ;
//FAWE end
2019-03-21 01:05:11 +00:00
visitor . setMask ( new NoiseFilter2D ( new RandomNoise ( ) , density ) ) ;
Operations . completeLegacy ( visitor ) ;
return ground . getAffected ( ) ;
2010-10-13 05:38:05 +00:00
}
2010-11-07 04:03:34 +00:00
2010-11-17 06:59:53 +00:00
/ * *
* Get the block distribution inside a region .
2011-09-24 19:32:03 +00:00
*
2014-07-29 18:04:04 +00:00
* @param region a region
* @return the results
2010-11-17 06:59:53 +00:00
* /
2018-12-27 00:39:10 +00:00
public List < Countable < BlockState > > getBlockDistribution ( Region region , boolean separateStates ) {
2021-07-23 15:48:51 +00:00
//FAWE start - get distr
2020-10-05 17:41:41 +00:00
if ( separateStates ) {
return getBlockDistributionWithData ( region ) ;
}
2019-10-23 04:23:52 +00:00
List < Countable < BlockType > > normalDistr = getBlockDistribution ( region ) ;
2019-04-03 11:28:57 +00:00
List < Countable < BlockState > > distribution = new ArrayList < > ( ) ;
2019-10-23 04:23:52 +00:00
for ( Countable < BlockType > count : normalDistr ) {
distribution . add ( new Countable < > ( count . getID ( ) . getDefaultState ( ) , count . getAmount ( ) ) ) ;
2018-08-12 14:03:07 +00:00
}
2021-07-23 15:48:51 +00:00
//FAWE end
2013-01-19 14:31:00 +00:00
return distribution ;
}
2019-06-04 15:48:30 +00:00
/ * *
* Generate a shape for the given expression .
*
2021-07-24 15:34:05 +00:00
* @param region the region to generate the shape in
* @param zero the coordinate origin for x / y / z variables
* @param unit the scale of the x / y / z / variables
* @param pattern the default material to make the shape from
2019-06-04 15:48:30 +00:00
* @param expressionString the expression defining the shape
2021-07-24 15:34:05 +00:00
* @param hollow whether the shape should be hollow
2019-06-04 15:48:30 +00:00
* @return number of blocks changed
2021-07-24 15:34:05 +00:00
* @throws ExpressionException if there is a problem with the expression
2020-10-05 17:41:41 +00:00
* @throws MaxChangedBlocksException if the maximum block change limit is exceeded
2019-06-04 15:48:30 +00:00
* /
2021-07-24 15:34:05 +00:00
public int makeShape (
final Region region , final Vector3 zero , final Vector3 unit ,
final Pattern pattern , final String expressionString , final boolean hollow
)
2019-06-30 18:56:32 +00:00
throws ExpressionException , MaxChangedBlocksException {
2021-07-24 15:34:05 +00:00
return makeShape (
region ,
zero ,
unit ,
pattern ,
expressionString ,
hollow ,
WorldEdit . getInstance ( ) . getConfiguration ( ) . calculationTimeout
) ;
2019-06-30 18:56:32 +00:00
}
/ * *
* Generate a shape for the given expression .
*
2021-07-24 15:34:05 +00:00
* @param region the region to generate the shape in
* @param zero the coordinate origin for x / y / z variables
* @param unit the scale of the x / y / z / variables
* @param pattern the default material to make the shape from
2019-06-30 18:56:32 +00:00
* @param expressionString the expression defining the shape
2021-07-24 15:34:05 +00:00
* @param hollow whether the shape should be hollow
* @param timeout the time , in milliseconds , to wait for each expression evaluation before halting it . - 1 to disable
2019-06-30 18:56:32 +00:00
* @return number of blocks changed
2021-07-24 15:34:05 +00:00
* @throws ExpressionException if there is a problem with the expression
2020-10-05 17:41:41 +00:00
* @throws MaxChangedBlocksException if the maximum block change limit is exceeded
2019-06-30 18:56:32 +00:00
* /
2021-07-24 15:34:05 +00:00
public int makeShape (
final Region region , final Vector3 zero , final Vector3 unit ,
final Pattern pattern , final String expressionString , final boolean hollow , final int timeout
)
2019-06-04 15:48:30 +00:00
throws ExpressionException , MaxChangedBlocksException {
2011-11-01 13:57:58 +00:00
final Expression expression = Expression . compile ( expressionString , " x " , " y " , " z " , " type " , " data " ) ;
expression . optimize ( ) ;
2019-10-19 05:24:56 +00:00
final Variable typeVariable = expression . getSlots ( ) . getVariable ( " type " )
2021-07-24 15:34:05 +00:00
. orElseThrow ( IllegalStateException : : new ) ;
2019-10-19 05:24:56 +00:00
final Variable dataVariable = expression . getSlots ( ) . getVariable ( " data " )
2021-07-24 15:34:05 +00:00
. orElseThrow ( IllegalStateException : : new ) ;
2011-11-01 13:57:58 +00:00
2013-09-21 12:35:57 +00:00
final WorldEditExpressionEnvironment environment = new WorldEditExpressionEnvironment ( this , unit , zero ) ;
expression . setEnvironment ( environment ) ;
2019-03-07 00:58:32 +00:00
final int [ ] timedOut = { 0 } ;
2011-11-01 13:57:58 +00:00
final ArbitraryShape shape = new ArbitraryShape ( region ) {
@Override
2019-06-30 18:56:32 +00:00
protected BaseBlock getMaterial ( int x , int y , int z , BaseBlock defaultMaterial ) {
2018-10-19 20:13:32 +00:00
final Vector3 current = Vector3 . at ( x , y , z ) ;
2013-09-21 12:35:57 +00:00
environment . setCurrentBlock ( current ) ;
2018-12-23 16:19:33 +00:00
final Vector3 scaled = current . subtract ( zero ) . divide ( unit ) ;
2011-11-01 13:57:58 +00:00
try {
2019-11-20 00:11:54 +00:00
int [ ] legacy = LegacyMapper . getInstance ( ) . getLegacyFromBlock ( defaultMaterial . toImmutableState ( ) ) ;
int typeVar = 0 ;
int dataVar = 0 ;
if ( legacy ! = null ) {
typeVar = legacy [ 0 ] ;
if ( legacy . length > 1 ) {
dataVar = legacy [ 1 ] ;
}
}
2021-07-24 15:34:05 +00:00
if ( expression . evaluate (
new double [ ] { scaled . getX ( ) , scaled . getY ( ) , scaled . getZ ( ) , typeVar , dataVar } ,
timeout
) < = 0 ) {
2011-11-01 13:57:58 +00:00
return null ;
}
2019-11-20 00:11:54 +00:00
int newType = ( int ) typeVariable . getValue ( ) ;
int newData = ( int ) dataVariable . getValue ( ) ;
if ( newType ! = typeVar | | newData ! = dataVar ) {
BlockState state = LegacyMapper . getInstance ( ) . getBlockFromLegacy ( newType , newData ) ;
return state = = null ? defaultMaterial : state . toBaseBlock ( ) ;
} else {
return defaultMaterial ;
}
2019-06-30 18:56:32 +00:00
} catch ( ExpressionTimeoutException e ) {
timedOut [ 0 ] = timedOut [ 0 ] + 1 ;
return null ;
2019-04-02 22:21:02 +00:00
} catch ( Exception e ) {
2021-03-29 13:29:16 +00:00
LOGGER . warn ( " Failed to create shape " , e ) ;
2011-11-01 13:57:58 +00:00
return null ;
}
}
} ;
2019-03-07 00:58:32 +00:00
int changed = shape . generate ( this , pattern , hollow ) ;
if ( timedOut [ 0 ] > 0 ) {
throw new ExpressionTimeoutException (
String . format ( " %d blocks changed. %d blocks took too long to evaluate (increase with //timeout). " ,
2021-07-24 15:34:05 +00:00
changed , timedOut [ 0 ]
) ) ;
2018-08-12 14:03:07 +00:00
}
2019-03-07 00:58:32 +00:00
return changed ;
2011-11-01 13:57:58 +00:00
}
2011-11-01 14:23:42 +00:00
2020-06-13 18:41:36 +00:00
/ * *
* Deforms the region by a given expression . A deform provides a block ' s x , y , and z coordinates ( possibly scaled )
* to an expression , and then sets the block to the block given by the resulting values of the variables , if they
* have changed .
*
2021-07-24 15:34:05 +00:00
* @param region the region to deform
* @param zero the origin of the coordinate system
* @param unit the scale of the coordinate system
2020-06-13 18:41:36 +00:00
* @param expressionString the expression to evaluate for each block
* @return number of blocks changed
2021-07-24 15:34:05 +00:00
* @throws ExpressionException thrown on invalid expression input
2020-06-13 18:41:36 +00:00
* @throws MaxChangedBlocksException thrown if too many blocks are changed
* /
2019-06-04 15:48:30 +00:00
public int deformRegion ( final Region region , final Vector3 zero , final Vector3 unit , final String expressionString )
throws ExpressionException , MaxChangedBlocksException {
2019-06-30 18:56:32 +00:00
return deformRegion ( region , zero , unit , expressionString , WorldEdit . getInstance ( ) . getConfiguration ( ) . calculationTimeout ) ;
}
2020-06-13 18:41:36 +00:00
/ * *
* Deforms the region by a given expression . A deform provides a block ' s x , y , and z coordinates ( possibly scaled )
* to an expression , and then sets the block to the block given by the resulting values of the variables , if they
* have changed .
*
2021-07-24 15:34:05 +00:00
* @param region the region to deform
* @param zero the origin of the coordinate system
* @param unit the scale of the coordinate system
2020-06-13 18:41:36 +00:00
* @param expressionString the expression to evaluate for each block
2021-07-24 15:34:05 +00:00
* @param timeout maximum time for the expression to evaluate for each block . - 1 for unlimited .
2020-06-13 18:41:36 +00:00
* @return number of blocks changed
2021-07-24 15:34:05 +00:00
* @throws ExpressionException thrown on invalid expression input
2020-06-13 18:41:36 +00:00
* @throws MaxChangedBlocksException thrown if too many blocks are changed
* /
2021-07-24 15:34:05 +00:00
public int deformRegion (
final Region region , final Vector3 zero , final Vector3 unit , final String expressionString ,
final int timeout
) throws ExpressionException , MaxChangedBlocksException {
2011-11-01 14:23:42 +00:00
final Expression expression = Expression . compile ( expressionString , " x " , " y " , " z " ) ;
expression . optimize ( ) ;
2021-09-19 20:02:41 +00:00
return deformRegion ( region , zero , unit , expression , timeout ) ;
}
2019-06-04 15:48:30 +00:00
2021-09-19 20:02:41 +00:00
/ * *
* Internal version of { @link EditSession # deformRegion ( Region , Vector3 , Vector3 , String , int ) } .
*
* < p >
* The Expression class is subject to change . Expressions should be provided via the string overload .
* < / p >
* /
public int deformRegion (
final Region region , final Vector3 zero , final Vector3 unit , final Expression expression ,
final int timeout
) throws ExpressionException , MaxChangedBlocksException {
2019-10-19 05:24:56 +00:00
final Variable x = expression . getSlots ( ) . getVariable ( " x " )
2021-07-24 15:34:05 +00:00
. orElseThrow ( IllegalStateException : : new ) ;
2019-10-19 05:24:56 +00:00
final Variable y = expression . getSlots ( ) . getVariable ( " y " )
2021-07-24 15:34:05 +00:00
. orElseThrow ( IllegalStateException : : new ) ;
2019-10-19 05:24:56 +00:00
final Variable z = expression . getSlots ( ) . getVariable ( " z " )
2021-07-24 15:34:05 +00:00
. orElseThrow ( IllegalStateException : : new ) ;
2019-07-06 00:46:48 +00:00
2013-09-21 12:35:57 +00:00
final WorldEditExpressionEnvironment environment = new WorldEditExpressionEnvironment ( this , unit , zero ) ;
expression . setEnvironment ( environment ) ;
2021-07-23 15:48:51 +00:00
//FAWE start
2018-12-23 16:19:33 +00:00
final Vector3 zero2 = zero . add ( 0 . 5 , 0 . 5 , 0 . 5 ) ;
2011-11-02 02:39:02 +00:00
2021-07-23 15:48:51 +00:00
RegionVisitor visitor = new RegionVisitor ( region , position - > {
try {
// offset, scale
final Vector3 scaled = position . toVector3 ( ) . subtract ( zero ) . divide ( unit ) ;
2011-11-02 02:39:02 +00:00
2021-07-23 15:48:51 +00:00
// transform
expression . evaluate ( new double [ ] { scaled . getX ( ) , scaled . getY ( ) , scaled . getZ ( ) } , timeout ) ;
int xv = ( int ) ( x . getValue ( ) * unit . getX ( ) + zero2 . getX ( ) ) ;
int yv = ( int ) ( y . getValue ( ) * unit . getY ( ) + zero2 . getY ( ) ) ;
int zv = ( int ) ( z . getValue ( ) * unit . getZ ( ) + zero2 . getZ ( ) ) ;
2020-07-03 15:45:28 +00:00
2021-07-23 15:48:51 +00:00
BlockState get ;
2021-08-17 21:13:51 +00:00
if ( yv > = minY & & yv < = maxY ) {
2021-07-23 15:48:51 +00:00
get = getBlock ( xv , yv , zv ) ;
} else {
get = BlockTypes . AIR . getDefaultState ( ) ;
2018-08-12 14:03:07 +00:00
}
2021-07-23 15:48:51 +00:00
// read block from world
return setBlock ( position , get ) ;
} catch ( EvaluationException e ) {
throw new RuntimeException ( e ) ;
2011-11-01 14:23:42 +00:00
}
2021-07-24 14:47:22 +00:00
} , this ) ;
2018-08-12 14:03:07 +00:00
Operations . completeBlindly ( visitor ) ;
changes + = visitor . getAffected ( ) ;
return changes ;
2021-07-23 15:48:51 +00:00
//FAWE end
2011-11-01 14:23:42 +00:00
}
2011-12-08 09:31:12 +00:00
2021-07-23 15:48:51 +00:00
//FAWE start - respect Mask
2021-07-24 15:34:05 +00:00
2011-12-08 09:31:12 +00:00
/ * *
2011-12-20 10:20:18 +00:00
* Hollows out the region ( Semi - well - defined for non - cuboid selections ) .
2011-12-08 09:31:12 +00:00
*
2021-07-24 15:34:05 +00:00
* @param region the region to hollow out .
2011-12-20 10:20:18 +00:00
* @param thickness the thickness of the shell to leave ( manhattan distance )
2021-07-24 15:34:05 +00:00
* @param pattern The block pattern to use
2011-12-08 09:31:12 +00:00
* @return number of blocks affected
2014-07-29 21:23:00 +00:00
* @throws MaxChangedBlocksException thrown if too many blocks are changed
2011-12-08 09:31:12 +00:00
* /
2019-09-22 01:00:45 +00:00
public int hollowOutRegion ( Region region , int thickness , Pattern pattern , Mask mask ) {
2019-07-18 06:56:57 +00:00
try {
2020-10-05 17:41:41 +00:00
final Set < BlockVector3 > outside = new LocalBlockVectorSet ( ) ;
2011-12-08 09:31:12 +00:00
2020-10-05 17:41:41 +00:00
final BlockVector3 min = region . getMinimumPoint ( ) ;
final BlockVector3 max = region . getMaximumPoint ( ) ;
2011-12-08 09:31:12 +00:00
2020-10-05 17:41:41 +00:00
final int minX = min . getBlockX ( ) ;
final int minY = min . getBlockY ( ) ;
final int minZ = min . getBlockZ ( ) ;
final int maxX = max . getBlockX ( ) ;
final int maxY = max . getBlockY ( ) ;
final int maxZ = max . getBlockZ ( ) ;
2021-08-11 13:56:10 +00:00
//FAWE start - mutable
MutableBlockVector3 mutable = new MutableBlockVector3 ( ) ;
//FAWE end
2020-10-05 17:41:41 +00:00
for ( int x = minX ; x < = maxX ; + + x ) {
for ( int y = minY ; y < = maxY ; + + y ) {
2021-08-11 13:56:10 +00:00
//FAWE start - mutable
recurseHollow ( region , mutable . setComponents ( x , y , minZ ) , outside , mask ) ;
recurseHollow ( region , mutable . setComponents ( x , y , maxZ ) , outside , mask ) ;
//FAWE end
2020-10-05 17:41:41 +00:00
}
}
2011-12-08 09:31:12 +00:00
for ( int y = minY ; y < = maxY ; + + y ) {
2020-10-05 17:41:41 +00:00
for ( int z = minZ ; z < = maxZ ; + + z ) {
2021-08-11 13:56:10 +00:00
//FAWE start - mutable
recurseHollow ( region , mutable . setComponents ( minX , y , z ) , outside , mask ) ;
recurseHollow ( region , mutable . setComponents ( maxX , y , z ) , outside , mask ) ;
//FAWE end
2020-10-05 17:41:41 +00:00
}
2011-12-08 09:31:12 +00:00
}
for ( int z = minZ ; z < = maxZ ; + + z ) {
2020-10-05 17:41:41 +00:00
for ( int x = minX ; x < = maxX ; + + x ) {
2021-08-11 13:56:10 +00:00
//FAWE start - mutable
recurseHollow ( region , mutable . setComponents ( x , minY , z ) , outside , mask ) ;
recurseHollow ( region , mutable . setComponents ( x , maxY , z ) , outside , mask ) ;
//FAWE end
2020-10-05 17:41:41 +00:00
}
2011-12-08 09:31:12 +00:00
}
2020-10-05 17:41:41 +00:00
for ( int i = 1 ; i < thickness ; + + i ) {
final Set < BlockVector3 > newOutside = new LocalBlockVectorSet ( ) ;
2021-07-24 15:34:05 +00:00
outer :
for ( BlockVector3 position : region ) {
2020-10-05 17:41:41 +00:00
for ( BlockVector3 recurseDirection : recurseDirections ) {
BlockVector3 neighbor = position . add ( recurseDirection ) ;
if ( outside . contains ( neighbor ) ) {
newOutside . add ( position ) ;
continue outer ;
}
}
}
outside . addAll ( newOutside ) ;
2011-12-08 09:31:12 +00:00
}
2021-07-24 15:34:05 +00:00
outer :
for ( BlockVector3 position : region ) {
2018-12-23 16:19:33 +00:00
for ( BlockVector3 recurseDirection : recurseDirections ) {
BlockVector3 neighbor = position . add ( recurseDirection ) ;
2019-06-04 15:48:30 +00:00
2011-12-19 10:58:38 +00:00
if ( outside . contains ( neighbor ) ) {
continue outer ;
}
}
2020-10-05 17:41:41 +00:00
this . changes + + ;
2020-03-21 01:39:40 +00:00
pattern . apply ( getExtent ( ) , position , position ) ;
}
2019-07-18 06:56:57 +00:00
} catch ( WorldEditException e ) {
throw new RuntimeException ( e ) ;
2011-12-08 09:31:12 +00:00
}
2018-08-12 14:03:07 +00:00
return changes ;
}
2021-07-23 15:48:51 +00:00
//FAWE end
2018-08-12 14:03:07 +00:00
2021-07-24 15:34:05 +00:00
public int drawLine ( Pattern pattern , BlockVector3 pos1 , BlockVector3 pos2 , double radius , boolean filled ) throws
MaxChangedBlocksException {
2018-08-12 14:03:07 +00:00
return drawLine ( pattern , pos1 , pos2 , radius , filled , false ) ;
2011-12-08 09:31:12 +00:00
}
2013-07-26 05:45:17 +00:00
/ * *
* Draws a line ( out of blocks ) between two vectors .
*
2013-08-05 16:53:30 +00:00
* @param pattern The block pattern used to draw the line .
2021-07-24 15:34:05 +00:00
* @param pos1 One of the points that define the line .
* @param pos2 The other point that defines the line .
* @param radius The radius ( thickness ) of the line .
* @param filled If false , only a shell will be generated .
2013-07-26 05:45:17 +00:00
* @return number of blocks affected
2014-07-29 21:23:00 +00:00
* @throws MaxChangedBlocksException thrown if too many blocks are changed
2020-02-12 21:18:36 +00:00
* @see # drawLine ( Pattern , List , double , boolean )
2013-07-26 05:45:17 +00:00
* /
2019-06-30 18:56:32 +00:00
public int drawLine ( Pattern pattern , BlockVector3 pos1 , BlockVector3 pos2 , double radius , boolean filled , boolean flat )
2021-07-24 15:34:05 +00:00
throws MaxChangedBlocksException {
2013-07-26 05:45:17 +00:00
2021-08-11 13:56:10 +00:00
//FAWE start - LocalBlockVectorSet
2018-08-12 14:03:07 +00:00
LocalBlockVectorSet vset = new LocalBlockVectorSet ( ) ;
2013-07-26 05:45:17 +00:00
boolean notdrawn = true ;
2021-07-23 15:48:51 +00:00
//FAWE end
2013-07-26 05:45:17 +00:00
2020-10-05 17:41:41 +00:00
int x1 = pos1 . getBlockX ( ) ;
int y1 = pos1 . getBlockY ( ) ;
int z1 = pos1 . getBlockZ ( ) ;
int x2 = pos2 . getBlockX ( ) ;
int y2 = pos2 . getBlockY ( ) ;
int z2 = pos2 . getBlockZ ( ) ;
int tipx = x1 ;
int tipy = y1 ;
int tipz = z1 ;
int dx = Math . abs ( x2 - x1 ) ;
int dy = Math . abs ( y2 - y1 ) ;
int dz = Math . abs ( z2 - z1 ) ;
2013-07-26 05:45:17 +00:00
2019-03-28 19:02:37 +00:00
if ( dx + dy + dz = = 0 ) {
2021-08-11 13:56:10 +00:00
//FAWE start - LocalBlockVectorSet
vset . add ( tipx , tipy , tipz ) ;
2013-08-04 01:42:19 +00:00
notdrawn = false ;
2021-07-23 15:48:51 +00:00
//FAWE end
2013-07-26 05:45:17 +00:00
}
2020-02-12 21:18:36 +00:00
int dMax = Math . max ( Math . max ( dx , dy ) , dz ) ;
2021-07-23 15:48:51 +00:00
//FAWE start - notdrawn
2020-02-12 21:18:36 +00:00
if ( dMax = = dx & & notdrawn ) {
2021-07-23 15:48:51 +00:00
//FAWE end
2013-07-26 05:45:17 +00:00
for ( int domstep = 0 ; domstep < = dx ; domstep + + ) {
2019-03-28 19:02:37 +00:00
tipx = x1 + domstep * ( x2 - x1 > 0 ? 1 : - 1 ) ;
2019-09-22 01:00:45 +00:00
tipy = ( int ) Math . round ( y1 + domstep * ( double ) dy / ( double ) dx * ( y2 - y1 > 0 ? 1 : - 1 ) ) ;
tipz = ( int ) Math . round ( z1 + domstep * ( double ) dz / ( double ) dx * ( z2 - z1 > 0 ? 1 : - 1 ) ) ;
2019-03-28 19:02:37 +00:00
2021-08-11 13:56:10 +00:00
//FAWE start - LocalBlockVectorSet
vset . add ( tipx , tipy , tipz ) ;
//FAWE end
2013-07-26 05:45:17 +00:00
}
2021-07-23 15:48:51 +00:00
//FAWE start - notdrawn
2020-02-12 21:18:36 +00:00
} else if ( dMax = = dy & & notdrawn ) {
2021-07-23 15:48:51 +00:00
//FAWE end
2013-07-26 05:45:17 +00:00
for ( int domstep = 0 ; domstep < = dy ; domstep + + ) {
2019-03-28 19:02:37 +00:00
tipy = y1 + domstep * ( y2 - y1 > 0 ? 1 : - 1 ) ;
2019-09-22 01:00:45 +00:00
tipx = ( int ) Math . round ( x1 + domstep * ( double ) dx / ( double ) dy * ( x2 - x1 > 0 ? 1 : - 1 ) ) ;
tipz = ( int ) Math . round ( z1 + domstep * ( double ) dz / ( double ) dy * ( z2 - z1 > 0 ? 1 : - 1 ) ) ;
2013-07-26 05:45:17 +00:00
2021-08-11 13:56:10 +00:00
//FAWE start - LocalBlockVectorSet
vset . add ( tipx , tipy , tipz ) ;
//FAWE end
2013-07-26 05:45:17 +00:00
}
2021-07-23 15:48:51 +00:00
//FAWE start - notdrawn
2020-02-12 21:18:36 +00:00
} else if ( dMax = = dz & & notdrawn ) {
2021-07-23 15:48:51 +00:00
//FAWE end
2013-07-26 05:45:17 +00:00
for ( int domstep = 0 ; domstep < = dz ; domstep + + ) {
2019-03-28 19:02:37 +00:00
tipz = z1 + domstep * ( z2 - z1 > 0 ? 1 : - 1 ) ;
2020-10-05 17:41:41 +00:00
tipy = ( int ) Math . round ( y1 + domstep * ( double ) dy / ( double ) dz * ( y2 - y1 > 0 ? 1 : - 1 ) ) ;
tipx = ( int ) Math . round ( x1 + domstep * ( double ) dx / ( double ) dz * ( x2 - x1 > 0 ? 1 : - 1 ) ) ;
2019-03-28 19:02:37 +00:00
2021-08-11 13:56:10 +00:00
//FAWE start - LocalBlockVectorSet
vset . add ( tipx , tipy , tipz ) ;
//FAWE end
2013-07-26 05:45:17 +00:00
}
}
2021-07-23 15:48:51 +00:00
//FAWE start - set BV3
2018-12-23 16:19:33 +00:00
Set < BlockVector3 > newVset ;
2018-08-12 14:03:07 +00:00
if ( flat ) {
2019-07-06 00:46:48 +00:00
newVset = getStretched ( vset , radius ) ;
2018-08-12 14:03:07 +00:00
if ( ! filled ) {
newVset = this . getOutline ( newVset ) ;
}
} else {
2019-07-06 00:46:48 +00:00
newVset = getBallooned ( vset , radius ) ;
2018-08-12 14:03:07 +00:00
if ( ! filled ) {
newVset = this . getHollowed ( newVset ) ;
}
2013-08-05 16:53:30 +00:00
}
2020-12-17 15:02:49 +00:00
return this . changes + = setBlocks ( newVset , pattern ) ;
2021-07-23 15:48:51 +00:00
//FAWE end
2013-08-05 16:53:30 +00:00
}
2020-02-12 21:18:36 +00:00
/ * *
* Draws a line ( out of blocks ) between two or more vectors .
*
* @param pattern The block pattern used to draw the line .
* @param vectors the list of vectors to draw the line between
2021-07-24 15:34:05 +00:00
* @param radius The radius ( thickness ) of the line .
* @param filled If false , only a shell will be generated .
2020-02-12 21:18:36 +00:00
* @return number of blocks affected
* @throws MaxChangedBlocksException thrown if too many blocks are changed
* /
public int drawLine ( Pattern pattern , List < BlockVector3 > vectors , double radius , boolean filled )
2020-03-21 01:39:40 +00:00
throws MaxChangedBlocksException {
2020-02-12 21:18:36 +00:00
Set < BlockVector3 > vset = new HashSet < > ( ) ;
for ( int i = 0 ; vectors . size ( ) ! = 0 & & i < vectors . size ( ) - 1 ; i + + ) {
BlockVector3 pos1 = vectors . get ( i ) ;
BlockVector3 pos2 = vectors . get ( i + 1 ) ;
2020-10-05 17:41:41 +00:00
int x1 = pos1 . getBlockX ( ) ;
int y1 = pos1 . getBlockY ( ) ;
int z1 = pos1 . getBlockZ ( ) ;
int x2 = pos2 . getBlockX ( ) ;
int y2 = pos2 . getBlockY ( ) ;
int z2 = pos2 . getBlockZ ( ) ;
int tipx = x1 ;
int tipy = y1 ;
int tipz = z1 ;
int dx = Math . abs ( x2 - x1 ) ;
int dy = Math . abs ( y2 - y1 ) ;
int dz = Math . abs ( z2 - z1 ) ;
2020-02-12 21:18:36 +00:00
if ( dx + dy + dz = = 0 ) {
vset . add ( BlockVector3 . at ( tipx , tipy , tipz ) ) ;
continue ;
}
int dMax = Math . max ( Math . max ( dx , dy ) , dz ) ;
if ( dMax = = dx ) {
for ( int domstep = 0 ; domstep < = dx ; domstep + + ) {
tipx = x1 + domstep * ( x2 - x1 > 0 ? 1 : - 1 ) ;
tipy = ( int ) Math . round ( y1 + domstep * ( ( double ) dy ) / ( ( double ) dx ) * ( y2 - y1 > 0 ? 1 : - 1 ) ) ;
tipz = ( int ) Math . round ( z1 + domstep * ( ( double ) dz ) / ( ( double ) dx ) * ( z2 - z1 > 0 ? 1 : - 1 ) ) ;
vset . add ( BlockVector3 . at ( tipx , tipy , tipz ) ) ;
}
} else if ( dMax = = dy ) {
for ( int domstep = 0 ; domstep < = dy ; domstep + + ) {
tipy = y1 + domstep * ( y2 - y1 > 0 ? 1 : - 1 ) ;
tipx = ( int ) Math . round ( x1 + domstep * ( ( double ) dx ) / ( ( double ) dy ) * ( x2 - x1 > 0 ? 1 : - 1 ) ) ;
tipz = ( int ) Math . round ( z1 + domstep * ( ( double ) dz ) / ( ( double ) dy ) * ( z2 - z1 > 0 ? 1 : - 1 ) ) ;
vset . add ( BlockVector3 . at ( tipx , tipy , tipz ) ) ;
}
} else /* if (dMax == dz) */ {
for ( int domstep = 0 ; domstep < = dz ; domstep + + ) {
tipz = z1 + domstep * ( z2 - z1 > 0 ? 1 : - 1 ) ;
2020-10-05 17:41:41 +00:00
tipy = ( int ) Math . round ( y1 + domstep * ( ( double ) dy ) / ( ( double ) dz ) * ( y2 - y1 > 0 ? 1 : - 1 ) ) ;
tipx = ( int ) Math . round ( x1 + domstep * ( ( double ) dx ) / ( ( double ) dz ) * ( x2 - x1 > 0 ? 1 : - 1 ) ) ;
2020-02-12 21:18:36 +00:00
vset . add ( BlockVector3 . at ( tipx , tipy , tipz ) ) ;
}
}
}
vset = getBallooned ( vset , radius ) ;
if ( ! filled ) {
vset = getHollowed ( vset ) ;
}
2020-12-17 15:02:49 +00:00
return this . changes + = setBlocks ( vset , pattern ) ;
2020-02-12 21:18:36 +00:00
}
2013-08-05 16:53:30 +00:00
/ * *
* Draws a spline ( out of blocks ) between specified vectors .
*
2021-07-24 15:34:05 +00:00
* @param pattern The block pattern used to draw the spline .
2013-08-05 16:53:30 +00:00
* @param nodevectors The list of vectors to draw through .
2021-07-24 15:34:05 +00:00
* @param tension The tension of every node .
* @param bias The bias of every node .
* @param continuity The continuity of every node .
* @param quality The quality of the spline . Must be greater than 0 .
* @param radius The radius ( thickness ) of the spline .
* @param filled If false , only a shell will be generated .
2013-08-05 16:53:30 +00:00
* @return number of blocks affected
2014-07-29 21:23:00 +00:00
* @throws MaxChangedBlocksException thrown if too many blocks are changed
2013-08-05 16:53:30 +00:00
* /
2021-07-24 15:34:05 +00:00
public int drawSpline (
Pattern pattern , List < BlockVector3 > nodevectors , double tension , double bias ,
double continuity , double quality , double radius , boolean filled
)
2019-06-04 15:48:30 +00:00
throws MaxChangedBlocksException {
2018-08-12 14:03:07 +00:00
LocalBlockVectorSet vset = new LocalBlockVectorSet ( ) ;
2019-06-04 15:48:30 +00:00
List < Node > nodes = new ArrayList < > ( nodevectors . size ( ) ) ;
Interpolation interpol = new KochanekBartelsInterpolation ( ) ;
2013-08-05 16:53:30 +00:00
2018-12-23 16:19:33 +00:00
for ( BlockVector3 nodevector : nodevectors ) {
Node n = new Node ( nodevector . toVector3 ( ) ) ;
2013-08-05 16:53:30 +00:00
n . setTension ( tension ) ;
n . setBias ( bias ) ;
n . setContinuity ( continuity ) ;
nodes . add ( n ) ;
}
interpol . setNodes ( nodes ) ;
2019-06-04 15:48:30 +00:00
double splinelength = interpol . arcLength ( 0 , 1 ) ;
2013-08-05 16:53:30 +00:00
for ( double loop = 0 ; loop < = 1 ; loop + = 1D / splinelength / quality ) {
2019-07-06 00:46:48 +00:00
BlockVector3 tipv = interpol . getPosition ( loop ) . toBlockPoint ( ) ;
2018-08-12 14:03:07 +00:00
if ( radius = = 0 ) {
2019-07-17 16:31:13 +00:00
pattern . apply ( this , tipv , tipv ) ;
2020-07-03 12:18:09 +00:00
changes + + ;
2018-08-12 14:03:07 +00:00
} else {
vset . add ( tipv ) ;
}
2013-08-05 16:53:30 +00:00
}
2018-12-23 16:19:33 +00:00
Set < BlockVector3 > newVset ;
2018-08-12 14:03:07 +00:00
if ( radius ! = 0 ) {
2019-07-06 00:46:48 +00:00
newVset = getBallooned ( vset , radius ) ;
2018-08-12 14:03:07 +00:00
if ( ! filled ) {
newVset = this . getHollowed ( newVset ) ;
}
2020-12-17 15:02:49 +00:00
return this . changes + = setBlocks ( newVset , pattern ) ;
2013-08-04 01:42:19 +00:00
}
2018-08-12 14:03:07 +00:00
return changes ;
2013-08-04 01:42:19 +00:00
}
2019-07-06 00:46:48 +00:00
private static Set < BlockVector3 > getBallooned ( Set < BlockVector3 > vset , double radius ) {
2018-08-12 14:03:07 +00:00
if ( radius < 1 ) {
return vset ;
}
2019-06-04 15:48:30 +00:00
LocalBlockVectorSet returnset = new LocalBlockVectorSet ( ) ;
int ceilrad = ( int ) Math . ceil ( radius ) ;
for ( BlockVector3 v : vset ) {
2020-10-05 17:41:41 +00:00
int tipx = v . getBlockX ( ) ;
int tipy = v . getBlockY ( ) ;
int tipz = v . getBlockZ ( ) ;
2019-06-04 15:48:30 +00:00
2019-07-06 00:46:48 +00:00
for ( int loopx = tipx - ceilrad ; loopx < = tipx + ceilrad ; loopx + + ) {
for ( int loopy = tipy - ceilrad ; loopy < = tipy + ceilrad ; loopy + + ) {
for ( int loopz = tipz - ceilrad ; loopz < = tipz + ceilrad ; loopz + + ) {
2018-08-12 14:03:07 +00:00
if ( MathMan . hypot ( loopx - tipx , loopy - tipy , loopz - tipz ) < = radius ) {
returnset . add ( loopx , loopy , loopz ) ;
}
}
}
}
2013-08-04 01:42:19 +00:00
}
2018-08-12 14:03:07 +00:00
return returnset ;
2013-08-04 01:42:19 +00:00
}
2021-07-23 15:48:51 +00:00
//FAWE start
2019-07-06 00:46:48 +00:00
public static Set < BlockVector3 > getStretched ( Set < BlockVector3 > vset , double radius ) {
2018-08-12 14:03:07 +00:00
if ( radius < 1 ) {
return vset ;
}
final LocalBlockVectorSet returnset = new LocalBlockVectorSet ( ) ;
final int ceilrad = ( int ) Math . ceil ( radius ) ;
2019-09-22 01:00:45 +00:00
for ( BlockVector3 v : vset ) {
2020-10-05 17:41:41 +00:00
final int tipx = v . getBlockX ( ) ;
final int tipy = v . getBlockY ( ) ;
final int tipz = v . getBlockZ ( ) ;
2019-07-06 00:46:48 +00:00
for ( int loopx = tipx - ceilrad ; loopx < = tipx + ceilrad ; loopx + + ) {
for ( int loopz = tipz - ceilrad ; loopz < = tipz + ceilrad ; loopz + + ) {
2018-08-12 14:03:07 +00:00
if ( MathMan . hypot ( loopx - tipx , 0 , loopz - tipz ) < = radius ) {
returnset . add ( loopx , v . getBlockY ( ) , loopz ) ;
2013-08-05 16:53:30 +00:00
}
}
}
}
return returnset ;
}
2019-07-06 00:46:48 +00:00
public Set < BlockVector3 > getOutline ( Set < BlockVector3 > vset ) {
2018-08-12 14:03:07 +00:00
final LocalBlockVectorSet returnset = new LocalBlockVectorSet ( ) ;
2018-12-23 16:19:33 +00:00
final LocalBlockVectorSet newset = new LocalBlockVectorSet ( ) ;
newset . addAll ( vset ) ;
2019-06-30 18:56:32 +00:00
for ( BlockVector3 v : newset ) {
2020-10-05 17:41:41 +00:00
final int x = v . getX ( ) ;
final int y = v . getY ( ) ;
final int z = v . getZ ( ) ;
if ( ! ( newset . contains ( x + 1 , y , z )
2021-07-24 15:34:05 +00:00
& & newset . contains ( x - 1 , y , z )
& & newset . contains ( x , y , z + 1 )
& & newset . contains ( x , y , z - 1 ) ) ) {
2018-08-12 14:03:07 +00:00
returnset . add ( v ) ;
}
}
return returnset ;
}
2021-07-23 15:48:51 +00:00
//FAWE end
2018-08-12 14:03:07 +00:00
2019-07-06 00:46:48 +00:00
public Set < BlockVector3 > getHollowed ( Set < BlockVector3 > vset ) {
2019-06-30 18:56:32 +00:00
final Set < BlockVector3 > returnset = new LocalBlockVectorSet ( ) ;
2018-12-23 16:19:33 +00:00
final LocalBlockVectorSet newset = new LocalBlockVectorSet ( ) ;
newset . addAll ( vset ) ;
2019-06-30 18:56:32 +00:00
for ( BlockVector3 v : newset ) {
2020-10-05 17:41:41 +00:00
final int x = v . getX ( ) ;
final int y = v . getY ( ) ;
final int z = v . getZ ( ) ;
if ( ! ( newset . contains ( x + 1 , y , z )
2021-07-24 15:34:05 +00:00
& & newset . contains ( x - 1 , y , z )
& & newset . contains ( x , y + 1 , z )
& & newset . contains ( x , y - 1 , z )
& & newset . contains ( x , y , z + 1 )
& & newset . contains ( x , y , z - 1 ) ) ) {
2013-08-04 01:42:19 +00:00
returnset . add ( v ) ;
}
}
return returnset ;
}
2019-07-18 06:56:57 +00:00
private void recurseHollow ( Region region , BlockVector3 origin , Set < BlockVector3 > outside , Mask mask ) {
2019-04-05 14:01:05 +00:00
final LocalBlockVectorSet queue = new LocalBlockVectorSet ( ) ;
2019-06-08 18:48:30 +00:00
queue . add ( origin ) ;
2019-07-06 00:46:48 +00:00
2011-12-08 09:31:12 +00:00
while ( ! queue . isEmpty ( ) ) {
2019-07-18 06:56:57 +00:00
Iterator < BlockVector3 > iter = queue . iterator ( ) ;
while ( iter . hasNext ( ) ) {
final BlockVector3 current = iter . next ( ) ;
iter . remove ( ) ;
2020-09-11 19:13:31 +00:00
if ( mask . test ( current ) ) {
2019-07-18 06:56:57 +00:00
continue ;
}
if ( ! outside . add ( current ) ) {
continue ;
}
if ( ! region . contains ( current ) ) {
continue ;
}
2019-06-12 21:12:12 +00:00
2019-07-18 06:56:57 +00:00
for ( BlockVector3 recurseDirection : recurseDirections ) {
queue . add ( current . add ( recurseDirection ) ) ;
}
}
2019-06-12 21:12:12 +00:00
}
2011-12-08 09:31:12 +00:00
}
2013-01-19 14:31:00 +00:00
2021-07-24 15:34:05 +00:00
public int makeBiomeShape (
final Region region , final Vector3 zero , final Vector3 unit , final BiomeType biomeType ,
final String expressionString , final boolean hollow
) throws ExpressionException {
return makeBiomeShape (
region ,
zero ,
unit ,
biomeType ,
expressionString ,
hollow ,
WorldEdit . getInstance ( ) . getConfiguration ( ) . calculationTimeout
) ;
2019-06-30 18:56:32 +00:00
}
2021-07-24 15:34:05 +00:00
public int makeBiomeShape (
final Region region , final Vector3 zero , final Vector3 unit , final BiomeType biomeType ,
final String expressionString , final boolean hollow , final int timeout
) throws ExpressionException {
2013-10-20 14:26:06 +00:00
2021-01-06 16:57:59 +00:00
final Expression expression = Expression . compile ( expressionString , " x " , " y " , " z " ) ;
2013-10-20 14:26:06 +00:00
expression . optimize ( ) ;
final EditSession editSession = this ;
final WorldEditExpressionEnvironment environment = new WorldEditExpressionEnvironment ( editSession , unit , zero ) ;
expression . setEnvironment ( environment ) ;
2021-01-06 16:57:59 +00:00
AtomicInteger timedOut = new AtomicInteger ( ) ;
2013-10-20 14:26:06 +00:00
final ArbitraryBiomeShape shape = new ArbitraryBiomeShape ( region ) {
@Override
2020-08-18 19:48:31 +00:00
protected BiomeType getBiome ( int x , int y , int z , BiomeType defaultBiomeType ) {
2020-09-12 13:31:42 +00:00
environment . setCurrentBlock ( x , y , z ) ;
double scaledX = ( x - zero . getX ( ) ) / unit . getX ( ) ;
2020-09-14 19:16:46 +00:00
double scaledY = ( y - zero . getY ( ) ) / unit . getY ( ) ;
2020-09-12 13:31:42 +00:00
double scaledZ = ( z - zero . getZ ( ) ) / unit . getZ ( ) ;
2013-10-20 14:26:06 +00:00
try {
2020-09-12 13:31:42 +00:00
if ( expression . evaluate ( timeout , scaledX , scaledY , scaledZ ) < = 0 ) {
2018-08-12 14:03:07 +00:00
return null ;
2013-10-20 14:26:06 +00:00
}
2019-06-04 15:48:30 +00:00
// TODO: Allow biome setting via a script variable (needs BiomeType<->int mapping)
2013-10-20 14:26:06 +00:00
return defaultBiomeType ;
2019-06-30 18:56:32 +00:00
} catch ( ExpressionTimeoutException e ) {
2021-01-06 16:57:59 +00:00
timedOut . getAndIncrement ( ) ;
2019-06-30 18:56:32 +00:00
return null ;
2019-04-02 22:21:02 +00:00
} catch ( Exception e ) {
2021-03-29 13:29:16 +00:00
LOGGER . warn ( " Failed to create shape " , e ) ;
2013-10-20 14:26:06 +00:00
return null ;
}
}
} ;
2019-03-07 00:58:32 +00:00
int changed = shape . generate ( this , biomeType , hollow ) ;
2021-01-06 16:57:59 +00:00
if ( timedOut . get ( ) > 0 ) {
2019-06-30 18:56:32 +00:00
throw new ExpressionTimeoutException (
2021-01-06 16:57:59 +00:00
String . format ( " %d biomes changed. %d biomes took too long to evaluate (increase time with //timeout) " ,
2021-07-24 15:34:05 +00:00
changed , timedOut . get ( )
) ) ;
2019-06-30 18:56:32 +00:00
}
2019-03-07 00:58:32 +00:00
return changed ;
2013-10-20 14:26:06 +00:00
}
2019-06-04 15:48:30 +00:00
2018-12-23 16:19:33 +00:00
private static final BlockVector3 [ ] recurseDirections = {
Direction . NORTH . toBlockVector ( ) ,
Direction . EAST . toBlockVector ( ) ,
Direction . SOUTH . toBlockVector ( ) ,
Direction . WEST . toBlockVector ( ) ,
Direction . UP . toBlockVector ( ) ,
Direction . DOWN . toBlockVector ( ) ,
} ;
2019-06-04 15:48:30 +00:00
2021-07-23 15:48:51 +00:00
//FAWE start
2019-09-22 01:00:45 +00:00
public boolean regenerate ( Region region ) {
2018-08-12 14:03:07 +00:00
return regenerate ( region , this ) ;
}
2019-09-22 01:00:45 +00:00
public boolean regenerate ( Region region , EditSession session ) {
2018-08-12 14:03:07 +00:00
return session . regenerate ( region , null , null ) ;
}
2018-12-23 16:19:33 +00:00
private void setExistingBlocks ( BlockVector3 pos1 , BlockVector3 pos2 ) {
2019-04-03 03:36:32 +00:00
for ( int x = pos1 . getX ( ) ; x < = pos2 . getX ( ) ; x + + ) {
2018-08-12 14:03:07 +00:00
for ( int z = pos1 . getBlockZ ( ) ; z < = pos2 . getBlockZ ( ) ; z + + ) {
2019-04-03 03:36:32 +00:00
for ( int y = pos1 . getY ( ) ; y < = pos2 . getY ( ) ; y + + ) {
2019-07-18 06:56:57 +00:00
setBlock ( x , y , z , getFullBlock ( x , y , z ) ) ;
2018-08-12 14:03:07 +00:00
}
}
}
}
2019-09-22 01:00:45 +00:00
public boolean regenerate ( Region region , BiomeType biome , Long seed ) {
2018-08-12 14:03:07 +00:00
//TODO Optimize - avoid Vector2D creation (make mutable)
2020-01-06 08:36:16 +00:00
final AbstractChangeSet fcs = ( AbstractChangeSet ) this . getChangeSet ( ) ;
2019-07-18 16:07:31 +00:00
this . setChangeSet ( null ) ;
2018-08-12 14:03:07 +00:00
final FaweRegionExtent fe = this . getRegionExtent ( ) ;
final boolean cuboid = region instanceof CuboidRegion ;
if ( fe ! = null & & cuboid ) {
2019-07-22 20:42:40 +00:00
BlockVector3 max = region . getMaximumPoint ( ) ;
BlockVector3 min = region . getMinimumPoint ( ) ;
2021-07-24 15:34:05 +00:00
if ( ! fe . contains ( max . getBlockX ( ) , max . getBlockY ( ) , max . getBlockZ ( ) ) & & ! fe . contains (
min . getBlockX ( ) ,
min . getBlockY ( ) ,
min . getBlockZ ( )
) ) {
2020-01-29 20:01:38 +00:00
throw FaweCache . OUTSIDE_REGION ;
2018-08-12 14:03:07 +00:00
}
}
2018-12-23 16:19:33 +00:00
final Set < BlockVector2 > chunks = region . getChunks ( ) ;
2019-03-31 16:09:20 +00:00
MutableBlockVector3 mutable = new MutableBlockVector3 ( ) ;
2021-08-11 13:56:10 +00:00
MutableBlockVector3 mutable2 = new MutableBlockVector3 ( ) ;
2019-03-31 16:09:20 +00:00
MutableBlockVector2 mutable2D = new MutableBlockVector2 ( ) ;
2018-12-23 16:19:33 +00:00
for ( BlockVector2 chunk : chunks ) {
2018-08-12 14:03:07 +00:00
final int cx = chunk . getBlockX ( ) ;
final int cz = chunk . getBlockZ ( ) ;
final int bx = cx < < 4 ;
final int bz = cz < < 4 ;
2018-10-19 20:13:32 +00:00
final BlockVector3 cmin = BlockVector3 . at ( bx , 0 , bz ) ;
2019-04-05 06:51:42 +00:00
final BlockVector3 cmax = cmin . add ( 15 , maxY , 15 ) ;
2019-09-22 01:00:45 +00:00
final boolean containsBot1 =
2021-07-24 15:34:05 +00:00
fe = = null | | fe . contains ( cmin . getBlockX ( ) , cmin . getBlockY ( ) , cmin . getBlockZ ( ) ) ;
2018-08-12 14:03:07 +00:00
final boolean containsBot2 = region . contains ( cmin ) ;
2019-09-22 01:00:45 +00:00
final boolean containsTop1 =
2021-07-24 15:34:05 +00:00
fe = = null | | fe . contains ( cmax . getBlockX ( ) , cmax . getBlockY ( ) , cmax . getBlockZ ( ) ) ;
2018-08-12 14:03:07 +00:00
final boolean containsTop2 = region . contains ( cmax ) ;
2019-09-22 01:00:45 +00:00
if ( containsBot2 & & containsTop2 & & ! containsBot1 & & ! containsTop1 ) {
2018-08-12 14:03:07 +00:00
continue ;
}
boolean conNextX = chunks . contains ( mutable2D . setComponents ( cx + 1 , cz ) ) ;
boolean conNextZ = chunks . contains ( mutable2D . setComponents ( cx , cz + 1 ) ) ;
boolean containsAny = false ;
if ( cuboid & & containsBot1 & & containsBot2 & & containsTop1 & & containsTop2 & & conNextX & & conNextZ ) {
containsAny = true ;
if ( fcs ! = null ) {
for ( int x = 0 ; x < 16 ; x + + ) {
int xx = x + bx ;
for ( int z = 0 ; z < 16 ; z + + ) {
int zz = z + bz ;
2021-08-17 21:13:51 +00:00
for ( int y = minY ; y < maxY + 1 ; y + + ) {
2019-04-03 11:28:57 +00:00
BaseBlock block = getFullBlock ( mutable . setComponents ( xx , y , zz ) ) ;
2019-06-30 18:56:32 +00:00
fcs . add ( mutable , block , BlockTypes . AIR . getDefaultState ( ) . toBaseBlock ( ) ) ;
2018-08-12 14:03:07 +00:00
}
}
}
}
} else {
if ( ! conNextX ) {
2021-08-11 13:56:10 +00:00
setExistingBlocks ( mutable . setComponents ( bx + 16 , 0 , bz ) , mutable2 . setComponents ( bx + 31 , maxY , bz + 15 ) ) ;
2018-08-12 14:03:07 +00:00
}
if ( ! conNextZ ) {
2021-08-11 13:56:10 +00:00
setExistingBlocks ( mutable . setComponents ( bx , 0 , bz + 16 ) , mutable2 . setComponents ( bx + 15 , maxY , bz + 31 ) ) ;
2018-08-12 14:03:07 +00:00
}
if ( ! chunks . contains ( mutable2D . setComponents ( cx + 1 , cz + 1 ) ) & & ! conNextX & & ! conNextZ ) {
2021-08-11 13:56:10 +00:00
setExistingBlocks ( mutable . setComponents ( bx + 16 , 0 , bz + 16 ) , mutable2 . setComponents ( bx + 31 , maxY , bz + 31 ) ) ;
2018-08-12 14:03:07 +00:00
}
for ( int x = 0 ; x < 16 ; x + + ) {
int xx = x + bx ;
mutable . mutX ( xx ) ;
for ( int z = 0 ; z < 16 ; z + + ) {
int zz = z + bz ;
mutable . mutZ ( zz ) ;
2021-08-17 21:13:51 +00:00
for ( int y = minY ; y < maxY + 1 ; y + + ) {
2018-08-12 14:03:07 +00:00
mutable . mutY ( y ) ;
2019-04-03 11:28:57 +00:00
boolean contains = ( fe = = null | | fe . contains ( xx , y , zz ) ) & & region . contains ( mutable ) ;
2018-08-12 14:03:07 +00:00
if ( contains ) {
containsAny = true ;
if ( fcs ! = null ) {
2019-04-03 11:28:57 +00:00
BaseBlock block = getFullBlock ( mutable ) ;
fcs . add ( mutable , block , BlockTypes . AIR . getDefaultState ( ) . toBaseBlock ( ) ) ;
2018-08-12 14:03:07 +00:00
}
} else {
2019-09-22 01:00:45 +00:00
BaseBlock block = getFullBlock ( mutable ) ;
2018-08-12 14:03:07 +00:00
try {
2019-04-03 11:28:57 +00:00
setBlock ( mutable , block ) ;
2018-08-12 14:03:07 +00:00
} catch ( MaxChangedBlocksException e ) {
throw new RuntimeException ( e ) ;
}
}
}
}
}
}
if ( containsAny ) {
changes + + ;
TaskManager . IMP . sync ( new RunnableVal < Object > ( ) {
@Override
public void run ( Object value ) {
2019-07-18 16:07:31 +00:00
regenerateChunk ( cx , cz , biome , seed ) ;
2018-08-12 14:03:07 +00:00
}
} ) ;
}
}
if ( changes ! = 0 ) {
flushQueue ( ) ;
return true ;
}
return false ;
}
2020-07-01 17:28:38 +00:00
2020-07-27 21:51:26 +00:00
@Override
public List < ? extends Entity > getEntities ( ) {
return world . getEntities ( ) ;
}
2020-08-25 01:31:47 +00:00
2020-07-01 17:28:38 +00:00
@Override
public List < ? extends Entity > getEntities ( Region region ) {
return world . getEntities ( region ) ;
2020-07-03 17:52:55 +00:00
}
2020-08-25 01:31:47 +00:00
2020-07-03 17:52:55 +00:00
@Override
2020-08-19 09:08:59 +00:00
public Entity createEntity ( Location location , BaseEntity entity ) {
2020-07-03 17:52:55 +00:00
try {
return this . getExtent ( ) . createEntity ( location , entity ) ;
} catch ( WorldEditException e ) {
throw new RuntimeException ( " Unexpected exception " , e ) ;
}
}
2020-07-27 21:51:26 +00:00
@Override
2020-08-19 09:08:59 +00:00
public void removeEntity ( int x , int y , int z , UUID uuid ) {
2020-07-27 21:51:26 +00:00
try {
this . getExtent ( ) . removeEntity ( x , y , z , uuid ) ;
} catch ( WorldEditException e ) {
throw new RuntimeException ( " Unexpected exception " , e ) ;
}
}
2021-07-16 09:43:15 +00:00
@Override
public void generate ( Region region , GenBase gen ) throws WorldEditException {
for ( BlockVector2 chunkPos : region . getChunks ( ) ) {
2021-07-16 09:44:52 +00:00
gen . generate ( chunkPos , new SingleRegionExtent ( this , getLimit ( ) , region ) ) ;
2021-07-16 09:43:15 +00:00
}
}
@Override
2021-07-24 15:34:05 +00:00
public void addSchems ( Region region , Mask mask , List < ClipboardHolder > clipboards , int rarity , boolean rotate ) throws
WorldEditException {
2021-07-16 09:43:15 +00:00
spawnResource ( region , new SchemGen ( mask , this , clipboards , rotate ) , rarity , 1 ) ;
}
@Override
2021-07-24 15:34:05 +00:00
public void addOre ( Region region , Mask mask , Pattern material , int size , int frequency , int rarity , int minY , int maxY ) throws
WorldEditException {
2021-07-16 09:43:15 +00:00
spawnResource ( region , new OreGen ( this , mask , material , size , minY , maxY ) , rarity , frequency ) ;
}
@Override
public Clipboard lazyCopy ( Region region ) {
WorldCopyClipboard faweClipboard = new WorldCopyClipboard ( ( ) - > this , region ) ;
faweClipboard . setOrigin ( region . getMinimumPoint ( ) ) ;
return faweClipboard ;
}
2021-09-18 16:42:58 +00:00
/ * *
* Makes a distorted sphere .
*
* @param position Center of blob
* @param pattern pattern to use
* @param size overall size of the blob
* @param frequency distortion amount ( 0 to 1 )
* @param amplitude distortion amplitude ( 0 to 1 )
* @param radius radii to multiply x / y / z by
* @param sphericity how spherical to make the blob . 1 = very spherical , 0 = not
* @return changes
* /
public int makeBlob (
BlockVector3 position , Pattern pattern , double size , double frequency , double amplitude , Vector3 radius ,
double sphericity
) {
double seedX = ThreadLocalRandom . current ( ) . nextDouble ( ) ;
double seedY = ThreadLocalRandom . current ( ) . nextDouble ( ) ;
double seedZ = ThreadLocalRandom . current ( ) . nextDouble ( ) ;
int px = position . getBlockX ( ) ;
int py = position . getBlockY ( ) ;
int pz = position . getBlockZ ( ) ;
double distort = frequency / size ;
double modX = 1d / radius . getX ( ) ;
double modY = 1d / radius . getY ( ) ;
double modZ = 1d / radius . getZ ( ) ;
int r = ( int ) size ;
int radiusSqr = ( int ) ( size * size ) ;
int sizeInt = ( int ) size * 2 ;
if ( sphericity = = 1 ) {
for ( int x = - sizeInt ; x < = sizeInt ; x + + ) {
double nx = seedX + x * distort ;
double d1 = x * x * modX ;
for ( int y = - sizeInt ; y < = sizeInt ; y + + ) {
double d2 = d1 + y * y * modY ;
double ny = seedY + y * distort ;
for ( int z = - sizeInt ; z < = sizeInt ; z + + ) {
double nz = seedZ + z * distort ;
double distance = d2 + z * z * modZ ;
double noise = amplitude * SimplexNoise . noise ( nx , ny , nz ) ;
if ( distance + distance * noise < radiusSqr ) {
setBlock ( px + x , py + y , pz + z , pattern ) ;
}
}
}
}
} else {
AffineTransform transform = new AffineTransform ( )
. rotateX ( ThreadLocalRandom . current ( ) . nextInt ( 360 ) )
. rotateY ( ThreadLocalRandom . current ( ) . nextInt ( 360 ) )
. rotateZ ( ThreadLocalRandom . current ( ) . nextInt ( 360 ) ) ;
double manScaleX = 1 . 25 + seedX * 0 . 5 ;
double manScaleY = 1 . 25 + seedY * 0 . 5 ;
double manScaleZ = 1 . 25 + seedZ * 0 . 5 ;
MutableVector3 mutable = new MutableVector3 ( ) ;
double roughness = 1 - sphericity ;
for ( int xr = - sizeInt ; xr < = sizeInt ; xr + + ) {
for ( int yr = - sizeInt ; yr < = sizeInt ; yr + + ) {
for ( int zr = - sizeInt ; zr < = sizeInt ; zr + + ) {
// pt == mutable as it's a MutableVector3
// so it must be set each time
mutable . mutX ( xr ) ;
mutable . mutY ( yr ) ;
mutable . mutZ ( zr ) ;
Vector3 pt = transform . apply ( mutable ) ;
int x = MathMan . roundInt ( pt . getX ( ) ) ;
int y = MathMan . roundInt ( pt . getY ( ) ) ;
int z = MathMan . roundInt ( pt . getZ ( ) ) ;
double xScaled = Math . abs ( x ) * modX ;
double yScaled = Math . abs ( y ) * modY ;
double zScaled = Math . abs ( z ) * modZ ;
double manDist = xScaled + yScaled + zScaled ;
double distSqr = x * x * modX + z * z * modZ + y * y * modY ;
double distance = Math . sqrt ( distSqr ) * sphericity + MathMan . max (
manDist ,
xScaled * manScaleX ,
yScaled * manScaleY ,
zScaled * manScaleZ
) * roughness ;
double noise = amplitude * SimplexNoise . noise (
seedX + x * distort ,
seedZ + z * distort ,
seedZ + z * distort
) ;
if ( distance + distance * noise < r ) {
setBlock ( px + xr , py + yr , pz + zr , pattern ) ;
}
}
}
}
}
return changes ;
}
2021-07-23 15:48:51 +00:00
//FAWE end
2010-10-02 21:52:42 +00:00
}