From f43faae91723187ef46533858fad0eb08cb4a028 Mon Sep 17 00:00:00 2001 From: Jesse Boyd Date: Thu, 23 Aug 2018 06:02:04 +1000 Subject: [PATCH] Update favs --- favs/build.gradle | 24 + .../boydti/fawe/bukkit/favs/PatternUtil.java | 30 + .../com/thevoxelbox/voxelsniper/Brushes.java | 92 ++ .../com/thevoxelbox/voxelsniper/Message.java | 169 +++ .../voxelsniper/PaintingWrapper.java | 102 ++ .../voxelsniper/RangeBlockHelper.java | 303 ++++++ .../thevoxelbox/voxelsniper/SnipeAction.java | 9 + .../thevoxelbox/voxelsniper/SnipeData.java | 328 ++++++ .../com/thevoxelbox/voxelsniper/Sniper.java | 679 ++++++++++++ .../voxelsniper/SniperManager.java | 30 + .../com/thevoxelbox/voxelsniper/Undo.java | 70 ++ .../thevoxelbox/voxelsniper/VoxelSniper.java | 227 ++++ .../voxelsniper/VoxelSniperConfiguration.java | 110 ++ .../voxelsniper/VoxelSniperListener.java | 138 +++ .../voxelsniper/api/command/VoxelCommand.java | 81 ++ .../voxelsniper/brush/BallBrush.java | 146 +++ .../voxelsniper/brush/BiomeBrush.java | 126 +++ .../voxelsniper/brush/BlendBallBrush.java | 162 +++ .../voxelsniper/brush/BlendBrushBase.java | 93 ++ .../voxelsniper/brush/BlendDiscBrush.java | 143 +++ .../voxelsniper/brush/BlendVoxelBrush.java | 155 +++ .../brush/BlendVoxelDiscBrush.java | 139 +++ .../voxelsniper/brush/BlobBrush.java | 313 ++++++ .../voxelsniper/brush/BlockResetBrush.java | 90 ++ .../brush/BlockResetSurfaceBrush.java | 154 +++ .../thevoxelbox/voxelsniper/brush/Brush.java | 311 ++++++ .../voxelsniper/brush/CanyonBrush.java | 146 +++ .../brush/CanyonSelectionBrush.java | 88 ++ .../brush/CheckerVoxelDiscBrush.java | 101 ++ .../voxelsniper/brush/CleanSnowBrush.java | 113 ++ .../voxelsniper/brush/CloneStampBrush.java | 172 +++ .../voxelsniper/brush/CometBrush.java | 108 ++ .../voxelsniper/brush/CopyPastaBrush.java | 222 ++++ .../voxelsniper/brush/CylinderBrush.java | 146 +++ .../voxelsniper/brush/DiscBrush.java | 108 ++ .../voxelsniper/brush/DiscFaceBrush.java | 181 ++++ .../voxelsniper/brush/DomeBrush.java | 119 +++ .../voxelsniper/brush/DrainBrush.java | 173 +++ .../voxelsniper/brush/EllipseBrush.java | 304 ++++++ .../voxelsniper/brush/EllipsoidBrush.java | 147 +++ .../voxelsniper/brush/EntityBrush.java | 98 ++ .../voxelsniper/brush/EntityRemovalBrush.java | 187 ++++ .../voxelsniper/brush/EraserBrush.java | 88 ++ .../voxelsniper/brush/ErodeBrush.java | 570 ++++++++++ .../voxelsniper/brush/ExtrudeBrush.java | 223 ++++ .../voxelsniper/brush/FillDownBrush.java | 149 +++ .../voxelsniper/brush/FlatOceanBrush.java | 128 +++ .../voxelsniper/brush/GenerateTreeBrush.java | 781 ++++++++++++++ .../voxelsniper/brush/HeatRayBrush.java | 226 ++++ .../thevoxelbox/voxelsniper/brush/IBrush.java | 53 + .../voxelsniper/brush/JaggedLineBrush.java | 157 +++ .../voxelsniper/brush/JockeyBrush.java | 278 +++++ .../voxelsniper/brush/LightningBrush.java | 43 + .../voxelsniper/brush/LineBrush.java | 103 ++ .../voxelsniper/brush/MoveBrush.java | 312 ++++++ .../voxelsniper/brush/OceanBrush.java | 191 ++++ .../voxelsniper/brush/OverlayBrush.java | 233 +++++ .../voxelsniper/brush/PaintingBrush.java | 56 + .../voxelsniper/brush/PullBrush.java | 371 +++++++ .../voxelsniper/brush/PunishBrush.java | 383 +++++++ .../voxelsniper/brush/RandomErodeBrush.java | 470 +++++++++ .../brush/RegenerateChunkBrush.java | 70 ++ .../voxelsniper/brush/RingBrush.java | 120 +++ .../voxelsniper/brush/Rot2DBrush.java | 214 ++++ .../voxelsniper/brush/Rot2DvertBrush.java | 223 ++++ .../voxelsniper/brush/Rot3DBrush.java | 286 +++++ .../voxelsniper/brush/RulerBrush.java | 129 +++ .../voxelsniper/brush/ScannerBrush.java | 200 ++++ .../voxelsniper/brush/SetBrush.java | 116 +++ .../brush/SetRedstoneFlipBrush.java | 160 +++ .../brush/SetRedstoneRotateBrush.java | 113 ++ .../voxelsniper/brush/ShellBallBrush.java | 161 +++ .../voxelsniper/brush/ShellSetBrush.java | 153 +++ .../voxelsniper/brush/ShellVoxelBrush.java | 163 +++ .../voxelsniper/brush/SignOverwriteBrush.java | 484 +++++++++ .../voxelsniper/brush/SnipeBrush.java | 47 + .../voxelsniper/brush/SnowConeBrush.java | 194 ++++ .../brush/SpiralStaircaseBrush.java | 830 +++++++++++++++ .../voxelsniper/brush/SplatterBallBrush.java | 284 +++++ .../voxelsniper/brush/SplatterDiscBrush.java | 253 +++++ .../brush/SplatterOverlayBrush.java | 453 ++++++++ .../voxelsniper/brush/SplatterVoxelBrush.java | 274 +++++ .../brush/SplatterVoxelDiscBrush.java | 250 +++++ .../voxelsniper/brush/SplineBrush.java | 313 ++++++ .../voxelsniper/brush/StampBrush.java | 348 +++++++ .../voxelsniper/brush/StencilBrush.java | 461 ++++++++ .../voxelsniper/brush/StencilListBrush.java | 984 ++++++++++++++++++ .../brush/ThreePointCircleBrush.java | 238 +++++ .../voxelsniper/brush/TreeSnipeBrush.java | 132 +++ .../voxelsniper/brush/TriangleBrush.java | 334 ++++++ .../voxelsniper/brush/UnderlayBrush.java | 198 ++++ .../voxelsniper/brush/VoltMeterBrush.java | 71 ++ .../voxelsniper/brush/VoxelBrush.java | 61 ++ .../voxelsniper/brush/VoxelDiscBrush.java | 60 ++ .../voxelsniper/brush/VoxelDiscFaceBrush.java | 115 ++ .../voxelsniper/brush/WarpBrush.java | 97 ++ .../brush/perform/PatternPerformer.java | 43 + .../brush/perform/PerformBrush.java | 100 ++ .../voxelsniper/brush/perform/Performer.java | 18 + .../voxelsniper/brush/perform/PerformerE.java | 179 ++++ .../voxelsniper/brush/perform/pCombo.java | 47 + .../brush/perform/pComboCombo.java | 62 ++ .../brush/perform/pComboComboNoPhys.java | 63 ++ .../voxelsniper/brush/perform/pComboInk.java | 59 ++ .../brush/perform/pComboInkNoPhys.java | 59 ++ .../voxelsniper/brush/perform/pComboMat.java | 59 ++ .../brush/perform/pComboMatNoPhys.java | 59 ++ .../brush/perform/pComboNoPhys.java | 47 + .../brush/perform/pComboNoUndo.java | 49 + .../brush/perform/pExcludeCombo.java | 54 + .../brush/perform/pExcludeInk.java | 51 + .../brush/perform/pExcludeMat.java | 53 + .../brush/perform/pIncludeCombo.java | 54 + .../brush/perform/pIncludeInk.java | 51 + .../brush/perform/pIncludeMat.java | 53 + .../voxelsniper/brush/perform/pInk.java | 44 + .../voxelsniper/brush/perform/pInkCombo.java | 59 ++ .../brush/perform/pInkComboNoPhys.java | 55 + .../voxelsniper/brush/perform/pInkInk.java | 56 + .../brush/perform/pInkInkNoPhys.java | 52 + .../voxelsniper/brush/perform/pInkMat.java | 56 + .../brush/perform/pInkMatNoPhys.java | 52 + .../voxelsniper/brush/perform/pInkNoPhys.java | 40 + .../voxelsniper/brush/perform/pInkNoUndo.java | 46 + .../voxelsniper/brush/perform/pMatCombo.java | 61 ++ .../brush/perform/pMatComboNophys.java | 61 ++ .../voxelsniper/brush/perform/pMatInk.java | 58 ++ .../brush/perform/pMatInkNoPhys.java | 58 ++ .../voxelsniper/brush/perform/pMatMat.java | 58 ++ .../brush/perform/pMatMatNoPhys.java | 58 ++ .../voxelsniper/brush/perform/pMaterial.java | 49 + .../brush/perform/pMaterialNoPhys.java | 48 + .../voxelsniper/brush/perform/pNoUndo.java | 48 + .../voxelsniper/brush/perform/vPerformer.java | 45 + .../command/VoxelBrushCommand.java | 93 ++ .../command/VoxelBrushToolCommand.java | 91 ++ .../command/VoxelCenterCommand.java | 38 + .../command/VoxelChunkCommand.java | 21 + .../command/VoxelDefaultCommand.java | 27 + .../voxelsniper/command/VoxelGoToCommand.java | 35 + .../command/VoxelHeightCommand.java | 38 + .../voxelsniper/command/VoxelInkCommand.java | 64 ++ .../command/VoxelInkReplaceCommand.java | 64 ++ .../voxelsniper/command/VoxelListCommand.java | 74 ++ .../command/VoxelPaintCommand.java | 48 + .../command/VoxelPerformerCommand.java | 62 ++ .../command/VoxelReplaceCommand.java | 51 + .../command/VoxelSniperCommand.java | 111 ++ .../voxelsniper/command/VoxelUndoCommand.java | 41 + .../command/VoxelUndoUserCommand.java | 32 + .../command/VoxelVoxelCommand.java | 89 ++ .../event/SniperBrushChangedEvent.java | 75 ++ .../event/SniperBrushSizeChangedEvent.java | 57 + .../event/SniperMaterialChangedEvent.java | 77 ++ .../SniperReplaceMaterialChangedEvent.java | 30 + .../voxelsniper/jsap/HelpJSAP.java | 205 ++++ .../jsap/NullableIntegerStringParser.java | 75 ++ .../voxelsniper/util/BlockWrapper.java | 134 +++ .../voxelsniper/util/UndoDelegate.java | 61 ++ .../voxelsniper/util/VoxelList.java | 95 ++ favs/src/main/resources/LICENSE | 53 + favs/src/main/resources/config.yml | 3 + favs/src/main/resources/plugin.yml | 437 ++++++++ settings.gradle | 2 +- .../fawe/bukkit/v0/BukkitQueue_All.java | 3 +- .../fawe/bukkit/wrapper/AsyncBlock.java | 51 +- .../fawe/bukkit/wrapper/AsyncBlockState.java | 12 +- .../fawe/bukkit/wrapper/AsyncChunk.java | 4 +- .../fawe/bukkit/wrapper/AsyncWorld.java | 14 +- .../worldedit/bukkit/CachedBukkitAdapter.java | 1 + .../boydti/fawe/example/MappedFaweQueue.java | 14 +- .../fawe/example/NMSMappedFaweQueue.java | 4 +- .../boydti/fawe/example/NullFaweChunk.java | 4 +- .../com/boydti/fawe/object/FaweQueue.java | 3 +- .../object/queue/FaweQueueDelegateExtent.java | 101 ++ .../worldedit/function/mask/BlockMask.java | 34 + .../function/mask/BlockMaskBuilder.java | 2 +- .../worldedit/world/block/BlockTypes.java | 18 + 178 files changed, 24721 insertions(+), 32 deletions(-) create mode 100644 favs/build.gradle create mode 100644 favs/src/main/java/com/boydti/fawe/bukkit/favs/PatternUtil.java create mode 100644 favs/src/main/java/com/thevoxelbox/voxelsniper/Brushes.java create mode 100644 favs/src/main/java/com/thevoxelbox/voxelsniper/Message.java create mode 100644 favs/src/main/java/com/thevoxelbox/voxelsniper/PaintingWrapper.java create mode 100644 favs/src/main/java/com/thevoxelbox/voxelsniper/RangeBlockHelper.java create mode 100644 favs/src/main/java/com/thevoxelbox/voxelsniper/SnipeAction.java create mode 100644 favs/src/main/java/com/thevoxelbox/voxelsniper/SnipeData.java create mode 100644 favs/src/main/java/com/thevoxelbox/voxelsniper/Sniper.java create mode 100644 favs/src/main/java/com/thevoxelbox/voxelsniper/SniperManager.java create mode 100644 favs/src/main/java/com/thevoxelbox/voxelsniper/Undo.java create mode 100644 favs/src/main/java/com/thevoxelbox/voxelsniper/VoxelSniper.java create mode 100644 favs/src/main/java/com/thevoxelbox/voxelsniper/VoxelSniperConfiguration.java create mode 100644 favs/src/main/java/com/thevoxelbox/voxelsniper/VoxelSniperListener.java create mode 100644 favs/src/main/java/com/thevoxelbox/voxelsniper/api/command/VoxelCommand.java create mode 100644 favs/src/main/java/com/thevoxelbox/voxelsniper/brush/BallBrush.java create mode 100644 favs/src/main/java/com/thevoxelbox/voxelsniper/brush/BiomeBrush.java create mode 100644 favs/src/main/java/com/thevoxelbox/voxelsniper/brush/BlendBallBrush.java create mode 100644 favs/src/main/java/com/thevoxelbox/voxelsniper/brush/BlendBrushBase.java create mode 100644 favs/src/main/java/com/thevoxelbox/voxelsniper/brush/BlendDiscBrush.java create mode 100644 favs/src/main/java/com/thevoxelbox/voxelsniper/brush/BlendVoxelBrush.java create mode 100644 favs/src/main/java/com/thevoxelbox/voxelsniper/brush/BlendVoxelDiscBrush.java create mode 100644 favs/src/main/java/com/thevoxelbox/voxelsniper/brush/BlobBrush.java create mode 100644 favs/src/main/java/com/thevoxelbox/voxelsniper/brush/BlockResetBrush.java create mode 100644 favs/src/main/java/com/thevoxelbox/voxelsniper/brush/BlockResetSurfaceBrush.java create mode 100644 favs/src/main/java/com/thevoxelbox/voxelsniper/brush/Brush.java create mode 100644 favs/src/main/java/com/thevoxelbox/voxelsniper/brush/CanyonBrush.java create mode 100644 favs/src/main/java/com/thevoxelbox/voxelsniper/brush/CanyonSelectionBrush.java create mode 100644 favs/src/main/java/com/thevoxelbox/voxelsniper/brush/CheckerVoxelDiscBrush.java create mode 100644 favs/src/main/java/com/thevoxelbox/voxelsniper/brush/CleanSnowBrush.java create mode 100644 favs/src/main/java/com/thevoxelbox/voxelsniper/brush/CloneStampBrush.java create mode 100644 favs/src/main/java/com/thevoxelbox/voxelsniper/brush/CometBrush.java create mode 100644 favs/src/main/java/com/thevoxelbox/voxelsniper/brush/CopyPastaBrush.java create mode 100644 favs/src/main/java/com/thevoxelbox/voxelsniper/brush/CylinderBrush.java create mode 100644 favs/src/main/java/com/thevoxelbox/voxelsniper/brush/DiscBrush.java create mode 100644 favs/src/main/java/com/thevoxelbox/voxelsniper/brush/DiscFaceBrush.java create mode 100644 favs/src/main/java/com/thevoxelbox/voxelsniper/brush/DomeBrush.java create mode 100644 favs/src/main/java/com/thevoxelbox/voxelsniper/brush/DrainBrush.java create mode 100644 favs/src/main/java/com/thevoxelbox/voxelsniper/brush/EllipseBrush.java create mode 100644 favs/src/main/java/com/thevoxelbox/voxelsniper/brush/EllipsoidBrush.java create mode 100644 favs/src/main/java/com/thevoxelbox/voxelsniper/brush/EntityBrush.java create mode 100644 favs/src/main/java/com/thevoxelbox/voxelsniper/brush/EntityRemovalBrush.java create mode 100644 favs/src/main/java/com/thevoxelbox/voxelsniper/brush/EraserBrush.java create mode 100644 favs/src/main/java/com/thevoxelbox/voxelsniper/brush/ErodeBrush.java create mode 100644 favs/src/main/java/com/thevoxelbox/voxelsniper/brush/ExtrudeBrush.java create mode 100644 favs/src/main/java/com/thevoxelbox/voxelsniper/brush/FillDownBrush.java create mode 100644 favs/src/main/java/com/thevoxelbox/voxelsniper/brush/FlatOceanBrush.java create mode 100644 favs/src/main/java/com/thevoxelbox/voxelsniper/brush/GenerateTreeBrush.java create mode 100644 favs/src/main/java/com/thevoxelbox/voxelsniper/brush/HeatRayBrush.java create mode 100644 favs/src/main/java/com/thevoxelbox/voxelsniper/brush/IBrush.java create mode 100644 favs/src/main/java/com/thevoxelbox/voxelsniper/brush/JaggedLineBrush.java create mode 100644 favs/src/main/java/com/thevoxelbox/voxelsniper/brush/JockeyBrush.java create mode 100644 favs/src/main/java/com/thevoxelbox/voxelsniper/brush/LightningBrush.java create mode 100644 favs/src/main/java/com/thevoxelbox/voxelsniper/brush/LineBrush.java create mode 100644 favs/src/main/java/com/thevoxelbox/voxelsniper/brush/MoveBrush.java create mode 100644 favs/src/main/java/com/thevoxelbox/voxelsniper/brush/OceanBrush.java create mode 100644 favs/src/main/java/com/thevoxelbox/voxelsniper/brush/OverlayBrush.java create mode 100644 favs/src/main/java/com/thevoxelbox/voxelsniper/brush/PaintingBrush.java create mode 100644 favs/src/main/java/com/thevoxelbox/voxelsniper/brush/PullBrush.java create mode 100644 favs/src/main/java/com/thevoxelbox/voxelsniper/brush/PunishBrush.java create mode 100644 favs/src/main/java/com/thevoxelbox/voxelsniper/brush/RandomErodeBrush.java create mode 100644 favs/src/main/java/com/thevoxelbox/voxelsniper/brush/RegenerateChunkBrush.java create mode 100644 favs/src/main/java/com/thevoxelbox/voxelsniper/brush/RingBrush.java create mode 100644 favs/src/main/java/com/thevoxelbox/voxelsniper/brush/Rot2DBrush.java create mode 100644 favs/src/main/java/com/thevoxelbox/voxelsniper/brush/Rot2DvertBrush.java create mode 100644 favs/src/main/java/com/thevoxelbox/voxelsniper/brush/Rot3DBrush.java create mode 100644 favs/src/main/java/com/thevoxelbox/voxelsniper/brush/RulerBrush.java create mode 100644 favs/src/main/java/com/thevoxelbox/voxelsniper/brush/ScannerBrush.java create mode 100644 favs/src/main/java/com/thevoxelbox/voxelsniper/brush/SetBrush.java create mode 100644 favs/src/main/java/com/thevoxelbox/voxelsniper/brush/SetRedstoneFlipBrush.java create mode 100644 favs/src/main/java/com/thevoxelbox/voxelsniper/brush/SetRedstoneRotateBrush.java create mode 100644 favs/src/main/java/com/thevoxelbox/voxelsniper/brush/ShellBallBrush.java create mode 100644 favs/src/main/java/com/thevoxelbox/voxelsniper/brush/ShellSetBrush.java create mode 100644 favs/src/main/java/com/thevoxelbox/voxelsniper/brush/ShellVoxelBrush.java create mode 100644 favs/src/main/java/com/thevoxelbox/voxelsniper/brush/SignOverwriteBrush.java create mode 100644 favs/src/main/java/com/thevoxelbox/voxelsniper/brush/SnipeBrush.java create mode 100644 favs/src/main/java/com/thevoxelbox/voxelsniper/brush/SnowConeBrush.java create mode 100644 favs/src/main/java/com/thevoxelbox/voxelsniper/brush/SpiralStaircaseBrush.java create mode 100644 favs/src/main/java/com/thevoxelbox/voxelsniper/brush/SplatterBallBrush.java create mode 100644 favs/src/main/java/com/thevoxelbox/voxelsniper/brush/SplatterDiscBrush.java create mode 100644 favs/src/main/java/com/thevoxelbox/voxelsniper/brush/SplatterOverlayBrush.java create mode 100644 favs/src/main/java/com/thevoxelbox/voxelsniper/brush/SplatterVoxelBrush.java create mode 100644 favs/src/main/java/com/thevoxelbox/voxelsniper/brush/SplatterVoxelDiscBrush.java create mode 100644 favs/src/main/java/com/thevoxelbox/voxelsniper/brush/SplineBrush.java create mode 100644 favs/src/main/java/com/thevoxelbox/voxelsniper/brush/StampBrush.java create mode 100644 favs/src/main/java/com/thevoxelbox/voxelsniper/brush/StencilBrush.java create mode 100644 favs/src/main/java/com/thevoxelbox/voxelsniper/brush/StencilListBrush.java create mode 100644 favs/src/main/java/com/thevoxelbox/voxelsniper/brush/ThreePointCircleBrush.java create mode 100644 favs/src/main/java/com/thevoxelbox/voxelsniper/brush/TreeSnipeBrush.java create mode 100644 favs/src/main/java/com/thevoxelbox/voxelsniper/brush/TriangleBrush.java create mode 100644 favs/src/main/java/com/thevoxelbox/voxelsniper/brush/UnderlayBrush.java create mode 100644 favs/src/main/java/com/thevoxelbox/voxelsniper/brush/VoltMeterBrush.java create mode 100644 favs/src/main/java/com/thevoxelbox/voxelsniper/brush/VoxelBrush.java create mode 100644 favs/src/main/java/com/thevoxelbox/voxelsniper/brush/VoxelDiscBrush.java create mode 100644 favs/src/main/java/com/thevoxelbox/voxelsniper/brush/VoxelDiscFaceBrush.java create mode 100644 favs/src/main/java/com/thevoxelbox/voxelsniper/brush/WarpBrush.java create mode 100644 favs/src/main/java/com/thevoxelbox/voxelsniper/brush/perform/PatternPerformer.java create mode 100644 favs/src/main/java/com/thevoxelbox/voxelsniper/brush/perform/PerformBrush.java create mode 100644 favs/src/main/java/com/thevoxelbox/voxelsniper/brush/perform/Performer.java create mode 100644 favs/src/main/java/com/thevoxelbox/voxelsniper/brush/perform/PerformerE.java create mode 100644 favs/src/main/java/com/thevoxelbox/voxelsniper/brush/perform/pCombo.java create mode 100644 favs/src/main/java/com/thevoxelbox/voxelsniper/brush/perform/pComboCombo.java create mode 100644 favs/src/main/java/com/thevoxelbox/voxelsniper/brush/perform/pComboComboNoPhys.java create mode 100644 favs/src/main/java/com/thevoxelbox/voxelsniper/brush/perform/pComboInk.java create mode 100644 favs/src/main/java/com/thevoxelbox/voxelsniper/brush/perform/pComboInkNoPhys.java create mode 100644 favs/src/main/java/com/thevoxelbox/voxelsniper/brush/perform/pComboMat.java create mode 100644 favs/src/main/java/com/thevoxelbox/voxelsniper/brush/perform/pComboMatNoPhys.java create mode 100644 favs/src/main/java/com/thevoxelbox/voxelsniper/brush/perform/pComboNoPhys.java create mode 100644 favs/src/main/java/com/thevoxelbox/voxelsniper/brush/perform/pComboNoUndo.java create mode 100644 favs/src/main/java/com/thevoxelbox/voxelsniper/brush/perform/pExcludeCombo.java create mode 100644 favs/src/main/java/com/thevoxelbox/voxelsniper/brush/perform/pExcludeInk.java create mode 100644 favs/src/main/java/com/thevoxelbox/voxelsniper/brush/perform/pExcludeMat.java create mode 100644 favs/src/main/java/com/thevoxelbox/voxelsniper/brush/perform/pIncludeCombo.java create mode 100644 favs/src/main/java/com/thevoxelbox/voxelsniper/brush/perform/pIncludeInk.java create mode 100644 favs/src/main/java/com/thevoxelbox/voxelsniper/brush/perform/pIncludeMat.java create mode 100644 favs/src/main/java/com/thevoxelbox/voxelsniper/brush/perform/pInk.java create mode 100644 favs/src/main/java/com/thevoxelbox/voxelsniper/brush/perform/pInkCombo.java create mode 100644 favs/src/main/java/com/thevoxelbox/voxelsniper/brush/perform/pInkComboNoPhys.java create mode 100644 favs/src/main/java/com/thevoxelbox/voxelsniper/brush/perform/pInkInk.java create mode 100644 favs/src/main/java/com/thevoxelbox/voxelsniper/brush/perform/pInkInkNoPhys.java create mode 100644 favs/src/main/java/com/thevoxelbox/voxelsniper/brush/perform/pInkMat.java create mode 100644 favs/src/main/java/com/thevoxelbox/voxelsniper/brush/perform/pInkMatNoPhys.java create mode 100644 favs/src/main/java/com/thevoxelbox/voxelsniper/brush/perform/pInkNoPhys.java create mode 100644 favs/src/main/java/com/thevoxelbox/voxelsniper/brush/perform/pInkNoUndo.java create mode 100644 favs/src/main/java/com/thevoxelbox/voxelsniper/brush/perform/pMatCombo.java create mode 100644 favs/src/main/java/com/thevoxelbox/voxelsniper/brush/perform/pMatComboNophys.java create mode 100644 favs/src/main/java/com/thevoxelbox/voxelsniper/brush/perform/pMatInk.java create mode 100644 favs/src/main/java/com/thevoxelbox/voxelsniper/brush/perform/pMatInkNoPhys.java create mode 100644 favs/src/main/java/com/thevoxelbox/voxelsniper/brush/perform/pMatMat.java create mode 100644 favs/src/main/java/com/thevoxelbox/voxelsniper/brush/perform/pMatMatNoPhys.java create mode 100644 favs/src/main/java/com/thevoxelbox/voxelsniper/brush/perform/pMaterial.java create mode 100644 favs/src/main/java/com/thevoxelbox/voxelsniper/brush/perform/pMaterialNoPhys.java create mode 100644 favs/src/main/java/com/thevoxelbox/voxelsniper/brush/perform/pNoUndo.java create mode 100644 favs/src/main/java/com/thevoxelbox/voxelsniper/brush/perform/vPerformer.java create mode 100644 favs/src/main/java/com/thevoxelbox/voxelsniper/command/VoxelBrushCommand.java create mode 100644 favs/src/main/java/com/thevoxelbox/voxelsniper/command/VoxelBrushToolCommand.java create mode 100644 favs/src/main/java/com/thevoxelbox/voxelsniper/command/VoxelCenterCommand.java create mode 100644 favs/src/main/java/com/thevoxelbox/voxelsniper/command/VoxelChunkCommand.java create mode 100644 favs/src/main/java/com/thevoxelbox/voxelsniper/command/VoxelDefaultCommand.java create mode 100644 favs/src/main/java/com/thevoxelbox/voxelsniper/command/VoxelGoToCommand.java create mode 100644 favs/src/main/java/com/thevoxelbox/voxelsniper/command/VoxelHeightCommand.java create mode 100644 favs/src/main/java/com/thevoxelbox/voxelsniper/command/VoxelInkCommand.java create mode 100644 favs/src/main/java/com/thevoxelbox/voxelsniper/command/VoxelInkReplaceCommand.java create mode 100644 favs/src/main/java/com/thevoxelbox/voxelsniper/command/VoxelListCommand.java create mode 100644 favs/src/main/java/com/thevoxelbox/voxelsniper/command/VoxelPaintCommand.java create mode 100644 favs/src/main/java/com/thevoxelbox/voxelsniper/command/VoxelPerformerCommand.java create mode 100644 favs/src/main/java/com/thevoxelbox/voxelsniper/command/VoxelReplaceCommand.java create mode 100644 favs/src/main/java/com/thevoxelbox/voxelsniper/command/VoxelSniperCommand.java create mode 100644 favs/src/main/java/com/thevoxelbox/voxelsniper/command/VoxelUndoCommand.java create mode 100644 favs/src/main/java/com/thevoxelbox/voxelsniper/command/VoxelUndoUserCommand.java create mode 100644 favs/src/main/java/com/thevoxelbox/voxelsniper/command/VoxelVoxelCommand.java create mode 100644 favs/src/main/java/com/thevoxelbox/voxelsniper/event/SniperBrushChangedEvent.java create mode 100644 favs/src/main/java/com/thevoxelbox/voxelsniper/event/SniperBrushSizeChangedEvent.java create mode 100644 favs/src/main/java/com/thevoxelbox/voxelsniper/event/SniperMaterialChangedEvent.java create mode 100644 favs/src/main/java/com/thevoxelbox/voxelsniper/event/SniperReplaceMaterialChangedEvent.java create mode 100644 favs/src/main/java/com/thevoxelbox/voxelsniper/jsap/HelpJSAP.java create mode 100644 favs/src/main/java/com/thevoxelbox/voxelsniper/jsap/NullableIntegerStringParser.java create mode 100644 favs/src/main/java/com/thevoxelbox/voxelsniper/util/BlockWrapper.java create mode 100644 favs/src/main/java/com/thevoxelbox/voxelsniper/util/UndoDelegate.java create mode 100644 favs/src/main/java/com/thevoxelbox/voxelsniper/util/VoxelList.java create mode 100644 favs/src/main/resources/LICENSE create mode 100644 favs/src/main/resources/config.yml create mode 100644 favs/src/main/resources/plugin.yml create mode 100644 worldedit-core/src/main/java/com/boydti/fawe/object/queue/FaweQueueDelegateExtent.java diff --git a/favs/build.gradle b/favs/build.gradle new file mode 100644 index 000000000..4c126f5a5 --- /dev/null +++ b/favs/build.gradle @@ -0,0 +1,24 @@ +repositories { + maven {url "http://vault.voxelmodpack.com/content/repositories/central/"} +} + +dependencies { + compile project(':worldedit-bukkit') + compile 'com.martiansoftware:jsap:2.1' +} + +processResources { + from('src/main/resources') { + include 'plugin.yml' + expand( + name: project.parent.name, + version: project.parent.version + ) + } +} + +jar.destinationDir = file '../target' +jar.archiveName = "FastAsyncVoxelSniper-${project.name}-${parent.version}.jar" +jar.doLast { task -> + ant.checksum file: task.archivePath +} \ No newline at end of file diff --git a/favs/src/main/java/com/boydti/fawe/bukkit/favs/PatternUtil.java b/favs/src/main/java/com/boydti/fawe/bukkit/favs/PatternUtil.java new file mode 100644 index 000000000..81d4e6f9f --- /dev/null +++ b/favs/src/main/java/com/boydti/fawe/bukkit/favs/PatternUtil.java @@ -0,0 +1,30 @@ +package com.boydti.fawe.bukkit.favs; + +import com.boydti.fawe.config.BBC; +import com.boydti.fawe.object.FawePlayer; +import com.sk89q.worldedit.WorldEdit; +import com.sk89q.worldedit.extension.input.InputParseException; +import com.sk89q.worldedit.extension.input.ParserContext; +import com.sk89q.worldedit.function.pattern.Pattern; +import com.thevoxelbox.voxelsniper.SnipeData; +import org.bukkit.ChatColor; +import org.bukkit.entity.Player; + +public class PatternUtil { + public static Pattern parsePattern(Player player, SnipeData snipeData, String arg) { + ParserContext context = new ParserContext(); + FawePlayer fp = FawePlayer.wrap(player); + context.setActor(fp.getPlayer()); + context.setWorld(fp.getWorld()); + context.setSession(fp.getSession()); + try { + Pattern pattern = WorldEdit.getInstance().getPatternFactory().parseFromInput(arg, context); + snipeData.setPattern(pattern, arg); + snipeData.sendMessage(ChatColor.GOLD + "Voxel: " + ChatColor.RED + arg); + return pattern; + } catch (InputParseException e) { + fp.sendMessage(BBC.getPrefix() + e.getMessage()); + return null; + } + } +} diff --git a/favs/src/main/java/com/thevoxelbox/voxelsniper/Brushes.java b/favs/src/main/java/com/thevoxelbox/voxelsniper/Brushes.java new file mode 100644 index 000000000..77fcc072b --- /dev/null +++ b/favs/src/main/java/com/thevoxelbox/voxelsniper/Brushes.java @@ -0,0 +1,92 @@ +package com.thevoxelbox.voxelsniper; + +import com.google.common.base.Preconditions; +import com.google.common.collect.HashMultimap; +import com.google.common.collect.ImmutableMultimap; +import com.google.common.collect.Multimap; +import com.thevoxelbox.voxelsniper.brush.IBrush; + +import java.util.HashSet; +import java.util.Map; +import java.util.Set; + +/** + * Brush registration manager. + */ +public class Brushes +{ + private Multimap, String> brushes = HashMultimap.create(); + + /** + * Register a brush for VoxelSniper to be able to use. + * + * @param clazz Brush implementing IBrush interface. + * @param handles Handles under which the brush can be accessed ingame. + */ + public void registerSniperBrush(Class clazz, String... handles) + { + Preconditions.checkNotNull(clazz, "Cannot register null as a class."); + for (String handle : handles) + { + brushes.put(clazz, handle.toLowerCase()); + } + } + + /** + * Retrieve Brush class via handle Lookup. + * + * @param handle Case insensitive brush handle + * @return Brush class + */ + public Class getBrushForHandle(String handle) + { + Preconditions.checkNotNull(handle, "Brushhandle can not be null."); + if (!brushes.containsValue(handle.toLowerCase())) + { + return null; + } + + for (Map.Entry, String> entry : brushes.entries()) + { + if (entry.getValue().equalsIgnoreCase(handle)) + { + return entry.getKey(); + } + } + return null; + } + + /** + * @return Amount of IBrush classes registered with the system under Sniper visibility. + */ + public int registeredSniperBrushes() + { + return brushes.keySet().size(); + } + + /** + * @return Amount of handles registered with the system under Sniper visibility. + */ + public int registeredSniperBrushHandles() + { + return brushes.size(); + } + + /** + * + * @param clazz Brush class + * @return All Sniper registered handles for the brush. + */ + public Set getSniperBrushHandles(Class clazz) + { + return new HashSet(brushes.get(clazz)); + } + + /** + * @return Immutable Multimap copy of all the registered brushes + */ + public Multimap, String> getRegisteredBrushesMultimap() + { + return ImmutableMultimap.copyOf(brushes); + } +} diff --git a/favs/src/main/java/com/thevoxelbox/voxelsniper/Message.java b/favs/src/main/java/com/thevoxelbox/voxelsniper/Message.java new file mode 100644 index 000000000..193420707 --- /dev/null +++ b/favs/src/main/java/com/thevoxelbox/voxelsniper/Message.java @@ -0,0 +1,169 @@ +package com.thevoxelbox.voxelsniper; + +import com.sk89q.worldedit.world.block.BlockState; +import com.sk89q.worldedit.world.block.BlockTypes; +import org.bukkit.ChatColor; +import org.bukkit.Material; + +/** + * + */ +public class Message +{ + private static final int BRUSH_SIZE_WARNING_THRESHOLD = 20; + private final SnipeData snipeData; + + /** + * @param snipeData + */ + public Message(SnipeData snipeData) + { + this.snipeData = snipeData; + } + + /** + * Send a brush message styled message to the player. + * + * @param brushMessage + */ + public void brushMessage(String brushMessage) + { + snipeData.sendMessage(ChatColor.LIGHT_PURPLE + brushMessage); + } + + /** + * Display Brush Name. + * + * @param brushName + */ + public void brushName(String brushName) + { + snipeData.sendMessage(ChatColor.AQUA + "Brush Type: " + ChatColor.LIGHT_PURPLE + brushName); + } + + /** + * Display Center Parameter. + */ + public void center() + { + snipeData.sendMessage(ChatColor.DARK_BLUE + "Brush Center: " + ChatColor.DARK_RED + snipeData.getcCen()); + } + + /** + * Display custom message. + * + * @param message + */ + public void custom(String message) + { + snipeData.sendMessage(message); + } + + /** + * Display data value. + */ + public void data() + { + snipeData.sendMessage(ChatColor.BLUE + "Data Variable: " + ChatColor.DARK_RED + snipeData.getPropertyId()); + } + + /** + * Display voxel height. + */ + public void height() + { + snipeData.sendMessage(ChatColor.DARK_AQUA + "Brush Height: " + ChatColor.DARK_RED + snipeData.getVoxelHeight()); + } + + /** + * Display performer. + * + * @param performerName + */ + public void performerName(String performerName) + { + this.snipeData.sendMessage(ChatColor.DARK_PURPLE + "Performer: " + ChatColor.DARK_GREEN + performerName); + } + + /** + * Displaye replace material. + */ + @SuppressWarnings("deprecation") + public void replace() + { + snipeData.sendMessage(ChatColor.AQUA + "Replace Material: " + ChatColor.RED + snipeData.getReplaceId() + ChatColor.GRAY + " (" + BlockTypes.get(snipeData.getReplaceId()).toString() + ")"); + } + + /** + * Display replace data value. + */ + public void replaceData() + { + snipeData.sendMessage(ChatColor.DARK_GRAY + "Replace Data Variable: " + ChatColor.DARK_RED + snipeData.getReplaceData()); + } + + /** + * Display brush size. + */ + public void size() + { + snipeData.sendMessage(ChatColor.GREEN + "Brush Size: " + ChatColor.DARK_RED + snipeData.getBrushSize()); + if (snipeData.getBrushSize() >= BRUSH_SIZE_WARNING_THRESHOLD) + { + snipeData.sendMessage(ChatColor.RED + "WARNING: Large brush size selected!"); + } + } + + /** + * Display toggle lightning message. + */ + public void toggleLightning() + { + snipeData.sendMessage(ChatColor.GOLD + "Lightning mode has been toggled " + ChatColor.DARK_RED + ((snipeData.owner().getSnipeData(snipeData.owner().getCurrentToolId()).isLightningEnabled()) ? "on" : "off")); + } + + /** + * Display toggle printout message. + */ + public final void togglePrintout() + { + snipeData.sendMessage(ChatColor.GOLD + "Brush info printout mode has been toggled " + ChatColor.DARK_RED + ((snipeData.owner().getSnipeData(snipeData.owner().getCurrentToolId()).isLightningEnabled()) ? "on" : "off")); + } + + /** + * Display toggle range message. + */ + public void toggleRange() + { + snipeData.sendMessage(ChatColor.GOLD + "Distance Restriction toggled " + ChatColor.DARK_RED + ((snipeData.owner().getSnipeData(snipeData.owner().getCurrentToolId()).isRanged()) ? "on" : "off") + ChatColor.GOLD + ". Range is " + ChatColor.LIGHT_PURPLE + (double) snipeData.owner().getSnipeData(snipeData.owner().getCurrentToolId()).getRange()); + } + + /** + * Display voxel type. + */ + @SuppressWarnings("deprecation") + public void voxel() + { + snipeData.sendMessage(ChatColor.GOLD + "Voxel: " + ChatColor.RED + snipeData.getVoxelId() + ChatColor.GRAY + " (" + BlockTypes.get(snipeData.getVoxelId()).toString() + ")"); + } + + /** + * Display voxel list. + */ + public void voxelList() + { + if (snipeData.getVoxelList().isEmpty()) + { + snipeData.sendMessage(ChatColor.DARK_GREEN + "No blocks selected!"); + } + else + { + StringBuilder returnValueBuilder = new StringBuilder(); + returnValueBuilder.append(ChatColor.DARK_GREEN); + returnValueBuilder.append("Block Types Selected: "); + returnValueBuilder.append(ChatColor.AQUA); + returnValueBuilder.append(snipeData.getVoxelList()); + snipeData.sendMessage(returnValueBuilder.toString()); + } + } +} diff --git a/favs/src/main/java/com/thevoxelbox/voxelsniper/PaintingWrapper.java b/favs/src/main/java/com/thevoxelbox/voxelsniper/PaintingWrapper.java new file mode 100644 index 000000000..25df54ee1 --- /dev/null +++ b/favs/src/main/java/com/thevoxelbox/voxelsniper/PaintingWrapper.java @@ -0,0 +1,102 @@ +package com.thevoxelbox.voxelsniper; + +import org.bukkit.Art; +import org.bukkit.ChatColor; +import org.bukkit.Chunk; +import org.bukkit.Location; +import org.bukkit.Material; +import org.bukkit.entity.Entity; +import org.bukkit.entity.EntityType; +import org.bukkit.entity.Painting; +import org.bukkit.entity.Player; + +import java.util.Set; + +/** + * Painting state change handler. + * + * @author Piotr + */ +public final class PaintingWrapper +{ + + private PaintingWrapper() + { + } + + + /** + * The paint method used to scroll or set a painting to a specific type. + * + * @param p + * The player executing the method + * @param auto + * Scroll automatically? If false will use 'choice' to try and set the painting + * @param back + * Scroll in reverse? + * @param choice + * Chosen index to set the painting to + */ + @SuppressWarnings("deprecation") + public static void paint(final Player p, final boolean auto, final boolean back, final int choice) + { + Location targetLocation = p.getTargetBlock((Set) null, 4).getLocation(); + Chunk paintingChunk = p.getTargetBlock((Set) null, 4).getLocation().getChunk(); + + Double bestDistanceMatch = 50D; + Painting bestMatch = null; + + for (Entity entity : paintingChunk.getEntities()) + { + if (entity.getType() == EntityType.PAINTING) + { + Double distance = targetLocation.distanceSquared(entity.getLocation()); + + if (distance <= 4 && distance < bestDistanceMatch) + { + bestDistanceMatch = distance; + bestMatch = (Painting) entity; + } + } + } + + if (bestMatch != null) + { + if (auto) + { + try + { + final int i = bestMatch.getArt().getId() + (back ? -1 : 1) + Art.values().length % Art.values().length; + Art art = Art.getById(i); + + if (art == null) + { + p.sendMessage(ChatColor.RED + "This is the final painting, try scrolling to the other direction."); + return; + } + + bestMatch.setArt(art); + p.sendMessage(ChatColor.GREEN + "Painting set to ID: " + (i)); + } + catch (final Exception e) + { + p.sendMessage(ChatColor.RED + "Oops. Something went wrong."); + } + } + else + { + try + { + Art art = Art.getById(choice); + + bestMatch.setArt(art); + p.sendMessage(ChatColor.GREEN + "Painting set to ID: " + choice); + } + catch (final Exception exception) + { + p.sendMessage(ChatColor.RED + "Your input was invalid somewhere."); + } + } + } + } +} diff --git a/favs/src/main/java/com/thevoxelbox/voxelsniper/RangeBlockHelper.java b/favs/src/main/java/com/thevoxelbox/voxelsniper/RangeBlockHelper.java new file mode 100644 index 000000000..2d4a6d011 --- /dev/null +++ b/favs/src/main/java/com/thevoxelbox/voxelsniper/RangeBlockHelper.java @@ -0,0 +1,303 @@ +/** + This file is part of VoxelSniper, licensed under the MIT License (MIT). + + Copyright (c) The VoxelBox + Copyright (c) contributors + + Permission is hereby granted, free of charge, to any person obtaining a copy + of this software and associated documentation files (the "Software"), to deal + in the Software without restriction, including without limitation the rights + to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + copies of the Software, and to permit persons to whom the Software is + furnished to do so, subject to the following conditions: + + The above copyright notice and this permission notice shall be included in + all copies or substantial portions of the Software. + + THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + THE SOFTWARE. + */ +package com.thevoxelbox.voxelsniper; + +import com.boydti.fawe.bukkit.wrapper.AsyncBlock; +import com.boydti.fawe.bukkit.wrapper.AsyncWorld; +import com.sk89q.worldedit.bukkit.BukkitAdapter; +import com.sk89q.worldedit.world.registry.LegacyMapper; +import org.bukkit.Location; +import org.bukkit.Material; +import org.bukkit.World; +import org.bukkit.block.Block; +import org.bukkit.entity.Player; + +public class RangeBlockHelper { + private static final int MAXIMUM_WORLD_HEIGHT = 255; + private static final double DEFAULT_PLAYER_VIEW_HEIGHT = 1.65D; + private static final double DEFAULT_LOCATION_VIEW_HEIGHT = 0.0D; + private static final double DEFAULT_STEP = 0.2D; + private static final int DEFAULT_RANGE = 250; + private Location playerLoc; + private double rotX; + private double rotY; + private double viewHeight; + private double rotXSin; + private double rotXCos; + private double rotYSin; + private double rotYCos; + private double length; + private double hLength; + private double step; + private double range; + private double playerX; + private double playerY; + private double playerZ; + private double xOffset; + private double yOffset; + private double zOffset; + private int lastX; + private int lastY; + private int lastZ; + private int targetX; + private int targetY; + private int targetZ; + private AsyncWorld world; + + public RangeBlockHelper(Location location) { + this.init(location, 250.0D, 0.2D, 0.0D); + } + + public RangeBlockHelper(Location location, int range, double step) { + this.world = (AsyncWorld) location.getWorld(); + this.init(location, (double)range, step, 0.0D); + } + + public RangeBlockHelper(Player player, int range, double step) { + if (player != null) { + this.world = VoxelSniper.getInstance().getSniperManager().getSniperForPlayer(player).getWorld(); + } + this.init(player.getLocation(), (double)range, step, 1.65D); + } + + public RangeBlockHelper(Player player, AsyncWorld world) { + if (player != null && (world == null || player.getWorld().getName().equals(world.getName()))) { + this.world = VoxelSniper.getInstance().getSniperManager().getSniperForPlayer(player).getWorld(); + } else { + this.world = world; + } + this.init(player.getLocation(), 250.0D, 0.2D, 1.65D); + } + + public RangeBlockHelper(Player player, AsyncWorld world, double range) { + if (player != null && (world == null || player.getWorld().getName().equals(world.getName()))) { + this.world = VoxelSniper.getInstance().getSniperManager().getSniperForPlayer(player).getWorld(); + } else { + this.world = world; + } + this.init(player.getLocation(), range, 0.2D, 1.65D); + this.fromOffworld(); + } + + public final void fromOffworld() { + if(this.targetY <= 255) { + if(this.targetY < 0) { + while(this.targetY < 0 && this.length <= this.range) { + this.lastX = this.targetX; + this.lastY = this.targetY; + this.lastZ = this.targetZ; + + while(true) { + this.length += this.step; + this.hLength = this.length * this.rotYCos; + this.yOffset = this.length * this.rotYSin; + this.xOffset = this.hLength * this.rotXCos; + this.zOffset = this.hLength * this.rotXSin; + this.targetX = (int)Math.floor(this.xOffset + this.playerX); + this.targetY = (int)Math.floor(this.yOffset + this.playerY); + this.targetZ = (int)Math.floor(this.zOffset + this.playerZ); + if(this.length > this.range || this.targetX != this.lastX || this.targetY != this.lastY || this.targetZ != this.lastZ) { + break; + } + } + } + } + } else { + while(this.targetY > 255 && this.length <= this.range) { + this.lastX = this.targetX; + this.lastY = this.targetY; + this.lastZ = this.targetZ; + + while(true) { + this.length += this.step; + this.hLength = this.length * this.rotYCos; + this.yOffset = this.length * this.rotYSin; + this.xOffset = this.hLength * this.rotXCos; + this.zOffset = this.hLength * this.rotXSin; + this.targetX = (int)Math.floor(this.xOffset + this.playerX); + this.targetY = (int)Math.floor(this.yOffset + this.playerY); + this.targetZ = (int)Math.floor(this.zOffset + this.playerZ); + if(this.length > this.range || this.targetX != this.lastX || this.targetY != this.lastY || this.targetZ != this.lastZ) { + break; + } + } + } + } + + } + + public final AsyncBlock getCurBlock() { + return this.length <= this.range && this.targetY <= 255 && this.targetY >= 0?this.world.getBlockAt(this.targetX, this.targetY, this.targetZ):null; + } + + private boolean isAir(Material m) { + switch (m) { + case AIR: + case CAVE_AIR: + case VOID_AIR: + return true; + default: + return false; + } + } + + public final AsyncBlock getFaceBlock() { + while(this.getNextBlock() != null && isAir(this.getCurBlock().getType())) { + ; + } + + if(this.getCurBlock() != null) { + return this.getLastBlock(); + } else { + return null; + } + } + + public final AsyncBlock getLastBlock() { + return this.lastY <= 255 && this.lastY >= 0?this.world.getBlockAt(this.lastX, this.lastY, this.lastZ):null; + } + + public final AsyncBlock getNextBlock() { + this.lastX = this.targetX; + this.lastY = this.targetY; + this.lastZ = this.targetZ; + + do { + this.length += this.step; + this.hLength = this.length * this.rotYCos; + this.yOffset = this.length * this.rotYSin; + this.xOffset = this.hLength * this.rotXCos; + this.zOffset = this.hLength * this.rotXSin; + this.targetX = (int)Math.floor(this.xOffset + this.playerX); + this.targetY = (int)Math.floor(this.yOffset + this.playerY); + this.targetZ = (int)Math.floor(this.zOffset + this.playerZ); + } while(this.length <= this.range && this.targetX == this.lastX && this.targetY == this.lastY && this.targetZ == this.lastZ); + + return this.length <= this.range && this.targetY <= 255 && this.targetY >= 0?this.world.getBlockAt(this.targetX, this.targetY, this.targetZ):null; + } + + public final AsyncBlock getRangeBlock() { + this.fromOffworld(); + return this.length > this.range?null:this.getRange(); + } + + public final AsyncBlock getTargetBlock() { + this.fromOffworld(); + + while(this.getNextBlock() != null && isAir(this.getCurBlock().getType())) { + ; + } + + return this.getCurBlock(); + } + + public final void setCurBlock(int type) { + if(this.getCurBlock() != null) { + this.world.getBlockAt(this.targetX, this.targetY, this.targetZ).setType(getType(type)); + } + + } + + public final void setFaceBlock(int type) { + while(this.getNextBlock() != null && isAir(this.getCurBlock().getType())) { + ; + } + + if(this.getCurBlock() != null) { + this.world.getBlockAt(this.targetX, this.targetY, this.targetZ).setType(getType(type)); + } + + } + + private Material getType(int id) { + return BukkitAdapter.adapt(LegacyMapper.getInstance().getBlockFromLegacy(id).getBlockType()); + } + + public final void setLastBlock(int type) { + if(this.getLastBlock() != null) { + this.world.getBlockAt(this.lastX, this.lastY, this.lastZ).setType(getType(type)); + } + + } + + public final void setTargetBlock(int type) { + while(this.getNextBlock() != null && isAir(this.getCurBlock().getType())) { + ; + } + + if(this.getCurBlock() != null) { + this.world.getBlockAt(this.targetX, this.targetY, this.targetZ).setType(getType(type)); + } + + } + + private AsyncBlock getRange() { + this.lastX = this.targetX; + this.lastY = this.targetY; + this.lastZ = this.targetZ; + + do { + this.length += this.step; + this.hLength = this.length * this.rotYCos; + this.yOffset = this.length * this.rotYSin; + this.xOffset = this.hLength * this.rotXCos; + this.zOffset = this.hLength * this.rotXSin; + this.targetX = (int)Math.floor(this.xOffset + this.playerX); + this.targetY = (int)Math.floor(this.yOffset + this.playerY); + this.targetZ = (int)Math.floor(this.zOffset + this.playerZ); + } while(this.length <= this.range && this.targetX == this.lastX && this.targetY == this.lastY && this.targetZ == this.lastZ); + + AsyncBlock block = world.getBlockAt(this.targetX, this.targetY, this.targetZ); + Material type = block.getType(); + return !isAir(type) ? block : (this.length <= this.range && this.targetY <= 255 && this.targetY >= 0?this.getRange():this.world.getBlockAt(this.lastX, this.lastY, this.lastZ)); + } + + private void init(Location location, double range, double step, double viewHeight) { + this.playerLoc = location; + this.viewHeight = viewHeight; + this.playerX = this.playerLoc.getX(); + this.playerY = this.playerLoc.getY() + this.viewHeight; + this.playerZ = this.playerLoc.getZ(); + this.range = range; + this.step = step; + this.length = 0.0D; + this.rotX = (double)((this.playerLoc.getYaw() + 90.0F) % 360.0F); + this.rotY = (double)(this.playerLoc.getPitch() * -1.0F); + this.rotYCos = Math.cos(Math.toRadians(this.rotY)); + this.rotYSin = Math.sin(Math.toRadians(this.rotY)); + this.rotXCos = Math.cos(Math.toRadians(this.rotX)); + this.rotXSin = Math.sin(Math.toRadians(this.rotX)); + this.targetX = (int)Math.floor(this.playerLoc.getX()); + this.targetY = (int)Math.floor(this.playerLoc.getY() + this.viewHeight); + this.targetZ = (int)Math.floor(this.playerLoc.getZ()); + this.lastX = this.targetX; + this.lastY = this.targetY; + this.lastZ = this.targetZ; + } + + public static Class inject() { + return RangeBlockHelper.class; + } +} diff --git a/favs/src/main/java/com/thevoxelbox/voxelsniper/SnipeAction.java b/favs/src/main/java/com/thevoxelbox/voxelsniper/SnipeAction.java new file mode 100644 index 000000000..3102e0e82 --- /dev/null +++ b/favs/src/main/java/com/thevoxelbox/voxelsniper/SnipeAction.java @@ -0,0 +1,9 @@ +package com.thevoxelbox.voxelsniper; + +/** +* +*/ +public enum SnipeAction +{ + ARROW, GUNPOWDER +} diff --git a/favs/src/main/java/com/thevoxelbox/voxelsniper/SnipeData.java b/favs/src/main/java/com/thevoxelbox/voxelsniper/SnipeData.java new file mode 100644 index 000000000..e997e5ec6 --- /dev/null +++ b/favs/src/main/java/com/thevoxelbox/voxelsniper/SnipeData.java @@ -0,0 +1,328 @@ +/** + This file is part of VoxelSniper, licensed under the MIT License (MIT). + + Copyright (c) The VoxelBox + Copyright (c) contributors + + Permission is hereby granted, free of charge, to any person obtaining a copy + of this software and associated documentation files (the "Software"), to deal + in the Software without restriction, including without limitation the rights + to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + copies of the Software, and to permit persons to whom the Software is + furnished to do so, subject to the following conditions: + + The above copyright notice and this permission notice shall be included in + all copies or substantial portions of the Software. + + THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + THE SOFTWARE. + */ +package com.thevoxelbox.voxelsniper; + +import com.sk89q.worldedit.WorldEdit; +import com.sk89q.worldedit.extent.Extent; +import com.sk89q.worldedit.function.pattern.Pattern; +import com.sk89q.worldedit.world.block.BlockTypes; +import com.thevoxelbox.voxelsniper.util.VoxelList; +import org.bukkit.ChatColor; +import org.bukkit.World; +import org.bukkit.entity.Player; + +/** + * @author Piotr + */ +public class SnipeData { + + public static final int DEFAULT_REPLACE_DATA_VALUE = 0; + public static final int DEFAULT_CYLINDER_CENTER = 0; + public static final int DEFAULT_VOXEL_HEIGHT = 1; + public static final int DEFAULT_BRUSH_SIZE = 3; + public static final int DEFAULT_DATA_VALUE = 0; + public static final int DEFAULT_REPLACE_ID = BlockTypes.AIR.getInternalId(); + public static final int DEFAULT_VOXEL_ID = BlockTypes.AIR.getInternalId(); + + private final Sniper owner; + private Message voxelMessage; + /** + * Brush size -- set blockPositionY /b #. + */ + private int brushSize = SnipeData.DEFAULT_BRUSH_SIZE; + /** + * Voxel Id -- set blockPositionY /v (#,name). + */ + private int voxelId = SnipeData.DEFAULT_VOXEL_ID; + /** + * Voxel Replace Id -- set blockPositionY /vr #. + */ + private int replaceId = SnipeData.DEFAULT_REPLACE_ID; + /** + * Voxel 'ink' -- set blockPositionY /vi #. + */ + private int data = SnipeData.DEFAULT_DATA_VALUE; + /** + * Voxel 'ink' Replace -- set blockPositionY /vir #. + */ + private int replaceData = SnipeData.DEFAULT_REPLACE_DATA_VALUE; + /** + * Voxel List of ID's -- set blockPositionY /vl # # # -#. + */ + private VoxelList voxelList = new VoxelList(); + /** + * Voxel 'heigth' -- set blockPositionY /vh #. + */ + private int voxelHeight = SnipeData.DEFAULT_VOXEL_HEIGHT; + /** + * Voxel centroid -- set Cylynder center /vc #. + */ + private int cCen = SnipeData.DEFAULT_CYLINDER_CENTER; + private int range = 0; + private boolean ranged = false; + private boolean lightning = false; + private Extent extent; + private Pattern pattern; + private String patternInfo; + + /** + * @param vs + */ + public SnipeData(final Sniper vs) { + this.owner = vs; + } + + /** + * Get the extent currently being used to set blocks + * @return + */ + public Extent getExtent() { + return extent; + } + + /** + * Set the extent currently being used to set blocks + * @param extent + */ + public void setExtent(Extent extent) { + this.extent = extent; + } + + public void setPattern(Pattern pattern, String info) { + if (pattern != null) { + if (info == null) info = ""; + } else { + info = null; + } + this.pattern = pattern; + this.patternInfo = info; + } + + public Pattern getPattern() { + return pattern; + } + + public String getPatternInfo() { + return patternInfo; + } + + /** + * @return the brushSize + */ + public final int getBrushSize() { + return this.brushSize; + } + + /** + * @return the cCen + */ + public final int getcCen() { + return this.cCen; + } + + /** + * @return the data + */ + public final int getPropertyId() { + return this.data; + } + + /** + * @return the replaceData + */ + public final int getReplaceData() { + return this.replaceData; + } + + /** + * @return the replaceId + */ + public final int getReplaceId() { + return this.replaceId; + } + + /** + * @return the voxelHeight + */ + public final int getVoxelHeight() { + return this.voxelHeight; + } + + /** + * @return the voxelId + */ + public final int getVoxelId() { + return this.voxelId; + } + + /** + * @return the voxelList + */ + public final VoxelList getVoxelList() { + return this.voxelList; + } + + /** + * @return the voxelMessage + */ + public final Message getVoxelMessage() { + return this.voxelMessage; + } + + /** + * @return World + */ + public final World getWorld() { + return this.owner.getWorld(); // Changed + } + + /** + * @return Sniper + */ + public final Sniper owner() { + return this.owner; + } + + /** + * Reset to default values. + */ + public final void reset() { + this.voxelId = SnipeData.DEFAULT_VOXEL_ID; + this.replaceId = SnipeData.DEFAULT_REPLACE_ID; + this.data = SnipeData.DEFAULT_DATA_VALUE; + this.brushSize = SnipeData.DEFAULT_BRUSH_SIZE; + this.voxelHeight = SnipeData.DEFAULT_VOXEL_HEIGHT; + this.cCen = SnipeData.DEFAULT_CYLINDER_CENTER; + this.replaceData = SnipeData.DEFAULT_REPLACE_DATA_VALUE; + this.voxelList = new VoxelList(); + } + + /** + * @param message + */ + public final void sendMessage(final String message) { + this.owner.getPlayer().sendMessage(message); + } + + /** + * @param brushSize the brushSize to set + */ + public final void setBrushSize(final int brushSize) { + this.brushSize = brushSize; + } + + /** + * @param cCen the cCen to set + */ + public final void setcCen(final int cCen) { + this.cCen = cCen; + } + + /** + * @param data the data to set + */ + public final void setData(final int data) { + this.data = data; + } + + /** + * @param replaceData the replaceData to set + */ + public final void setReplaceData(final int replaceData) { + this.replaceData = replaceData; + } + + /** + * @param replaceId the replaceId to set + */ + public final void setReplaceId(final int replaceId) { + this.replaceId = replaceId; + } + + /** + * @param voxelHeight the voxelHeight to set + */ + public final void setVoxelHeight(final int voxelHeight) { + this.voxelHeight = voxelHeight; + } + + /** + * @param voxelId the voxelId to set + */ + public final void setVoxelId(final int voxelId) { + if (WorldEdit.getInstance().getConfiguration().disallowedBlocks.contains(voxelId)) { + if (owner != null) { + Player plr = owner.getPlayer(); + if (plr != null) { + plr.sendMessage(ChatColor.RED + "You are not allowed to use '" + voxelId + "'"); + return; + } + } + } + this.voxelId = voxelId; + } + + /** + * @param voxelList the voxelList to set + */ + public final void setVoxelList(final VoxelList voxelList) { + this.voxelList = voxelList; + } + + /** + * @param voxelMessage the voxelMessage to set + */ + public final void setVoxelMessage(final Message voxelMessage) { + this.voxelMessage = voxelMessage; + } + + public int getRange() { + return range; + } + + public void setRange(int range) { + this.range = range; + } + + public boolean isRanged() { + return ranged; + } + + public void setRanged(boolean ranged) { + this.ranged = ranged; + } + + public boolean isLightningEnabled() { + return lightning; + } + + public void setLightningEnabled(boolean lightning) { + this.lightning = lightning; + } + + public static Class inject() { + return SnipeData.class; + } +} \ No newline at end of file diff --git a/favs/src/main/java/com/thevoxelbox/voxelsniper/Sniper.java b/favs/src/main/java/com/thevoxelbox/voxelsniper/Sniper.java new file mode 100644 index 000000000..0301d54c0 --- /dev/null +++ b/favs/src/main/java/com/thevoxelbox/voxelsniper/Sniper.java @@ -0,0 +1,679 @@ +/** + This file is part of VoxelSniper, licensed under the MIT License (MIT). + + Copyright (c) The VoxelBox + Copyright (c) contributors + + Permission is hereby granted, free of charge, to any person obtaining a copy + of this software and associated documentation files (the "Software"), to deal + in the Software without restriction, including without limitation the rights + to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + copies of the Software, and to permit persons to whom the Software is + furnished to do so, subject to the following conditions: + + The above copyright notice and this permission notice shall be included in + all copies or substantial portions of the Software. + + THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + THE SOFTWARE. + */ + +package com.thevoxelbox.voxelsniper; + +import com.boydti.fawe.Fawe; +import com.boydti.fawe.bukkit.wrapper.AsyncBlock; +import com.boydti.fawe.bukkit.wrapper.AsyncWorld; +import com.boydti.fawe.config.BBC; +import com.boydti.fawe.config.Settings; +import com.boydti.fawe.logging.LoggingChangeSet; +import com.boydti.fawe.object.*; +import com.boydti.fawe.object.changeset.FaweChangeSet; +import com.boydti.fawe.object.extent.ResettableExtent; +import com.boydti.fawe.object.extent.SourceMaskExtent; +import com.boydti.fawe.object.queue.FaweQueueDelegateExtent; +import com.boydti.fawe.util.MaskTraverser; +import com.boydti.fawe.util.SetQueue; +import com.boydti.fawe.util.TaskManager; +import com.boydti.fawe.util.WEManager; +import com.google.common.base.Preconditions; +import com.google.common.collect.*; +import com.sk89q.worldedit.EditSession; +import com.sk89q.worldedit.LocalSession; +import com.sk89q.worldedit.bukkit.BukkitAdapter; +import com.sk89q.worldedit.extent.MaskingExtent; +import com.sk89q.worldedit.function.mask.Mask; +import com.sk89q.worldedit.function.mask.Masks; +import com.sk89q.worldedit.regions.Region; +import com.sk89q.worldedit.session.request.Request; +import com.sk89q.worldedit.world.block.BlockState; +import com.sk89q.worldedit.world.block.BlockTypes; +import com.thevoxelbox.voxelsniper.brush.IBrush; +import com.thevoxelbox.voxelsniper.brush.SnipeBrush; +import com.thevoxelbox.voxelsniper.brush.perform.PerformBrush; +import com.thevoxelbox.voxelsniper.brush.perform.Performer; +import com.thevoxelbox.voxelsniper.event.SniperMaterialChangedEvent; +import com.thevoxelbox.voxelsniper.event.SniperReplaceMaterialChangedEvent; + +import java.lang.reflect.Method; +import java.util.HashMap; +import java.util.Map; +import java.util.UUID; +import org.bukkit.Bukkit; +import org.bukkit.ChatColor; +import org.bukkit.Material; +import org.bukkit.World; +import org.bukkit.block.Block; +import org.bukkit.block.BlockFace; +import org.bukkit.entity.Player; +import org.bukkit.event.Event; +import org.bukkit.event.block.Action; +import org.bukkit.material.MaterialData; +import org.bukkit.plugin.PluginManager; + +public class Sniper { + private VoxelSniper plugin; + private final UUID player; + private boolean enabled = true; +// private LinkedList undoList = new LinkedList<>(); + private Map tools = new HashMap<>(); + + public Sniper(VoxelSniper plugin, Player player) { + Preconditions.checkNotNull(plugin); + Preconditions.checkNotNull(player); + this.plugin = plugin; + this.player = player.getUniqueId(); + SniperTool sniperTool = new SniperTool(this); + sniperTool.assignAction(SnipeAction.ARROW, Material.ARROW); + sniperTool.assignAction(SnipeAction.GUNPOWDER, Material.GUNPOWDER); + tools.put(null, sniperTool); + } + + public String getCurrentToolId() { + return getToolId((getPlayer().getItemInHand() != null) ? getPlayer().getItemInHand().getType() : null); + } + + public String getToolId(Material itemInHand) { + if (itemInHand == null) { + return null; + } + + for (Map.Entry entry : tools.entrySet()) { + if (entry.getValue().hasToolAssigned(itemInHand)) { + return entry.getKey(); + } + } + return null; + } + + // Added + private AsyncWorld permanentWorld; + + public void storeUndo(Undo undo) { + } + + // Added + public AsyncWorld getWorld() { + AsyncWorld world = permanentWorld; + if (world == null) { + Player bukkitPlayer = getPlayer(); + World bukkitWorld = bukkitPlayer.getWorld(); + world = AsyncWorld.wrap(bukkitWorld); + permanentWorld = world; + } + return world; + } + + public Player getPlayer() { + return Bukkit.getPlayer(player); + } + + /** + * Sniper execution call. + * + * @param action Action player performed + * @param itemInHand Item in hand of player + * @param clickedBlock Block that the player targeted/interacted with + * @param clickedFace Face of that targeted Block + * @return true if command visibly processed, false otherwise. + */ + public boolean snipe(final Action action, final Material itemInHand, final Block clickedBlock, final BlockFace clickedFace) { + switch (action) { + case LEFT_CLICK_AIR: + case LEFT_CLICK_BLOCK: + case RIGHT_CLICK_AIR: + case RIGHT_CLICK_BLOCK: + break; + default: + return false; + } + if (tools.isEmpty()) { + return false; + } + String toolId = getToolId(itemInHand); + SniperTool sniperTool = tools.get(toolId); + if (sniperTool == null) { + return false; + } + if (!sniperTool.hasToolAssigned(itemInHand)) { + return false; + } + if (sniperTool.getCurrentBrush() == null) { + getPlayer().sendMessage("No Brush selected."); + return false; + } + try { + Player player = getPlayer(); + final FawePlayer fp = FawePlayer.wrap(player); + TaskManager.IMP.taskNow(new Runnable() { + @Override + public void run() { + if (!fp.runAction(new Runnable() { + @Override + public void run() { + snipeOnCurrentThread(fp, action, itemInHand, clickedBlock, clickedFace, sniperTool, toolId); + } + }, false, true)) { + BBC.WORLDEDIT_COMMAND_LIMIT.send(fp); + } + } + }, Fawe.isMainThread()); + return true; + } catch (Throwable e) { + e.printStackTrace(); + } + return false; + } + + // Old method (plus world arg) + public synchronized boolean snipeOnCurrentThread(FawePlayer fp, final Action action, final Material itemInHand, Block clickedBlock, final BlockFace clickedFace, SniperTool sniperTool, String toolId) { + try { + Player bukkitPlayer = getPlayer(); + World bukkitWorld = bukkitPlayer.getWorld(); + + FaweQueue baseQueue = fp.getFaweQueue(false); + Region[] mask = WEManager.IMP.getMask(fp); + if (mask.length == 0) { + BBC.NO_REGION.send(fp); + return false; + } + MaskedFaweQueue maskQueue = new MaskedFaweQueue(baseQueue, mask); + com.sk89q.worldedit.world.World worldEditWorld = fp.getWorld(); + FaweChangeSet changeSet = FaweChangeSet.getDefaultChangeSet(worldEditWorld, fp.getUUID()); + if (Fawe.imp().getBlocksHubApi() != null) { + changeSet = LoggingChangeSet.wrap(fp, changeSet); + } + FaweQueue changeQueue; + if (Settings.IMP.HISTORY.COMBINE_STAGES) { + changeQueue = maskQueue; + changeSet.addChangeTask(baseQueue); + } else { + changeQueue = new ChangeSetFaweQueue(changeSet, maskQueue); + } + LocalSession session = fp.getSession(); + { // Set mask etc + Mask destMask = session.getMask(); + if (!Masks.isNull(destMask)) { + new MaskTraverser(destMask).reset(changeQueue); + changeQueue = new FaweQueueDelegateExtent(changeQueue, new MaskingExtent(changeQueue, destMask)); + } + Mask sourceMask = session.getSourceMask(); + if (!Masks.isNull(sourceMask)) { + new MaskTraverser(sourceMask).reset(changeQueue); + changeQueue = new FaweQueueDelegateExtent(changeQueue, new SourceMaskExtent(changeQueue, sourceMask)); + } + ResettableExtent transform = session.getTransform(); + if (transform != null) { + transform.setExtent(changeQueue); + changeQueue = new FaweQueueDelegateExtent(changeQueue, transform); + } + } + + AsyncWorld world = getWorld(); + world.changeWorld(bukkitWorld, changeQueue); + + AsyncBlock asyncBlock = null; + if (clickedBlock != null) { + asyncBlock = world.getBlockAt(clickedBlock.getX(), clickedBlock.getY(), clickedBlock.getZ()); + } + if (!getPlayer().hasPermission(sniperTool.getCurrentBrush().getPermissionNode())) { + getPlayer().sendMessage("You are not allowed to use this brush. You're missing the permission node '" + sniperTool.getCurrentBrush().getPermissionNode() + "'"); + return true; + } + + final SnipeData snipeData = sniperTool.getSnipeData(); + if (getPlayer().isSneaking()) { + AsyncBlock targetBlock; + SnipeAction snipeAction = sniperTool.getActionAssigned(itemInHand); + + switch (action) { + case LEFT_CLICK_BLOCK: + case LEFT_CLICK_AIR: + if (asyncBlock != null) { + targetBlock = asyncBlock; + } else { + RangeBlockHelper rangeBlockHelper = snipeData.isRanged() ? new RangeBlockHelper(getPlayer(), world, snipeData.getRange()) : new RangeBlockHelper(getPlayer(), world); + targetBlock = snipeData.isRanged() ? rangeBlockHelper.getRangeBlock() : rangeBlockHelper.getTargetBlock(); + } + + switch (snipeAction) { + case ARROW: + if (targetBlock != null) { + int originalVoxel = snipeData.getVoxelId(); + snipeData.setVoxelId(targetBlock.getTypeId()); +// SniperMaterialChangedEvent event = new SniperMaterialChangedEvent(this, toolId, BukkitAdapter.adapt(BlockState.get((originalVoxel << BlockTypes.BIT_OFFSET) + snipeData.getPropertyId())), BukkitAdapter.adapt(BlockState.get(snipeData.getVoxelId() + snipeData.getPropertyId()))); +// callEvent(event); + snipeData.getVoxelMessage().voxel(); + return true; + } else { + int originalVoxel = snipeData.getVoxelId(); + snipeData.setVoxelId(BlockTypes.AIR.getInternalId()); +// SniperMaterialChangedEvent event = new SniperMaterialChangedEvent(this, toolId, BukkitAdapter.adapt(BlockState.get((originalVoxel << BlockTypes.BIT_OFFSET) + snipeData.getPropertyId())), BukkitAdapter.adapt(BlockState.get(snipeData.getVoxelId() + snipeData.getPropertyId()))); +// callEvent(event); + snipeData.getVoxelMessage().voxel(); + return true; + } + case GUNPOWDER: + if (targetBlock != null) { + int originalData = snipeData.getPropertyId(); + snipeData.setData(targetBlock.getPropertyId()); +// SniperMaterialChangedEvent event = new SniperMaterialChangedEvent(this, toolId, BukkitAdapter.adapt(BlockState.get(snipeData.getVoxelId() + originalData)), BukkitAdapter.adapt(BlockState.get(snipeData.getVoxelId() + snipeData.getPropertyId()))); +// callEvent(event); + snipeData.getVoxelMessage().data(); + return true; + } else { + int originalData = snipeData.getPropertyId(); + snipeData.setData(0); +// SniperMaterialChangedEvent event = new SniperMaterialChangedEvent(this, toolId, BukkitAdapter.adapt(BlockState.get(snipeData.getVoxelId() + originalData)), BukkitAdapter.adapt(BlockState.get(snipeData.getVoxelId() + snipeData.getPropertyId()))); +// callEvent(event); + snipeData.getVoxelMessage().data(); + return true; + } + default: + break; + } + break; + case RIGHT_CLICK_AIR: + case RIGHT_CLICK_BLOCK: + if (asyncBlock != null) { + targetBlock = asyncBlock; + } else { + RangeBlockHelper rangeBlockHelper = snipeData.isRanged() ? new RangeBlockHelper(getPlayer(), world, snipeData.getRange()) : new RangeBlockHelper(getPlayer(), world); + targetBlock = snipeData.isRanged() ? rangeBlockHelper.getRangeBlock() : rangeBlockHelper.getTargetBlock(); + } + + switch (snipeAction) { + case ARROW: + if (targetBlock != null) { + int originalId = snipeData.getReplaceId(); + snipeData.setReplaceId(targetBlock.getTypeId()); +// SniperReplaceMaterialChangedEvent event = new SniperReplaceMaterialChangedEvent(this, toolId, BukkitAdapter.adapt(BlockState.get((originalId << BlockTypes.BIT_OFFSET) + snipeData.getReplaceData())), BukkitAdapter.adapt(BlockState.get((snipeData.getReplaceId() << BlockTypes.BIT_OFFSET) + snipeData.getReplaceData()))); +// callEvent(event); + snipeData.getVoxelMessage().replace(); + return true; + } else { + int originalId = snipeData.getReplaceId(); + snipeData.setReplaceId(BlockTypes.AIR.getInternalId()); +// SniperReplaceMaterialChangedEvent event = new SniperReplaceMaterialChangedEvent(this, toolId, BukkitAdapter.adapt(BlockState.get((originalId << BlockTypes.BIT_OFFSET) + snipeData.getReplaceData())), BukkitAdapter.adapt(BlockState.get((snipeData.getReplaceId() << BlockTypes.BIT_OFFSET) + snipeData.getReplaceData()))); +// callEvent(event); + snipeData.getVoxelMessage().replace(); + return true; + } + case GUNPOWDER: + if (targetBlock != null) { + int originalData = snipeData.getReplaceData(); + snipeData.setReplaceData(targetBlock.getPropertyId()); +// SniperReplaceMaterialChangedEvent event = new SniperReplaceMaterialChangedEvent(this, toolId, BukkitAdapter.adapt(BlockState.get((snipeData.getReplaceId() << BlockTypes.BIT_OFFSET) + originalData)), BukkitAdapter.adapt(BlockState.get((snipeData.getReplaceId() << BlockTypes.BIT_OFFSET) + snipeData.getReplaceData()))); +// callEvent(event); + snipeData.getVoxelMessage().replaceData(); + return true; + } else { + int originalData = snipeData.getReplaceData(); + snipeData.setReplaceData(BlockTypes.AIR.getInternalId()); +// SniperReplaceMaterialChangedEvent event = new SniperReplaceMaterialChangedEvent(this, toolId, BukkitAdapter.adapt(BlockState.get((snipeData.getReplaceId() << BlockTypes.BIT_OFFSET) + originalData)), BukkitAdapter.adapt(BlockState.get((snipeData.getReplaceId() << BlockTypes.BIT_OFFSET) + snipeData.getReplaceData()))); +// callEvent(event); + snipeData.getVoxelMessage().replaceData(); + return true; + } + default: + break; + } + break; + default: + return false; + } + } else { + final AsyncBlock targetBlock; + final AsyncBlock lastBlock; + final SnipeAction snipeAction = sniperTool.getActionAssigned(itemInHand); + + switch (action) { + case RIGHT_CLICK_AIR: + case RIGHT_CLICK_BLOCK: + break; + default: + return false; + } + + if (asyncBlock != null) { + targetBlock = asyncBlock; + lastBlock = asyncBlock.getRelative(clickedFace); + if (lastBlock == null || targetBlock == null) { + getPlayer().sendMessage(ChatColor.RED + "Snipe target block must be visible."); + return true; + } + } else { + RangeBlockHelper rangeBlockHelper = snipeData.isRanged() ? new RangeBlockHelper(getPlayer(), world, snipeData.getRange()) : new RangeBlockHelper(getPlayer(), world); + targetBlock = snipeData.isRanged() ? rangeBlockHelper.getRangeBlock() : rangeBlockHelper.getTargetBlock(); + lastBlock = rangeBlockHelper.getLastBlock(); + + if (targetBlock == null || lastBlock == null) { + getPlayer().sendMessage(ChatColor.RED + "Snipe target block must be visible."); + return true; + } + } + + final IBrush brush = sniperTool.getCurrentBrush(); + + try { + snipeData.setExtent(world); + Request.reset(); + Request.request().setExtent(world); + switch (brush.getClass().getSimpleName()) { + case "JockeyBrush": + TaskManager.IMP.sync(new RunnableVal() { + @Override + public void run(Object value) { + brush.perform(snipeAction, snipeData, targetBlock, lastBlock); + } + }); + break; + default: + if (sniperTool.getCurrentBrush() instanceof PerformBrush) { + PerformBrush performerBrush = (PerformBrush) sniperTool.getCurrentBrush(); + performerBrush.initP(snipeData); + } + brush.perform(snipeAction, snipeData, targetBlock, lastBlock); + break; + } + } finally { + snipeData.setExtent(null); + Request.reset(); + } + if (Fawe.isMainThread()) { + SetQueue.IMP.flush(changeQueue); + } else { + changeQueue.flush(); + } + if (changeSet != null) { + if (Settings.IMP.HISTORY.COMBINE_STAGES) { + changeSet.closeAsync(); + } else { + changeSet.close(); + } + session.remember(changeSet.toEditSession(fp)); + } + return true; + } + return false; + } catch (Throwable e) { + e.printStackTrace(); + } + return false; + } + + private void callEvent(Event event) { + if (Fawe.isMainThread()) { + Bukkit.getPluginManager().callEvent(event); + } else { + if (event.isAsynchronous()) { + Bukkit.getPluginManager().callEvent(event); + } else { + try { + PluginManager plm = Bukkit.getPluginManager(); + Class clazz = plm.getClass(); + Method methodFireEvent = clazz.getDeclaredMethod("fireEvent", Event.class); + methodFireEvent.setAccessible(true); + methodFireEvent.invoke(plm, event); + } catch (Throwable ignore) {} + } + } + } + + public IBrush setBrush(String toolId, Class brush) { + if (!tools.containsKey(toolId)) { + return null; + } + + return tools.get(toolId).setCurrentBrush(brush); + } + + public IBrush getBrush(String toolId) { + if (!tools.containsKey(toolId)) { + return null; + } + + return tools.get(toolId).getCurrentBrush(); + } + + public IBrush previousBrush(String toolId) { + if (!tools.containsKey(toolId)) { + return null; + } + + return tools.get(toolId).previousBrush(); + } + + public boolean setTool(String toolId, SnipeAction action, Material itemInHand) { + for (Map.Entry entry : tools.entrySet()) { + if (entry.getKey() != toolId && entry.getValue().hasToolAssigned(itemInHand)) { + return false; + } + } + + if (!tools.containsKey(toolId)) { + SniperTool tool = new SniperTool(this); + tools.put(toolId, tool); + } + tools.get(toolId).assignAction(action, itemInHand); + return true; + } + + public void removeTool(String toolId, Material itemInHand) { + if (!tools.containsKey(toolId)) { + SniperTool tool = new SniperTool(this); + tools.put(toolId, tool); + } + tools.get(toolId).unassignAction(itemInHand); + } + + public void removeTool(String toolId) { + if (toolId == null) { + return; + } + tools.remove(toolId); + } + + public boolean isEnabled() { + return enabled; + } + + public void setEnabled(boolean enabled) { + this.enabled = enabled; + } + + public void undo() { + undo(1); + } + + public void undo(int amount) { + FawePlayer fp = FawePlayer.wrap(getPlayer()); + if (!fp.runAction(new Runnable() { + @Override + public void run() { + int count = 0; + for (int i = 0; i < amount; i++) { + EditSession es = fp.getSession().undo(null, fp.getPlayer()); + if (es == null) { + break; + } else { + es.flushQueue(); + } + count++; + } + if (count > 0) { + BBC.COMMAND_UNDO_SUCCESS.send(fp); + } else { + BBC.COMMAND_UNDO_ERROR.send(fp); + } + } + }, true, false)); + } + + public void reset(String toolId) { + SniperTool backup = tools.remove(toolId); + SniperTool newTool = new SniperTool(this); + + for (Map.Entry entry : backup.getActionTools().entrySet()) { + newTool.assignAction(entry.getKey(), entry.getValue()); + } + tools.put(toolId, newTool); + } + + public SnipeData getSnipeData(String toolId) { + return tools.containsKey(toolId) ? tools.get(toolId).getSnipeData() : null; + } + + public void displayInfo() { + String currentToolId = getCurrentToolId(); + SniperTool sniperTool = tools.get(currentToolId); + IBrush brush = sniperTool.getCurrentBrush(); + getPlayer().sendMessage("Current Tool: " + ((currentToolId != null) ? currentToolId : "Default Tool")); + if (brush == null) { + getPlayer().sendMessage("No brush selected."); + return; + } + brush.info(sniperTool.getMessageHelper()); + if (brush instanceof Performer) { + ((Performer) brush).showInfo(sniperTool.getMessageHelper()); + } + } + + public SniperTool getSniperTool(String toolId) { + return tools.get(toolId); + } + + public class SniperTool { + private BiMap actionTools = HashBiMap.create(); + private ClassToInstanceMap brushes = MutableClassToInstanceMap.create(); + private Class currentBrush; + private Class previousBrush; + private SnipeData snipeData; + private Message messageHelper; + + private SniperTool(Sniper owner) { + this(SnipeBrush.class, new SnipeData(owner)); + } + + private SniperTool(Class currentBrush, SnipeData snipeData) { + Preconditions.checkNotNull(currentBrush); + Preconditions.checkNotNull(snipeData); + this.snipeData = snipeData; + messageHelper = new Message(snipeData); + snipeData.setVoxelMessage(messageHelper); + + IBrush newBrushInstance = instantiateBrush(currentBrush); + if (snipeData.owner().getPlayer().hasPermission(newBrushInstance.getPermissionNode())) { + brushes.put(currentBrush, newBrushInstance); + this.currentBrush = currentBrush; + } + } + + public boolean hasToolAssigned(Material material) { + return actionTools.containsValue(material); + } + + public SnipeAction getActionAssigned(Material itemInHand) { + return actionTools.inverse().get(itemInHand); + } + + public Material getToolAssigned(SnipeAction action) { + return actionTools.get(action); + } + + public void assignAction(SnipeAction action, Material itemInHand) { + actionTools.forcePut(action, itemInHand); + } + + public void unassignAction(Material itemInHand) { + actionTools.inverse().remove(itemInHand); + } + + public BiMap getActionTools() { + return ImmutableBiMap.copyOf(actionTools); + } + + public SnipeData getSnipeData() { + return snipeData; + } + + public Message getMessageHelper() { + return messageHelper; + } + + public IBrush getCurrentBrush() { + if (currentBrush == null) { + return null; + } + return brushes.getInstance(currentBrush); + } + + public IBrush setCurrentBrush(Class brush) { + Preconditions.checkNotNull(brush, "Can't set brush to null."); + IBrush brushInstance = brushes.get(brush); + if (brushInstance == null) { + brushInstance = instantiateBrush(brush); + Preconditions.checkNotNull(brushInstance, "Could not instanciate brush class."); + if (snipeData.owner().getPlayer().hasPermission(brushInstance.getPermissionNode())) { + brushes.put(brush, brushInstance); + previousBrush = currentBrush; + currentBrush = brush; + return brushInstance; + } + } + + if (snipeData.owner().getPlayer().hasPermission(brushInstance.getPermissionNode())) { + previousBrush = currentBrush; + currentBrush = brush; + return brushInstance; + } + + return null; + } + + public IBrush previousBrush() { + if (previousBrush == null) { + return null; + } + return setCurrentBrush(previousBrush); + } + + private IBrush instantiateBrush(Class brush) { + try { + return brush.newInstance(); + } catch (InstantiationException e) { + return null; + } catch (IllegalAccessException e) { + return null; + } + } + } + + public static Class inject() { + return Sniper.class; + } +} \ No newline at end of file diff --git a/favs/src/main/java/com/thevoxelbox/voxelsniper/SniperManager.java b/favs/src/main/java/com/thevoxelbox/voxelsniper/SniperManager.java new file mode 100644 index 000000000..7bc394e9c --- /dev/null +++ b/favs/src/main/java/com/thevoxelbox/voxelsniper/SniperManager.java @@ -0,0 +1,30 @@ +package com.thevoxelbox.voxelsniper; + +import com.google.common.collect.Maps; +import org.bukkit.entity.Player; + +import java.util.Map; +import java.util.UUID; + +/** + * + */ +public class SniperManager +{ + private Map sniperInstances = Maps.newHashMap(); + private VoxelSniper plugin; + + public SniperManager(VoxelSniper plugin) + { + this.plugin = plugin; + } + + public Sniper getSniperForPlayer(Player player) + { + if (sniperInstances.get(player.getUniqueId()) == null) + { + sniperInstances.put(player.getUniqueId(), new Sniper(plugin, player)); + } + return sniperInstances.get(player.getUniqueId()); + } +} diff --git a/favs/src/main/java/com/thevoxelbox/voxelsniper/Undo.java b/favs/src/main/java/com/thevoxelbox/voxelsniper/Undo.java new file mode 100644 index 000000000..31c17960e --- /dev/null +++ b/favs/src/main/java/com/thevoxelbox/voxelsniper/Undo.java @@ -0,0 +1,70 @@ +/** + This file is part of VoxelSniper, licensed under the MIT License (MIT). + + Copyright (c) The VoxelBox + Copyright (c) contributors + + Permission is hereby granted, free of charge, to any person obtaining a copy + of this software and associated documentation files (the "Software"), to deal + in the Software without restriction, including without limitation the rights + to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + copies of the Software, and to permit persons to whom the Software is + furnished to do so, subject to the following conditions: + + The above copyright notice and this permission notice shall be included in + all copies or substantial portions of the Software. + + THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + THE SOFTWARE. + */ +package com.thevoxelbox.voxelsniper; + +import org.bukkit.World; +import org.bukkit.block.Block; + +/** + * Holds {@link org.bukkit.block.BlockState}s that can be later on used to reset those block + * locations back to the recorded states. + */ +public class Undo { + + int size; + private World world; + + /** + * Default constructor of a Undo container. + */ + public Undo() {} + + /** + * Get the number of blocks in the collection. + * + * @return size of the Undo collection + */ + public int getSize() { + return size; + } + + /** + * Adds a Block to the collection. + * + * @param block Block to be added + */ + public void put(Block block) { + size++; + } + + + /** + * Set the blockstates of all recorded blocks back to the state when they + * were inserted. + */ + public void undo() { + + } +} \ No newline at end of file diff --git a/favs/src/main/java/com/thevoxelbox/voxelsniper/VoxelSniper.java b/favs/src/main/java/com/thevoxelbox/voxelsniper/VoxelSniper.java new file mode 100644 index 000000000..0f6f9d493 --- /dev/null +++ b/favs/src/main/java/com/thevoxelbox/voxelsniper/VoxelSniper.java @@ -0,0 +1,227 @@ +package com.thevoxelbox.voxelsniper; + +import com.boydti.fawe.Fawe; +import com.boydti.fawe.bukkit.BukkitCommand; +import com.boydti.fawe.object.FaweCommand; +import com.boydti.fawe.object.FawePlayer; +import com.boydti.fawe.util.Jars; +import com.boydti.fawe.util.MainUtil; +import com.google.common.base.Preconditions; +import com.thevoxelbox.voxelsniper.brush.*; +import com.thevoxelbox.voxelsniper.brush.perform.PerformBrush; +import com.thevoxelbox.voxelsniper.command.VoxelVoxelCommand; +import com.thevoxelbox.voxelsniper.event.SniperBrushChangedEvent; +import com.thevoxelbox.voxelsniper.event.SniperMaterialChangedEvent; +import org.bukkit.Bukkit; +import org.bukkit.command.Command; +import org.bukkit.command.CommandSender; +import org.bukkit.entity.Player; +import org.bukkit.plugin.java.JavaPlugin; + +import java.io.File; +import java.io.FileOutputStream; +import java.util.ArrayList; +import java.util.List; +import java.util.logging.Level; + +/** + * Bukkit extension point. + */ +public class VoxelSniper extends JavaPlugin +{ + private static VoxelSniper instance; + private SniperManager sniperManager = new SniperManager(this); + private final VoxelSniperListener voxelSniperListener = new VoxelSniperListener(this); + private VoxelSniperConfiguration voxelSniperConfiguration; + + /** + * Returns {@link com.thevoxelbox.voxelsniper.Brushes} for current instance. + * + * @return Brush Manager for current instance. + */ + public Brushes getBrushManager() + { + return brushManager; + } + + private Brushes brushManager = new Brushes(); + + /** + * @return {@link VoxelSniper} + */ + public static VoxelSniper getInstance() + { + return VoxelSniper.instance; + } + + /** + * Returns object for accessing global VoxelSniper options. + * + * @return {@link VoxelSniperConfiguration} object for accessing global VoxelSniper options. + */ + public VoxelSniperConfiguration getVoxelSniperConfiguration() + { + return voxelSniperConfiguration; + } + + /** + * Returns {@link com.thevoxelbox.voxelsniper.SniperManager} for current instance. + * + * @return SniperManager + */ + public SniperManager getSniperManager() + { + return sniperManager; + } + + @Override + public boolean onCommand(CommandSender sender, Command command, String commandLabel, String[] args) + { + if (sender instanceof Player) + { + String[] arguments = args; + + if (arguments == null) + { + arguments = new String[0]; + } + + return voxelSniperListener.onCommand((Player) sender, arguments, command.getName()); + } + + getLogger().info("Only Players can execute commands."); + return true; + } + + @Override + public void onEnable() + { + VoxelSniper.instance = this; + + registerBrushes(); + getLogger().info("Registered " + brushManager.registeredSniperBrushes() + " Sniper Brushes with " + brushManager.registeredSniperBrushHandles() + " handles."); + + saveDefaultConfig(); + voxelSniperConfiguration = new VoxelSniperConfiguration(getConfig()); + + Bukkit.getPluginManager().registerEvents(this.voxelSniperListener, this); + getLogger().info("Registered Sniper Listener."); + + try { + setupCommand("/p", new FaweCommand("voxelsniper.sniper") { + @Override + public boolean execute(FawePlayer fp, String... args) { + Player player = (Player) fp.parent; + return (Bukkit.getPluginManager().getPlugin("VoxelSniper")).onCommand(player, new Command("p") { + @Override + public boolean execute(CommandSender sender, String commandLabel, String[] args) { + return false; + } + }, null, args); + + } + }); + setupCommand("/d", new FaweCommand("voxelsniper.sniper") { + @Override + public boolean execute(FawePlayer fp, String... args) { + Player player = (Player) fp.parent; + return (Bukkit.getPluginManager().getPlugin("VoxelSniper")).onCommand(player, new Command("d") { + @Override + public boolean execute(CommandSender sender, String commandLabel, String[] args) { + return false; + } + }, null, args); + + } + }); + } catch (Throwable ignore) {} + } + + /** + * Registers all brushes. + */ + public void registerBrushes() + { + brushManager.registerSniperBrush(BallBrush.class, "b", "ball"); + brushManager.registerSniperBrush(BiomeBrush.class, "bio", "biome"); + brushManager.registerSniperBrush(BlendBallBrush.class, "bb", "blendball"); + brushManager.registerSniperBrush(BlendDiscBrush.class, "bd", "blenddisc"); + brushManager.registerSniperBrush(BlendVoxelBrush.class, "bv", "blendvoxel"); + brushManager.registerSniperBrush(BlendVoxelDiscBrush.class, "bvd", "blendvoxeldisc"); + brushManager.registerSniperBrush(BlobBrush.class, "blob", "splatblob"); + brushManager.registerSniperBrush(BlockResetBrush.class, "brb", "blockresetbrush"); + brushManager.registerSniperBrush(BlockResetSurfaceBrush.class, "brbs", "blockresetbrushsurface"); + brushManager.registerSniperBrush(CanyonBrush.class, "ca", "canyon"); + brushManager.registerSniperBrush(CanyonSelectionBrush.class, "cas", "canyonselection"); + brushManager.registerSniperBrush(CheckerVoxelDiscBrush.class, "cvd", "checkervoxeldisc"); + brushManager.registerSniperBrush(CleanSnowBrush.class, "cls", "cleansnow"); + brushManager.registerSniperBrush(CloneStampBrush.class, "cs", "clonestamp"); + brushManager.registerSniperBrush(CometBrush.class, "com", "comet"); + brushManager.registerSniperBrush(CopyPastaBrush.class, "cp", "copypasta"); + brushManager.registerSniperBrush(CylinderBrush.class, "c", "cylinder"); + brushManager.registerSniperBrush(DiscBrush.class, "d", "disc"); + brushManager.registerSniperBrush(DiscFaceBrush.class, "df", "discface"); + brushManager.registerSniperBrush(DomeBrush.class, "dome", "domebrush"); + brushManager.registerSniperBrush(DrainBrush.class, "drain"); + brushManager.registerSniperBrush(EllipseBrush.class, "el", "ellipse"); + brushManager.registerSniperBrush(EllipsoidBrush.class, "elo", "ellipsoid"); + brushManager.registerSniperBrush(EntityBrush.class, "en", "entity"); + brushManager.registerSniperBrush(EntityRemovalBrush.class, "er", "entityremoval"); + brushManager.registerSniperBrush(EraserBrush.class, "erase", "eraser"); + brushManager.registerSniperBrush(ErodeBrush.class, "e", "erode"); + brushManager.registerSniperBrush(ExtrudeBrush.class, "ex", "extrude"); + brushManager.registerSniperBrush(FillDownBrush.class, "fd", "filldown"); + brushManager.registerSniperBrush(FlatOceanBrush.class, "fo", "flatocean"); + brushManager.registerSniperBrush(GenerateTreeBrush.class, "gt", "generatetree"); + brushManager.registerSniperBrush(HeatRayBrush.class, "hr", "heatray"); + brushManager.registerSniperBrush(JaggedLineBrush.class, "j", "jagged"); + brushManager.registerSniperBrush(JockeyBrush.class, "jockey"); + brushManager.registerSniperBrush(LightningBrush.class, "light", "lightning"); + brushManager.registerSniperBrush(LineBrush.class, "l", "line"); + brushManager.registerSniperBrush(MoveBrush.class, "mv", "move"); + brushManager.registerSniperBrush(OceanBrush.class, "o", "ocean"); + brushManager.registerSniperBrush(OverlayBrush.class, "over", "overlay"); + brushManager.registerSniperBrush(PaintingBrush.class, "paint", "painting"); + brushManager.registerSniperBrush(PullBrush.class, "pull"); + brushManager.registerSniperBrush(PunishBrush.class, "p", "punish"); + brushManager.registerSniperBrush(RandomErodeBrush.class, "re", "randomerode"); + brushManager.registerSniperBrush(RegenerateChunkBrush.class, "gc", "generatechunk"); + brushManager.registerSniperBrush(RingBrush.class, "ri", "ring"); + brushManager.registerSniperBrush(Rot2DBrush.class, "rot2", "rotation2d"); + brushManager.registerSniperBrush(Rot2DvertBrush.class, "rot2v", "rotation2dvertical"); + brushManager.registerSniperBrush(Rot3DBrush.class, "rot3", "rotation3d"); + brushManager.registerSniperBrush(RulerBrush.class, "r", "ruler"); + brushManager.registerSniperBrush(ScannerBrush.class, "sc", "scanner"); + brushManager.registerSniperBrush(SetBrush.class, "set"); + brushManager.registerSniperBrush(SetRedstoneFlipBrush.class, "setrf", "setredstoneflip"); + brushManager.registerSniperBrush(ShellBallBrush.class, "shb", "shellball"); + brushManager.registerSniperBrush(ShellSetBrush.class, "shs", "shellset"); + brushManager.registerSniperBrush(ShellVoxelBrush.class, "shv", "shellvoxel"); + brushManager.registerSniperBrush(SignOverwriteBrush.class, "sio", "signoverwriter"); + brushManager.registerSniperBrush(SnipeBrush.class, "s", "snipe"); + brushManager.registerSniperBrush(SnowConeBrush.class, "snow", "snowcone"); + brushManager.registerSniperBrush(SpiralStaircaseBrush.class, "sstair", "spiralstaircase"); + brushManager.registerSniperBrush(SplatterBallBrush.class, "sb", "splatball"); + brushManager.registerSniperBrush(SplatterDiscBrush.class, "sd", "splatdisc"); + brushManager.registerSniperBrush(SplatterOverlayBrush.class, "sover", "splatteroverlay"); + brushManager.registerSniperBrush(SplatterVoxelBrush.class, "sv", "splattervoxel"); + brushManager.registerSniperBrush(SplatterDiscBrush.class, "svd", "splatvoxeldisc"); + brushManager.registerSniperBrush(SplineBrush.class, "sp", "spline"); + brushManager.registerSniperBrush(StencilBrush.class, "st", "stencil"); + brushManager.registerSniperBrush(StencilListBrush.class, "sl", "stencillist"); + brushManager.registerSniperBrush(ThreePointCircleBrush.class, "tpc", "threepointcircle"); + brushManager.registerSniperBrush(TreeSnipeBrush.class, "t", "tree", "treesnipe"); + brushManager.registerSniperBrush(TriangleBrush.class, "tri", "triangle"); + brushManager.registerSniperBrush(UnderlayBrush.class, "under", "underlay"); + brushManager.registerSniperBrush(VoltMeterBrush.class, "volt", "voltmeter"); + brushManager.registerSniperBrush(VoxelBrush.class, "v", "voxel"); + brushManager.registerSniperBrush(VoxelDiscBrush.class, "vd", "voxeldisc"); + brushManager.registerSniperBrush(VoxelDiscFaceBrush.class, "vdf", "voxeldiscface"); + brushManager.registerSniperBrush(WarpBrush.class, "w", "warp"); + } + + public void setupCommand(final String label, final FaweCommand cmd) { + this.getCommand(label).setExecutor(new BukkitCommand(cmd)); + } + +} diff --git a/favs/src/main/java/com/thevoxelbox/voxelsniper/VoxelSniperConfiguration.java b/favs/src/main/java/com/thevoxelbox/voxelsniper/VoxelSniperConfiguration.java new file mode 100644 index 000000000..3b226a414 --- /dev/null +++ b/favs/src/main/java/com/thevoxelbox/voxelsniper/VoxelSniperConfiguration.java @@ -0,0 +1,110 @@ +package com.thevoxelbox.voxelsniper; + +import com.google.common.base.Preconditions; +import org.bukkit.configuration.file.FileConfiguration; + +import java.util.List; + +/** + * Configuration storage defining global configurations for VoxelSniper. + */ +public class VoxelSniperConfiguration +{ + public static final String CONFIG_IDENTIFIER_LITESNIPER_MAX_BRUSH_SIZE = "litesniper-max-brush-size"; + public static final String CONFIG_IDENTIFIER_UNDO_CACHE_SIZE = "undo-cache-size"; + public static final String CONFIG_IDENTIFIER_LITESNIPER_RESTRICTED_ITEMS = "litesniper-restricted-items"; + public static final String CONFIG_IDENTIFIER_MESSAGE_ON_LOGIN_ENABLED = "message-on-login-enabled"; + public static final int DEFAULT_LITESNIPER_MAX_BRUSH_SIZE = 5; + public static final int DEFAULT_UNDO_CACHE_SIZE = 20; + public static final boolean DEFAULT_MESSAGE_ON_LOGIN_ENABLED = true; + private FileConfiguration configuration; + + /** + * @param configuration Configuration that is going to be used. + */ + public VoxelSniperConfiguration(FileConfiguration configuration) + { + this.configuration = configuration; + } + + /** + * Returns the maximum amount of snipes stored in the undo cache of snipers. + * + * @return the maximum amount of snipes stored in the undo cache of snipers + */ + public int getUndoCacheSize() + { + return configuration.getInt(CONFIG_IDENTIFIER_UNDO_CACHE_SIZE, DEFAULT_UNDO_CACHE_SIZE); + } + + /** + * Set the maximum amount of snipes stored in the undo cache of snipers. + * + * @param size size of undo cache + */ + public void setUndoCacheSize(int size) + { + configuration.set(CONFIG_IDENTIFIER_UNDO_CACHE_SIZE, size); + } + + /** + * Returns maximum size of brushes that LiteSnipers can use. + * + * @return maximum size + */ + public int getLiteSniperMaxBrushSize() + { + return configuration.getInt(CONFIG_IDENTIFIER_LITESNIPER_MAX_BRUSH_SIZE, DEFAULT_LITESNIPER_MAX_BRUSH_SIZE); + } + + /** + * Set maximum size of brushes that LiteSnipers can use. + * + * @param size maximum size + */ + public void setLiteSniperMaxBrushSize(int size) + { + configuration.set(CONFIG_IDENTIFIER_LITESNIPER_MAX_BRUSH_SIZE, size); + } + + /** + * Returns List of restricted Litesniper Items. + * + * @return List of restricted Litesniper Items + */ + public List getLiteSniperRestrictedItems() + { + return configuration.getIntegerList(CONFIG_IDENTIFIER_LITESNIPER_RESTRICTED_ITEMS); + } + + /** + * Set new list of restricted Litesniper Items. + * + * @param restrictedItems List of restricted Litesniper Items + */ + public void setLitesniperRestrictedItems(List restrictedItems) + { + Preconditions.checkNotNull(restrictedItems, "Restricted items must be a list."); + configuration.set(CONFIG_IDENTIFIER_LITESNIPER_RESTRICTED_ITEMS, restrictedItems); + } + + /** + * Returns if the login message is enabled. + * + * @return true if message on login is enabled, false otherwise. + */ + public boolean isMessageOnLoginEnabled() + { + return configuration.getBoolean(CONFIG_IDENTIFIER_MESSAGE_ON_LOGIN_ENABLED, DEFAULT_MESSAGE_ON_LOGIN_ENABLED); + } + + /** + * Set the message on login to be enabled or disabled. + * + * @param enabled Message on Login enabled + */ + public void setMessageOnLoginEnabled(boolean enabled) + { + configuration.set(CONFIG_IDENTIFIER_MESSAGE_ON_LOGIN_ENABLED, enabled); + } +} diff --git a/favs/src/main/java/com/thevoxelbox/voxelsniper/VoxelSniperListener.java b/favs/src/main/java/com/thevoxelbox/voxelsniper/VoxelSniperListener.java new file mode 100644 index 000000000..88c85e5b2 --- /dev/null +++ b/favs/src/main/java/com/thevoxelbox/voxelsniper/VoxelSniperListener.java @@ -0,0 +1,138 @@ +package com.thevoxelbox.voxelsniper; + +import com.thevoxelbox.voxelsniper.api.command.VoxelCommand; +import com.thevoxelbox.voxelsniper.command.*; +import org.bukkit.ChatColor; +import org.bukkit.entity.Player; +import org.bukkit.event.EventHandler; +import org.bukkit.event.Listener; +import org.bukkit.event.player.PlayerInteractEvent; +import org.bukkit.event.player.PlayerJoinEvent; + +import java.util.HashMap; +import java.util.Map; + +/** + * @author Voxel + */ +public class VoxelSniperListener implements Listener +{ + + private static final String SNIPER_PERMISSION = "voxelsniper.sniper"; + private final VoxelSniper plugin; + private Map commands = new HashMap(); + + /** + * @param plugin + */ + public VoxelSniperListener(final VoxelSniper plugin) + { + this.plugin = plugin; + addCommand(new VoxelBrushCommand(plugin)); + addCommand(new VoxelBrushToolCommand(plugin)); + addCommand(new VoxelCenterCommand(plugin)); + addCommand(new VoxelChunkCommand(plugin)); + addCommand(new VoxelDefaultCommand(plugin)); + addCommand(new VoxelGoToCommand(plugin)); + addCommand(new VoxelHeightCommand(plugin)); + addCommand(new VoxelInkCommand(plugin)); + addCommand(new VoxelInkReplaceCommand(plugin)); + addCommand(new VoxelListCommand(plugin)); + addCommand(new VoxelPaintCommand(plugin)); + addCommand(new VoxelPerformerCommand(plugin)); + addCommand(new VoxelReplaceCommand(plugin)); + addCommand(new VoxelSniperCommand(plugin)); + addCommand(new VoxelUndoCommand(plugin)); + addCommand(new VoxelUndoUserCommand(plugin)); + addCommand(new VoxelVoxelCommand(plugin)); + } + + private void addCommand(final VoxelCommand command) + { + this.commands.put(command.getIdentifier().toLowerCase(), command); + } + + /** + * @param player + * @param split + * @param command + * @return boolean Success. + */ + public boolean onCommand(final Player player, final String[] split, final String command) + { + VoxelCommand found = this.commands.get(command.toLowerCase()); + if (found == null) + { + return false; + } + + if (!hasPermission(found, player)) + { + player.sendMessage(ChatColor.RED + "Insufficient Permissions."); + return true; + } + + return found.onCommand(player, split); + } + + private boolean hasPermission(final VoxelCommand command, final Player player) + { + if (command == null || player == null) + { + // Just a usual check for nulls + return false; + } + else if (command.getPermission() == null || command.getPermission().isEmpty()) + { + // This is for commands that do not require a permission node to be executed + return true; + } + else + { + // Should utilize Vault for permission checks if available + return player.hasPermission(command.getPermission()); + } + } + + /** + * @param event + */ + @EventHandler(ignoreCancelled = false) + public final void onPlayerInteract(final PlayerInteractEvent event) + { + Player player = event.getPlayer(); + + if (!player.hasPermission(SNIPER_PERMISSION)) + { + return; + } + + try + { + Sniper sniper = plugin.getSniperManager().getSniperForPlayer(player); + if (sniper.isEnabled() && sniper.snipe(event.getAction(), event.getMaterial(), event.getClickedBlock(), event.getBlockFace())) + { + event.setCancelled(true); + } + } + catch (final Throwable ignored) + { + ignored.printStackTrace(); + } + } + + /** + * @param event + */ + @EventHandler + public final void onPlayerJoin(final PlayerJoinEvent event) + { + Player player = event.getPlayer(); + Sniper sniper = plugin.getSniperManager().getSniperForPlayer(player); + + if (player.hasPermission(SNIPER_PERMISSION) && plugin.getVoxelSniperConfiguration().isMessageOnLoginEnabled()) + { + sniper.displayInfo(); + } + } +} diff --git a/favs/src/main/java/com/thevoxelbox/voxelsniper/api/command/VoxelCommand.java b/favs/src/main/java/com/thevoxelbox/voxelsniper/api/command/VoxelCommand.java new file mode 100644 index 000000000..3908d3e54 --- /dev/null +++ b/favs/src/main/java/com/thevoxelbox/voxelsniper/api/command/VoxelCommand.java @@ -0,0 +1,81 @@ +package com.thevoxelbox.voxelsniper.api.command; + +import com.thevoxelbox.voxelsniper.VoxelSniper; +import org.bukkit.entity.Player; + +public abstract class VoxelCommand +{ + + private final String name; + private String description = ""; + private String permission = ""; + private String identifier = ""; + protected final VoxelSniper plugin; + + public VoxelCommand(String name, final VoxelSniper plugin) + { + this.name = name; + this.plugin = plugin; + } + + public abstract boolean onCommand(final Player player, final String[] args); + + public String getDescription() + { + return description; + } + + public String getPermission() + { + return this.permission; + } + + public String getName() + { + return this.name; + } + + public void setDescription(String description) + { + this.description = description; + } + + public void setPermission(String permission) + { + this.permission = permission; + } + + public String getIdentifier() + { + return this.identifier; + } + + public void setIdentifier(String identifier) + { + this.identifier = identifier; + } + + public boolean isIdentifier(String offered) + { + return this.identifier.isEmpty() || this.identifier.equalsIgnoreCase(offered); + } + + /** + * Padds an empty String to the front of the array. + * + * @param args Array to pad empty string in front of + * @return padded array + */ + protected String[] hackTheArray(String[] args) + { + String[] returnValue = new String[args.length + 1]; + returnValue[0] = ""; + for (int i = 0, argsLength = args.length; i < argsLength; i++) + { + String arg = args[i]; + returnValue[i + 1] = arg; + } + return returnValue; + } + +} diff --git a/favs/src/main/java/com/thevoxelbox/voxelsniper/brush/BallBrush.java b/favs/src/main/java/com/thevoxelbox/voxelsniper/brush/BallBrush.java new file mode 100644 index 000000000..e8daed35b --- /dev/null +++ b/favs/src/main/java/com/thevoxelbox/voxelsniper/brush/BallBrush.java @@ -0,0 +1,146 @@ +package com.thevoxelbox.voxelsniper.brush; + +import com.boydti.fawe.bukkit.wrapper.AsyncBlock; +import com.thevoxelbox.voxelsniper.Message; +import com.thevoxelbox.voxelsniper.SnipeData; +import com.thevoxelbox.voxelsniper.brush.perform.PerformBrush; + +import org.bukkit.ChatColor; +import org.bukkit.block.Block; + +/** + * A brush that creates a solid ball. + * http://www.voxelwiki.com/minecraft/Voxelsniper#The_Ball_Brush + * + * @author Piotr + */ +public class BallBrush extends PerformBrush +{ + public static final double TRUE_CIRCLE_ON_VALUE = 0.5; + public static final int TRUE_CIRCLE_OFF_VALUE = 0; + private double trueCircle = 0; + + /** + * + */ + public BallBrush() + { + this.setName("Ball"); + } + + private void ball(final SnipeData v, AsyncBlock targetBlock) + { + final int brushSize = v.getBrushSize(); + final double brushSizeSquared = Math.pow(brushSize + this.trueCircle, 2); + + int blockPositionX = targetBlock.getX(); + int blockPositionY = targetBlock.getY(); + int blockPositionZ = targetBlock.getZ(); + this.current.perform(targetBlock); + + for (int z = 1; z <= brushSize; z++) + { + final double zSquared = Math.pow(z, 2); + + this.current.perform(this.clampY(blockPositionX + z, blockPositionY, blockPositionZ)); + this.current.perform(this.clampY(blockPositionX - z, blockPositionY, blockPositionZ)); + this.current.perform(this.clampY(blockPositionX, blockPositionY + z, blockPositionZ)); + this.current.perform(this.clampY(blockPositionX, blockPositionY - z, blockPositionZ)); + this.current.perform(this.clampY(blockPositionX, blockPositionY, blockPositionZ + z)); + this.current.perform(this.clampY(blockPositionX, blockPositionY, blockPositionZ - z)); + + for (int x = 1; x <= brushSize; x++) + { + final double xSquared = Math.pow(x, 2); + + if (zSquared + xSquared <= brushSizeSquared) + { + this.current.perform(this.clampY(blockPositionX + z, blockPositionY, blockPositionZ + x)); + this.current.perform(this.clampY(blockPositionX + z, blockPositionY, blockPositionZ - x)); + this.current.perform(this.clampY(blockPositionX - z, blockPositionY, blockPositionZ + x)); + this.current.perform(this.clampY(blockPositionX - z, blockPositionY, blockPositionZ - x)); + this.current.perform(this.clampY(blockPositionX + z, blockPositionY + x, blockPositionZ)); + this.current.perform(this.clampY(blockPositionX + z, blockPositionY - x, blockPositionZ)); + this.current.perform(this.clampY(blockPositionX - z, blockPositionY + x, blockPositionZ)); + this.current.perform(this.clampY(blockPositionX - z, blockPositionY - x, blockPositionZ)); + this.current.perform(this.clampY(blockPositionX, blockPositionY + z, blockPositionZ + x)); + this.current.perform(this.clampY(blockPositionX, blockPositionY + z, blockPositionZ - x)); + this.current.perform(this.clampY(blockPositionX, blockPositionY - z, blockPositionZ + x)); + this.current.perform(this.clampY(blockPositionX, blockPositionY - z, blockPositionZ - x)); + } + + for (int y = 1; y <= brushSize; y++) + { + if ((xSquared + Math.pow(y, 2) + zSquared) <= brushSizeSquared) + { + this.current.perform(this.clampY(blockPositionX + x, blockPositionY + y, blockPositionZ + z)); + this.current.perform(this.clampY(blockPositionX + x, blockPositionY + y, blockPositionZ - z)); + this.current.perform(this.clampY(blockPositionX - x, blockPositionY + y, blockPositionZ + z)); + this.current.perform(this.clampY(blockPositionX - x, blockPositionY + y, blockPositionZ - z)); + this.current.perform(this.clampY(blockPositionX + x, blockPositionY - y, blockPositionZ + z)); + this.current.perform(this.clampY(blockPositionX + x, blockPositionY - y, blockPositionZ - z)); + this.current.perform(this.clampY(blockPositionX - x, blockPositionY - y, blockPositionZ + z)); + this.current.perform(this.clampY(blockPositionX - x, blockPositionY - y, blockPositionZ - z)); + } + } + } + } + + v.owner().storeUndo(this.current.getUndo()); + } + + @Override + protected final void arrow(final SnipeData v) + { + this.ball(v, this.getTargetBlock()); + } + + @Override + protected final void powder(final SnipeData v) + { + this.ball(v, this.getLastBlock()); + } + + @Override + public final void info(final Message vm) + { + vm.brushName(this.getName()); + vm.size(); + } + + @Override + public final void parameters(final String[] par, final SnipeData v) + { + for (int i = 1; i < par.length; i++) + { + final String parameter = par[i]; + + if (parameter.equalsIgnoreCase("info")) + { + v.sendMessage(ChatColor.GOLD + "Ball Brush Parameters:"); + v.sendMessage(ChatColor.AQUA + "/b b true -- will use a true sphere algorithm instead of the skinnier version with classic sniper nubs. /b b false will switch back. (false is default)"); + return; + } + else if (parameter.startsWith("true")) + { + this.trueCircle = TRUE_CIRCLE_ON_VALUE; + v.sendMessage(ChatColor.AQUA + "True circle mode ON."); + } + else if (parameter.startsWith("false")) + { + this.trueCircle = TRUE_CIRCLE_OFF_VALUE; + v.sendMessage(ChatColor.AQUA + "True circle mode OFF."); + } + else + { + v.sendMessage(ChatColor.RED + "Invalid brush parameters! use the info parameter to display parameter info."); + } + } + } + + @Override + public String getPermissionNode() + { + return "voxelsniper.brush.ball"; + } +} diff --git a/favs/src/main/java/com/thevoxelbox/voxelsniper/brush/BiomeBrush.java b/favs/src/main/java/com/thevoxelbox/voxelsniper/brush/BiomeBrush.java new file mode 100644 index 000000000..788574e01 --- /dev/null +++ b/favs/src/main/java/com/thevoxelbox/voxelsniper/brush/BiomeBrush.java @@ -0,0 +1,126 @@ +package com.thevoxelbox.voxelsniper.brush; + +import com.thevoxelbox.voxelsniper.Message; +import com.thevoxelbox.voxelsniper.SnipeData; +import org.bukkit.ChatColor; +import org.bukkit.block.Biome; +import org.bukkit.block.Block; + +/** + * + */ +public class BiomeBrush extends Brush +{ + private Biome selectedBiome = Biome.PLAINS; + + /** + * + */ + public BiomeBrush() + { + this.setName("Biome (/b biome [Biome Name])"); + } + + private void biome(final SnipeData v) + { + final int brushSize = v.getBrushSize(); + final double brushSizeSquared = Math.pow(brushSize, 2); + + for (int x = -brushSize; x <= brushSize; x++) + { + final double xSquared = Math.pow(x, 2); + + for (int z = -brushSize; z <= brushSize; z++) + { + if ((xSquared + Math.pow(z, 2)) <= brushSizeSquared) + { + this.getWorld().setBiome(this.getTargetBlock().getX() + x, this.getTargetBlock().getZ() + z, this.selectedBiome); + } + } + } + + final Block block1 = this.getWorld().getBlockAt(this.getTargetBlock().getX() - brushSize, 0, this.getTargetBlock().getZ() - brushSize); + final Block block2 = this.getWorld().getBlockAt(this.getTargetBlock().getX() + brushSize, 0, this.getTargetBlock().getZ() + brushSize); + + final int lowChunkX = (block1.getX() <= block2.getX()) ? block1.getChunk().getX() : block2.getChunk().getX(); + final int lowChunkZ = (block1.getZ() <= block2.getZ()) ? block1.getChunk().getZ() : block2.getChunk().getZ(); + final int highChunkX = (block1.getX() >= block2.getX()) ? block1.getChunk().getX() : block2.getChunk().getX(); + final int highChunkZ = (block1.getZ() >= block2.getZ()) ? block1.getChunk().getZ() : block2.getChunk().getZ(); + + for (int x = lowChunkX; x <= highChunkX; x++) + { + for (int z = lowChunkZ; z <= highChunkZ; z++) + { + this.getWorld().refreshChunk(x, z); + } + } + } + + @Override + protected final void arrow(final SnipeData v) + { + this.biome(v); + } + + @Override + protected final void powder(final SnipeData v) + { + this.biome(v); + } + + @Override + public final void info(final Message vm) + { + vm.brushName(this.getName()); + vm.size(); + vm.custom(ChatColor.GOLD + "Currently selected biome type: " + ChatColor.DARK_GREEN + this.selectedBiome.name()); + } + + @Override + public final void parameters(final String[] args, final SnipeData v) + { + if (args[1].equalsIgnoreCase("info")) + { + v.sendMessage(ChatColor.GOLD + "Biome Brush Parameters:"); + String availableBiomes = ""; + + for (final Biome biome : Biome.values()) + { + if (availableBiomes.isEmpty()) + { + availableBiomes = ChatColor.DARK_GREEN + biome.name(); + continue; + } + + availableBiomes += ChatColor.RED + ", " + ChatColor.DARK_GREEN + biome.name(); + + } + v.sendMessage(ChatColor.DARK_BLUE + "Available biomes: " + availableBiomes); + } + else + { + // allows biome names with spaces in their name + String biomeName = args[1]; + for (int i = 2; i < args.length; i++) + { + biomeName += " " + args[i]; + } + + for (final Biome biome : Biome.values()) + { + if (biome.name().equalsIgnoreCase(biomeName)) + { + this.selectedBiome = biome; + break; + } + } + v.sendMessage(ChatColor.GOLD + "Currently selected biome type: " + ChatColor.DARK_GREEN + this.selectedBiome.name()); + } + } + + @Override + public String getPermissionNode() + { + return "voxelsniper.brush.biome"; + } +} diff --git a/favs/src/main/java/com/thevoxelbox/voxelsniper/brush/BlendBallBrush.java b/favs/src/main/java/com/thevoxelbox/voxelsniper/brush/BlendBallBrush.java new file mode 100644 index 000000000..1da2ec01d --- /dev/null +++ b/favs/src/main/java/com/thevoxelbox/voxelsniper/brush/BlendBallBrush.java @@ -0,0 +1,162 @@ +package com.thevoxelbox.voxelsniper.brush; + +import com.sk89q.worldedit.world.block.BlockTypes; +import com.thevoxelbox.voxelsniper.SnipeData; +import com.thevoxelbox.voxelsniper.Undo; + +import org.bukkit.ChatColor; +import org.bukkit.Material; + +/** + * http://www.voxelwiki.com/minecraft/Voxelsniper#Blend_Brushes + */ +public class BlendBallBrush extends BlendBrushBase +{ + /** + * + */ + public BlendBallBrush() + { + this.setName("Blend Ball"); + } + + @SuppressWarnings("deprecation") + @Override + protected final void blend(final SnipeData v) + { + final int brushSize = v.getBrushSize(); + final int brushSizeDoubled = 2 * brushSize; + // Array that holds the original materials plus a buffer + final int[][][] oldMaterials = new int[2 * (brushSize + 1) + 1][2 * (brushSize + 1) + 1][2 * (brushSize + 1) + 1]; + // Array that holds the blended materials + final int[][][] newMaterials = new int[brushSizeDoubled + 1][brushSizeDoubled + 1][brushSizeDoubled + 1]; + + // Log current materials into oldmats + for (int x = 0; x <= 2 * (brushSize + 1); x++) + { + for (int y = 0; y <= 2 * (brushSize + 1); y++) + { + for (int z = 0; z <= 2 * (brushSize + 1); z++) + { + oldMaterials[x][y][z] = this.getBlockIdAt(this.getTargetBlock().getX() - brushSize - 1 + x, this.getTargetBlock().getY() - brushSize - 1 + y, this.getTargetBlock().getZ() - brushSize - 1 + z); + } + } + } + + // Log current materials into newmats + for (int x = 0; x <= brushSizeDoubled; x++) + { + for (int y = 0; y <= brushSizeDoubled; y++) + { + for (int z = 0; z <= brushSizeDoubled; z++) + { + newMaterials[x][y][z] = oldMaterials[x + 1][y + 1][z + 1]; + } + } + } + + // Blend materials + for (int x = 0; x <= brushSizeDoubled; x++) + { + for (int y = 0; y <= brushSizeDoubled; y++) + { + for (int z = 0; z <= brushSizeDoubled; z++) + { + final int[] materialFrequency = new int[BlockTypes.size()]; // Array that tracks frequency of materials neighboring given block + int modeMatCount = 0; + int modeMatId = 0; + boolean tiecheck = true; + + for (int m = -1; m <= 1; m++) + { + for (int n = -1; n <= 1; n++) + { + for (int o = -1; o <= 1; o++) + { + if (!(m == 0 && n == 0 && o == 0)) + { + materialFrequency[oldMaterials[x + 1 + m][y + 1 + n][z + 1 + o]]++; + } + } + } + } + + // Find most common neighboring material. + for (BlockTypes type : BlockTypes.values) + { + int i = type.getInternalId(); + if (materialFrequency[i] > modeMatCount && !(this.excludeAir && type.getMaterial().isAir()) && !(this.excludeWater && (type == BlockTypes.WATER))) + { + modeMatCount = materialFrequency[i]; + modeMatId = i; + } + } + // Make sure there'world not a tie for most common + for (int i = 0; i < modeMatId; i++) + { + BlockTypes type = BlockTypes.get(i); + if (materialFrequency[i] == modeMatCount && !(this.excludeAir && type.getMaterial().isAir()) && !(this.excludeWater && (type == BlockTypes.WATER))) + { + tiecheck = false; + } + } + + // Record most common neighbor material for this block + if (tiecheck) + { + newMaterials[x][y][z] = modeMatId; + } + } + } + } + + final Undo undo = new Undo(); + final double rSquared = Math.pow(brushSize + 1, 2); + + // Make the changes + for (int x = brushSizeDoubled; x >= 0; x--) + { + final double xSquared = Math.pow(x - brushSize - 1, 2); + + for (int y = 0; y <= brushSizeDoubled; y++) + { + final double ySquared = Math.pow(y - brushSize - 1, 2); + + for (int z = brushSizeDoubled; z >= 0; z--) + { + if (xSquared + ySquared + Math.pow(z - brushSize - 1, 2) <= rSquared) + { + if (!(this.excludeAir && BlockTypes.get(newMaterials[x][y][z]).getMaterial().isAir()) && !(this.excludeWater && (newMaterials[x][y][z] == BlockTypes.WATER.getInternalId()))) + { + if (this.getBlockIdAt(this.getTargetBlock().getX() - brushSize + x, this.getTargetBlock().getY() - brushSize + y, this.getTargetBlock().getZ() - brushSize + z) != newMaterials[x][y][z]) + { + undo.put(this.clampY(this.getTargetBlock().getX() - brushSize + x, this.getTargetBlock().getY() - brushSize + y, this.getTargetBlock().getZ() - brushSize + z)); + } + this.setBlockIdAt(this.getTargetBlock().getZ() - brushSize + z, this.getTargetBlock().getX() - brushSize + x, this.getTargetBlock().getY() - brushSize + y, newMaterials[x][y][z]); + } + } + } + } + } + v.owner().storeUndo(undo); + } + + @Override + public final void parameters(final String[] par, final SnipeData v) + { + if (par[1].equalsIgnoreCase("info")) + { + v.sendMessage(ChatColor.GOLD + "Blend Ball Parameters:"); + v.sendMessage(ChatColor.AQUA + "/b bb water -- toggle include or exclude (default: exclude) water"); + return; + } + + super.parameters(par, v); + } + + @Override + public String getPermissionNode() + { + return "voxelsniper.brush.blendball"; + } +} diff --git a/favs/src/main/java/com/thevoxelbox/voxelsniper/brush/BlendBrushBase.java b/favs/src/main/java/com/thevoxelbox/voxelsniper/brush/BlendBrushBase.java new file mode 100644 index 000000000..324df9c4a --- /dev/null +++ b/favs/src/main/java/com/thevoxelbox/voxelsniper/brush/BlendBrushBase.java @@ -0,0 +1,93 @@ +package com.thevoxelbox.voxelsniper.brush; + +import com.bekvon.bukkit.residence.commands.material; +import com.sk89q.worldedit.world.block.BlockType; +import com.sk89q.worldedit.world.block.BlockTypes; +import com.thevoxelbox.voxelsniper.Message; +import com.thevoxelbox.voxelsniper.SnipeData; + +import org.bukkit.ChatColor; +import org.bukkit.Material; + +/** + * @author Monofraps + */ +@SuppressWarnings("deprecation") +public abstract class BlendBrushBase extends Brush +{ + protected boolean excludeAir = true; + protected boolean excludeWater = true; + + /** + * @param v + */ + protected abstract void blend(final SnipeData v); + + @Override + protected final void arrow(final SnipeData v) + { + this.excludeAir = false; + this.blend(v); + } + + @Override + protected final void powder(final SnipeData v) + { + this.excludeAir = true; + this.blend(v); + } + + @Override + public final void info(final Message vm) + { + vm.brushName(this.getName()); + vm.size(); + vm.voxel(); + vm.custom(ChatColor.BLUE + "Water Mode: " + (this.excludeWater ? "exclude" : "include")); + } + + @Override + public void parameters(final String[] par, final SnipeData v) + { + for (int i = 1; i < par.length; ++i) + { + if (par[i].equalsIgnoreCase("water")) + { + this.excludeWater = !this.excludeWater; + v.sendMessage(ChatColor.AQUA + "Water Mode: " + (this.excludeWater ? "exclude" : "include")); + } + } + } + + /** + * @return + */ + protected final boolean isExcludeAir() + { + return excludeAir; + } + + /** + * @param excludeAir + */ + protected final void setExcludeAir(boolean excludeAir) + { + this.excludeAir = excludeAir; + } + + /** + * @return + */ + protected final boolean isExcludeWater() + { + return excludeWater; + } + + /** + * @param excludeWater + */ + protected final void setExcludeWater(boolean excludeWater) + { + this.excludeWater = excludeWater; + } +} diff --git a/favs/src/main/java/com/thevoxelbox/voxelsniper/brush/BlendDiscBrush.java b/favs/src/main/java/com/thevoxelbox/voxelsniper/brush/BlendDiscBrush.java new file mode 100644 index 000000000..75130f9e9 --- /dev/null +++ b/favs/src/main/java/com/thevoxelbox/voxelsniper/brush/BlendDiscBrush.java @@ -0,0 +1,143 @@ +package com.thevoxelbox.voxelsniper.brush; + +import com.sk89q.worldedit.world.block.BlockTypes; +import com.thevoxelbox.voxelsniper.SnipeData; +import com.thevoxelbox.voxelsniper.Undo; + +import org.bukkit.ChatColor; +import org.bukkit.Material; + +/** + * http://www.voxelwiki.com/minecraft/Voxelsniper#Blend_Brushes + */ +public class BlendDiscBrush extends BlendBrushBase +{ + /** + * + */ + public BlendDiscBrush() + { + this.setName("Blend Disc"); + } + + @SuppressWarnings("deprecation") + @Override + protected final void blend(final SnipeData v) + { + final int brushSize = v.getBrushSize(); + final int brushSizeDoubled = 2 * brushSize; + final int[][] oldMaterials = new int[2 * (brushSize + 1) + 1][2 * (brushSize + 1) + 1]; // Array that holds the original materials plus a buffer + final int[][] newMaterials = new int[brushSizeDoubled + 1][brushSizeDoubled + 1]; // Array that holds the blended materials + + // Log current materials into oldmats + for (int x = 0; x <= 2 * (brushSize + 1); x++) + { + for (int z = 0; z <= 2 * (brushSize + 1); z++) + { + oldMaterials[x][z] = this.getBlockIdAt(this.getTargetBlock().getX() - brushSize - 1 + x, this.getTargetBlock().getY(), this.getTargetBlock().getZ() - brushSize - 1 + z); + } + } + + // Log current materials into newmats + for (int x = 0; x <= brushSizeDoubled; x++) + { + for (int z = 0; z <= brushSizeDoubled; z++) + { + newMaterials[x][z] = oldMaterials[x + 1][z + 1]; + } + } + + // Blend materials + for (int x = 0; x <= brushSizeDoubled; x++) + { + for (int z = 0; z <= brushSizeDoubled; z++) + { + final int[] materialFrequency = new int[BlockTypes.size()]; // Array that tracks frequency of materials neighboring given block + int modeMatCount = 0; + int modeMatId = 0; + boolean tiecheck = true; + + for (int m = -1; m <= 1; m++) + { + for (int n = -1; n <= 1; n++) + { + if (!(m == 0 && n == 0)) + { + materialFrequency[oldMaterials[x + 1 + m][z + 1 + n]]++; + } + } + } + + // Find most common neighboring material. + for (BlockTypes type : BlockTypes.values) + { + int i = type.getInternalId(); + if (materialFrequency[i] > modeMatCount && !(this.excludeAir && type.getMaterial().isAir()) && !(this.excludeWater && (type == BlockTypes.WATER))) + { + modeMatCount = materialFrequency[i]; + modeMatId = i; + } + } + // Make sure there'world not a tie for most common + for (int i = 0; i < modeMatId; i++) + { + BlockTypes type = BlockTypes.get(i); + if (materialFrequency[i] == modeMatCount && !(this.excludeAir && type.getMaterial().isAir()) && !(this.excludeWater && (type == BlockTypes.WATER))) + { + tiecheck = false; + } + } + + // Record most common neighbor material for this block + if (tiecheck) + { + newMaterials[x][z] = modeMatId; + } + } + } + + final Undo undo = new Undo(); + final double rSquared = Math.pow(brushSize + 1, 2); + + // Make the changes + for (int x = brushSizeDoubled; x >= 0; x--) + { + final double xSquared = Math.pow(x - brushSize - 1, 2); + + for (int z = brushSizeDoubled; z >= 0; z--) + { + if (xSquared + Math.pow(z - brushSize - 1, 2) <= rSquared) + { + if (!(this.excludeAir && BlockTypes.get(newMaterials[x][z]).getMaterial().isAir()) && !(this.excludeWater && (newMaterials[x][z] == BlockTypes.WATER.getInternalId()))) + { + if (this.getBlockIdAt(this.getTargetBlock().getX() - brushSize + x, this.getTargetBlock().getY(), this.getTargetBlock().getZ() - brushSize + z) != newMaterials[x][z]) + { + undo.put(this.clampY(this.getTargetBlock().getX() - brushSize + x, this.getTargetBlock().getY(), this.getTargetBlock().getZ() - brushSize + z)); + } + this.setBlockIdAt(this.getTargetBlock().getZ() - brushSize + z, this.getTargetBlock().getX() - brushSize + x, this.getTargetBlock().getY(), newMaterials[x][z]); + } + } + } + } + v.owner().storeUndo(undo); + } + + @Override + public final void parameters(final String[] par, final SnipeData v) + { + if (par[1].equalsIgnoreCase("info")) + { + v.sendMessage(ChatColor.GOLD + "Blend Disc Parameters:"); + v.sendMessage(ChatColor.AQUA + "/b bd water -- toggle include or exclude (default) water"); + return; + } + + super.parameters(par, v); + } + + @Override + public String getPermissionNode() + { + return "voxelsniper.brush.blenddisc"; + } +} diff --git a/favs/src/main/java/com/thevoxelbox/voxelsniper/brush/BlendVoxelBrush.java b/favs/src/main/java/com/thevoxelbox/voxelsniper/brush/BlendVoxelBrush.java new file mode 100644 index 000000000..30cf38268 --- /dev/null +++ b/favs/src/main/java/com/thevoxelbox/voxelsniper/brush/BlendVoxelBrush.java @@ -0,0 +1,155 @@ +package com.thevoxelbox.voxelsniper.brush; + +import com.sk89q.worldedit.world.block.BlockTypes; +import com.thevoxelbox.voxelsniper.SnipeData; +import com.thevoxelbox.voxelsniper.Undo; + +import org.bukkit.ChatColor; +import org.bukkit.Material; + +/** + * http://www.voxelwiki.com/minecraft/Voxelsniper#Blend_Brushes + */ +public class BlendVoxelBrush extends BlendBrushBase +{ + /** + * + */ + public BlendVoxelBrush() + { + this.setName("Blend Voxel"); + } + + @SuppressWarnings("deprecation") + @Override + protected final void blend(final SnipeData v) + { + final int brushSize = v.getBrushSize(); + final int brushSizeDoubled = 2 * brushSize; + // Array that holds the original materials plus a buffer + final int[][][] oldMaterials = new int[2 * (brushSize + 1) + 1][2 * (brushSize + 1) + 1][2 * (brushSize + 1) + 1]; + // Array that holds the blended materials + final int[][][] newMaterials = new int[brushSizeDoubled + 1][brushSizeDoubled + 1][brushSizeDoubled + 1]; + + // Log current materials into oldmats + for (int x = 0; x <= 2 * (brushSize + 1); x++) + { + for (int y = 0; y <= 2 * (brushSize + 1); y++) + { + for (int z = 0; z <= 2 * (brushSize + 1); z++) + { + oldMaterials[x][y][z] = this.getBlockIdAt(this.getTargetBlock().getX() - brushSize - 1 + x, this.getTargetBlock().getY() - brushSize - 1 + y, this.getTargetBlock().getZ() - brushSize - 1 + z); + } + } + } + + // Log current materials into newmats + for (int x = 0; x <= brushSizeDoubled; x++) + { + for (int y = 0; y <= brushSizeDoubled; y++) + { + for (int z = 0; z <= brushSizeDoubled; z++) + { + newMaterials[x][y][z] = oldMaterials[x + 1][y + 1][z + 1]; + } + } + } + + // Blend materials + for (int x = 0; x <= brushSizeDoubled; x++) + { + for (int y = 0; y <= brushSizeDoubled; y++) + { + for (int z = 0; z <= brushSizeDoubled; z++) + { + final int[] materialFrequency = new int[BlockTypes.size()]; // Array that tracks frequency of materials neighboring given block + int modeMatCount = 0; + int modeMatId = 0; + boolean tiecheck = true; + + for (int m = -1; m <= 1; m++) + { + for (int n = -1; n <= 1; n++) + { + for (int o = -1; o <= 1; o++) + { + if (!(m == 0 && n == 0 && o == 0)) + { + materialFrequency[oldMaterials[x + 1 + m][y + 1 + n][z + 1 + o]]++; + } + } + } + } + + // Find most common neighboring material. + for (BlockTypes type : BlockTypes.values) + { + int i = type.getInternalId(); + if (materialFrequency[i] > modeMatCount && !(this.excludeAir && type.getMaterial().isAir()) && !(this.excludeWater && (type == BlockTypes.WATER))) + { + modeMatCount = materialFrequency[i]; + modeMatId = i; + } + } + // Make sure there'world not a tie for most common + for (int i = 0; i < modeMatId; i++) + { + BlockTypes type = BlockTypes.get(i); + if (materialFrequency[i] == modeMatCount && !(this.excludeAir && type.getMaterial().isAir()) && !(this.excludeWater && (type == BlockTypes.WATER))) + { + tiecheck = false; + } + } + + // Record most common neighbor material for this block + if (tiecheck) + { + newMaterials[x][y][z] = modeMatId; + } + } + } + } + + final Undo undo = new Undo(); + + // Make the changes + for (int x = brushSizeDoubled; x >= 0; x--) + { + for (int y = 0; y <= brushSizeDoubled; y++) + { + for (int z = brushSizeDoubled; z >= 0; z--) + { + if (!(this.excludeAir && BlockTypes.get(newMaterials[x][y][z]).getMaterial().isAir()) && !(this.excludeWater && (newMaterials[x][y][z] == BlockTypes.WATER.getInternalId()))) + { + if (this.getBlockIdAt(this.getTargetBlock().getX() - brushSize + x, this.getTargetBlock().getY() - brushSize + y, this.getTargetBlock().getZ() - brushSize + z) != newMaterials[x][y][z]) + { + undo.put(this.clampY(this.getTargetBlock().getX() - brushSize + x, this.getTargetBlock().getY() - brushSize + y, this.getTargetBlock().getZ() - brushSize + z)); + } + this.setBlockIdAt(this.getTargetBlock().getZ() - brushSize + z, this.getTargetBlock().getX() - brushSize + x, this.getTargetBlock().getY() - brushSize + y, newMaterials[x][y][z]); + + } + } + } + } + v.owner().storeUndo(undo); + } + + @Override + public final void parameters(final String[] par, final SnipeData v) + { + if (par[1].equalsIgnoreCase("info")) + { + v.sendMessage(ChatColor.GOLD + "Blend Voxel Parameters:"); + v.sendMessage(ChatColor.AQUA + "/b bv water -- toggle include or exclude (default) water"); + return; + } + + super.parameters(par, v); + } + + @Override + public String getPermissionNode() + { + return "voxelsniper.brush.blendvoxel"; + } +} diff --git a/favs/src/main/java/com/thevoxelbox/voxelsniper/brush/BlendVoxelDiscBrush.java b/favs/src/main/java/com/thevoxelbox/voxelsniper/brush/BlendVoxelDiscBrush.java new file mode 100644 index 000000000..56a670f0b --- /dev/null +++ b/favs/src/main/java/com/thevoxelbox/voxelsniper/brush/BlendVoxelDiscBrush.java @@ -0,0 +1,139 @@ +package com.thevoxelbox.voxelsniper.brush; + +import com.sk89q.worldedit.world.block.BlockTypes; +import com.thevoxelbox.voxelsniper.SnipeData; +import com.thevoxelbox.voxelsniper.Undo; + +import org.bukkit.ChatColor; +import org.bukkit.Material; + +/** + * http://www.voxelwiki.com/minecraft/Voxelsniper#Blend_Brushes + */ +public class BlendVoxelDiscBrush extends BlendBrushBase +{ + /** + * + */ + public BlendVoxelDiscBrush() + { + this.setName("Blend Voxel Disc"); + } + + @SuppressWarnings("deprecation") + @Override + protected final void blend(final SnipeData v) + { + final int brushSize = v.getBrushSize(); + final int brushSizeDoubled = 2 * brushSize; + final int[][] oldMaterials = new int[2 * (brushSize + 1) + 1][2 * (brushSize + 1) + 1]; // Array that holds the original materials plus a buffer + final int[][] newMaterials = new int[brushSizeDoubled + 1][brushSizeDoubled + 1]; // Array that holds the blended materials + + // Log current materials into oldmats + for (int x = 0; x <= 2 * (brushSize + 1); x++) + { + for (int z = 0; z <= 2 * (brushSize + 1); z++) + { + oldMaterials[x][z] = this.getBlockIdAt(this.getTargetBlock().getX() - brushSize - 1 + x, this.getTargetBlock().getY(), this.getTargetBlock().getZ() - brushSize - 1 + z); + } + } + + // Log current materials into newmats + for (int x = 0; x <= brushSizeDoubled; x++) + { + for (int z = 0; z <= brushSizeDoubled; z++) + { + newMaterials[x][z] = oldMaterials[x + 1][z + 1]; + } + } + + // Blend materials + for (int x = 0; x <= brushSizeDoubled; x++) + { + for (int z = 0; z <= brushSizeDoubled; z++) + { + final int[] materialFrequency = new int[BlockTypes.size()]; // Array that tracks frequency of materials neighboring given block + int modeMatCount = 0; + int modeMatId = 0; + boolean tiecheck = true; + + for (int m = -1; m <= 1; m++) + { + for (int n = -1; n <= 1; n++) + { + if (!(m == 0 && n == 0)) + { + materialFrequency[oldMaterials[x + 1 + m][z + 1 + n]]++; + } + } + } + + // Find most common neighboring material. + for (BlockTypes type : BlockTypes.values) + { + int i = type.getInternalId(); + if (materialFrequency[i] > modeMatCount && !(this.excludeAir && type.getMaterial().isAir()) && !(this.excludeWater && (type == BlockTypes.WATER))) + { + modeMatCount = materialFrequency[i]; + modeMatId = i; + } + } + // Make sure there'world not a tie for most common + for (int i = 0; i < modeMatId; i++) + { + BlockTypes type = BlockTypes.get(i); + if (materialFrequency[i] == modeMatCount && !(this.excludeAir && type.getMaterial().isAir()) && !(this.excludeWater && (type == BlockTypes.WATER))) + { + tiecheck = false; + } + } + + // Record most common neighbor material for this block + if (tiecheck) + { + newMaterials[x][z] = modeMatId; + } + } + } + + final Undo undo = new Undo(); + + // Make the changes + for (int x = brushSizeDoubled; x >= 0; x--) + { + for (int z = brushSizeDoubled; z >= 0; z--) + { + if (!(this.excludeAir && BlockTypes.get(newMaterials[x][z]).getMaterial().isAir()) && !(this.excludeWater && (newMaterials[x][z] == BlockTypes.WATER.getInternalId()))) + { + if (this.getBlockIdAt(this.getTargetBlock().getX() - brushSize + x, this.getTargetBlock().getY(), this.getTargetBlock().getZ() - brushSize + z) != newMaterials[x][z]) + { + undo.put(this.clampY(this.getTargetBlock().getX() - brushSize + x, this.getTargetBlock().getY(), this.getTargetBlock().getZ() - brushSize + z)); + } + this.setBlockIdAt(this.getTargetBlock().getZ() - brushSize + z, this.getTargetBlock().getX() - brushSize + x, this.getTargetBlock().getY(), newMaterials[x][z]); + + } + } + } + + v.owner().storeUndo(undo); + } + + @Override + public final void parameters(final String[] par, final SnipeData v) + { + if (par[1].equalsIgnoreCase("info")) + { + v.sendMessage(ChatColor.GOLD + "Blend Voxel Disc Parameters:"); + v.sendMessage(ChatColor.AQUA + "/b bvd water -- toggle include or exclude (default) water"); + return; + } + + super.parameters(par, v); + } + + @Override + public String getPermissionNode() + { + return "voxelsniper.brush.blendvoxeldisc"; + } +} diff --git a/favs/src/main/java/com/thevoxelbox/voxelsniper/brush/BlobBrush.java b/favs/src/main/java/com/thevoxelbox/voxelsniper/brush/BlobBrush.java new file mode 100644 index 000000000..cf51dca5e --- /dev/null +++ b/favs/src/main/java/com/thevoxelbox/voxelsniper/brush/BlobBrush.java @@ -0,0 +1,313 @@ +package com.thevoxelbox.voxelsniper.brush; + +import java.util.Random; + +import com.thevoxelbox.voxelsniper.Message; +import com.thevoxelbox.voxelsniper.SnipeData; +import com.thevoxelbox.voxelsniper.brush.perform.PerformBrush; + +import org.bukkit.ChatColor; + +/** + * http://www.voxelwiki.com/minecraft/Voxelsniper#The_Blob_Brush + * + * @author Giltwist + */ +public class BlobBrush extends PerformBrush +{ + private static final int GROW_PERCENT_DEFAULT = 1000; + private static final int GROW_PERCENT_MIN = 1; + private static final int GROW_PERCENT_MAX = 9999; + + private Random randomGenerator = new Random(); + private int growPercent = GROW_PERCENT_DEFAULT; // chance block on recursion pass is made active + + /** + * + */ + public BlobBrush() + { + this.setName("Blob"); + } + + private void checkValidGrowPercent(final SnipeData v) + { + if (this.growPercent < GROW_PERCENT_MIN || this.growPercent > GROW_PERCENT_MAX) + { + this.growPercent = GROW_PERCENT_DEFAULT; + v.sendMessage(ChatColor.BLUE + "Growth percent set to: 10%"); + } + } + + private void digBlob(final SnipeData v) + { + final int brushSize = v.getBrushSize(); + final int brushSizeDoubled = 2 * brushSize; + final int[][][] splat = new int[brushSizeDoubled + 1][brushSizeDoubled + 1][brushSizeDoubled + 1]; + final int[][][] tempSplat = new int[brushSizeDoubled + 1][brushSizeDoubled + 1][brushSizeDoubled + 1]; + + this.checkValidGrowPercent(v); + + // Seed the array + for (int x = brushSizeDoubled; x >= 0; x--) + { + for (int y = brushSizeDoubled; y >= 0; y--) + { + for (int z = brushSizeDoubled; z >= 0; z--) + { + if ((x == 0 || y == 0 | z == 0 || x == brushSizeDoubled || y == brushSizeDoubled || z == brushSizeDoubled) && this.randomGenerator.nextInt(GROW_PERCENT_MAX + 1) <= this.growPercent) + { + splat[x][y][z] = 0; + } + else + { + splat[x][y][z] = 1; + } + } + } + } + + // Grow the seed + for (int r = 0; r < brushSize; r++) + { + for (int x = brushSizeDoubled; x >= 0; x--) + { + for (int y = brushSizeDoubled; y >= 0; y--) + { + for (int z = brushSizeDoubled; z >= 0; z--) + { + tempSplat[x][y][z] = splat[x][y][z]; + double growCheck = 0; + if (splat[x][y][z] == 1) + { + if (x != 0 && splat[x - 1][y][z] == 0) + { + growCheck++; + } + if (y != 0 && splat[x][y - 1][z] == 0) + { + growCheck++; + } + if (z != 0 && splat[x][y][z - 1] == 0) + { + growCheck++; + } + if (x != 2 * brushSize && splat[x + 1][y][z] == 0) + { + growCheck++; + } + if (y != 2 * brushSize && splat[x][y + 1][z] == 0) + { + growCheck++; + } + if (z != 2 * brushSize && splat[x][y][z + 1] == 0) + { + growCheck++; + } + } + + if (growCheck >= 1 && this.randomGenerator.nextInt(GROW_PERCENT_MAX + 1) <= this.growPercent) + { + tempSplat[x][y][z] = 0; // prevent bleed into splat + } + } + } + } + + // shouldn't this just be splat = tempsplat;? -Gavjenks + // integrate tempsplat back into splat at end of iteration + for (int x = brushSizeDoubled; x >= 0; x--) + { + for (int y = brushSizeDoubled; y >= 0; y--) + { + for (int z = brushSizeDoubled; z >= 0; z--) + { + splat[x][y][z] = tempSplat[x][y][z]; + } + } + } + } + + final double rSquared = Math.pow(brushSize + 1, 2); + + // Make the changes + for (int x = brushSizeDoubled; x >= 0; x--) + { + final double xSquared = Math.pow(x - brushSize - 1, 2); + + for (int y = brushSizeDoubled; y >= 0; y--) + { + final double ySquared = Math.pow(y - brushSize - 1, 2); + + for (int z = brushSizeDoubled; z >= 0; z--) + { + if (splat[x][y][z] == 1 && xSquared + ySquared + Math.pow(z - brushSize - 1, 2) <= rSquared) + { + this.current.perform(this.clampY(this.getTargetBlock().getX() - brushSize + x, this.getTargetBlock().getY() - brushSize + z, this.getTargetBlock().getZ() - brushSize + y)); + } + } + } + } + + v.owner().storeUndo(this.current.getUndo()); + } + + private void growBlob(final SnipeData v) + { + final int brushSize = v.getBrushSize(); + final int brushSizeDoubled = 2 * brushSize; + final int[][][] splat = new int[brushSizeDoubled + 1][brushSizeDoubled + 1][brushSizeDoubled + 1]; + final int[][][] tempSplat = new int[brushSizeDoubled + 1][brushSizeDoubled + 1][brushSizeDoubled + 1]; + + this.checkValidGrowPercent(v); + + // Seed the array + splat[brushSize][brushSize][brushSize] = 1; + + // Grow the seed + for (int r = 0; r < brushSize; r++) + { + + for (int x = brushSizeDoubled; x >= 0; x--) + { + for (int y = brushSizeDoubled; y >= 0; y--) + { + for (int z = brushSizeDoubled; z >= 0; z--) + { + tempSplat[x][y][z] = splat[x][y][z]; + int growCheck = 0; + if (splat[x][y][z] == 0) + { + if (x != 0 && splat[x - 1][y][z] == 1) + { + growCheck++; + } + if (y != 0 && splat[x][y - 1][z] == 1) + { + growCheck++; + } + if (z != 0 && splat[x][y][z - 1] == 1) + { + growCheck++; + } + if (x != 2 * brushSize && splat[x + 1][y][z] == 1) + { + growCheck++; + } + if (y != 2 * brushSize && splat[x][y + 1][z] == 1) + { + growCheck++; + } + if (z != 2 * brushSize && splat[x][y][z + 1] == 1) + { + growCheck++; + } + } + + if (growCheck >= 1 && this.randomGenerator.nextInt(GROW_PERCENT_MAX + 1) <= this.growPercent) + { + // prevent bleed into splat + tempSplat[x][y][z] = 1; + } + } + } + } + + // integrate tempsplat back into splat at end of iteration + for (int x = brushSizeDoubled; x >= 0; x--) + { + for (int y = brushSizeDoubled; y >= 0; y--) + { + for (int z = brushSizeDoubled; z >= 0; z--) + { + splat[x][y][z] = tempSplat[x][y][z]; + } + } + } + } + + final double rSquared = Math.pow(brushSize + 1, 2); + + // Make the changes + for (int x = brushSizeDoubled; x >= 0; x--) + { + final double xSquared = Math.pow(x - brushSize - 1, 2); + + for (int y = brushSizeDoubled; y >= 0; y--) + { + final double ySquared = Math.pow(y - brushSize - 1, 2); + + for (int z = brushSizeDoubled; z >= 0; z--) + { + if (splat[x][y][z] == 1 && xSquared + ySquared + Math.pow(z - brushSize - 1, 2) <= rSquared) + { + this.current.perform(this.clampY(this.getTargetBlock().getX() - brushSize + x, this.getTargetBlock().getY() - brushSize + z, this.getTargetBlock().getZ() - brushSize + y)); + } + } + } + } + + v.owner().storeUndo(this.current.getUndo()); + } + + @Override + protected final void arrow(final SnipeData v) + { + this.growBlob(v); + } + + @Override + protected final void powder(final SnipeData v) + { + this.digBlob(v); + } + + @Override + public final void info(final Message vm) + { + this.checkValidGrowPercent(null); + + vm.brushName(this.getName()); + vm.size(); + vm.custom(ChatColor.BLUE + "Growth percent set to: " + this.growPercent / 100 + "%"); + } + + @Override + public final void parameters(final String[] par, final SnipeData v) + { + for (int i = 1; i < par.length; i++) + { + final String parameter = par[i]; + + if (parameter.equalsIgnoreCase("info")) + { + v.sendMessage(ChatColor.GOLD + "Blob brush Parameters:"); + v.sendMessage(ChatColor.AQUA + "/b blob g[int] -- set a growth percentage (" + GROW_PERCENT_MIN + "-" + GROW_PERCENT_MAX + "). Default is " + GROW_PERCENT_DEFAULT); + return; + } + if (parameter.startsWith("g")) + { + final int temp = Integer.parseInt(parameter.replace("g", "")); + if (temp >= GROW_PERCENT_MIN && temp <= GROW_PERCENT_MAX) + { + v.sendMessage(ChatColor.AQUA + "Growth percent set to: " + (float) temp / 100 + "%"); + this.growPercent = temp; + } + else + { + v.sendMessage(ChatColor.RED + "Growth percent must be an integer " + GROW_PERCENT_MIN + "-" + GROW_PERCENT_MAX + "!"); + } + } + else + { + v.sendMessage(ChatColor.RED + "Invalid brush parameters! use the info parameter to display parameter info."); + } + } + } + + @Override + public String getPermissionNode() + { + return "voxelsniper.brush.blob"; + } +} diff --git a/favs/src/main/java/com/thevoxelbox/voxelsniper/brush/BlockResetBrush.java b/favs/src/main/java/com/thevoxelbox/voxelsniper/brush/BlockResetBrush.java new file mode 100644 index 000000000..6738b696a --- /dev/null +++ b/favs/src/main/java/com/thevoxelbox/voxelsniper/brush/BlockResetBrush.java @@ -0,0 +1,90 @@ +package com.thevoxelbox.voxelsniper.brush; + +import java.util.ArrayList; + +import com.thevoxelbox.voxelsniper.Message; +import com.thevoxelbox.voxelsniper.SnipeData; + +import org.bukkit.Material; +import org.bukkit.block.Block; + +/** + * @author MikeMatrix + */ +public class BlockResetBrush extends Brush +{ + private static final ArrayList DENIED_UPDATES = new ArrayList(); + + static + { + BlockResetBrush.DENIED_UPDATES.add(Material.SIGN); + BlockResetBrush.DENIED_UPDATES.add(Material.LEGACY_SIGN_POST); + BlockResetBrush.DENIED_UPDATES.add(Material.WALL_SIGN); + BlockResetBrush.DENIED_UPDATES.add(Material.CHEST); + BlockResetBrush.DENIED_UPDATES.add(Material.FURNACE); + BlockResetBrush.DENIED_UPDATES.add(Material.LEGACY_BURNING_FURNACE); + BlockResetBrush.DENIED_UPDATES.add(Material.LEGACY_REDSTONE_TORCH_OFF); + BlockResetBrush.DENIED_UPDATES.add(Material.LEGACY_REDSTONE_TORCH_ON); + BlockResetBrush.DENIED_UPDATES.add(Material.REDSTONE_WIRE); + BlockResetBrush.DENIED_UPDATES.add(Material.LEGACY_DIODE_BLOCK_OFF); + BlockResetBrush.DENIED_UPDATES.add(Material.LEGACY_DIODE_BLOCK_ON); + BlockResetBrush.DENIED_UPDATES.add(Material.LEGACY_WOODEN_DOOR); + BlockResetBrush.DENIED_UPDATES.add(Material.LEGACY_WOOD_DOOR); + BlockResetBrush.DENIED_UPDATES.add(Material.IRON_DOOR); + BlockResetBrush.DENIED_UPDATES.add(Material.LEGACY_IRON_DOOR_BLOCK); + BlockResetBrush.DENIED_UPDATES.add(Material.LEGACY_FENCE_GATE); + } + + /** + * + */ + public BlockResetBrush() + { + this.setName("Block Reset Brush"); + } + + @SuppressWarnings("deprecation") + private void applyBrush(final SnipeData v) + { + for (int z = -v.getBrushSize(); z <= v.getBrushSize(); z++) + { + for (int x = -v.getBrushSize(); x <= v.getBrushSize(); x++) + { + for (int y = -v.getBrushSize(); y <= v.getBrushSize(); y++) + { + final Block block = this.getWorld().getBlockAt(this.getTargetBlock().getX() + x, this.getTargetBlock().getY() + y, this.getTargetBlock().getZ() + z); + if (BlockResetBrush.DENIED_UPDATES.contains(block.getType())) + { + continue; + } + + block.setBlockData(block.getType().createBlockData(), true); + } + } + } + } + + @Override + protected final void arrow(final SnipeData v) + { + applyBrush(v); + } + + @Override + protected final void powder(final SnipeData v) + { + applyBrush(v); + } + + @Override + public final void info(final Message vm) + { + vm.brushName(this.getName()); + } + + @Override + public String getPermissionNode() + { + return "voxelsniper.brush.blockreset"; + } +} diff --git a/favs/src/main/java/com/thevoxelbox/voxelsniper/brush/BlockResetSurfaceBrush.java b/favs/src/main/java/com/thevoxelbox/voxelsniper/brush/BlockResetSurfaceBrush.java new file mode 100644 index 000000000..de93fa6eb --- /dev/null +++ b/favs/src/main/java/com/thevoxelbox/voxelsniper/brush/BlockResetSurfaceBrush.java @@ -0,0 +1,154 @@ +package com.thevoxelbox.voxelsniper.brush; + +import java.util.ArrayList; + +import com.boydti.fawe.bukkit.wrapper.AsyncBlock; +import com.boydti.fawe.bukkit.wrapper.AsyncWorld; +import com.sk89q.worldedit.blocks.BlockMaterial; +import com.sk89q.worldedit.bukkit.BukkitAdapter; +import com.thevoxelbox.voxelsniper.Message; +import com.thevoxelbox.voxelsniper.SnipeData; + +import org.bukkit.Material; +import org.bukkit.World; +import org.bukkit.block.Block; + +/** + * This brush only looks for solid blocks, and then changes those plus any air blocks touching them. If it works, this brush should be faster than the original + * blockPositionY an amount proportional to the volume of a snipe selection area / the number of blocks touching air in the selection. This is because every solid block + * surrounded blockPositionY others should take equally long to check and not change as it would take MC to change them and then check and find no lighting to update. For + * air blocks surrounded blockPositionY other air blocks, this brush saves about 80-100 checks blockPositionY not updating them or their lighting. And for air blocks touching solids, + * this brush is slower, because it replaces the air once per solid block it is touching. I assume on average this is about 2 blocks. So every air block + * touching a solid negates one air block floating in air. Thus, for selections that have more air blocks surrounded blockPositionY air than air blocks touching solids, + * this brush will be faster, which is almost always the case, especially for undeveloped terrain and for larger brush sizes (unlike the original brush, this + * should only slow down blockPositionY the square of the brush size, not the cube of the brush size). For typical terrain, blockPositionY my calculations, overall speed increase is + * about a factor of 5-6 for a size 20 brush. For a complicated city or ship, etc., this may be only a factor of about 2. In a hypothetical worst case scenario + * of a 3d checkerboard of stone and air every other block, this brush should only be about 1.5x slower than the original brush. Savings increase for larger + * brushes. + * + * @author GavJenks + */ +public class BlockResetSurfaceBrush extends Brush +{ + /** + * + */ + public BlockResetSurfaceBrush() + { + this.setName("Block Reset Brush Surface Only"); + } + + @SuppressWarnings("deprecation") + private void applyBrush(final SnipeData v) + { + final AsyncWorld world = this.getWorld(); + + for (int z = -v.getBrushSize(); z <= v.getBrushSize(); z++) + { + for (int x = -v.getBrushSize(); x <= v.getBrushSize(); x++) + { + for (int y = -v.getBrushSize(); y <= v.getBrushSize(); y++) + { + + AsyncBlock block = world.getBlockAt(this.getTargetBlock().getX() + x, this.getTargetBlock().getY() + y, this.getTargetBlock().getZ() + z); + + + Material type = block.getType(); + BlockMaterial mat = BukkitAdapter.adapt(type).getMaterial(); + if (!mat.isSolid() || !mat.isFullCube() || mat.hasContainer()) + { + continue; + } + + boolean airFound = false; + + if (world.getBlockAt(this.getTargetBlock().getX() + x + 1, this.getTargetBlock().getY() + y, this.getTargetBlock().getZ() + z).isEmpty()) + { + block = world.getBlockAt(this.getTargetBlock().getX() + x + 1, this.getTargetBlock().getY() + y, this.getTargetBlock().getZ() + z); + final int oldData = block.getPropertyId(); + resetBlock(block, oldData); + airFound = true; + } + + if (world.getBlockAt(this.getTargetBlock().getX() + x - 1, this.getTargetBlock().getY() + y, this.getTargetBlock().getZ() + z).isEmpty()) + { + block = world.getBlockAt(this.getTargetBlock().getX() + x - 1, this.getTargetBlock().getY() + y, this.getTargetBlock().getZ() + z); + final int oldData = block.getPropertyId(); + resetBlock(block, oldData); + airFound = true; + } + + if (world.getBlockAt(this.getTargetBlock().getX() + x, this.getTargetBlock().getY() + y + 1, this.getTargetBlock().getZ() + z).isEmpty()) + { + block = world.getBlockAt(this.getTargetBlock().getX() + x, this.getTargetBlock().getY() + y + 1, this.getTargetBlock().getZ() + z); + final int oldData = block.getPropertyId(); + resetBlock(block, oldData); + airFound = true; + } + + if (world.getBlockAt(this.getTargetBlock().getX() + x, this.getTargetBlock().getY() + y - 1, this.getTargetBlock().getZ() + z).isEmpty()) + { + block = world.getBlockAt(this.getTargetBlock().getX() + x, this.getTargetBlock().getY() + y - 1, this.getTargetBlock().getZ() + z); + final int oldData = block.getPropertyId(); + resetBlock(block, oldData); + airFound = true; + } + + if (world.getBlockAt(this.getTargetBlock().getX() + x, this.getTargetBlock().getY() + y, this.getTargetBlock().getZ() + z + 1).isEmpty()) + { + block = world.getBlockAt(this.getTargetBlock().getX() + x, this.getTargetBlock().getY() + y, this.getTargetBlock().getZ() + z + 1); + final int oldData = block.getPropertyId(); + resetBlock(block, oldData); + airFound = true; + } + + if (world.getBlockAt(this.getTargetBlock().getX() + x, this.getTargetBlock().getY() + y, this.getTargetBlock().getZ() + z - 1).isEmpty()) + { + block = world.getBlockAt(this.getTargetBlock().getX() + x, this.getTargetBlock().getY() + y, this.getTargetBlock().getZ() + z - 1); + final int oldData = block.getPropertyId(); + resetBlock(block, oldData); + airFound = true; + } + + if (airFound) + { + block = world.getBlockAt(this.getTargetBlock().getX() + x, this.getTargetBlock().getY() + y, this.getTargetBlock().getZ() + z); + final int oldData = block.getPropertyId(); + resetBlock(block, oldData); + } + } + } + } + } + + @SuppressWarnings("deprecation") + private void resetBlock(AsyncBlock block, final int oldData) + { + block.setTypeIdAndPropertyId(block.getTypeId(), ((block.getPropertyId() + 1) & 0xf), true); + block.setTypeIdAndPropertyId(block.getTypeId(), oldData, true); + } + + @Override + protected final void arrow(final SnipeData v) + { + applyBrush(v); + } + + @Override + protected final void powder(final SnipeData v) + { + applyBrush(v); + } + + @Override + public final void info(final Message vm) + { + vm.brushName(this.getName()); + } + + @Override + public String getPermissionNode() + { + return "voxelsniper.brush.blockresetsurface"; + } +} diff --git a/favs/src/main/java/com/thevoxelbox/voxelsniper/brush/Brush.java b/favs/src/main/java/com/thevoxelbox/voxelsniper/brush/Brush.java new file mode 100644 index 000000000..7278b0e70 --- /dev/null +++ b/favs/src/main/java/com/thevoxelbox/voxelsniper/brush/Brush.java @@ -0,0 +1,311 @@ +package com.thevoxelbox.voxelsniper.brush; + +import com.boydti.fawe.bukkit.wrapper.AsyncBlock; +import com.boydti.fawe.bukkit.wrapper.AsyncWorld; +import com.thevoxelbox.voxelsniper.Message; +import com.thevoxelbox.voxelsniper.RangeBlockHelper; +import com.thevoxelbox.voxelsniper.SnipeAction; +import com.thevoxelbox.voxelsniper.SnipeData; +import com.thevoxelbox.voxelsniper.brush.perform.PerformBrush; +import com.thevoxelbox.voxelsniper.util.BlockWrapper; +import org.bukkit.ChatColor; +import org.bukkit.Material; +import org.bukkit.World; +import org.bukkit.block.Block; +import org.bukkit.block.BlockFace; + +/** + * Abstract implementation of the {@link IBrush} interface. + */ +public abstract class Brush implements IBrush +{ + protected static final int CHUNK_SIZE = 16; + /** + * Targeted Block. + */ + private AsyncBlock targetBlock; + /** + * Last Block before targeted Block. + */ + private AsyncBlock lastBlock; + /** + * Brush name. + */ + private String name = "Undefined"; + + /** + * @param x + * @param y + * @param z + * @return {@link Block} + */ + public final AsyncBlock clampY(final int x, final int y, final int z) + { + int clampedY = y; + if (clampedY < 0) + { + clampedY = 0; + } + else if (clampedY > this.getWorld().getMaxHeight()) + { + clampedY = this.getWorld().getMaxHeight(); + } + + return this.getWorld().getBlockAt(x, clampedY, z); + } + + private boolean preparePerform(final SnipeData v, final AsyncBlock clickedBlock, final BlockFace clickedFace) + { + if (this.getTarget(v, clickedBlock, clickedFace)) + { + if (this instanceof PerformBrush) + { + ((PerformBrush) this).initP(v); + } + return true; + } + + return false; + } + + @Override + public boolean perform(SnipeAction action, SnipeData data, AsyncBlock targetBlock, AsyncBlock lastBlock) + { + this.setTargetBlock(targetBlock); + this.setLastBlock(lastBlock); + switch (action) + { + case ARROW: + this.arrow(data); + return true; + case GUNPOWDER: + this.powder(data); + return true; + default: + return false; + } + } + + /** + * The arrow action. Executed when a player RightClicks with an Arrow + * + * @param v Sniper caller + */ + protected void arrow(final SnipeData v) + { + } + + /** + * The powder action. Executed when a player RightClicks with Gunpowder + * + * @param v Sniper caller + */ + protected void powder(final SnipeData v) + { + } + + @Override + public abstract void info(Message vm); + + @Override + public void parameters(final String[] par, final SnipeData v) + { + v.sendMessage(ChatColor.RED + "This brush does not accept additional parameters."); + } + + /** + * Overridable getTarget method. + * + * @param v + * @param clickedBlock + * @param clickedFace + * @return boolean + */ + protected final boolean getTarget(final SnipeData v, final AsyncBlock clickedBlock, final BlockFace clickedFace) + { + if (clickedBlock != null) + { + this.setTargetBlock(clickedBlock); + this.setLastBlock(clickedBlock.getRelative(clickedFace)); + if (this.getLastBlock() == null) + { + v.sendMessage(ChatColor.RED + "Snipe target block must be visible."); + return false; + } + if (v.owner().getSnipeData(v.owner().getCurrentToolId()).isLightningEnabled()) + { + this.getWorld().strikeLightning(this.getTargetBlock().getLocation()); + } + return true; + } + else + { + RangeBlockHelper rangeBlockHelper; + if (v.owner().getSnipeData(v.owner().getCurrentToolId()).isRanged()) + { + rangeBlockHelper = new RangeBlockHelper(v.owner().getPlayer(), v.owner().getWorld(), (double) v.owner().getSnipeData(v.owner().getCurrentToolId()).getRange()); + this.setTargetBlock(rangeBlockHelper.getRangeBlock()); + } + else + { + rangeBlockHelper = new RangeBlockHelper(v.owner().getPlayer(), v.owner().getWorld()); + this.setTargetBlock(rangeBlockHelper.getTargetBlock()); + } + if (this.getTargetBlock() != null) + { + this.setLastBlock(rangeBlockHelper.getLastBlock()); + if (this.getLastBlock() == null) + { + v.sendMessage(ChatColor.RED + "Snipe target block must be visible."); + return false; + } + if (v.owner().getSnipeData(v.owner().getCurrentToolId()).isLightningEnabled()) + { + this.getWorld().strikeLightning(this.getTargetBlock().getLocation()); + } + return true; + } + else + { + v.sendMessage(ChatColor.RED + "Snipe target block must be visible."); + return false; + } + } + } + + @Override + public final String getName() + { + return this.name; + } + + @Override + public final void setName(final String name) + { + this.name = name; + } + + @Override + public String getBrushCategory() + { + return "General"; + } + + /** + * @return the targetBlock + */ + protected final AsyncBlock getTargetBlock() + { + return this.targetBlock; + } + + /** + * @param targetBlock the targetBlock to set + */ + protected final void setTargetBlock(final AsyncBlock targetBlock) + { + this.targetBlock = targetBlock; + } + + /** + * @return the world + */ + protected final AsyncWorld getWorld() + { + return targetBlock.getWorld(); + } + + /** + * Looks up Type ID of Block at given coordinates in the world of the targeted Block. + * + * @param x X coordinate + * @param y Y coordinate + * @param z Z coordinate + * @return Type ID of Block at given coordinates in the world of the targeted Block. + */ + @SuppressWarnings("deprecation") + protected int getBlockIdAt(int x, int y, int z) + { + return getWorld().getBlockAt(x, y, z).getTypeId(); + } + + protected Block getBlockAt(int x, int y, int z) + { + return getWorld().getBlockAt(x, y, z); + } + + protected Material getBlockType(int x, int y, int z) + { + return getWorld().getBlockAt(x, y, z).getType(); + } + + /** + * Looks up Block Data Value of Block at given coordinates in the world of the targeted Block. + * + * @param x X coordinate + * @param y Y coordinate + * @param z Z coordinate + * @return Block Data Value of Block at given coordinates in the world of the targeted Block. + */ + @SuppressWarnings("deprecation") + protected int getBlockDataAt(int x, int y, int z) + { + return this.getWorld().getBlockAt(x, y, z).getPropertyId(); + } + + /** + * @return Block before target Block. + */ + protected final AsyncBlock getLastBlock() + { + return this.lastBlock; + } + + /** + * @param lastBlock Last Block before target Block. + */ + protected final void setLastBlock(AsyncBlock lastBlock) + { + this.lastBlock = lastBlock; + } + + /** + * Set block data with supplied data over BlockWrapper. + * + * @param blockWrapper Block data wrapper + */ + @Deprecated + protected final void setBlock(BlockWrapper blockWrapper) + { + this.getWorld().getBlockAt(blockWrapper.getX(), blockWrapper.getY(), blockWrapper.getZ()).setTypeId(blockWrapper.getId()); + } + + /** + * Sets the Id of the block at the passed coordinate. + * + * @param z Z coordinate + * @param x X coordinate + * @param y Y coordinate + * @param id The id the block will be set to + */ + @SuppressWarnings("deprecation") + protected final void setBlockIdAt(int z, int x, int y, int id) + { + this.getWorld().getBlockAt(x, y, z).setTypeId(id); + } + + /** + * Sets the id and data value of the block at the passed coordinate. + * + * @param x X coordinate + * @param y Y coordinate + * @param z Z coordinate + * @param id The id the block will be set to + * @param data The data value the block will be set to + */ + @SuppressWarnings("deprecation") + protected final void setBlockIdAndDataAt(int x, int y, int z, int id, int data) + { + this.getWorld().getBlockAt(x, y, z).setTypeIdAndPropertyId(id, data, true); + } +} diff --git a/favs/src/main/java/com/thevoxelbox/voxelsniper/brush/CanyonBrush.java b/favs/src/main/java/com/thevoxelbox/voxelsniper/brush/CanyonBrush.java new file mode 100644 index 000000000..976058e10 --- /dev/null +++ b/favs/src/main/java/com/thevoxelbox/voxelsniper/brush/CanyonBrush.java @@ -0,0 +1,146 @@ +package com.thevoxelbox.voxelsniper.brush; + +import com.boydti.fawe.bukkit.wrapper.AsyncBlock; +import com.boydti.fawe.bukkit.wrapper.AsyncChunk; +import com.sk89q.worldedit.world.block.BlockTypes; +import com.thevoxelbox.voxelsniper.Message; +import com.thevoxelbox.voxelsniper.SnipeData; +import com.thevoxelbox.voxelsniper.Undo; +import org.bukkit.ChatColor; +import org.bukkit.Chunk; +import org.bukkit.Material; +import org.bukkit.block.Block; + +/** + * http://www.voxelwiki.com/minecraft/Voxelsniper#The_CANYONATOR + * + * @author Voxel + */ +public class CanyonBrush extends Brush +{ + private static final int SHIFT_LEVEL_MIN = 10; + private static final int SHIFT_LEVEL_MAX = 60; + private int yLevel = 10; + + /** + * + */ + public CanyonBrush() + { + this.setName("Canyon"); + } + + /** + * @param chunk + * @param undo + */ + @SuppressWarnings("deprecation") + protected final void canyon(final AsyncChunk chunk, final Undo undo) + { + for (int x = 0; x < CHUNK_SIZE; x++) + { + for (int z = 0; z < CHUNK_SIZE; z++) + { + int currentYLevel = this.yLevel; + + for (int y = 63; y < this.getWorld().getMaxHeight(); y++) + { + final AsyncBlock block = chunk.getBlock(x, y, z); + final AsyncBlock currentYLevelBlock = chunk.getBlock(x, currentYLevel, z); + + undo.put(block); + undo.put(currentYLevelBlock); + + currentYLevelBlock.setTypeId(block.getTypeId()); + block.setType(Material.AIR); + + currentYLevel++; + } + + final AsyncBlock block = chunk.getBlock(x, 0, z); + undo.put(block); + block.setTypeId(BlockTypes.BEDROCK.getInternalId()); + + for (int y = 1; y < SHIFT_LEVEL_MIN; y++) + { + final Block currentBlock = chunk.getBlock(x, y, z); + undo.put(currentBlock); + currentBlock.setType(Material.STONE); + } + } + } + } + + @Override + protected void arrow(final SnipeData v) + { + final Undo undo = new Undo(); + + canyon(getTargetBlock().getChunk(), undo); + + v.owner().storeUndo(undo); + } + + @Override + protected void powder(final SnipeData v) + { + final Undo undo = new Undo(); + + Chunk targetChunk = getTargetBlock().getChunk(); + for (int x = targetChunk.getX() - 1; x <= targetChunk.getX() + 1; x++) + { + for (int z = targetChunk.getX() - 1; z <= targetChunk.getX() + 1; z++) + { + canyon(getWorld().getChunkAt(x, z), undo); + } + } + + v.owner().storeUndo(undo); + } + + @Override + public void info(final Message vm) + { + vm.brushName(this.getName()); + vm.custom(ChatColor.GREEN + "Shift Level set to " + this.yLevel); + } + + @Override + public final void parameters(final String[] par, final SnipeData v) + { + if (par[1].equalsIgnoreCase("info")) + { + v.sendMessage(ChatColor.GREEN + "y[number] to set the Level to which the land will be shifted down"); + } + if (par[1].startsWith("y")) + { + int _i = Integer.parseInt(par[1].replace("y", "")); + if (_i < SHIFT_LEVEL_MIN) + { + _i = SHIFT_LEVEL_MIN; + } + else if (_i > SHIFT_LEVEL_MAX) + { + _i = SHIFT_LEVEL_MAX; + } + this.yLevel = _i; + v.sendMessage(ChatColor.GREEN + "Shift Level set to " + this.yLevel); + } + } + + protected final int getYLevel() + { + return yLevel; + } + + protected final void setYLevel(int yLevel) + { + this.yLevel = yLevel; + } + + @Override + public String getPermissionNode() + { + return "voxelsniper.brush.canyon"; + } +} diff --git a/favs/src/main/java/com/thevoxelbox/voxelsniper/brush/CanyonSelectionBrush.java b/favs/src/main/java/com/thevoxelbox/voxelsniper/brush/CanyonSelectionBrush.java new file mode 100644 index 000000000..defbdd739 --- /dev/null +++ b/favs/src/main/java/com/thevoxelbox/voxelsniper/brush/CanyonSelectionBrush.java @@ -0,0 +1,88 @@ +package com.thevoxelbox.voxelsniper.brush; + +import com.thevoxelbox.voxelsniper.Message; +import com.thevoxelbox.voxelsniper.SnipeData; +import com.thevoxelbox.voxelsniper.Undo; +import org.bukkit.ChatColor; +import org.bukkit.Chunk; + +/** + * http://www.voxelwiki.com/minecraft/Voxelsniper#The_Canyon_Selection_Brush + * + * @author Voxel + */ +public class CanyonSelectionBrush extends CanyonBrush +{ + private boolean first = true; + private int fx; + private int fz; + + /** + * + */ + public CanyonSelectionBrush() + { + this.setName("Canyon Selection"); + } + + private void execute(final SnipeData v) + { + final Chunk chunk = getTargetBlock().getChunk(); + + if (this.first) + { + this.fx = chunk.getX(); + this.fz = chunk.getZ(); + + v.sendMessage(ChatColor.YELLOW + "First point selected!"); + this.first = !this.first; + } + else + { + v.sendMessage(ChatColor.YELLOW + "Second point selected!"); + selection(Math.min(fx, chunk.getX()), Math.min(fz, chunk.getZ()), Math.max(fx, chunk.getX()), Math.max(fz, chunk.getZ()), v); + + this.first = !this.first; + } + } + + private void selection(final int lowX, final int lowZ, final int highX, final int highZ, final SnipeData v) + { + final Undo undo = new Undo(); + + for (int x = lowX; x <= highX; x++) + { + for (int z = lowZ; z <= highZ; z++) + { + canyon(getWorld().getChunkAt(x, z), undo); + } + } + + v.owner().storeUndo(undo); + } + + @Override + protected final void arrow(final SnipeData v) + { + execute(v); + } + + @Override + protected final void powder(final SnipeData v) + { + execute(v); + } + + @Override + public final void info(final Message vm) + { + vm.brushName(this.getName()); + vm.custom(ChatColor.GREEN + "Shift Level set to " + this.getYLevel()); + } + + @Override + public String getPermissionNode() + { + return "voxelsniper.brush.canyonselection"; + } +} diff --git a/favs/src/main/java/com/thevoxelbox/voxelsniper/brush/CheckerVoxelDiscBrush.java b/favs/src/main/java/com/thevoxelbox/voxelsniper/brush/CheckerVoxelDiscBrush.java new file mode 100644 index 000000000..868527860 --- /dev/null +++ b/favs/src/main/java/com/thevoxelbox/voxelsniper/brush/CheckerVoxelDiscBrush.java @@ -0,0 +1,101 @@ +package com.thevoxelbox.voxelsniper.brush; + +import com.thevoxelbox.voxelsniper.Message; +import com.thevoxelbox.voxelsniper.SnipeData; +import com.thevoxelbox.voxelsniper.brush.perform.PerformBrush; + +import org.bukkit.ChatColor; +import org.bukkit.block.Block; + +/** + * @author MikeMatrix + */ +public class CheckerVoxelDiscBrush extends PerformBrush +{ + private boolean useWorldCoordinates = true; + + /** + * Default constructor. + */ + public CheckerVoxelDiscBrush() + { + this.setName("Checker Voxel Disc"); + } + + /** + * @param v + * @param target + */ + private void applyBrush(final SnipeData v, final Block target) + { + for (int x = v.getBrushSize(); x >= -v.getBrushSize(); x--) + { + for (int y = v.getBrushSize(); y >= -v.getBrushSize(); y--) + { + final int sum = this.useWorldCoordinates ? target.getX() + x + target.getZ() + y : x + y; + if (sum % 2 != 0) + { + this.current.perform(this.clampY(target.getX() + x, target.getY(), target.getZ() + y)); + } + } + } + v.owner().storeUndo(this.current.getUndo()); + } + + @Override + protected final void arrow(final SnipeData v) + { + this.applyBrush(v, this.getTargetBlock()); + } + + @Override + protected final void powder(final SnipeData v) + { + this.applyBrush(v, this.getLastBlock()); + } + + @Override + public final void info(final Message vm) + { + vm.brushName(this.getName()); + vm.size(); + } + + @Override + public final void parameters(final String[] par, final SnipeData v) + { + for (int x = 1; x < par.length; x++) + { + final String parameter = par[x].toLowerCase(); + + if (parameter.equals("info")) + { + v.sendMessage(ChatColor.GOLD + this.getName() + " Parameters:"); + v.sendMessage(ChatColor.AQUA + "true -- Enables using World Coordinates."); + v.sendMessage(ChatColor.AQUA + "false -- Disables using World Coordinates."); + return; + } + if (parameter.startsWith("true")) + { + this.useWorldCoordinates = true; + v.sendMessage(ChatColor.AQUA + "Enabled using World Coordinates."); + } + else if (parameter.startsWith("false")) + { + this.useWorldCoordinates = false; + v.sendMessage(ChatColor.AQUA + "Disabled using World Coordinates."); + } + else + { + v.sendMessage(ChatColor.RED + "Invalid brush parameters! use the info parameter to display parameter info."); + break; + } + } + } + + @Override + public String getPermissionNode() + { + return "voxelsniper.brush.checkervoxeldisc"; + } +} diff --git a/favs/src/main/java/com/thevoxelbox/voxelsniper/brush/CleanSnowBrush.java b/favs/src/main/java/com/thevoxelbox/voxelsniper/brush/CleanSnowBrush.java new file mode 100644 index 000000000..72e6b603a --- /dev/null +++ b/favs/src/main/java/com/thevoxelbox/voxelsniper/brush/CleanSnowBrush.java @@ -0,0 +1,113 @@ +package com.thevoxelbox.voxelsniper.brush; + +import com.thevoxelbox.voxelsniper.Message; +import com.thevoxelbox.voxelsniper.SnipeData; +import com.thevoxelbox.voxelsniper.Undo; + +import org.bukkit.ChatColor; +import org.bukkit.Material; + +/** + * http://www.voxelwiki.com/minecraft/Voxelsniper#Clean_Snow_Brush + * + * @author psanker + */ +public class CleanSnowBrush extends Brush +{ + private double trueCircle = 0; + + /** + * + */ + public CleanSnowBrush() + { + this.setName("Clean Snow"); + } + + private void cleanSnow(final SnipeData v) + { + final int brushSize = v.getBrushSize(); + final double brushSizeSquared = Math.pow(brushSize + this.trueCircle, 2); + final Undo undo = new Undo(); + + for (int y = (brushSize + 1) * 2; y >= 0; y--) + { + final double ySquared = Math.pow(y - brushSize, 2); + + for (int x = (brushSize + 1) * 2; x >= 0; x--) + { + final double xSquared = Math.pow(x - brushSize, 2); + + for (int z = (brushSize + 1) * 2; z >= 0; z--) + { + if ((xSquared + Math.pow(z - brushSize, 2) + ySquared) <= brushSizeSquared) + { + if ((this.clampY(this.getTargetBlock().getX() + x - brushSize, this.getTargetBlock().getY() + z - brushSize, this.getTargetBlock().getZ() + y - brushSize).getType() == Material.SNOW) && ((this.clampY(this.getTargetBlock().getX() + x - brushSize, this.getTargetBlock().getY() + z - brushSize - 1, this.getTargetBlock().getZ() + y - brushSize).getType() == Material.SNOW) || (this.clampY(this.getTargetBlock().getX() + x - brushSize, this.getTargetBlock().getY() + z - brushSize - 1, this.getTargetBlock().getZ() + y - brushSize).isEmpty()))) + { + undo.put(this.clampY(this.getTargetBlock().getX() + x, this.getTargetBlock().getY() + z, this.getTargetBlock().getZ() + y)); + this.setBlockIdAt(this.getTargetBlock().getZ() + y - brushSize, this.getTargetBlock().getX() + x - brushSize, this.getTargetBlock().getY() + z - brushSize, 0); + } + + } + } + } + } + + v.owner().storeUndo(undo); + } + + @Override + protected final void arrow(final SnipeData v) + { + this.cleanSnow(v); + } + + @Override + protected final void powder(final SnipeData v) + { + this.cleanSnow(v); + } + + @Override + public final void info(final Message vm) + { + vm.brushName(this.getName()); + vm.size(); + } + + @Override + public final void parameters(final String[] par, final SnipeData v) + { + for (int i = 1; i < par.length; i++) + { + final String parameter = par[i]; + + if (parameter.equalsIgnoreCase("info")) + { + v.sendMessage(ChatColor.GOLD + "Clean Snow Brush Parameters:"); + v.sendMessage(ChatColor.AQUA + "/b cls true -- will use a true sphere algorithm instead of the skinnier version with classic sniper nubs. /b cls false will switch back. (false is default)"); + return; + } + else if (parameter.startsWith("true")) + { + this.trueCircle = 0.5; + v.sendMessage(ChatColor.AQUA + "True circle mode ON."); + } + else if (parameter.startsWith("false")) + { + this.trueCircle = 0; + v.sendMessage(ChatColor.AQUA + "True circle mode OFF."); + } + else + { + v.sendMessage(ChatColor.RED + "Invalid brush parameters! use the info parameter to display parameter info."); + } + } + } + + @Override + public String getPermissionNode() + { + return "voxelsniper.brush.cleansnow"; + } +} diff --git a/favs/src/main/java/com/thevoxelbox/voxelsniper/brush/CloneStampBrush.java b/favs/src/main/java/com/thevoxelbox/voxelsniper/brush/CloneStampBrush.java new file mode 100644 index 000000000..6281ec254 --- /dev/null +++ b/favs/src/main/java/com/thevoxelbox/voxelsniper/brush/CloneStampBrush.java @@ -0,0 +1,172 @@ +package com.thevoxelbox.voxelsniper.brush; + +import com.thevoxelbox.voxelsniper.Message; +import com.thevoxelbox.voxelsniper.SnipeData; + +import org.bukkit.ChatColor; + +/** + * The CloneStamp class is used to create a collection of blocks in a cylinder shape according to the selection the player has set. + * http://www.voxelwiki.com/minecraft/Voxelsniper#Clone_and_CopyPasta_Brushes + * + * @author Voxel + */ +public class CloneStampBrush extends StampBrush +{ + /** + * + */ + public CloneStampBrush() + { + this.setName("Clone"); + } + + /** + * The clone method is used to grab a snapshot of the selected area dictated blockPositionY targetBlock.x y z v.brushSize v.voxelHeight and v.cCen. + *

+ * x y z -- initial center of the selection v.brushSize -- the radius of the cylinder v.voxelHeight -- the heigth of the cylinder c.cCen -- the offset on + * the Y axis of the selection ( bottom of the cylinder ) as blockPositionY: Bottom_Y = targetBlock.y + v.cCen; + * + * @param v + * the caller + */ + private void clone(final SnipeData v) + { + final int brushSize = v.getBrushSize(); + this.clone.clear(); + this.fall.clear(); + this.drop.clear(); + this.solid.clear(); + this.sorted = false; + + int yStartingPoint = this.getTargetBlock().getY() + v.getcCen(); + int yEndPoint = this.getTargetBlock().getY() + v.getVoxelHeight() + v.getcCen(); + + if (yStartingPoint < 0) + { + yStartingPoint = 0; + v.sendMessage(ChatColor.DARK_PURPLE + "Warning: off-world start position."); + } + else if (yStartingPoint > this.getWorld().getMaxHeight() - 1) + { + yStartingPoint = this.getWorld().getMaxHeight() - 1; + v.sendMessage(ChatColor.DARK_PURPLE + "Warning: off-world start position."); + } + + if (yEndPoint < 0) + { + yEndPoint = 0; + v.sendMessage(ChatColor.DARK_PURPLE + "Warning: off-world end position."); + } + else if (yEndPoint > this.getWorld().getMaxHeight() - 1) + { + yEndPoint = this.getWorld().getMaxHeight() - 1; + v.sendMessage(ChatColor.DARK_PURPLE + "Warning: off-world end position."); + } + + final double bSquared = Math.pow(brushSize, 2); + + for (int z = yStartingPoint; z < yEndPoint; z++) + { + this.clone.add(new BlockWrapper(this.clampY(this.getTargetBlock().getX(), z, this.getTargetBlock().getZ()), 0, z - yStartingPoint, 0)); + for (int y = 1; y <= brushSize; y++) + { + this.clone.add(new BlockWrapper(this.clampY(this.getTargetBlock().getX(), z, this.getTargetBlock().getZ() + y), 0, z - yStartingPoint, y)); + this.clone.add(new BlockWrapper(this.clampY(this.getTargetBlock().getX(), z, this.getTargetBlock().getZ() - y), 0, z - yStartingPoint, -y)); + this.clone.add(new BlockWrapper(this.clampY(this.getTargetBlock().getX() + y, z, this.getTargetBlock().getZ()), y, z - yStartingPoint, 0)); + this.clone.add(new BlockWrapper(this.clampY(this.getTargetBlock().getX() - y, z, this.getTargetBlock().getZ()), -y, z - yStartingPoint, 0)); + } + for (int x = 1; x <= brushSize; x++) + { + final double xSquared = Math.pow(x, 2); + for (int y = 1; y <= brushSize; y++) + { + if ((xSquared + Math.pow(y, 2)) <= bSquared) + { + this.clone.add(new BlockWrapper(this.clampY(this.getTargetBlock().getX() + x, z, this.getTargetBlock().getZ() + y), x, z - yStartingPoint, y)); + this.clone.add(new BlockWrapper(this.clampY(this.getTargetBlock().getX() + x, z, this.getTargetBlock().getZ() - y), x, z - yStartingPoint, -y)); + this.clone.add(new BlockWrapper(this.clampY(this.getTargetBlock().getX() - x, z, this.getTargetBlock().getZ() + y), -x, z - yStartingPoint, y)); + this.clone.add(new BlockWrapper(this.clampY(this.getTargetBlock().getX() - x, z, this.getTargetBlock().getZ() - y), -x, z - yStartingPoint, -y)); + } + } + } + } + v.sendMessage(ChatColor.GREEN + String.valueOf(this.clone.size()) + ChatColor.AQUA + " blocks copied sucessfully."); + } + + @Override + protected final void powder(final SnipeData v) + { + this.clone(v); + } + + @Override + public final void info(final Message vm) + { + vm.brushName(this.getName()); + vm.size(); + vm.height(); + vm.center(); + switch (this.stamp) + { + case DEFAULT: + vm.brushMessage("Default Stamp"); + break; + + case NO_AIR: + vm.brushMessage("No-Air Stamp"); + break; + + case FILL: + vm.brushMessage("Fill Stamp"); + break; + + default: + vm.custom(ChatColor.DARK_RED + "Error while stamping! Report"); + break; + } + } + + @Override + public final void parameters(final String[] par, final com.thevoxelbox.voxelsniper.SnipeData v) + { + final String parameter = par[1]; + + if (parameter.equalsIgnoreCase("info")) + { + v.sendMessage(ChatColor.GOLD + "Clone / Stamp Cylinder brush parameters"); + v.sendMessage(ChatColor.GREEN + "cs f -- Activates Fill mode"); + v.sendMessage(ChatColor.GREEN + "cs a -- Activates No-Air mode"); + v.sendMessage(ChatColor.GREEN + "cs d -- Activates Default mode"); + } + if (parameter.equalsIgnoreCase("a")) + { + this.setStamp(StampType.NO_AIR); + this.reSort(); + v.sendMessage(ChatColor.AQUA + "No-Air stamp brush"); + } + else if (parameter.equalsIgnoreCase("f")) + { + this.setStamp(StampType.FILL); + this.reSort(); + v.sendMessage(ChatColor.AQUA + "Fill stamp brush"); + } + else if (parameter.equalsIgnoreCase("d")) + { + this.setStamp(StampType.DEFAULT); + this.reSort(); + v.sendMessage(ChatColor.AQUA + "Default stamp brush"); + } + else if (parameter.startsWith("c")) + { + v.setcCen(Integer.parseInt(parameter.replace("c", ""))); + v.sendMessage(ChatColor.BLUE + "Center set to " + v.getcCen()); + } + } + + @Override + public String getPermissionNode() + { + return "voxelsniper.brush.clonestamp"; + } +} diff --git a/favs/src/main/java/com/thevoxelbox/voxelsniper/brush/CometBrush.java b/favs/src/main/java/com/thevoxelbox/voxelsniper/brush/CometBrush.java new file mode 100644 index 000000000..3d17a331b --- /dev/null +++ b/favs/src/main/java/com/thevoxelbox/voxelsniper/brush/CometBrush.java @@ -0,0 +1,108 @@ +package com.thevoxelbox.voxelsniper.brush; + +import org.bukkit.ChatColor; +import org.bukkit.Location; +import org.bukkit.entity.LargeFireball; +import org.bukkit.entity.SmallFireball; +import org.bukkit.util.Vector; + +import com.thevoxelbox.voxelsniper.Message; +import com.thevoxelbox.voxelsniper.SnipeData; + +/** + * @author Gavjenks Heavily revamped from ruler brush blockPositionY + * @author Giltwist + * @author Monofraps (Merged Meteor brush) + */ +public class CometBrush extends Brush +{ + private boolean useBigBalls = false; + + /** + * + */ + public CometBrush() + { + this.setName("Comet"); + } + + private void doFireball(final SnipeData v) + { + final Vector targetCoords = new Vector(this.getTargetBlock().getX() + .5 * this.getTargetBlock().getX() / Math.abs(this.getTargetBlock().getX()), this.getTargetBlock().getY() + .5, this.getTargetBlock().getZ() + .5 * this.getTargetBlock().getZ() / Math.abs(this.getTargetBlock().getZ())); + final Location playerLocation = v.owner().getPlayer().getEyeLocation(); + final Vector slope = targetCoords.subtract(playerLocation.toVector()); + + if (useBigBalls) + { + v.owner().getPlayer().launchProjectile(LargeFireball.class).setVelocity(slope.normalize()); + } + else + { + v.owner().getPlayer().launchProjectile(SmallFireball.class).setVelocity(slope.normalize()); + } + } + + @Override + public final void parameters(final String[] par, final SnipeData v) + { + for (int i = 0; i < par.length; ++i) + { + String parameter = par[i]; + + if (parameter.equalsIgnoreCase("info")) + { + v.sendMessage("Parameters:"); + v.sendMessage("balls [big|small] -- Sets your ball size."); + } + if (parameter.equalsIgnoreCase("balls")) + { + if (i + 1 >= par.length) + { + v.sendMessage("The balls parameter expects a ball size after it."); + } + + String newBallSize = par[++i]; + if (newBallSize.equalsIgnoreCase("big")) + { + useBigBalls = true; + v.sendMessage("Your balls are " + ChatColor.DARK_RED + ("BIG")); + } + else if (newBallSize.equalsIgnoreCase("small")) + { + useBigBalls = false; + v.sendMessage("Your balls are " + ChatColor.DARK_RED + ("small")); + } + else + { + v.sendMessage("Unknown ball size."); + } + } + } + } + + @Override + protected final void arrow(final SnipeData v) + { + this.doFireball(v); + } + + @Override + protected final void powder(final SnipeData v) + { + this.doFireball(v); + } + + @Override + public final void info(final Message vm) + { + vm.brushName(this.getName()); + vm.voxel(); + vm.custom("Your balls are " + ChatColor.DARK_RED + (useBigBalls ? "BIG" : "small")); + } + + @Override + public String getPermissionNode() + { + return "voxelsniper.brush.comet"; + } +} diff --git a/favs/src/main/java/com/thevoxelbox/voxelsniper/brush/CopyPastaBrush.java b/favs/src/main/java/com/thevoxelbox/voxelsniper/brush/CopyPastaBrush.java new file mode 100644 index 000000000..781be7ca8 --- /dev/null +++ b/favs/src/main/java/com/thevoxelbox/voxelsniper/brush/CopyPastaBrush.java @@ -0,0 +1,222 @@ +package com.thevoxelbox.voxelsniper.brush; + +import com.boydti.fawe.bukkit.wrapper.AsyncBlock; +import com.sk89q.worldedit.world.block.BlockTypes; +import com.thevoxelbox.voxelsniper.Message; +import com.thevoxelbox.voxelsniper.SnipeData; +import com.thevoxelbox.voxelsniper.Undo; + +import org.bukkit.ChatColor; +import org.bukkit.block.Block; + +/** + * http://www.voxelwiki.com/minecraft/Voxelsniper#CopyPasta_Brush + * + * @author giltwist + */ +public class CopyPastaBrush extends Brush +{ + private static final int BLOCK_LIMIT = 10000; + + private boolean pasteAir = true; // False = no air, true = air + private int points = 0; // + private int numBlocks = 0; + private int[] firstPoint = new int[3]; + private int[] secondPoint = new int[3]; + private int[] pastePoint = new int[3]; + private int[] minPoint = new int[3]; + private int[] offsetPoint = new int[3]; + private int[] blockArray; + private int[] arraySize = new int[3]; + private int pivot = 0; // ccw degrees + + /** + * + */ + public CopyPastaBrush() + { + this.setName("CopyPasta"); + } + + @SuppressWarnings("deprecation") + private void doCopy(final SnipeData v) + { + for (int i = 0; i < 3; i++) + { + this.arraySize[i] = Math.abs(this.firstPoint[i] - this.secondPoint[i]) + 1; + this.minPoint[i] = Math.min(this.firstPoint[i], this.secondPoint[i]); + this.offsetPoint[i] = this.minPoint[i] - this.firstPoint[i]; // will always be negative or zero + } + + this.numBlocks = (this.arraySize[0]) * (this.arraySize[1]) * (this.arraySize[2]); + + if (this.numBlocks > 0 && this.numBlocks < CopyPastaBrush.BLOCK_LIMIT) + { + this.blockArray = new int[this.numBlocks]; + + for (int i = 0; i < this.arraySize[0]; i++) + { + for (int j = 0; j < this.arraySize[1]; j++) + { + for (int k = 0; k < this.arraySize[2]; k++) + { + final int currentPosition = i + this.arraySize[0] * j + this.arraySize[0] * this.arraySize[1] * k; + this.blockArray[currentPosition] = this.getWorld().getBlockAt(this.minPoint[0] + i, this.minPoint[1] + j, this.minPoint[2] + k).getCombinedId(); + } + } + } + + v.sendMessage(ChatColor.AQUA + "" + this.numBlocks + " blocks copied."); + } + else + { + v.sendMessage(ChatColor.RED + "Copy area too big: " + this.numBlocks + "(Limit: " + CopyPastaBrush.BLOCK_LIMIT + ")"); + } + } + + @SuppressWarnings("deprecation") + private void doPasta(final SnipeData v) + { + final Undo undo = new Undo(); + + for (int i = 0; i < this.arraySize[0]; i++) + { + for (int j = 0; j < this.arraySize[1]; j++) + { + for (int k = 0; k < this.arraySize[2]; k++) + { + final int currentPosition = i + this.arraySize[0] * j + this.arraySize[0] * this.arraySize[1] * k; + AsyncBlock block; + + switch (this.pivot) + { + case 180: + block = this.clampY(this.pastePoint[0] - this.offsetPoint[0] - i, this.pastePoint[1] + this.offsetPoint[1] + j, this.pastePoint[2] - this.offsetPoint[2] - k); + break; + case 270: + block = this.clampY(this.pastePoint[0] + this.offsetPoint[2] + k, this.pastePoint[1] + this.offsetPoint[1] + j, this.pastePoint[2] - this.offsetPoint[0] - i); + break; + case 90: + block = this.clampY(this.pastePoint[0] - this.offsetPoint[2] - k, this.pastePoint[1] + this.offsetPoint[1] + j, this.pastePoint[2] + this.offsetPoint[0] + i); + break; + default: // assume no rotation + block = this.clampY(this.pastePoint[0] + this.offsetPoint[0] + i, this.pastePoint[1] + this.offsetPoint[1] + j, this.pastePoint[2] + this.offsetPoint[2] + k); + break; + } + + if (!(BlockTypes.getFromStateId(this.blockArray[currentPosition]).getMaterial().isAir() && !this.pasteAir)) + { + + if (block.getCombinedId() != this.blockArray[currentPosition]) + { + undo.put(block); + } + block.setCombinedId(this.blockArray[currentPosition]); + } + } + } + } + v.sendMessage(ChatColor.AQUA + "" + this.numBlocks + " blocks pasted."); + + v.owner().storeUndo(undo); + } + + @Override + protected final void arrow(final com.thevoxelbox.voxelsniper.SnipeData v) + { + switch (this.points) + { + case 0: + this.firstPoint[0] = this.getTargetBlock().getX(); + this.firstPoint[1] = this.getTargetBlock().getY(); + this.firstPoint[2] = this.getTargetBlock().getZ(); + v.sendMessage(ChatColor.GRAY + "First point"); + this.points = 1; + break; + case 1: + this.secondPoint[0] = this.getTargetBlock().getX(); + this.secondPoint[1] = this.getTargetBlock().getY(); + this.secondPoint[2] = this.getTargetBlock().getZ(); + v.sendMessage(ChatColor.GRAY + "Second point"); + this.points = 2; + break; + default: + this.firstPoint = new int[3]; + this.secondPoint = new int[3]; + this.numBlocks = 0; + this.blockArray = new int[1]; + this.points = 0; + v.sendMessage(ChatColor.GRAY + "Points cleared."); + break; + } + } + + @Override + protected final void powder(final com.thevoxelbox.voxelsniper.SnipeData v) + { + if (this.points == 2) + { + if (this.numBlocks == 0) + { + this.doCopy(v); + } + else if (this.numBlocks > 0 && this.numBlocks < CopyPastaBrush.BLOCK_LIMIT) + { + this.pastePoint[0] = this.getTargetBlock().getX(); + this.pastePoint[1] = this.getTargetBlock().getY(); + this.pastePoint[2] = this.getTargetBlock().getZ(); + this.doPasta(v); + } + else + { + v.sendMessage(ChatColor.RED + "Error"); + } + } + else + { + v.sendMessage(ChatColor.RED + "You must select exactly two points."); + } + } + + @Override + public final void info(final Message vm) + { + vm.brushName(this.getName()); + vm.custom(ChatColor.GOLD + "Paste air: " + this.pasteAir); + vm.custom(ChatColor.GOLD + "Pivot angle: " + this.pivot); + } + + @Override + public final void parameters(final String[] par, final com.thevoxelbox.voxelsniper.SnipeData v) + { + final String parameter = par[1]; + + if (parameter.equalsIgnoreCase("info")) + { + v.sendMessage(ChatColor.GOLD + "CopyPasta Parameters:"); + v.sendMessage(ChatColor.AQUA + "/b cp air -- toggle include (default) or exclude air during paste"); + v.sendMessage(ChatColor.AQUA + "/b cp 0|90|180|270 -- toggle rotation (0 default)"); + return; + } + + if (parameter.equalsIgnoreCase("air")) + { + this.pasteAir = !this.pasteAir; + + v.sendMessage(ChatColor.GOLD + "Paste air: " + this.pasteAir); + return; + } + + if (parameter.equalsIgnoreCase("90") || parameter.equalsIgnoreCase("180") || parameter.equalsIgnoreCase("270") || parameter.equalsIgnoreCase("0")) + { + this.pivot = Integer.parseInt(parameter); + v.sendMessage(ChatColor.GOLD + "Pivot angle: " + this.pivot); + } + } + + @Override + public String getPermissionNode() + { + return "voxelsniper.brush.copypasta"; + } +} diff --git a/favs/src/main/java/com/thevoxelbox/voxelsniper/brush/CylinderBrush.java b/favs/src/main/java/com/thevoxelbox/voxelsniper/brush/CylinderBrush.java new file mode 100644 index 000000000..4b9325e92 --- /dev/null +++ b/favs/src/main/java/com/thevoxelbox/voxelsniper/brush/CylinderBrush.java @@ -0,0 +1,146 @@ +package com.thevoxelbox.voxelsniper.brush; + +import com.thevoxelbox.voxelsniper.Message; +import com.thevoxelbox.voxelsniper.SnipeData; +import com.thevoxelbox.voxelsniper.brush.perform.PerformBrush; +import org.bukkit.ChatColor; +import org.bukkit.block.Block; + +/** + * @author Kavutop + */ +public class CylinderBrush extends PerformBrush +{ + private double trueCircle = 0; + + /** + * + */ + public CylinderBrush() + { + this.setName("Cylinder"); + } + + private void cylinder(final SnipeData v, Block targetBlock) + { + final int brushSize = v.getBrushSize(); + int yStartingPoint = targetBlock.getY() + v.getcCen(); + int yEndPoint = targetBlock.getY() + v.getVoxelHeight() + v.getcCen(); + + if (yEndPoint < yStartingPoint) + { + yEndPoint = yStartingPoint; + } + if (yStartingPoint < 0) + { + yStartingPoint = 0; + v.sendMessage(ChatColor.DARK_PURPLE + "Warning: off-world start position."); + } + else if (yStartingPoint > this.getWorld().getMaxHeight() - 1) + { + yStartingPoint = this.getWorld().getMaxHeight() - 1; + v.sendMessage(ChatColor.DARK_PURPLE + "Warning: off-world start position."); + } + if (yEndPoint < 0) + { + yEndPoint = 0; + v.sendMessage(ChatColor.DARK_PURPLE + "Warning: off-world end position."); + } + else if (yEndPoint > this.getWorld().getMaxHeight() - 1) + { + yEndPoint = this.getWorld().getMaxHeight() - 1; + v.sendMessage(ChatColor.DARK_PURPLE + "Warning: off-world end position."); + } + + final double bSquared = Math.pow(brushSize + this.trueCircle, 2); + + for (int y = yEndPoint; y >= yStartingPoint; y--) + { + for (int x = brushSize; x >= 0; x--) + { + final double xSquared = Math.pow(x, 2); + + for (int z = brushSize; z >= 0; z--) + { + if ((xSquared + Math.pow(z, 2)) <= bSquared) + { + this.current.perform(this.clampY(targetBlock.getX() + x, y, targetBlock.getZ() + z)); + this.current.perform(this.clampY(targetBlock.getX() + x, y, targetBlock.getZ() - z)); + this.current.perform(this.clampY(targetBlock.getX() - x, y, targetBlock.getZ() + z)); + this.current.perform(this.clampY(targetBlock.getX() - x, y, targetBlock.getZ() - z)); + } + } + } + } + v.owner().storeUndo(this.current.getUndo()); + } + + @Override + protected final void arrow(final SnipeData v) + { + this.cylinder(v, this.getTargetBlock()); + } + + @Override + protected final void powder(final SnipeData v) + { + this.cylinder(v, this.getLastBlock()); + } + + @Override + public final void info(final Message vm) + { + vm.brushName(this.getName()); + vm.size(); + vm.height(); + vm.center(); + } + + @Override + public final void parameters(final String[] par, final SnipeData v) + { + for (int i = 1; i < par.length; i++) + { + final String parameter = par[i]; + + if (parameter.equalsIgnoreCase("info")) + { + v.sendMessage(ChatColor.GOLD + "Cylinder Brush Parameters:"); + v.sendMessage(ChatColor.AQUA + "/b c h[number] -- set the cylinder v.voxelHeight. Default is 1."); + v.sendMessage(ChatColor.DARK_AQUA + "/b c true -- will use a true circle algorithm instead of the skinnier version with classic sniper nubs. /b b false will switch back. (false is default)"); + v.sendMessage(ChatColor.DARK_BLUE + "/b c c[number] -- set the origin of the cylinder compared to the target block. Positive numbers will move the cylinder upward, negative will move it downward."); + return; + } + if (parameter.startsWith("true")) + { + this.trueCircle = 0.5; + v.sendMessage(ChatColor.AQUA + "True circle mode ON."); + } + else if (parameter.startsWith("false")) + { + this.trueCircle = 0; + v.sendMessage(ChatColor.AQUA + "True circle mode OFF."); + } + else if (parameter.startsWith("h")) + { + v.setVoxelHeight((int) Double.parseDouble(parameter.replace("h", ""))); + v.sendMessage(ChatColor.AQUA + "Cylinder v.voxelHeight set to: " + v.getVoxelHeight()); + } + else if (parameter.startsWith("c")) + { + v.setcCen((int) Double.parseDouble(parameter.replace("c", ""))); + v.sendMessage(ChatColor.AQUA + "Cylinder origin set to: " + v.getcCen()); + } + else + { + v.sendMessage(ChatColor.RED + "Invalid brush parameters! use the info parameter to display parameter info."); + } + } + } + + @Override + public String getPermissionNode() + { + return "voxelsniper.brush.cylinder"; + } +} diff --git a/favs/src/main/java/com/thevoxelbox/voxelsniper/brush/DiscBrush.java b/favs/src/main/java/com/thevoxelbox/voxelsniper/brush/DiscBrush.java new file mode 100644 index 000000000..4423eb0c4 --- /dev/null +++ b/favs/src/main/java/com/thevoxelbox/voxelsniper/brush/DiscBrush.java @@ -0,0 +1,108 @@ +package com.thevoxelbox.voxelsniper.brush; + +import com.thevoxelbox.voxelsniper.Message; +import com.thevoxelbox.voxelsniper.SnipeData; +import com.thevoxelbox.voxelsniper.brush.perform.PerformBrush; + +import org.bukkit.ChatColor; +import org.bukkit.block.Block; +import org.bukkit.util.Vector; + +/** + * http://www.voxelwiki.com/minecraft/Voxelsniper#The_Disc_Brush + * + * @author Voxel + */ +public class DiscBrush extends PerformBrush +{ + private double trueCircle = 0; + + /** + * Default Constructor. + */ + public DiscBrush() + { + this.setName("Disc"); + } + + /** + * Disc executor. + * + * @param v + */ + private void disc(final SnipeData v, final Block targetBlock) + { + final double radiusSquared = (v.getBrushSize() + this.trueCircle) * (v.getBrushSize() + this.trueCircle); + final Vector centerPoint = targetBlock.getLocation().toVector(); + final Vector currentPoint = centerPoint.clone(); + + for (int x = -v.getBrushSize(); x <= v.getBrushSize(); x++) + { + currentPoint.setX(centerPoint.getX() + x); + for (int z = -v.getBrushSize(); z <= v.getBrushSize(); z++) + { + currentPoint.setZ(centerPoint.getZ() + z); + if (centerPoint.distanceSquared(currentPoint) <= radiusSquared) + { + this.current.perform(this.clampY(currentPoint.getBlockX(), currentPoint.getBlockY(), currentPoint.getBlockZ())); + } + } + } + v.owner().storeUndo(this.current.getUndo()); + } + + @Override + protected final void arrow(final SnipeData v) + { + this.disc(v, this.getTargetBlock()); + } + + @Override + protected final void powder(final SnipeData v) + { + this.disc(v, this.getLastBlock()); + } + + @Override + public final void info(final Message vm) + { + vm.brushName(this.getName()); + vm.size(); + } + + @Override + public final void parameters(final String[] par, final SnipeData v) + { + for (int i = 1; i < par.length; i++) + { + final String parameter = par[i].toLowerCase(); + + if (parameter.equalsIgnoreCase("info")) + { + v.sendMessage(ChatColor.GOLD + "Disc Brush Parameters:"); + v.sendMessage(ChatColor.AQUA + "/b d true|false" + " -- toggles useing the true circle algorithm instead of the skinnier version with classic sniper nubs. (false is default)"); + return; + } + else if (parameter.startsWith("true")) + { + this.trueCircle = 0.5; + v.sendMessage(ChatColor.AQUA + "True circle mode ON."); + } + else if (parameter.startsWith("false")) + { + this.trueCircle = 0; + v.sendMessage(ChatColor.AQUA + "True circle mode OFF."); + } + else + { + v.sendMessage(ChatColor.RED + "Invalid brush parameters! use the info parameter to display parameter info."); + } + } + } + + @Override + public String getPermissionNode() + { + return "voxelsniper.brush.disc"; + } +} diff --git a/favs/src/main/java/com/thevoxelbox/voxelsniper/brush/DiscFaceBrush.java b/favs/src/main/java/com/thevoxelbox/voxelsniper/brush/DiscFaceBrush.java new file mode 100644 index 000000000..f499f720d --- /dev/null +++ b/favs/src/main/java/com/thevoxelbox/voxelsniper/brush/DiscFaceBrush.java @@ -0,0 +1,181 @@ +package com.thevoxelbox.voxelsniper.brush; + +import com.boydti.fawe.bukkit.wrapper.AsyncBlock; +import com.thevoxelbox.voxelsniper.Message; +import com.thevoxelbox.voxelsniper.SnipeData; +import com.thevoxelbox.voxelsniper.brush.perform.PerformBrush; +import org.bukkit.ChatColor; +import org.bukkit.block.Block; +import org.bukkit.block.BlockFace; + +/** + * http://www.voxelwiki.com/minecraft/Voxelsniper#The_Disc_Face_Brush + * + * @author Voxel + */ +public class DiscFaceBrush extends PerformBrush +{ + private double trueCircle = 0; + + /** + * + */ + public DiscFaceBrush() + { + this.setName("Disc Face"); + } + + private void discUD(final SnipeData v, AsyncBlock targetBlock) + { + final int brushSize = v.getBrushSize(); + final double brushSizeSquared = Math.pow(brushSize + this.trueCircle, 2); + + for (int x = brushSize; x >= 0; x--) + { + final double xSquared = Math.pow(x, 2); + + for (int z = brushSize; z >= 0; z--) + { + if ((xSquared + Math.pow(z, 2)) <= brushSizeSquared) + { + current.perform(targetBlock.getRelative(x, 0, z)); + current.perform(targetBlock.getRelative(x, 0, -z)); + current.perform(targetBlock.getRelative(-x, 0, z)); + current.perform(targetBlock.getRelative(-x, 0, -z)); + } + } + } + + v.owner().storeUndo(this.current.getUndo()); + } + + private void discNS(final SnipeData v, AsyncBlock targetBlock) + { + final int brushSize = v.getBrushSize(); + final double brushSizeSquared = Math.pow(brushSize + this.trueCircle, 2); + + for (int x = brushSize; x >= 0; x--) + { + final double xSquared = Math.pow(x, 2); + for (int y = brushSize; y >= 0; y--) + { + if ((xSquared + Math.pow(y, 2)) <= brushSizeSquared) + { + current.perform(targetBlock.getRelative(x, y, 0)); + current.perform(targetBlock.getRelative(x, -y, 0)); + current.perform(targetBlock.getRelative(-x, y, 0)); + current.perform(targetBlock.getRelative(-x, -y, 0)); + } + } + } + + v.owner().storeUndo(this.current.getUndo()); + } + + private void discEW(final SnipeData v, AsyncBlock targetBlock) + { + final int brushSize = v.getBrushSize(); + final double brushSizeSquared = Math.pow(brushSize + this.trueCircle, 2); + + for (int x = brushSize; x >= 0; x--) + { + final double xSquared = Math.pow(x, 2); + for (int y = brushSize; y >= 0; y--) + { + if ((xSquared + Math.pow(y, 2)) <= brushSizeSquared) + { + current.perform(targetBlock.getRelative(0, x, y)); + current.perform(targetBlock.getRelative(0, x, -y)); + current.perform(targetBlock.getRelative(0, -x, y)); + current.perform(targetBlock.getRelative(0, -x, -y)); + } + } + } + + v.owner().storeUndo(this.current.getUndo()); + } + + private void pre(final SnipeData v, AsyncBlock targetBlock) + { + BlockFace blockFace = getTargetBlock().getFace(this.getLastBlock()); + if (blockFace == null) + { + return; + } + switch (blockFace) + { + case NORTH: + case SOUTH: + this.discNS(v, targetBlock); + break; + + case EAST: + case WEST: + this.discEW(v, targetBlock); + break; + + case UP: + case DOWN: + this.discUD(v, targetBlock); + break; + + default: + break; + } + } + + @Override + protected final void arrow(final SnipeData v) + { + this.pre(v, this.getTargetBlock()); + } + + @Override + protected final void powder(final SnipeData v) + { + this.pre(v, this.getLastBlock()); + } + + @Override + public final void info(final Message vm) + { + vm.brushName(this.getName()); + vm.size(); + } + + @Override + public final void parameters(final String[] par, final SnipeData v) + { + for (int i = 1; i < par.length; i++) + { + final String parameter = par[i]; + + if (parameter.equalsIgnoreCase("info")) + { + v.sendMessage(ChatColor.GOLD + "Disc Face brush Parameters:"); + v.sendMessage(ChatColor.AQUA + "/b df true -- will use a true circle algorithm instead of the skinnier version with classic sniper nubs. /b b false will switch back. (false is default)"); + return; + } + if (parameter.startsWith("true")) + { + this.trueCircle = 0.5; + v.sendMessage(ChatColor.AQUA + "True circle mode ON."); + } + else if (parameter.startsWith("false")) + { + this.trueCircle = 0; + v.sendMessage(ChatColor.AQUA + "True circle mode OFF."); + } + else + { + v.sendMessage(ChatColor.RED + "Invalid brush parameters! use the info parameter to display parameter info."); + } + } + } + + @Override + public String getPermissionNode() + { + return "voxelsniper.brush.discface"; + } +} diff --git a/favs/src/main/java/com/thevoxelbox/voxelsniper/brush/DomeBrush.java b/favs/src/main/java/com/thevoxelbox/voxelsniper/brush/DomeBrush.java new file mode 100644 index 000000000..19e1322a8 --- /dev/null +++ b/favs/src/main/java/com/thevoxelbox/voxelsniper/brush/DomeBrush.java @@ -0,0 +1,119 @@ +package com.thevoxelbox.voxelsniper.brush; + +import java.util.HashSet; +import java.util.Set; + +import com.boydti.fawe.bukkit.wrapper.AsyncBlock; +import com.thevoxelbox.voxelsniper.Message; +import com.thevoxelbox.voxelsniper.SnipeData; +import com.thevoxelbox.voxelsniper.Undo; + +import org.bukkit.block.Block; +import org.bukkit.util.NumberConversions; +import org.bukkit.util.Vector; + +/** + * http://www.voxelwiki.com/minecraft/Voxelsniper#Dome_Brush + * + * @author Gavjenks + * @author MikeMatrix + */ +public class DomeBrush extends Brush +{ + /** + * + */ + public DomeBrush() + { + this.setName("Dome"); + } + + @Override + public final void info(final Message vm) + { + vm.brushName(this.getName()); + vm.size(); + vm.voxel(); + vm.height(); + } + + /** + * @param v + * @param targetBlock + */ + @SuppressWarnings("deprecation") + private void generateDome(final SnipeData v, final Block targetBlock) + { + + if (v.getVoxelHeight() == 0) + { + v.sendMessage("VoxelHeight must not be 0."); + return; + } + + final int absoluteHeight = Math.abs(v.getVoxelHeight()); + final boolean negative = v.getVoxelHeight() < 0; + + final Set changeablePositions = new HashSet(); + + final Undo undo = new Undo(); + + final int brushSizeTimesVoxelHeight = v.getBrushSize() * absoluteHeight; + final double stepScale = ((v.getBrushSize() * v.getBrushSize()) + brushSizeTimesVoxelHeight + brushSizeTimesVoxelHeight) / 5; + + final double stepSize = 1 / stepScale; + + for (double u = 0; u <= Math.PI / 2; u += stepSize) + { + final double y = absoluteHeight * Math.sin(u); + for (double stepV = -Math.PI; stepV <= -(Math.PI / 2); stepV += stepSize) + { + final double x = v.getBrushSize() * Math.cos(u) * Math.cos(stepV); + final double z = v.getBrushSize() * Math.cos(u) * Math.sin(stepV); + + final double targetBlockX = targetBlock.getX() + 0.5; + final double targetBlockZ = targetBlock.getZ() + 0.5; + final int targetY = NumberConversions.floor(targetBlock.getY() + (negative ? -y : y)); + final int currentBlockXAdd = NumberConversions.floor(targetBlockX + x); + final int currentBlockZAdd = NumberConversions.floor(targetBlockZ + z); + final int currentBlockXSubtract = NumberConversions.floor(targetBlockX - x); + final int currentBlockZSubtract = NumberConversions.floor(targetBlockZ - z); + changeablePositions.add(new Vector(currentBlockXAdd, targetY, currentBlockZAdd)); + changeablePositions.add(new Vector(currentBlockXSubtract, targetY, currentBlockZAdd)); + changeablePositions.add(new Vector(currentBlockXAdd, targetY, currentBlockZSubtract)); + changeablePositions.add(new Vector(currentBlockXSubtract, targetY, currentBlockZSubtract)); + + } + } + + for (final Vector vector : changeablePositions) + { + final AsyncBlock currentTargetBlock = (AsyncBlock) vector.toLocation(this.getTargetBlock().getWorld()).getBlock(); + if (currentTargetBlock.getTypeId() != v.getVoxelId() || currentTargetBlock.getPropertyId() != v.getPropertyId()) + { + undo.put(currentTargetBlock); + currentTargetBlock.setTypeIdAndPropertyId(v.getVoxelId(), v.getPropertyId(), true); + } + } + + v.owner().storeUndo(undo); + } + + @Override + protected final void arrow(final SnipeData v) + { + this.generateDome(v, this.getTargetBlock()); + } + + @Override + protected final void powder(final SnipeData v) + { + this.generateDome(v, this.getLastBlock()); + } + + @Override + public String getPermissionNode() + { + return "voxelsniper.brush.dome"; + } +} diff --git a/favs/src/main/java/com/thevoxelbox/voxelsniper/brush/DrainBrush.java b/favs/src/main/java/com/thevoxelbox/voxelsniper/brush/DrainBrush.java new file mode 100644 index 000000000..bbf0185f5 --- /dev/null +++ b/favs/src/main/java/com/thevoxelbox/voxelsniper/brush/DrainBrush.java @@ -0,0 +1,173 @@ +package com.thevoxelbox.voxelsniper.brush; + +import com.sk89q.worldedit.world.block.BlockTypes; +import com.thevoxelbox.voxelsniper.Message; +import com.thevoxelbox.voxelsniper.SnipeData; +import com.thevoxelbox.voxelsniper.Undo; + +import org.bukkit.ChatColor; +import org.bukkit.Material; + +/** + * http://www.voxelwiki.com/minecraft/Voxelsniper#The_Drain_Brush + * + * @author Gavjenks + * @author psanker + */ +public class DrainBrush extends Brush +{ + private double trueCircle = 0; + private boolean disc = false; + + /** + * + */ + public DrainBrush() + { + this.setName("Drain"); + } + + @SuppressWarnings("deprecation") + private void drain(final SnipeData v) + { + final int brushSize = v.getBrushSize(); + final double brushSizeSquared = Math.pow(brushSize + this.trueCircle, 2); + final Undo undo = new Undo(); + + if (this.disc) + { + for (int x = brushSize; x >= 0; x--) + { + final double xSquared = Math.pow(x, 2); + + for (int y = brushSize; y >= 0; y--) + { + if ((xSquared + Math.pow(y, 2)) <= brushSizeSquared) + { + if (this.getBlockIdAt(this.getTargetBlock().getX() + x, this.getTargetBlock().getY(), this.getTargetBlock().getZ() + y) == BlockTypes.WATER.getInternalId() || this.getBlockIdAt(this.getTargetBlock().getX() + x, this.getTargetBlock().getY(), this.getTargetBlock().getZ() + y) == BlockTypes.LAVA.getInternalId()) + { + undo.put(this.clampY(this.getTargetBlock().getX() + x, this.getTargetBlock().getY(), this.getTargetBlock().getZ() + y)); + this.setBlockIdAt(this.getTargetBlock().getZ() + y, this.getTargetBlock().getX() + x, this.getTargetBlock().getY(), BlockTypes.AIR.getInternalId()); + } + + if (this.getBlockIdAt(this.getTargetBlock().getX() + x, this.getTargetBlock().getY(), this.getTargetBlock().getZ() - y) == BlockTypes.WATER.getInternalId() || this.getBlockIdAt(this.getTargetBlock().getX() + x, this.getTargetBlock().getY(), this.getTargetBlock().getZ() - y) == BlockTypes.LAVA.getInternalId()) + { + undo.put(this.clampY(this.getTargetBlock().getX() + x, this.getTargetBlock().getY(), this.getTargetBlock().getZ() - y)); + this.setBlockIdAt(this.getTargetBlock().getZ() - y, this.getTargetBlock().getX() + x, this.getTargetBlock().getY(), BlockTypes.AIR.getInternalId()); + } + + if (this.getBlockIdAt(this.getTargetBlock().getX() - x, this.getTargetBlock().getY(), this.getTargetBlock().getZ() + y) == BlockTypes.WATER.getInternalId() || this.getBlockIdAt(this.getTargetBlock().getX() - x, this.getTargetBlock().getY(), this.getTargetBlock().getZ() + y) == BlockTypes.LAVA.getInternalId()) + { + undo.put(this.clampY(this.getTargetBlock().getX() - x, this.getTargetBlock().getY(), this.getTargetBlock().getZ() + y)); + this.setBlockIdAt(this.getTargetBlock().getZ() + y, this.getTargetBlock().getX() - x, this.getTargetBlock().getY(), BlockTypes.AIR.getInternalId()); + } + + if (this.getBlockIdAt(this.getTargetBlock().getX() - x, this.getTargetBlock().getY(), this.getTargetBlock().getZ() - y) == BlockTypes.WATER.getInternalId() || this.getBlockIdAt(this.getTargetBlock().getX() - x, this.getTargetBlock().getY(), this.getTargetBlock().getZ() - y) == BlockTypes.LAVA.getInternalId()) + { + undo.put(this.clampY(this.getTargetBlock().getX() - x, this.getTargetBlock().getY(), this.getTargetBlock().getZ() - y)); + this.setBlockIdAt(this.getTargetBlock().getZ() - y, this.getTargetBlock().getX() - x, this.getTargetBlock().getY(), BlockTypes.AIR.getInternalId()); + } + } + } + } + } + else + { + for (int y = (brushSize + 1) * 2; y >= 0; y--) + { + final double ySquared = Math.pow(y - brushSize, 2); + + for (int x = (brushSize + 1) * 2; x >= 0; x--) + { + final double xSquared = Math.pow(x - brushSize, 2); + + for (int z = (brushSize + 1) * 2; z >= 0; z--) + { + if ((xSquared + Math.pow(z - brushSize, 2) + ySquared) <= brushSizeSquared) + { + if (this.getBlockIdAt(this.getTargetBlock().getX() + x - brushSize, this.getTargetBlock().getY() + z - brushSize, this.getTargetBlock().getZ() + y - brushSize) == BlockTypes.WATER.getInternalId() || this.getBlockIdAt(this.getTargetBlock().getX() + x - brushSize, this.getTargetBlock().getY() + z - brushSize, this.getTargetBlock().getZ() + y - brushSize) == BlockTypes.LAVA.getInternalId()) + { + undo.put(this.clampY(this.getTargetBlock().getX() + x, this.getTargetBlock().getY() + z, this.getTargetBlock().getZ() + y)); + this.setBlockIdAt(this.getTargetBlock().getZ() + y - brushSize, this.getTargetBlock().getX() + x - brushSize, this.getTargetBlock().getY() + z - brushSize, BlockTypes.AIR.getInternalId()); + } + } + } + } + } + } + + v.owner().storeUndo(undo); + } + + @Override + protected final void arrow(final SnipeData v) + { + this.drain(v); + } + + @Override + protected final void powder(final SnipeData v) + { + this.drain(v); + } + + @Override + public final void info(final Message vm) + { + vm.brushName(this.getName()); + vm.size(); + + vm.custom(ChatColor.AQUA + ((this.trueCircle == 0.5) ? "True circle mode ON" : "True circle mode OFF")); + vm.custom(ChatColor.AQUA + ((this.disc) ? "Disc drain mode ON" : "Disc drain mode OFF")); + } + + @Override + public final void parameters(final String[] par, final SnipeData v) + { + for (int i = 1; i < par.length; i++) + { + final String parameter = par[i]; + + if (parameter.equalsIgnoreCase("info")) + { + v.sendMessage(ChatColor.GOLD + "Drain Brush Parameters:"); + v.sendMessage(ChatColor.AQUA + "/b drain true -- will use a true sphere algorithm instead of the skinnier version with classic sniper nubs. /b drain false will switch back. (false is default)"); + v.sendMessage(ChatColor.AQUA + "/b drain d -- toggles disc drain mode, as opposed to a ball drain mode"); + return; + } + else if (parameter.startsWith("true")) + { + this.trueCircle = 0.5; + v.sendMessage(ChatColor.AQUA + "True circle mode ON."); + } + else if (parameter.startsWith("false")) + { + this.trueCircle = 0; + v.sendMessage(ChatColor.AQUA + "True circle mode OFF."); + } + else if (parameter.equalsIgnoreCase("d")) + { + if (this.disc) + { + this.disc = false; + v.sendMessage(ChatColor.AQUA + "Disc drain mode OFF"); + } + else + { + this.disc = true; + v.sendMessage(ChatColor.AQUA + "Disc drain mode ON"); + } + } + else + { + v.sendMessage(ChatColor.RED + "Invalid brush parameters! use the info parameter to display parameter info."); + } + } + } + + @Override + public String getPermissionNode() + { + return "voxelsniper.brush.drain"; + } +} diff --git a/favs/src/main/java/com/thevoxelbox/voxelsniper/brush/EllipseBrush.java b/favs/src/main/java/com/thevoxelbox/voxelsniper/brush/EllipseBrush.java new file mode 100644 index 000000000..2eeedffe9 --- /dev/null +++ b/favs/src/main/java/com/thevoxelbox/voxelsniper/brush/EllipseBrush.java @@ -0,0 +1,304 @@ +package com.thevoxelbox.voxelsniper.brush; + +import com.boydti.fawe.bukkit.wrapper.AsyncBlock; +import com.thevoxelbox.voxelsniper.Message; +import com.thevoxelbox.voxelsniper.SnipeData; +import com.thevoxelbox.voxelsniper.brush.perform.PerformBrush; +import org.bukkit.ChatColor; +import org.bukkit.block.Block; + +/** + * http://www.voxelwiki.com/minecraft/Voxelsniper#Ellipse_Brush + * + * @author psanker + */ +public class EllipseBrush extends PerformBrush +{ + private static final double TWO_PI = (2 * Math.PI); + private static final int SCL_MIN = 1; + private static final int SCL_MAX = 9999; + private static final int SCL_DEFAULT = 10; + private static final int STEPS_MIN = 1; + private static final int STEPS_MAX = 2000; + private static final int STEPS_DEFAULT = 200; + private int xscl; + private int yscl; + private int steps; + private double stepSize; + private boolean fill; + + /** + * + */ + public EllipseBrush() + { + this.setName("Ellipse"); + } + + private void ellipse(final SnipeData v, AsyncBlock targetBlock) + { + try + { + for (double steps = 0; (steps <= TWO_PI); steps += stepSize) + { + final int x = (int) Math.round(this.xscl * Math.cos(steps)); + final int y = (int) Math.round(this.yscl * Math.sin(steps)); + + switch (getTargetBlock().getFace(this.getLastBlock())) + { + case NORTH: + case SOUTH: + current.perform(targetBlock.getRelative(0, x, y)); + break; + case EAST: + case WEST: + current.perform(targetBlock.getRelative(x, y, 0)); + break; + case UP: + case DOWN: + current.perform(targetBlock.getRelative(x, 0, y)); + default: + break; + } + + if (steps >= TWO_PI) + { + break; + } + } + } + catch (final Exception exception) + { + v.sendMessage(ChatColor.RED + "Invalid target."); + } + + v.owner().storeUndo(this.current.getUndo()); + } + + private void ellipsefill(final SnipeData v, AsyncBlock targetBlock) + { + int ix = this.xscl; + int iy = this.yscl; + + current.perform(targetBlock); + + try + { + if (ix >= iy) + { // Need this unless you want weird holes + for (iy = this.yscl; iy > 0; iy--) + { + for (double steps = 0; (steps <= TWO_PI); steps += stepSize) + { + final int x = (int) Math.round(ix * Math.cos(steps)); + final int y = (int) Math.round(iy * Math.sin(steps)); + + switch (getTargetBlock().getFace(this.getLastBlock())) + { + case NORTH: + case SOUTH: + current.perform(targetBlock.getRelative(0, x, y)); + break; + case EAST: + case WEST: + current.perform(targetBlock.getRelative(x, y, 0)); + break; + case UP: + case DOWN: + current.perform(targetBlock.getRelative(x, 0, y)); + default: + break; + } + + if (steps >= TWO_PI) + { + break; + } + } + ix--; + } + } + else + { + for (ix = this.xscl; ix > 0; ix--) + { + for (double steps = 0; (steps <= TWO_PI); steps += stepSize) + { + final int x = (int) Math.round(ix * Math.cos(steps)); + final int y = (int) Math.round(iy * Math.sin(steps)); + + switch (getTargetBlock().getFace(this.getLastBlock())) + { + case NORTH: + case SOUTH: + current.perform(targetBlock.getRelative(0, x, y)); + break; + case EAST: + case WEST: + current.perform(targetBlock.getRelative(x, y, 0)); + break; + case UP: + case DOWN: + current.perform(targetBlock.getRelative(x, 0, y)); + default: + break; + } + + if (steps >= TWO_PI) + { + break; + } + } + iy--; + } + } + } + catch (final Exception exception) + { + v.sendMessage(ChatColor.RED + "Invalid target."); + } + + v.owner().storeUndo(this.current.getUndo()); + } + + private void execute(final SnipeData v, AsyncBlock targetBlock) + { + this.stepSize = (TWO_PI / this.steps); + + if (this.fill) + { + this.ellipsefill(v, targetBlock); + } + else + { + this.ellipse(v, targetBlock); + } + } + + @Override + protected final void arrow(final SnipeData v) + { + this.execute(v, this.getTargetBlock()); + } + + @Override + protected final void powder(final SnipeData v) + { + this.execute(v, this.getLastBlock()); + } + + @Override + public final void info(final Message vm) + { + if (this.xscl < SCL_MIN || this.xscl > SCL_MAX) + { + this.xscl = SCL_DEFAULT; + } + + if (this.yscl < SCL_MIN || this.yscl > SCL_MAX) + { + this.yscl = SCL_DEFAULT; + } + + if (this.steps < STEPS_MIN || this.steps > STEPS_MAX) + { + this.steps = STEPS_DEFAULT; + } + + vm.brushName(this.getName()); + vm.custom(ChatColor.AQUA + "X-size set to: " + ChatColor.DARK_AQUA + this.xscl); + vm.custom(ChatColor.AQUA + "Y-size set to: " + ChatColor.DARK_AQUA + this.yscl); + vm.custom(ChatColor.AQUA + "Render step number set to: " + ChatColor.DARK_AQUA + this.steps); + if (this.fill) + { + vm.custom(ChatColor.AQUA + "Fill mode is enabled"); + } + else + { + vm.custom(ChatColor.AQUA + "Fill mode is disabled"); + } + } + + @Override + public final void parameters(final String[] par, final com.thevoxelbox.voxelsniper.SnipeData v) + { + for (int i = 1; i < par.length; i++) + { + final String parameter = par[i]; + + try + { + if (parameter.equalsIgnoreCase("info")) + { + v.sendMessage(ChatColor.GOLD + "Ellipse brush parameters"); + v.sendMessage(ChatColor.AQUA + "x[n]: Set X size modifier to n"); + v.sendMessage(ChatColor.AQUA + "y[n]: Set Y size modifier to n"); + v.sendMessage(ChatColor.AQUA + "t[n]: Set the amount of time steps"); + v.sendMessage(ChatColor.AQUA + "fill: Toggles fill mode"); + return; + } + else if (parameter.startsWith("x")) + { + int tempXScale = Integer.parseInt(par[i].replace("x", "")); + if (tempXScale < SCL_MIN || tempXScale > SCL_MAX) + { + v.sendMessage(ChatColor.AQUA + "Invalid X scale (" + SCL_MIN + "-" + SCL_MAX + ")"); + continue; + } + this.xscl = tempXScale; + v.sendMessage(ChatColor.AQUA + "X-scale modifier set to: " + this.xscl); + } + else if (parameter.startsWith("y")) + { + int tempYScale = Integer.parseInt(par[i].replace("y", "")); + if (tempYScale < SCL_MIN || tempYScale > SCL_MAX) + { + v.sendMessage(ChatColor.AQUA + "Invalid Y scale (" + SCL_MIN + "-" + SCL_MAX + ")"); + continue; + } + this.yscl = tempYScale; + v.sendMessage(ChatColor.AQUA + "Y-scale modifier set to: " + this.yscl); + } + else if (parameter.startsWith("t")) + { + int tempSteps = Integer.parseInt(par[i].replace("t", "")); + if (tempSteps < STEPS_MIN || tempSteps > STEPS_MAX) + { + v.sendMessage(ChatColor.AQUA + "Invalid step number (" + STEPS_MIN + "-" + STEPS_MAX + ")"); + continue; + } + this.steps = tempSteps; + v.sendMessage(ChatColor.AQUA + "Render step number set to: " + this.steps); + } + else if (parameter.equalsIgnoreCase("fill")) + { + if (this.fill) + { + this.fill = false; + v.sendMessage(ChatColor.AQUA + "Fill mode is disabled"); + } + else + { + this.fill = true; + v.sendMessage(ChatColor.AQUA + "Fill mode is enabled"); + } + } + else + { + v.sendMessage(ChatColor.RED + "Invalid brush parameters! Use the \"info\" parameter to display parameter info."); + } + + } + catch (final Exception exception) + { + v.sendMessage(ChatColor.RED + "Incorrect parameter \"" + parameter + "\"; use the \"info\" parameter."); + } + } + } + + @Override + public String getPermissionNode() + { + return "voxelsniper.brush.ellipse"; + } +} diff --git a/favs/src/main/java/com/thevoxelbox/voxelsniper/brush/EllipsoidBrush.java b/favs/src/main/java/com/thevoxelbox/voxelsniper/brush/EllipsoidBrush.java new file mode 100644 index 000000000..8286df26a --- /dev/null +++ b/favs/src/main/java/com/thevoxelbox/voxelsniper/brush/EllipsoidBrush.java @@ -0,0 +1,147 @@ +package com.thevoxelbox.voxelsniper.brush; + +import com.boydti.fawe.bukkit.wrapper.AsyncBlock; +import com.thevoxelbox.voxelsniper.Message; +import com.thevoxelbox.voxelsniper.SnipeData; +import com.thevoxelbox.voxelsniper.brush.perform.PerformBrush; +import org.bukkit.ChatColor; +import org.bukkit.block.Block; + +/** + * http://www.voxelwiki.com/minecraft/Voxelsniper#Ellipsoid_Brush + * + */ +public class EllipsoidBrush extends PerformBrush +{ + private double xRad; + private double yRad; + private double zRad; + private boolean istrue; + + /** + * + */ + public EllipsoidBrush() + { + this.setName("Ellipsoid"); + } + + private void execute(final SnipeData v, AsyncBlock targetBlock) + { + this.current.perform(targetBlock); + double istrueoffset = istrue ? 0.5 : 0; + int blockPositionX = targetBlock.getX(); + int blockPositionY = targetBlock.getY(); + int blockPositionZ = targetBlock.getZ(); + + for (double x = 0; x <= xRad; x++) + { + + final double xSquared = (x / (xRad + istrueoffset)) * (x / (xRad + istrueoffset)); + + for (double z = 0; z <= zRad; z++) + { + + final double zSquared = (z / (zRad + istrueoffset)) * (z / (zRad + istrueoffset)); + + for (double y = 0; y <= yRad; y++) + { + + final double ySquared = (y / (yRad + istrueoffset)) * (y / (yRad + istrueoffset)); + + if (xSquared + ySquared + zSquared <= 1) + { + this.current.perform(this.clampY((int) (blockPositionX + x), (int) (blockPositionY + y), (int) (blockPositionZ + z))); + this.current.perform(this.clampY((int) (blockPositionX + x), (int) (blockPositionY + y), (int) (blockPositionZ - z))); + this.current.perform(this.clampY((int) (blockPositionX + x), (int) (blockPositionY - y), (int) (blockPositionZ + z))); + this.current.perform(this.clampY((int) (blockPositionX + x), (int) (blockPositionY - y), (int) (blockPositionZ - z))); + this.current.perform(this.clampY((int) (blockPositionX - x), (int) (blockPositionY + y), (int) (blockPositionZ + z))); + this.current.perform(this.clampY((int) (blockPositionX - x), (int) (blockPositionY + y), (int) (blockPositionZ - z))); + this.current.perform(this.clampY((int) (blockPositionX - x), (int) (blockPositionY - y), (int) (blockPositionZ + z))); + this.current.perform(this.clampY((int) (blockPositionX - x), (int) (blockPositionY - y), (int) (blockPositionZ - z))); + } + + } + } + } + + v.owner().storeUndo(this.current.getUndo()); + } + + @Override + protected final void arrow(final SnipeData v) + { + this.execute(v, this.getTargetBlock()); + } + + @Override + protected final void powder(final SnipeData v) + { + this.execute(v, this.getLastBlock()); + } + + @Override + public final void info(final Message vm) + { + vm.brushName(this.getName()); + vm.custom(ChatColor.AQUA + "X-size set to: " + ChatColor.DARK_AQUA + this.xRad); + vm.custom(ChatColor.AQUA + "Y-size set to: " + ChatColor.DARK_AQUA + this.yRad); + vm.custom(ChatColor.AQUA + "Z-size set to: " + ChatColor.DARK_AQUA + this.zRad); + } + + @Override + public final void parameters(final String[] par, final com.thevoxelbox.voxelsniper.SnipeData v) + { + this.istrue = false; + for (int i = 1; i < par.length; i++) + { + final String parameter = par[i]; + + try + { + if (parameter.equalsIgnoreCase("info")) + { + v.sendMessage(ChatColor.GOLD + "Ellipse brush parameters"); + v.sendMessage(ChatColor.AQUA + "x[n]: Set X radius to n"); + v.sendMessage(ChatColor.AQUA + "y[n]: Set Y radius to n"); + v.sendMessage(ChatColor.AQUA + "z[n]: Set Z radius to n"); + return; + } + else if (parameter.startsWith("x")) + { + this.xRad = Integer.parseInt(par[i].replace("x", "")); + v.sendMessage(ChatColor.AQUA + "X radius set to: " + this.xRad); + } + else if (parameter.startsWith("y")) + { + this.yRad = Integer.parseInt(par[i].replace("y", "")); + v.sendMessage(ChatColor.AQUA + "Y radius set to: " + this.yRad); + } + else if (parameter.startsWith("z")) + { + this.zRad = Integer.parseInt(par[i].replace("z", "")); + v.sendMessage(ChatColor.AQUA + "Z radius set to: " + this.zRad); + } + else if (parameter.equalsIgnoreCase("true")) + { + this.istrue = true; + } + else + { + v.sendMessage(ChatColor.RED + "Invalid brush parameters! Use the \"info\" parameter to display parameter info."); + } + + } + catch (final Exception exception) + { + v.sendMessage(ChatColor.RED + "Incorrect parameter \"" + parameter + "\"; use the \"info\" parameter."); + } + } + } + + @Override + public String getPermissionNode() + { + return "voxelsniper.brush.ellipsoid"; + } +} diff --git a/favs/src/main/java/com/thevoxelbox/voxelsniper/brush/EntityBrush.java b/favs/src/main/java/com/thevoxelbox/voxelsniper/brush/EntityBrush.java new file mode 100644 index 000000000..0ef9fdb63 --- /dev/null +++ b/favs/src/main/java/com/thevoxelbox/voxelsniper/brush/EntityBrush.java @@ -0,0 +1,98 @@ +package com.thevoxelbox.voxelsniper.brush; + +import com.thevoxelbox.voxelsniper.Message; +import com.thevoxelbox.voxelsniper.SnipeData; + +import org.bukkit.ChatColor; +import org.bukkit.entity.EntityType; + +/** + * http://www.voxelwiki.com/minecraft/Voxelsniper#The_Entity_Brush + * + * @author Piotr + */ +public class EntityBrush extends Brush +{ + private EntityType entityType = EntityType.ZOMBIE; + + /** + * + */ + public EntityBrush() + { + this.setName("Entity"); + } + + private void spawn(final SnipeData v) + { + for (int x = 0; x < v.getBrushSize(); x++) + { + try + { + this.getWorld().spawn(this.getLastBlock().getLocation(), this.entityType.getEntityClass()); + } + catch (final IllegalArgumentException exception) + { + v.sendMessage(ChatColor.RED + "Cannot spawn entity!"); + } + } + } + + @Override + protected final void arrow(final SnipeData v) + { + this.spawn(v); + } + + @Override + protected final void powder(final SnipeData v) + { + this.spawn(v); + } + + @SuppressWarnings("deprecation") + @Override + public final void info(final Message vm) + { + vm.brushMessage(ChatColor.LIGHT_PURPLE + "Entity brush" + " (" + this.entityType.getName() + ")"); + vm.size(); + } + + @SuppressWarnings("deprecation") + @Override + public final void parameters(final String[] par, final SnipeData v) + { + if (par[1].equalsIgnoreCase("info")) + { + String names = ""; + + v.sendMessage(ChatColor.BLUE + "The available entity types are as follows:"); + for (final EntityType currentEntity : EntityType.values()) + { + + names += ChatColor.AQUA + " | " + ChatColor.DARK_GREEN + currentEntity.getName(); + } + names += ChatColor.AQUA + " |"; + v.sendMessage(names); + } + else + { + final EntityType currentEntity = EntityType.fromName(par[1]); + if (currentEntity != null) + { + this.entityType = currentEntity; + v.sendMessage(ChatColor.GREEN + "Entity type set to " + this.entityType.getName()); + } + else + { + v.sendMessage(ChatColor.RED + "This is not a valid entity!"); + } + } + } + + @Override + public String getPermissionNode() + { + return "voxelsniper.brush.entity"; + } +} diff --git a/favs/src/main/java/com/thevoxelbox/voxelsniper/brush/EntityRemovalBrush.java b/favs/src/main/java/com/thevoxelbox/voxelsniper/brush/EntityRemovalBrush.java new file mode 100644 index 000000000..0d6871621 --- /dev/null +++ b/favs/src/main/java/com/thevoxelbox/voxelsniper/brush/EntityRemovalBrush.java @@ -0,0 +1,187 @@ +package com.thevoxelbox.voxelsniper.brush; + +import com.thevoxelbox.voxelsniper.Message; +import com.thevoxelbox.voxelsniper.SnipeData; +import org.bukkit.ChatColor; +import org.bukkit.Chunk; +import org.bukkit.entity.Entity; + +import java.util.ArrayList; +import java.util.Iterator; +import java.util.List; +import java.util.regex.PatternSyntaxException; + +/** + * + */ +public class EntityRemovalBrush extends Brush +{ + private final List exemptions = new ArrayList(3); + + /** + * + */ + public EntityRemovalBrush() + { + this.setName("Entity Removal"); + + exemptions.add("org.bukkit.entity.Player"); + exemptions.add("org.bukkit.entity.Hanging"); + exemptions.add("org.bukkit.entity.NPC"); + } + + private void radialRemoval(SnipeData v) + { + final Chunk targetChunk = getTargetBlock().getChunk(); + int entityCount = 0; + int chunkCount = 0; + + try + { + entityCount += removeEntities(targetChunk); + + int radius = Math.round(v.getBrushSize() / 16); + + for (int x = targetChunk.getX() - radius; x <= targetChunk.getX() + radius; x++) + { + for (int z = targetChunk.getZ() - radius; z <= targetChunk.getZ() + radius; z++) + { + entityCount += removeEntities(getWorld().getChunkAt(x, z)); + + chunkCount++; + } + } + } + catch (final PatternSyntaxException pse) + { + pse.printStackTrace(); + v.sendMessage(ChatColor.RED + "Error in RegEx: " + ChatColor.LIGHT_PURPLE + pse.getPattern()); + v.sendMessage(ChatColor.RED + String.format("%s (Index: %d)", pse.getDescription(), pse.getIndex())); + } + v.sendMessage(ChatColor.GREEN + "Removed " + ChatColor.RED + entityCount + ChatColor.GREEN + " entities out of " + ChatColor.BLUE + chunkCount + ChatColor.GREEN + (chunkCount == 1 ? " chunk." : " chunks.")); + } + + private int removeEntities(Chunk chunk) throws PatternSyntaxException + { + int entityCount = 0; + + for (Entity entity : chunk.getEntities()) + { + if (isClassInExemptionList(entity.getClass())) + { + continue; + } + + entity.remove(); + entityCount++; + } + + return entityCount; + } + + private boolean isClassInExemptionList(Class entityClass) throws PatternSyntaxException + { + // Create a list of superclasses and interfaces implemented by the current entity type + final List entityClassHierarchy = new ArrayList(); + + Class currentClass = entityClass; + while (currentClass != null && !currentClass.equals(Object.class)) + { + entityClassHierarchy.add(currentClass.getCanonicalName()); + + for (final Class intrf : currentClass.getInterfaces()) + { + entityClassHierarchy.add(intrf.getCanonicalName()); + } + + currentClass = currentClass.getSuperclass(); + } + + for (final String exemptionPattern : exemptions) + { + for (final String typeName : entityClassHierarchy) + { + if (typeName.matches(exemptionPattern)) + { + return true; + } + + } + } + + return false; + } + + @Override + protected void arrow(SnipeData v) + { + this.radialRemoval(v); + } + + @Override + protected void powder(SnipeData v) + { + this.radialRemoval(v); + } + + @Override + public void info(Message vm) + { + vm.brushName(getName()); + + final StringBuilder exemptionsList = new StringBuilder(ChatColor.GREEN + "Exemptions: " + ChatColor.LIGHT_PURPLE); + for (Iterator it = exemptions.iterator(); it.hasNext(); ) + { + exemptionsList.append(it.next()); + if (it.hasNext()) + { + exemptionsList.append(", "); + } + } + vm.custom(exemptionsList.toString()); + + vm.size(); + } + + @Override + public void parameters(final String[] par, final SnipeData v) + { + for (final String currentParam : par) + { + if (currentParam.startsWith("+") || currentParam.startsWith("-")) + { + final boolean isAddOperation = currentParam.startsWith("+"); + + // +#/-# will suppress auto-prefixing + final String exemptionPattern = currentParam.startsWith("+#") || currentParam.startsWith("-#") ? + currentParam.substring(2) : + (currentParam.contains(".") ? currentParam.substring(1) : ".*." + currentParam.substring(1)); + + if (isAddOperation) + { + exemptions.add(exemptionPattern); + v.sendMessage(String.format("Added %s to entity exemptions list.", exemptionPattern)); + } + else + { + exemptions.remove(exemptionPattern); + v.sendMessage(String.format("Removed %s from entity exemptions list.", exemptionPattern)); + } + } + + if (currentParam.equalsIgnoreCase("list-exemptions") || currentParam.equalsIgnoreCase("lex")) + { + for (final String exemption : exemptions) + { + v.sendMessage(ChatColor.LIGHT_PURPLE + exemption); + } + } + } + } + + @Override + public String getPermissionNode() + { + return "voxelsniper.brush.entityremoval"; + } +} diff --git a/favs/src/main/java/com/thevoxelbox/voxelsniper/brush/EraserBrush.java b/favs/src/main/java/com/thevoxelbox/voxelsniper/brush/EraserBrush.java new file mode 100644 index 000000000..05125e13d --- /dev/null +++ b/favs/src/main/java/com/thevoxelbox/voxelsniper/brush/EraserBrush.java @@ -0,0 +1,88 @@ +package com.thevoxelbox.voxelsniper.brush; + +import com.thevoxelbox.voxelsniper.Message; +import com.thevoxelbox.voxelsniper.SnipeData; +import com.thevoxelbox.voxelsniper.Undo; +import java.util.EnumSet; +import java.util.Set; + +import org.bukkit.Material; +import org.bukkit.World; +import org.bukkit.block.Block; + +/** + * http://www.voxelwiki.com/minecraft/Voxelsniper#Eraser_Brush + * + * @author Voxel + */ +public class EraserBrush extends Brush +{ + + private static final Set EXCLUSIVE_MATERIALS = EnumSet.of( + Material.AIR, Material.STONE, Material.GRASS, Material.DIRT, Material.SAND, Material.GRAVEL, Material.SANDSTONE); + private static final Set EXCLUSIVE_LIQUIDS = EnumSet.of( + Material.WATER, Material.WATER, Material.LAVA, Material.LAVA); + + /** + * + */ + public EraserBrush() + { + this.setName("Eraser"); + } + + private void doErase(final SnipeData v, final boolean keepWater) + { + final int brushSize = v.getBrushSize(); + final int brushSizeDoubled = 2 * brushSize; + World world = this.getTargetBlock().getWorld(); + final Undo undo = new Undo(); + + for (int x = brushSizeDoubled; x >= 0; x--) + { + int currentX = this.getTargetBlock().getX() - brushSize + x; + for (int y = 0; y <= brushSizeDoubled; y++) + { + int currentY = this.getTargetBlock().getY() - brushSize + y; + for (int z = brushSizeDoubled; z >= 0; z--) + { + int currentZ = this.getTargetBlock().getZ() - brushSize + z; + Block currentBlock = world.getBlockAt(currentX, currentY, currentZ); + if (EXCLUSIVE_MATERIALS.contains(currentBlock.getType()) + || (keepWater && EXCLUSIVE_LIQUIDS.contains(currentBlock.getType()))) + { + continue; + } + undo.put(currentBlock); + currentBlock.setType(Material.AIR); + } + } + } + v.owner().storeUndo(undo); + } + + @Override + protected final void arrow(final SnipeData v) + { + this.doErase(v, false); + } + + @Override + protected final void powder(final SnipeData v) + { + this.doErase(v, true); + } + + @Override + public final void info(final Message vm) + { + vm.brushName(this.getName()); + vm.size(); + } + + @Override + public String getPermissionNode() + { + return "voxelsniper.brush.eraser"; + } +} diff --git a/favs/src/main/java/com/thevoxelbox/voxelsniper/brush/ErodeBrush.java b/favs/src/main/java/com/thevoxelbox/voxelsniper/brush/ErodeBrush.java new file mode 100644 index 000000000..90ec7beb9 --- /dev/null +++ b/favs/src/main/java/com/thevoxelbox/voxelsniper/brush/ErodeBrush.java @@ -0,0 +1,570 @@ +package com.thevoxelbox.voxelsniper.brush; + +import com.boydti.fawe.bukkit.wrapper.AsyncBlock; +import com.boydti.fawe.bukkit.wrapper.AsyncWorld; +import com.google.common.base.Objects; +import com.martiansoftware.jsap.FlaggedOption; +import com.martiansoftware.jsap.JSAPException; +import com.martiansoftware.jsap.JSAPResult; +import com.martiansoftware.jsap.UnflaggedOption; +import com.martiansoftware.jsap.stringparsers.EnumeratedStringParser; +import com.massivecraft.factions.P; +import com.thevoxelbox.voxelsniper.Message; +import com.thevoxelbox.voxelsniper.SnipeData; +import com.thevoxelbox.voxelsniper.Undo; +import com.thevoxelbox.voxelsniper.jsap.HelpJSAP; +import com.thevoxelbox.voxelsniper.jsap.NullableIntegerStringParser; +import org.bukkit.ChatColor; +import org.bukkit.Material; +import org.bukkit.entity.Player; +import org.bukkit.util.ChatPaginator; +import org.bukkit.util.Vector; + +import java.util.Arrays; +import java.util.Collection; +import java.util.HashMap; +import java.util.List; +import java.util.Map; + +/** + * http://www.voxelwiki.com/minecraft/VoxelSniper#The_Erosion_Brush + * + * @author Piotr + * @author MikeMatrix + */ +public class ErodeBrush extends Brush +{ + private static final Vector[] FACES_TO_CHECK = {new Vector(0, 0, 1), new Vector(0, 0, -1), new Vector(0, 1, 0), new Vector(0, -1, 0), new Vector(1, 0, 0), new Vector(-1, 0, 0)}; + private final HelpJSAP parser = new HelpJSAP("/b e", "Brush for eroding landscape.", ChatPaginator.GUARANTEED_NO_WRAP_CHAT_PAGE_WIDTH); + private ErosionPreset currentPreset = new ErosionPreset(0, 1, 0, 1); + + /** + * + */ + public ErodeBrush() + { + this.setName("Erode"); + + try + { + this.parser.registerParameter(new UnflaggedOption("preset", EnumeratedStringParser.getParser(Preset.getValuesString(";"), false), null, false, false, "Preset options: " + Preset.getValuesString(", "))); + this.parser.registerParameter(new FlaggedOption("fill", NullableIntegerStringParser.getParser(), null, false, 'f', "fill", "Surrounding blocks required to fill the block.")); + this.parser.registerParameter(new FlaggedOption("erode", NullableIntegerStringParser.getParser(), null, false, 'e', "erode", "Surrounding air required to erode the block.")); + this.parser.registerParameter(new FlaggedOption("fillrecursion", NullableIntegerStringParser.getParser(), null, false, 'F', "fillrecursion", "Repeated fill iterations.")); + this.parser.registerParameter(new FlaggedOption("eroderecursion", NullableIntegerStringParser.getParser(), null, false, 'E', "eroderecursion", "Repeated erode iterations.")); + } + catch (JSAPException ignored) + { + } + } + + /** + * @param result + * @param player + * @param helpJSAP + * @return if a message was sent. + */ + public static boolean sendHelpOrErrorMessageToPlayer(final JSAPResult result, final Player player, final HelpJSAP helpJSAP) + { + final List output = helpJSAP.writeHelpOrErrorMessageIfRequired(result); + if (!output.isEmpty()) + { + for (final String string : output) + { + player.sendMessage(string); + } + return true; + } + return false; + } + + @Override + protected final void arrow(final SnipeData v) + { + this.erosion(v, this.currentPreset); + } + + @SuppressWarnings("deprecation") + private void erosion(final SnipeData v, final ErosionPreset erosionPreset) + { + + final BlockChangeTracker blockChangeTracker = new BlockChangeTracker(this.getTargetBlock().getWorld()); + + final Vector targetBlockVector = this.getTargetBlock().getLocation().toVector(); + + for (int i = 0; i < erosionPreset.getErosionRecursion(); ++i) + { + erosionIteration(v, erosionPreset, blockChangeTracker, targetBlockVector); + } + + for (int i = 0; i < erosionPreset.getFillRecursion(); ++i) + { + fillIteration(v, erosionPreset, blockChangeTracker, targetBlockVector); + } + + final Undo undo = new Undo(); + for (final BlockWrapper blockWrapper : blockChangeTracker.getAll()) + { + undo.put(blockWrapper.getBlock()); + blockWrapper.getBlock().setTypeIdAndPropertyId(blockWrapper.getMaterial().getId(), blockWrapper.getPropertyId(), true); + } + + v.owner().storeUndo(undo); + } + + private void fillIteration(final SnipeData v, final ErosionPreset erosionPreset, final BlockChangeTracker blockChangeTracker, final Vector targetBlockVector) + { + final int currentIteration = blockChangeTracker.nextIteration(); + for (int x = this.getTargetBlock().getX() - v.getBrushSize(); x <= this.getTargetBlock().getX() + v.getBrushSize(); ++x) + { + for (int z = this.getTargetBlock().getZ() - v.getBrushSize(); z <= this.getTargetBlock().getZ() + v.getBrushSize(); ++z) + { + for (int y = this.getTargetBlock().getY() - v.getBrushSize(); y <= this.getTargetBlock().getY() + v.getBrushSize(); ++y) + { + final Vector currentPosition = new Vector(x, y, z); + if (currentPosition.isInSphere(targetBlockVector, v.getBrushSize())) + { + final BlockWrapper currentBlock = blockChangeTracker.get(currentPosition, currentIteration); + + if (!(currentBlock.isEmpty() || currentBlock.isLiquid())) + { + continue; + } + + int count = 0; + + final Map blockCount = new HashMap(); + + for (final Vector vector : ErodeBrush.FACES_TO_CHECK) + { + final Vector relativePosition = currentPosition.clone().add(vector); + final BlockWrapper relativeBlock = blockChangeTracker.get(relativePosition, currentIteration); + + if (!(relativeBlock.isEmpty() || relativeBlock.isLiquid())) + { + count++; + final BlockWrapper typeBlock = new BlockWrapper(null, relativeBlock.getMaterial(), relativeBlock.getPropertyId()); + if (blockCount.containsKey(typeBlock)) + { + blockCount.put(typeBlock, blockCount.get(typeBlock) + 1); + } + else + { + blockCount.put(typeBlock, 1); + } + } + } + + BlockWrapper currentMaterial = new BlockWrapper(null, Material.AIR, 0); + int amount = 0; + + for (final BlockWrapper wrapper : blockCount.keySet()) + { + final Integer currentCount = blockCount.get(wrapper); + if (amount <= currentCount) + { + currentMaterial = wrapper; + amount = currentCount; + } + } + + if (count >= erosionPreset.getFillFaces()) + { + blockChangeTracker.put(currentPosition, new BlockWrapper(currentBlock.getBlock(), currentMaterial.getMaterial(), currentMaterial.getPropertyId()), currentIteration); + } + } + } + } + } + } + + private void erosionIteration(final SnipeData v, final ErosionPreset erosionPreset, final BlockChangeTracker blockChangeTracker, final Vector targetBlockVector) + { + final int currentIteration = blockChangeTracker.nextIteration(); + for (int x = this.getTargetBlock().getX() - v.getBrushSize(); x <= this.getTargetBlock().getX() + v.getBrushSize(); ++x) + { + for (int z = this.getTargetBlock().getZ() - v.getBrushSize(); z <= this.getTargetBlock().getZ() + v.getBrushSize(); ++z) + { + for (int y = this.getTargetBlock().getY() - v.getBrushSize(); y <= this.getTargetBlock().getY() + v.getBrushSize(); ++y) + { + final Vector currentPosition = new Vector(x, y, z); + if (currentPosition.isInSphere(targetBlockVector, v.getBrushSize())) + { + final BlockWrapper currentBlock = blockChangeTracker.get(currentPosition, currentIteration); + + if (currentBlock.isEmpty() || currentBlock.isLiquid()) + { + continue; + } + + int count = 0; + for (final Vector vector : ErodeBrush.FACES_TO_CHECK) + { + final Vector relativePosition = currentPosition.clone().add(vector); + final BlockWrapper relativeBlock = blockChangeTracker.get(relativePosition, currentIteration); + + if (relativeBlock.isEmpty() || relativeBlock.isLiquid()) + { + count++; + } + } + + if (count >= erosionPreset.getErosionFaces()) + { + blockChangeTracker.put(currentPosition, new BlockWrapper(currentBlock.getBlock(), Material.AIR, 0), currentIteration); + } + } + } + } + } + } + + @Override + protected final void powder(final SnipeData v) + { + this.erosion(v, this.currentPreset.getInverted()); + } + + @Override + public final void info(final Message vm) + { + vm.brushName(this.getName()); + vm.size(); + vm.custom(ChatColor.AQUA + "Erosion minimum exposed faces set to " + this.currentPreset.getErosionFaces()); + vm.custom(ChatColor.BLUE + "Fill minumum touching faces set to " + this.currentPreset.getFillFaces()); + vm.custom(ChatColor.DARK_BLUE + "Erosion recursion amount set to " + this.currentPreset.getErosionRecursion()); + vm.custom(ChatColor.DARK_GREEN + "Fill recursion amount set to " + this.currentPreset.getFillRecursion()); + } + + @Override + public final void parameters(final String[] par, final SnipeData v) + { + JSAPResult result = this.parser.parse(Arrays.copyOfRange(par, 1, par.length)); + + if (sendHelpOrErrorMessageToPlayer(result, v.owner().getPlayer(), this.parser)) + { + return; + } + + if (result.getString("preset") != null) + { + try + { + this.currentPreset = Preset.valueOf(result.getString("preset").toUpperCase()).getPreset(); + v.getVoxelMessage().brushMessage("Brush preset set to " + result.getString("preset")); + return; + } + catch (final IllegalArgumentException exception) + { + v.getVoxelMessage().brushMessage("No such preset."); + return; + } + } + + ErosionPreset currentPresetBackup = this.currentPreset; + + if (result.getObject("fill") != null) + { + this.currentPreset = new ErosionPreset(this.currentPreset.getErosionFaces(), this.currentPreset.getErosionRecursion(), result.getInt("fill"), this.currentPreset.getFillRecursion()); + } + + if (result.getObject("erode") != null) + { + this.currentPreset = new ErosionPreset(result.getInt("erode"), this.currentPreset.getErosionRecursion(), this.currentPreset.getFillFaces(), this.currentPreset.getFillRecursion()); + } + + if (result.getObject("fillrecursion") != null) + { + this.currentPreset = new ErosionPreset(this.currentPreset.getErosionFaces(), this.currentPreset.getErosionRecursion(), this.currentPreset.getFillFaces(), result.getInt("fillrecursion")); + } + + if (result.getObject("eroderecursion") != null) + { + this.currentPreset = new ErosionPreset(this.currentPreset.getErosionFaces(), result.getInt("eroderecursion"), this.currentPreset.getFillFaces(), this.currentPreset.getFillRecursion()); + } + + if (!currentPreset.equals(currentPresetBackup)) + { + if (currentPreset.getErosionFaces() != currentPresetBackup.getErosionFaces()) + { + v.sendMessage(ChatColor.AQUA + "Erosion faces set to: " + ChatColor.WHITE + currentPreset.getErosionFaces()); + } + if (currentPreset.getFillFaces() != currentPresetBackup.getFillFaces()) + { + v.sendMessage(ChatColor.AQUA + "Fill faces set to: " + ChatColor.WHITE + currentPreset.getFillFaces()); + } + if (currentPreset.getErosionRecursion() != currentPresetBackup.getErosionRecursion()) + { + v.sendMessage(ChatColor.AQUA + "Erosion recursions set to: " + ChatColor.WHITE + currentPreset.getErosionRecursion()); + } + if (currentPreset.getFillRecursion() != currentPresetBackup.getFillRecursion()) + { + v.sendMessage(ChatColor.AQUA + "Fill recursions set to: " + ChatColor.WHITE + currentPreset.getFillRecursion()); + } + } + } + + /** + * @author MikeMatrix + */ + private enum Preset + { + MELT(new ErosionPreset(2, 1, 5, 1)), FILL(new ErosionPreset(5, 1, 2, 1)), SMOOTH(new ErosionPreset(3, 1, 3, 1)), LIFT(new ErosionPreset(6, 0, 1, 1)), FLOATCLEAN(new ErosionPreset(6, 1, 6, 1)); + private ErosionPreset preset; + + Preset(final ErosionPreset preset) + { + this.preset = preset; + } + + /** + * Generates a concat string of all options. + * + * @param seperator Seperator for delimiting entries. + * @return + */ + public static String getValuesString(String seperator) + { + String valuesString = ""; + + boolean delimiterHelper = true; + for (final Preset preset : Preset.values()) + { + if (delimiterHelper) + { + delimiterHelper = false; + } + else + { + valuesString += seperator; + } + valuesString += preset.name(); + } + return valuesString; + } + + public ErosionPreset getPreset() + { + return this.preset; + } + + + } + + /** + * @author MikeMatrix + */ + private static final class BlockChangeTracker + { + private final Map> blockChanges; + private final Map flatChanges; + private final AsyncWorld world; + private int nextIterationId = 0; + + public BlockChangeTracker(final AsyncWorld world) + { + this.blockChanges = new HashMap>(); + this.flatChanges = new HashMap(); + this.world = world; + } + + public BlockWrapper get(final Vector position, final int iteration) + { + BlockWrapper changedBlock = null; + + for (int i = iteration - 1; i >= 0; --i) + { + if (this.blockChanges.containsKey(i) && this.blockChanges.get(i).containsKey(position)) + { + changedBlock = this.blockChanges.get(i).get(position); + return changedBlock; + } + } + + changedBlock = new BlockWrapper((AsyncBlock) position.toLocation(this.world).getBlock()); + + return changedBlock; + } + + public Collection getAll() + { + return this.flatChanges.values(); + } + + public int nextIteration() + { + return this.nextIterationId++; + } + + public void put(final Vector position, final BlockWrapper changedBlock, final int iteration) + { + if (!this.blockChanges.containsKey(iteration)) + { + this.blockChanges.put(iteration, new HashMap()); + } + + this.blockChanges.get(iteration).put(position, changedBlock); + this.flatChanges.put(position, changedBlock); + } + } + + /** + * @author MikeMatrix + */ + private static final class BlockWrapper + { + + private final AsyncBlock block; + private final Material material; + private final int data; + + @SuppressWarnings("deprecation") + public BlockWrapper(final AsyncBlock block) + { + this.block = block; + this.data = block.getPropertyId(); + this.material = block.getType(); + } + + public BlockWrapper(final AsyncBlock block, final Material material, final int data) + { + this.block = block; + this.material = material; + this.data = data; + } + + /** + * @return the block + */ + public AsyncBlock getBlock() + { + return this.block; + } + + /** + * @return the data + */ + public int getPropertyId() + { + return this.data; + } + + /** + * @return the material + */ + public Material getMaterial() + { + return this.material; + } + + /** + * @return if the block is Empty. + */ + public boolean isEmpty() + { + switch (material) { + case AIR: + case CAVE_AIR: + case VOID_AIR: + return true; + default: + return false; + } + } + + /** + * @return if the block is a Liquid. + */ + public boolean isLiquid() + { + switch (this.material) + { + case WATER: + case LAVA: + return true; + default: + return false; + } + } + + } + + /** + * @author MikeMatrix + */ + private static final class ErosionPreset + { + private final int erosionFaces; + private final int erosionRecursion; + private final int fillFaces; + private final int fillRecursion; + + public ErosionPreset(final int erosionFaces, final int erosionRecursion, final int fillFaces, final int fillRecursion) + { + this.erosionFaces = erosionFaces; + this.erosionRecursion = erosionRecursion; + this.fillFaces = fillFaces; + this.fillRecursion = fillRecursion; + } + + @Override + public int hashCode() + { + return Objects.hashCode(erosionFaces, erosionRecursion, fillFaces, fillRecursion); + } + + @Override + public boolean equals(final Object obj) + { + if (obj instanceof ErosionPreset) + { + ErosionPreset other = (ErosionPreset) obj; + return Objects.equal(this.erosionFaces, other.erosionFaces) && Objects.equal(this.erosionRecursion, other.erosionRecursion) && Objects.equal(this.fillFaces, other.fillFaces) && Objects.equal(this.fillRecursion, other.fillRecursion); + } + return false; + } + + /** + * @return the erosionFaces + */ + public int getErosionFaces() + { + return this.erosionFaces; + } + + /** + * @return the erosionRecursion + */ + public int getErosionRecursion() + { + return this.erosionRecursion; + } + + /** + * @return the fillFaces + */ + public int getFillFaces() + { + return this.fillFaces; + } + + /** + * @return the fillRecursion + */ + public int getFillRecursion() + { + return this.fillRecursion; + } + + public ErosionPreset getInverted() + { + return new ErosionPreset(this.fillFaces, this.fillRecursion, this.erosionFaces, this.erosionRecursion); + } + } + + @Override + public String getPermissionNode() + { + return "voxelsniper.brush.erode"; + } +} diff --git a/favs/src/main/java/com/thevoxelbox/voxelsniper/brush/ExtrudeBrush.java b/favs/src/main/java/com/thevoxelbox/voxelsniper/brush/ExtrudeBrush.java new file mode 100644 index 000000000..800ebb913 --- /dev/null +++ b/favs/src/main/java/com/thevoxelbox/voxelsniper/brush/ExtrudeBrush.java @@ -0,0 +1,223 @@ +package com.thevoxelbox.voxelsniper.brush; + +import com.thevoxelbox.voxelsniper.Message; +import com.thevoxelbox.voxelsniper.SnipeData; +import com.thevoxelbox.voxelsniper.Undo; +import org.bukkit.ChatColor; +import org.bukkit.block.Block; +import org.bukkit.block.BlockFace; + +/** + * http://www.voxelwiki.com/minecraft/Voxelsniper#Extrude_Brush + * + * @author psanker + */ +public class ExtrudeBrush extends Brush +{ + private double trueCircle; + + /** + * + */ + public ExtrudeBrush() + { + this.setName("Extrude"); + } + + private void extrudeUpOrDown(final SnipeData v, boolean isUp) + { + final int brushSize = v.getBrushSize(); + final double brushSizeSquared = Math.pow(brushSize + this.trueCircle, 2); + Undo undo = new Undo(); + + for (int x = -brushSize; x <= brushSize; x++) + { + final double xSquared = Math.pow(x, 2); + for (int z = -brushSize; z <= brushSize; z++) + { + if ((xSquared + Math.pow(z, 2)) <= brushSizeSquared) + { + final int direction = (isUp ? 1 : -1); + for (int y = 0; y < Math.abs(v.getVoxelHeight()); y++) + { + final int tempY = y * direction; + undo = this.perform( + this.clampY(this.getTargetBlock().getX() + x, this.getTargetBlock().getY() + tempY, this.getTargetBlock().getZ() + z), + this.clampY(this.getTargetBlock().getX() + x, this.getTargetBlock().getY() + tempY + direction, this.getTargetBlock().getZ() + z), + v, undo); + } + } + } + } + + v.owner().storeUndo(undo); + } + + private void extrudeNorthOrSouth(final SnipeData v, boolean isSouth) + { + final int brushSize = v.getBrushSize(); + final double brushSizeSquared = Math.pow(brushSize + this.trueCircle, 2); + Undo undo = new Undo(); + + for (int x = -brushSize; x <= brushSize; x++) + { + final double xSquared = Math.pow(x, 2); + for (int y = -brushSize; y <= brushSize; y++) + { + if ((xSquared + Math.pow(y, 2)) <= brushSizeSquared) + { + final int direction = (isSouth) ? 1 : -1; + for (int z = 0; z < Math.abs(v.getVoxelHeight()); z++) + { + final int tempZ = z * direction; + undo = this.perform( + this.clampY(this.getTargetBlock().getX() + x, this.getTargetBlock().getY() + y, this.getTargetBlock().getZ() + tempZ), + this.clampY(this.getTargetBlock().getX() + x, this.getTargetBlock().getY() + y, this.getTargetBlock().getZ() + tempZ + direction), + v, undo); + } + + } + } + } + + v.owner().storeUndo(undo); + } + + private void extrudeEastOrWest(final SnipeData v, boolean isEast) + { + final int brushSize = v.getBrushSize(); + final double brushSizeSquared = Math.pow(brushSize + this.trueCircle, 2); + Undo undo = new Undo(); + + for (int y = -brushSize; y <= brushSize; y++) + { + final double ySquared = Math.pow(y, 2); + for (int z = -brushSize; z <= brushSize; z++) + { + if ((ySquared + Math.pow(z, 2)) <= brushSizeSquared) + { + final int direction = (isEast) ? 1 : -1; + for (int x = 0; x < Math.abs(v.getVoxelHeight()); x++) + { + final int tempX = x * direction; + undo = this.perform( + this.clampY(this.getTargetBlock().getX() + tempX, this.getTargetBlock().getY() + y, this.getTargetBlock().getZ() + z), + this.clampY(this.getTargetBlock().getX() + tempX + direction, this.getTargetBlock().getY() + y, this.getTargetBlock().getZ() + z), + v, undo); + } + + } + } + } + v.owner().storeUndo(undo); + } + + @SuppressWarnings("deprecation") + private Undo perform(final Block b1, final Block b2, final SnipeData v, final Undo undo) + { + if (v.getVoxelList().contains(b1.getBlockData())) + { + undo.put(b2); + this.setBlockIdAt(b2.getZ(), b2.getX(), b2.getY(), this.getBlockIdAt(b1.getX(), b1.getY(), b1.getZ())); + this.clampY(b2.getX(), b2.getY(), b2.getZ()).setPropertyId(this.clampY(b1.getX(), b1.getY(), b1.getZ()).getPropertyId()); + } + + return undo; + } + + private void selectExtrudeMethod(final SnipeData v, final BlockFace blockFace, final boolean towardsUser) + { + if (blockFace == null || v.getVoxelHeight() == 0) + { + return; + } + boolean tempDirection = towardsUser; + switch (blockFace) + { + case DOWN: + tempDirection = !towardsUser; + case UP: + extrudeUpOrDown(v, tempDirection); + break; + case NORTH: + tempDirection = !towardsUser; + case SOUTH: + extrudeNorthOrSouth(v, tempDirection); + break; + case WEST: + tempDirection = !towardsUser; + case EAST: + extrudeEastOrWest(v, tempDirection); + break; + default: + break; + } + } + + @Override + protected final void arrow(final SnipeData v) + { + this.selectExtrudeMethod(v, this.getTargetBlock().getFace(this.getLastBlock()), false); + } + + @Override + protected final void powder(final SnipeData v) + { + this.selectExtrudeMethod(v, this.getTargetBlock().getFace(this.getLastBlock()), true); + } + + @Override + public final void info(final Message vm) + { + vm.brushName(this.getName()); + vm.size(); + vm.height(); + vm.voxelList(); + + vm.custom(ChatColor.AQUA + ((this.trueCircle == 0.5) ? "True circle mode ON" : "True circle mode OFF")); + } + + @Override + public final void parameters(final String[] par, final com.thevoxelbox.voxelsniper.SnipeData v) + { + for (int i = 1; i < par.length; i++) + { + final String parameter = par[i]; + + try + { + if (parameter.equalsIgnoreCase("info")) + { + v.sendMessage(ChatColor.GOLD + "Extrude brush Parameters:"); + v.sendMessage(ChatColor.AQUA + "/b ex true -- will use a true circle algorithm instead of the skinnier version with classic sniper nubs. /b ex false will switch back. (false is default)"); + return; + } + else if (parameter.startsWith("true")) + { + this.trueCircle = 0.5; + v.sendMessage(ChatColor.AQUA + "True circle mode ON."); + } + else if (parameter.startsWith("false")) + { + this.trueCircle = 0; + v.sendMessage(ChatColor.AQUA + "True circle mode OFF."); + } + else + { + v.sendMessage(ChatColor.RED + "Invalid brush parameters! Use the \"info\" parameter to display parameter info."); + return; + } + } + catch (final Exception exception) + { + v.sendMessage(ChatColor.RED + "Incorrect parameter \"" + parameter + "\"; use the \"info\" parameter."); + } + } + } + + @Override + public String getPermissionNode() + { + return "voxelsniper.brush.extrude"; + } +} diff --git a/favs/src/main/java/com/thevoxelbox/voxelsniper/brush/FillDownBrush.java b/favs/src/main/java/com/thevoxelbox/voxelsniper/brush/FillDownBrush.java new file mode 100644 index 000000000..dbd6874e4 --- /dev/null +++ b/favs/src/main/java/com/thevoxelbox/voxelsniper/brush/FillDownBrush.java @@ -0,0 +1,149 @@ +package com.thevoxelbox.voxelsniper.brush; + +import com.boydti.fawe.bukkit.wrapper.AsyncBlock; +import com.thevoxelbox.voxelsniper.Message; +import com.thevoxelbox.voxelsniper.SnipeData; +import com.thevoxelbox.voxelsniper.brush.perform.PerformBrush; +import org.bukkit.ChatColor; +import org.bukkit.block.Block; + +/** + * @author Voxel + */ +public class FillDownBrush extends PerformBrush +{ + private double trueCircle = 0; + private boolean fillLiquid = true; + private boolean fromExisting = false; + + /** + * + */ + public FillDownBrush() + { + this.setName("Fill Down"); + } + + private void fillDown(final SnipeData v, final Block b) + { + final int brushSize = v.getBrushSize(); + final double brushSizeSquared = Math.pow(brushSize + this.trueCircle, 2); + final Block targetBlock = this.getTargetBlock(); + for (int x = -brushSize; x <= brushSize; x++) + { + final double currentXSquared = Math.pow(x, 2); + + for (int z = -brushSize; z <= brushSize; z++) + { + if (currentXSquared + Math.pow(z, 2) <= brushSizeSquared) + { + int y = 0; + boolean found = false; + if(this.fromExisting) { + for(y = -v.getVoxelHeight(); y < v.getVoxelHeight(); y++) { + final Block currentBlock = this.getWorld().getBlockAt( + targetBlock.getX() + x, + targetBlock.getY() + y, + targetBlock.getZ() + z); + if(!currentBlock.isEmpty()) { + found = true; + break; + } + } + if(!found) continue; + y--; + } + for (; y >= -targetBlock.getY(); --y) + { + final AsyncBlock currentBlock = this.getWorld().getBlockAt( + targetBlock.getX() + x, + targetBlock.getY() + y, + targetBlock.getZ() + z); + if (currentBlock.isEmpty() || (fillLiquid && currentBlock.isLiquid())) + { + this.current.perform(currentBlock); + } else + { + break; + } + } + } + } + } + + v.owner().storeUndo(this.current.getUndo()); + } + + @Override + protected final void arrow(final SnipeData v) + { + this.fillDown(v, this.getTargetBlock()); + } + + @Override + protected final void powder(final SnipeData v) + { + this.fillDown(v, this.getLastBlock()); + } + + @Override + public final void info(final Message vm) + { + vm.brushName(this.getName()); + vm.size(); + } + + @Override + public final void parameters(final String[] par, final SnipeData v) + { + for (int i = 1; i < par.length; i++) + { + if (par[i].equalsIgnoreCase("info")) + { + v.sendMessage(ChatColor.GOLD + "Fill Down Parameters:"); + v.sendMessage(ChatColor.AQUA + "/b fd true -- will use a true circle algorithm."); + v.sendMessage(ChatColor.AQUA + "/b fd false -- will switch back. (Default)"); + v.sendMessage(ChatColor.AQUA + "/b fd some -- Fills only into air."); + v.sendMessage(ChatColor.AQUA + "/b fd all -- Fills into liquids as well. (Default)"); + v.sendMessage(ChatColor.AQUA + "/b fd -e -- Fills into only existing blocks. (Toggle)"); + return; + } + else if (par[i].equalsIgnoreCase("true")) + { + this.trueCircle = 0.5; + v.sendMessage(ChatColor.AQUA + "True circle mode ON."); + } + else if (par[i].equalsIgnoreCase("false")) + { + this.trueCircle = 0; + v.sendMessage(ChatColor.AQUA + "True circle mode OFF."); + } + else if (par[i].equalsIgnoreCase("all")) + { + this.fillLiquid = true; + v.sendMessage(ChatColor.AQUA + "Now filling liquids as well as air."); + } + else if (par[i].equalsIgnoreCase("some")) + { + this.fillLiquid = false; + v.setReplaceId(0); + v.sendMessage(ChatColor.AQUA + "Now only filling air."); + } + else if (par[i].equalsIgnoreCase("-e")) + { + this.fromExisting = !this.fromExisting; + v.sendMessage(ChatColor.AQUA + "Now filling down from " + ((this.fromExisting) ? "existing" : "all") + " blocks."); + } + else + { + v.sendMessage(ChatColor.RED + "Invalid brush parameters! use the info parameter to display parameter info."); + } + } + } + + @Override + public String getPermissionNode() + { + return "voxelsniper.brush.filldown"; + } +} diff --git a/favs/src/main/java/com/thevoxelbox/voxelsniper/brush/FlatOceanBrush.java b/favs/src/main/java/com/thevoxelbox/voxelsniper/brush/FlatOceanBrush.java new file mode 100644 index 000000000..a7419b4c3 --- /dev/null +++ b/favs/src/main/java/com/thevoxelbox/voxelsniper/brush/FlatOceanBrush.java @@ -0,0 +1,128 @@ +package com.thevoxelbox.voxelsniper.brush; + +import com.boydti.fawe.bukkit.wrapper.AsyncChunk; +import com.thevoxelbox.voxelsniper.Message; +import com.thevoxelbox.voxelsniper.SnipeData; +import org.bukkit.ChatColor; +import org.bukkit.Chunk; +import org.bukkit.Material; + +/** + * @author GavJenks + */ +public class FlatOceanBrush extends Brush +{ + private static final int DEFAULT_WATER_LEVEL = 29; + private static final int DEFAULT_FLOOR_LEVEL = 8; + private int waterLevel = DEFAULT_WATER_LEVEL; + private int floorLevel = DEFAULT_FLOOR_LEVEL; + + /** + * + */ + public FlatOceanBrush() + { + this.setName("FlatOcean"); + } + + @SuppressWarnings("deprecation") + private void flatOcean(final AsyncChunk chunk) + { + for (int x = 0; x < CHUNK_SIZE; x++) + { + for (int z = 0; z < CHUNK_SIZE; z++) + { + for (int y = 0; y < chunk.getWorld().getMaxHeight(); y++) + { + if (y <= this.floorLevel) + { + chunk.getBlock(x, y, z).setType(Material.DIRT); + } + else if (y <= this.waterLevel) + { + chunk.getBlock(x, y, z).setType(Material.WATER); + } + else + { + chunk.getBlock(x, y, z).setType(Material.AIR); + } + } + } + } + } + + @Override + protected final void arrow(final SnipeData v) + { + this.flatOcean(this.getWorld().getChunkAt(this.getTargetBlock())); + } + + @Override + protected final void powder(final SnipeData v) + { + this.flatOcean(this.getWorld().getChunkAt(this.getTargetBlock())); + this.flatOcean(this.getWorld().getChunkAt(this.clampY(this.getTargetBlock().getX() + CHUNK_SIZE, 1, this.getTargetBlock().getZ()))); + this.flatOcean(this.getWorld().getChunkAt(this.clampY(this.getTargetBlock().getX() + CHUNK_SIZE, 1, this.getTargetBlock().getZ() + CHUNK_SIZE))); + this.flatOcean(this.getWorld().getChunkAt(this.clampY(this.getTargetBlock().getX(), 1, this.getTargetBlock().getZ() + CHUNK_SIZE))); + this.flatOcean(this.getWorld().getChunkAt(this.clampY(this.getTargetBlock().getX() - CHUNK_SIZE, 1, this.getTargetBlock().getZ() + CHUNK_SIZE))); + this.flatOcean(this.getWorld().getChunkAt(this.clampY(this.getTargetBlock().getX() - CHUNK_SIZE, 1, this.getTargetBlock().getZ()))); + this.flatOcean(this.getWorld().getChunkAt(this.clampY(this.getTargetBlock().getX() - CHUNK_SIZE, 1, this.getTargetBlock().getZ() - CHUNK_SIZE))); + this.flatOcean(this.getWorld().getChunkAt(this.clampY(this.getTargetBlock().getX(), 1, this.getTargetBlock().getZ() - CHUNK_SIZE))); + this.flatOcean(this.getWorld().getChunkAt(this.clampY(this.getTargetBlock().getX() + CHUNK_SIZE, 1, this.getTargetBlock().getZ() - CHUNK_SIZE))); + } + + @Override + public final void info(final Message vm) + { + vm.brushName(this.getName()); + vm.custom(ChatColor.RED + "THIS BRUSH DOES NOT UNDO"); + vm.custom(ChatColor.GREEN + "Water level set to " + this.waterLevel); + vm.custom(ChatColor.GREEN + "Ocean floor level set to " + this.floorLevel); + } + + @Override + public final void parameters(final String[] par, final SnipeData v) + { + for (int i = 1; i < par.length; i++) + { + final String parameter = par[i]; + + if (parameter.equalsIgnoreCase("info")) + { + v.sendMessage(ChatColor.GREEN + "yo[number] to set the Level to which the water will rise."); + v.sendMessage(ChatColor.GREEN + "yl[number] to set the Level to which the ocean floor will rise."); + } + if (parameter.startsWith("yo")) + { + int newWaterLevel = Integer.parseInt(parameter.replace("yo", "")); + if (newWaterLevel < this.floorLevel) + { + newWaterLevel = this.floorLevel + 1; + } + this.waterLevel = newWaterLevel; + v.sendMessage(ChatColor.GREEN + "Water Level set to " + this.waterLevel); + } + else if (parameter.startsWith("yl")) + { + int newFloorLevel = Integer.parseInt(parameter.replace("yl", "")); + if (newFloorLevel > this.waterLevel) + { + newFloorLevel = this.waterLevel - 1; + if (newFloorLevel == 0) + { + newFloorLevel = 1; + this.waterLevel = 2; + } + } + this.floorLevel = newFloorLevel; + v.sendMessage(ChatColor.GREEN + "Ocean floor Level set to " + this.floorLevel); + } + } + } + + @Override + public String getPermissionNode() + { + return "voxelsniper.brush.flatocean"; + } +} diff --git a/favs/src/main/java/com/thevoxelbox/voxelsniper/brush/GenerateTreeBrush.java b/favs/src/main/java/com/thevoxelbox/voxelsniper/brush/GenerateTreeBrush.java new file mode 100644 index 000000000..4a9067442 --- /dev/null +++ b/favs/src/main/java/com/thevoxelbox/voxelsniper/brush/GenerateTreeBrush.java @@ -0,0 +1,781 @@ +package com.thevoxelbox.voxelsniper.brush; + +import java.util.ArrayList; +import java.util.Random; + +import com.sk89q.worldedit.bukkit.BukkitAdapter; +import com.sk89q.worldedit.world.block.BlockTypes; +import com.thevoxelbox.voxelsniper.Message; +import com.thevoxelbox.voxelsniper.SnipeData; +import com.thevoxelbox.voxelsniper.Undo; + +import org.bukkit.ChatColor; +import org.bukkit.Material; +import org.bukkit.block.Block; + +// Proposal: Use /v and /vr for leave and wood material // or two more parameters -- Monofraps + +/** + * http://www.voxelwiki.com/minecraft/Voxelsniper#VoxelTrees_Brush + * + * @author Ghost8700 @ Voxel + */ +public class GenerateTreeBrush extends Brush +{ + // Tree Variables. + private Random randGenerator = new Random(); + private ArrayList branchBlocks = new ArrayList(); + private Undo undo; + // If these default values are edited. Remember to change default values in the default preset. + private Material leafType = Material.OAK_LEAVES; + private Material woodType = Material.OAK_WOOD; + private boolean rootFloat = false; + private int startHeight = 0; + private int rootLength = 9; + private int maxRoots = 2; + private int minRoots = 1; + private int thickness = 1; + private int slopeChance = 40; + private int twistChance = 5; // This is a hidden value not available through Parameters. Otherwise messy. + private int heightMininmum = 14; + private int heightMaximum = 18; + private int branchLength = 8; + private int nodeMax = 4; + private int nodeMin = 3; + + private int blockPositionX; + private int blockPositionY; + private int blockPositionZ; + + /** + * + */ + public GenerateTreeBrush() + { + this.setName("Generate Tree"); + } + + public boolean isLog(Material m) { + switch (m) { + case ACACIA_LOG: + case BIRCH_LOG: + case DARK_OAK_LOG: + case JUNGLE_LOG: + case OAK_LOG: + case SPRUCE_LOG: + return true; + default: + return false; + } + } + + public boolean isLeave(Material m) { + switch (m) { + case ACACIA_LEAVES: + case BIRCH_LEAVES: + case DARK_OAK_LEAVES: + case JUNGLE_LEAVES: + case OAK_LEAVES: + case SPRUCE_LEAVES: + return true; + default: + return false; + } + } + + // Branch Creation based on direction chosen from the parameters passed. + @SuppressWarnings("deprecation") + private void branchCreate(final int xDirection, final int zDirection) + { + + // Sets branch origin. + final int originX = blockPositionX; + final int originY = blockPositionY; + final int originZ = blockPositionZ; + + // Sets direction preference. + final int xPreference = this.randGenerator.nextInt(60) + 20; + final int zPreference = this.randGenerator.nextInt(60) + 20; + + // Iterates according to branch length. + for (int r = 0; r < this.branchLength; r++) + { + + // Alters direction according to preferences. + if (this.randGenerator.nextInt(100) < xPreference) + { + blockPositionX = blockPositionX + 1 * xDirection; + } + if (this.randGenerator.nextInt(100) < zPreference) + { + blockPositionZ = blockPositionZ + 1 * zDirection; + } + + // 50% chance to increase elevation every second block. + if (Math.abs(r % 2) == 1) + { + blockPositionY = blockPositionY + this.randGenerator.nextInt(2); + } + + // Add block to undo function. + if (!isLog(this.getBlockType(blockPositionX, blockPositionY, blockPositionZ))) + { + this.undo.put(this.clampY(blockPositionX, blockPositionY, blockPositionZ)); + } + + // Creates a branch block. + this.clampY(blockPositionX, blockPositionY, blockPositionZ).setType(this.woodType); + this.branchBlocks.add(this.clampY(blockPositionX, blockPositionY, blockPositionZ)); + } + + // Resets the origin + blockPositionX = originX; + blockPositionY = originY; + blockPositionZ = originZ; + } + + @SuppressWarnings("deprecation") + private void leafNodeCreate() + { + // Generates the node size. + final int nodeRadius = this.randGenerator.nextInt(this.nodeMax - this.nodeMin + 1) + this.nodeMin; + final double bSquared = Math.pow(nodeRadius + 0.5, 2); + + // Lowers the current block in order to start at the bottom of the node. + blockPositionY = blockPositionY - 2; + + + for (int z = nodeRadius; z >= 0; z--) + { + final double zSquared = Math.pow(z, 2); + + for (int x = nodeRadius; x >= 0; x--) + { + final double xSquared = Math.pow(x, 2); + + for (int y = nodeRadius; y >= 0; y--) + { + if ((xSquared + Math.pow(y, 2) + zSquared) <= bSquared) + { + // Chance to skip creation of a block. + if (this.randGenerator.nextInt(100) >= 30) + { + // If block is Air, create a leaf block. + if (this.getWorld().getBlockAt(blockPositionX + x, blockPositionY + y, blockPositionZ + z).isEmpty()) + { + // Adds block to undo function. + if (!isLeave(this.getBlockType(blockPositionX + x, blockPositionY + y, blockPositionZ + z))) + { + this.undo.put(this.clampY(blockPositionX + x, blockPositionY + y, blockPositionZ + z)); + } + // Creates block. + this.clampY(blockPositionX + x, blockPositionY + y, blockPositionZ + z).setType(this.leafType); + } + } + if (this.randGenerator.nextInt(100) >= 30) + { + if (this.getWorld().getBlockAt(blockPositionX + x, blockPositionY + y, blockPositionZ - z).isEmpty()) + { + if (!isLeave(this.getBlockType(blockPositionX + x, blockPositionY + y, blockPositionZ - z))) + { + this.undo.put(this.clampY(blockPositionX + x, blockPositionY + y, blockPositionZ - z)); + } + this.clampY(blockPositionX + x, blockPositionY + y, blockPositionZ - z).setType(this.leafType); + } + } + if (this.randGenerator.nextInt(100) >= 30) + { + if (this.getWorld().getBlockAt(blockPositionX - x, blockPositionY + y, blockPositionZ + z).isEmpty()) + { + if (!isLeave(this.getBlockType(blockPositionX - x, blockPositionY + y, blockPositionZ + z))) + { + this.undo.put(this.clampY(blockPositionX - x, blockPositionY + y, blockPositionZ + z)); + } + this.clampY(blockPositionX - x, blockPositionY + y, blockPositionZ + z).setType(this.leafType); + } + } + if (this.randGenerator.nextInt(100) >= 30) + { + if (this.getWorld().getBlockAt(blockPositionX - x, blockPositionY + y, blockPositionZ - z).isEmpty()) + { + if (!isLeave(this.getBlockType(blockPositionX - x, blockPositionY + y, blockPositionZ - z))) + { + this.undo.put(this.clampY(blockPositionX - x, blockPositionY + y, blockPositionZ - z)); + } + this.clampY(blockPositionX - x, blockPositionY + y, blockPositionZ - z).setType(this.leafType); + } + } + if (this.randGenerator.nextInt(100) >= 30) + { + if (this.getWorld().getBlockAt(blockPositionX + x, blockPositionY - y, blockPositionZ + z).isEmpty()) + { + if (!isLeave(this.getBlockType(blockPositionX + x, blockPositionY - y, blockPositionZ + z))) + { + this.undo.put(this.clampY(blockPositionX + x, blockPositionY - y, blockPositionZ + z)); + } + this.clampY(blockPositionX + x, blockPositionY - y, blockPositionZ + z).setType(this.leafType); + } + } + if (this.randGenerator.nextInt(100) >= 30) + { + if (this.getWorld().getBlockAt(blockPositionX + x, blockPositionY - y, blockPositionZ - z).isEmpty()) + { + if (!isLeave(this.getBlockType(blockPositionX + x, blockPositionY - y, blockPositionZ - z))) + { + this.undo.put(this.clampY(blockPositionX + x, blockPositionY - y, blockPositionZ - z)); + } + this.clampY(blockPositionX + x, blockPositionY - y, blockPositionZ - z).setType(this.leafType); + } + } + if (this.randGenerator.nextInt(100) >= 30) + { + if (this.getWorld().getBlockAt(blockPositionX - x, blockPositionY - y, blockPositionZ + z).isEmpty()) + { + if (!isLeave(this.getBlockType(blockPositionX - x, blockPositionY - y, blockPositionZ + z))) + { + this.undo.put(this.clampY(blockPositionX - x, blockPositionY - y, blockPositionZ + z)); + } + this.clampY(blockPositionX - x, blockPositionY - y, blockPositionZ + z).setType(this.leafType); + } + } + if (this.randGenerator.nextInt(100) >= 30) + { + if (this.getWorld().getBlockAt(blockPositionX - x, blockPositionY - y, blockPositionZ - z).isEmpty()) + { + if (!isLeave(this.getBlockType(blockPositionX - x, blockPositionY - y, blockPositionZ - z))) + { + this.undo.put(this.clampY(blockPositionX - x, blockPositionY - y, blockPositionZ - z)); + } + this.clampY(blockPositionX - x, blockPositionY - y, blockPositionZ - z).setType(this.leafType); + } + } + } + } + } + } + } + + /** + * Code Concerning Root Generation. + * + * @param xDirection + * @param zDirection + */ + @SuppressWarnings("deprecation") + private void rootCreate(final int xDirection, final int zDirection) + { + // Sets Origin. + final int originX = blockPositionX; + final int originY = blockPositionY; + final int originZ = blockPositionZ; + + // Generates the number of roots to create. + final int roots = this.randGenerator.nextInt(this.maxRoots - this.minRoots + 1) + this.minRoots; + + // A roots preference to move along the X and Y axis. + + + // Loops for each root to be created. + for (int i = 0; i < roots; i++) + { + // Pushes the root'world starting point out from the center of the tree. + for (int t = 0; t < this.thickness - 1; t++) + { + blockPositionX = blockPositionX + xDirection; + blockPositionZ = blockPositionZ + zDirection; + } + + // Generate directional preference between 30% and 70% + final int xPreference = this.randGenerator.nextInt(30) + 40; + final int zPreference = this.randGenerator.nextInt(30) + 40; + + for (int j = 0; j < this.rootLength; j++) + { + // For the purposes of this algorithm, logs aren't considered solid. + + // If not solid then... + // Save for undo function + if (!isLog(this.getBlockType(blockPositionX, blockPositionY, blockPositionZ))) + { + this.undo.put(this.clampY(blockPositionX, blockPositionY, blockPositionZ)); + + // Place log block. + this.clampY(blockPositionX, blockPositionY, blockPositionZ).setType(this.woodType); + } + else + { + // If solid then... + // End loop + break; + } + + // Checks is block below is solid + if (this.clampY(blockPositionX, blockPositionY - 1, blockPositionZ).isEmpty() || this.clampY(blockPositionX, blockPositionY - 1, blockPositionZ).getType() == Material.WATER || this.clampY(blockPositionX, blockPositionY - 1, blockPositionZ).getType() == Material.SNOW || isLog(this.clampY(blockPositionX, blockPositionY - 1, blockPositionZ).getType())) + { + // Mos down if solid. + blockPositionY = blockPositionY - 1; + if (this.rootFloat) + { + if (this.randGenerator.nextInt(100) < xPreference) + { + blockPositionX = blockPositionX + xDirection; + } + if (this.randGenerator.nextInt(100) < zPreference) + { + blockPositionZ = blockPositionZ + zDirection; + } + } + } + else + { + // If solid then move. + if (this.randGenerator.nextInt(100) < xPreference) + { + blockPositionX = blockPositionX + xDirection; + } + if (this.randGenerator.nextInt(100) < zPreference) + { + blockPositionZ = blockPositionZ + zDirection; + } + // Checks if new location is solid, if not then move down. + if (this.clampY(blockPositionX, blockPositionY - 1, blockPositionZ).isEmpty() || this.clampY(blockPositionX, blockPositionY - 1, blockPositionZ).getType() == Material.WATER || this.clampY(blockPositionX, blockPositionY - 1, blockPositionZ).getType() == Material.SNOW || isLog(this.clampY(blockPositionX, blockPositionY - 1, blockPositionZ).getType())) + { + blockPositionY = blockPositionY - 1; + } + } + } + + // Reset origin. + blockPositionX = originX; + blockPositionY = originY; + blockPositionZ = originZ; + + } + } + + private void rootGen() + { + // Quadrant 1 + this.rootCreate(1, 1); + + // Quadrant 2 + this.rootCreate(-1, 1); + + // Quadrant 3 + this.rootCreate(1, -1); + + // Quadrant 4 + this.rootCreate(-1, -1); + } + + @SuppressWarnings("deprecation") + private void trunkCreate() + { + // Creates true circle discs of the set size using the wood type selected. + final double bSquared = Math.pow(this.thickness + 0.5, 2); + + for (int x = this.thickness; x >= 0; x--) + { + final double xSquared = Math.pow(x, 2); + + for (int z = this.thickness; z >= 0; z--) + { + if ((xSquared + Math.pow(z, 2)) <= bSquared) + { + // If block is air, then create a block. + if (this.getWorld().getBlockAt(blockPositionX + x, blockPositionY, blockPositionZ + z).isEmpty()) + { + // Adds block to undo function. + if (!isLog(this.getBlockType(blockPositionX + x, blockPositionY, blockPositionZ + z))) + { + this.undo.put(this.clampY(blockPositionX + x, blockPositionY, blockPositionZ + z)); + } + // Creates block. + this.clampY(blockPositionX + x, blockPositionY, blockPositionZ + z).setType(this.woodType); + } + if (this.getWorld().getBlockAt(blockPositionX + x, blockPositionY, blockPositionZ - z).isEmpty()) + { + if (!isLog(this.getBlockType(blockPositionX + x, blockPositionY, blockPositionZ - z))) + { + this.undo.put(this.clampY(blockPositionX + x, blockPositionY, blockPositionZ - z)); + } + this.clampY(blockPositionX + x, blockPositionY, blockPositionZ - z).setType(this.woodType); + } + if (this.getWorld().getBlockAt(blockPositionX - x, blockPositionY, blockPositionZ + z).isEmpty()) + { + if (!isLog(this.getBlockType(blockPositionX - x, blockPositionY, blockPositionZ + z))) + { + this.undo.put(this.clampY(blockPositionX - x, blockPositionY, blockPositionZ + z)); + } + this.clampY(blockPositionX - x, blockPositionY, blockPositionZ + z).setType(this.woodType); + } + if (this.getWorld().getBlockAt(blockPositionX - x, blockPositionY, blockPositionZ - z).isEmpty()) + { + if (!isLog(this.getBlockType(blockPositionX - x, blockPositionY, blockPositionZ - z))) + { + this.undo.put(this.clampY(blockPositionX - x, blockPositionY, blockPositionZ - z)); + } + this.clampY(blockPositionX - x, blockPositionY, blockPositionZ - z).setType(this.woodType); + } + } + } + } + } + + /* + * + * Code Concerning Trunk Generation + */ + private void trunkGen() + { + // Sets Origin + final int originX = blockPositionX; + final int originY = blockPositionY; + final int originZ = blockPositionZ; + + // ---------- + // Main Trunk + // ---------- + // Sets diretional preferences. + int xPreference = this.randGenerator.nextInt(this.slopeChance); + int zPreference = this.randGenerator.nextInt(this.slopeChance); + + // Sets direction. + int xDirection = 1; + if (this.randGenerator.nextInt(100) < 50) + { + xDirection = -1; + } + + int zDirection = 1; + if (this.randGenerator.nextInt(100) < 50) + { + zDirection = -1; + } + + // Generates a height for trunk. + int height = this.randGenerator.nextInt(this.heightMaximum - this.heightMininmum + 1) + this.heightMininmum; + + for (int p = 0; p < height; p++) + { + if (p > 3) + { + if (this.randGenerator.nextInt(100) <= this.twistChance) + { + xDirection *= -1; + } + if (this.randGenerator.nextInt(100) <= this.twistChance) + { + zDirection *= -1; + } + if (this.randGenerator.nextInt(100) < xPreference) + { + blockPositionX += xDirection; + } + if (this.randGenerator.nextInt(100) < zPreference) + { + blockPositionZ += zDirection; + } + } + + // Creates trunk section + this.trunkCreate(); + + // Mos up for next section + blockPositionY = blockPositionY + 1; + } + + // Generates branchs at top of trunk for each quadrant. + this.branchCreate(1, 1); + this.branchCreate(-1, 1); + this.branchCreate(1, -1); + this.branchCreate(-1, -1); + + // Reset Origin for next trunk. + blockPositionX = originX; + blockPositionY = originY + 4; + blockPositionZ = originZ; + + // --------------- + // Secondary Trunk + // --------------- + // Sets diretional preferences. + xPreference = this.randGenerator.nextInt(this.slopeChance); + zPreference = this.randGenerator.nextInt(this.slopeChance); + + // Sets direction. + xDirection = 1; + if (this.randGenerator.nextInt(100) < 50) + { + xDirection = -1; + } + + zDirection = 1; + if (this.randGenerator.nextInt(100) < 50) + { + zDirection = -1; + } + + // Generates a height for trunk. + height = this.randGenerator.nextInt(this.heightMaximum - this.heightMininmum + 1) + this.heightMininmum; + + if (height > 4) + { + for (int p = 0; p < height; p++) + { + if (this.randGenerator.nextInt(100) <= this.twistChance) + { + xDirection *= -1; + } + if (this.randGenerator.nextInt(100) <= this.twistChance) + { + zDirection *= -1; + } + if (this.randGenerator.nextInt(100) < xPreference) + { + blockPositionX = blockPositionX + 1 * xDirection; + } + if (this.randGenerator.nextInt(100) < zPreference) + { + blockPositionZ = blockPositionZ + 1 * zDirection; + } + + // Creates a trunk section + this.trunkCreate(); + + // Mos up for next section + blockPositionY = blockPositionY + 1; + } + + // Generates branchs at top of trunk for each quadrant. + this.branchCreate(1, 1); + this.branchCreate(-1, 1); + this.branchCreate(1, -1); + this.branchCreate(-1, -1); + } + } + + @Override + protected final void arrow(final SnipeData v) + { + this.undo = new Undo(); + + this.branchBlocks.clear(); + + // Sets the location variables. + blockPositionX = this.getTargetBlock().getX(); + blockPositionY = this.getTargetBlock().getY() + this.startHeight; + blockPositionZ = this.getTargetBlock().getZ(); + + // Generates the roots. + this.rootGen(); + + // Generates the trunk, which also generates branches. + this.trunkGen(); + + // Each branch block was saved in an array. This is now fed through an array. + // This array takes each branch block and constructs a leaf node around it. + for (final Block block : this.branchBlocks) + { + blockPositionX = block.getX(); + blockPositionY = block.getY(); + blockPositionZ = block.getZ(); + this.leafNodeCreate(); + } + + // Ends the undo function and mos on. + v.owner().storeUndo(this.undo); + } + + // The Powder currently does nothing extra. + @Override + protected final void powder(final SnipeData v) + { + this.arrow(v); + } + + @Override + public final void info(final Message vm) + { + vm.brushName(this.getName()); + } + + @Override + public final void parameters(final String[] par, final SnipeData v) + { + for (int i = 1; i < par.length; i++) + { + final String parameter = par[i]; + + try + { + if (parameter.equalsIgnoreCase("info")) + { + v.sendMessage(ChatColor.GOLD + "This brush takes the following parameters:"); + v.sendMessage(ChatColor.AQUA + "lt# - leaf type (data value)"); + v.sendMessage(ChatColor.AQUA + "wt# - wood type (data value)"); + v.sendMessage(ChatColor.AQUA + "tt# - tree thickness (whote number)"); + v.sendMessage(ChatColor.AQUA + "rfX - root float (true or false)"); + v.sendMessage(ChatColor.AQUA + "sh# - starting height (whole number)"); + v.sendMessage(ChatColor.AQUA + "rl# - root length (whole number)"); + v.sendMessage(ChatColor.AQUA + "ts# - trunk slope chance (0-100)"); + v.sendMessage(ChatColor.AQUA + "bl# - branch length (whole number)"); + v.sendMessage(ChatColor.AQUA + "info2 - more parameters"); + return; + } + + if (parameter.equalsIgnoreCase("info2")) + { + v.sendMessage(ChatColor.GOLD + "This brush takes the following parameters:"); + v.sendMessage(ChatColor.AQUA + "minr# - minimum roots (whole number)"); + v.sendMessage(ChatColor.AQUA + "maxr# - maximum roots (whole number)"); + v.sendMessage(ChatColor.AQUA + "minh# - minimum height (whole number)"); + v.sendMessage(ChatColor.AQUA + "maxh# - maximum height (whole number)"); + v.sendMessage(ChatColor.AQUA + "minl# - minimum leaf node size (whole number)"); + v.sendMessage(ChatColor.AQUA + "maxl# - maximum leaf node size (whole number)"); + v.sendMessage(ChatColor.AQUA + "default - restore default params"); + return; + } + if (parameter.startsWith("lt")) + { // Leaf Type + this.leafType = BukkitAdapter.adapt(BlockTypes.parse(parameter.replace("lt", ""))); + v.sendMessage(ChatColor.BLUE + "Leaf Type set to " + this.leafType); + } + else if (parameter.startsWith("wt")) + { // Wood Type + this.woodType = BukkitAdapter.adapt(BlockTypes.parse(parameter.replace("wt", ""))); + v.sendMessage(ChatColor.BLUE + "Wood Type set to " + this.woodType); + } + else if (parameter.startsWith("tt")) + { // Tree Thickness + this.thickness = Integer.parseInt(parameter.replace("tt", "")); + v.sendMessage(ChatColor.BLUE + "Thickness set to " + this.thickness); + } + else if (parameter.startsWith("rf")) + { // Root Float + this.rootFloat = Boolean.parseBoolean(parameter.replace("rf", "")); + v.sendMessage(ChatColor.BLUE + "Floating Roots set to " + this.rootFloat); + } + else if (parameter.startsWith("sh")) + { // Starting Height + this.startHeight = Integer.parseInt(parameter.replace("sh", "")); + v.sendMessage(ChatColor.BLUE + "Starting Height set to " + this.startHeight); + } + else if (parameter.startsWith("rl")) + { // Root Length + this.rootLength = Integer.parseInt(parameter.replace("rl", "")); + v.sendMessage(ChatColor.BLUE + "Root Length set to " + this.rootLength); + } + else if (parameter.startsWith("minr")) + { // Minimum Roots + this.minRoots = Integer.parseInt(parameter.replace("minr", "")); + if (this.minRoots > this.maxRoots) + { + this.minRoots = this.maxRoots; + v.sendMessage(ChatColor.RED + "Minimum Roots can't exceed Maximum Roots, has been set to " + this.minRoots + " Instead!"); + } + else + { + v.sendMessage(ChatColor.BLUE + "Minimum Roots set to " + this.minRoots); + } + } + else if (parameter.startsWith("maxr")) + { // Maximum Roots + this.maxRoots = Integer.parseInt(parameter.replace("maxr", "")); + if (this.minRoots > this.maxRoots) + { + this.maxRoots = this.minRoots; + v.sendMessage(ChatColor.RED + "Maximum Roots can't be lower than Minimum Roots, has been set to " + this.minRoots + " Instead!"); + } + else + { + v.sendMessage(ChatColor.BLUE + "Maximum Roots set to " + this.maxRoots); + } + } + else if (parameter.startsWith("ts")) + { // Trunk Slope Chance + this.slopeChance = Integer.parseInt(parameter.replace("ts", "")); + v.sendMessage(ChatColor.BLUE + "Trunk Slope set to " + this.slopeChance); + } + else if (parameter.startsWith("minh")) + { // Height Minimum + this.heightMininmum = Integer.parseInt(parameter.replace("minh", "")); + if (this.heightMininmum > this.heightMaximum) + { + this.heightMininmum = this.heightMaximum; + v.sendMessage(ChatColor.RED + "Minimum Height exceed than Maximum Height, has been set to " + this.heightMininmum + " Instead!"); + } + else + { + v.sendMessage(ChatColor.BLUE + "Minimum Height set to " + this.heightMininmum); + } + } + else if (parameter.startsWith("maxh")) + { // Height Maximum + this.heightMaximum = Integer.parseInt(parameter.replace("maxh", "")); + if (this.heightMininmum > this.heightMaximum) + { + this.heightMaximum = this.heightMininmum; + v.sendMessage(ChatColor.RED + "Maximum Height can't be lower than Minimum Height, has been set to " + this.heightMaximum + " Instead!"); + } + else + { + v.sendMessage(ChatColor.BLUE + "Maximum Roots set to " + this.heightMaximum); + } + } + else if (parameter.startsWith("bl")) + { // Branch Length + this.branchLength = Integer.parseInt(parameter.replace("bl", "")); + v.sendMessage(ChatColor.BLUE + "Branch Length set to " + this.branchLength); + } + else if (parameter.startsWith("maxl")) + { // Leaf Node Max Size + this.nodeMax = Integer.parseInt(parameter.replace("maxl", "")); + v.sendMessage(ChatColor.BLUE + "Leaf Max Thickness set to " + this.nodeMax + " (Default 4)"); + } + else if (parameter.startsWith("minl")) + { // Leaf Node Min Size + this.nodeMin = Integer.parseInt(parameter.replace("minl", "")); + v.sendMessage(ChatColor.BLUE + "Leaf Min Thickness set to " + this.nodeMin + " (Default 3)"); + + // ------- + // Presets + // ------- + } + else if (parameter.startsWith("default")) + { // Default settings. + this.leafType = Material.OAK_LEAVES; + this.woodType = Material.OAK_WOOD; + this.rootFloat = false; + this.startHeight = 0; + this.rootLength = 9; + this.maxRoots = 2; + this.minRoots = 1; + this.thickness = 1; + this.slopeChance = 40; + this.heightMininmum = 14; + this.heightMaximum = 18; + this.branchLength = 8; + this.nodeMax = 4; + this.nodeMin = 3; + v.sendMessage(ChatColor.GOLD + "Brush reset to default parameters."); + } + else + { + v.sendMessage(ChatColor.RED + "Invalid brush parameters! use the info parameter to display parameter info."); + } + } + catch (final Exception exception) + { + v.sendMessage(ChatColor.RED + "Invalid brush parameters! \"" + par[i] + "\" is not a valid statement. Please use the 'info' parameter to display parameter info."); + } + + } + } + + @Override + public String getPermissionNode() + { + return "voxelsniper.brush.generatetree"; + } +} diff --git a/favs/src/main/java/com/thevoxelbox/voxelsniper/brush/HeatRayBrush.java b/favs/src/main/java/com/thevoxelbox/voxelsniper/brush/HeatRayBrush.java new file mode 100644 index 000000000..1ac689d24 --- /dev/null +++ b/favs/src/main/java/com/thevoxelbox/voxelsniper/brush/HeatRayBrush.java @@ -0,0 +1,226 @@ +package com.thevoxelbox.voxelsniper.brush; + +import java.util.ArrayList; +import java.util.Random; + +import com.sk89q.worldedit.bukkit.BukkitAdapter; +import com.sk89q.worldedit.world.block.BlockTypes; +import com.thevoxelbox.voxelsniper.Message; +import com.thevoxelbox.voxelsniper.SnipeData; +import com.thevoxelbox.voxelsniper.Undo; + +import org.bukkit.ChatColor; +import org.bukkit.Location; +import org.bukkit.Material; +import org.bukkit.block.Block; +import org.bukkit.util.Vector; +import org.bukkit.util.noise.PerlinNoiseGenerator; + +/** + * http://www.voxelwiki.com/minecraft/Voxelsniper#The_Heat_Ray + * + * @author Gavjenks + */ +public class HeatRayBrush extends Brush +{ + + /** + * @author MikeMatrix + */ +// private enum FlameableBlock +// { +// WOOD(Material.WOOD), SAPLING(Material.SAPLING), LOG(Material.LOG), LEAVES(Material.LEAVES), SPONGE(Material.SPONGE), WEB(Material.WEB), LONG_GRASS(Material.LONG_GRASS), DEAD_BUSH(Material.DEAD_BUSH), WOOL(Material.WOOL), YELLOW_FLOWER(Material.YELLOW_FLOWER), RED_ROSE(Material.RED_ROSE), TORCH(Material.TORCH), FIRE(Material.FIRE), WOOD_STAIRS(Material.WOOD_STAIRS), CROPS(Material.CROPS), SIGN_POST(Material.SIGN_POST), WOODEN_DOOR(Material.WOODEN_DOOR), LADDER(Material.LADDER), WALL_SIGN(Material.WALL_SIGN), WOOD_PLATE(Material.WOOD_PLATE), SNOW(Material.SNOW), ICE(Material.ICE), SUGAR_CANE_BLOCK(Material.SUGAR_CANE_BLOCK), FENCE(Material.FENCE), TRAP_DOOR(Material.TRAP_DOOR), VINE(Material.VINE), FENCE_GATE(Material.FENCE_GATE), WATER_LILLY(Material.WATER_LILY); +// +// private Material material; +// +// FlameableBlock(final Material material) +// { +// this.material = material; +// } +// } + + private static final double REQUIRED_OBSIDIAN_DENSITY = 0.6; + private static final double REQUIRED_COBBLE_DENSITY = 0.5; + private static final double REQUIRED_FIRE_DENSITY = -0.25; + private static final double REQUIRED_AIR_DENSITY = 0; + + private static final ArrayList FLAMABLE_BLOCKS = new ArrayList(); + + private int octaves = 5; + private double frequency = 1; + + private double amplitude = 0.3; + + static + { + for (Material m : Material.values()) { + if (!m.isLegacy() && m.isBlock() && m.isFlammable()) { + FLAMABLE_BLOCKS.add(m); + } + } + } + + + /** + * Default Constructor. + */ + public HeatRayBrush() + { + this.setName("Heat Ray"); + } + + /** + * Heat Ray executer. + * + * @param v + */ + public final void heatRay(final SnipeData v) + { + final PerlinNoiseGenerator generator = new PerlinNoiseGenerator(new Random()); + + final Vector targetLocation = this.getTargetBlock().getLocation().toVector(); + final Location currentLocation = new Location(this.getTargetBlock().getWorld(), 0, 0, 0); + final Undo undo = new Undo(); + Block currentBlock; + + for (int z = v.getBrushSize(); z >= -v.getBrushSize(); z--) + { + for (int x = v.getBrushSize(); x >= -v.getBrushSize(); x--) + { + for (int y = v.getBrushSize(); y >= -v.getBrushSize(); y--) + { + currentLocation.setX(this.getTargetBlock().getX() + x); + currentLocation.setY(this.getTargetBlock().getY() + y); + currentLocation.setZ(this.getTargetBlock().getZ() + z); + + if (currentLocation.toVector().isInSphere(targetLocation, v.getBrushSize())) + { + currentBlock = currentLocation.getBlock(); + if (currentBlock == null || currentBlock.getType() == Material.CHEST) + { + continue; + } + + if (currentBlock.isLiquid()) + { + undo.put(currentBlock); + currentBlock.setType(Material.AIR); + continue; + } + + if (HeatRayBrush.FLAMABLE_BLOCKS.contains(currentBlock.getType())) + { + undo.put(currentBlock); + currentBlock.setType(Material.FIRE); + continue; + } + + if (!currentBlock.getType().equals(Material.AIR)) + { + final double airDensity = generator.noise(currentLocation.getX(), currentLocation.getY(), currentLocation.getZ(), this.octaves, this.frequency, this.amplitude); + final double fireDensity = generator.noise(currentLocation.getX(), currentLocation.getY(), currentLocation.getZ(), this.octaves, this.frequency, this.amplitude); + final double cobbleDensity = generator.noise(currentLocation.getX(), currentLocation.getY(), currentLocation.getZ(), this.octaves, this.frequency, this.amplitude); + final double obsidianDensity = generator.noise(currentLocation.getX(), currentLocation.getY(), currentLocation.getZ(), this.octaves, this.frequency, this.amplitude); + + if (obsidianDensity >= HeatRayBrush.REQUIRED_OBSIDIAN_DENSITY) + { + undo.put(currentBlock); + if (currentBlock.getType() != Material.OBSIDIAN) + { + currentBlock.setType(Material.OBSIDIAN); + } + } + else if (cobbleDensity >= HeatRayBrush.REQUIRED_COBBLE_DENSITY) + { + undo.put(currentBlock); + if (currentBlock.getType() != Material.COBBLESTONE) + { + currentBlock.setType(Material.COBBLESTONE); + } + } + else if (fireDensity >= HeatRayBrush.REQUIRED_FIRE_DENSITY) + { + undo.put(currentBlock); + if (currentBlock.getType() != Material.FIRE) + { + currentBlock.setType(Material.FIRE); + } + } + else if (airDensity >= HeatRayBrush.REQUIRED_AIR_DENSITY) + { + undo.put(currentBlock); + if (!currentBlock.isEmpty()) + { + currentBlock.setType(Material.AIR); + } + } + } + } + + } + } + } + + v.owner().storeUndo(undo); + } + + @Override + protected final void arrow(final SnipeData v) + { + this.heatRay(v); + } + + @Override + protected final void powder(final SnipeData v) + { + this.heatRay(v); + } + + @Override + public final void info(final Message vm) + { + vm.brushName(this.getName()); + vm.custom(ChatColor.GREEN + "Octaves: " + this.octaves); + vm.custom(ChatColor.GREEN + "Amplitude: " + this.amplitude); + vm.custom(ChatColor.GREEN + "Frequency: " + this.frequency); + vm.size(); + } + + @Override + public final void parameters(final String[] par, final SnipeData v) + { + for (int i = 1; i < par.length; i++) + { + final String parameter = par[i].toLowerCase(); + + if (parameter.equalsIgnoreCase("info")) + { + v.sendMessage(ChatColor.GOLD + "Heat Ray brush Parameters:"); + v.sendMessage(ChatColor.AQUA + "/b hr oct[int] -- Octaves parameter for the noise generator."); + v.sendMessage(ChatColor.AQUA + "/b hr amp[float] -- Amplitude parameter for the noise generator."); + v.sendMessage(ChatColor.AQUA + "/b hr freq[float] -- Frequency parameter for the noise generator."); + } + if (parameter.startsWith("oct")) + { + this.octaves = Integer.valueOf(parameter.replace("oct", "")); + v.getVoxelMessage().custom(ChatColor.GREEN + "Octaves: " + this.octaves); + } + else if (parameter.startsWith("amp")) + { + this.amplitude = Double.valueOf(parameter.replace("amp", "")); + v.getVoxelMessage().custom(ChatColor.GREEN + "Amplitude: " + this.amplitude); + } + else if (parameter.startsWith("freq")) + { + this.frequency = Double.valueOf(parameter.replace("freq", "")); + v.getVoxelMessage().custom(ChatColor.GREEN + "Frequency: " + this.frequency); + } + } + } + + @Override + public String getPermissionNode() + { + return "voxelsniper.brush.heatray"; + } +} diff --git a/favs/src/main/java/com/thevoxelbox/voxelsniper/brush/IBrush.java b/favs/src/main/java/com/thevoxelbox/voxelsniper/brush/IBrush.java new file mode 100644 index 000000000..451cecab5 --- /dev/null +++ b/favs/src/main/java/com/thevoxelbox/voxelsniper/brush/IBrush.java @@ -0,0 +1,53 @@ +package com.thevoxelbox.voxelsniper.brush; + +import com.boydti.fawe.bukkit.wrapper.AsyncBlock; +import com.thevoxelbox.voxelsniper.Message; +import com.thevoxelbox.voxelsniper.SnipeAction; +import com.thevoxelbox.voxelsniper.SnipeData; +import org.bukkit.Material; +import org.bukkit.block.Block; +import org.bukkit.block.BlockFace; +import org.bukkit.event.block.Action; + +/** + * Brush Interface. + * + */ +public interface IBrush +{ + + /** + * @param vm Message object + */ + void info(Message vm); + + /** + * Handles parameters passed to brushes. + * + * @param par Array of string containing parameters + * @param v Snipe Data + */ + void parameters(String[] par, SnipeData v); + + boolean perform(SnipeAction action, SnipeData data, AsyncBlock targetBlock, AsyncBlock lastBlock); + + /** + * @return The name of the Brush + */ + String getName(); + + /** + * @param name New name for the Brush + */ + void setName(String name); + + /** + * @return The name of the category the brush is in. + */ + String getBrushCategory(); + + /** + * @return Permission node required to use this brush + */ + String getPermissionNode(); +} diff --git a/favs/src/main/java/com/thevoxelbox/voxelsniper/brush/JaggedLineBrush.java b/favs/src/main/java/com/thevoxelbox/voxelsniper/brush/JaggedLineBrush.java new file mode 100644 index 000000000..48d375609 --- /dev/null +++ b/favs/src/main/java/com/thevoxelbox/voxelsniper/brush/JaggedLineBrush.java @@ -0,0 +1,157 @@ +package com.thevoxelbox.voxelsniper.brush; + +import java.util.Random; + +import com.boydti.fawe.bukkit.wrapper.AsyncBlock; +import com.thevoxelbox.voxelsniper.Message; +import com.thevoxelbox.voxelsniper.SnipeData; +import com.thevoxelbox.voxelsniper.brush.perform.PerformBrush; + +import org.bukkit.ChatColor; +import org.bukkit.block.Block; +import org.bukkit.util.BlockIterator; +import org.bukkit.util.NumberConversions; +import org.bukkit.util.Vector; + +/** + * http://www.voxelwiki.com/minecraft/Voxelsniper#Jagged_Line_Brush + * + * @author Giltwist + * @author Monofraps + */ +public class JaggedLineBrush extends PerformBrush +{ + private static final Vector HALF_BLOCK_OFFSET = new Vector(0.5, 0.5, 0.5); + private static int timesUsed = 0; + + private static final int RECURSION_MIN = 1; + private static final int RECURSION_DEFAULT = 3; + private static final int RECURSION_MAX = 10; + private static final int SPREAD_DEFAULT = 3; + + private Random random = new Random(); + private Vector originCoords = null; + private Vector targetCoords = new Vector(); + private int recursion = RECURSION_DEFAULT; + private int spread = SPREAD_DEFAULT; + + /** + * + */ + public JaggedLineBrush() + { + this.setName("Jagged Line"); + } + + private void jaggedP(final SnipeData v) + { + final Vector originClone = this.originCoords.clone().add(JaggedLineBrush.HALF_BLOCK_OFFSET); + final Vector targetClone = this.targetCoords.clone().add(JaggedLineBrush.HALF_BLOCK_OFFSET); + + final Vector direction = targetClone.clone().subtract(originClone); + final double length = this.targetCoords.distance(this.originCoords); + + if (length == 0) + { + this.current.perform((AsyncBlock) this.targetCoords.toLocation(this.getWorld()).getBlock()); + } + else + { + for (final BlockIterator iterator = new BlockIterator(this.getWorld(), originClone, direction, 0, NumberConversions.round(length)); iterator.hasNext(); ) + { + final Block block = iterator.next(); + for (int i = 0; i < recursion; i++) + { + this.current.perform(this.clampY(Math.round(block.getX() + this.random.nextInt(spread * 2) - spread), Math.round(block.getY() + this.random.nextInt(spread * 2) - spread), Math.round(block.getZ() + this.random.nextInt(spread * 2) - spread))); + } + } + } + + v.owner().storeUndo(this.current.getUndo()); + } + + @Override + public final void arrow(final SnipeData v) + { + if (originCoords == null) + { + originCoords = new Vector(); + } + this.originCoords = this.getTargetBlock().getLocation().toVector(); + v.sendMessage(ChatColor.DARK_PURPLE + "First point selected."); + } + + @Override + public final void powder(final SnipeData v) + { + if (originCoords == null) + { + v.sendMessage(ChatColor.RED + "Warning: You did not select a first coordinate with the arrow"); + } + else + { + this.targetCoords = this.getTargetBlock().getLocation().toVector(); + this.jaggedP(v); + } + + } + + @Override + public final void info(final Message vm) + { + vm.brushName(this.getName()); + vm.custom(ChatColor.GRAY + String.format("Recursion set to: %d", this.recursion)); + vm.custom(ChatColor.GRAY + String.format("Spread set to: %d", this.spread)); + } + + @Override + public final void parameters(final String[] par, final SnipeData v) + { + for (final String parameter : par) + { + try + { + if (parameter.equalsIgnoreCase("info")) + { + v.sendMessage(ChatColor.GOLD + "Jagged Line Brush instructions: Right click first point with the arrow. Right click with powder to draw a jagged line to set the second point."); + v.sendMessage(ChatColor.AQUA + "/b j r# - sets the number of recursions (default 3, must be 1-10)"); + v.sendMessage(ChatColor.AQUA + "/b j s# - sets the spread (default 3, must be 1-10)"); + return; + } + if (parameter.startsWith("r")) + { + final int temp = Integer.parseInt(parameter.substring(1)); + if (temp >= RECURSION_MIN && temp <= RECURSION_MAX) + { + this.recursion = temp; + v.sendMessage(ChatColor.GREEN + "Recursion set to: " + this.recursion); + } + else + { + v.sendMessage(ChatColor.RED + "ERROR: Recursion must be " + RECURSION_MIN + "-" + RECURSION_MAX); + } + + return; + } + else if (parameter.startsWith("s")) + { + final int temp = Integer.parseInt(parameter.substring(1)); + this.spread = temp; + v.sendMessage(ChatColor.GREEN + "Spread set to: " + this.spread); + } + } + catch (Exception exception) + { + v.sendMessage(ChatColor.RED + String.format("Exception while parsing parameter: %s", parameter)); + exception.printStackTrace(); + } + } + + } + + @Override + public String getPermissionNode() + { + return "voxelsniper.brush.jaggedline"; + } +} diff --git a/favs/src/main/java/com/thevoxelbox/voxelsniper/brush/JockeyBrush.java b/favs/src/main/java/com/thevoxelbox/voxelsniper/brush/JockeyBrush.java new file mode 100644 index 000000000..a4477dd1b --- /dev/null +++ b/favs/src/main/java/com/thevoxelbox/voxelsniper/brush/JockeyBrush.java @@ -0,0 +1,278 @@ +package com.thevoxelbox.voxelsniper.brush; + +import com.thevoxelbox.voxelsniper.Message; +import com.thevoxelbox.voxelsniper.SnipeData; +import org.bukkit.Bukkit; +import org.bukkit.ChatColor; +import org.bukkit.Chunk; +import org.bukkit.Location; +import org.bukkit.entity.Entity; +import org.bukkit.entity.Player; +import org.bukkit.event.player.PlayerTeleportEvent; + +import java.util.List; + +/** + * http://www.voxelwiki.com/minecraft/Voxelsniper#The_Jockey_Brush + * + * @author Voxel + * @author Monofraps + */ +public class JockeyBrush extends Brush +{ + private static final int ENTITY_STACK_LIMIT = 50; + private JockeyType jockeyType = JockeyType.NORMAL_ALL_ENTITIES; + private Entity jockeyedEntity = null; + + /** + * + */ + public JockeyBrush() + { + this.setName("Jockey"); + } + + private void sitOn(final SnipeData v) + { + final Chunk targetChunk = this.getWorld().getChunkAt(this.getTargetBlock().getLocation()); + final int targetChunkX = targetChunk.getX(); + final int targetChunkZ = targetChunk.getZ(); + + double range = Double.MAX_VALUE; + Entity closest = null; + + for (int x = targetChunkX - 1; x <= targetChunkX + 1; x++) + { + for (int y = targetChunkZ - 1; y <= targetChunkZ + 1; y++) + { + for (final Entity entity : this.getWorld().getChunkAt(x, y).getEntities()) + { + if (entity.getEntityId() == v.owner().getPlayer().getEntityId()) + { + continue; + } + + if (jockeyType == JockeyType.NORMAL_PLAYER_ONLY || jockeyType == JockeyType.INVERSE_PLAYER_ONLY) + { + if (!(entity instanceof Player)) + { + continue; + } + } + + final Location entityLocation = entity.getLocation(); + final double entityDistance = entityLocation.distance(v.owner().getPlayer().getLocation()); + + if (entityDistance < range) + { + range = entityDistance; + closest = entity; + } + } + } + } + + if (closest != null) + { + final Player player = v.owner().getPlayer(); + final PlayerTeleportEvent playerTeleportEvent = new PlayerTeleportEvent(player, player.getLocation(), closest.getLocation(), PlayerTeleportEvent.TeleportCause.PLUGIN); + + Bukkit.getPluginManager().callEvent(playerTeleportEvent); + + if (!playerTeleportEvent.isCancelled()) + { + if (jockeyType == JockeyType.INVERSE_PLAYER_ONLY || jockeyType == JockeyType.INVERSE_ALL_ENTITIES) + { + player.setPassenger(closest); + } + else + { + closest.setPassenger(player); + jockeyedEntity = closest; + } + v.sendMessage(ChatColor.GREEN + "You are now saddles on entity: " + closest.getEntityId()); + } + } + else + { + v.sendMessage(ChatColor.RED + "Could not find any entities"); + } + } + + private void stack(final SnipeData v) + { + final int brushSizeDoubled = v.getBrushSize() * 2; + + List nearbyEntities = v.owner().getPlayer().getNearbyEntities(brushSizeDoubled, brushSizeDoubled, brushSizeDoubled); + Entity lastEntity = v.owner().getPlayer(); + int stackHeight = 0; + + for (Entity entity : nearbyEntities) + { + if (!(stackHeight >= ENTITY_STACK_LIMIT)) + { + if (jockeyType == JockeyType.STACK_ALL_ENTITIES) + { + lastEntity.setPassenger(entity); + lastEntity = entity; + stackHeight++; + } + else if (jockeyType == JockeyType.STACK_PLAYER_ONLY) + { + if (entity instanceof Player) + { + lastEntity.setPassenger(entity); + lastEntity = entity; + stackHeight++; + } + } + else + { + v.owner().getPlayer().sendMessage("You broke stack! :O"); + } + } + else + { + return; + } + } + + } + + @Override + protected final void arrow(final SnipeData v) + { + if (jockeyType == JockeyType.STACK_ALL_ENTITIES || jockeyType == JockeyType.STACK_PLAYER_ONLY) + { + stack(v); + } + else + { + this.sitOn(v); + } + } + + @Override + protected final void powder(final SnipeData v) + { + if (jockeyType == JockeyType.INVERSE_PLAYER_ONLY || jockeyType == JockeyType.INVERSE_ALL_ENTITIES) + { + v.owner().getPlayer().eject(); + v.owner().getPlayer().sendMessage(ChatColor.GOLD + "The guy on top of you has been ejected!"); + } + else + { + if (jockeyedEntity != null) + { + jockeyedEntity.eject(); + jockeyedEntity = null; + v.owner().getPlayer().sendMessage(ChatColor.GOLD + "You have been ejected!"); + } + } + + } + + @Override + public final void info(final Message vm) + { + vm.brushName(this.getName()); + vm.custom("Current jockey mode: " + ChatColor.GREEN + jockeyType.toString()); + vm.custom(ChatColor.GREEN + "Help: " + ChatColor.AQUA + "http://www.voxelwiki.com/minecraft/Voxelsniper#The_Jockey_Brush"); + } + + @Override + public final void parameters(final String[] par, final SnipeData v) + { + boolean inverse = false; + boolean playerOnly = false; + boolean stack = false; + + try + { + for (String parameter : par) + { + if (parameter.startsWith("-i:")) + { + inverse = parameter.endsWith("y"); + } + + if (parameter.startsWith("-po:")) + { + playerOnly = parameter.endsWith("y"); + } + if (parameter.startsWith("-s:")) + { + stack = parameter.endsWith("y"); + } + + } + + if (inverse) + { + if (playerOnly) + { + jockeyType = JockeyType.INVERSE_PLAYER_ONLY; + } + else + { + jockeyType = JockeyType.INVERSE_ALL_ENTITIES; + } + } + else if (stack) + { + if (playerOnly) + { + jockeyType = JockeyType.STACK_PLAYER_ONLY; + } + else + { + jockeyType = JockeyType.STACK_ALL_ENTITIES; + } + } + else + { + if (playerOnly) + { + jockeyType = JockeyType.NORMAL_PLAYER_ONLY; + } + else + { + jockeyType = JockeyType.NORMAL_ALL_ENTITIES; + } + } + + v.sendMessage("Current jockey mode: " + ChatColor.GREEN + jockeyType.toString()); + } + catch (Exception exception) + { + v.sendMessage("Error while parsing your arguments."); + exception.printStackTrace(); + } + } + + /** + * Available types of jockey modes. + */ + private enum JockeyType + { + NORMAL_ALL_ENTITIES("Normal (All)"), NORMAL_PLAYER_ONLY("Normal (Player only)"), INVERSE_ALL_ENTITIES("Inverse (All)"), INVERSE_PLAYER_ONLY("Inverse (Player only)"), STACK_ALL_ENTITIES("Stack (All)"), STACK_PLAYER_ONLY("Stack (Player only)"); + private String name; + + JockeyType(String name) + { + this.name = name; + } + + @Override + public String toString() + { + return this.name; + } + } + + @Override + public String getPermissionNode() + { + return "voxelsniper.brush.jockey"; + } +} diff --git a/favs/src/main/java/com/thevoxelbox/voxelsniper/brush/LightningBrush.java b/favs/src/main/java/com/thevoxelbox/voxelsniper/brush/LightningBrush.java new file mode 100644 index 000000000..59b3b625b --- /dev/null +++ b/favs/src/main/java/com/thevoxelbox/voxelsniper/brush/LightningBrush.java @@ -0,0 +1,43 @@ +package com.thevoxelbox.voxelsniper.brush; + +import com.thevoxelbox.voxelsniper.Message; +import com.thevoxelbox.voxelsniper.SnipeData; + +/** + * @author Gavjenks + */ +public class LightningBrush extends Brush +{ + /** + * + */ + public LightningBrush() + { + this.setName("Lightning"); + } + + @Override + public final void info(final Message vm) + { + vm.brushName(this.getName()); + vm.brushMessage("Lightning Brush! Please use in moderation."); + } + + @Override + protected final void arrow(final SnipeData v) + { + this.getWorld().strikeLightning(this.getTargetBlock().getLocation()); + } + + @Override + protected final void powder(final SnipeData v) + { + this.getWorld().strikeLightning(this.getTargetBlock().getLocation()); + } + + @Override + public String getPermissionNode() + { + return "voxelsniper.brush.lightning"; + } +} diff --git a/favs/src/main/java/com/thevoxelbox/voxelsniper/brush/LineBrush.java b/favs/src/main/java/com/thevoxelbox/voxelsniper/brush/LineBrush.java new file mode 100644 index 000000000..c1d0737ac --- /dev/null +++ b/favs/src/main/java/com/thevoxelbox/voxelsniper/brush/LineBrush.java @@ -0,0 +1,103 @@ +package com.thevoxelbox.voxelsniper.brush; + +import com.boydti.fawe.bukkit.wrapper.AsyncBlock; +import com.boydti.fawe.bukkit.wrapper.AsyncWorld; +import com.thevoxelbox.voxelsniper.Message; +import com.thevoxelbox.voxelsniper.SnipeData; +import com.thevoxelbox.voxelsniper.brush.perform.PerformBrush; +import org.bukkit.ChatColor; +import org.bukkit.World; +import org.bukkit.block.Block; +import org.bukkit.util.BlockIterator; +import org.bukkit.util.NumberConversions; +import org.bukkit.util.Vector; + +/** + * http://www.voxelwiki.com/minecraft/Voxelsniper#Line_Brush + * + * @author Gavjenks + * @author giltwist + * @author MikeMatrix + */ +public class LineBrush extends PerformBrush +{ + private static final Vector HALF_BLOCK_OFFSET = new Vector(0.5, 0.5, 0.5); + private Vector originCoords = null; + private Vector targetCoords = new Vector(); + private AsyncWorld targetWorld; + + /** + * + */ + public LineBrush() + { + this.setName("Line"); + } + + @Override + public final void info(final Message vm) + { + vm.brushName(this.getName()); + } + + @Override + public final void parameters(final String[] par, final SnipeData v) + { + if (par[1].equalsIgnoreCase("info")) + { + v.sendMessage(ChatColor.GOLD + "Line Brush instructions: Right click first point with the arrow. Right click with powder to draw a line to set the second point."); + } + } + + private void linePowder(final SnipeData v) + { + final Vector originClone = this.originCoords.clone().add(LineBrush.HALF_BLOCK_OFFSET); + final Vector targetClone = this.targetCoords.clone().add(LineBrush.HALF_BLOCK_OFFSET); + + final Vector direction = targetClone.clone().subtract(originClone); + final double length = this.targetCoords.distance(this.originCoords); + + if (length == 0) + { + this.current.perform((AsyncBlock) this.targetCoords.toLocation(this.targetWorld).getBlock()); + } + else + { + for (final BlockIterator blockIterator = new BlockIterator(this.targetWorld, originClone, direction, 0, NumberConversions.round(length)); blockIterator.hasNext(); ) + { + final AsyncBlock currentBlock = (AsyncBlock) blockIterator.next(); + this.current.perform(currentBlock); + } + } + + v.owner().storeUndo(this.current.getUndo()); + } + + @Override + protected final void arrow(final SnipeData v) + { + this.originCoords = this.getTargetBlock().getLocation().toVector(); + this.targetWorld = this.getTargetBlock().getWorld(); + v.owner().getPlayer().sendMessage(ChatColor.DARK_PURPLE + "First point selected."); + } + + @Override + protected final void powder(final SnipeData v) + { + if (this.originCoords == null || !this.getTargetBlock().getWorld().equals(this.targetWorld)) + { + v.owner().getPlayer().sendMessage(ChatColor.RED + "Warning: You did not select a first coordinate with the arrow"); + } + else + { + this.targetCoords = this.getTargetBlock().getLocation().toVector(); + this.linePowder(v); + } + } + + @Override + public String getPermissionNode() + { + return "voxelsniper.brush.line"; + } +} diff --git a/favs/src/main/java/com/thevoxelbox/voxelsniper/brush/MoveBrush.java b/favs/src/main/java/com/thevoxelbox/voxelsniper/brush/MoveBrush.java new file mode 100644 index 000000000..b59d0ece1 --- /dev/null +++ b/favs/src/main/java/com/thevoxelbox/voxelsniper/brush/MoveBrush.java @@ -0,0 +1,312 @@ +package com.thevoxelbox.voxelsniper.brush; + +import com.boydti.fawe.bukkit.wrapper.AsyncBlock; +import com.boydti.fawe.bukkit.wrapper.AsyncBlockState; +import com.boydti.fawe.bukkit.wrapper.AsyncWorld; +import com.thevoxelbox.voxelsniper.Message; +import com.thevoxelbox.voxelsniper.SnipeData; +import com.thevoxelbox.voxelsniper.Undo; +import org.bukkit.ChatColor; +import org.bukkit.Location; +import org.bukkit.Material; +import org.bukkit.World; +import org.bukkit.block.Block; +import org.bukkit.block.BlockState; + +import java.util.ArrayList; +import java.util.HashSet; +import java.util.Set; +import java.util.TreeSet; + +/** + * Moves a selection blockPositionY a certain amount. + * http://www.voxelwiki.com/minecraft/Voxelsniper#Move_Brush + * + * @author MikeMatrix + */ +public class MoveBrush extends Brush +{ + /** + * Saved direction. + */ + private final int[] moveDirections = {0, 0, 0}; + /** + * Saved selection. + */ + private Selection selection = null; + + /** + * + */ + public MoveBrush() + { + this.setName("Move"); + } + + /** + * Moves the given selection blockPositionY the amount given in direction and saves an undo for the player. + * + * @param v + * @param selection + * @param direction + */ + @SuppressWarnings("deprecation") + private void moveSelection(final SnipeData v, final Selection selection, final int[] direction) + { + if (selection.getBlockStates().size() > 0) + { + final AsyncWorld world = selection.getBlockStates().get(0).getWorld(); + + final Undo undo = new Undo(); + final HashSet undoSet = new HashSet(); + + final Selection newSelection = new Selection(); + final Location movedLocation1 = selection.getLocation1(); + movedLocation1.add(direction[0], direction[1], direction[2]); + final Location movedLocation2 = selection.getLocation2(); + movedLocation2.add(direction[0], direction[1], direction[2]); + newSelection.setLocation1(movedLocation1); + newSelection.setLocation2(movedLocation2); + try + { + newSelection.calculateRegion(); + } + catch (final Exception exception) + { + v.getVoxelMessage().brushMessage("The new Selection has more blocks than the original selection. This should never happen!"); + } + + for (final BlockState blockState : selection.getBlockStates()) + { + undoSet.add(blockState.getBlock()); + } + for (final BlockState blockState : newSelection.getBlockStates()) + { + undoSet.add(blockState.getBlock()); + } + + for (final Block block : undoSet) + { + undo.put(block); + } + v.owner().storeUndo(undo); + + for (final BlockState blockState : selection.getBlockStates()) + { + blockState.getBlock().setType(Material.AIR); + } + for (final AsyncBlockState blockState : selection.getBlockStates()) + { + final AsyncBlock affectedBlock = world.getBlockAt(blockState.getX() + direction[0], blockState.getY() + direction[1], blockState.getZ() + direction[2]); + affectedBlock.setTypeId(blockState.getTypeId()); + affectedBlock.setPropertyId(blockState.getPropertyId()); + } + } + } + + @Override + protected final void arrow(final SnipeData v) + { + if (this.selection == null) + { + this.selection = new Selection(); + } + this.selection.setLocation1(this.getTargetBlock().getLocation()); + v.getVoxelMessage().brushMessage("Point 1 set."); + + try + { + if (this.selection.calculateRegion()) + { + this.moveSelection(v, this.selection, this.moveDirections); + this.selection = null; + } + } + catch (final Exception exception) + { + v.sendMessage(exception.getMessage()); + } + } + + @Override + protected final void powder(final SnipeData v) + { + if (this.selection == null) + { + this.selection = new Selection(); + } + this.selection.setLocation2(this.getTargetBlock().getLocation()); + v.getVoxelMessage().brushMessage("Point 2 set."); + + try + { + if (this.selection.calculateRegion()) + { + this.moveSelection(v, this.selection, this.moveDirections); + this.selection = null; + } + } + catch (final Exception exception) + { + v.sendMessage(exception.getMessage()); + } + } + + @Override + public final void info(final Message vm) + { + vm.brushName(this.getName()); + vm.custom(ChatColor.BLUE + "Move selection blockPositionY " + ChatColor.GOLD + "x:" + this.moveDirections[0] + " y:" + this.moveDirections[1] + " z:" + this.moveDirections[2]); + } + + @Override + public final void parameters(final String[] par, final SnipeData v) + { + for (int i = 1; i < par.length; i++) + { + if (par[i].equalsIgnoreCase("info")) + { + v.getVoxelMessage().custom(ChatColor.GOLD + this.getName() + " Parameters:"); + v.getVoxelMessage().custom(ChatColor.AQUA + "/b mv x[int] -- set the x direction (positive => east)"); + v.getVoxelMessage().custom(ChatColor.AQUA + "/b mv y[int] -- set the y direction (positive => up)"); + v.getVoxelMessage().custom(ChatColor.AQUA + "/b mv z[int] -- set the z direction (positive => south)"); + v.getVoxelMessage().custom(ChatColor.AQUA + "/b mv reset -- reset the brush (x:0 y:0 z:0)"); + v.getVoxelMessage().custom(ChatColor.AQUA + "Use arrow and gunpowder to define two points."); + } + if (par[i].equalsIgnoreCase("reset")) + { + this.moveDirections[0] = 0; + this.moveDirections[1] = 0; + this.moveDirections[2] = 0; + v.getVoxelMessage().custom(ChatColor.AQUA + "X direction set to: " + this.moveDirections[0]); + v.getVoxelMessage().custom(ChatColor.AQUA + "Y direction set to: " + this.moveDirections[1]); + v.getVoxelMessage().custom(ChatColor.AQUA + "Z direction set to: " + this.moveDirections[2]); + } + if (par[i].toLowerCase().startsWith("x")) + { + this.moveDirections[0] = Integer.valueOf(par[i].substring(1)); + v.getVoxelMessage().custom(ChatColor.AQUA + "X direction set to: " + this.moveDirections[0]); + } + else if (par[i].toLowerCase().startsWith("y")) + { + this.moveDirections[1] = Integer.valueOf(par[i].substring(1)); + v.getVoxelMessage().custom(ChatColor.AQUA + "Y direction set to: " + this.moveDirections[1]); + } + else if (par[i].toLowerCase().startsWith("z")) + { + this.moveDirections[2] = Integer.valueOf(par[i].substring(1)); + v.getVoxelMessage().custom(ChatColor.AQUA + "Z direction set to: " + this.moveDirections[2]); + } + } + } + + /** + * Selection Helper class. + * + * @author MikeMatrix + */ + private class Selection + { + /** + * Maximum amount of Blocks allowed blockPositionY the Selection. + */ + private static final int MAX_BLOCK_COUNT = 5000000; + /** + * Calculated BlockStates of the selection. + */ + private final ArrayList blockStates = new ArrayList(); + /** + * + */ + private Location location1 = null; + /** + * + */ + private Location location2 = null; + + /** + * Calculates region, then saves all Blocks as BlockState. + * + * @return boolean success. + * @throws Exception Message to be sent to the player. + */ + public boolean calculateRegion() throws Exception + { + if (this.location1 != null && this.location2 != null) + { + if (this.location1.getWorld().equals(this.location2.getWorld())) + { + final int lowX = ((this.location1.getBlockX() <= this.location2.getBlockX()) ? this.location1.getBlockX() : this.location2.getBlockX()); + final int lowY = (this.location1.getBlockY() <= this.location2.getBlockY()) ? this.location1.getBlockY() : this.location2.getBlockY(); + final int lowZ = (this.location1.getBlockZ() <= this.location2.getBlockZ()) ? this.location1.getBlockZ() : this.location2.getBlockZ(); + final int highX = (this.location1.getBlockX() >= this.location2.getBlockX()) ? this.location1.getBlockX() : this.location2.getBlockX(); + final int highY = (this.location1.getBlockY() >= this.location2.getBlockY()) ? this.location1.getBlockY() : this.location2.getBlockY(); + final int highZ = (this.location1.getBlockZ() >= this.location2.getBlockZ()) ? this.location1.getBlockZ() : this.location2.getBlockZ(); + if (Math.abs(highX - lowX) * Math.abs(highZ - lowZ) * Math.abs(highY - lowY) > Selection.MAX_BLOCK_COUNT) + { + throw new Exception(ChatColor.RED + "Selection size above hardcoded limit, please use a smaller selection."); + } + final AsyncWorld world = (AsyncWorld) this.location1.getWorld(); + for (int y = lowY; y <= highY; y++) + { + for (int x = lowX; x <= highX; x++) + { + for (int z = lowZ; z <= highZ; z++) + { + this.blockStates.add(world.getBlockAt(x, y, z).getState()); + } + } + } + return true; + } + } + return false; + } + + /** + * @return ArrayList calculated BlockStates of defined region. + */ + public ArrayList getBlockStates() + { + return this.blockStates; + } + + /** + * @return Location + */ + public Location getLocation1() + { + return this.location1; + } + + /** + * @param location1 + */ + public void setLocation1(final Location location1) + { + this.location1 = location1; + } + + /** + * @return Location + */ + public Location getLocation2() + { + return this.location2; + } + + /** + * @param location2 + */ + public void setLocation2(final Location location2) + { + this.location2 = location2; + } + } + + @Override + public String getPermissionNode() + { + return "voxelsniper.brush.move"; + } +} diff --git a/favs/src/main/java/com/thevoxelbox/voxelsniper/brush/OceanBrush.java b/favs/src/main/java/com/thevoxelbox/voxelsniper/brush/OceanBrush.java new file mode 100644 index 000000000..79af80e5d --- /dev/null +++ b/favs/src/main/java/com/thevoxelbox/voxelsniper/brush/OceanBrush.java @@ -0,0 +1,191 @@ +package com.thevoxelbox.voxelsniper.brush; + +import com.boydti.fawe.bukkit.wrapper.AsyncBlock; +import com.boydti.fawe.bukkit.wrapper.AsyncWorld; +import com.thevoxelbox.voxelsniper.Message; +import com.thevoxelbox.voxelsniper.SnipeData; +import com.thevoxelbox.voxelsniper.Undo; +import org.bukkit.ChatColor; +import org.bukkit.Material; +import org.bukkit.block.Block; + +/** + * http://www.voxelwiki.com/minecraft/Voxelsniper#The_OCEANATOR_5000 + * + * @author Voxel + */ +public class OceanBrush extends Brush +{ + private static final int WATER_LEVEL_DEFAULT = 62; // y=63 -- we are using array indices here + private static final int WATER_LEVEL_MIN = 12; + private static final int LOW_CUT_LEVEL = 12; + + private int waterLevel = WATER_LEVEL_DEFAULT; + private boolean coverFloor = false; + + /** + * + */ + public OceanBrush() + { + this.setName("OCEANATOR 5000(tm)"); + } + + private int getHeight(final int bx, final int bz) + { + for (int y = this.getWorld().getHighestBlockYAt(bx, bz); y > 0; y--) + { + final Material material = this.clampY(bx, y, bz).getType(); + if (material.isSolid()) + { + return y; + } + } + return 0; + } + + /** + * @param v + * @param undo + */ + protected final void oceanator(final SnipeData v, final Undo undo) + { + final AsyncWorld world = this.getWorld(); + + final int minX = (int) Math.floor((this.getTargetBlock().getX() - v.getBrushSize())); + final int minZ = (int) Math.floor((this.getTargetBlock().getZ() - v.getBrushSize())); + final int maxX = (int) Math.floor((this.getTargetBlock().getX() + v.getBrushSize())); + final int maxZ = (int) Math.floor((this.getTargetBlock().getZ() + v.getBrushSize())); + + for (int x = minX; x <= maxX; x++) + { + for (int z = minZ; z <= maxZ; z++) + { + final int currentHeight = getHeight(x, z); + final int wLevelDiff = currentHeight - (this.waterLevel - 1); + final int newSeaFloorLevel = ((this.waterLevel - wLevelDiff) >= LOW_CUT_LEVEL) ? this.waterLevel - wLevelDiff : LOW_CUT_LEVEL; + + final int highestY = this.getWorld().getHighestBlockYAt(x, z); + + // go down from highest Y block down to new sea floor + for (int y = highestY; y > newSeaFloorLevel; y--) + { + final Block block = world.getBlockAt(x, y, z); + if (!block.getType().equals(Material.AIR)) + { + undo.put(block); + block.setType(Material.AIR); + } + } + + // go down from water level to new sea level + for (int y = this.waterLevel; y > newSeaFloorLevel; y--) + { + final Block block = world.getBlockAt(x, y, z); + if (!block.getType().equals(Material.WATER)) + { + // do not put blocks into the undo we already put into + if (!block.getType().equals(Material.AIR)) + { + undo.put(block); + } + block.setType(Material.WATER); + } + } + + // cover the sea floor of required + if (this.coverFloor && (newSeaFloorLevel < this.waterLevel)) + { + AsyncBlock block = world.getBlockAt(x, newSeaFloorLevel, z); + if (block.getTypeId() != v.getVoxelId()) + { + undo.put(block); + block.setTypeId(v.getVoxelId()); + } + } + } + } + } + + @Override + protected final void arrow(final SnipeData v) + { + Undo undo = new Undo(); + this.oceanator(v, undo); + v.owner().storeUndo(undo); + } + + @Override + protected final void powder(final SnipeData v) + { + arrow(v); + } + + @Override + public final void parameters(final String[] par, final SnipeData v) + { + for (int i = 0; i < par.length; i++) + { + final String parameter = par[i]; + + try + { + if (parameter.equalsIgnoreCase("info")) + { + v.sendMessage(ChatColor.BLUE + "Parameters:"); + v.sendMessage(ChatColor.GREEN + "-wlevel # " + ChatColor.BLUE + "-- Sets the water level (e.g. -wlevel 64)"); + v.sendMessage(ChatColor.GREEN + "-cfloor [y|n] " + ChatColor.BLUE + "-- Enables or disables sea floor cover (e.g. -cfloor y) (Cover material will be your voxel material)"); + } + else if (parameter.equalsIgnoreCase("-wlevel")) + { + if ((i + 1) >= par.length) + { + v.sendMessage(ChatColor.RED + "Missing parameter. Correct syntax: -wlevel [#] (e.g. -wlevel 64)"); + continue; + } + + int temp = Integer.parseInt(par[++i]); + + if (temp <= WATER_LEVEL_MIN) + { + v.sendMessage(ChatColor.RED + "Error: Your specified water level was below 12."); + continue; + } + + this.waterLevel = temp - 1; + v.sendMessage(ChatColor.BLUE + "Water level set to " + ChatColor.GREEN + (waterLevel + 1)); // +1 since we are working with 0-based array indices + } + else if (parameter.equalsIgnoreCase("-cfloor") || parameter.equalsIgnoreCase("-coverfloor")) + { + if ((i + 1) >= par.length) + { + v.sendMessage(ChatColor.RED + "Missing parameter. Correct syntax: -cfloor [y|n] (e.g. -cfloor y)"); + continue; + } + + this.coverFloor = par[++i].equalsIgnoreCase("y"); + v.sendMessage(ChatColor.BLUE + String.format("Floor cover %s.", ChatColor.GREEN + (this.coverFloor ? "enabled" : "disabled"))); + } + } + catch (Exception exception) + { + v.sendMessage(ChatColor.RED + String.format("Error while parsing parameter: %s", parameter)); + exception.printStackTrace(); + } + } + } + + @Override + public final void info(final Message vm) + { + vm.brushName(this.getName()); + vm.custom(ChatColor.BLUE + "Water level set to " + ChatColor.GREEN + (waterLevel + 1)); // +1 since we are working with 0-based array indices + vm.custom(ChatColor.BLUE + String.format("Floor cover %s.", ChatColor.GREEN + (this.coverFloor ? "enabled" : "disabled"))); + } + + @Override + public String getPermissionNode() + { + return "voxelsniper.brush.ocean"; + } +} diff --git a/favs/src/main/java/com/thevoxelbox/voxelsniper/brush/OverlayBrush.java b/favs/src/main/java/com/thevoxelbox/voxelsniper/brush/OverlayBrush.java new file mode 100644 index 000000000..51188ddee --- /dev/null +++ b/favs/src/main/java/com/thevoxelbox/voxelsniper/brush/OverlayBrush.java @@ -0,0 +1,233 @@ +package com.thevoxelbox.voxelsniper.brush; + +import com.sk89q.worldedit.blocks.BlockMaterial; +import com.sk89q.worldedit.world.block.BlockTypes; +import com.thevoxelbox.voxelsniper.Message; +import com.thevoxelbox.voxelsniper.SnipeData; +import com.thevoxelbox.voxelsniper.brush.perform.PerformBrush; +import org.bukkit.ChatColor; +import org.bukkit.Material; + +/** + * http://www.voxelwiki.com/minecraft/Voxelsniper#The_Overlay_.2F_Topsoil_Brush + * + * @author Gavjenks + */ +public class OverlayBrush extends PerformBrush +{ + private static final int DEFAULT_DEPTH = 3; + private int depth = DEFAULT_DEPTH; + private boolean allBlocks = false; + + /** + * + */ + public OverlayBrush() + { + this.setName("Overlay (Topsoil Filling)"); + } + + private void overlay(final SnipeData v) + { + final int brushSize = v.getBrushSize(); + final double brushSizeSquared = Math.pow(brushSize + 0.5, 2); + + + for (int z = brushSize; z >= -brushSize; z--) + { + for (int x = brushSize; x >= -brushSize; x--) + { + // check if column is valid + // column is valid if it has no solid block right above the clicked layer + final int materialId = this.getBlockIdAt(this.getTargetBlock().getX() + x, this.getTargetBlock().getY() + 1, this.getTargetBlock().getZ() + z); + if (isIgnoredBlock(materialId)) + { + if ((Math.pow(x, 2) + Math.pow(z, 2)) <= brushSizeSquared) + { + for (int y = this.getTargetBlock().getY(); y > 0; y--) + { + // check for surface + final int layerBlockId = this.getBlockIdAt(this.getTargetBlock().getX() + x, y, this.getTargetBlock().getZ() + z); + if (!isIgnoredBlock(layerBlockId)) + { + for (int currentDepth = y; y - currentDepth < depth; currentDepth--) + { + final int currentBlockId = this.getBlockIdAt(this.getTargetBlock().getX() + x, currentDepth, this.getTargetBlock().getZ() + z); + if (isOverrideableMaterial(currentBlockId)) + { + this.current.perform(this.clampY(this.getTargetBlock().getX() + x, currentDepth, this.getTargetBlock().getZ() + z)); + } + } + break; + } + } + } + } + } + } + + v.owner().storeUndo(this.current.getUndo()); + } + + @SuppressWarnings("deprecation") + private boolean isIgnoredBlock(int materialId) + { + BlockTypes type = BlockTypes.getFromStateId(materialId); + switch (type) { + case WATER: + case LAVA: + case CACTUS: + return true; + } + BlockMaterial mat = type.getMaterial(); + return mat.isTranslucent(); + } + + @SuppressWarnings("deprecation") + private boolean isOverrideableMaterial(int materialId) + { + BlockMaterial mat = BlockTypes.getFromStateId(materialId).getMaterial(); + if (allBlocks && !(mat.isAir())) + { + return true; + } + + if (!mat.isFragileWhenPushed() && mat.isFullCube()) { + return true; + } + return false; + } + + private void overlayTwo(final SnipeData v) + { + final int brushSize = v.getBrushSize(); + final double brushSizeSquared = Math.pow(brushSize + 0.5, 2); + final int[][] memory = new int[brushSize * 2 + 1][brushSize * 2 + 1]; + + for (int z = brushSize; z >= -brushSize; z--) + { + for (int x = brushSize; x >= -brushSize; x--) + { + boolean surfaceFound = false; + for (int y = this.getTargetBlock().getY(); y > 0 && !surfaceFound; y--) + { // start scanning from the height you clicked at + if (memory[x + brushSize][z + brushSize] != 1) + { // if haven't already found the surface in this column + if ((Math.pow(x, 2) + Math.pow(z, 2)) <= brushSizeSquared) + { // if inside of the column... + if (this.getBlockIdAt(this.getTargetBlock().getX() + x, y - 1, this.getTargetBlock().getZ() + z) != 0) + { // if not a floating block (like one of Notch'world pools) + if (this.getBlockIdAt(this.getTargetBlock().getX() + x, y + 1, this.getTargetBlock().getZ() + z) == 0) + { // must start at surface... this prevents it filling stuff in if + // you click in a wall and it starts out below surface. + if (!this.allBlocks) + { // if the override parameter has not been activated, go to the switch that filters out manmade stuff. + + BlockTypes type = BlockTypes.get(this.getBlockIdAt(this.getTargetBlock().getX() + x, y, this.getTargetBlock().getZ() + z)); + BlockMaterial mat = type.getMaterial(); + if (mat.isSolid() && mat.isFullCube() && !mat.hasContainer()) { + for (int d = 1; (d < this.depth + 1); d++) { + this.current.perform(this.clampY(this.getTargetBlock().getX() + x, y + d, this.getTargetBlock().getZ() + z)); // fills down as many layers as you specify + // in parameters + memory[x + brushSize][z + brushSize] = 1; // stop it from checking any other blocks in this vertical 1x1 column. + } + surfaceFound = true; + continue; + + } else { + continue; + } + } + else + { + for (int d = 1; (d < this.depth + 1); d++) + { + this.current.perform(this.clampY(this.getTargetBlock().getX() + x, y + d, this.getTargetBlock().getZ() + z)); // fills down as many layers as you specify in + // parameters + memory[x + brushSize][z + brushSize] = 1; // stop it from checking any other blocks in this vertical 1x1 column. + } + surfaceFound = true; + } + + } + } + } + } + } + } + } + + v.owner().storeUndo(this.current.getUndo()); + } + + @Override + protected final void arrow(final SnipeData v) + { + this.overlay(v); + } + + @Override + protected final void powder(final SnipeData v) + { + this.overlayTwo(v); + } + + @Override + public final void info(final Message vm) + { + vm.brushName(this.getName()); + vm.size(); + } + + @Override + public final void parameters(final String[] par, final SnipeData v) + { + for (int i = 1; i < par.length; i++) + { + final String parameter = par[i]; + + if (parameter.equalsIgnoreCase("info")) + { + v.sendMessage(ChatColor.GOLD + "Overlay brush parameters:"); + v.sendMessage(ChatColor.AQUA + "d[number] (ex: d3) How many blocks deep you want to replace from the surface."); + v.sendMessage(ChatColor.BLUE + "all (ex: /b over all) Sets the brush to overlay over ALL materials, not just natural surface ones (will no longer ignore trees and buildings). The parameter /some will set it back to default."); + return; + } + if (parameter.startsWith("d")) + { + try { + this.depth = Integer.parseInt(parameter.replace("d", "")); + + if (this.depth < 1) + { + this.depth = 1; + } + + v.sendMessage(ChatColor.AQUA + "Depth set to " + this.depth); + } catch (NumberFormatException e) { + v.sendMessage(ChatColor.RED + "Depth isn't a number."); + } + } + else if (parameter.startsWith("all")) + { + this.allBlocks = true; + v.sendMessage(ChatColor.BLUE + "Will overlay over any block." + this.depth); + } + else if (parameter.startsWith("some")) + { + this.allBlocks = false; + v.sendMessage(ChatColor.BLUE + "Will overlay only natural block types." + this.depth); + } + else + { + v.sendMessage(ChatColor.RED + "Invalid brush parameters! use the info parameter to display parameter info."); + } + } + } + + @Override + public String getPermissionNode() + { + return "voxelsniper.brush.overlay"; + } +} diff --git a/favs/src/main/java/com/thevoxelbox/voxelsniper/brush/PaintingBrush.java b/favs/src/main/java/com/thevoxelbox/voxelsniper/brush/PaintingBrush.java new file mode 100644 index 000000000..a40026e50 --- /dev/null +++ b/favs/src/main/java/com/thevoxelbox/voxelsniper/brush/PaintingBrush.java @@ -0,0 +1,56 @@ +package com.thevoxelbox.voxelsniper.brush; + +import com.thevoxelbox.voxelsniper.Message; +import com.thevoxelbox.voxelsniper.PaintingWrapper; +import com.thevoxelbox.voxelsniper.SnipeData; + +/** + * Painting scrolling Brush. + * http://www.voxelwiki.com/minecraft/Voxelsniper#The_Painting_Picker_Brush + * + * @author Voxel + */ +public class PaintingBrush extends Brush +{ + /** + * + */ + public PaintingBrush() + { + this.setName("Painting"); + } + + /** + * Scroll painting forward. + * + * @param v Sniper caller + */ + @Override + protected final void arrow(final SnipeData v) + { + PaintingWrapper.paint(v.owner().getPlayer(), true, false, 0); + } + + /** + * Scroll painting backwards. + * + * @param v Sniper caller + */ + @Override + protected final void powder(final SnipeData v) + { + PaintingWrapper.paint(v.owner().getPlayer(), true, true, 0); + } + + @Override + public final void info(final Message vm) + { + vm.brushName(this.getName()); + } + + @Override + public String getPermissionNode() + { + return "voxelsniper.brush.painting"; + } +} diff --git a/favs/src/main/java/com/thevoxelbox/voxelsniper/brush/PullBrush.java b/favs/src/main/java/com/thevoxelbox/voxelsniper/brush/PullBrush.java new file mode 100644 index 000000000..6fbed519b --- /dev/null +++ b/favs/src/main/java/com/thevoxelbox/voxelsniper/brush/PullBrush.java @@ -0,0 +1,371 @@ +package com.thevoxelbox.voxelsniper.brush; + +import com.boydti.fawe.bukkit.wrapper.AsyncBlock; +import com.thevoxelbox.voxelsniper.Message; +import com.thevoxelbox.voxelsniper.SnipeData; +import org.bukkit.ChatColor; +import org.bukkit.block.Block; + +import java.util.HashSet; + +/** + * @author Piotr + */ +public class PullBrush extends Brush +{ + private final HashSet surface = new HashSet(); + private int vh; + private double c1 = 1; + private double c2 = 0; + + /** + * Default Constructor. + */ + public PullBrush() + { + this.setName("Soft Selection"); + } + + @Override + public final void info(final Message vm) + { + vm.brushName(this.getName()); + vm.size(); + vm.height(); + vm.custom(ChatColor.AQUA + "Pinch " + (-this.c1 + 1)); + vm.custom(ChatColor.AQUA + "Bubble " + this.c2); + } + + @Override + public final void parameters(final String[] par, final SnipeData v) + { + try + { + final double pinch = Double.parseDouble(par[1]); + final double bubble = Double.parseDouble(par[2]); + this.c1 = 1 - pinch; + this.c2 = bubble; + } + catch (final Exception exception) + { + v.sendMessage(ChatColor.RED + "Invalid brush parameters!"); + } + } + + /** + * @param t + * @return double + */ + private double getStr(final double t) + { + final double lt = 1 - t; + return (lt * lt * lt) + 3 * (lt * lt) * t * this.c1 + 3 * lt * (t * t) * this.c2; // My + (t * ((By + (t * ((c2 + (t * (0 - c2))) - By))) - My)); + } + + /** + * @param v + */ + private void getSurface(final SnipeData v) + { + this.surface.clear(); + + final double bSquared = Math.pow(v.getBrushSize() + 0.5, 2); + for (int z = -v.getBrushSize(); z <= v.getBrushSize(); z++) + { + final double zSquared = Math.pow(z, 2); + final int actualZ = this.getTargetBlock().getZ() + z; + for (int x = -v.getBrushSize(); x <= v.getBrushSize(); x++) + { + final double xSquared = Math.pow(x, 2); + final int actualX = this.getTargetBlock().getX() + x; + for (int y = -v.getBrushSize(); y <= v.getBrushSize(); y++) + { + final double volume = (xSquared + Math.pow(y, 2) + zSquared); + if (volume <= bSquared) + { + if (this.isSurface(actualX, this.getTargetBlock().getY() + y, actualZ)) + { + this.surface.add(new BlockWrapper(this.clampY(actualX, this.getTargetBlock().getY() + y, actualZ), this.getStr(((volume / bSquared))))); + } + } + } + } + } + } + + /** + * @param x + * @param y + * @param z + * @return boolean + */ + private boolean isSurface(final int x, final int y, final int z) + { + return this.getBlockIdAt(x, y, z) != 0 && ((this.getBlockIdAt(x, y - 1, z) == 0) || (this.getBlockIdAt(x, y + 1, z) == 0) || (this.getBlockIdAt(x + 1, y, z) == 0) || (this.getBlockIdAt(x - 1, y, z) == 0) || (this.getBlockIdAt(x, y, z + 1) == 0) || (this.getBlockIdAt(x, y, z - 1) == 0)); + + } + + @SuppressWarnings("deprecation") + private void setBlock(final BlockWrapper block) + { + final AsyncBlock currentBlock = this.clampY(block.getX(), block.getY() + (int) (this.vh * block.getStr()), block.getZ()); + if (this.getBlockIdAt(block.getX(), block.getY() - 1, block.getZ()) == 0) + { + currentBlock.setTypeId(block.getId()); + currentBlock.setPropertyId(block.getD()); + for (int y = block.getY(); y < currentBlock.getY(); y++) + { + this.setBlockIdAt(block.getZ(), block.getX(), y, 0); + } + } + else + { + currentBlock.setTypeId(block.getId()); + currentBlock.setPropertyId(block.getD()); + for (int y = block.getY() - 1; y < currentBlock.getY(); y++) + { + final AsyncBlock current = this.clampY(block.getX(), y, block.getZ()); + current.setTypeId(block.getId()); + current.setPropertyId(block.getD()); + } + } + } + + @SuppressWarnings("deprecation") + private void setBlockDown(final BlockWrapper block) + { + final AsyncBlock currentBlock = this.clampY(block.getX(), block.getY() + (int) (this.vh * block.getStr()), block.getZ()); + currentBlock.setTypeId(block.getId()); + currentBlock.setPropertyId(block.getD()); + for (int y = block.getY(); y > currentBlock.getY(); y--) + { + this.setBlockIdAt(block.getZ(), block.getX(), y, 0); + } + // } + } + + @Override + protected final void arrow(final SnipeData v) + { + this.vh = v.getVoxelHeight(); + this.getSurface(v); + + if (this.vh > 0) + { + for (final BlockWrapper block : this.surface) + { + this.setBlock(block); + } + } + else if (this.vh < 0) + { + for (final BlockWrapper block : this.surface) + { + this.setBlockDown(block); + } + } + } + + @SuppressWarnings("deprecation") + @Override + protected final void powder(final SnipeData v) + { + this.vh = v.getVoxelHeight(); + + this.surface.clear(); + + int lastY; + int newY; + int lastStr; + double str; + final double brushSizeSquared = Math.pow(v.getBrushSize() + 0.5, 2); + + int id; + + // Are we pulling up ? + if (this.vh > 0) + { + + // Z - Axis + for (int z = -v.getBrushSize(); z <= v.getBrushSize(); z++) + { + + final int zSquared = z * z; + final int actualZ = this.getTargetBlock().getZ() + z; + + // X - Axis + for (int x = -v.getBrushSize(); x <= v.getBrushSize(); x++) + { + + final int xSquared = x * x; + final int actualX = this.getTargetBlock().getX() + x; + + // Down the Y - Axis + for (int y = v.getBrushSize(); y >= -v.getBrushSize(); y--) + { + + final double volume = zSquared + xSquared + (y * y); + + // Is this in the range of the brush? + if (volume <= brushSizeSquared && !this.getWorld().getBlockAt(actualX, this.getTargetBlock().getY() + y, actualZ).isEmpty()) + { + + int actualY = this.getTargetBlock().getY() + y; + + // Starting strength and new Position + str = this.getStr(volume / brushSizeSquared); + lastStr = (int) (this.vh * str); + lastY = actualY + lastStr; + + this.clampY(actualX, lastY, actualZ).setTypeId(this.getWorld().getBlockAt(actualX, actualY, actualZ).getTypeId()); + + if (str == 1) + { + str = 0.8; + } + + while (lastStr > 0) + { + if (actualY < this.getTargetBlock().getY()) + { + str = str * str; + } + lastStr = (int) (this.vh * str); + newY = actualY + lastStr; + id = this.getWorld().getBlockAt(actualX, actualY, actualZ).getTypeId(); + for (int i = newY; i < lastY; i++) + { + this.clampY(actualX, i, actualZ).setTypeId(id); + } + lastY = newY; + actualY--; + } + break; + } + } + } + } + } + else + { + for (int z = -v.getBrushSize(); z <= v.getBrushSize(); z++) + { + final double zSquared = Math.pow(z, 2); + final int actualZ = this.getTargetBlock().getZ() + z; + for (int x = -v.getBrushSize(); x <= v.getBrushSize(); x++) + { + final double xSquared = Math.pow(x, 2); + final int actualX = this.getTargetBlock().getX() + x; + for (int y = -v.getBrushSize(); y <= v.getBrushSize(); y++) + { + double volume = (xSquared + Math.pow(y, 2) + zSquared); + if (volume <= brushSizeSquared && !this.getWorld().getBlockAt(actualX, this.getTargetBlock().getY() + y, actualZ).isEmpty()) + { + final int actualY = this.getTargetBlock().getY() + y; + lastY = actualY + (int) (this.vh * this.getStr(volume / brushSizeSquared)); + this.clampY(actualX, lastY, actualZ).setTypeId(this.getWorld().getBlockAt(actualX, actualY, actualZ).getTypeId()); + y++; + volume = (xSquared + Math.pow(y, 2) + zSquared); + while (volume <= brushSizeSquared) + { + final int blockY = this.getTargetBlock().getY() + y + (int) (this.vh * this.getStr(volume / brushSizeSquared)); + final int blockId = this.getWorld().getBlockAt(actualX, this.getTargetBlock().getY() + y, actualZ).getTypeId(); + for (int i = blockY; i < lastY; i++) + { + this.clampY(actualX, i, actualZ).setTypeId(blockId); + } + lastY = blockY; + y++; + volume = (xSquared + Math.pow(y, 2) + zSquared); + } + break; + } + } + } + } + } + } + + /** + * @author Piotr + */ + private final class BlockWrapper + { + + private final int id; + private final int d; + private final double str; + private final int x; + private final int y; + private final int z; + + /** + * @param block + * @param st + */ + @SuppressWarnings("deprecation") + public BlockWrapper(final AsyncBlock block, final double st) + { + this.id = block.getTypeId(); + this.d = block.getPropertyId(); + this.x = block.getX(); + this.y = block.getY(); + this.z = block.getZ(); + this.str = st; + } + + /** + * @return the d + */ + public int getD() + { + return this.d; + } + + /** + * @return the id + */ + public int getId() + { + return this.id; + } + + /** + * @return the str + */ + public double getStr() + { + return this.str; + } + + /** + * @return the x + */ + public int getX() + { + return this.x; + } + + /** + * @return the y + */ + public int getY() + { + return this.y; + } + + /** + * @return the z + */ + public int getZ() + { + return this.z; + } + } + + @Override + public String getPermissionNode() + { + return "voxelsniper.brush.pull"; + } +} diff --git a/favs/src/main/java/com/thevoxelbox/voxelsniper/brush/PunishBrush.java b/favs/src/main/java/com/thevoxelbox/voxelsniper/brush/PunishBrush.java new file mode 100644 index 000000000..2374f3c87 --- /dev/null +++ b/favs/src/main/java/com/thevoxelbox/voxelsniper/brush/PunishBrush.java @@ -0,0 +1,383 @@ +package com.thevoxelbox.voxelsniper.brush; + +import com.sk89q.worldedit.bukkit.BukkitAdapter; +import com.sk89q.worldedit.world.block.BlockState; +import com.sk89q.worldedit.world.block.BlockTypes; +import com.thevoxelbox.voxelsniper.Message; +import com.thevoxelbox.voxelsniper.SnipeData; +import com.thevoxelbox.voxelsniper.brush.perform.PerformBrush; +import org.bukkit.Bukkit; +import org.bukkit.ChatColor; +import org.bukkit.Location; +import org.bukkit.Material; +import org.bukkit.block.data.BlockData; +import org.bukkit.entity.LivingEntity; +import org.bukkit.entity.Player; +import org.bukkit.potion.PotionEffect; +import org.bukkit.potion.PotionEffectType; +import org.bukkit.util.Vector; + +import java.util.List; +import java.util.Random; + +/** + * http://www.voxelwiki.com/minecraft/Voxelsniper#Punish_Brush + * + * @author Monofraps + * @author Deamon + * @author MikeMatrix + */ +public class PunishBrush extends PerformBrush +{ + private static final int MAXIMAL_RANDOM_TELEPORTATION_RANGE = 400; + private static final int TICKS_PER_SECOND = 20; + private static final int INFINIPUNISH_SIZE = -3; + private static final int DEFAULT_PUNISH_LEVEL = 10; + private static final int DEFAULT_PUSNIH_DURATION = 60; + private Punishment punishment = Punishment.FIRE; + private int punishLevel = DEFAULT_PUNISH_LEVEL; + private int punishDuration = DEFAULT_PUSNIH_DURATION; + private boolean specificPlayer = false; + private String punishPlayerName = ""; + private boolean hypnoAffectLandscape = false; + private boolean hitsSelf = false; + + /** + * Default Constructor. + */ + public PunishBrush() + { + this.setName("Punish"); + } + + @SuppressWarnings("deprecation") + private void applyPunishment(final LivingEntity entity, final SnipeData v) + { + switch (this.punishment) + { + case FIRE: + entity.setFireTicks(PunishBrush.TICKS_PER_SECOND * this.punishDuration); + break; + case LIGHTNING: + entity.getWorld().strikeLightning(entity.getLocation()); + break; + case BLINDNESS: + entity.addPotionEffect(new PotionEffect(PotionEffectType.BLINDNESS, PunishBrush.TICKS_PER_SECOND * this.punishDuration, this.punishLevel), true); + break; + case DRUNK: + entity.addPotionEffect(new PotionEffect(PotionEffectType.CONFUSION, PunishBrush.TICKS_PER_SECOND * this.punishDuration, this.punishLevel), true); + break; + case SLOW: + entity.addPotionEffect(new PotionEffect(PotionEffectType.SLOW, PunishBrush.TICKS_PER_SECOND * this.punishDuration, this.punishLevel), true); + break; + case JUMP: + entity.addPotionEffect(new PotionEffect(PotionEffectType.JUMP, PunishBrush.TICKS_PER_SECOND * this.punishDuration, this.punishLevel), true); + break; + case ABSORPTION: + entity.addPotionEffect(new PotionEffect(PotionEffectType.ABSORPTION, PunishBrush.TICKS_PER_SECOND * this.punishDuration, this.punishLevel), true); + break; + case DAMAGE_RESISTANCE: + entity.addPotionEffect(new PotionEffect(PotionEffectType.DAMAGE_RESISTANCE, PunishBrush.TICKS_PER_SECOND * this.punishDuration, this.punishLevel), true); + break; + case FAST_DIGGING: + entity.addPotionEffect(new PotionEffect(PotionEffectType.FAST_DIGGING, PunishBrush.TICKS_PER_SECOND * this.punishDuration, this.punishLevel), true); + break; + case FIRE_RESISTANCE: + entity.addPotionEffect(new PotionEffect(PotionEffectType.FIRE_RESISTANCE, PunishBrush.TICKS_PER_SECOND * this.punishDuration, this.punishLevel), true); + break; + case HEAL: + entity.addPotionEffect(new PotionEffect(PotionEffectType.HEAL, PunishBrush.TICKS_PER_SECOND * this.punishDuration, this.punishLevel), true); + break; + case HEALTH_BOOST: + entity.addPotionEffect(new PotionEffect(PotionEffectType.HEALTH_BOOST, PunishBrush.TICKS_PER_SECOND * this.punishDuration, this.punishLevel), true); + break; + case HUNGER: + entity.addPotionEffect(new PotionEffect(PotionEffectType.HUNGER, PunishBrush.TICKS_PER_SECOND * this.punishDuration, this.punishLevel), true); + break; + case INCREASE_DAMAGE: + entity.addPotionEffect(new PotionEffect(PotionEffectType.INCREASE_DAMAGE, PunishBrush.TICKS_PER_SECOND * this.punishDuration, this.punishLevel), true); + break; + case INVISIBILITY: + entity.addPotionEffect(new PotionEffect(PotionEffectType.INVISIBILITY, PunishBrush.TICKS_PER_SECOND * this.punishDuration, this.punishLevel), true); + break; + case NIGHT_VISION: + entity.addPotionEffect(new PotionEffect(PotionEffectType.NIGHT_VISION, PunishBrush.TICKS_PER_SECOND * this.punishDuration, this.punishLevel), true); + break; + case POISON: + entity.addPotionEffect(new PotionEffect(PotionEffectType.POISON, PunishBrush.TICKS_PER_SECOND * this.punishDuration, this.punishLevel), true); + break; + case REGENERATION: + entity.addPotionEffect(new PotionEffect(PotionEffectType.REGENERATION, PunishBrush.TICKS_PER_SECOND * this.punishDuration, this.punishLevel), true); + break; + case SATURATION: + entity.addPotionEffect(new PotionEffect(PotionEffectType.SATURATION, PunishBrush.TICKS_PER_SECOND * this.punishDuration, this.punishLevel), true); + break; + case SLOW_DIGGING: + entity.addPotionEffect(new PotionEffect(PotionEffectType.SLOW_DIGGING, PunishBrush.TICKS_PER_SECOND * this.punishDuration, this.punishLevel), true); + break; + case SPEED: + entity.addPotionEffect(new PotionEffect(PotionEffectType.SPEED, PunishBrush.TICKS_PER_SECOND * this.punishDuration, this.punishLevel), true); + break; + case WATER_BREATHING: + entity.addPotionEffect(new PotionEffect(PotionEffectType.WATER_BREATHING, PunishBrush.TICKS_PER_SECOND * this.punishDuration, this.punishLevel), true); + break; + case WEAKNESS: + entity.addPotionEffect(new PotionEffect(PotionEffectType.WEAKNESS, PunishBrush.TICKS_PER_SECOND * this.punishDuration, this.punishLevel), true); + break; + case WITHER: + entity.addPotionEffect(new PotionEffect(PotionEffectType.WITHER, PunishBrush.TICKS_PER_SECOND * this.punishDuration, this.punishLevel), true); + break; + case KILL: + entity.setHealth(0d); + break; + case RANDOMTP: + final Random random = new Random(); + final Location targetLocation = entity.getLocation(); + targetLocation.setX(targetLocation.getX() + (random.nextInt(MAXIMAL_RANDOM_TELEPORTATION_RANGE) - (MAXIMAL_RANDOM_TELEPORTATION_RANGE / 2))); + targetLocation.setZ(targetLocation.getZ() + (random.nextInt(PunishBrush.MAXIMAL_RANDOM_TELEPORTATION_RANGE) - PunishBrush.MAXIMAL_RANDOM_TELEPORTATION_RANGE / 2)); + entity.teleport(targetLocation); + break; + case ALL_POTION: + entity.addPotionEffect(new PotionEffect(PotionEffectType.BLINDNESS, PunishBrush.TICKS_PER_SECOND * this.punishDuration, this.punishLevel), true); + entity.addPotionEffect(new PotionEffect(PotionEffectType.CONFUSION, PunishBrush.TICKS_PER_SECOND * this.punishDuration, this.punishLevel), true); + entity.addPotionEffect(new PotionEffect(PotionEffectType.SLOW, PunishBrush.TICKS_PER_SECOND * this.punishDuration, this.punishLevel), true); + entity.addPotionEffect(new PotionEffect(PotionEffectType.JUMP, PunishBrush.TICKS_PER_SECOND * this.punishDuration, this.punishLevel), true); + break; + case FORCE: + final Vector playerVector = this.getTargetBlock().getLocation().toVector(); + final Vector direction = entity.getLocation().toVector().clone(); + direction.subtract(playerVector); + final double length = direction.length(); + final double stregth = (1 - (length / v.getBrushSize())) * this.punishLevel; + direction.normalize(); + direction.multiply(stregth); + entity.setVelocity(direction); + break; + case HYPNO: + if (entity instanceof Player) + { + final Location location = entity.getLocation(); + Location target = location.clone(); + for (int z = this.punishLevel; z >= -this.punishLevel; z--) + { + for (int x = this.punishLevel; x >= -this.punishLevel; x--) + { + for (int y = this.punishLevel; y >= -this.punishLevel; y--) + { + target.setX(location.getX() + x); + target.setY(location.getY() + y); + target.setZ(location.getZ() + z); + if (this.hypnoAffectLandscape && target.getBlock().isEmpty()) + { + continue; + } + target = location.clone(); + target.add(x, y, z); + Player plr = ((Player) entity); + BlockData bd = BukkitAdapter.adapt(BlockState.get(v.getVoxelId() + (v.getPropertyId() << BlockTypes.BIT_OFFSET))); + plr.sendBlockChange(target, bd); + } + } + } + } + break; + default: + Bukkit.getLogger().warning("Could not determine the punishment of punish brush!"); + break; + } + } + + @Override + protected final void arrow(final SnipeData v) + { + if (!v.owner().getPlayer().hasPermission("voxelsniper.punish")) + { + v.sendMessage("The server says no!"); + return; + } + + this.punishDuration = v.getVoxelHeight(); + this.punishLevel = v.getcCen(); + + if (this.specificPlayer) + { + final Player punishedPlayer = Bukkit.getPlayer(this.punishPlayerName); + if (punishedPlayer == null) + { + v.sendMessage("No player " + this.punishPlayerName + " found."); + return; + } + + this.applyPunishment(punishedPlayer, v); + return; + } + + final int brushSizeSquare = v.getBrushSize() * v.getBrushSize(); + final Location targetLocation = new Location(v.getWorld(), this.getTargetBlock().getX(), this.getTargetBlock().getY(), this.getTargetBlock().getZ()); + + final List entities = v.getWorld().getLivingEntities(); + int numPunishApps = 0; + for (final LivingEntity entity : entities) + { + if (v.owner().getPlayer() != entity || hitsSelf) + { + if (v.getBrushSize() >= 0) + { + try + { + if (entity.getLocation().distanceSquared(targetLocation) <= brushSizeSquare) + { + numPunishApps++; + this.applyPunishment(entity, v); + } + } + catch (final Exception exception) + { + exception.printStackTrace(); + v.sendMessage("An error occured."); + return; + } + } + else if (v.getBrushSize() == PunishBrush.INFINIPUNISH_SIZE) + { + numPunishApps++; + this.applyPunishment(entity, v); + } + } + } + v.sendMessage(ChatColor.DARK_RED + "Punishment applied to " + numPunishApps + " living entities."); + } + + @Override + protected final void powder(final SnipeData v) + { + if (!v.owner().getPlayer().hasPermission("voxelsniper.punish")) + { + v.sendMessage("The server says no!"); + return; + } + + final int brushSizeSquare = v.getBrushSize() * v.getBrushSize(); + final Location targetLocation = new Location(v.getWorld(), this.getTargetBlock().getX(), this.getTargetBlock().getY(), this.getTargetBlock().getZ()); + + final List entities = v.getWorld().getLivingEntities(); + + for (final LivingEntity entity : entities) + { + if (entity.getLocation().distanceSquared(targetLocation) < brushSizeSquare) + { + entity.setFireTicks(0); + entity.removePotionEffect(PotionEffectType.BLINDNESS); + entity.removePotionEffect(PotionEffectType.CONFUSION); + entity.removePotionEffect(PotionEffectType.SLOW); + entity.removePotionEffect(PotionEffectType.JUMP); + } + } + + } + + @Override + public final void info(final Message vm) + { + vm.brushName(this.getName()); + vm.custom(ChatColor.GREEN + "Punishment: " + this.punishment.toString()); + vm.size(); + vm.center(); + } + + @Override + public final void parameters(final String[] par, final SnipeData v) + { + for (int i = 1; i < par.length; i++) + { + final String parameter = par[i].toLowerCase(); + + if (parameter.equalsIgnoreCase("info")) + { + v.sendMessage(ChatColor.GOLD + "Punish Brush Options:"); + v.sendMessage(ChatColor.AQUA + "Punishments can be set via /b p [punishment]"); + v.sendMessage(ChatColor.AQUA + "Punishment level can be set with /vc [level]"); + v.sendMessage(ChatColor.AQUA + "Punishment duration in seconds can be set with /vh [duration]"); + v.sendMessage(ChatColor.AQUA + "Parameter -toggleHypnoLandscape will make Hypno punishment only affect landscape."); + v.sendMessage(ChatColor.AQUA + "Parameter -toggleSM [playername] will make punishbrush only affect that player."); + v.sendMessage(ChatColor.AQUA + "Parameter -toggleSelf will toggle whether you get hit as well."); + v.sendMessage(ChatColor.AQUA + "Available Punishment Options:"); + final StringBuilder punishmentOptions = new StringBuilder(); + for (final Punishment punishment : Punishment.values()) + { + if (punishmentOptions.length() != 0) + { + punishmentOptions.append(" | "); + } + punishmentOptions.append(punishment.name()); + } + v.sendMessage(ChatColor.GOLD + punishmentOptions.toString()); + return; + } + else if (parameter.equalsIgnoreCase("-toggleSM")) + { + this.specificPlayer = !this.specificPlayer; + if (this.specificPlayer) + { + try + { + this.punishPlayerName = par[++i]; + } + catch (final IndexOutOfBoundsException exception) + { + v.sendMessage(ChatColor.AQUA + "You have to specify a player name after -toggleSM if you want to turn the specific player feature on."); + } + } + } + else if (parameter.equalsIgnoreCase("-toggleSelf")) + { + this.hitsSelf = !this.hitsSelf; + if (hitsSelf) + { + v.sendMessage(ChatColor.AQUA + "Your punishments will now affect you too!"); + } + else + { + v.sendMessage(ChatColor.AQUA + "Your punishments will no longer affect you!"); + } + } + else if (parameter.equalsIgnoreCase("-toggleHypnoLandscape")) + { + this.hypnoAffectLandscape = !this.hypnoAffectLandscape; + } + else + { + try + { + this.punishment = Punishment.valueOf(parameter.toUpperCase()); + v.sendMessage(ChatColor.AQUA + this.punishment.name().toLowerCase() + " punishment selected."); + } + catch (final IllegalArgumentException exception) + { + v.sendMessage(ChatColor.AQUA + "No such Punishment."); + } + } + } + + } + + /** + * @author Monofraps + */ + private enum Punishment + { + // Monofraps + FIRE, LIGHTNING, BLINDNESS, DRUNK, KILL, RANDOMTP, ALL_POTION, + // Deamon + SLOW, JUMP, ABSORPTION, DAMAGE_RESISTANCE, FAST_DIGGING, FIRE_RESISTANCE, HEAL, HEALTH_BOOST, HUNGER, INCREASE_DAMAGE, INVISIBILITY, NIGHT_VISION, POISON, REGENERATION, + SATURATION, SLOW_DIGGING, SPEED, WATER_BREATHING, WEAKNESS, WITHER, + // MikeMatrix + FORCE, HYPNO + } + + @Override + public String getPermissionNode() + { + return "voxelsniper.brush.punish"; + } +} diff --git a/favs/src/main/java/com/thevoxelbox/voxelsniper/brush/RandomErodeBrush.java b/favs/src/main/java/com/thevoxelbox/voxelsniper/brush/RandomErodeBrush.java new file mode 100644 index 000000000..7f5778b01 --- /dev/null +++ b/favs/src/main/java/com/thevoxelbox/voxelsniper/brush/RandomErodeBrush.java @@ -0,0 +1,470 @@ +package com.thevoxelbox.voxelsniper.brush; + +import com.boydti.fawe.bukkit.wrapper.AsyncBlock; +import com.thevoxelbox.voxelsniper.Message; +import com.thevoxelbox.voxelsniper.SnipeData; +import com.thevoxelbox.voxelsniper.Undo; +import org.bukkit.block.Block; + +import java.util.Random; + +/** + * http://www.voxelwiki.com/minecraft/Voxelsniper#The_Random-Erode_Brush + * + * @author Piotr + * @author Giltwist (Randomized blockPositionY) + */ +public class RandomErodeBrush extends Brush +{ + private final double trueCircle = 0.5; + private BlockWrapper[][][] snap; + private BlockWrapper[][][] firstSnap; + private int bsize; + private int erodeFace; + private int fillFace; + private int brushSize; + private int erodeRecursion = 1; + private int fillRecursion = 1; + private Random generator = new Random(); + + /** + * + */ + public RandomErodeBrush() + { + this.setName("RandomErode"); + } + + private boolean erode(final int x, final int y, final int z) + { + if (this.snap[x][y][z].isSolid()) + { + int d = 0; + if (!this.snap[x + 1][y][z].isSolid()) + { + d++; + } + if (!this.snap[x - 1][y][z].isSolid()) + { + d++; + } + if (!this.snap[x][y + 1][z].isSolid()) + { + d++; + } + if (!this.snap[x][y - 1][z].isSolid()) + { + d++; + } + if (!this.snap[x][y][z + 1].isSolid()) + { + d++; + } + if (!this.snap[x][y][z - 1].isSolid()) + { + d++; + } + return (d >= this.erodeFace); + } + else + { + return false; + } + } + + @SuppressWarnings("deprecation") + private boolean fill(final int x, final int y, final int z) + { + if (this.snap[x][y][z].isSolid()) + { + return false; + } + else + { + int d = 0; + if (this.snap[x + 1][y][z].isSolid()) + { + this.snap[x][y][z].setId(this.snap[x + 1][y][z].getNativeBlock().getTypeId()); + d++; + } + if (this.snap[x - 1][y][z].isSolid()) + { + this.snap[x][y][z].setId(this.snap[x - 1][y][z].getNativeBlock().getTypeId()); + d++; + } + if (this.snap[x][y + 1][z].isSolid()) + { + this.snap[x][y][z].setId(this.snap[x][y + 1][z].getNativeBlock().getTypeId()); + d++; + } + if (this.snap[x][y - 1][z].isSolid()) + { + this.snap[x][y][z].setId(this.snap[x][y - 1][z].getNativeBlock().getTypeId()); + d++; + } + if (this.snap[x][y][z + 1].isSolid()) + { + this.snap[x][y][z].setId(this.snap[x][y][z + 1].getNativeBlock().getTypeId()); + d++; + } + if (this.snap[x][y][z - 1].isSolid()) + { + this.snap[x][y][z].setId(this.snap[x][y][z - 1].getNativeBlock().getTypeId()); + d++; + } + return (d >= this.fillFace); + } + } + + private void getMatrix() + { + this.brushSize = ((this.bsize + 1) * 2) + 1; + + if (this.snap.length == 0) + { + this.snap = new BlockWrapper[this.brushSize][this.brushSize][this.brushSize]; + + int sx = this.getTargetBlock().getX() - (this.bsize + 1); + int sy = this.getTargetBlock().getY() - (this.bsize + 1); + int sz = this.getTargetBlock().getZ() - (this.bsize + 1); + + for (int x = 0; x < this.snap.length; x++) + { + sz = this.getTargetBlock().getZ() - (this.bsize + 1); + for (int z = 0; z < this.snap.length; z++) + { + sy = this.getTargetBlock().getY() - (this.bsize + 1); + for (int y = 0; y < this.snap.length; y++) + { + this.snap[x][y][z] = new BlockWrapper(this.clampY(sx, sy, sz)); + sy++; + } + sz++; + } + sx++; + } + this.firstSnap = this.snap.clone(); + } + else + { + this.snap = new BlockWrapper[this.brushSize][this.brushSize][this.brushSize]; + + int sx = this.getTargetBlock().getX() - (this.bsize + 1); + int sy = this.getTargetBlock().getY() - (this.bsize + 1); + int sz = this.getTargetBlock().getZ() - (this.bsize + 1); + + for (int x = 0; x < this.snap.length; x++) + { + sz = this.getTargetBlock().getZ() - (this.bsize + 1); + for (int z = 0; z < this.snap.length; z++) + { + sy = this.getTargetBlock().getY() - (this.bsize + 1); + for (int y = 0; y < this.snap.length; y++) + { + this.snap[x][y][z] = new BlockWrapper(this.clampY(sx, sy, sz)); + sy++; + } + sz++; + } + sx++; + } + } + } + + @SuppressWarnings("deprecation") + private void rerosion(final SnipeData v) + { + final Undo undo = new Undo(); + + if (this.erodeFace >= 0 && this.erodeFace <= 6) + { + for (int currentErodeRecursion = 0; currentErodeRecursion < this.erodeRecursion; currentErodeRecursion++) + { + this.getMatrix(); + + final double brushSizeSquared = Math.pow(this.bsize + this.trueCircle, 2); + for (int z = 1; z < this.snap.length - 1; z++) + { + + final double zSquared = Math.pow(z - (this.bsize + 1), 2); + for (int x = 1; x < this.snap.length - 1; x++) + { + + final double xSquared = Math.pow(x - (this.bsize + 1), 2); + for (int y = 1; y < this.snap.length - 1; y++) + { + + if (((xSquared + Math.pow(y - (this.bsize + 1), 2) + zSquared) <= brushSizeSquared)) + { + if (this.erode(x, y, z)) + { + this.snap[x][y][z].getNativeBlock().setTypeId(0); + } + } + } + } + } + } + } + if (this.fillFace >= 0 && this.fillFace <= 6) + { + final double brushSizeSquared = Math.pow(this.bsize + 0.5, 2); + + for (int currentFillRecursion = 0; currentFillRecursion < this.fillRecursion; currentFillRecursion++) + { + this.getMatrix(); + + for (int z = 1; z < this.snap.length - 1; z++) + { + + final double zSquared = Math.pow(z - (this.bsize + 1), 2); + for (int x = 1; x < this.snap.length - 1; x++) + { + + final double xSquared = Math.pow(x - (this.bsize + 1), 2); + for (int y = 1; y < this.snap.length - 1; y++) + { + + if (((xSquared + Math.pow(y - (this.bsize + 1), 2) + zSquared) <= brushSizeSquared)) + { + if (this.fill(x, y, z)) + { + this.snap[x][y][z].getNativeBlock().setTypeId(this.snap[x][y][z].getId()); + } + } + } + } + } + } + } + + for (BlockWrapper[][] firstSnapSlice : this.firstSnap) + { + for (BlockWrapper[] firstSnapString : firstSnapSlice) + { + for (final BlockWrapper block : firstSnapString) + { + if (block.getI() != block.getNativeBlock().getTypeId()) + { + undo.put(block.getNativeBlock()); + } + } + } + } + + v.owner().storeUndo(undo); + } + + @SuppressWarnings("deprecation") + private void rfilling(final SnipeData v) + { + final Undo undo = new Undo(); + + if (this.fillFace >= 0 && this.fillFace <= 6) + { + final double bSquared = Math.pow(this.bsize + 0.5, 2); + + for (int currentFillRecursion = 0; currentFillRecursion < this.fillRecursion; currentFillRecursion++) + { + this.getMatrix(); + + for (int z = 1; z < this.snap.length - 1; z++) + { + final double zSquared = Math.pow(z - (this.bsize + 1), 2); + for (int x = 1; x < this.snap.length - 1; x++) + { + final double xSquared = Math.pow(x - (this.bsize + 1), 2); + for (int y = 1; y < this.snap.length - 1; y++) + { + if (((xSquared + Math.pow(y - (this.bsize + 1), 2) + zSquared) <= bSquared)) + { + if (this.fill(x, y, z)) + { + this.snap[x][y][z].getNativeBlock().setTypeId(this.snap[x][y][z].getId()); + } + } + } + } + } + } + } + if (this.erodeFace >= 0 && this.erodeFace <= 6) + { + final double bSquared = Math.pow(this.bsize + this.trueCircle, 2); + + for (int currentErodeRecursion = 0; currentErodeRecursion < this.erodeRecursion; currentErodeRecursion++) + { + this.getMatrix(); + + for (int z = 1; z < this.snap.length - 1; z++) + { + + final double zSquared = Math.pow(z - (this.bsize + 1), 2); + for (int x = 1; x < this.snap.length - 1; x++) + { + + final double xSquared = Math.pow(x - (this.bsize + 1), 2); + for (int y = 1; y < this.snap.length - 1; y++) + { + + if (((xSquared + Math.pow(y - (this.bsize + 1), 2) + zSquared) <= bSquared)) + { + if (this.erode(x, y, z)) + { + this.snap[x][y][z].getNativeBlock().setTypeId(0); + } + } + } + } + } + } + } + + for (BlockWrapper[][] firstSnapSlice : this.firstSnap) + { + for (BlockWrapper[] firstSnapString : firstSnapSlice) + { + for (final BlockWrapper block : firstSnapString) + { + if (block.getI() != block.getNativeBlock().getTypeId()) + { + undo.put(block.getNativeBlock()); + } + } + } + } + + v.owner().storeUndo(undo); + } + + @Override + protected final void arrow(final SnipeData v) + { + this.bsize = v.getBrushSize(); + + this.snap = new BlockWrapper[0][0][0]; + + this.erodeFace = this.generator.nextInt(5) + 1; + this.fillFace = this.generator.nextInt(3) + 3; + this.erodeRecursion = this.generator.nextInt(3); + this.fillRecursion = this.generator.nextInt(3); + + if (this.fillRecursion == 0 && this.erodeRecursion == 0) + { // if they are both zero, it will lead to a null pointer exception. Still want to give them a + // chance to be zero though, for more interestingness -Gav + this.erodeRecursion = this.generator.nextInt(2) + 1; + this.fillRecursion = this.generator.nextInt(2) + 1; + } + + this.rerosion(v); + } + + @Override + protected final void powder(final SnipeData v) + { + this.bsize = v.getBrushSize(); + + this.snap = new BlockWrapper[0][0][0]; + + this.erodeFace = this.generator.nextInt(3) + 3; + this.fillFace = this.generator.nextInt(5) + 1; + this.erodeRecursion = this.generator.nextInt(3); + this.fillRecursion = this.generator.nextInt(3); + if (this.fillRecursion == 0 && this.erodeRecursion == 0) + { // if they are both zero, it will lead to a null pointer exception. Still want to give them a + // chance to be zero though, for more interestingness -Gav + this.erodeRecursion = this.generator.nextInt(2) + 1; + this.fillRecursion = this.generator.nextInt(2) + 1; + } + + this.rfilling(v); + } + + @Override + public final void info(final Message vm) + { + vm.brushName(this.getName()); + vm.size(); + } + + /** + * @author unknown + */ + private class BlockWrapper + { + private boolean solid; + private AsyncBlock nativeBlock; + private int id; + private int i; + + /** + * @param bl + */ + @SuppressWarnings("deprecation") + public BlockWrapper(final AsyncBlock bl) + { + this.setNativeBlock(bl); + this.setI(bl.getTypeId()); + switch (bl.getType()) + { + case AIR: + this.setSolid(false); + break; + case WATER: + this.setSolid(false); + break; + case LAVA: + this.setSolid(false); + break; + default: + this.setSolid(true); + } + } + + public boolean isSolid() + { + return solid; + } + + public void setSolid(boolean solid) + { + this.solid = solid; + } + + public AsyncBlock getNativeBlock() + { + return nativeBlock; + } + + public void setNativeBlock(AsyncBlock nativeBlock) + { + this.nativeBlock = nativeBlock; + } + + public int getId() + { + return id; + } + + public void setId(int id) + { + this.id = id; + } + + public int getI() + { + return i; + } + + public void setI(int i) + { + this.i = i; + } + } + + @Override + public String getPermissionNode() + { + return "voxelsniper.brush.randomerode"; + } +} diff --git a/favs/src/main/java/com/thevoxelbox/voxelsniper/brush/RegenerateChunkBrush.java b/favs/src/main/java/com/thevoxelbox/voxelsniper/brush/RegenerateChunkBrush.java new file mode 100644 index 000000000..24485ea10 --- /dev/null +++ b/favs/src/main/java/com/thevoxelbox/voxelsniper/brush/RegenerateChunkBrush.java @@ -0,0 +1,70 @@ +package com.thevoxelbox.voxelsniper.brush; + +import com.thevoxelbox.voxelsniper.Message; +import com.thevoxelbox.voxelsniper.SnipeData; +import com.thevoxelbox.voxelsniper.Undo; +import org.bukkit.Chunk; + +/** + * Regenerates the target chunk. + * + * @author Mick + */ +public class RegenerateChunkBrush extends Brush +{ + /** + * + */ + public RegenerateChunkBrush() + { + this.setName("Chunk Generator 40k"); + } + + private void generateChunk(final SnipeData v) + { + final Chunk chunk = this.getTargetBlock().getChunk(); + final Undo undo = new Undo(); + + for (int z = CHUNK_SIZE; z >= 0; z--) + { + for (int x = CHUNK_SIZE; x >= 0; x--) + { + for (int y = this.getWorld().getMaxHeight(); y >= 0; y--) + { + undo.put(chunk.getBlock(x, y, z)); + } + } + } + v.owner().storeUndo(undo); + + v.sendMessage("Generate that chunk! " + chunk.getX() + " " + chunk.getZ()); + this.getWorld().regenerateChunk(chunk.getX(), chunk.getZ()); + this.getWorld().refreshChunk(chunk.getX(), chunk.getZ()); + } + + @Override + protected final void arrow(final SnipeData v) + { + this.generateChunk(v); + } + + @Override + protected final void powder(final SnipeData v) + { + this.generateChunk(v); + } + + @Override + public final void info(final Message vm) + { + vm.brushName(this.getName()); + vm.brushMessage("Tread lightly."); + vm.brushMessage("This brush will melt your spleen and sell your kidneys."); + } + + @Override + public String getPermissionNode() + { + return "voxelsniper.brush.regeneratechunk"; + } +} diff --git a/favs/src/main/java/com/thevoxelbox/voxelsniper/brush/RingBrush.java b/favs/src/main/java/com/thevoxelbox/voxelsniper/brush/RingBrush.java new file mode 100644 index 000000000..f27bcc97b --- /dev/null +++ b/favs/src/main/java/com/thevoxelbox/voxelsniper/brush/RingBrush.java @@ -0,0 +1,120 @@ +package com.thevoxelbox.voxelsniper.brush; + +import com.boydti.fawe.bukkit.wrapper.AsyncBlock; +import com.thevoxelbox.voxelsniper.Message; +import com.thevoxelbox.voxelsniper.SnipeData; +import com.thevoxelbox.voxelsniper.brush.perform.PerformBrush; +import org.bukkit.ChatColor; +import org.bukkit.block.Block; + +/** + * http://www.voxelwiki.com/minecraft/Voxelsniper#Ring_Brush + * + * @author Voxel + */ +public class RingBrush extends PerformBrush +{ + private double trueCircle = 0; + private double innerSize = 0; + + /** + * + */ + public RingBrush() + { + this.setName("Ring"); + } + + private void ring(final SnipeData v, AsyncBlock targetBlock) + { + final int brushSize = v.getBrushSize(); + final double outerSquared = Math.pow(brushSize + this.trueCircle, 2); + final double innerSquared = Math.pow(this.innerSize, 2); + + for (int x = brushSize; x >= 0; x--) + { + final double xSquared = Math.pow(x, 2); + for (int z = brushSize; z >= 0; z--) + { + final double ySquared = Math.pow(z, 2); + if ((xSquared + ySquared) <= outerSquared && (xSquared + ySquared) >= innerSquared) + { + current.perform(targetBlock.getRelative(x, 0, z)); + current.perform(targetBlock.getRelative(x, 0, -z)); + current.perform(targetBlock.getRelative(-x, 0, z)); + current.perform(targetBlock.getRelative(-x, 0, -z)); + } + } + } + + v.owner().storeUndo(this.current.getUndo()); + } + + @Override + protected final void arrow(final SnipeData v) + { + this.ring(v, this.getTargetBlock()); + } + + @Override + protected final void powder(final SnipeData v) + { + this.ring(v, this.getLastBlock()); + } + + @Override + public final void info(final Message vm) + { + vm.brushName(this.getName()); + vm.size(); + vm.custom(ChatColor.AQUA + "The inner radius is " + ChatColor.RED + this.innerSize); + } + + @Override + public final void parameters(final String[] par, final SnipeData v) + { + for (int i = 1; i < par.length; i++) + { + if (par[i].equalsIgnoreCase("info")) + { + v.sendMessage(ChatColor.GOLD + "Ring Brush Parameters:"); + v.sendMessage(ChatColor.AQUA + "/b ri true -- will use a true circle algorithm instead of the skinnier version with classic sniper nubs. /b ri false will switch back. (false is default)"); + v.sendMessage(ChatColor.AQUA + "/b ri ir2.5 -- will set the inner radius to 2.5 units"); + return; + } + else if (par[i].startsWith("true")) + { + this.trueCircle = 0.5; + v.sendMessage(ChatColor.AQUA + "True circle mode ON."); + } + else if (par[i].startsWith("false")) + { + this.trueCircle = 0; + v.sendMessage(ChatColor.AQUA + "True circle mode OFF."); + } + else if (par[i].startsWith("ir")) + { + try + { + final double d = Double.parseDouble(par[i].replace("ir", "")); + this.innerSize = d; + v.sendMessage(ChatColor.AQUA + "The inner radius has been set to " + ChatColor.RED + this.innerSize); + } + catch (final Exception exception) + { + v.sendMessage(ChatColor.RED + "The parameters included are invalid."); + } + } + else + { + v.sendMessage(ChatColor.RED + "Invalid brush parameters! use the info parameter to display parameter info."); + } + } + } + + @Override + public String getPermissionNode() + { + return "voxelsniper.brush.ring"; + } +} diff --git a/favs/src/main/java/com/thevoxelbox/voxelsniper/brush/Rot2DBrush.java b/favs/src/main/java/com/thevoxelbox/voxelsniper/brush/Rot2DBrush.java new file mode 100644 index 000000000..f79a08836 --- /dev/null +++ b/favs/src/main/java/com/thevoxelbox/voxelsniper/brush/Rot2DBrush.java @@ -0,0 +1,214 @@ +package com.thevoxelbox.voxelsniper.brush; + +import com.boydti.fawe.bukkit.wrapper.AsyncBlock; +import com.thevoxelbox.voxelsniper.Message; +import com.thevoxelbox.voxelsniper.SnipeData; +import com.thevoxelbox.voxelsniper.util.BlockWrapper; + +import org.bukkit.ChatColor; + +/** + * @author Piotr + */ +public class Rot2DBrush extends Brush +{ + private int mode = 0; + private int bSize; + private int brushSize; + private BlockWrapper[][][] snap; + private double se; + + /** + * + */ + public Rot2DBrush() + { + this.setName("2D Rotation"); + } + + @SuppressWarnings("deprecation") + private void getMatrix() + { + this.brushSize = (this.bSize * 2) + 1; + + this.snap = new BlockWrapper[this.brushSize][this.brushSize][this.brushSize]; + + final double brushSizeSquared = Math.pow(this.bSize + 0.5, 2); + int sx = this.getTargetBlock().getX() - this.bSize; + int sy = this.getTargetBlock().getY() - this.bSize; + int sz = this.getTargetBlock().getZ() - this.bSize; + + for (int x = 0; x < this.snap.length; x++) + { + sz = this.getTargetBlock().getZ() - this.bSize; + final double xSquared = Math.pow(x - this.bSize, 2); + for (int y = 0; y < this.snap.length; y++) + { + sy = this.getTargetBlock().getY() - this.bSize; + if (xSquared + Math.pow(y - this.bSize, 2) <= brushSizeSquared) + { + for (int z = 0; z < this.snap.length; z++) + { + final AsyncBlock block = this.clampY(sx, sy, sz); // why is this not sx + x, sy + y sz + z? + this.snap[x][z][y] = new BlockWrapper(block); + block.setTypeId(0); + sy++; + } + } + sz++; + } + sx++; + } + } + + private void rotate(final SnipeData v) + { + final double brushSiyeSquared = Math.pow(this.bSize + 0.5, 2); + final double cos = Math.cos(this.se); + final double sin = Math.sin(this.se); + final boolean[][] doNotFill = new boolean[this.snap.length][this.snap.length]; + // I put y in the inside loop, since it doesn't have any power functions, should be much faster. + // Also, new array keeps track of which x and z coords are being assigned in the rotated space so that we can + // do a targeted filling of only those columns later that were left out. + + for (int x = 0; x < this.snap.length; x++) + { + final int xx = x - this.bSize; + final double xSquared = Math.pow(xx, 2); + + for (int y = 0; y < this.snap.length; y++) + { + final int zz = y - this.bSize; + + if (xSquared + Math.pow(zz, 2) <= brushSiyeSquared) + { + final double newX = (xx * cos) - (zz * sin); + final double newZ = (xx * sin) + (zz * cos); + + doNotFill[(int) newX + this.bSize][(int) newZ + this.bSize] = true; + + for (int currentY = 0; currentY < this.snap.length; currentY++) + { + final int yy = currentY - this.bSize; + final BlockWrapper block = this.snap[x][currentY][y]; + + if (block.getId() == 0) + { + continue; + } + this.setBlockIdAndDataAt(this.getTargetBlock().getX() + (int) newX, this.getTargetBlock().getY() + yy, this.getTargetBlock().getZ() + (int) newZ, block.getId(), block.getPropertyId()); + } + } + } + } + for (int x = 0; x < this.snap.length; x++) + { + final double xSquared = Math.pow(x - this.bSize, 2); + final int fx = x + this.getTargetBlock().getX() - this.bSize; + + for (int z = 0; z < this.snap.length; z++) + { + if (xSquared + Math.pow(z - this.bSize, 2) <= brushSiyeSquared) + { + final int fz = z + this.getTargetBlock().getZ() - this.bSize; + + if (!doNotFill[x][z]) + { + // smart fill stuff + + for (int y = 0; y < this.snap.length; y++) + { + final int fy = y + this.getTargetBlock().getY() - this.bSize; + + final int a = this.getBlockIdAt(fx + 1, fy, fz); + final int aData = this.getBlockDataAt(fx + 1, fy, fz); + final int d = this.getBlockIdAt(fx - 1, fy, fz); + final int dData = this.getBlockDataAt(fx - 1, fy, fz); + final int c = this.getBlockIdAt(fx, fy, fz + 1); + final int b = this.getBlockIdAt(fx, fy, fz - 1); + final int bData = this.getBlockDataAt(fx, fy, fz - 1); + + int winner; + int winnerData; + + if (a == b || a == c || a == d) + { // I figure that since we are already narrowing it down to ONLY the holes left behind, it + // should + // be fine to do all 5 checks needed to be legit about it. + winner = a; + winnerData = aData; + } + else if (b == d || c == d) + { + winner = d; + winnerData = dData; + } + else + { + winner = b; // blockPositionY making this default, it will also automatically cover situations where B = C; + winnerData = bData; + } + + this.setBlockIdAndDataAt(fx, fy, fz, winner, winnerData); + } + } + } + } + } + } + + @Override + protected final void arrow(final SnipeData v) + { + this.bSize = v.getBrushSize(); + + switch (this.mode) + { + case 0: + this.getMatrix(); + this.rotate(v); + break; + + default: + v.sendMessage(ChatColor.RED + "Something went wrong."); + break; + } + } + + @Override + protected final void powder(final SnipeData v) + { + this.bSize = v.getBrushSize(); + + switch (this.mode) + { + case 0: + this.getMatrix(); + this.rotate(v); + break; + + default: + v.sendMessage(ChatColor.RED + "Something went wrong."); + break; + } + } + + @Override + public final void info(final Message vm) + { + vm.brushName(this.getName()); + } + + @Override + public final void parameters(final String[] par, final SnipeData v) + { + this.se = Math.toRadians(Double.parseDouble(par[1])); + v.sendMessage(ChatColor.GREEN + "Angle set to " + this.se); + } + + @Override + public String getPermissionNode() + { + return "voxelsniper.brush.rot2d"; + } +} diff --git a/favs/src/main/java/com/thevoxelbox/voxelsniper/brush/Rot2DvertBrush.java b/favs/src/main/java/com/thevoxelbox/voxelsniper/brush/Rot2DvertBrush.java new file mode 100644 index 000000000..e1ff8e3f6 --- /dev/null +++ b/favs/src/main/java/com/thevoxelbox/voxelsniper/brush/Rot2DvertBrush.java @@ -0,0 +1,223 @@ +package com.thevoxelbox.voxelsniper.brush; + +import com.boydti.fawe.bukkit.wrapper.AsyncBlock; +import com.thevoxelbox.voxelsniper.Message; +import com.thevoxelbox.voxelsniper.SnipeData; +import com.thevoxelbox.voxelsniper.util.BlockWrapper; + +import org.bukkit.Bukkit; +import org.bukkit.ChatColor; + +/** + * @author Gavjenks, hack job from the other 2d rotation brush blockPositionY piotr + */ +// The X Y and Z variable names in this file do NOT MAKE ANY SENSE. Do not attempt to actually figure out what on earth is going on here. Just go to the +// original 2d horizontal brush if you wish to make anything similar to this, and start there. I didn't bother renaming everything. +public class Rot2DvertBrush extends Brush +{ + private int mode = 0; + private int bSize; + private int brushSize; + private BlockWrapper[][][] snap; + private double se; + + /** + * + */ + public Rot2DvertBrush() + { + this.setName("2D Rotation"); + } + + @SuppressWarnings("deprecation") + private void getMatrix() + { + this.brushSize = (this.bSize * 2) + 1; + + this.snap = new BlockWrapper[this.brushSize][this.brushSize][this.brushSize]; + + int sx = this.getTargetBlock().getX() - this.bSize; + int sy = this.getTargetBlock().getY() - this.bSize; + int sz = this.getTargetBlock().getZ() - this.bSize; + + for (int x = 0; x < this.snap.length; x++) + { + sz = this.getTargetBlock().getZ() - this.bSize; + + for (int z = 0; z < this.snap.length; z++) + { + sy = this.getTargetBlock().getY() - this.bSize; + + for (int y = 0; y < this.snap.length; y++) + { + final AsyncBlock block = this.clampY(sx, sy, sz); // why is this not sx + x, sy + y sz + z? + this.snap[x][y][z] = new BlockWrapper(block); + block.setTypeId(0); + sy++; + } + + sz++; + } + sx++; + } + } + + private void rotate(final SnipeData v) + { + final double brushSizeSquared = Math.pow(this.bSize + 0.5, 2); + final double cos = Math.cos(this.se); + final double sin = Math.sin(this.se); + final boolean[][] doNotFill = new boolean[this.snap.length][this.snap.length]; + // I put y in the inside loop, since it doesn't have any power functions, should be much faster. + // Also, new array keeps track of which x and z coords are being assigned in the rotated space so that we can + // do a targeted filling of only those columns later that were left out. + + for (int x = 0; x < this.snap.length; x++) + { + final int xx = x - this.bSize; + final double xSquared = Math.pow(xx, 2); + + for (int z = 0; z < this.snap.length; z++) + { + final int zz = z - this.bSize; + + if (xSquared + Math.pow(zz, 2) <= brushSizeSquared) + { + final double newX = (xx * cos) - (zz * sin); + final double newZ = (xx * sin) + (zz * cos); + + doNotFill[(int) newX + this.bSize][(int) newZ + this.bSize] = true; + + for (int y = 0; y < this.snap.length; y++) + { + final int yy = y - this.bSize; + + final BlockWrapper block = this.snap[y][x][z]; + if (block.getId() == 0) + { + continue; + } + this.setBlockIdAndDataAt(this.getTargetBlock().getX() + yy, this.getTargetBlock().getY() + (int) newX, this.getTargetBlock().getZ() + (int) newZ, block.getId(), block.getPropertyId()); + } + } + } + } + + for (int x = 0; x < this.snap.length; x++) + { + final double xSquared = Math.pow(x - this.bSize, 2); + final int fx = x + this.getTargetBlock().getX() - this.bSize; + + for (int z = 0; z < this.snap.length; z++) + { + if (xSquared + Math.pow(z - this.bSize, 2) <= brushSizeSquared) + { + final int fz = z + this.getTargetBlock().getZ() - this.bSize; + + if (!doNotFill[x][z]) + { + // smart fill stuff + for (int y = 0; y < this.snap.length; y++) + { + final int fy = y + this.getTargetBlock().getY() - this.bSize; + + final int a = this.getBlockIdAt(fy, fx + 1, fz); + final int aData = this.getBlockDataAt(fy, fx + 1, fz); + final int d = this.getBlockIdAt(fy, fx - 1, fz); + final int dData = this.getBlockDataAt(fy, fx - 1, fz); + final int c = this.getBlockIdAt(fy, fx, fz + 1); + final int b = this.getBlockIdAt(fy, fx, fz - 1); + final int bData = this.getBlockDataAt(fy, fx, fz - 1); + + int winner; + int winnerData; + + if (a == b || a == c || a == d) + { // I figure that since we are already narrowing it down to ONLY the holes left behind, it + // should + // be fine to do all 5 checks needed to be legit about it. + winner = a; + winnerData = aData; + } + else if (b == d || c == d) + { + winner = d; + winnerData = dData; + } + else + { + winner = b; // blockPositionY making this default, it will also automatically cover situations where B = C; + winnerData = bData; + } + + this.setBlockIdAndDataAt(fy, fx, fz, winner, winnerData); + } + } + } + } + } + } + + @Override + protected final void arrow(final SnipeData v) + { + this.bSize = v.getBrushSize(); + + switch (this.mode) + { + case 0: + this.getMatrix(); + this.rotate(v); + break; + + default: + v.owner().getPlayer().sendMessage(ChatColor.RED + "Something went wrong."); + break; + } + } + + @Override + protected final void powder(final SnipeData v) + { + this.bSize = v.getBrushSize(); + + switch (this.mode) + { + case 0: + this.getMatrix(); + this.rotate(v); + break; + + default: + v.owner().getPlayer().sendMessage(ChatColor.RED + "Something went wrong."); + break; + } + } + + @Override + public final void info(final Message vm) + { + vm.brushName(this.getName()); + } + + @Override + public final void parameters(final String[] par, final SnipeData v) + { + try + { + this.se = Math.toRadians(Double.parseDouble(par[1])); + v.sendMessage(ChatColor.GREEN + "Angle set to " + this.se); + } + catch (Exception _ex) + { + v.sendMessage("Exception while parsing parameter: " + par[1]); + Bukkit.getLogger().severe(_ex.getMessage()); + } + } + + @Override + public String getPermissionNode() + { + return "voxelsniper.brush.rot2dvert"; + } +} diff --git a/favs/src/main/java/com/thevoxelbox/voxelsniper/brush/Rot3DBrush.java b/favs/src/main/java/com/thevoxelbox/voxelsniper/brush/Rot3DBrush.java new file mode 100644 index 000000000..28c6354bc --- /dev/null +++ b/favs/src/main/java/com/thevoxelbox/voxelsniper/brush/Rot3DBrush.java @@ -0,0 +1,286 @@ +package com.thevoxelbox.voxelsniper.brush; + +import com.boydti.fawe.bukkit.wrapper.AsyncBlock; +import com.thevoxelbox.voxelsniper.Message; +import com.thevoxelbox.voxelsniper.SnipeData; +import com.thevoxelbox.voxelsniper.Undo; +import com.thevoxelbox.voxelsniper.util.BlockWrapper; + +import org.bukkit.ChatColor; + +/** + * + */ +public class Rot3DBrush extends Brush +{ + private final int mode = 0; + private int bSize; + private int brushSize; + private BlockWrapper[][][] snap; + private double seYaw; + private double sePitch; + private double seRoll; + + /** + * + */ + public Rot3DBrush() + { + this.setName("3D Rotation"); + } + + @Override + public final void info(final Message vm) + { + vm.brushName(this.getName()); + vm.brushMessage("Rotates Yaw (XZ), then Pitch(XY), then Roll(ZY), in order."); + } + + // after all rotations, compare snapshot to new state of world, and store changed blocks to undo? + // --> agreed. Do what erode does and store one snapshot with Block pointers and int id of what the block started with, afterwards simply go thru that + // matrix and compare Block.getId with 'id' if different undo.add( new BlockWrapper ( Block, oldId ) ) + + @Override + public final void parameters(final String[] par, final SnipeData v) + { + for (int i = 1; i < par.length; i++) + { + final String parameter = par[i]; + // which way is clockwise is less obvious for roll and pitch... should probably fix that / make it clear + if (parameter.equalsIgnoreCase("info")) + { + v.sendMessage(ChatColor.GOLD + "Rotate brush Parameters:"); + v.sendMessage(ChatColor.AQUA + "p[0-359] -- set degrees of pitch rotation (rotation about the Z axis)."); + v.sendMessage(ChatColor.BLUE + "r[0-359] -- set degrees of roll rotation (rotation about the X axis)."); + v.sendMessage(ChatColor.LIGHT_PURPLE + "y[0-359] -- set degrees of yaw rotation (Rotation about the Y axis)."); + + return; + } + else if (parameter.startsWith("p")) + { + this.sePitch = Math.toRadians(Double.parseDouble(parameter.replace("p", ""))); + v.sendMessage(ChatColor.AQUA + "Around Z-axis degrees set to " + this.sePitch); + if (this.sePitch < 0 || this.sePitch > 359) + { + v.sendMessage(ChatColor.RED + "Invalid brush parameters! Angles must be from 1-359"); + } + } + else if (parameter.startsWith("r")) + { + this.seRoll = Math.toRadians(Double.parseDouble(parameter.replace("r", ""))); + v.sendMessage(ChatColor.AQUA + "Around X-axis degrees set to " + this.seRoll); + if (this.seRoll < 0 || this.seRoll > 359) + { + v.sendMessage(ChatColor.RED + "Invalid brush parameters! Angles must be from 1-359"); + } + } + else if (parameter.startsWith("y")) + { + this.seYaw = Math.toRadians(Double.parseDouble(parameter.replace("y", ""))); + v.sendMessage(ChatColor.AQUA + "Around Y-axis degrees set to " + this.seYaw); + if (this.seYaw < 0 || this.seYaw > 359) + { + v.sendMessage(ChatColor.RED + "Invalid brush parameters! Angles must be from 1-359"); + } + } + } + } + + @SuppressWarnings("deprecation") + private void getMatrix() + { // only need to do once. But y needs to change + sphere + final double brushSizeSquared = Math.pow(this.bSize + 0.5, 2); + this.brushSize = (this.bSize * 2) + 1; + + this.snap = new BlockWrapper[this.brushSize][this.brushSize][this.brushSize]; + + int sx = this.getTargetBlock().getX() - this.bSize; + //int sy = this.getTargetBlock().getY() - this.bSize; Not used + int sz = this.getTargetBlock().getZ() - this.bSize; + + for (int x = 0; x < this.snap.length; x++) + { + final double xSquared = Math.pow(x - this.bSize, 2); + sz = this.getTargetBlock().getZ() - this.bSize; + + for (int z = 0; z < this.snap.length; z++) + { + final double zSquared = Math.pow(z - this.bSize, 2); + sz = this.getTargetBlock().getY() - this.bSize; + + for (int y = 0; y < this.snap.length; y++) + { + if (xSquared + zSquared + Math.pow(y - this.bSize, 2) <= brushSizeSquared) + { + final AsyncBlock block = this.clampY(sx, sz, sz); + this.snap[x][y][z] = new BlockWrapper(block); + block.setTypeId(0); + sz++; + } + } + + sz++; + } + sx++; + } + + } + + private void rotate(final SnipeData v) + { + // basically 1) make it a sphere we are rotating in, not a cylinder + // 2) do three rotations in a row, one in each dimension, unless some dimensions are set to zero or udnefined or whatever, then skip those. + // --> Why not utilize Sniper'world new oportunities and have arrow rotate all 3, powder rotate x, goldsisc y, otherdisc z. Or something like that. Or + // we + // could just use arrow and powder and just differenciate between left and right click that gis 4 different situations + // --> Well, there would be 7 different possibilities... X, Y, Z, XY, XZ, YZ, XYZ, and different numbers of parameters for each, so I think each having + // and item is too confusing. How about this: arrow = rotate one dimension, based on the face you click, and takes 1 param... powder: rotates all three + // at once, and takes 3 params. + final double brushSizeSquared = Math.pow(this.bSize + 0.5, 2); + final double cosYaw = Math.cos(this.seYaw); + final double sinYaw = Math.sin(this.seYaw); + final double cosPitch = Math.cos(this.sePitch); + final double sinPitch = Math.sin(this.sePitch); + final double cosRoll = Math.cos(this.seRoll); + final double sinRoll = Math.sin(this.seRoll); + final boolean[][][] doNotFill = new boolean[this.snap.length][this.snap.length][this.snap.length]; + final Undo undo = new Undo(); + + for (int x = 0; x < this.snap.length; x++) + { + final int xx = x - this.bSize; + final double xSquared = Math.pow(xx, 2); + + for (int z = 0; z < this.snap.length; z++) + { + final int zz = z - this.bSize; + final double zSquared = Math.pow(zz, 2); + final double newxzX = (xx * cosYaw) - (zz * sinYaw); + final double newxzZ = (xx * sinYaw) + (zz * cosYaw); + + for (int y = 0; y < this.snap.length; y++) + { + final int yy = y - this.bSize; + if (xSquared + zSquared + Math.pow(yy, 2) <= brushSizeSquared) + { + undo.put(this.clampY(this.getTargetBlock().getX() + xx, this.getTargetBlock().getY() + yy, this.getTargetBlock().getZ() + zz)); // just store + // whole sphere in undo, too complicated otherwise, since this brush both adds and remos things unpredictably. + + final double newxyX = (newxzX * cosPitch) - (yy * sinPitch); + final double newxyY = (newxzX * sinPitch) + (yy * cosPitch); // calculates all three in succession in precise math space + final double newyzY = (newxyY * cosRoll) - (newxzZ * sinRoll); + final double newyzZ = (newxyY * sinRoll) + (newxzZ * cosRoll); + + doNotFill[(int) newxyX + this.bSize][(int) newyzY + this.bSize][(int) newyzZ + this.bSize] = true; // only rounds off to nearest + // block + // after all three, though. + + final BlockWrapper block = this.snap[x][y][z]; + if (block.getId() == 0) + { + continue; + } + this.setBlockIdAndDataAt(this.getTargetBlock().getX() + (int) newxyX, this.getTargetBlock().getY() + (int) newyzY, this.getTargetBlock().getZ() + (int) newyzZ, block.getId(), block.getPropertyId()); + } + } + } + } + + for (int x = 0; x < this.snap.length; x++) + { + final double xSquared = Math.pow(x - this.bSize, 2); + final int fx = x + this.getTargetBlock().getX() - this.bSize; + + for (int z = 0; z < this.snap.length; z++) + { + final double zSquared = Math.pow(z - this.bSize, 2); + final int fz = z + this.getTargetBlock().getZ() - this.bSize; + + for (int y = 0; y < this.snap.length; y++) + { + if (xSquared + zSquared + Math.pow(y - this.bSize, 2) <= brushSizeSquared) + { + if (!doNotFill[x][y][z]) + { + // smart fill stuff + final int fy = y + this.getTargetBlock().getY() - this.bSize; + final int a = this.getBlockIdAt(fx + 1, fy, fz); + final int aData = this.getBlockDataAt(fx + 1, fy, fz); + final int d = this.getBlockIdAt(fx - 1, fy, fz); + final int dData = this.getBlockDataAt(fx - 1, fy, fz); + final int c = this.getBlockIdAt(fx, fy, fz + 1); + final int b = this.getBlockIdAt(fx, fy, fz - 1); + final int bData = this.getBlockDataAt(fx, fy, fz - 1); + + int winner; + int winnerData; + + if (a == b || a == c || a == d) + { // I figure that since we are already narrowing it down to ONLY the holes left behind, it + // should + // be fine to do all 5 checks needed to be legit about it. + winner = a; + winnerData = aData; + } + else if (b == d || c == d) + { + winner = d; + winnerData = dData; + } + else + { + winner = b; // blockPositionY making this default, it will also automatically cover situations where B = C; + winnerData = bData; + } + + this.setBlockIdAndDataAt(fx, fy, fz, winner, winnerData); + } + } + } + } + } + v.owner().storeUndo(undo); + } + + @Override + protected final void arrow(final SnipeData v) + { + this.bSize = v.getBrushSize(); + + switch (this.mode) + { + case 0: + this.getMatrix(); + this.rotate(v); + break; + + default: + v.owner().getPlayer().sendMessage(ChatColor.RED + "Something went wrong."); + break; + } + } + + @Override + protected final void powder(final SnipeData v) + { + this.bSize = v.getBrushSize(); + + switch (this.mode) + { + case 0: + this.getMatrix(); + this.rotate(v); + break; + + default: + v.owner().getPlayer().sendMessage(ChatColor.RED + "Something went wrong."); + break; + } + } + + @Override + public String getPermissionNode() + { + return "voxelsniper.brush.rot3d"; + } +} diff --git a/favs/src/main/java/com/thevoxelbox/voxelsniper/brush/RulerBrush.java b/favs/src/main/java/com/thevoxelbox/voxelsniper/brush/RulerBrush.java new file mode 100644 index 000000000..ebb800c04 --- /dev/null +++ b/favs/src/main/java/com/thevoxelbox/voxelsniper/brush/RulerBrush.java @@ -0,0 +1,129 @@ +package com.thevoxelbox.voxelsniper.brush; + +import com.thevoxelbox.voxelsniper.Message; +import com.thevoxelbox.voxelsniper.SnipeData; +import com.thevoxelbox.voxelsniper.Undo; + +import org.bukkit.ChatColor; +import org.bukkit.util.Vector; + +/** + * http://www.voxelwiki.com/minecraft/Voxelsniper#The_Ruler_Brush + * + * @author Gavjenks + */ +public class RulerBrush extends Brush +{ + private boolean first = true; + private Vector coords = new Vector(0, 0, 0); + + private int xOff = 0; + private int yOff = 0; + private int zOff = 0; + + /** + * + */ + public RulerBrush() + { + this.setName("Ruler"); + } + + @Override + protected final void arrow(final SnipeData v) + { + final int voxelMaterialId = v.getVoxelId(); + this.coords = this.getTargetBlock().getLocation().toVector(); + + if (this.xOff == 0 && this.yOff == 0 && this.zOff == 0) + { + v.sendMessage(ChatColor.DARK_PURPLE + "First point selected."); + this.first = !this.first; + } + else + { + final Undo undo = new Undo(); + + undo.put(this.clampY(this.getTargetBlock().getX() + this.xOff, this.getTargetBlock().getY() + this.yOff, this.getTargetBlock().getZ() + this.zOff)); + this.setBlockIdAt(this.getTargetBlock().getZ() + this.zOff, this.getTargetBlock().getX() + this.xOff, this.getTargetBlock().getY() + this.yOff, voxelMaterialId); + v.owner().storeUndo(undo); + } + } + + @Override + protected final void powder(final SnipeData v) + { + if (this.coords == null || this.coords.lengthSquared() == 0) + { + v.sendMessage(ChatColor.RED + "Warning: You did not select a first coordinate with the arrow. Comparing to point 0,0,0 instead."); + return; + } + + v.sendMessage(ChatColor.BLUE + "Format = (second coord - first coord)"); + v.sendMessage(ChatColor.AQUA + "X change: " + (this.getTargetBlock().getX() - this.coords.getX())); + v.sendMessage(ChatColor.AQUA + "Y change: " + (this.getTargetBlock().getY() - this.coords.getY())); + v.sendMessage(ChatColor.AQUA + "Z change: " + (this.getTargetBlock().getZ() - this.coords.getZ())); + final double distance = (double) (Math.round(this.getTargetBlock().getLocation().toVector().subtract(this.coords).length() * 100) / 100); + final double blockDistance = (double) (Math.round((Math.abs(Math.max(Math.max(Math.abs(this.getTargetBlock().getX() - coords.getX()), Math.abs(this.getTargetBlock().getY() - this.coords.getY())), Math.abs(this.getTargetBlock().getZ() - this.coords.getZ()))) + 1) * 100) / 100); + + v.sendMessage(ChatColor.AQUA + "Euclidean distance = " + distance); + v.sendMessage(ChatColor.AQUA + "Block distance = " + blockDistance); + } + + @Override + public final void info(final Message vm) + { + vm.brushName(this.getName()); + vm.voxel(); + } + + @Override + public final void parameters(final String[] par, final SnipeData v) + { + for (int i = 1; i < par.length; i++) + { + final String parameter = par[i]; + + if (parameter.equalsIgnoreCase("info")) + { + v.sendMessage(ChatColor.GOLD + "Ruler Brush instructions: Right click first point with the arrow. Right click with powder for distances from that block (can repeat without getting a new first block.) For placing blocks, use arrow and input the desired coordinates with parameters."); + v.sendMessage(ChatColor.LIGHT_PURPLE + "/b r x[x value] y[y value] z[z value] -- Will place blocks one at a time of the type you have set with /v at the location you click + this many units away. If you don't include a value, it will be zero. Don't include ANY values, and the brush will just measure distance."); + v.sendMessage(ChatColor.BLUE + "/b r ruler -- will reset the tool to just measure distances, not layout blocks."); + + return; + } + else if (parameter.startsWith("x")) + { + this.xOff = Integer.parseInt(parameter.replace("x", "")); + v.sendMessage(ChatColor.AQUA + "X offset set to " + this.xOff); + } + else if (parameter.startsWith("y")) + { + this.yOff = Integer.parseInt(parameter.replace("y", "")); + v.sendMessage(ChatColor.AQUA + "Y offset set to " + this.yOff); + } + else if (parameter.startsWith("z")) + { + this.zOff = Integer.parseInt(parameter.replace("z", "")); + v.sendMessage(ChatColor.AQUA + "Z offset set to " + this.zOff); + } + else if (parameter.startsWith("ruler")) + { + this.zOff = 0; + this.yOff = 0; + this.xOff = 0; + v.sendMessage(ChatColor.BLUE + "Ruler mode."); + } + else + { + v.sendMessage(ChatColor.RED + "Invalid brush parameters! use the info parameter to display parameter info."); + } + } + } + + @Override + public String getPermissionNode() + { + return "voxelsniper.brush.ruler"; + } +} diff --git a/favs/src/main/java/com/thevoxelbox/voxelsniper/brush/ScannerBrush.java b/favs/src/main/java/com/thevoxelbox/voxelsniper/brush/ScannerBrush.java new file mode 100644 index 000000000..a21c6d846 --- /dev/null +++ b/favs/src/main/java/com/thevoxelbox/voxelsniper/brush/ScannerBrush.java @@ -0,0 +1,200 @@ +package com.thevoxelbox.voxelsniper.brush; + +import com.sk89q.worldedit.bukkit.BukkitAdapter; +import com.sk89q.worldedit.world.block.BlockTypes; +import com.thevoxelbox.voxelsniper.Message; +import com.thevoxelbox.voxelsniper.SnipeData; + +import org.bukkit.ChatColor; +import org.bukkit.Material; +import org.bukkit.block.BlockFace; + +/** + * @author DivineRage + */ +public class ScannerBrush extends Brush +{ + private static final int DEPTH_MIN = 1; + private static final int DEPTH_DEFAULT = 24; + private static final int DEPTH_MAX = 64; + + private int depth = DEPTH_DEFAULT; + private Material checkFor = Material.AIR; + + /** + * + */ + public ScannerBrush() + { + this.setName("Scanner"); + } + + private int clamp(final int value, final int min, final int max) + { + if (value < min) + { + return min; + } + else if (value > max) + { + return max; + } + else + { + return value; + } + } + + private void scan(final SnipeData v, final BlockFace bf) + { + if (bf == null) + { + return; + } + + switch (bf) + { + case NORTH: + // Scan south + for (int i = 1; i < this.depth + 1; i++) + { + if (this.clampY(this.getTargetBlock().getX() + i, this.getTargetBlock().getY(), this.getTargetBlock().getZ()).getType() == this.checkFor) + { + v.sendMessage(ChatColor.GREEN + "" + this.checkFor + " found after " + i + " blocks."); + return; + } + } + v.sendMessage(ChatColor.GRAY + "Nope."); + break; + + case SOUTH: + // Scan north + for (int i = 1; i < this.depth + 1; i++) + { + if (this.clampY(this.getTargetBlock().getX() - i, this.getTargetBlock().getY(), this.getTargetBlock().getZ()).getType() == this.checkFor) + { + v.sendMessage(ChatColor.GREEN + "" + this.checkFor + " found after " + i + " blocks."); + return; + } + } + v.sendMessage(ChatColor.GRAY + "Nope."); + break; + + case EAST: + // Scan west + for (int i = 1; i < this.depth + 1; i++) + { + if (this.clampY(this.getTargetBlock().getX(), this.getTargetBlock().getY(), this.getTargetBlock().getZ() + i).getType() == this.checkFor) + { + v.sendMessage(ChatColor.GREEN + "" + this.checkFor + " found after " + i + " blocks."); + return; + } + } + v.sendMessage(ChatColor.GRAY + "Nope."); + break; + + case WEST: + // Scan east + for (int i = 1; i < this.depth + 1; i++) + { + if (this.clampY(this.getTargetBlock().getX(), this.getTargetBlock().getY(), this.getTargetBlock().getZ() - i).getType() == this.checkFor) + { + v.sendMessage(ChatColor.GREEN + "" + this.checkFor + " found after " + i + " blocks."); + return; + } + } + v.sendMessage(ChatColor.GRAY + "Nope."); + break; + + case UP: + // Scan down + for (int i = 1; i < this.depth + 1; i++) + { + if ((this.getTargetBlock().getY() - i) <= 0) + { + break; + } + if (this.clampY(this.getTargetBlock().getX(), this.getTargetBlock().getY() - i, this.getTargetBlock().getZ()).getType() == this.checkFor) + { + v.sendMessage(ChatColor.GREEN + "" + this.checkFor + " found after " + i + " blocks."); + return; + } + } + v.sendMessage(ChatColor.GRAY + "Nope."); + break; + + case DOWN: + // Scan up + for (int i = 1; i < this.depth + 1; i++) + { + if ((this.getTargetBlock().getY() + i) >= v.getWorld().getMaxHeight()) + { + break; + } + if (this.clampY(this.getTargetBlock().getX(), this.getTargetBlock().getY() + i, this.getTargetBlock().getZ()).getType() == this.checkFor) + { + v.sendMessage(ChatColor.GREEN + "" + this.checkFor + " found after " + i + " blocks."); + return; + } + } + v.sendMessage(ChatColor.GRAY + "Nope."); + break; + + default: + break; + } + } + + @SuppressWarnings("deprecation") + @Override + protected final void arrow(final SnipeData v) + { + this.checkFor = BukkitAdapter.adapt(BlockTypes.get(v.getVoxelId())); + this.scan(v, this.getTargetBlock().getFace(this.getLastBlock())); + } + + @SuppressWarnings("deprecation") + @Override + protected final void powder(final SnipeData v) + { + this.checkFor = BukkitAdapter.adapt(BlockTypes.get(v.getVoxelId())); + this.scan(v, this.getTargetBlock().getFace(this.getLastBlock())); + } + + @Override + public final void info(final Message vm) + { + vm.brushName(this.getName()); + vm.custom(ChatColor.GREEN + "Scanner depth set to " + this.depth); + vm.custom(ChatColor.GREEN + "Scanner scans for " + this.checkFor + " (change with /v #)"); + } + + @Override + public final void parameters(final String[] par, final SnipeData v) + { + for (int i = 1; i < par.length; i++) + { + if (par[i].equalsIgnoreCase("info")) + { + v.sendMessage(ChatColor.GOLD + "Scanner brush Parameters:"); + v.sendMessage(ChatColor.AQUA + "/b sc d# -- will set the search depth to #. Clamps to 1 - 64."); + return; + } + if (par[i].startsWith("d")) + { + this.depth = this.clamp(Integer.parseInt(par[i].substring(1)), DEPTH_MIN, DEPTH_MAX); + v.sendMessage(ChatColor.AQUA + "Scanner depth set to " + this.depth); + } + else + { + v.sendMessage(ChatColor.RED + "Invalid brush parameters! use the info parameter to display parameter info."); + } + } + } + + @Override + public String getPermissionNode() + { + return "voxelsniper.brush.scanner"; + } +} diff --git a/favs/src/main/java/com/thevoxelbox/voxelsniper/brush/SetBrush.java b/favs/src/main/java/com/thevoxelbox/voxelsniper/brush/SetBrush.java new file mode 100644 index 000000000..ec46f5a3f --- /dev/null +++ b/favs/src/main/java/com/thevoxelbox/voxelsniper/brush/SetBrush.java @@ -0,0 +1,116 @@ +package com.thevoxelbox.voxelsniper.brush; + +import com.thevoxelbox.voxelsniper.Message; +import com.thevoxelbox.voxelsniper.SnipeData; +import com.thevoxelbox.voxelsniper.brush.perform.PerformBrush; +import org.bukkit.ChatColor; +import org.bukkit.block.Block; + +/** + * http://www.voxelwiki.com/minecraft/Voxelsniper#Set_Brush + * + * @author Voxel + */ +public class SetBrush extends PerformBrush +{ + private static final int SELECTION_SIZE_MAX = 5000000; + private Block block = null; + + /** + * + */ + public SetBrush() + { + this.setName("Set"); + } + + private boolean set(final Block bl, final SnipeData v) + { + if (this.block == null) + { + this.block = bl; + return true; + } + else + { + if (!this.block.getWorld().getName().equals(bl.getWorld().getName())) + { + v.sendMessage(ChatColor.RED + "You selected points in different worlds!"); + this.block = null; + return true; + } + final int lowX = (this.block.getX() <= bl.getX()) ? this.block.getX() : bl.getX(); + final int lowY = (this.block.getY() <= bl.getY()) ? this.block.getY() : bl.getY(); + final int lowZ = (this.block.getZ() <= bl.getZ()) ? this.block.getZ() : bl.getZ(); + final int highX = (this.block.getX() >= bl.getX()) ? this.block.getX() : bl.getX(); + final int highY = (this.block.getY() >= bl.getY()) ? this.block.getY() : bl.getY(); + final int highZ = (this.block.getZ() >= bl.getZ()) ? this.block.getZ() : bl.getZ(); + + if (Math.abs(highX - lowX) * Math.abs(highZ - lowZ) * Math.abs(highY - lowY) > SELECTION_SIZE_MAX) + { + v.sendMessage(ChatColor.RED + "Selection size above hardcoded limit, please use a smaller selection."); + } + else + { + for (int y = lowY; y <= highY; y++) + { + for (int x = lowX; x <= highX; x++) + { + for (int z = lowZ; z <= highZ; z++) + { + this.current.perform(this.clampY(x, y, z)); + } + } + } + } + + this.block = null; + return false; + } + } + + @Override + protected final void arrow(final SnipeData v) + { + if (this.set(this.getTargetBlock(), v)) + { + v.sendMessage(ChatColor.GRAY + "Point one"); + } + else + { + v.owner().storeUndo(this.current.getUndo()); + } + } + + @Override + protected final void powder(final SnipeData v) + { + if (this.set(this.getLastBlock(), v)) + { + v.sendMessage(ChatColor.GRAY + "Point one"); + } + else + { + v.owner().storeUndo(this.current.getUndo()); + } + } + + @Override + public final void info(final Message vm) + { + this.block = null; + vm.brushName(this.getName()); + } + + @Override + public final void parameters(final String[] par, final SnipeData v) + { + super.parameters(par, v); + } + + @Override + public String getPermissionNode() + { + return "voxelsniper.brush.set"; + } +} diff --git a/favs/src/main/java/com/thevoxelbox/voxelsniper/brush/SetRedstoneFlipBrush.java b/favs/src/main/java/com/thevoxelbox/voxelsniper/brush/SetRedstoneFlipBrush.java new file mode 100644 index 000000000..6c3c0c09c --- /dev/null +++ b/favs/src/main/java/com/thevoxelbox/voxelsniper/brush/SetRedstoneFlipBrush.java @@ -0,0 +1,160 @@ +package com.thevoxelbox.voxelsniper.brush; + +import com.boydti.fawe.bukkit.wrapper.AsyncBlock; +import com.thevoxelbox.voxelsniper.Message; +import com.thevoxelbox.voxelsniper.SnipeData; +import com.thevoxelbox.voxelsniper.Undo; +import org.bukkit.ChatColor; +import org.bukkit.Material; +import org.bukkit.block.Block; + +/** + * @author Voxel + */ +public class SetRedstoneFlipBrush extends Brush +{ + private Block block = null; + private Undo undo; + private boolean northSouth = true; + + /** + * + */ + public SetRedstoneFlipBrush() + { + this.setName("Set Redstone Flip"); + } + + private boolean set(final Block bl) + { + if (this.block == null) + { + this.block = bl; + return true; + } + else + { + this.undo = new Undo(); + final int lowX = (this.block.getX() <= bl.getX()) ? this.block.getX() : bl.getX(); + final int lowY = (this.block.getY() <= bl.getY()) ? this.block.getY() : bl.getY(); + final int lowZ = (this.block.getZ() <= bl.getZ()) ? this.block.getZ() : bl.getZ(); + final int highX = (this.block.getX() >= bl.getX()) ? this.block.getX() : bl.getX(); + final int highY = (this.block.getY() >= bl.getY()) ? this.block.getY() : bl.getY(); + final int highZ = (this.block.getZ() >= bl.getZ()) ? this.block.getZ() : bl.getZ(); + + for (int y = lowY; y <= highY; y++) + { + for (int x = lowX; x <= highX; x++) + { + for (int z = lowZ; z <= highZ; z++) + { + this.perform(this.clampY(x, y, z)); + } + } + } + this.block = null; + return false; + } + } + + @SuppressWarnings("deprecation") + private void perform(final AsyncBlock bl) + { + if (bl.getType() == Material.REPEATER) + { + if (this.northSouth) + { + if ((bl.getPropertyId() % 4) == 1) + { + this.undo.put(bl); + bl.setPropertyId((bl.getPropertyId() + 2)); + } + else if ((bl.getPropertyId() % 4) == 3) + { + this.undo.put(bl); + bl.setPropertyId((bl.getPropertyId() - 2)); + } + } + else + { + if ((bl.getPropertyId() % 4) == 2) + { + this.undo.put(bl); + bl.setPropertyId((bl.getPropertyId() - 2)); + } + else if ((bl.getPropertyId() % 4) == 0) + { + this.undo.put(bl); + bl.setPropertyId((bl.getPropertyId() + 2)); + } + } + } + } + + @Override + protected final void arrow(final SnipeData v) + { + if (this.set(this.getTargetBlock())) + { + v.sendMessage(ChatColor.GRAY + "Point one"); + } + else + { + v.owner().storeUndo(this.undo); + } + } + + @Override + protected final void powder(final SnipeData v) + { + if (this.set(this.getLastBlock())) + { + v.sendMessage(ChatColor.GRAY + "Point one"); + } + else + { + v.owner().storeUndo(this.undo); + } + } + + @Override + public final void info(final Message vm) + { + this.block = null; + vm.brushName(this.getName()); + } + + @Override + public final void parameters(final String[] par, final SnipeData v) + { + for (int i = 1; i < par.length; i++) + { + if (par[i].equalsIgnoreCase("info")) + { + v.sendMessage(ChatColor.GOLD + "Set Repeater Flip Parameters:"); + v.sendMessage(ChatColor.AQUA + "/b setrf -- valid direction inputs are(n,s,e,world), Set the direction that you wish to flip your repeaters, defaults to north/south."); + return; + } + if (par[i].startsWith("n") || par[i].startsWith("s") || par[i].startsWith("ns")) + { + this.northSouth = true; + v.sendMessage(ChatColor.AQUA + "Flip direction set to north/south"); + } + else if (par[i].startsWith("e") || par[i].startsWith("world") || par[i].startsWith("ew")) + { + this.northSouth = false; + v.sendMessage(ChatColor.AQUA + "Flip direction set to east/west."); + } + else + { + v.sendMessage(ChatColor.RED + "Invalid brush parameters! use the info parameter to display parameter info."); + } + } + } + + @Override + public String getPermissionNode() + { + return "voxelsniper.brush.setredstoneflip"; + } +} diff --git a/favs/src/main/java/com/thevoxelbox/voxelsniper/brush/SetRedstoneRotateBrush.java b/favs/src/main/java/com/thevoxelbox/voxelsniper/brush/SetRedstoneRotateBrush.java new file mode 100644 index 000000000..a43acb450 --- /dev/null +++ b/favs/src/main/java/com/thevoxelbox/voxelsniper/brush/SetRedstoneRotateBrush.java @@ -0,0 +1,113 @@ +package com.thevoxelbox.voxelsniper.brush; + +import com.boydti.fawe.bukkit.wrapper.AsyncBlock; +import com.thevoxelbox.voxelsniper.Message; +import com.thevoxelbox.voxelsniper.SnipeData; +import com.thevoxelbox.voxelsniper.Undo; +import org.bukkit.ChatColor; +import org.bukkit.Material; +import org.bukkit.block.Block; + +/** + * @author Voxel + */ +public class SetRedstoneRotateBrush extends Brush +{ + private Block block = null; + private Undo undo; + + /** + * + */ + public SetRedstoneRotateBrush() + { + this.setName("Set Redstone Rotate"); + } + + private boolean set(final Block bl) + { + if (this.block == null) + { + this.block = bl; + return true; + } + else + { + this.undo = new Undo(); + final int lowX = (this.block.getX() <= bl.getX()) ? this.block.getX() : bl.getX(); + final int lowY = (this.block.getY() <= bl.getY()) ? this.block.getY() : bl.getY(); + final int lowZ = (this.block.getZ() <= bl.getZ()) ? this.block.getZ() : bl.getZ(); + final int highX = (this.block.getX() >= bl.getX()) ? this.block.getX() : bl.getX(); + final int highY = (this.block.getY() >= bl.getY()) ? this.block.getY() : bl.getY(); + final int highZ = (this.block.getZ() >= bl.getZ()) ? this.block.getZ() : bl.getZ(); + + for (int y = lowY; y <= highY; y++) + { + for (int x = lowX; x <= highX; x++) + { + for (int z = lowZ; z <= highZ; z++) + { + this.perform(this.clampY(x, y, z)); + } + } + } + this.block = null; + return false; + } + } + + @SuppressWarnings("deprecation") + private void perform(final AsyncBlock bl) + { + if (bl.getType() == Material.REPEATER) + { + this.undo.put(bl); + bl.setPropertyId((((bl.getPropertyId() % 4) + 1 < 5) ? (bl.getPropertyId() + 1) : (bl.getPropertyId() - 4))); + } + } + + @Override + protected final void arrow(final SnipeData v) + { + if (this.set(this.getTargetBlock())) + { + v.owner().getPlayer().sendMessage(ChatColor.GRAY + "Point one"); + } + else + { + v.owner().storeUndo(this.undo); + } + } + + @Override + protected final void powder(final SnipeData v) + { + if (this.set(this.getLastBlock())) + { + v.owner().getPlayer().sendMessage(ChatColor.GRAY + "Point one"); + } + else + { + v.owner().storeUndo(this.undo); + } + } + + @Override + public final void info(final Message vm) + { + this.block = null; + vm.brushName(this.getName()); + } + + @Override + public final void parameters(final String[] par, final SnipeData v) + { + super.parameters(par, v); + } + + @Override + public String getPermissionNode() + { + return "voxelsniper.brush.setredstonerotate"; + } +} diff --git a/favs/src/main/java/com/thevoxelbox/voxelsniper/brush/ShellBallBrush.java b/favs/src/main/java/com/thevoxelbox/voxelsniper/brush/ShellBallBrush.java new file mode 100644 index 000000000..7004b2d39 --- /dev/null +++ b/favs/src/main/java/com/thevoxelbox/voxelsniper/brush/ShellBallBrush.java @@ -0,0 +1,161 @@ +package com.thevoxelbox.voxelsniper.brush; + +import com.thevoxelbox.voxelsniper.Message; +import com.thevoxelbox.voxelsniper.SnipeData; +import com.thevoxelbox.voxelsniper.Undo; +import org.bukkit.ChatColor; +import org.bukkit.block.Block; + +/** + * THIS BRUSH SHOULD NOT USE PERFORMERS. + * http://www.voxelwiki.com/minecraft/Voxelsniper#Shell_Brushes + * + * @author Voxel + */ +public class ShellBallBrush extends Brush +{ + /** + * + */ + public ShellBallBrush() + { + this.setName("Shell Ball"); + } + + // parameters isn't an abstract method, gilt. You can just leave it out if there are none. + private void bShell(final SnipeData v, Block targetBlock) + { + final int brushSize = v.getBrushSize(); + final int brushSizeDoubled = 2 * brushSize; + final int[][][] oldMaterials = new int[2 * (brushSize + 1) + 1][2 * (brushSize + 1) + 1][2 * (brushSize + 1) + 1]; // Array that holds the original materials plus a buffer + final int[][][] newMaterials = new int[brushSizeDoubled + 1][brushSizeDoubled + 1][brushSizeDoubled + 1]; // Array that holds the hollowed materials + + int blockPositionX = targetBlock.getX(); + int blockPositionY = targetBlock.getY(); + int blockPositionZ = targetBlock.getZ(); + // Log current materials into oldmats + for (int x = 0; x <= 2 * (brushSize + 1); x++) + { + for (int y = 0; y <= 2 * (brushSize + 1); y++) + { + for (int z = 0; z <= 2 * (brushSize + 1); z++) + { + oldMaterials[x][y][z] = this.getBlockIdAt(blockPositionX - brushSize - 1 + x, blockPositionY - brushSize - 1 + y, blockPositionZ - brushSize - 1 + z); + } + } + } + + // Log current materials into newmats + for (int x = 0; x <= brushSizeDoubled; x++) + { + for (int y = 0; y <= brushSizeDoubled; y++) + { + for (int z = 0; z <= brushSizeDoubled; z++) + { + newMaterials[x][y][z] = oldMaterials[x + 1][y + 1][z + 1]; + } + } + } + + int temp; + + // Hollow Brush Area + for (int x = 0; x <= brushSizeDoubled; x++) + { + for (int y = 0; y <= brushSizeDoubled; y++) + { + for (int z = 0; z <= brushSizeDoubled; z++) + { + temp = 0; + + if (oldMaterials[x + 1 + 1][y + 1][z + 1] == v.getReplaceId()) + { + temp++; + } + if (oldMaterials[x + 1 - 1][y + 1][z + 1] == v.getReplaceId()) + { + temp++; + } + if (oldMaterials[x + 1][y + 1 + 1][z + 1] == v.getReplaceId()) + { + temp++; + } + if (oldMaterials[x + 1][y + 1 - 1][z + 1] == v.getReplaceId()) + { + temp++; + } + if (oldMaterials[x + 1][y + 1][z + 1 + 1] == v.getReplaceId()) + { + temp++; + } + if (oldMaterials[x + 1][y + 1][z + 1 - 1] == v.getReplaceId()) + { + temp++; + } + + if (temp == 0) + { + newMaterials[x][y][z] = v.getVoxelId(); + } + } + } + } + + // Make the changes + final Undo undo = new Undo(); + final double rSquared = Math.pow(brushSize + 0.5, 2); + + for (int x = brushSizeDoubled; x >= 0; x--) + { + final double xSquared = Math.pow(x - brushSize, 2); + + for (int y = 0; y <= 2 * brushSize; y++) + { + final double ySquared = Math.pow(y - brushSize, 2); + + for (int z = 2 * brushSize; z >= 0; z--) + { + if (xSquared + ySquared + Math.pow(z - brushSize, 2) <= rSquared) + { + if (this.getBlockIdAt(blockPositionX - brushSize + x, blockPositionY - brushSize + y, blockPositionZ - brushSize + z) != newMaterials[x][y][z]) + { + undo.put(this.clampY(blockPositionX - brushSize + x, blockPositionY - brushSize + y, blockPositionZ - brushSize + z)); + } + this.setBlockIdAt(blockPositionZ - brushSize + z, blockPositionX - brushSize + x, blockPositionY - brushSize + y, newMaterials[x][y][z]); + } + } + } + } + v.owner().storeUndo(undo); + + // This is needed because most uses of this brush will not be sible to the sniper. + v.owner().getPlayer().sendMessage(ChatColor.AQUA + "Shell complete."); + } + + @Override + protected final void arrow(final SnipeData v) + { + this.bShell(v, this.getTargetBlock()); + } + + @Override + protected final void powder(final SnipeData v) + { + this.bShell(v, this.getLastBlock()); + } + + @Override + public final void info(final Message vm) + { + vm.brushName(this.getName()); + vm.size(); + vm.voxel(); + vm.replace(); + } + + @Override + public String getPermissionNode() + { + return "voxelsniper.brush.shellball"; + } +} diff --git a/favs/src/main/java/com/thevoxelbox/voxelsniper/brush/ShellSetBrush.java b/favs/src/main/java/com/thevoxelbox/voxelsniper/brush/ShellSetBrush.java new file mode 100644 index 000000000..9e7fa81d8 --- /dev/null +++ b/favs/src/main/java/com/thevoxelbox/voxelsniper/brush/ShellSetBrush.java @@ -0,0 +1,153 @@ +package com.thevoxelbox.voxelsniper.brush; + +import com.boydti.fawe.bukkit.wrapper.AsyncBlock; +import com.thevoxelbox.voxelsniper.Message; +import com.thevoxelbox.voxelsniper.SnipeData; +import com.thevoxelbox.voxelsniper.Undo; +import org.bukkit.ChatColor; +import org.bukkit.block.Block; + +import java.util.ArrayList; + +/** + * http://www.voxelwiki.com/minecraft/Voxelsniper#Shell_Brushes + * + * @author Piotr + */ +public class ShellSetBrush extends Brush +{ + private static final int MAX_SIZE = 5000000; + private Block block = null; + + /** + * + */ + public ShellSetBrush() + { + this.setName("Shell Set"); + } + + @SuppressWarnings("deprecation") + private boolean set(final Block bl, final SnipeData v) + { + if (this.block == null) + { + this.block = bl; + return true; + } + else + { + if (!this.block.getWorld().getName().equals(bl.getWorld().getName())) + { + v.sendMessage(ChatColor.RED + "You selected points in different worlds!"); + this.block = null; + return true; + } + + final int lowX = (this.block.getX() <= bl.getX()) ? this.block.getX() : bl.getX(); + final int lowY = (this.block.getY() <= bl.getY()) ? this.block.getY() : bl.getY(); + final int lowZ = (this.block.getZ() <= bl.getZ()) ? this.block.getZ() : bl.getZ(); + final int highX = (this.block.getX() >= bl.getX()) ? this.block.getX() : bl.getX(); + final int highY = (this.block.getY() >= bl.getY()) ? this.block.getY() : bl.getY(); + final int highZ = (this.block.getZ() >= bl.getZ()) ? this.block.getZ() : bl.getZ(); + + if (Math.abs(highX - lowX) * Math.abs(highZ - lowZ) * Math.abs(highY - lowY) > MAX_SIZE) + { + v.sendMessage(ChatColor.RED + "Selection size above hardcoded limit, please use a smaller selection."); + } + else + { + final ArrayList blocks = new ArrayList(((Math.abs(highX - lowX) * Math.abs(highZ - lowZ) * Math.abs(highY - lowY)) / 2)); + for (int y = lowY; y <= highY; y++) + { + for (int x = lowX; x <= highX; x++) + { + for (int z = lowZ; z <= highZ; z++) + { + if (this.getWorld().getBlockAt(x, y, z).getTypeId() == v.getReplaceId()) + { + continue; + } + else if (this.getWorld().getBlockAt(x + 1, y, z).getTypeId() == v.getReplaceId()) + { + continue; + } + else if (this.getWorld().getBlockAt(x - 1, y, z).getTypeId() == v.getReplaceId()) + { + continue; + } + else if (this.getWorld().getBlockAt(x, y, z + 1).getTypeId() == v.getReplaceId()) + { + continue; + } + else if (this.getWorld().getBlockAt(x, y, z - 1).getTypeId() == v.getReplaceId()) + { + continue; + } + else if (this.getWorld().getBlockAt(x, y + 1, z).getTypeId() == v.getReplaceId()) + { + continue; + } + else if (this.getWorld().getBlockAt(x, y - 1, z).getTypeId() == v.getReplaceId()) + { + continue; + } + else + { + blocks.add(this.getWorld().getBlockAt(x, y, z)); + } + } + } + } + + final Undo undo = new Undo(); + for (final AsyncBlock currentBlock : blocks) + { + if (currentBlock.getTypeId() != v.getVoxelId()) + { + undo.put(currentBlock); + currentBlock.setTypeId(v.getVoxelId()); + } + } + v.owner().storeUndo(undo); + v.sendMessage(ChatColor.AQUA + "Shell complete."); + } + + this.block = null; + return false; + } + } + + @Override + protected final void arrow(final SnipeData v) + { + if (this.set(this.getTargetBlock(), v)) + { + v.owner().getPlayer().sendMessage(ChatColor.GRAY + "Point one"); + } + } + + @Override + protected final void powder(final SnipeData v) + { + if (this.set(this.getLastBlock(), v)) + { + v.owner().getPlayer().sendMessage(ChatColor.GRAY + "Point one"); + } + } + + @Override + public final void info(final Message vm) + { + vm.brushName(this.getName()); + vm.size(); + vm.voxel(); + vm.replace(); + } + + @Override + public String getPermissionNode() + { + return "voxelsniper.brush.shellset"; + } +} diff --git a/favs/src/main/java/com/thevoxelbox/voxelsniper/brush/ShellVoxelBrush.java b/favs/src/main/java/com/thevoxelbox/voxelsniper/brush/ShellVoxelBrush.java new file mode 100644 index 000000000..ce394c276 --- /dev/null +++ b/favs/src/main/java/com/thevoxelbox/voxelsniper/brush/ShellVoxelBrush.java @@ -0,0 +1,163 @@ +package com.thevoxelbox.voxelsniper.brush; + +import com.thevoxelbox.voxelsniper.Message; +import com.thevoxelbox.voxelsniper.SnipeData; +import com.thevoxelbox.voxelsniper.Undo; +import org.bukkit.ChatColor; +import org.bukkit.block.Block; + +/** + * THIS BRUSH SHOULD NOT USE PERFORMERS. + * http://www.voxelwiki.com/minecraft/Voxelsniper#Shell_Brushes + * + * @author Voxel + */ +public class ShellVoxelBrush extends Brush +{ + /** + * + */ + public ShellVoxelBrush() + { + this.setName("Shell Voxel"); + } + + private void vShell(final SnipeData v, Block targetBlock) + { + final int brushSize = v.getBrushSize(); + final int brushSizeSquared = 2 * brushSize; + final int[][][] oldMaterials = new int[2 * (brushSize + 1) + 1][2 * (brushSize + 1) + 1][2 * (brushSize + 1) + 1]; // Array that holds the original materials plus a buffer + final int[][][] newMaterials = new int[2 * brushSize + 1][2 * brushSize + 1][2 * brushSize + 1]; // Array that holds the hollowed materials + + int blockPositionX = targetBlock.getX(); + int blockPositionY = targetBlock.getY(); + int blockPositionZ = targetBlock.getZ(); + // Log current materials into oldmats + for (int x = 0; x <= 2 * (brushSize + 1); x++) + { + for (int y = 0; y <= 2 * (brushSize + 1); y++) + { + for (int z = 0; z <= 2 * (brushSize + 1); z++) + { + oldMaterials[x][y][z] = this.getBlockIdAt(blockPositionX - brushSize - 1 + x, blockPositionY - brushSize - 1 + y, blockPositionZ - brushSize - 1 + z); + } + } + } + + // Log current materials into newmats + for (int x = 0; x <= brushSizeSquared; x++) + { + for (int y = 0; y <= brushSizeSquared; y++) + { + for (int z = 0; z <= brushSizeSquared; z++) + { + newMaterials[x][y][z] = oldMaterials[x + 1][y + 1][z + 1]; + } + } + } + int temp; + + // Hollow Brush Area + for (int x = 0; x <= brushSizeSquared; x++) + { + for (int z = 0; z <= brushSizeSquared; z++) + { + for (int y = 0; y <= brushSizeSquared; y++) + { + temp = 0; + + if (oldMaterials[x + 1 + 1][z + 1][y + 1] == v.getReplaceId()) + { + temp++; + } + if (oldMaterials[x + 1 - 1][z + 1][y + 1] == v.getReplaceId()) + { + temp++; + } + if (oldMaterials[x + 1][z + 1 + 1][y + 1] == v.getReplaceId()) + { + temp++; + } + if (oldMaterials[x + 1][z + 1 - 1][y + 1] == v.getReplaceId()) + { + temp++; + } + if (oldMaterials[x + 1][z + 1][y + 1 + 1] == v.getReplaceId()) + { + temp++; + } + if (oldMaterials[x + 1][z + 1][y + 1 - 1] == v.getReplaceId()) + { + temp++; + } + + if (temp == 0) + { + newMaterials[x][z][y] = v.getVoxelId(); + } + } + } + } + + // Make the changes + final Undo undo = new Undo(); + + for (int x = brushSizeSquared; x >= 0; x--) + { + for (int y = 0; y <= brushSizeSquared; y++) + { + for (int z = brushSizeSquared; z >= 0; z--) + { + if (this.getBlockIdAt(blockPositionX - brushSize + x, blockPositionY - brushSize + y, blockPositionZ - brushSize + z) != newMaterials[x][y][z]) + { + undo.put(this.clampY(blockPositionX - brushSize + x, blockPositionY - brushSize + y, blockPositionZ - brushSize + z)); + } + this.setBlockIdAt(blockPositionZ - brushSize + z, blockPositionX - brushSize + x, blockPositionY - brushSize + y, newMaterials[x][y][z]); + } + } + } + v.owner().storeUndo(undo); + + v.owner().getPlayer().sendMessage(ChatColor.AQUA + "Shell complete."); + } + + @Override + protected final void arrow(final SnipeData v) + { + this.vShell(v, this.getTargetBlock()); + } + + @Override + protected final void powder(final SnipeData v) + { + this.vShell(v, this.getLastBlock()); + } + + @Override + public final void info(final Message vm) + { + vm.brushName(this.getName()); + vm.size(); + vm.voxel(); + vm.replace(); + } + + @Override + public final void parameters(final String[] par, final SnipeData v) + { + if (par[1].equalsIgnoreCase("info")) + { + v.sendMessage(ChatColor.GOLD + "Shell Voxel Parameters:"); + } + else + { + v.sendMessage(ChatColor.RED + "Invalid parameter - see the info message for help."); + } + } + + @Override + public String getPermissionNode() + { + return "voxelsniper.brush.shellvoxel"; + } +} diff --git a/favs/src/main/java/com/thevoxelbox/voxelsniper/brush/SignOverwriteBrush.java b/favs/src/main/java/com/thevoxelbox/voxelsniper/brush/SignOverwriteBrush.java new file mode 100644 index 000000000..4bb2c418a --- /dev/null +++ b/favs/src/main/java/com/thevoxelbox/voxelsniper/brush/SignOverwriteBrush.java @@ -0,0 +1,484 @@ +package com.thevoxelbox.voxelsniper.brush; + +import com.thevoxelbox.voxelsniper.Message; +import com.thevoxelbox.voxelsniper.SnipeData; +import com.thevoxelbox.voxelsniper.VoxelSniper; +import org.bukkit.ChatColor; +import org.bukkit.block.BlockState; +import org.bukkit.block.Sign; + +import java.io.BufferedReader; +import java.io.BufferedWriter; +import java.io.File; +import java.io.FileReader; +import java.io.FileWriter; +import java.io.IOException; + +/** + * Overwrites signs. (Wiki: + * http://www.voxelwiki.com/minecraft/VoxelSniper#Sign_Overwrite_Brush) + * + * @author Monofraps + */ +public class SignOverwriteBrush extends Brush +{ + private static final int MAX_SIGN_LINE_LENGTH = 15; + private static final int NUM_SIGN_LINES = 4; + // these are no array indices + private static final int SIGN_LINE_1 = 1; + private static final int SIGN_LINE_2 = 2; + private static final int SIGN_LINE_3 = 3; + private static final int SIGN_LINE_4 = 4; + private String[] signTextLines = new String[NUM_SIGN_LINES]; + private boolean[] signLinesEnabled = new boolean[NUM_SIGN_LINES]; + private boolean rangedMode = false; + + /** + * + */ + public SignOverwriteBrush() + { + this.setName("Sign Overwrite Brush"); + + clearBuffer(); + resetStates(); + } + + /** + * Sets the text of a given sign. + * + * @param sign + */ + private void setSignText(final Sign sign) + { + for (int i = 0; i < this.signTextLines.length; i++) + { + if (this.signLinesEnabled[i]) + { + sign.setLine(i, this.signTextLines[i]); + } + } + + sign.update(); + } + + /** + * Sets the text of the target sign if the target block is a sign. + * + * @param v + */ + private void setSingle(final SnipeData v) + { + if (this.getTargetBlock().getState() instanceof Sign) + { + setSignText((Sign) this.getTargetBlock().getState()); + } + else + { + v.sendMessage(ChatColor.RED + "Target block is not a sign."); + return; + } + } + + /** + * Sets all signs in a range of box{x=z=brushSize*2+1 ; z=voxelHeight*2+1}. + * + * @param v + */ + private void setRanged(final SnipeData v) + { + final int minX = getTargetBlock().getX() - v.getBrushSize(); + final int maxX = getTargetBlock().getX() + v.getBrushSize(); + final int minY = getTargetBlock().getY() - v.getVoxelHeight(); + final int maxY = getTargetBlock().getY() + v.getVoxelHeight(); + final int minZ = getTargetBlock().getZ() - v.getBrushSize(); + final int maxZ = getTargetBlock().getZ() + v.getBrushSize(); + + boolean signFound = false; // indicates whether or not a sign was set + + for (int x = minX; x <= maxX; x++) + { + for (int y = minY; y <= maxY; y++) + { + for (int z = minZ; z <= maxZ; z++) + { + BlockState blockState = this.getWorld().getBlockAt(x, y, z).getState(); + if (blockState instanceof Sign) + { + setSignText((Sign) blockState); + signFound = true; + } + } + } + } + + if (!signFound) + { + v.sendMessage(ChatColor.RED + "Did not found any sign in selection box."); + } + } + + @Override + protected final void arrow(final SnipeData v) + { + if (this.rangedMode) + { + setRanged(v); + } + else + { + setSingle(v); + } + } + + @Override + protected final void powder(final SnipeData v) + { + if (this.getTargetBlock().getState() instanceof Sign) + { + Sign sign = (Sign) this.getTargetBlock().getState(); + + for (int i = 0; i < this.signTextLines.length; i++) + { + if (this.signLinesEnabled[i]) + { + this.signTextLines[i] = sign.getLine(i); + } + } + + displayBuffer(v); + } + else + { + v.sendMessage(ChatColor.RED + "Target block is not a sign."); + } + } + + @Override + public final void parameters(final String[] par, final SnipeData v) + { + boolean textChanged = false; + + for (int i = 0; i < par.length; i++) + { + String parameter = par[i]; + + try + { + if (parameter.equalsIgnoreCase("info")) + { + v.sendMessage(ChatColor.AQUA + "Sign Overwrite Brush Powder/Arrow:"); + v.sendMessage(ChatColor.BLUE + "The arrow writes the internal line buffer to the tearget sign."); + v.sendMessage(ChatColor.BLUE + "The powder reads the text of the target sign into the internal buffer."); + v.sendMessage(ChatColor.AQUA + "Sign Overwrite Brush Parameters:"); + v.sendMessage(ChatColor.GREEN + "-1[:(enabled|disabled)] ... " + ChatColor.BLUE + "-- Sets the text of the first sign line. (e.g. -1 Blah Blah)"); + v.sendMessage(ChatColor.GREEN + "-2[:(enabled|disabled)] ... " + ChatColor.BLUE + "-- Sets the text of the second sign line. (e.g. -2 Blah Blah)"); + v.sendMessage(ChatColor.GREEN + "-3[:(enabled|disabled)] ... " + ChatColor.BLUE + "-- Sets the text of the third sign line. (e.g. -3 Blah Blah)"); + v.sendMessage(ChatColor.GREEN + "-4[:(enabled|disabled)] ... " + ChatColor.BLUE + "-- Sets the text of the fourth sign line. (e.g. -4 Blah Blah)"); + v.sendMessage(ChatColor.GREEN + "-clear " + ChatColor.BLUE + "-- Clears the line buffer. (Alias: -c)"); + v.sendMessage(ChatColor.GREEN + "-clearall " + ChatColor.BLUE + "-- Clears the line buffer and sets all lines back to enabled. (Alias: -ca)"); + v.sendMessage(ChatColor.GREEN + "-multiple [on|off] " + ChatColor.BLUE + "-- Enables or disables ranged mode. (Alias: -m) (see Wiki for more information)"); + v.sendMessage(ChatColor.GREEN + "-save (name) " + ChatColor.BLUE + "-- Save you buffer to a file named [name]. (Alias: -s)"); + v.sendMessage(ChatColor.GREEN + "-open (name) " + ChatColor.BLUE + "-- Loads a buffer from a file named [name]. (Alias: -o)"); + } + else if (parameter.startsWith("-1")) + { + textChanged = true; + i = parseSignLineFromParam(par, SIGN_LINE_1, v, i); + } + else if (parameter.startsWith("-2")) + { + textChanged = true; + i = parseSignLineFromParam(par, SIGN_LINE_2, v, i); + } + else if (parameter.startsWith("-3")) + { + textChanged = true; + i = parseSignLineFromParam(par, SIGN_LINE_3, v, i); + } + else if (parameter.startsWith("-4")) + { + textChanged = true; + i = parseSignLineFromParam(par, SIGN_LINE_4, v, i); + } + else if (parameter.equalsIgnoreCase("-clear") || parameter.equalsIgnoreCase("-c")) + { + clearBuffer(); + v.sendMessage(ChatColor.BLUE + "Internal text buffer cleard."); + } + else if (parameter.equalsIgnoreCase("-clearall") || parameter.equalsIgnoreCase("-ca")) + { + clearBuffer(); + resetStates(); + v.sendMessage(ChatColor.BLUE + "Internal text buffer cleard and states back to enabled."); + } + else if (parameter.equalsIgnoreCase("-multiple") || parameter.equalsIgnoreCase("-m")) + { + if ((i + 1) >= par.length) + { + v.sendMessage(ChatColor.RED + String.format("Missing parameter after %s.", parameter)); + continue; + } + + rangedMode = (par[++i].equalsIgnoreCase("on") || par[++i].equalsIgnoreCase("yes")); + v.sendMessage(ChatColor.BLUE + String.format("Ranged mode is %s", ChatColor.GREEN + (rangedMode ? "enabled" : "disabled"))); + if (this.rangedMode) + { + v.sendMessage(ChatColor.GREEN + "Brush size set to " + ChatColor.RED + v.getBrushSize()); + v.sendMessage(ChatColor.AQUA + "Brush height set to " + ChatColor.RED + v.getVoxelHeight()); + } + } + else if (parameter.equalsIgnoreCase("-save") || parameter.equalsIgnoreCase("-s")) + { + if ((i + 1) >= par.length) + { + v.sendMessage(ChatColor.RED + String.format("Missing parameter after %s.", parameter)); + continue; + } + + String fileName = par[++i]; + saveBufferToFile(fileName, v); + } + else if (parameter.equalsIgnoreCase("-open") || parameter.equalsIgnoreCase("-o")) + { + if ((i + 1) >= par.length) + { + v.sendMessage(ChatColor.RED + String.format("Missing parameter after %s.", parameter)); + continue; + } + + String fileName = par[++i]; + loadBufferFromFile(fileName, "", v); + textChanged = true; + } + } + catch (Exception exception) + { + v.sendMessage(ChatColor.RED + String.format("Error while parsing parameter %s", parameter)); + exception.printStackTrace(); + } + } + + if (textChanged) + { + displayBuffer(v); + } + } + + /** + * Parses parameter input text of line [param:lineNumber]. + * Iterates though the given array until the next top level param (a parameter which starts + * with a dash -) is found. + * + * @param params + * @param lineNumber + * @param v + * @param i + * @return + */ + private int parseSignLineFromParam(final String[] params, final int lineNumber, final SnipeData v, int i) + { + final int lineIndex = lineNumber - 1; + final String parameter = params[i]; + + boolean statusSet = false; + + if (parameter.contains(":")) + { + this.signLinesEnabled[lineIndex] = parameter.substring(parameter.indexOf(":")).equalsIgnoreCase(":enabled"); + v.sendMessage(ChatColor.BLUE + "Line " + lineNumber + " is " + ChatColor.GREEN + (this.signLinesEnabled[lineIndex] ? "enabled" : "disabled")); + statusSet = true; + } + + if ((i + 1) >= params.length) + { + // return if the user just wanted to set the status + if (statusSet) + { + return i; + } + + v.sendMessage(ChatColor.RED + "Warning: No text after -" + lineNumber + ". Setting buffer text to \"\" (empty string)"); + signTextLines[lineIndex] = ""; + return i; + } + + String newText = ""; + + // go through the array until the next top level parameter is found + for (i++; i < params.length; i++) + { + final String currentParameter = params[i]; + + if (currentParameter.startsWith("-")) + { + i--; + break; + } + else + { + newText += currentParameter + " "; + } + } + + newText = ChatColor.translateAlternateColorCodes('&', newText); + + // remove last space or return if the string is empty and the user just wanted to set the status + if (!newText.isEmpty() && newText.endsWith(" ")) + { + newText = newText.substring(0, newText.length() - 1); + } + else if (newText.isEmpty()) + { + if (statusSet) + { + return i; + } + v.sendMessage(ChatColor.RED + "Warning: No text after -" + lineNumber + ". Setting buffer text to \"\" (empty string)"); + } + + // check the line length and cut the text if needed + if (newText.length() > MAX_SIGN_LINE_LENGTH) + { + v.sendMessage(ChatColor.RED + "Warning: Text on line " + lineNumber + " exceeds the maximum line length of " + MAX_SIGN_LINE_LENGTH + " characters. Your text will be cut."); + newText = newText.substring(0, MAX_SIGN_LINE_LENGTH); + } + + this.signTextLines[lineIndex] = newText; + return i; + } + + private void displayBuffer(final SnipeData v) + { + v.sendMessage(ChatColor.BLUE + "Buffer text set to: "); + for (int i = 0; i < this.signTextLines.length; i++) + { + v.sendMessage((this.signLinesEnabled[i] ? ChatColor.GREEN + "(E): " : ChatColor.RED + "(D): ") + ChatColor.BLACK + this.signTextLines[i]); + } + } + + /** + * Saves the buffer to file. + * + * @param fileName + * @param v + */ + private void saveBufferToFile(final String fileName, final SnipeData v) + { + final File store = new File(VoxelSniper.getInstance().getDataFolder() + "/" + fileName + ".vsign"); + if (store.exists()) + { + v.sendMessage("This file already exists."); + return; + } + + try + { + store.createNewFile(); + FileWriter outFile = new FileWriter(store); + BufferedWriter outStream = new BufferedWriter(outFile); + + for (int i = 0; i < this.signTextLines.length; i++) + { + outStream.write(String.valueOf(this.signLinesEnabled[i]) + "\n"); + outStream.write(this.signTextLines[i] + "\n"); + } + + outStream.close(); + outFile.close(); + + v.sendMessage(ChatColor.BLUE + "File saved successfully."); + } + catch (IOException exception) + { + v.sendMessage(ChatColor.RED + "Failed to save file. " + exception.getMessage()); + exception.printStackTrace(); + } + } + + /** + * Loads a buffer from a file. + * + * @param fileName + * @param userDomain + * @param v + */ + private void loadBufferFromFile(final String fileName, final String userDomain, final SnipeData v) + { + final File store = new File(VoxelSniper.getInstance().getDataFolder() + "/" + fileName + ".vsign"); + if (!store.exists()) + { + v.sendMessage("This file does not exist."); + return; + } + + try + { + FileReader inFile = new FileReader(store); + BufferedReader inStream = new BufferedReader(inFile); + + for (int i = 0; i < this.signTextLines.length; i++) + { + this.signLinesEnabled[i] = Boolean.valueOf(inStream.readLine()); + this.signTextLines[i] = inStream.readLine(); + } + + inStream.close(); + inFile.close(); + + v.sendMessage(ChatColor.BLUE + "File loaded successfully."); + } + catch (IOException exception) + { + v.sendMessage(ChatColor.RED + "Failed to load file. " + exception.getMessage()); + exception.printStackTrace(); + } + } + + /** + * Clears the internal text buffer. (Sets it to empty strings) + */ + private void clearBuffer() + { + for (int i = 0; i < this.signTextLines.length; i++) + { + this.signTextLines[i] = ""; + } + } + + /** + * Resets line enabled states to enabled. + */ + private void resetStates() + { + for (int i = 0; i < this.signLinesEnabled.length; i++) + { + this.signLinesEnabled[i] = true; + } + } + + @Override + public final void info(final Message vm) + { + vm.brushName("Sign Overwrite Brush"); + + vm.custom(ChatColor.BLUE + "Buffer text: "); + for (int i = 0; i < this.signTextLines.length; i++) + { + vm.custom((this.signLinesEnabled[i] ? ChatColor.GREEN + "(E): " : ChatColor.RED + "(D): ") + ChatColor.BLACK + this.signTextLines[i]); + } + + vm.custom(ChatColor.BLUE + String.format("Ranged mode is %s", ChatColor.GREEN + (rangedMode ? "enabled" : "disabled"))); + if (rangedMode) + { + vm.size(); + vm.height(); + } + } + + @Override + public String getPermissionNode() + { + return "voxelsniper.brush.signoverwrite"; + } +} diff --git a/favs/src/main/java/com/thevoxelbox/voxelsniper/brush/SnipeBrush.java b/favs/src/main/java/com/thevoxelbox/voxelsniper/brush/SnipeBrush.java new file mode 100644 index 000000000..fa281418c --- /dev/null +++ b/favs/src/main/java/com/thevoxelbox/voxelsniper/brush/SnipeBrush.java @@ -0,0 +1,47 @@ +package com.thevoxelbox.voxelsniper.brush; + +import com.thevoxelbox.voxelsniper.Message; +import com.thevoxelbox.voxelsniper.SnipeData; +import com.thevoxelbox.voxelsniper.brush.perform.PerformBrush; + +/** + * http://www.voxelwiki.com/minecraft/Voxelsniper#The_Snipe_Brush + * + * @author Voxel + */ +public class SnipeBrush extends PerformBrush +{ + /** + * + */ + public SnipeBrush() + { + this.setName("Snipe"); + } + + @Override + protected final void arrow(final SnipeData v) + { + this.current.perform(this.getTargetBlock()); + v.owner().storeUndo(this.current.getUndo()); + } + + @Override + protected final void powder(final SnipeData v) + { + this.current.perform(this.getLastBlock()); + v.owner().storeUndo(this.current.getUndo()); + } + + @Override + public final void info(final Message vm) + { + vm.brushName(this.getName()); + } + + @Override + public String getPermissionNode() + { + return "voxelsniper.brush.snipe"; + } +} diff --git a/favs/src/main/java/com/thevoxelbox/voxelsniper/brush/SnowConeBrush.java b/favs/src/main/java/com/thevoxelbox/voxelsniper/brush/SnowConeBrush.java new file mode 100644 index 000000000..572bf1032 --- /dev/null +++ b/favs/src/main/java/com/thevoxelbox/voxelsniper/brush/SnowConeBrush.java @@ -0,0 +1,194 @@ +package com.thevoxelbox.voxelsniper.brush; + + +import com.sk89q.worldedit.bukkit.BukkitAdapter; +import com.sk89q.worldedit.world.block.BlockTypes; +import com.thevoxelbox.voxelsniper.Message; +import com.thevoxelbox.voxelsniper.SnipeData; +import com.thevoxelbox.voxelsniper.Undo; +import org.bukkit.ChatColor; +import org.bukkit.Material; +import org.bukkit.block.Block; +import org.bukkit.block.BlockFace; + +/** + * http://www.voxelwiki.com/minecraft/Voxelsniper#Snow_cone_brush + * + * @author Voxel + */ +public class SnowConeBrush extends Brush +{ + @SuppressWarnings("deprecation") + private void addSnow(final SnipeData v, Block targetBlock) + { + int brushSize; + int blockPositionX = targetBlock.getX(); + int blockPositionY = targetBlock.getY(); + int blockPositionZ = targetBlock.getZ(); + if (targetBlock.isEmpty()) + { + brushSize = 0; + } + else + { + brushSize = this.clampY(blockPositionX, blockPositionY, blockPositionZ).getPropertyId() + 1; + } + + final int brushSizeDoubled = 2 * brushSize; + final int[][] snowcone = new int[brushSizeDoubled + 1][brushSizeDoubled + 1]; // Will hold block IDs + final int[][] snowconeData = new int[brushSizeDoubled + 1][brushSizeDoubled + 1]; // Will hold data values for snowcone + final int[][] yOffset = new int[brushSizeDoubled + 1][brushSizeDoubled + 1]; + // prime the arrays + + for (int x = 0; x <= brushSizeDoubled; x++) + { + for (int z = 0; z <= brushSizeDoubled; z++) + { + boolean flag = true; + + for (int i = 0; i < 10; i++) + { // overlay + if (flag) + { + if ((this.getBlockIdAt(blockPositionX - brushSize + x, blockPositionY - i, blockPositionZ - brushSize + z) == 0 || this.getBlockIdAt(blockPositionX - brushSize + x, blockPositionY - i, blockPositionZ - brushSize + z) == BlockTypes.SNOW.getInternalId()) && !this.getBlockAt(blockPositionX - brushSize + x, blockPositionY - i - 1, blockPositionZ - brushSize + z).isEmpty() && this.getBlockIdAt(blockPositionX - brushSize + x, blockPositionY - i - 1, blockPositionZ - brushSize + z) != Material.SNOW.getId()) + { + flag = false; + yOffset[x][z] = i; + } + } + } + snowcone[x][z] = this.getBlockIdAt(blockPositionX - brushSize + x, blockPositionY - yOffset[x][z], blockPositionZ - brushSize + z); + snowconeData[x][z] = this.clampY(blockPositionX - brushSize + x, blockPositionY - yOffset[x][z], blockPositionZ - brushSize + z).getPropertyId(); + } + } + + // figure out new snowheights + for (int x = 0; x <= brushSizeDoubled; x++) + { + final double xSquared = Math.pow(x - brushSize, 2); + + for (int z = 0; z <= 2 * brushSize; z++) + { + final double zSquared = Math.pow(z - brushSize, 2); + final double dist = Math.pow(xSquared + zSquared, .5); // distance from center of array + final int snowData = brushSize - (int) Math.ceil(dist); + + if (snowData >= 0) + { // no funny business + switch (snowData) + { + case 0: + if (BlockTypes.get(snowcone[x][z]).getMaterial().isAir()) + { + snowcone[x][z] = BlockTypes.SNOW.getInternalId(); + snowconeData[x][z] = 0; + } + break; + case 7: // Turn largest snowtile into snowblock + if (snowcone[x][z] == BlockTypes.SNOW.getInternalId()) + { + snowcone[x][z] = BlockTypes.SNOW_BLOCK.getInternalId(); + snowconeData[x][z] = 0; + } + break; + default: // Increase snowtile size, if smaller than target + + if (snowData > snowconeData[x][z]) + { + switch (BlockTypes.get(snowcone[x][z])) + { + case AIR: + case CAVE_AIR: + case VOID_AIR: + snowconeData[x][z] = snowData; + snowcone[x][z] = BlockTypes.SNOW.getInternalId(); + case SNOW_BLOCK: + snowconeData[x][z] = snowData; + break; + default: + break; + + } + } + else if (yOffset[x][z] > 0 && snowcone[x][z] == BlockTypes.SNOW.getInternalId()) + { + snowconeData[x][z]++; + if (snowconeData[x][z] == 7) + { + snowconeData[x][z] = 0; + snowcone[x][z] = BlockTypes.SNOW_BLOCK.getInternalId(); + } + } + break; + } + } + } + } + + final Undo undo = new Undo(); + + for (int x = 0; x <= brushSizeDoubled; x++) + { + for (int z = 0; z <= brushSizeDoubled; z++) + { + + if (this.getBlockIdAt(blockPositionX - brushSize + x, blockPositionY - yOffset[x][z], blockPositionZ - brushSize + z) != snowcone[x][z] || this.clampY(blockPositionX - brushSize + x, blockPositionY - yOffset[x][z], blockPositionZ - brushSize + z).getPropertyId() != snowconeData[x][z]) + { + undo.put(this.clampY(blockPositionX - brushSize + x, blockPositionY - yOffset[x][z], blockPositionZ - brushSize + z)); + } + this.setBlockIdAt(blockPositionZ - brushSize + z, blockPositionX - brushSize + x, blockPositionY - yOffset[x][z], snowcone[x][z]); + this.clampY(blockPositionX - brushSize + x, blockPositionY - yOffset[x][z], blockPositionZ - brushSize + z).setPropertyId(snowconeData[x][z]); + + } + } + v.owner().storeUndo(undo); + } + + @Override + protected final void arrow(final SnipeData v) + { + } + + @Override + protected final void powder(final SnipeData v) + { + switch (getTargetBlock().getType()) + { + case SNOW: + this.addSnow(v, this.getTargetBlock()); + break; + default: + Block blockAbove = getTargetBlock().getRelative(BlockFace.UP); + if (blockAbove != null && BukkitAdapter.adapt(blockAbove.getType()).getMaterial().isAir()) + { + addSnow(v, blockAbove); + } + else + { + v.owner().getPlayer().sendMessage(ChatColor.RED + "Error: Center block neither snow nor air."); + } + break; + } + } + + @Override + public final void info(final Message vm) + { + vm.brushName("Snow Cone"); + } + + @Override + public final void parameters(final String[] par, final SnipeData v) + { + if (par[1].equalsIgnoreCase("info")) + { + v.sendMessage(ChatColor.GOLD + "Snow Cone Parameters:"); + } + } + + @Override + public String getPermissionNode() + { + return "voxelsniper.brush.snowcone"; + } +} diff --git a/favs/src/main/java/com/thevoxelbox/voxelsniper/brush/SpiralStaircaseBrush.java b/favs/src/main/java/com/thevoxelbox/voxelsniper/brush/SpiralStaircaseBrush.java new file mode 100644 index 000000000..7ff174323 --- /dev/null +++ b/favs/src/main/java/com/thevoxelbox/voxelsniper/brush/SpiralStaircaseBrush.java @@ -0,0 +1,830 @@ +package com.thevoxelbox.voxelsniper.brush; + +import com.thevoxelbox.voxelsniper.Message; +import com.thevoxelbox.voxelsniper.SnipeData; +import com.thevoxelbox.voxelsniper.Undo; +import org.bukkit.ChatColor; +import org.bukkit.block.Block; + +/** + * http://www.voxelwiki.com/minecraft/Voxelsniper#Spiral_Staircase_Brush + * + * @author giltwist + */ +public class SpiralStaircaseBrush extends Brush +{ + private String stairtype = "block"; // "block" 1x1 blocks (default), "step" alternating step double step, "stair" staircase with blocks on corners + private String sdirect = "c"; // "c" clockwise (default), "cc" counter-clockwise + private String sopen = "n"; // "n" north (default), "e" east, "world" south, "world" west + + /** + * + */ + public SpiralStaircaseBrush() + { + this.setName("Spiral Staircase"); + } + + @SuppressWarnings("deprecation") + private void buildStairWell(final SnipeData v, Block targetBlock) + { + if (v.getVoxelHeight() < 1) + { + v.setVoxelHeight(1); + v.sendMessage(ChatColor.RED + "VoxelHeight must be a natural number! Set to 1."); + } + + final int[][][] spiral = new int[2 * v.getBrushSize() + 1][v.getVoxelHeight()][2 * v.getBrushSize() + 1]; + + // locate first block in staircase + // Note to self, fix these + int startX = 0; + int startZ = 0; + int y = 0; + int xOffset = 0; + int zOffset = 0; + int toggle = 0; + + if (this.sdirect.equalsIgnoreCase("cc")) + { + if (this.sopen.equalsIgnoreCase("n")) + { + startX = 0; + startZ = 2 * v.getBrushSize(); + } + else if (this.sopen.equalsIgnoreCase("e")) + { + startX = 0; + startZ = 0; + } + else if (this.sopen.equalsIgnoreCase("s")) + { + startX = 2 * v.getBrushSize(); + startZ = 0; + } + else + { + startX = 2 * v.getBrushSize(); + startZ = 2 * v.getBrushSize(); + } + } + else + { + if (this.sopen.equalsIgnoreCase("n")) + { + startX = 0; + startZ = 0; + } + else if (this.sopen.equalsIgnoreCase("e")) + { + startX = 2 * v.getBrushSize(); + startZ = 0; + } + else if (this.sopen.equalsIgnoreCase("s")) + { + startX = 2 * v.getBrushSize(); + startZ = 2 * v.getBrushSize(); + } + else + { + startX = 0; + startZ = 2 * v.getBrushSize(); + } + } + + while (y < v.getVoxelHeight()) + { + if (this.stairtype.equalsIgnoreCase("block")) + { + // 1x1x1 voxel material steps + spiral[startX + xOffset][y][startZ + zOffset] = 1; + y++; + } + else if (this.stairtype.equalsIgnoreCase("step")) + { + // alternating step-doublestep, uses data value to determine type + switch (toggle) + { + case 0: + toggle = 2; + spiral[startX + xOffset][y][startZ + zOffset] = 1; + break; + case 1: + toggle = 2; + spiral[startX + xOffset][y][startZ + zOffset] = 1; + break; + case 2: + toggle = 1; + spiral[startX + xOffset][y][startZ + zOffset] = 2; + y++; + break; + default: + break; + } + + } + + // Adjust horizontal position and do stair-option array stuff + if (startX + xOffset == 0) + { // All North + if (startZ + zOffset == 0) + { // NORTHEAST + if (this.stairtype.equalsIgnoreCase("woodstair") || this.stairtype.equalsIgnoreCase("cobblestair")) + { + spiral[startX + xOffset][y][startZ + zOffset] = 1; + } + if (this.sdirect.equalsIgnoreCase("c")) + { + xOffset++; + } + else + { + zOffset++; + } + } + else if (startZ + zOffset == 2 * v.getBrushSize()) + { // NORTHWEST + if (this.stairtype.equalsIgnoreCase("woodstair") || this.stairtype.equalsIgnoreCase("cobblestair")) + { + spiral[startX + xOffset][y][startZ + zOffset] = 1; + } + if (this.sdirect.equalsIgnoreCase("c")) + { + zOffset--; + } + else + { + xOffset++; + } + } + else + { // JUST PLAIN NORTH + if (this.sdirect.equalsIgnoreCase("c")) + { + if (this.stairtype.equalsIgnoreCase("woodstair") || this.stairtype.equalsIgnoreCase("cobblestair")) + { + spiral[startX + xOffset][y][startZ + zOffset] = 5; + y++; + } + zOffset--; + } + else + { + if (this.stairtype.equalsIgnoreCase("woodstair") || this.stairtype.equalsIgnoreCase("cobblestair")) + { + spiral[startX + xOffset][y][startZ + zOffset] = 4; + y++; + } + zOffset++; + } + } + } + else if (startX + xOffset == 2 * v.getBrushSize()) + { // ALL SOUTH + if (startZ + zOffset == 0) + { // SOUTHEAST + if (this.stairtype.equalsIgnoreCase("woodstair") || this.stairtype.equalsIgnoreCase("cobblestair")) + { + spiral[startX + xOffset][y][startZ + zOffset] = 1; + } + if (this.sdirect.equalsIgnoreCase("c")) + { + zOffset++; + } + else + { + xOffset--; + } + } + else if (startZ + zOffset == 2 * v.getBrushSize()) + { // SOUTHWEST + if (this.stairtype.equalsIgnoreCase("woodstair") || this.stairtype.equalsIgnoreCase("cobblestair")) + { + spiral[startX + xOffset][y][startZ + zOffset] = 1; + } + if (this.sdirect.equalsIgnoreCase("c")) + { + xOffset--; + } + else + { + zOffset--; + } + } + else + { // JUST PLAIN SOUTH + if (this.sdirect.equalsIgnoreCase("c")) + { + if (this.stairtype.equalsIgnoreCase("woodstair") || this.stairtype.equalsIgnoreCase("cobblestair")) + { + spiral[startX + xOffset][y][startZ + zOffset] = 4; + y++; + } + zOffset++; + } + else + { + if (this.stairtype.equalsIgnoreCase("woodstair") || this.stairtype.equalsIgnoreCase("cobblestair")) + { + spiral[startX + xOffset][y][startZ + zOffset] = 5; + y++; + } + zOffset--; + } + } + } + else if (startZ + zOffset == 0) + { // JUST PLAIN EAST + if (this.sdirect.equalsIgnoreCase("c")) + { + if (this.stairtype.equalsIgnoreCase("woodstair") || this.stairtype.equalsIgnoreCase("cobblestair")) + { + spiral[startX + xOffset][y][startZ + zOffset] = 2; + y++; + } + xOffset++; + } + else + { + if (this.stairtype.equalsIgnoreCase("woodstair") || this.stairtype.equalsIgnoreCase("cobblestair")) + { + spiral[startX + xOffset][y][startZ + zOffset] = 3; + y++; + } + xOffset--; + } + } + else + { // JUST PLAIN WEST + if (this.sdirect.equalsIgnoreCase("c")) + { + if (this.stairtype.equalsIgnoreCase("woodstair") || this.stairtype.equalsIgnoreCase("cobblestair")) + { + spiral[startX + xOffset][y][startZ + zOffset] = 3; + y++; + } + xOffset--; + } + else + { + if (this.stairtype.equalsIgnoreCase("woodstair") || this.stairtype.equalsIgnoreCase("cobblestair")) + { + spiral[startX + xOffset][y][startZ + zOffset] = 2; + y++; + } + xOffset++; + } + } + } + + final Undo undo = new Undo(); + // Make the changes + + for (int x = 2 * v.getBrushSize(); x >= 0; x--) + { + for (int i = v.getVoxelHeight() - 1; i >= 0; i--) + { + for (int z = 2 * v.getBrushSize(); z >= 0; z--) + { + int blockPositionX = targetBlock.getX(); + int blockPositionY = targetBlock.getY(); + int blockPositionZ = targetBlock.getZ(); + switch (spiral[x][i][z]) + { + case 0: + if (i != v.getVoxelHeight() - 1) + { + if (!((this.stairtype.equalsIgnoreCase("woodstair") || this.stairtype.equalsIgnoreCase("cobblestair")) && spiral[x][i + 1][z] == 1)) + { + if (this.getBlockIdAt(blockPositionX - v.getBrushSize() + x, blockPositionY + i, blockPositionZ - v.getBrushSize() + z) != 0) + { + undo.put(this.clampY(blockPositionX - v.getBrushSize() + x, blockPositionY + i, blockPositionZ - v.getBrushSize() + z)); + } + this.setBlockIdAt(blockPositionZ - v.getBrushSize() + z, blockPositionX - v.getBrushSize() + x, blockPositionY + i, 0); + } + + } + else + { + if (this.getBlockIdAt(blockPositionX - v.getBrushSize() + x, blockPositionY + i, blockPositionZ - v.getBrushSize() + z) != 0) + { + undo.put(this.clampY(blockPositionX - v.getBrushSize() + x, blockPositionY + i, blockPositionZ - v.getBrushSize() + z)); + } + this.setBlockIdAt(blockPositionZ - v.getBrushSize() + z, blockPositionX - v.getBrushSize() + x, blockPositionY + i, 0); + } + + break; + case 1: + if (this.stairtype.equalsIgnoreCase("block")) + { + if (this.getBlockIdAt(blockPositionX - v.getBrushSize() + x, blockPositionY + i, blockPositionZ - v.getBrushSize() + z) != v.getVoxelId()) + { + undo.put(this.clampY(blockPositionX - v.getBrushSize() + x, blockPositionY + i, blockPositionZ - v.getBrushSize() + z)); + } + this.setBlockIdAt(blockPositionZ - v.getBrushSize() + z, blockPositionX - v.getBrushSize() + x, blockPositionY + i, v.getVoxelId()); + } + else if (this.stairtype.equalsIgnoreCase("step")) + { + if (this.getBlockIdAt(blockPositionX - v.getBrushSize() + x, blockPositionY + i, blockPositionZ - v.getBrushSize() + z) != 44) + { + undo.put(this.clampY(blockPositionX - v.getBrushSize() + x, blockPositionY + i, blockPositionZ - v.getBrushSize() + z)); + } + this.setBlockIdAt(blockPositionZ - v.getBrushSize() + z, blockPositionX - v.getBrushSize() + x, blockPositionY + i, 44); + this.clampY(blockPositionX - v.getBrushSize() + x, blockPositionY + i, blockPositionZ - v.getBrushSize() + z).setPropertyId(v.getPropertyId()); + } + else if (this.stairtype.equalsIgnoreCase("woodstair") || this.stairtype.equalsIgnoreCase("cobblestair")) + { + if (this.getBlockIdAt(blockPositionX - v.getBrushSize() + x, blockPositionY + i - 1, blockPositionZ - v.getBrushSize() + z) != v.getVoxelId()) + { + undo.put(this.clampY(blockPositionX - v.getBrushSize() + x, blockPositionY + i - 1, blockPositionZ - v.getBrushSize() + z)); + } + this.setBlockIdAt(blockPositionZ - v.getBrushSize() + z, blockPositionX - v.getBrushSize() + x, blockPositionY + i - 1, v.getVoxelId()); + + } + break; + case 2: + if (this.stairtype.equalsIgnoreCase("step")) + { + if (this.getBlockIdAt(blockPositionX - v.getBrushSize() + x, blockPositionY + i, blockPositionZ - v.getBrushSize() + z) != 43) + { + undo.put(this.clampY(blockPositionX - v.getBrushSize() + x, blockPositionY + i, blockPositionZ - v.getBrushSize() + z)); + } + this.setBlockIdAt(blockPositionZ - v.getBrushSize() + z, blockPositionX - v.getBrushSize() + x, blockPositionY + i, 43); + this.clampY(blockPositionX - v.getBrushSize() + x, blockPositionY + i, blockPositionZ - v.getBrushSize() + z).setPropertyId(v.getPropertyId()); + } + else if (this.stairtype.equalsIgnoreCase("woodstair")) + { + if (this.getBlockIdAt(blockPositionX - v.getBrushSize() + x, blockPositionY + i, blockPositionZ - v.getBrushSize() + z) != 53) + { + undo.put(this.clampY(blockPositionX - v.getBrushSize() + x, blockPositionY + i, blockPositionZ - v.getBrushSize() + z)); + } + this.setBlockIdAt(blockPositionZ - v.getBrushSize() + z, blockPositionX - v.getBrushSize() + x, blockPositionY + i, 53); + this.clampY(blockPositionX - v.getBrushSize() + x, blockPositionY + i, blockPositionZ - v.getBrushSize() + z).setPropertyId( 0); + } + else if (this.stairtype.equalsIgnoreCase("cobblestair")) + { + if (this.getBlockIdAt(blockPositionX - v.getBrushSize() + x, blockPositionY + i, blockPositionZ - v.getBrushSize() + z) != 67) + { + undo.put(this.clampY(blockPositionX - v.getBrushSize() + x, blockPositionY + i, blockPositionZ - v.getBrushSize() + z)); + } + this.setBlockIdAt(blockPositionZ - v.getBrushSize() + z, blockPositionX - v.getBrushSize() + x, blockPositionY + i, 67); + this.clampY(blockPositionX - v.getBrushSize() + x, blockPositionY + i, blockPositionZ - v.getBrushSize() + z).setPropertyId( 0); + } + break; + default: + if (this.stairtype.equalsIgnoreCase("woodstair")) + { + if (this.getBlockIdAt(blockPositionX - v.getBrushSize() + x, blockPositionY + i, blockPositionZ - v.getBrushSize() + z) != 53) + { + undo.put(this.clampY(blockPositionX - v.getBrushSize() + x, blockPositionY + i, blockPositionZ - v.getBrushSize() + z)); + } + this.setBlockIdAt(blockPositionZ - v.getBrushSize() + z, blockPositionX - v.getBrushSize() + x, blockPositionY + i, 53); + this.clampY(blockPositionX - v.getBrushSize() + x, blockPositionY + i, blockPositionZ - v.getBrushSize() + z).setPropertyId((spiral[x][i][z] - 2)); + } + else if (this.stairtype.equalsIgnoreCase("cobblestair")) + { + if (this.getBlockIdAt(blockPositionX - v.getBrushSize() + x, blockPositionY + i, blockPositionZ - v.getBrushSize() + z) != 67) + { + undo.put(this.clampY(blockPositionX - v.getBrushSize() + x, blockPositionY + i, blockPositionZ - v.getBrushSize() + z)); + } + this.setBlockIdAt(blockPositionZ - v.getBrushSize() + z, blockPositionX - v.getBrushSize() + x, blockPositionY + i, 67); + this.clampY(blockPositionX - v.getBrushSize() + x, blockPositionY + i, blockPositionZ - v.getBrushSize() + z).setPropertyId((spiral[x][i][z] - 2)); + } + break; + } + } + } + } + v.owner().storeUndo(undo); + } + + @SuppressWarnings("deprecation") + private void digStairWell(final SnipeData v, Block targetBlock) + { + if (v.getVoxelHeight() < 1) + { + v.setVoxelHeight(1); + v.sendMessage(ChatColor.RED + "VoxelHeight must be a natural number! Set to 1."); + } + + // initialize array + final int[][][] spiral = new int[2 * v.getBrushSize() + 1][v.getVoxelHeight()][2 * v.getBrushSize() + 1]; + + // locate first block in staircase + // Note to self, fix these + int startX = 0; + int startZ = 0; + int y = 0; + int xOffset = 0; + int zOffset = 0; + int toggle = 0; + + if (this.sdirect.equalsIgnoreCase("cc")) + { + if (this.sopen.equalsIgnoreCase("n")) + { + startX = 0; + startZ = 2 * v.getBrushSize(); + } + else if (this.sopen.equalsIgnoreCase("e")) + { + startX = 0; + startZ = 0; + } + else if (this.sopen.equalsIgnoreCase("s")) + { + startX = 2 * v.getBrushSize(); + startZ = 0; + } + else + { + startX = 2 * v.getBrushSize(); + startZ = 2 * v.getBrushSize(); + } + } + else + { + if (this.sopen.equalsIgnoreCase("n")) + { + startX = 0; + startZ = 0; + } + else if (this.sopen.equalsIgnoreCase("e")) + { + startX = 2 * v.getBrushSize(); + startZ = 0; + } + else if (this.sopen.equalsIgnoreCase("s")) + { + startX = 2 * v.getBrushSize(); + startZ = 2 * v.getBrushSize(); + } + else + { + startX = 0; + startZ = 2 * v.getBrushSize(); + } + } + + while (y < v.getVoxelHeight()) + { + if (this.stairtype.equalsIgnoreCase("block")) + { + // 1x1x1 voxel material steps + spiral[startX + xOffset][y][startZ + zOffset] = 1; + y++; + } + else if (this.stairtype.equalsIgnoreCase("step")) + { + // alternating step-doublestep, uses data value to determine type + switch (toggle) + { + case 0: + toggle = 2; + spiral[startX + xOffset][y][startZ + zOffset] = 2; + break; + case 1: + toggle = 2; + spiral[startX + xOffset][y][startZ + zOffset] = 2; + break; + case 2: + toggle = 1; + spiral[startX + xOffset][y][startZ + zOffset] = 1; + y++; + break; + default: + break; + } + + } + + // Adjust horizontal position and do stair-option array stuff + if (startX + xOffset == 0) + { // All North + if (startZ + zOffset == 0) + { // NORTHEAST + if (this.stairtype.equalsIgnoreCase("woodstair") || this.stairtype.equalsIgnoreCase("cobblestair")) + { + spiral[startX + xOffset][y][startZ + zOffset] = 1; + } + if (this.sdirect.equalsIgnoreCase("c")) + { + xOffset++; + } + else + { + zOffset++; + } + } + else if (startZ + zOffset == 2 * v.getBrushSize()) + { // NORTHWEST + if (this.stairtype.equalsIgnoreCase("woodstair") || this.stairtype.equalsIgnoreCase("cobblestair")) + { + spiral[startX + xOffset][y][startZ + zOffset] = 1; + } + if (this.sdirect.equalsIgnoreCase("c")) + { + zOffset--; + } + else + { + xOffset++; + } + } + else + { // JUST PLAIN NORTH + if (this.sdirect.equalsIgnoreCase("c")) + { + if (this.stairtype.equalsIgnoreCase("woodstair") || this.stairtype.equalsIgnoreCase("cobblestair")) + { + spiral[startX + xOffset][y][startZ + zOffset] = 4; + y++; + } + zOffset--; + } + else + { + if (this.stairtype.equalsIgnoreCase("woodstair") || this.stairtype.equalsIgnoreCase("cobblestair")) + { + spiral[startX + xOffset][y][startZ + zOffset] = 5; + y++; + } + zOffset++; + } + } + + } + else if (startX + xOffset == 2 * v.getBrushSize()) + { // ALL SOUTH + if (startZ + zOffset == 0) + { // SOUTHEAST + if (this.stairtype.equalsIgnoreCase("woodstair") || this.stairtype.equalsIgnoreCase("cobblestair")) + { + spiral[startX + xOffset][y][startZ + zOffset] = 1; + } + if (this.sdirect.equalsIgnoreCase("c")) + { + zOffset++; + } + else + { + xOffset--; + } + } + else if (startZ + zOffset == 2 * v.getBrushSize()) + { // SOUTHWEST + if (this.stairtype.equalsIgnoreCase("woodstair") || this.stairtype.equalsIgnoreCase("cobblestair")) + { + spiral[startX + xOffset][y][startZ + zOffset] = 1; + } + if (this.sdirect.equalsIgnoreCase("c")) + { + xOffset--; + } + else + { + zOffset--; + } + } + else + { // JUST PLAIN SOUTH + if (this.sdirect.equalsIgnoreCase("c")) + { + if (this.stairtype.equalsIgnoreCase("woodstair") || this.stairtype.equalsIgnoreCase("cobblestair")) + { + spiral[startX + xOffset][y][startZ + zOffset] = 5; + y++; + } + zOffset++; + } + else + { + if (this.stairtype.equalsIgnoreCase("woodstair") || this.stairtype.equalsIgnoreCase("cobblestair")) + { + spiral[startX + xOffset][y][startZ + zOffset] = 4; + y++; + } + zOffset--; + } + } + + } + else if (startZ + zOffset == 0) + { // JUST PLAIN EAST + if (this.sdirect.equalsIgnoreCase("c")) + { + if (this.stairtype.equalsIgnoreCase("woodstair") || this.stairtype.equalsIgnoreCase("cobblestair")) + { + spiral[startX + xOffset][y][startZ + zOffset] = 3; + y++; + } + xOffset++; + } + else + { + if (this.stairtype.equalsIgnoreCase("woodstair") || this.stairtype.equalsIgnoreCase("cobblestair")) + { + spiral[startX + xOffset][y][startZ + zOffset] = 2; + y++; + } + xOffset--; + } + } + else + { // JUST PLAIN WEST + if (this.sdirect.equalsIgnoreCase("c")) + { + if (this.stairtype.equalsIgnoreCase("woodstair") || this.stairtype.equalsIgnoreCase("cobblestair")) + { + spiral[startX + xOffset][y][startZ + zOffset] = 2; + y++; + } + xOffset--; + } + else + { + if (this.stairtype.equalsIgnoreCase("woodstair") || this.stairtype.equalsIgnoreCase("cobblestair")) + { + spiral[startX + xOffset][y][startZ + zOffset] = 3; + y++; + } + xOffset++; + } + } + + } + + final Undo undo = new Undo(); + // Make the changes + + for (int x = 2 * v.getBrushSize(); x >= 0; x--) + { + + for (int i = v.getVoxelHeight() - 1; i >= 0; i--) + { + + for (int z = 2 * v.getBrushSize(); z >= 0; z--) + { + + int blockPositionX = targetBlock.getX(); + int blockPositionY = targetBlock.getY(); + int blockPositionZ = targetBlock.getZ(); + switch (spiral[x][i][z]) + { + case 0: + if (this.getBlockIdAt(blockPositionX - v.getBrushSize() + x, blockPositionY - i, blockPositionZ - v.getBrushSize() + z) != 0) + { + undo.put(this.clampY(blockPositionX - v.getBrushSize() + x, blockPositionY - i, blockPositionZ - v.getBrushSize() + z)); + } + this.setBlockIdAt(blockPositionZ - v.getBrushSize() + z, blockPositionX - v.getBrushSize() + x, blockPositionY - i, 0); + break; + case 1: + if (this.stairtype.equalsIgnoreCase("block")) + { + if (this.getBlockIdAt(blockPositionX - v.getBrushSize() + x, blockPositionY - i, blockPositionZ - v.getBrushSize() + z) != v.getVoxelId()) + { + undo.put(this.clampY(blockPositionX - v.getBrushSize() + x, blockPositionY - i, blockPositionZ - v.getBrushSize() + z)); + } + this.setBlockIdAt(blockPositionZ - v.getBrushSize() + z, blockPositionX - v.getBrushSize() + x, blockPositionY - i, v.getVoxelId()); + } + else if (this.stairtype.equalsIgnoreCase("step")) + { + if (this.getBlockIdAt(blockPositionX - v.getBrushSize() + x, blockPositionY - i, blockPositionZ - v.getBrushSize() + z) != 44) + { + undo.put(this.clampY(blockPositionX - v.getBrushSize() + x, blockPositionY - i, blockPositionZ - v.getBrushSize() + z)); + } + this.setBlockIdAt(blockPositionZ - v.getBrushSize() + z, blockPositionX - v.getBrushSize() + x, blockPositionY - i, 44); + this.clampY(blockPositionX - v.getBrushSize() + x, blockPositionY - i, blockPositionZ - v.getBrushSize() + z).setPropertyId(v.getPropertyId()); + } + else if (this.stairtype.equalsIgnoreCase("woodstair") || this.stairtype.equalsIgnoreCase("cobblestair")) + { + if (this.getBlockIdAt(blockPositionX - v.getBrushSize() + x, blockPositionY - i, blockPositionZ - v.getBrushSize() + z) != v.getVoxelId()) + { + undo.put(this.clampY(blockPositionX - v.getBrushSize() + x, blockPositionY - i, blockPositionZ - v.getBrushSize() + z)); + } + this.setBlockIdAt(blockPositionZ - v.getBrushSize() + z, blockPositionX - v.getBrushSize() + x, blockPositionY - i, v.getVoxelId()); + } + break; + case 2: + if (this.stairtype.equalsIgnoreCase("step")) + { + if (this.getBlockIdAt(blockPositionX - v.getBrushSize() + x, blockPositionY - i, blockPositionZ - v.getBrushSize() + z) != 43) + { + undo.put(this.clampY(blockPositionX - v.getBrushSize() + x, blockPositionY - i, blockPositionZ - v.getBrushSize() + z)); + } + this.setBlockIdAt(blockPositionZ - v.getBrushSize() + z, blockPositionX - v.getBrushSize() + x, blockPositionY - i, 43); + this.clampY(blockPositionX - v.getBrushSize() + x, blockPositionY - i, blockPositionZ - v.getBrushSize() + z).setPropertyId(v.getPropertyId()); + } + else if (this.stairtype.equalsIgnoreCase("woodstair")) + { + if (this.getBlockIdAt(blockPositionX - v.getBrushSize() + x, blockPositionY - i, blockPositionZ - v.getBrushSize() + z) != 53) + { + undo.put(this.clampY(blockPositionX - v.getBrushSize() - x, blockPositionY + i, blockPositionZ - v.getBrushSize() + z)); + } + this.setBlockIdAt(blockPositionZ - v.getBrushSize() + z, blockPositionX - v.getBrushSize() + x, blockPositionY - i, 53); + this.clampY(blockPositionX - v.getBrushSize() + x, blockPositionY - i, blockPositionZ - v.getBrushSize() + z).setPropertyId( 0); + } + else if (this.stairtype.equalsIgnoreCase("cobblestair")) + { + if (this.getBlockIdAt(blockPositionX - v.getBrushSize() + x, blockPositionY - i, blockPositionZ - v.getBrushSize() + z) != 67) + { + undo.put(this.clampY(blockPositionX - v.getBrushSize() + x, blockPositionY - i, blockPositionZ - v.getBrushSize() + z)); + } + this.setBlockIdAt(blockPositionZ - v.getBrushSize() + z, blockPositionX - v.getBrushSize() + x, blockPositionY - i, 67); + this.clampY(blockPositionX - v.getBrushSize() + x, blockPositionY - i, blockPositionZ - v.getBrushSize() + z).setPropertyId( 0); + } + break; + default: + if (this.stairtype.equalsIgnoreCase("woodstair")) + { + if (this.getBlockIdAt(blockPositionX - v.getBrushSize() + x, blockPositionY - i, blockPositionZ - v.getBrushSize() + z) != 53) + { + undo.put(this.clampY(blockPositionX - v.getBrushSize() + x, blockPositionY - i, blockPositionZ - v.getBrushSize() + z)); + } + this.setBlockIdAt(blockPositionZ - v.getBrushSize() + z, blockPositionX - v.getBrushSize() + x, blockPositionY - i, 53); + this.clampY(blockPositionX - v.getBrushSize() + x, blockPositionY - i, blockPositionZ - v.getBrushSize() + z).setPropertyId((spiral[x][i][z] - 2)); + } + else if (this.stairtype.equalsIgnoreCase("cobblestair")) + { + if (this.getBlockIdAt(blockPositionX - v.getBrushSize() + x, blockPositionY - i, blockPositionZ - v.getBrushSize() + z) != 67) + { + undo.put(this.clampY(blockPositionX - v.getBrushSize() + x, blockPositionY - i, blockPositionZ - v.getBrushSize() + z)); + } + this.setBlockIdAt(blockPositionZ - v.getBrushSize() + z, blockPositionX - v.getBrushSize() + x, blockPositionY - i, 67); + this.clampY(blockPositionX - v.getBrushSize() + x, blockPositionY - i, blockPositionZ - v.getBrushSize() + z).setPropertyId((spiral[x][i][z] - 2)); + } + break; + } + } + } + } + v.owner().storeUndo(undo); + } + + @Override + protected final void arrow(final SnipeData v) + { + this.digStairWell(v, this.getTargetBlock()); // make stairwell below target + } + + @Override + protected final void powder(final SnipeData v) + { + this.buildStairWell(v, this.getLastBlock()); // make stairwell above target + } + + @Override + public final void info(final Message vm) + { + vm.brushName("Spiral Staircase"); + vm.size(); + vm.voxel(); + vm.height(); + vm.data(); + vm.custom(ChatColor.BLUE + "Staircase type: " + this.stairtype); + vm.custom(ChatColor.BLUE + "Staircase turns: " + this.sdirect); + vm.custom(ChatColor.BLUE + "Staircase opens: " + this.sopen); + } + + @Override + public final void parameters(final String[] par, final SnipeData v) + { + if (par[1].equalsIgnoreCase("info")) + { + v.sendMessage(ChatColor.GOLD + "Spiral Staircase Parameters:"); + v.sendMessage(ChatColor.AQUA + "/b sstair 'block' (default) | 'step' | 'woodstair' | 'cobblestair' -- set the type of staircase"); + v.sendMessage(ChatColor.AQUA + "/b sstair 'c' (default) | 'cc' -- set the turning direction of staircase"); + v.sendMessage(ChatColor.AQUA + "/b sstair 'n' (default) | 'e' | 's' | 'world' -- set the opening direction of staircase"); + return; + } + + for (int i = 1; i < par.length; i++) + { + if (par[i].equalsIgnoreCase("block") || par[i].equalsIgnoreCase("step") || par[i].equalsIgnoreCase("woodstair") || par[i].equalsIgnoreCase("cobblestair")) + { + this.stairtype = par[i]; + v.sendMessage(ChatColor.BLUE + "Staircase type: " + this.stairtype); + } + else if (par[i].equalsIgnoreCase("c") || par[i].equalsIgnoreCase("cc")) + { + this.sdirect = par[i]; + v.sendMessage(ChatColor.BLUE + "Staircase turns: " + this.sdirect); + } + else if (par[i].equalsIgnoreCase("n") || par[i].equalsIgnoreCase("e") || par[i].equalsIgnoreCase("s") || par[i].equalsIgnoreCase("world")) + { + this.sopen = par[i]; + v.sendMessage(ChatColor.BLUE + "Staircase opens: " + this.sopen); + } + else + { + v.sendMessage(ChatColor.RED + "Invalid brush parameters! use the info parameter to display parameter info."); + } + } + } + + @Override + public String getPermissionNode() + { + return "voxelsniper.brush.spiralstaircase"; + } +} diff --git a/favs/src/main/java/com/thevoxelbox/voxelsniper/brush/SplatterBallBrush.java b/favs/src/main/java/com/thevoxelbox/voxelsniper/brush/SplatterBallBrush.java new file mode 100644 index 000000000..ec13e95c7 --- /dev/null +++ b/favs/src/main/java/com/thevoxelbox/voxelsniper/brush/SplatterBallBrush.java @@ -0,0 +1,284 @@ +package com.thevoxelbox.voxelsniper.brush; + +import com.boydti.fawe.bukkit.wrapper.AsyncBlock; +import com.thevoxelbox.voxelsniper.Message; +import com.thevoxelbox.voxelsniper.SnipeData; +import com.thevoxelbox.voxelsniper.brush.perform.PerformBrush; +import org.bukkit.ChatColor; +import org.bukkit.block.Block; + +import java.util.Random; + +/** + * http://www.voxelwiki.com/minecraft/Voxelsniper#Splatter_Brushes + * + * @author Voxel + */ +public class SplatterBallBrush extends PerformBrush +{ + private static final int GROW_PERCENT_MIN = 1; + private static final int GROW_PERCENT_DEFAULT = 1000; + private static final int GROW_PERCENT_MAX = 9999; + private static final int SEED_PERCENT_MIN = 1; + private static final int SEED_PERCENT_DEFAULT = 1000; + private static final int SEED_PERCENT_MAX = 9999; + private static final int SPLATREC_PERCENT_MIN = 1; + private static final int SPLATREC_PERCENT_DEFAULT = 3; + private static final int SPLATREC_PERCENT_MAX = 10; + private int seedPercent; // Chance block on first pass is made active + private int growPercent; // chance block on recursion pass is made active + private int splatterRecursions; // How many times you grow the seeds + private Random generator = new Random(); + + /** + * + */ + public SplatterBallBrush() + { + this.setName("Splatter Ball"); + } + + private void splatterBall(final SnipeData v, AsyncBlock targetBlock) + { + if (this.seedPercent < SEED_PERCENT_MIN || this.seedPercent > SEED_PERCENT_MAX) + { + v.owner().getPlayer().sendMessage(ChatColor.BLUE + "Seed percent set to: 10%"); + this.seedPercent = SEED_PERCENT_DEFAULT; + } + if (this.growPercent < GROW_PERCENT_MIN || this.growPercent > GROW_PERCENT_MAX) + { + v.owner().getPlayer().sendMessage(ChatColor.BLUE + "Growth percent set to: 10%"); + this.growPercent = GROW_PERCENT_DEFAULT; + } + if (this.splatterRecursions < SPLATREC_PERCENT_MIN || this.splatterRecursions > SPLATREC_PERCENT_MAX) + { + v.owner().getPlayer().sendMessage(ChatColor.BLUE + "Recursions set to: 3"); + this.splatterRecursions = SPLATREC_PERCENT_DEFAULT; + } + + final int[][][] splat = new int[2 * v.getBrushSize() + 1][2 * v.getBrushSize() + 1][2 * v.getBrushSize() + 1]; + + // Seed the array + for (int x = 2 * v.getBrushSize(); x >= 0; x--) + { + for (int y = 2 * v.getBrushSize(); y >= 0; y--) + { + for (int z = 2 * v.getBrushSize(); z >= 0; z--) + { + if (this.generator.nextInt(SEED_PERCENT_MAX + 1) <= this.seedPercent) + { + splat[x][y][z] = 1; + } + } + } + } + // Grow the seeds + final int gref = this.growPercent; + final int[][][] tempSplat = new int[2 * v.getBrushSize() + 1][2 * v.getBrushSize() + 1][2 * v.getBrushSize() + 1]; + int growcheck; + + for (int r = 0; r < this.splatterRecursions; r++) + { + this.growPercent = gref - ((gref / this.splatterRecursions) * (r)); + for (int x = 2 * v.getBrushSize(); x >= 0; x--) + { + for (int y = 2 * v.getBrushSize(); y >= 0; y--) + { + for (int z = 2 * v.getBrushSize(); z >= 0; z--) + { + tempSplat[x][y][z] = splat[x][y][z]; // prime tempsplat + + growcheck = 0; + if (splat[x][y][z] == 0) + { + if (x != 0 && splat[x - 1][y][z] == 1) + { + growcheck++; + } + if (y != 0 && splat[x][y - 1][z] == 1) + { + growcheck++; + } + if (z != 0 && splat[x][y][z - 1] == 1) + { + growcheck++; + } + if (x != 2 * v.getBrushSize() && splat[x + 1][y][z] == 1) + { + growcheck++; + } + if (y != 2 * v.getBrushSize() && splat[x][y + 1][z] == 1) + { + growcheck++; + } + if (z != 2 * v.getBrushSize() && splat[x][y][z + 1] == 1) + { + growcheck++; + } + } + + if (growcheck >= GROW_PERCENT_MIN && this.generator.nextInt(GROW_PERCENT_MAX + 1) <= this.growPercent) + { + tempSplat[x][y][z] = 1; // prevent bleed into splat + } + + } + } + } + // integrate tempsplat back into splat at end of iteration + for (int x = 2 * v.getBrushSize(); x >= 0; x--) + { + for (int y = 2 * v.getBrushSize(); y >= 0; y--) + { + for (int z = 2 * v.getBrushSize(); z >= 0; z--) + { + splat[x][y][z] = tempSplat[x][y][z]; + } + } + } + } + this.growPercent = gref; + // Fill 1x1x1 holes + for (int x = 2 * v.getBrushSize(); x >= 0; x--) + { + for (int y = 2 * v.getBrushSize(); y >= 0; y--) + { + for (int z = 2 * v.getBrushSize(); z >= 0; z--) + { + if (splat[Math.max(x - 1, 0)][y][z] == 1 && splat[Math.min(x + 1, 2 * v.getBrushSize())][y][z] == 1 && splat[x][Math.max(0, y - 1)][z] == 1 && splat[x][Math.min(2 * v.getBrushSize(), y + 1)][z] == 1) + { + splat[x][y][z] = 1; + } + } + } + } + + // Make the changes + final double rSquared = Math.pow(v.getBrushSize() + 1, 2); + + for (int x = 2 * v.getBrushSize(); x >= 0; x--) + { + final double xSquared = Math.pow(x - v.getBrushSize() - 1, 2); + + for (int y = 2 * v.getBrushSize(); y >= 0; y--) + { + final double ySquared = Math.pow(y - v.getBrushSize() - 1, 2); + + for (int z = 2 * v.getBrushSize(); z >= 0; z--) + { + if (splat[x][y][z] == 1 && xSquared + ySquared + Math.pow(z - v.getBrushSize() - 1, 2) <= rSquared) + { + current.perform(targetBlock.getRelative(-v.getBrushSize() + x, -v.getBrushSize() + y, -v.getBrushSize() + z)); + } + } + } + } + + v.owner().storeUndo(this.current.getUndo()); + } + + @Override + protected final void arrow(final SnipeData v) + { + this.splatterBall(v, this.getTargetBlock()); + } + + @Override + protected final void powder(final SnipeData v) + { + this.splatterBall(v, this.getLastBlock()); + } + + @Override + public final void info(final Message vm) + { + if (this.seedPercent < SEED_PERCENT_MIN || this.seedPercent > SEED_PERCENT_MAX) + { + this.seedPercent = SEED_PERCENT_DEFAULT; + } + if (this.growPercent < GROW_PERCENT_MIN || this.growPercent > GROW_PERCENT_MAX) + { + this.growPercent = GROW_PERCENT_DEFAULT; + } + if (this.splatterRecursions < SPLATREC_PERCENT_MIN || this.splatterRecursions > SPLATREC_PERCENT_MAX) + { + this.splatterRecursions = SPLATREC_PERCENT_DEFAULT; + } + vm.brushName("Splatter Ball"); + vm.size(); + vm.custom(ChatColor.BLUE + "Seed percent set to: " + this.seedPercent / 100 + "%"); + vm.custom(ChatColor.BLUE + "Growth percent set to: " + this.growPercent / 100 + "%"); + vm.custom(ChatColor.BLUE + "Recursions set to: " + this.splatterRecursions); + + } + + @Override + public final void parameters(final String[] par, final SnipeData v) + { + for (int i = 1; i < par.length; i++) + { + final String parameter = par[i]; + + if (parameter.equalsIgnoreCase("info")) + { + v.sendMessage(ChatColor.GOLD + "Splatter Ball brush Parameters:"); + v.sendMessage(ChatColor.AQUA + "/b sb s[int] -- set a seed percentage (1-9999). 100 = 1% Default is 1000"); + v.sendMessage(ChatColor.AQUA + "/b sb g[int] -- set a growth percentage (1-9999). Default is 1000"); + v.sendMessage(ChatColor.AQUA + "/b sb r[int] -- set a recursion (1-10). Default is 3"); + return; + } + else if (parameter.startsWith("s")) + { + final double temp = Integer.parseInt(parameter.replace("s", "")); + + if (temp >= SEED_PERCENT_MIN && temp <= SEED_PERCENT_MAX) + { + v.sendMessage(ChatColor.AQUA + "Seed percent set to: " + temp / 100 + "%"); + this.seedPercent = (int) temp; + } + else + { + v.sendMessage(ChatColor.RED + "Seed percent must be an integer 1-9999!"); + } + } + else if (parameter.startsWith("g")) + { + final double temp = Integer.parseInt(parameter.replace("g", "")); + + if (temp >= GROW_PERCENT_MIN && temp <= GROW_PERCENT_MAX) + { + v.sendMessage(ChatColor.AQUA + "Growth percent set to: " + temp / 100 + "%"); + this.growPercent = (int) temp; + } + else + { + v.sendMessage(ChatColor.RED + "Growth percent must be an integer 1-9999!"); + } + } + else if (parameter.startsWith("r")) + { + final int temp = Integer.parseInt(parameter.replace("r", "")); + + if (temp >= SPLATREC_PERCENT_MIN && temp <= SPLATREC_PERCENT_MAX) + { + v.sendMessage(ChatColor.AQUA + "Recursions set to: " + temp); + this.splatterRecursions = temp; + } + else + { + v.sendMessage(ChatColor.RED + "Recursions must be an integer 1-10!"); + } + } + else + { + v.sendMessage(ChatColor.RED + "Invalid brush parameters! use the info parameter to display parameter info."); + } + } + } + + @Override + public String getPermissionNode() + { + return "voxelsniper.brush.splatterball"; + } +} diff --git a/favs/src/main/java/com/thevoxelbox/voxelsniper/brush/SplatterDiscBrush.java b/favs/src/main/java/com/thevoxelbox/voxelsniper/brush/SplatterDiscBrush.java new file mode 100644 index 000000000..c67d1e094 --- /dev/null +++ b/favs/src/main/java/com/thevoxelbox/voxelsniper/brush/SplatterDiscBrush.java @@ -0,0 +1,253 @@ +package com.thevoxelbox.voxelsniper.brush; + +import com.boydti.fawe.bukkit.wrapper.AsyncBlock; +import com.thevoxelbox.voxelsniper.Message; +import com.thevoxelbox.voxelsniper.SnipeData; +import com.thevoxelbox.voxelsniper.brush.perform.PerformBrush; +import org.bukkit.ChatColor; +import org.bukkit.block.Block; + +import java.util.Random; + +/** + * http://www.voxelwiki.com/minecraft/Voxelsniper#Splatter_Brushes + * + * @author Voxel + */ +public class SplatterDiscBrush extends PerformBrush +{ + private static final int GROW_PERCENT_MIN = 1; + private static final int GROW_PERCENT_DEFAULT = 1000; + private static final int GROW_PERCENT_MAX = 9999; + private static final int SEED_PERCENT_MIN = 1; + private static final int SEED_PERCENT_DEFAULT = 1000; + private static final int SEED_PERCENT_MAX = 9999; + private static final int SPLATREC_PERCENT_MIN = 1; + private static final int SPLATREC_PERCENT_DEFAULT = 3; + private static final int SPLATREC_PERCENT_MAX = 10; + private int seedPercent; // Chance block on first pass is made active + private int growPercent; // chance block on recursion pass is made active + private int splatterRecursions; // How many times you grow the seeds + private Random generator = new Random(); + + /** + * + */ + public SplatterDiscBrush() + { + this.setName("Splatter Disc"); + } + + private void splatterDisc(final SnipeData v, AsyncBlock targetBlock) + { + if (this.seedPercent < SEED_PERCENT_MIN || this.seedPercent > SEED_PERCENT_MAX) + { + v.sendMessage(ChatColor.BLUE + "Seed percent set to: 10%"); + this.seedPercent = SEED_PERCENT_DEFAULT; + } + if (this.growPercent < GROW_PERCENT_MIN || this.growPercent > GROW_PERCENT_MAX) + { + v.sendMessage(ChatColor.BLUE + "Growth percent set to: 10%"); + this.growPercent = GROW_PERCENT_DEFAULT; + } + if (this.splatterRecursions < SPLATREC_PERCENT_MIN || this.splatterRecursions > SPLATREC_PERCENT_MAX) + { + v.sendMessage(ChatColor.BLUE + "Recursions set to: 3"); + this.splatterRecursions = SPLATREC_PERCENT_DEFAULT; + } + final int[][] splat = new int[2 * v.getBrushSize() + 1][2 * v.getBrushSize() + 1]; + + // Seed the array + for (int x = 2 * v.getBrushSize(); x >= 0; x--) + { + for (int y = 2 * v.getBrushSize(); y >= 0; y--) + { + + if (this.generator.nextInt(SEED_PERCENT_MAX + 1) <= this.seedPercent) + { + splat[x][y] = 1; + + } + } + } + // Grow the seeds + final int gref = this.growPercent; + int growcheck; + final int[][] tempSplat = new int[2 * v.getBrushSize() + 1][2 * v.getBrushSize() + 1]; + for (int r = 0; r < this.splatterRecursions; r++) + { + + this.growPercent = gref - ((gref / this.splatterRecursions) * (r)); + for (int x = 2 * v.getBrushSize(); x >= 0; x--) + { + for (int y = 2 * v.getBrushSize(); y >= 0; y--) + { + tempSplat[x][y] = splat[x][y]; // prime tempsplat + + growcheck = 0; + if (splat[x][y] == 0) + { + if (x != 0 && splat[x - 1][y] == 1) + { + growcheck++; + } + if (y != 0 && splat[x][y - 1] == 1) + { + growcheck++; + } + if (x != 2 * v.getBrushSize() && splat[x + 1][y] == 1) + { + growcheck++; + } + if (y != 2 * v.getBrushSize() && splat[x][y + 1] == 1) + { + growcheck++; + } + } + + if (growcheck >= 1 && this.generator.nextInt(GROW_PERCENT_MAX + 1) <= this.growPercent) + { + tempSplat[x][y] = 1; // prevent bleed into splat + } + } + } + + // integrate tempsplat back into splat at end of iteration + for (int x = 2 * v.getBrushSize(); x >= 0; x--) + { + for (int y = 2 * v.getBrushSize(); y >= 0; y--) + { + splat[x][y] = tempSplat[x][y]; + } + } + } + this.growPercent = gref; + // Fill 1x1 holes + for (int x = 2 * v.getBrushSize(); x >= 0; x--) + { + for (int y = 2 * v.getBrushSize(); y >= 0; y--) + { + if (splat[Math.max(x - 1, 0)][y] == 1 && splat[Math.min(x + 1, 2 * v.getBrushSize())][y] == 1 && splat[x][Math.max(0, y - 1)] == 1 && splat[x][Math.min(2 * v.getBrushSize(), y + 1)] == 1) + { + splat[x][y] = 1; + } + } + } + + // Make the changes + final double rSquared = Math.pow(v.getBrushSize() + 1, 2); + for (int x = 2 * v.getBrushSize(); x >= 0; x--) + { + final double xSquared = Math.pow(x - v.getBrushSize() - 1, 2); + for (int y = 2 * v.getBrushSize(); y >= 0; y--) + { + if (splat[x][y] == 1 && xSquared + Math.pow(y - v.getBrushSize() - 1, 2) <= rSquared) + { + current.perform(targetBlock.getRelative(x - v.getBrushSize(), 0, y - v.getBrushSize())); + } + } + } + v.owner().storeUndo(this.current.getUndo()); + } + + @Override + protected final void arrow(final SnipeData v) + { + this.splatterDisc(v, this.getTargetBlock()); + } + + @Override + protected final void powder(final SnipeData v) + { + this.splatterDisc(v, this.getLastBlock()); + } + + @Override + public final void info(final Message vm) + { + if (this.seedPercent < SEED_PERCENT_MIN || this.seedPercent > SEED_PERCENT_MAX) + { + this.seedPercent = SEED_PERCENT_DEFAULT; + } + if (this.growPercent < GROW_PERCENT_MIN || this.growPercent > GROW_PERCENT_MAX) + { + this.growPercent = GROW_PERCENT_DEFAULT; + } + if (this.splatterRecursions < SPLATREC_PERCENT_MIN || this.splatterRecursions > SPLATREC_PERCENT_MAX) + { + this.splatterRecursions = SPLATREC_PERCENT_DEFAULT; + } + vm.brushName("Splatter Disc"); + vm.size(); + vm.custom(ChatColor.BLUE + "Seed percent set to: " + this.seedPercent / 100 + "%"); + vm.custom(ChatColor.BLUE + "Growth percent set to: " + this.growPercent / 100 + "%"); + vm.custom(ChatColor.BLUE + "Recursions set to: " + this.splatterRecursions); + } + + @Override + public final void parameters(final String[] par, final SnipeData v) + { + for (int i = 1; i < par.length; i++) + { + final String parameter = par[i]; + + if (parameter.equalsIgnoreCase("info")) + { + v.sendMessage(ChatColor.GOLD + "Splatter Disc brush Parameters:"); + v.sendMessage(ChatColor.AQUA + "/b sd s[int] -- set a seed percentage (1-9999). 100 = 1% Default is 1000"); + v.sendMessage(ChatColor.AQUA + "/b sd g[int] -- set a growth percentage (1-9999). Default is 1000"); + v.sendMessage(ChatColor.AQUA + "/b sd r[int] -- set a recursion (1-10). Default is 3"); + return; + } + else if (parameter.startsWith("s")) + { + final double temp = Integer.parseInt(parameter.replace("s", "")); + if (temp >= SEED_PERCENT_MIN && temp <= SEED_PERCENT_MAX) + { + v.sendMessage(ChatColor.AQUA + "Seed percent set to: " + temp / 100 + "%"); + this.seedPercent = (int) temp; + } + else + { + v.sendMessage(ChatColor.RED + "Seed percent must be an integer 1-9999!"); + } + } + else if (parameter.startsWith("g")) + { + final double temp = Integer.parseInt(parameter.replace("g", "")); + if (temp >= GROW_PERCENT_MIN && temp <= GROW_PERCENT_MAX) + { + v.sendMessage(ChatColor.AQUA + "Growth percent set to: " + temp / 100 + "%"); + this.growPercent = (int) temp; + } + else + { + v.sendMessage(ChatColor.RED + "Growth percent must be an integer 1-9999!"); + } + } + else if (parameter.startsWith("r")) + { + final int temp = Integer.parseInt(parameter.replace("r", "")); + if (temp >= SPLATREC_PERCENT_MIN && temp <= SPLATREC_PERCENT_MAX) + { + v.sendMessage(ChatColor.AQUA + "Recursions set to: " + temp); + this.splatterRecursions = temp; + } + else + { + v.sendMessage(ChatColor.RED + "Recursions must be an integer 1-10!"); + } + } + else + { + v.sendMessage(ChatColor.RED + "Invalid brush parameters! use the info parameter to display parameter info."); + } + } + } + + @Override + public String getPermissionNode() + { + return "voxelsniper.brush.splatterdisc"; + } +} diff --git a/favs/src/main/java/com/thevoxelbox/voxelsniper/brush/SplatterOverlayBrush.java b/favs/src/main/java/com/thevoxelbox/voxelsniper/brush/SplatterOverlayBrush.java new file mode 100644 index 000000000..3ec799c6a --- /dev/null +++ b/favs/src/main/java/com/thevoxelbox/voxelsniper/brush/SplatterOverlayBrush.java @@ -0,0 +1,453 @@ +package com.thevoxelbox.voxelsniper.brush; + +import com.sk89q.worldedit.blocks.BlockMaterial; +import com.sk89q.worldedit.world.block.BlockTypes; +import com.thevoxelbox.voxelsniper.Message; +import com.thevoxelbox.voxelsniper.SnipeData; +import com.thevoxelbox.voxelsniper.brush.perform.PerformBrush; +import org.bukkit.ChatColor; + +import java.util.Random; + +/** + * http://www.voxelwiki.com/minecraft/Voxelsniper#Splatter_Overlay_Brush + * + * @author Gavjenks Splatterized blockPositionY Giltwist + */ +public class SplatterOverlayBrush extends PerformBrush +{ + private static final int GROW_PERCENT_MIN = 1; + private static final int GROW_PERCENT_DEFAULT = 1000; + private static final int GROW_PERCENT_MAX = 9999; + private static final int SEED_PERCENT_MIN = 1; + private static final int SEED_PERCENT_DEFAULT = 1000; + private static final int SEED_PERCENT_MAX = 9999; + private static final int SPLATREC_PERCENT_MIN = 1; + private static final int SPLATREC_PERCENT_DEFAULT = 3; + private static final int SPLATREC_PERCENT_MAX = 10; + private int seedPercent; // Chance block on first pass is made active + private int growPercent; // chance block on recursion pass is made active + private int splatterRecursions; // How many times you grow the seeds + private int yOffset = 0; + private boolean randomizeHeight = false; + private Random generator = new Random(); + private int depth = 3; + private boolean allBlocks = false; + + /** + * + */ + public SplatterOverlayBrush() + { + this.setName("Splatter Overlay"); + } + + @SuppressWarnings("deprecation") + private void sOverlay(final SnipeData v) + { + + // Splatter Time + final int[][] splat = new int[2 * v.getBrushSize() + 1][2 * v.getBrushSize() + 1]; + // Seed the array + for (int x = 2 * v.getBrushSize(); x >= 0; x--) + { + for (int y = 2 * v.getBrushSize(); y >= 0; y--) + { + if (this.generator.nextInt(SEED_PERCENT_MAX + 1) <= this.seedPercent) + { + splat[x][y] = 1; + } + } + } + // Grow the seeds + final int gref = this.growPercent; + final int[][] tempSplat = new int[2 * v.getBrushSize() + 1][2 * v.getBrushSize() + 1]; + int growcheck; + + for (int r = 0; r < this.splatterRecursions; r++) + { + this.growPercent = gref - ((gref / this.splatterRecursions) * (r)); + for (int x = 2 * v.getBrushSize(); x >= 0; x--) + { + for (int y = 2 * v.getBrushSize(); y >= 0; y--) + { + tempSplat[x][y] = splat[x][y]; // prime tempsplat + + growcheck = 0; + if (splat[x][y] == 0) + { + if (x != 0 && splat[x - 1][y] == 1) + { + growcheck++; + } + if (y != 0 && splat[x][y - 1] == 1) + { + growcheck++; + } + if (x != 2 * v.getBrushSize() && splat[x + 1][y] == 1) + { + growcheck++; + } + if (y != 2 * v.getBrushSize() && splat[x][y + 1] == 1) + { + growcheck++; + } + } + + if (growcheck >= 1 && this.generator.nextInt(GROW_PERCENT_MAX + 1) <= this.growPercent) + { + tempSplat[x][y] = 1; // prevent bleed into splat + } + } + } + // integrate tempsplat back into splat at end of iteration + for (int x = 2 * v.getBrushSize(); x >= 0; x--) + { + for (int y = 2 * v.getBrushSize(); y >= 0; y--) + { + splat[x][y] = tempSplat[x][y]; + } + } + } + this.growPercent = gref; + + final int[][] memory = new int[2 * v.getBrushSize() + 1][2 * v.getBrushSize() + 1]; + final double brushSizeSquared = Math.pow(v.getBrushSize() + 0.5, 2); + + for (int z = v.getBrushSize(); z >= -v.getBrushSize(); z--) + { + for (int x = v.getBrushSize(); x >= -v.getBrushSize(); x--) + { + for (int y = this.getTargetBlock().getY(); y > 0; y--) + { + // start scanning from the height you clicked at + if (memory[x + v.getBrushSize()][z + v.getBrushSize()] != 1) + { + // if haven't already found the surface in this column + if ((Math.pow(x, 2) + Math.pow(z, 2)) <= brushSizeSquared && splat[x + v.getBrushSize()][z + v.getBrushSize()] == 1) + { + // if inside of the column && if to be splattered + final int check = this.getBlockIdAt(this.getTargetBlock().getX() + x, y + 1, this.getTargetBlock().getZ() + z); + if (check == 0 || check == 8 || check == 9) + { + // must start at surface... this prevents it filling stuff in if you click in a wall + // and it starts out below surface. + if (!this.allBlocks) + { + // if the override parameter has not been activated, go to the switch that filters out manmade stuff. + BlockTypes type = BlockTypes.get(this.getBlockIdAt(this.getTargetBlock().getX() + x, y, this.getTargetBlock().getZ() + z)); + BlockMaterial mat = type.getMaterial(); + if (mat.isSolid() && mat.isFullCube() && !mat.hasContainer()) { + final int depth = randomizeHeight ? generator.nextInt(this.depth) : this.depth; + + for (int d = this.depth - 1; ((this.depth - d) <= depth); d--) { + if (this.clampY(this.getTargetBlock().getX() + x, y - d, this.getTargetBlock().getZ() + z).getTypeId() != 0) { + // fills down as many layers as you specify in parameters + this.current.perform(this.clampY(this.getTargetBlock().getX() + x, y - d + yOffset, this.getTargetBlock().getZ() + z)); + // stop it from checking any other blocks in this vertical 1x1 column. + memory[x + v.getBrushSize()][z + v.getBrushSize()] = 1; + } + } + continue; + } else { + continue; + } + } + else + { + final int depth = randomizeHeight ? generator.nextInt(this.depth) : this.depth; + for (int d = this.depth - 1; ((this.depth - d) <= depth); d--) + { + if (this.clampY(this.getTargetBlock().getX() + x, y - d, this.getTargetBlock().getZ() + z).getTypeId() != 0) + { + // fills down as many layers as you specify in parameters + this.current.perform(this.clampY(this.getTargetBlock().getX() + x, y - d + yOffset, this.getTargetBlock().getZ() + z)); + // stop it from checking any other blocks in this vertical 1x1 column. + memory[x + v.getBrushSize()][z + v.getBrushSize()] = 1; + } + } + } + } + } + } + } + } + } + + v.owner().storeUndo(this.current.getUndo()); + } + + private void soverlayTwo(final SnipeData v) + { + // Splatter Time + final int[][] splat = new int[2 * v.getBrushSize() + 1][2 * v.getBrushSize() + 1]; + // Seed the array + for (int x = 2 * v.getBrushSize(); x >= 0; x--) + { + for (int y = 2 * v.getBrushSize(); y >= 0; y--) + { + if (this.generator.nextInt(SEED_PERCENT_MAX + 1) <= this.seedPercent) + { + splat[x][y] = 1; + } + } + } + // Grow the seeds + final int gref = this.growPercent; + final int[][] tempsplat = new int[2 * v.getBrushSize() + 1][2 * v.getBrushSize() + 1]; + int growcheck; + + for (int r = 0; r < this.splatterRecursions; r++) + { + this.growPercent = gref - ((gref / this.splatterRecursions) * (r)); + + for (int x = 2 * v.getBrushSize(); x >= 0; x--) + { + for (int y = 2 * v.getBrushSize(); y >= 0; y--) + { + tempsplat[x][y] = splat[x][y]; // prime tempsplat + + growcheck = 0; + if (splat[x][y] == 0) + { + if (x != 0 && splat[x - 1][y] == 1) + { + growcheck++; + } + if (y != 0 && splat[x][y - 1] == 1) + { + growcheck++; + } + if (x != 2 * v.getBrushSize() && splat[x + 1][y] == 1) + { + growcheck++; + } + if (y != 2 * v.getBrushSize() && splat[x][y + 1] == 1) + { + growcheck++; + } + } + + if (growcheck >= 1 && this.generator.nextInt(GROW_PERCENT_MAX + 1) <= this.growPercent) + { + tempsplat[x][y] = 1; // prevent bleed into splat + } + + } + + } + // integrate tempsplat back into splat at end of iteration + for (int x = 2 * v.getBrushSize(); x >= 0; x--) + { + for (int y = 2 * v.getBrushSize(); y >= 0; y--) + { + splat[x][y] = tempsplat[x][y]; + } + } + } + this.growPercent = gref; + + final int[][] memory = new int[v.getBrushSize() * 2 + 1][v.getBrushSize() * 2 + 1]; + final double brushSizeSquared = Math.pow(v.getBrushSize() + 0.5, 2); + + for (int z = v.getBrushSize(); z >= -v.getBrushSize(); z--) + { + for (int x = v.getBrushSize(); x >= -v.getBrushSize(); x--) + { + for (int y = this.getTargetBlock().getY(); y > 0; y--) + { // start scanning from the height you clicked at + if (memory[x + v.getBrushSize()][z + v.getBrushSize()] != 1) + { // if haven't already found the surface in this column + if ((Math.pow(x, 2) + Math.pow(z, 2)) <= brushSizeSquared && splat[x + v.getBrushSize()][z + v.getBrushSize()] == 1) + { // if inside of the column...&& if to be splattered + if (this.getBlockIdAt(this.getTargetBlock().getX() + x, y - 1, this.getTargetBlock().getZ() + z) != 0) + { // if not a floating block (like one of Notch'world pools) + if (this.getBlockIdAt(this.getTargetBlock().getX() + x, y + 1, this.getTargetBlock().getZ() + z) == 0) + { // must start at surface... this prevents it filling stuff in if + // you click in a wall and it starts out below surface. + if (!this.allBlocks) + { // if the override parameter has not been activated, go to the switch that filters out manmade stuff. + + BlockTypes type = BlockTypes.get(this.getBlockIdAt(this.getTargetBlock().getX() + x, y, this.getTargetBlock().getZ() + z)); + BlockMaterial mat = type.getMaterial(); + if (mat.isSolid() && mat.isFullCube() && !mat.hasContainer()) + { + final int depth = randomizeHeight ? generator.nextInt(this.depth) : this.depth; + for (int d = 1; (d < depth + 1); d++) { + this.current.perform(this.clampY(this.getTargetBlock().getX() + x, y + d + yOffset, this.getTargetBlock().getZ() + z)); // fills down as many layers as you specify + // in parameters + memory[x + v.getBrushSize()][z + v.getBrushSize()] = 1; // stop it from checking any other blocks in this vertical 1x1 column. + } + continue; + } else { + continue; + } + } + else + { + final int depth = randomizeHeight ? generator.nextInt(this.depth) : this.depth; + for (int d = 1; (d < depth + 1); d++) + { + this.current.perform(this.clampY(this.getTargetBlock().getX() + x, y + d + yOffset, this.getTargetBlock().getZ() + z)); // fills down as many layers as you specify in + // parameters + memory[x + v.getBrushSize()][z + v.getBrushSize()] = 1; // stop it from checking any other blocks in this vertical 1x1 column. + } + } + } + } + } + } + } + } + } + + v.owner().storeUndo(this.current.getUndo()); + } + + @Override + protected final void arrow(final SnipeData v) + { + this.sOverlay(v); + } + + @Override + protected final void powder(final SnipeData v) + { + this.soverlayTwo(v); + } + + @Override + public final void info(final Message vm) + { + if (this.seedPercent < SEED_PERCENT_MIN || this.seedPercent > SEED_PERCENT_MAX) + { + this.seedPercent = SEED_PERCENT_DEFAULT; + } + if (this.growPercent < GROW_PERCENT_MIN || this.growPercent > GROW_PERCENT_MAX) + { + this.growPercent = GROW_PERCENT_DEFAULT; + } + if (this.splatterRecursions < SPLATREC_PERCENT_MIN || this.splatterRecursions > SPLATREC_PERCENT_MAX) + { + this.splatterRecursions = SPLATREC_PERCENT_DEFAULT; + } + vm.brushName(this.getName()); + vm.size(); + vm.custom(ChatColor.BLUE + "Seed percent set to: " + this.seedPercent / 100 + "%"); + vm.custom(ChatColor.BLUE + "Growth percent set to: " + this.growPercent / 100 + "%"); + vm.custom(ChatColor.BLUE + "Recursions set to: " + this.splatterRecursions); + vm.custom(ChatColor.BLUE + "Y-Offset set to: " + this.yOffset); + } + + @Override + public final void parameters(final String[] par, final SnipeData v) + { + for (int i = 1; i < par.length; i++) + { + final String parameter = par[i]; + try + { + if (parameter.equalsIgnoreCase("info")) + { + v.sendMessage(ChatColor.GOLD + "Splatter Overlay brush parameters:"); + v.sendMessage(ChatColor.AQUA + "d[number] (ex: d3) How many blocks deep you want to replace from the surface."); + v.sendMessage(ChatColor.BLUE + "all (ex: /b over all) Sets the brush to overlay over ALL materials, not just natural surface ones (will no longer ignore trees and buildings). The parameter /some will set it back to default."); + v.sendMessage(ChatColor.AQUA + "/b sover s[int] -- set a seed percentage (1-9999). 100 = 1% Default is 1000"); + v.sendMessage(ChatColor.AQUA + "/b sover g[int] -- set a growth percentage (1-9999). Default is 1000"); + v.sendMessage(ChatColor.AQUA + "/b sover r[int] -- set a recursion (1-10). Default is 3"); + return; + } + else if (parameter.startsWith("d")) + { + this.depth = Integer.parseInt(parameter.replace("d", "")); + v.sendMessage(ChatColor.AQUA + "Depth set to " + this.depth); + if (this.depth < 1) + { + this.depth = 1; + } + } + else if (parameter.startsWith("all")) + { + this.allBlocks = true; + v.sendMessage(ChatColor.BLUE + "Will overlay over any block." + this.depth); + } + else if (parameter.startsWith("some")) + { + this.allBlocks = false; + v.sendMessage(ChatColor.BLUE + "Will overlay only natural block types." + this.depth); + } + else if (par[i].startsWith("s")) + { + final double temp = Integer.parseInt(parameter.replace("s", "")); + if (temp >= SEED_PERCENT_MIN && temp <= SEED_PERCENT_MAX) + { + v.sendMessage(ChatColor.AQUA + "Seed percent set to: " + temp / 100 + "%"); + this.seedPercent = (int) temp; + } + else + { + v.sendMessage(ChatColor.RED + "Seed percent must be an integer 1-9999!"); + } + } + else if (parameter.startsWith("g")) + { + final double temp = Integer.parseInt(parameter.replace("g", "")); + if (temp >= GROW_PERCENT_MIN && temp <= GROW_PERCENT_MAX) + { + v.sendMessage(ChatColor.AQUA + "Growth percent set to: " + temp / 100 + "%"); + this.growPercent = (int) temp; + } + else + { + v.sendMessage(ChatColor.RED + "Growth percent must be an integer 1-9999!"); + } + } + else if (parameter.startsWith("randh")) + { + randomizeHeight = !randomizeHeight; + v.sendMessage(ChatColor.RED + "RandomizeHeight set to: " + randomizeHeight); + } + else if (parameter.startsWith("r")) + { + final int temp = Integer.parseInt(parameter.replace("r", "")); + if (temp >= SPLATREC_PERCENT_MIN && temp <= SPLATREC_PERCENT_MAX) + { + v.sendMessage(ChatColor.AQUA + "Recursions set to: " + temp); + this.splatterRecursions = temp; + } + else + { + v.sendMessage(ChatColor.RED + "Recursions must be an integer 1-10!"); + } + } + else if (parameter.startsWith("yoff")) + { + final int temp = Integer.parseInt(parameter.replace("yoff", "")); + if (temp >= SPLATREC_PERCENT_MIN && temp <= SPLATREC_PERCENT_MAX) + { + v.sendMessage(ChatColor.AQUA + "Y-Offset set to: " + temp); + this.yOffset = temp; + } + else + { + v.sendMessage(ChatColor.RED + "Recursions must be an integer 1-10!"); + } + } + else + { + v.sendMessage(ChatColor.RED + "Invalid brush parameters! use the info parameter to display parameter info."); + } + } + catch (Exception exception) + { + v.sendMessage(String.format("An error occured while processing parameter %s.", parameter)); + } + } + } + + @Override + public String getPermissionNode() + { + return "voxelsniper.brush.splatteroverlay"; + } +} diff --git a/favs/src/main/java/com/thevoxelbox/voxelsniper/brush/SplatterVoxelBrush.java b/favs/src/main/java/com/thevoxelbox/voxelsniper/brush/SplatterVoxelBrush.java new file mode 100644 index 000000000..cfa39e759 --- /dev/null +++ b/favs/src/main/java/com/thevoxelbox/voxelsniper/brush/SplatterVoxelBrush.java @@ -0,0 +1,274 @@ +package com.thevoxelbox.voxelsniper.brush; + +import com.boydti.fawe.bukkit.wrapper.AsyncBlock; +import com.thevoxelbox.voxelsniper.Message; +import com.thevoxelbox.voxelsniper.SnipeData; +import com.thevoxelbox.voxelsniper.brush.perform.PerformBrush; +import org.bukkit.ChatColor; +import org.bukkit.block.Block; + +import java.util.Random; + +/** + * http://www.voxelwiki.com/minecraft/Voxelsniper#Splatter_Brushes + * + * @author Voxel + */ +public class SplatterVoxelBrush extends PerformBrush +{ + private static final int GROW_PERCENT_MIN = 1; + private static final int GROW_PERCENT_DEFAULT = 1000; + private static final int GROW_PERCENT_MAX = 9999; + private static final int SEED_PERCENT_MIN = 1; + private static final int SEED_PERCENT_DEFAULT = 1000; + private static final int SEED_PERCENT_MAX = 9999; + private static final int SPLATREC_PERCENT_MIN = 1; + private static final int SPLATREC_PERCENT_DEFAULT = 3; + private static final int SPLATREC_PERCENT_MAX = 10; + private int seedPercent; // Chance block on first pass is made active + private int growPercent; // chance block on recursion pass is made active + private int splatterRecursions; // How many times you grow the seeds + private Random generator = new Random(); + + /** + * + */ + public SplatterVoxelBrush() + { + this.setName("Splatter Voxel"); + } + + private void vSplatterBall(final SnipeData v, AsyncBlock targetBlock) + { + if (this.seedPercent < SEED_PERCENT_MIN || this.seedPercent > SEED_PERCENT_MAX) + { + v.sendMessage(ChatColor.BLUE + "Seed percent set to: 10%"); + this.seedPercent = SEED_PERCENT_DEFAULT; + } + if (this.growPercent < GROW_PERCENT_MIN || this.growPercent > GROW_PERCENT_MAX) + { + v.sendMessage(ChatColor.BLUE + "Growth percent set to: 10%"); + this.growPercent = GROW_PERCENT_DEFAULT; + } + if (this.splatterRecursions < SPLATREC_PERCENT_MIN || this.splatterRecursions > SPLATREC_PERCENT_MAX) + { + v.sendMessage(ChatColor.BLUE + "Recursions set to: 3"); + this.splatterRecursions = SPLATREC_PERCENT_DEFAULT; + } + final int[][][] splat = new int[2 * v.getBrushSize() + 1][2 * v.getBrushSize() + 1][2 * v.getBrushSize() + 1]; + + // Seed the array + for (int x = 2 * v.getBrushSize(); x >= 0; x--) + { + for (int y = 2 * v.getBrushSize(); y >= 0; y--) + { + for (int z = 2 * v.getBrushSize(); z >= 0; z--) + { + if (this.generator.nextInt(SEED_PERCENT_MAX + 1) <= this.seedPercent) + { + splat[x][y][z] = 1; + } + } + } + } + // Grow the seeds + final int gref = this.growPercent; + final int[][][] tempSplat = new int[2 * v.getBrushSize() + 1][2 * v.getBrushSize() + 1][2 * v.getBrushSize() + 1]; + int growcheck; + + for (int r = 0; r < this.splatterRecursions; r++) + { + this.growPercent = gref - ((gref / this.splatterRecursions) * (r)); + + for (int x = 2 * v.getBrushSize(); x >= 0; x--) + { + for (int y = 2 * v.getBrushSize(); y >= 0; y--) + { + for (int z = 2 * v.getBrushSize(); z >= 0; z--) + { + tempSplat[x][y][z] = splat[x][y][z]; // prime tempsplat + + growcheck = 0; + if (splat[x][y][z] == 0) + { + if (x != 0 && splat[x - 1][y][z] == 1) + { + growcheck++; + } + if (y != 0 && splat[x][y - 1][z] == 1) + { + growcheck++; + } + if (z != 0 && splat[x][y][z - 1] == 1) + { + growcheck++; + } + if (x != 2 * v.getBrushSize() && splat[x + 1][y][z] == 1) + { + growcheck++; + } + if (y != 2 * v.getBrushSize() && splat[x][y + 1][z] == 1) + { + growcheck++; + } + if (z != 2 * v.getBrushSize() && splat[x][y][z + 1] == 1) + { + growcheck++; + } + } + + if (growcheck >= 1 && this.generator.nextInt(GROW_PERCENT_MAX + 1) <= this.growPercent) + { + tempSplat[x][y][z] = 1; // prevent bleed into splat + } + + } + } + } + // integrate tempsplat back into splat at end of iteration + for (int x = 2 * v.getBrushSize(); x >= 0; x--) + { + for (int y = 2 * v.getBrushSize(); y >= 0; y--) + { + for (int z = 2 * v.getBrushSize(); z >= 0; z--) + { + splat[x][y][z] = tempSplat[x][y][z]; + } + } + } + } + this.growPercent = gref; + // Fill 1x1x1 holes + for (int x = 2 * v.getBrushSize(); x >= 0; x--) + { + for (int y = 2 * v.getBrushSize(); y >= 0; y--) + { + for (int z = 2 * v.getBrushSize(); z >= 0; z--) + { + if (splat[Math.max(x - 1, 0)][y][z] == 1 && splat[Math.min(x + 1, 2 * v.getBrushSize())][y][z] == 1 && splat[x][Math.max(0, y - 1)][z] == 1 && splat[x][Math.min(2 * v.getBrushSize(), y + 1)][z] == 1) + { + splat[x][y][z] = 1; + } + } + } + } + + // Make the changes + + for (int x = 2 * v.getBrushSize(); x >= 0; x--) + { + for (int y = 2 * v.getBrushSize(); y >= 0; y--) + { + for (int z = 2 * v.getBrushSize(); z >= 0; z--) + { + if (splat[x][y][z] == 1) + { + current.perform(targetBlock.getRelative(-v.getBrushSize() + x, -v.getBrushSize() + z, -v.getBrushSize() + y)); + } + } + } + } + v.owner().storeUndo(this.current.getUndo()); + } + + @Override + protected final void arrow(final SnipeData v) + { + this.vSplatterBall(v, this.getTargetBlock()); + } + + @Override + protected final void powder(final SnipeData v) + { + this.vSplatterBall(v, this.getLastBlock()); + } + + @Override + public final void info(final Message vm) + { + if (this.seedPercent < SEED_PERCENT_MIN || this.seedPercent > SEED_PERCENT_MAX) + { + this.seedPercent = SEED_PERCENT_DEFAULT; + } + if (this.growPercent < GROW_PERCENT_MIN || this.growPercent > GROW_PERCENT_MAX) + { + this.growPercent = GROW_PERCENT_DEFAULT; + } + if (this.splatterRecursions < SPLATREC_PERCENT_MIN || this.splatterRecursions > SPLATREC_PERCENT_MAX) + { + this.splatterRecursions = SPLATREC_PERCENT_DEFAULT; + } + vm.brushName("Splatter Voxel"); + vm.size(); + vm.custom(ChatColor.BLUE + "Seed percent set to: " + this.seedPercent / 100 + "%"); + vm.custom(ChatColor.BLUE + "Growth percent set to: " + this.growPercent / 100 + "%"); + vm.custom(ChatColor.BLUE + "Recursions set to: " + this.splatterRecursions); + } + + @Override + public final void parameters(final String[] par, final SnipeData v) + { + for (int i = 1; i < par.length; i++) + { + final String parameter = par[i]; + + if (parameter.equalsIgnoreCase("info")) + { + v.sendMessage(ChatColor.GOLD + "Splatter Voxel brush Parameters:"); + v.sendMessage(ChatColor.AQUA + "/b sv s[int] -- set a seed percentage (1-9999). 100 = 1% Default is 1000"); + v.sendMessage(ChatColor.AQUA + "/b sv g[int] -- set a growth percentage (1-9999). Default is 1000"); + v.sendMessage(ChatColor.AQUA + "/b sv r[int] -- set a recursion (1-10). Default is 3"); + return; + } + else if (parameter.startsWith("s")) + { + final double temp = Integer.parseInt(parameter.replace("s", "")); + if (temp >= SEED_PERCENT_MIN && temp <= SEED_PERCENT_MAX) + { + v.sendMessage(ChatColor.AQUA + "Seed percent set to: " + temp / 100 + "%"); + this.seedPercent = (int) temp; + } + else + { + v.sendMessage(ChatColor.RED + "Seed percent must be an integer 1-9999!"); + } + } + else if (parameter.startsWith("g")) + { + final double temp = Integer.parseInt(parameter.replace("g", "")); + if (temp >= GROW_PERCENT_MIN && temp <= GROW_PERCENT_MAX) + { + v.sendMessage(ChatColor.AQUA + "Growth percent set to: " + temp / 100 + "%"); + this.growPercent = (int) temp; + } + else + { + v.sendMessage(ChatColor.RED + "Growth percent must be an integer 1-9999!"); + } + } + else if (parameter.startsWith("r")) + { + final int temp = Integer.parseInt(parameter.replace("r", "")); + if (temp >= SPLATREC_PERCENT_MIN && temp <= SPLATREC_PERCENT_MAX) + { + v.sendMessage(ChatColor.AQUA + "Recursions set to: " + temp); + this.splatterRecursions = temp; + } + else + { + v.sendMessage(ChatColor.RED + "Recursions must be an integer 1-10!"); + } + } + else + { + v.sendMessage(ChatColor.RED + "Invalid brush parameters! use the info parameter to display parameter info."); + } + } + } + + @Override + public String getPermissionNode() + { + return "voxelsniper.brush.splattervoxel"; + } +} diff --git a/favs/src/main/java/com/thevoxelbox/voxelsniper/brush/SplatterVoxelDiscBrush.java b/favs/src/main/java/com/thevoxelbox/voxelsniper/brush/SplatterVoxelDiscBrush.java new file mode 100644 index 000000000..aea30c080 --- /dev/null +++ b/favs/src/main/java/com/thevoxelbox/voxelsniper/brush/SplatterVoxelDiscBrush.java @@ -0,0 +1,250 @@ +package com.thevoxelbox.voxelsniper.brush; + +import com.thevoxelbox.voxelsniper.Message; +import com.thevoxelbox.voxelsniper.SnipeData; +import com.thevoxelbox.voxelsniper.brush.perform.PerformBrush; +import org.bukkit.ChatColor; +import org.bukkit.block.Block; + +import java.util.Random; + +/** + * http://www.voxelwiki.com/minecraft/Voxelsniper#Splatter_Brushes + * + * @author Voxel + */ +public class SplatterVoxelDiscBrush extends PerformBrush +{ + private static final int GROW_PERCENT_MIN = 1; + private static final int GROW_PERCENT_DEFAULT = 1000; + private static final int GROW_PERCENT_MAX = 9999; + private static final int SEED_PERCENT_MIN = 1; + private static final int SEED_PERCENT_DEFAULT = 1000; + private static final int SEED_PERCENT_MAX = 9999; + private static final int SPLATREC_PERCENT_MIN = 1; + private static final int SPLATREC_PERCENT_DEFAULT = 3; + private static final int SPLATREC_PERCENT_MAX = 10; + private int seedPercent; // Chance block on first pass is made active + private int growPercent; // chance block on recursion pass is made active + private int splatterRecursions; // How many times you grow the seeds + private Random generator = new Random(); + + /** + * + */ + public SplatterVoxelDiscBrush() + { + this.setName("Splatter Voxel Disc"); + } + + private void vSplatterDisc(final SnipeData v, Block targetBlock) + { + if (this.seedPercent < SEED_PERCENT_MIN || this.seedPercent > SEED_PERCENT_MAX) + { + v.sendMessage(ChatColor.BLUE + "Seed percent set to: 10%"); + this.seedPercent = SEED_PERCENT_DEFAULT; + } + if (this.growPercent < GROW_PERCENT_MIN || this.growPercent > GROW_PERCENT_MAX) + { + v.sendMessage(ChatColor.BLUE + "Growth percent set to: 10%"); + this.growPercent = GROW_PERCENT_DEFAULT; + } + if (this.splatterRecursions < SPLATREC_PERCENT_MIN || this.splatterRecursions > SPLATREC_PERCENT_MAX) + { + v.sendMessage(ChatColor.BLUE + "Recursions set to: 3"); + this.splatterRecursions = SPLATREC_PERCENT_DEFAULT; + } + final int[][] splat = new int[2 * v.getBrushSize() + 1][2 * v.getBrushSize() + 1]; + + // Seed the array + for (int x = 2 * v.getBrushSize(); x >= 0; x--) + { + for (int y = 2 * v.getBrushSize(); y >= 0; y--) + { + if (this.generator.nextInt(SEED_PERCENT_MAX + 1) <= this.seedPercent) + { + splat[x][y] = 1; + } + } + } + // Grow the seeds + final int gref = this.growPercent; + final int[][] tempSplat = new int[2 * v.getBrushSize() + 1][2 * v.getBrushSize() + 1]; + int growcheck; + + for (int r = 0; r < this.splatterRecursions; r++) + { + this.growPercent = gref - ((gref / this.splatterRecursions) * (r)); + for (int x = 2 * v.getBrushSize(); x >= 0; x--) + { + for (int y = 2 * v.getBrushSize(); y >= 0; y--) + { + tempSplat[x][y] = splat[x][y]; // prime tempsplat + + growcheck = 0; + if (splat[x][y] == 0) + { + if (x != 0 && splat[x - 1][y] == 1) + { + growcheck++; + } + if (y != 0 && splat[x][y - 1] == 1) + { + growcheck++; + } + if (x != 2 * v.getBrushSize() && splat[x + 1][y] == 1) + { + growcheck++; + } + if (y != 2 * v.getBrushSize() && splat[x][y + 1] == 1) + { + growcheck++; + } + } + + if (growcheck >= 1 && this.generator.nextInt(GROW_PERCENT_MAX + 1) <= this.growPercent) + { + tempSplat[x][y] = 1; // prevent bleed into splat + } + } + } + // integrate tempsplat back into splat at end of iteration + for (int x = 2 * v.getBrushSize(); x >= 0; x--) + { + for (int y = 2 * v.getBrushSize(); y >= 0; y--) + { + splat[x][y] = tempSplat[x][y]; + } + } + } + this.growPercent = gref; + // Fill 1x1 holes + for (int x = 2 * v.getBrushSize(); x >= 0; x--) + { + for (int y = 2 * v.getBrushSize(); y >= 0; y--) + { + if (splat[Math.max(x - 1, 0)][y] == 1 && splat[Math.min(x + 1, 2 * v.getBrushSize())][y] == 1 && splat[x][Math.max(0, y - 1)] == 1 && splat[x][Math.min(2 * v.getBrushSize(), y + 1)] == 1) + { + splat[x][y] = 1; + } + } + } + + // Make the changes + + for (int x = 2 * v.getBrushSize(); x >= 0; x--) + { + for (int y = 2 * v.getBrushSize(); y >= 0; y--) + { + if (splat[x][y] == 1) + { + this.current.perform(this.clampY(targetBlock.getX() - v.getBrushSize() + x, targetBlock.getY(), targetBlock.getZ() - v.getBrushSize() + y)); + } + } + } + v.owner().storeUndo(this.current.getUndo()); + } + + @Override + protected final void arrow(final SnipeData v) + { + this.vSplatterDisc(v, this.getTargetBlock()); + } + + @Override + protected final void powder(final SnipeData v) + { + this.vSplatterDisc(v, this.getLastBlock()); + } + + @Override + public final void info(final Message vm) + { + if (this.seedPercent < SEED_PERCENT_MIN || this.seedPercent > SEED_PERCENT_MAX) + { + this.seedPercent = SEED_PERCENT_DEFAULT; + } + if (this.growPercent < GROW_PERCENT_MIN || this.growPercent > GROW_PERCENT_MAX) + { + this.growPercent = GROW_PERCENT_DEFAULT; + } + if (this.splatterRecursions < SPLATREC_PERCENT_MIN || this.splatterRecursions > SPLATREC_PERCENT_MAX) + { + this.splatterRecursions = SPLATREC_PERCENT_DEFAULT; + } + vm.brushName("Splatter Voxel Disc"); + vm.size(); + vm.custom(ChatColor.BLUE + "Seed percent set to: " + this.seedPercent / 100 + "%"); + vm.custom(ChatColor.BLUE + "Growth percent set to: " + this.growPercent / 100 + "%"); + vm.custom(ChatColor.BLUE + "Recursions set to: " + this.splatterRecursions); + + } + + @Override + public final void parameters(final String[] par, final SnipeData v) + { + + for (int i = 1; i < par.length; i++) + { + final String parameter = par[i]; + + if (parameter.equalsIgnoreCase("info")) + { + v.sendMessage(ChatColor.GOLD + "Splatter Voxel Disc brush Parameters:"); + v.sendMessage(ChatColor.AQUA + "/b svd s[int] -- set a seed percentage (1-9999). 100 = 1% Default is 1000"); + v.sendMessage(ChatColor.AQUA + "/b svd g[int] -- set a growth percentage (1-9999). Default is 1000"); + v.sendMessage(ChatColor.AQUA + "/b svd r[int] -- set a recursion (1-10). Default is 3"); + return; + } + else if (parameter.startsWith("s")) + { + final double temp = Integer.parseInt(parameter.replace("s", "")); + if (temp >= SEED_PERCENT_MIN && temp <= SEED_PERCENT_MAX) + { + v.sendMessage(ChatColor.AQUA + "Seed percent set to: " + temp / 100 + "%"); + this.seedPercent = (int) temp; + } + else + { + v.sendMessage(ChatColor.RED + "Seed percent must be an integer 1-9999!"); + } + } + else if (parameter.startsWith("g")) + { + final double temp = Integer.parseInt(parameter.replace("g", "")); + if (temp >= GROW_PERCENT_MIN && temp <= GROW_PERCENT_MAX) + { + v.sendMessage(ChatColor.AQUA + "Growth percent set to: " + temp / 100 + "%"); + this.growPercent = (int) temp; + } + else + { + v.sendMessage(ChatColor.RED + "Growth percent must be an integer 1-9999!"); + } + } + else if (parameter.startsWith("r")) + { + final int temp = Integer.parseInt(parameter.replace("r", "")); + if (temp >= SPLATREC_PERCENT_MIN && temp <= SPLATREC_PERCENT_MAX) + { + v.sendMessage(ChatColor.AQUA + "Recursions set to: " + temp); + this.splatterRecursions = temp; + } + else + { + v.sendMessage(ChatColor.RED + "Recursions must be an integer 1-10!"); + } + } + else + { + v.sendMessage(ChatColor.RED + "Invalid brush parameters! use the info parameter to display parameter info."); + } + } + } + + @Override + public String getPermissionNode() + { + return "voxelsniper.brush.splattervoxeldisc"; + } +} diff --git a/favs/src/main/java/com/thevoxelbox/voxelsniper/brush/SplineBrush.java b/favs/src/main/java/com/thevoxelbox/voxelsniper/brush/SplineBrush.java new file mode 100644 index 000000000..707a8c7ab --- /dev/null +++ b/favs/src/main/java/com/thevoxelbox/voxelsniper/brush/SplineBrush.java @@ -0,0 +1,313 @@ +package com.thevoxelbox.voxelsniper.brush; + +import com.thevoxelbox.voxelsniper.Message; +import com.thevoxelbox.voxelsniper.SnipeData; +import com.thevoxelbox.voxelsniper.brush.perform.PerformBrush; +import org.bukkit.ChatColor; +import org.bukkit.block.Block; + +import java.util.ArrayList; + +/** + * FOR ANY BRUSH THAT USES A SPLINE, EXTEND THAT BRUSH FROM THIS BRUSH!!! That way, the spline calculations are already there. Also, the UI for + * the splines will be included. + * + * @author psanker + */ +public class SplineBrush extends PerformBrush +{ + private final ArrayList endPts = new ArrayList(); + private final ArrayList ctrlPts = new ArrayList(); + protected ArrayList spline = new ArrayList(); + protected boolean set; + protected boolean ctrl; + protected String[] sparams = {"ss", "sc", "clear"}; + + public SplineBrush() + { + this.setName("Spline"); + } + + public final void addToSet(final SnipeData v, final boolean ep, Block targetBlock) + { + if (ep) + { + if (this.endPts.contains(targetBlock) || this.endPts.size() == 2) + { + return; + } + + this.endPts.add(targetBlock); + v.sendMessage(ChatColor.GRAY + "Added block " + ChatColor.RED + "(" + targetBlock.getX() + ", " + targetBlock.getY() + ", " + targetBlock.getZ() + ") " + ChatColor.GRAY + "to endpoint selection"); + return; + } + + if (this.ctrlPts.contains(targetBlock) || this.ctrlPts.size() == 2) + { + return; + } + + this.ctrlPts.add(targetBlock); + v.sendMessage(ChatColor.GRAY + "Added block " + ChatColor.RED + "(" + targetBlock.getX() + ", " + targetBlock.getY() + ", " + targetBlock.getZ() + ") " + ChatColor.GRAY + + "to control point selection"); + } + + public final void removeFromSet(final SnipeData v, final boolean ep, Block targetBlock) + { + if (ep) + { + if (!this.endPts.contains(targetBlock)) + { + v.sendMessage(ChatColor.RED + "That block is not in the endpoint selection set."); + return; + } + + this.endPts.add(targetBlock); + v.sendMessage(ChatColor.GRAY + "Removed block " + ChatColor.RED + "(" + targetBlock.getX() + ", " + targetBlock.getY() + ", " + targetBlock.getZ() + ") " + ChatColor.GRAY + + "from endpoint selection"); + return; + } + + if (!this.ctrlPts.contains(targetBlock)) + { + v.sendMessage(ChatColor.RED + "That block is not in the control point selection set."); + return; + } + + this.ctrlPts.remove(targetBlock); + v.sendMessage(ChatColor.GRAY + "Removed block " + ChatColor.RED + "(" + targetBlock.getX() + ", " + targetBlock.getY() + ", " + targetBlock.getZ() + ") " + ChatColor.GRAY + + "from control point selection"); + } + + public final boolean spline(final Point start, final Point end, final Point c1, final Point c2, final SnipeData v) + { + this.spline.clear(); + + try + { + final Point c = (c1.subtract(start)).multiply(3); + final Point b = ((c2.subtract(c1)).multiply(3)).subtract(c); + final Point a = ((end.subtract(start)).subtract(c)).subtract(b); + + for (double t = 0.0; t < 1.0; t += 0.01) + { + final int px = (int) Math.round((a.getX() * (t * t * t)) + (b.getX() * (t * t)) + (c.getX() * t) + this.endPts.get(0).getX()); + final int py = (int) Math.round((a.getY() * (t * t * t)) + (b.getY() * (t * t)) + (c.getY() * t) + this.endPts.get(0).getY()); + final int pz = (int) Math.round((a.getZ() * (t * t * t)) + (b.getZ() * (t * t)) + (c.getZ() * t) + this.endPts.get(0).getZ()); + + if (!this.spline.contains(new Point(px, py, pz))) + { + this.spline.add(new Point(px, py, pz)); + } + } + + return true; + } + catch (final Exception exception) + { + v.sendMessage(ChatColor.RED + "Not enough points selected; " + this.endPts.size() + " endpoints, " + this.ctrlPts.size() + " control points"); + return false; + } + } + + protected final void render(final SnipeData v) + { + if (this.spline.isEmpty()) + { + return; + } + + for (final Point point : this.spline) + { + this.current.perform(this.clampY(point.getX(), point.getY(), point.getZ())); + } + + v.owner().storeUndo(this.current.getUndo()); + } + + @Override + protected final void arrow(final SnipeData v) + { + if (this.set) + { + this.removeFromSet(v, true, this.getTargetBlock()); + } + else if (this.ctrl) + { + this.removeFromSet(v, false, this.getTargetBlock()); + } + } + + protected final void clear(final SnipeData v) + { + this.spline.clear(); + this.ctrlPts.clear(); + this.endPts.clear(); + v.sendMessage(ChatColor.GRAY + "Bezier curve cleared."); + } + + @Override + protected final void powder(final SnipeData v) + { + if (this.set) + { + this.addToSet(v, true, this.getTargetBlock()); + } + if (this.ctrl) + { + this.addToSet(v, false, this.getTargetBlock()); + } + } + + @Override + public final void info(final Message vm) + { + vm.brushName(this.getName()); + + if (this.set) + { + vm.custom(ChatColor.GRAY + "Endpoint selection mode ENABLED."); + } + else if (this.ctrl) + { + vm.custom(ChatColor.GRAY + "Control point selection mode ENABLED."); + } + else + { + vm.custom(ChatColor.AQUA + "No selection mode enabled."); + } + } + + @Override + public final void parameters(final String[] par, final com.thevoxelbox.voxelsniper.SnipeData v) + { + for (int i = 1; i < par.length; i++) + { + if (par[i].equalsIgnoreCase("info")) + { + v.sendMessage(ChatColor.GOLD + "Spline brush parameters"); + v.sendMessage(ChatColor.AQUA + "ss: Enable endpoint selection mode for desired curve"); + v.sendMessage(ChatColor.AQUA + "sc: Enable control point selection mode for desired curve"); + v.sendMessage(ChatColor.AQUA + "clear: Clear out the curve selection"); + v.sendMessage(ChatColor.AQUA + "ren: Render curve from control points"); + return; + } + if (par[i].equalsIgnoreCase("sc")) + { + if (!this.ctrl) + { + this.set = false; + this.ctrl = true; + v.sendMessage(ChatColor.GRAY + "Control point selection mode ENABLED."); + } + else + { + this.ctrl = false; + v.sendMessage(ChatColor.AQUA + "Control point selection mode disabled."); + } + } + else if (par[i].equalsIgnoreCase("ss")) + { + if (!this.set) + { + this.set = true; + this.ctrl = false; + v.sendMessage(ChatColor.GRAY + "Endpoint selection mode ENABLED."); + } + else + { + this.set = false; + v.sendMessage(ChatColor.AQUA + "Endpoint selection mode disabled."); + } + } + else if (par[i].equalsIgnoreCase("clear")) + { + this.clear(v); + } + else if (par[i].equalsIgnoreCase("ren")) + { + if (this.spline(new Point(this.endPts.get(0)), new Point(this.endPts.get(1)), new Point(this.ctrlPts.get(0)), new Point(this.ctrlPts.get(1)), v)) + { + this.render(v); + } + } + else + { + v.sendMessage(ChatColor.RED + "Invalid brush parameters! use the info parameter to display parameter info."); + } + } + } + + // Vector class for splines + protected class Point + { + private int x; + private int y; + private int z; + + public Point(final Block b) + { + this.setX(b.getX()); + this.setY(b.getY()); + this.setZ(b.getZ()); + } + + public Point(final int x, final int y, final int z) + { + this.setX(x); + this.setY(y); + this.setZ(z); + } + + public final Point add(final Point p) + { + return new Point(this.getX() + p.getX(), this.getY() + p.getY(), this.getZ() + p.getZ()); + } + + public final Point multiply(final int scalar) + { + return new Point(this.getX() * scalar, this.getY() * scalar, this.getZ() * scalar); + } + + public final Point subtract(final Point p) + { + return new Point(this.getX() - p.getX(), this.getY() - p.getY(), this.getZ() - p.getZ()); + } + + public int getX() + { + return x; + } + + public void setX(int x) + { + this.x = x; + } + + public int getY() + { + return y; + } + + public void setY(int y) + { + this.y = y; + } + + public int getZ() + { + return z; + } + + public void setZ(int z) + { + this.z = z; + } + } + + @Override + public String getPermissionNode() + { + return "voxelsniper.brush.spline"; + } +} diff --git a/favs/src/main/java/com/thevoxelbox/voxelsniper/brush/StampBrush.java b/favs/src/main/java/com/thevoxelbox/voxelsniper/brush/StampBrush.java new file mode 100644 index 000000000..43b884c28 --- /dev/null +++ b/favs/src/main/java/com/thevoxelbox/voxelsniper/brush/StampBrush.java @@ -0,0 +1,348 @@ +package com.thevoxelbox.voxelsniper.brush; + +import java.util.HashSet; + +import com.boydti.fawe.bukkit.wrapper.AsyncBlock; +import com.sk89q.worldedit.world.block.BlockTypes; +import com.thevoxelbox.voxelsniper.Message; +import com.thevoxelbox.voxelsniper.SnipeData; +import com.thevoxelbox.voxelsniper.Undo; + +import org.bukkit.ChatColor; +import org.bukkit.block.Block; + +/** + * + */ +public class StampBrush extends Brush +{ + /** + * @author Voxel + */ + protected class BlockWrapper + { + public int id; + public int x; + public int y; + public int z; + public int d; + + /** + * @param b + * @param blx + * @param bly + * @param blz + */ + @SuppressWarnings("deprecation") + public BlockWrapper(final AsyncBlock b, final int blx, final int bly, final int blz) + { + this.id = b.getTypeId(); + this.d = b.getPropertyId(); + this.x = blx; + this.y = bly; + this.z = blz; + } + } + + /** + * @author Monofraps + */ + protected enum StampType + { + NO_AIR, FILL, DEFAULT + } + + protected HashSet clone = new HashSet(); + protected HashSet fall = new HashSet(); + protected HashSet drop = new HashSet(); + protected HashSet solid = new HashSet(); + protected Undo undo; + protected boolean sorted = false; + + protected StampType stamp = StampType.DEFAULT; + + /** + * + */ + public StampBrush() + { + this.setName("Stamp"); + } + + /** + * + */ + public final void reSort() + { + this.sorted = false; + } + + /** + * @param id + * + * @return + */ + protected final boolean falling(final int id) + { + return (id > 7 && id < 14); + } + + /** + * @param id + * + * @return + */ + protected final boolean fallsOff(final int id) + { + return (BlockTypes.get(id).getMaterial().isFragileWhenPushed()); + } + + /** + * @param cb + */ + @SuppressWarnings("deprecation") + protected final void setBlock(final BlockWrapper cb) + { + final AsyncBlock block = this.clampY(this.getTargetBlock().getX() + cb.x, this.getTargetBlock().getY() + cb.y, this.getTargetBlock().getZ() + cb.z); + this.undo.put(block); + block.setTypeId(cb.id); + block.setPropertyId(cb.d); + } + + /** + * @param cb + */ + @SuppressWarnings("deprecation") + protected final void setBlockFill(final BlockWrapper cb) + { + final AsyncBlock block = this.clampY(this.getTargetBlock().getX() + cb.x, this.getTargetBlock().getY() + cb.y, this.getTargetBlock().getZ() + cb.z); + if (block.isEmpty()) + { + this.undo.put(block); + block.setTypeId(cb.id); + block.setPropertyId(cb.d); + } + } + + /** + * @param type + */ + protected final void setStamp(final StampType type) + { + this.stamp = type; + } + + /** + * @param v + */ + protected final void stamp(final SnipeData v) + { + this.undo = new Undo(); + + if (this.sorted) + { + for (final BlockWrapper block : this.solid) + { + this.setBlock(block); + } + for (final BlockWrapper block : this.drop) + { + this.setBlock(block); + } + for (final BlockWrapper block : this.fall) + { + this.setBlock(block); + } + } + else + { + this.fall.clear(); + this.drop.clear(); + this.solid.clear(); + for (final BlockWrapper block : this.clone) + { + if (this.fallsOff(block.id)) + { + this.fall.add(block); + } + else if (this.falling(block.id)) + { + this.drop.add(block); + } + else + { + this.solid.add(block); + this.setBlock(block); + } + } + for (final BlockWrapper block : this.drop) + { + this.setBlock(block); + } + for (final BlockWrapper block : this.fall) + { + this.setBlock(block); + } + this.sorted = true; + } + + v.owner().storeUndo(this.undo); + } + + /** + * @param v + */ + protected final void stampFill(final SnipeData v) + { + + this.undo = new Undo(); + + if (this.sorted) + { + for (final BlockWrapper block : this.solid) + { + this.setBlockFill(block); + } + for (final BlockWrapper block : this.drop) + { + this.setBlockFill(block); + } + for (final BlockWrapper block : this.fall) + { + this.setBlockFill(block); + } + } + else + { + this.fall.clear(); + this.drop.clear(); + this.solid.clear(); + for (final BlockWrapper block : this.clone) + { + if (this.fallsOff(block.id)) + { + this.fall.add(block); + } + else if (this.falling(block.id)) + { + this.drop.add(block); + } + else if (block.id != 0) + { + this.solid.add(block); + this.setBlockFill(block); + } + } + for (final BlockWrapper block : this.drop) + { + this.setBlockFill(block); + } + for (final BlockWrapper block : this.fall) + { + this.setBlockFill(block); + } + this.sorted = true; + } + + v.owner().storeUndo(this.undo); + } + + /** + * @param v + */ + protected final void stampNoAir(final SnipeData v) + { + + this.undo = new Undo(); + + if (this.sorted) + { + for (final BlockWrapper block : this.solid) + { + this.setBlock(block); + } + for (final BlockWrapper block : this.drop) + { + this.setBlock(block); + } + for (final BlockWrapper block : this.fall) + { + this.setBlock(block); + } + } + else + { + this.fall.clear(); + this.drop.clear(); + this.solid.clear(); + for (final BlockWrapper block : this.clone) + { + if (this.fallsOff(block.id)) + { + this.fall.add(block); + } + else if (this.falling(block.id)) + { + this.drop.add(block); + } + else if (block.id != 0) + { + this.solid.add(block); + this.setBlock(block); + } + } + for (final BlockWrapper block : this.drop) + { + this.setBlock(block); + } + for (final BlockWrapper block : this.fall) + { + this.setBlock(block); + } + this.sorted = true; + } + + v.owner().storeUndo(this.undo); + } + + @Override + protected final void arrow(final SnipeData v) + { + switch (this.stamp) + { + case DEFAULT: + this.stamp(v); + break; + + case NO_AIR: + this.stampNoAir(v); + break; + + case FILL: + this.stampFill(v); + break; + + default: + v.sendMessage(ChatColor.DARK_RED + "Error while stamping! Report"); + break; + } + } + + @Override + protected void powder(final SnipeData v) + { + throw new UnsupportedOperationException("Not supported yet."); + } + + @Override + public void info(final Message vm) + { + throw new UnsupportedOperationException("Not supported yet."); + } + + @Override + public String getPermissionNode() + { + return "voxelsniper.brush.stamp"; + } +} diff --git a/favs/src/main/java/com/thevoxelbox/voxelsniper/brush/StencilBrush.java b/favs/src/main/java/com/thevoxelbox/voxelsniper/brush/StencilBrush.java new file mode 100644 index 000000000..d33d36bb0 --- /dev/null +++ b/favs/src/main/java/com/thevoxelbox/voxelsniper/brush/StencilBrush.java @@ -0,0 +1,461 @@ +package com.thevoxelbox.voxelsniper.brush; + +import java.io.BufferedInputStream; +import java.io.BufferedOutputStream; +import java.io.DataInputStream; +import java.io.DataOutputStream; +import java.io.File; +import java.io.FileInputStream; +import java.io.FileOutputStream; +import java.util.zip.GZIPInputStream; + +import com.boydti.fawe.bukkit.wrapper.AsyncBlock; +import com.boydti.fawe.object.FaweInputStream; +import com.boydti.fawe.object.FaweOutputStream; +import com.boydti.fawe.object.io.PGZIPOutputStream; +import com.google.common.io.Files; +import com.sk89q.worldedit.world.block.BlockTypes; +import com.thevoxelbox.voxelsniper.Message; +import com.thevoxelbox.voxelsniper.SnipeData; +import com.thevoxelbox.voxelsniper.Undo; + +import org.bukkit.ChatColor; +import org.bukkit.block.Block; + +/** + * This is paste only currently. Assumes files exist, and thus has no usefulness until I add in saving stencils later. Uses sniper-exclusive stencil format: 3 + * shorts for X,Z,Y size of cuboid 3 shorts for X,Z,Y offsets from the -X,-Z,-Y corner. This is the reference point for pasting, corresponding to where you + * click your brush. 1 long integer saying how many runs of blocks are in the schematic (data is compressed into runs) 1 per run: ( 1 boolean: true = compressed + * line ahead, false = locally unique block ahead. This wastes a bit instead of a byte, and overall saves space, as long as at least 1/8 of all RUNS are going + * to be size 1, which in Minecraft is almost definitely true. IF boolean was true, next unsigned byte stores the number of consecutive blocks of the same type, + * up to 256. IF boolean was false, there is no byte here, goes straight to ID and data instead, which applies to just one block. 2 bytes to identify type of + * block. First byte is ID, second is data. This applies to every one of the line of consecutive blocks if boolean was true. ) + * + * TODO: Make limit a config option + * + * @author Gavjenks + */ +public class StencilBrush extends Brush +{ + private byte pasteOption = 1; // 0 = full, 1 = fill, 2 = replace + private String filename = "NoFileLoaded"; + private short x; + private short z; + private short y; + private short xRef; + private short zRef; + private short yRef; + private byte pasteParam = 0; + private int[] firstPoint = new int[3]; + private int[] secondPoint = new int[3]; + private int[] pastePoint = new int[3]; + private byte point = 1; + + /** + * + */ + public StencilBrush() + { + this.setName("Stencil"); + } + + @SuppressWarnings("deprecation") + private void stencilPaste(final SnipeData v) + { + if (this.filename.matches("NoFileLoaded")) + { + v.sendMessage(ChatColor.RED + "You did not specify a filename. This is required."); + return; + } + + final Undo undo = new Undo(); + final File file = new File("plugins/VoxelSniper/stencils/" + this.filename + ".vstencil"); + + if (file.exists()) + { + try + { + final FaweInputStream in = new FaweInputStream(new DataInputStream(new GZIPInputStream(new BufferedInputStream(new FileInputStream(file))))); + + this.x = in.readShort(); + this.z = in.readShort(); + this.y = in.readShort(); + + this.xRef = in.readShort(); + this.zRef = in.readShort(); + this.yRef = in.readShort(); + + final int numRuns = in.readInt(); + + int currX = -this.xRef; // so if your ref point is +5 x, you want to start pasting -5 blocks from the clicked point (the reference) to get the + // corner, for example. + int currZ = -this.zRef; + int currY = -this.yRef; + int id; + int blockPositionX = getTargetBlock().getX(); + int blockPositionY = getTargetBlock().getY(); + int blockPositionZ = getTargetBlock().getZ(); + if (this.pasteOption == 0) + { + for (int i = 1; i < numRuns + 1; i++) + { + if (in.readBoolean()) + { + final int numLoops = in.readByte() + 128; + id = in.readVarInt(); + for (int j = 0; j < numLoops; j++) + { + undo.put(this.clampY(blockPositionX + currX, blockPositionY + currY, blockPositionZ + currZ)); + this.clampY(blockPositionX + currX, blockPositionY + currY, blockPositionZ + currZ).setCombinedId(id); + currX++; + if (currX == this.x - this.xRef) + { + currX = -this.xRef; + currZ++; + if (currZ == this.z - this.zRef) + { + currZ = -this.zRef; + currY++; + } + } + } + } + else + { + undo.put(this.clampY(blockPositionX + currX, blockPositionY + currY, blockPositionZ + currZ)); + int combined = in.readVarInt(); + this.clampY(blockPositionX + currX, blockPositionY + currY, blockPositionZ + currZ).setCombinedId(combined); + currX++; + if (currX == this.x - this.xRef) + { + currX = -this.xRef; + currZ++; + if (currZ == this.z - this.zRef) + { + currZ = -this.zRef; + currY++; + } + } + } + } + } + else if (this.pasteOption == 1) + { + for (int i = 1; i < numRuns + 1; i++) + { + if (in.readBoolean()) + { + final int numLoops = in.readByte() + 128; + id = (in.readVarInt()); + for (int j = 0; j < numLoops; j++) + { + + if (!BlockTypes.getFromStateId(id).getMaterial().isAir() && this.clampY(blockPositionX + currX, blockPositionY + currY, blockPositionZ + currZ).isEmpty()) + { + undo.put(this.clampY(blockPositionX + currX, blockPositionY + currY, blockPositionZ + currZ)); + this.clampY(blockPositionX + currX, blockPositionY + currY, blockPositionZ + currZ).setCombinedId(id); + } + currX++; + if (currX == this.x - this.xRef) + { + currX = -this.xRef; + currZ++; + if (currZ == this.z - this.zRef) + { + currZ = -this.zRef; + currY++; + } + } + } + } + else + { + id = (in.readVarInt()); + if (!BlockTypes.getFromStateId(id).getMaterial().isAir() && this.clampY(blockPositionX + currX, blockPositionY + currY, blockPositionZ + currZ).isEmpty()) + { + undo.put(this.clampY(blockPositionX + currX, blockPositionY + currY, blockPositionZ + currZ)); + // v.sendMessage("currX:" + currX + " currZ:"+currZ + " currY:" + currY + " id:" + id + " data:" + data); + this.clampY(blockPositionX + currX, blockPositionY + currY, blockPositionZ + currZ).setCombinedId(id); + } + currX++; + if (currX == this.x - this.xRef) + { + currX = -this.xRef; + currZ++; + if (currZ == this.z - this.zRef) + { + currZ = -this.zRef; + currY++; + } + } + } + } + } + else + { // replace + for (int i = 1; i < numRuns + 1; i++) + { + if (in.readBoolean()) + { + final int numLoops = in.readByte() + 128; + id = (in.readVarInt()); + for (int j = 0; j < (numLoops); j++) + { + if (!BlockTypes.getFromStateId(id).getMaterial().isAir()) + { + undo.put(this.clampY(blockPositionX + currX, blockPositionY + currY, blockPositionZ + currZ)); + this.clampY(blockPositionX + currX, blockPositionY + currY, blockPositionZ + currZ).setCombinedId(id); + } + currX++; + if (currX == this.x - this.xRef) + { + currX = -this.xRef; + currZ++; + if (currZ == this.z - this.zRef) + { + currZ = -this.zRef; + currY++; + } + } + } + } + else + { + id = (in.readVarInt()); + if (id != 0) + { + undo.put(this.clampY(blockPositionX + currX, blockPositionY + currY, blockPositionZ + currZ)); + this.clampY(blockPositionX + currX, blockPositionY + currY, blockPositionZ + currZ).setCombinedId(id); + } + currX++; + if (currX == this.x) + { + currX = 0; + currZ++; + if (currZ == this.z) + { + currZ = 0; + currY++; + } + } + } + } + } + in.close(); + v.owner().storeUndo(undo); + + } + catch (final Exception exception) + { + v.sendMessage(ChatColor.RED + "Something went wrong."); + exception.printStackTrace(); + } + } + else + { + v.sendMessage(ChatColor.RED + "You need to type a stencil name / your specified stencil does not exist."); + } + } + + @SuppressWarnings("deprecation") + private void stencilSave(final SnipeData v) + { + + final File file = new File("plugins/VoxelSniper/stencils/" + this.filename + ".vstencil"); + try + { + this.x = (short) (Math.abs((this.firstPoint[0] - this.secondPoint[0])) + 1); + this.z = (short) (Math.abs((this.firstPoint[1] - this.secondPoint[1])) + 1); + this.y = (short) (Math.abs((this.firstPoint[2] - this.secondPoint[2])) + 1); + this.xRef = (short) ((this.firstPoint[0] > this.secondPoint[0]) ? (this.pastePoint[0] - this.secondPoint[0]) : (this.pastePoint[0] - this.firstPoint[0])); + this.zRef = (short) ((this.firstPoint[1] > this.secondPoint[1]) ? (this.pastePoint[1] - this.secondPoint[1]) : (this.pastePoint[1] - this.firstPoint[1])); + this.yRef = (short) ((this.firstPoint[2] > this.secondPoint[2]) ? (this.pastePoint[2] - this.secondPoint[2]) : (this.pastePoint[2] - this.firstPoint[2])); + + if ((this.x * this.y * this.z) > 50000) + { + v.sendMessage(ChatColor.AQUA + "Volume exceeds maximum limit."); + return; + } + + Files.createParentDirs(file); + file.createNewFile(); + final FaweOutputStream out = new FaweOutputStream(new DataOutputStream(new PGZIPOutputStream(new BufferedOutputStream(new FileOutputStream(file))))); + int blockPositionX = (this.firstPoint[0] > this.secondPoint[0]) ? this.secondPoint[0] : this.firstPoint[0]; + int blockPositionZ = (this.firstPoint[1] > this.secondPoint[1]) ? this.secondPoint[1] : this.firstPoint[1]; + int blockPositionY = (this.firstPoint[2] > this.secondPoint[2]) ? this.secondPoint[2] : this.firstPoint[2]; + out.writeShort(this.x); + out.writeShort(this.z); + out.writeShort(this.y); + out.writeShort(this.xRef); + out.writeShort(this.zRef); + out.writeShort(this.yRef); + + v.sendMessage(ChatColor.AQUA + "Volume: " + this.x * this.z * this.y + " blockPositionX:" + blockPositionX + " blockPositionZ:" + blockPositionZ + " blockPositionY:" + blockPositionY); + + int[] blockArray = new int[this.x * this.z * this.y]; + byte[] runSizeArray = new byte[this.x * this.z * this.y]; + + int lastId = (this.getWorld().getBlockAt(blockPositionX, blockPositionY, blockPositionZ).getCombinedId()); + int thisId; + int counter = 0; + int arrayIndex = 0; + for (int y = 0; y < this.y; y++) + { + for (int z = 0; z < this.z; z++) + { + for (int x = 0; x < this.x; x++) + { + AsyncBlock currentBlock = getWorld().getBlockAt(blockPositionX + x, blockPositionY + y, blockPositionZ + z); + thisId = (currentBlock.getCombinedId()); + if (thisId != lastId || counter == 255) + { + blockArray[arrayIndex] = lastId; + runSizeArray[arrayIndex] = (byte) (counter - 128); + arrayIndex++; + counter = 1; + lastId = thisId; + } + else + { + counter++; + lastId = thisId; + } + } + } + } + blockArray[arrayIndex] = lastId; // saving last run, which will always be left over. + runSizeArray[arrayIndex] = (byte) (counter - 128); + + out.writeInt(arrayIndex + 1); + // v.sendMessage("number of runs = " + arrayIndex); + for (int i = 0; i < arrayIndex + 1; i++) + { + if (runSizeArray[i] > -127) + { + out.writeBoolean(true); + out.writeByte(runSizeArray[i]); + out.writeVarInt(blockArray[i]); + } + else + { + out.writeBoolean(false); + out.writeVarInt(blockArray[i]); + } + } + + v.sendMessage(ChatColor.BLUE + "Saved as '" + this.filename + "'."); + out.close(); + + } + catch (final Exception exception) + { + v.sendMessage(ChatColor.RED + "Something went wrong."); + exception.printStackTrace(); + } + } + + @Override + protected final void arrow(final SnipeData v) + { // will be used to copy/save later on? + if (this.point == 1) + { + this.firstPoint[0] = this.getTargetBlock().getX(); + this.firstPoint[1] = this.getTargetBlock().getZ(); + this.firstPoint[2] = this.getTargetBlock().getY(); + v.sendMessage(ChatColor.GRAY + "First point"); + v.sendMessage("X:" + this.firstPoint[0] + " Z:" + this.firstPoint[1] + " Y:" + this.firstPoint[2]); + this.point = 2; + } + else if (this.point == 2) + { + this.secondPoint[0] = this.getTargetBlock().getX(); + this.secondPoint[1] = this.getTargetBlock().getZ(); + this.secondPoint[2] = this.getTargetBlock().getY(); + if ((Math.abs(this.firstPoint[0] - this.secondPoint[0]) * Math.abs(this.firstPoint[1] - this.secondPoint[1]) * Math.abs(this.firstPoint[2] - this.secondPoint[2])) > 5000000) + { + v.sendMessage(ChatColor.DARK_RED + "Area selected is too large. (Limit is 5,000,000 blocks)"); + this.point = 1; + } + else + { + v.sendMessage(ChatColor.GRAY + "Second point"); + v.sendMessage("X:" + this.secondPoint[0] + " Z:" + this.secondPoint[1] + " Y:" + this.secondPoint[2]); + this.point = 3; + } + } + else if (this.point == 3) + { + this.pastePoint[0] = this.getTargetBlock().getX(); + this.pastePoint[1] = this.getTargetBlock().getZ(); + this.pastePoint[2] = this.getTargetBlock().getY(); + v.sendMessage(ChatColor.GRAY + "Paste Reference point"); + v.sendMessage("X:" + this.pastePoint[0] + " Z:" + this.pastePoint[1] + " Y:" + this.pastePoint[2]); + this.point = 1; + + this.stencilSave(v); + } + } + + @Override + protected final void powder(final SnipeData v) + { // will be used to paste later on + this.stencilPaste(v); + } + + @Override + public final void info(final Message vm) + { + vm.brushName(this.getName()); + vm.custom("File loaded: " + this.filename); + } + + @Override + public final void parameters(final String[] par, final SnipeData v) + { + if (par[1].equalsIgnoreCase("info")) + { + v.sendMessage(ChatColor.GOLD + "Stencil brush Parameters:"); + v.sendMessage(ChatColor.AQUA + "/b schem [optional: 'full' 'fill' or 'replace', with fill as default] [name] -- Loads the specified schematic. Allowed size of schematic is based on rank. Full/fill/replace must come first. Full = paste all blocks, fill = paste only into air blocks, replace = paste full blocks in only, but replace anything in their way."); + v.sendMessage(ChatColor.BLUE + "Size of the stencils you are allowed to paste depends on rank (member / lite, sniper, curator, admin)"); + return; + } + else if (par[1].equalsIgnoreCase("full")) + { + this.pasteOption = 0; + this.pasteParam = 1; + } + else if (par[1].equalsIgnoreCase("fill")) + { + this.pasteOption = 1; + this.pasteParam = 1; + } + else if (par[1].equalsIgnoreCase("replace")) + { + this.pasteOption = 2; + this.pasteParam = 1; + } + try + { + this.filename = par[1 + this.pasteParam]; + final File file = new File("plugins/VoxelSniper/stencils/" + this.filename + ".vstencil"); + if (file.exists()) + { + v.sendMessage(ChatColor.RED + "Stencil '" + this.filename + "' exists and was loaded. Make sure you are using powder if you do not want any chance of overwriting the file."); + } + else + { + v.sendMessage(ChatColor.AQUA + "Stencil '" + this.filename + "' does not exist. Ready to be saved to, but cannot be pasted."); + } + } + catch (final Exception exception) + { + v.sendMessage(ChatColor.RED + "You need to type a stencil name."); + } + } + + @Override + public String getPermissionNode() + { + return "voxelsniper.brush.stencil"; + } +} diff --git a/favs/src/main/java/com/thevoxelbox/voxelsniper/brush/StencilListBrush.java b/favs/src/main/java/com/thevoxelbox/voxelsniper/brush/StencilListBrush.java new file mode 100644 index 000000000..a90f80569 --- /dev/null +++ b/favs/src/main/java/com/thevoxelbox/voxelsniper/brush/StencilListBrush.java @@ -0,0 +1,984 @@ +package com.thevoxelbox.voxelsniper.brush; + +import com.thevoxelbox.voxelsniper.Message; +import com.thevoxelbox.voxelsniper.SnipeData; +import com.thevoxelbox.voxelsniper.Undo; +import org.bukkit.ChatColor; + +import java.io.BufferedInputStream; +import java.io.DataInputStream; +import java.io.File; +import java.io.FileInputStream; +import java.util.HashMap; +import java.util.Scanner; + +/** + * @author Gavjenks + */ +public class StencilListBrush extends Brush +{ + private byte pasteOption = 1; // 0 = full, 1 = fill, 2 = replace + private String filename = "NoFileLoaded"; + private short x; + private short z; + private short y; + private short xRef; + private short zRef; + private short yRef; + private byte pasteParam = 0; + private HashMap stencilList = new HashMap(); + + /** + * + */ + public StencilListBrush() + { + this.setName("StencilList"); + } + + private String readRandomStencil(final SnipeData v) + { + double rand = Math.random() * (this.stencilList.size()); + final int choice = (int) rand; + return this.stencilList.get(choice); + } + + private void readStencilList(final String listname, final SnipeData v) + { + final File file = new File("plugins/VoxelSniper/stencilLists/" + this.filename + ".txt"); + if (file.exists()) + { + try + { + final Scanner scanner = new Scanner(file); + int counter = 0; + while (scanner.hasNext()) + { + this.stencilList.put(counter, scanner.nextLine()); + counter++; + } + scanner.close(); + } + catch (final Exception exception) + { + exception.printStackTrace(); + } + } + } + + @SuppressWarnings("deprecation") + private void stencilPaste(final SnipeData v) + { + if (this.filename.matches("NoFileLoaded")) + { + v.sendMessage(ChatColor.RED + "You did not specify a filename for the list. This is required."); + return; + } + + final String stencilName = this.readRandomStencil(v); + v.sendMessage(stencilName); + + final Undo undo = new Undo(); + final File file = new File("plugins/VoxelSniper/stencils/" + stencilName + ".vstencil"); + + if (file.exists()) + { + try + { + final DataInputStream in = new DataInputStream(new BufferedInputStream(new FileInputStream(file))); + + this.x = in.readShort(); + this.z = in.readShort(); + this.y = in.readShort(); + + this.xRef = in.readShort(); + this.zRef = in.readShort(); + this.yRef = in.readShort(); + + final int numRuns = in.readInt(); + // Something here that checks ranks using sanker'world thingie he added to Sniper and boots you out with error message if too big. + final int volume = this.x * this.y * this.z; + v.owner().getPlayer().sendMessage(ChatColor.AQUA + this.filename + " pasted. Volume is " + volume + " blocks."); + + int currX = -this.xRef; // so if your ref point is +5 x, you want to start pasting -5 blocks from the clicked point (the reference) to get the + // corner, for example. + int currZ = -this.zRef; + int currY = -this.yRef; + int id; + int data; + if (this.pasteOption == 0) + { + for (int i = 1; i < numRuns + 1; i++) + { + if (in.readBoolean()) + { + final int numLoops = in.readByte() + 128; + id = (in.readByte() + 128); + data = (in.readByte() + 128); + for (int j = 0; j < numLoops; j++) + { + undo.put(this.clampY(this.getTargetBlock().getX() + currX, this.getTargetBlock().getY() + currY, this.getTargetBlock().getZ() + currZ)); + this.clampY(this.getTargetBlock().getX() + currX, this.getTargetBlock().getY() + currY, this.getTargetBlock().getZ() + currZ).setTypeIdAndPropertyId(id, data, false); + currX++; + if (currX == this.x - this.xRef) + { + currX = -this.xRef; + currZ++; + if (currZ == this.z - this.zRef) + { + currZ = -this.zRef; + currY++; + } + } + } + } + else + { + undo.put(this.clampY(this.getTargetBlock().getX() + currX, this.getTargetBlock().getY() + currY, this.getTargetBlock().getZ() + currZ)); + this.clampY(this.getTargetBlock().getX() + currX, this.getTargetBlock().getY() + currY, this.getTargetBlock().getZ() + currZ).setTypeIdAndPropertyId((in.readByte() + 128), (in.readByte() + 128), false); + currX++; + if (currX == this.x - this.xRef) + { + currX = -this.xRef; + currZ++; + if (currZ == this.z - this.zRef) + { + currZ = -this.zRef; + currY++; + } + } + } + } + } + else if (this.pasteOption == 1) + { + for (int i = 1; i < numRuns + 1; i++) + { + if (in.readBoolean()) + { + final int numLoops = in.readByte() + 128; + id = (in.readByte() + 128); + data = (in.readByte() + 128); + for (int j = 0; j < numLoops; j++) + { + if (id != 0 && this.clampY(this.getTargetBlock().getX() + currX, this.getTargetBlock().getY() + currY, this.getTargetBlock().getZ() + currZ).isEmpty()) + { + undo.put(this.clampY(this.getTargetBlock().getX() + currX, this.getTargetBlock().getY() + currY, this.getTargetBlock().getZ() + currZ)); + this.clampY(this.getTargetBlock().getX() + currX, this.getTargetBlock().getY() + currY, this.getTargetBlock().getZ() + currZ).setTypeIdAndPropertyId(id, (data), false); + } + currX++; + if (currX == this.x - this.xRef) + { + currX = -this.xRef; + currZ++; + if (currZ == this.z - this.zRef) + { + currZ = -this.zRef; + currY++; + } + } + } + } + else + { + id = (in.readByte() + 128); + data = (in.readByte() + 128); + if (id != 0 && this.clampY(this.getTargetBlock().getX() + currX, this.getTargetBlock().getY() + currY, this.getTargetBlock().getZ() + currZ).isEmpty()) + { + undo.put(this.clampY(this.getTargetBlock().getX() + currX, this.getTargetBlock().getY() + currY, this.getTargetBlock().getZ() + currZ)); + this.clampY(this.getTargetBlock().getX() + currX, this.getTargetBlock().getY() + currY, this.getTargetBlock().getZ() + currZ).setTypeIdAndPropertyId(id, (data), false); + } + currX++; + if (currX == this.x - this.xRef) + { + currX = -this.xRef; + currZ++; + if (currZ == this.z - this.zRef) + { + currZ = -this.zRef; + currY++; + } + } + } + } + } + else + { // replace + for (int i = 1; i < numRuns + 1; i++) + { + if (in.readBoolean()) + { + final int numLoops = in.readByte() + 128; + id = (in.readByte() + 128); + data = (in.readByte() + 128); + for (int j = 0; j < (numLoops); j++) + { + if (id != 0) + { + undo.put(this.clampY(this.getTargetBlock().getX() + currX, this.getTargetBlock().getY() + currY, this.getTargetBlock().getZ() + currZ)); + this.clampY(this.getTargetBlock().getX() + currX, this.getTargetBlock().getY() + currY, this.getTargetBlock().getZ() + currZ).setTypeIdAndPropertyId(id, data, false); + } + currX++; + if (currX == this.x - this.xRef) + { + currX = -this.xRef; + currZ++; + if (currZ == this.z - this.zRef) + { + currZ = -this.zRef; + currY++; + } + } + } + } + else + { + id = (in.readByte() + 128); + data = (in.readByte() + 128); + if (id != 0) + { + undo.put(this.clampY(this.getTargetBlock().getX() + currX, this.getTargetBlock().getY() + currY, this.getTargetBlock().getZ() + currZ)); + this.clampY(this.getTargetBlock().getX() + currX, this.getTargetBlock().getY() + currY, this.getTargetBlock().getZ() + currZ).setTypeIdAndPropertyId(id, data, false); + } + currX++; + if (currX == this.x) + { + currX = 0; + currZ++; + if (currZ == this.z) + { + currZ = 0; + currY++; + } + } + } + } + } + in.close(); + v.owner().storeUndo(undo); + + } + catch (final Exception exception) + { + v.owner().getPlayer().sendMessage(ChatColor.RED + "Something went wrong."); + exception.printStackTrace(); + } + } + else + { + v.owner().getPlayer().sendMessage(ChatColor.RED + "You need to type a stencil name / your specified stencil does not exist."); + } + } + + @SuppressWarnings("deprecation") + private void stencilPaste180(final SnipeData v) + { + if (this.filename.matches("NoFileLoaded")) + { + v.owner().getPlayer().sendMessage(ChatColor.RED + "You did not specify a filename for the list. This is required."); + return; + } + + final String stencilName = this.readRandomStencil(v); + + final Undo undo = new Undo(); + final File file = new File("plugins/VoxelSniper/stencils/" + stencilName + ".vstencil"); + + if (file.exists()) + { + try + { + final DataInputStream in = new DataInputStream(new BufferedInputStream(new FileInputStream(file))); + + this.x = in.readShort(); + this.z = in.readShort(); + this.y = in.readShort(); + + this.xRef = in.readShort(); + this.zRef = in.readShort(); + this.yRef = in.readShort(); + + final int numRuns = in.readInt(); + // Something here that checks ranks using sanker'world thingie he added to Sniper and boots you out with error message if too big. + final int volume = this.x * this.y * this.z; + v.owner().getPlayer().sendMessage(ChatColor.AQUA + this.filename + " pasted. Volume is " + volume + " blocks."); + + int currX = +this.xRef; // so if your ref point is +5 x, you want to start pasting -5 blocks from the clicked point (the reference) to get the + // corner, for example. + int currZ = +this.zRef; + int currY = -this.yRef; + int id; + int data; + if (this.pasteOption == 0) + { + for (int i = 1; i < numRuns + 1; i++) + { + if (in.readBoolean()) + { + final int numLoops = in.readByte() + 128; + id = (in.readByte() + 128); + data = (in.readByte() + 128); + for (int j = 0; j < numLoops; j++) + { + undo.put(this.clampY(this.getTargetBlock().getX() + currX, this.getTargetBlock().getY() + currY, this.getTargetBlock().getZ() + currZ)); + this.clampY(this.getTargetBlock().getX() + currX, this.getTargetBlock().getY() + currY, this.getTargetBlock().getZ() + currZ).setTypeIdAndPropertyId(id, data, false); + currX--; + if (currX == -this.x + this.xRef) + { + currX = this.xRef; + currZ--; + if (currZ == -this.z + this.zRef) + { + currZ = +this.zRef; + currY++; + } + } + } + } + else + { + undo.put(this.clampY(this.getTargetBlock().getX() + currX, this.getTargetBlock().getY() + currY, this.getTargetBlock().getZ() + currZ)); + this.clampY(this.getTargetBlock().getX() + currX, this.getTargetBlock().getY() + currY, this.getTargetBlock().getZ() + currZ).setTypeIdAndPropertyId((in.readByte() + 128), (in.readByte() + 128), false); + currX--; + if (currX == -this.x + this.xRef) + { + currX = this.xRef; + currZ--; + if (currZ == -this.z + this.zRef) + { + currZ = +this.zRef; + currY++; + } + } + } + } + } + else if (this.pasteOption == 1) + { + for (int i = 1; i < numRuns + 1; i++) + { + if (in.readBoolean()) + { + final int numLoops = in.readByte() + 128; + id = (in.readByte() + 128); + data = (in.readByte() + 128); + for (int j = 0; j < numLoops; j++) + { + if (id != 0 && this.clampY(this.getTargetBlock().getX() + currX, this.getTargetBlock().getY() + currY, this.getTargetBlock().getZ() + currZ).isEmpty()) + { + undo.put(this.clampY(this.getTargetBlock().getX() + currX, this.getTargetBlock().getY() + currY, this.getTargetBlock().getZ() + currZ)); + this.clampY(this.getTargetBlock().getX() + currX, this.getTargetBlock().getY() + currY, this.getTargetBlock().getZ() + currZ).setTypeIdAndPropertyId(id, (data), false); + } + currX--; + if (currX == -this.x + this.xRef) + { + currX = this.xRef; + currZ--; + if (currZ == -this.z + this.zRef) + { + currZ = +this.zRef; + currY++; + } + } + } + } + else + { + id = (in.readByte() + 128); + data = (in.readByte() + 128); + if (id != 0 && this.clampY(this.getTargetBlock().getX() + currX, this.getTargetBlock().getY() + currY, this.getTargetBlock().getZ() + currZ).isEmpty()) + { + undo.put(this.clampY(this.getTargetBlock().getX() + currX, this.getTargetBlock().getY() + currY, this.getTargetBlock().getZ() + currZ)); + this.clampY(this.getTargetBlock().getX() + currX, this.getTargetBlock().getY() + currY, this.getTargetBlock().getZ() + currZ).setTypeIdAndPropertyId(id, (data), false); + } + currX--; + if (currX == -this.x + this.xRef) + { + currX = this.xRef; + currZ--; + if (currZ == -this.z + this.zRef) + { + currZ = +this.zRef; + currY++; + } + } + } + } + } + else + { // replace + for (int i = 1; i < numRuns + 1; i++) + { + if (in.readBoolean()) + { + final int numLoops = in.readByte() + 128; + id = (in.readByte() + 128); + data = (in.readByte() + 128); + for (int j = 0; j < (numLoops); j++) + { + if (id != 0) + { + undo.put(this.clampY(this.getTargetBlock().getX() + currX, this.getTargetBlock().getY() + currY, this.getTargetBlock().getZ() + currZ)); + this.clampY(this.getTargetBlock().getX() + currX, this.getTargetBlock().getY() + currY, this.getTargetBlock().getZ() + currZ).setTypeIdAndPropertyId(id, data, false); + } + currX--; + if (currX == -this.x + this.xRef) + { + currX = this.xRef; + currZ--; + if (currZ == -this.z + this.zRef) + { + currZ = +this.zRef; + currY++; + } + } + } + } + else + { + id = (in.readByte() + 128); + data = (in.readByte() + 128); + if (id != 0) + { + undo.put(this.clampY(this.getTargetBlock().getX() + currX, this.getTargetBlock().getY() + currY, this.getTargetBlock().getZ() + currZ)); + this.clampY(this.getTargetBlock().getX() + currX, this.getTargetBlock().getY() + currY, this.getTargetBlock().getZ() + currZ).setTypeIdAndPropertyId(id, data, false); + } + currX--; + if (currX == -this.x + this.xRef) + { + currX = this.xRef; + currZ--; + if (currZ == -this.z + this.zRef) + { + currZ = +this.zRef; + currY++; + } + } + } + } + } + in.close(); + v.owner().storeUndo(undo); + + } + catch (final Exception exception) + { + v.owner().getPlayer().sendMessage(ChatColor.RED + "Something went wrong."); + exception.printStackTrace(); + } + } + else + { + v.owner().getPlayer().sendMessage(ChatColor.RED + "You need to type a stencil name / your specified stencil does not exist."); + } + } + + @SuppressWarnings("deprecation") + private void stencilPaste270(final SnipeData v) + { + if (this.filename.matches("NoFileLoaded")) + { + v.owner().getPlayer().sendMessage(ChatColor.RED + "You did not specify a filename for the list. This is required."); + return; + } + + final String stencilName = this.readRandomStencil(v); + + final Undo undo = new Undo(); + final File file = new File("plugins/VoxelSniper/stencils/" + stencilName + ".vstencil"); + + if (file.exists()) + { + try + { + final DataInputStream in = new DataInputStream(new BufferedInputStream(new FileInputStream(file))); + + this.x = in.readShort(); + this.z = in.readShort(); + this.y = in.readShort(); + + this.xRef = in.readShort(); + this.zRef = in.readShort(); + this.yRef = in.readShort(); + + final int numRuns = in.readInt(); + // Something here that checks ranks using sanker'world thingie he added to Sniper and boots you out with error message if too big. + final int volume = this.x * this.y * this.z; + v.owner().getPlayer().sendMessage(ChatColor.AQUA + this.filename + " pasted. Volume is " + volume + " blocks."); + + int currX = +this.zRef; // so if your ref point is +5 x, you want to start pasting -5 blocks from the clicked point (the reference) to get the + // corner, for example. + int currZ = -this.xRef; + int currY = -this.yRef; + int id; + int data; + if (this.pasteOption == 0) + { + for (int i = 1; i < numRuns + 1; i++) + { + if (in.readBoolean()) + { + final int numLoops = in.readByte() + 128; + id = (in.readByte() + 128); + data = (in.readByte() + 128); + for (int j = 0; j < numLoops; j++) + { + undo.put(this.clampY(this.getTargetBlock().getX() + currX, this.getTargetBlock().getY() + currY, this.getTargetBlock().getZ() + currZ)); + this.clampY(this.getTargetBlock().getX() + currX, this.getTargetBlock().getY() + currY, this.getTargetBlock().getZ() + currZ).setTypeIdAndPropertyId(id, data, false); + currZ++; + if (currZ == this.x - this.xRef) + { + currZ = -this.xRef; + currX--; + if (currX == -this.z + this.zRef) + { + currX = +this.zRef; + currY++; + } + } + } + } + else + { + undo.put(this.clampY(this.getTargetBlock().getX() + currX, this.getTargetBlock().getY() + currY, this.getTargetBlock().getZ() + currZ)); + this.clampY(this.getTargetBlock().getX() + currX, this.getTargetBlock().getY() + currY, this.getTargetBlock().getZ() + currZ).setTypeIdAndPropertyId((in.readByte() + 128), (in.readByte() + 128), false); + currZ++; + currZ++; + if (currZ == this.x - this.xRef) + { + currZ = -this.xRef; + currX--; + if (currX == -this.z + this.zRef) + { + currX = +this.zRef; + currY++; + } + } + } + } + } + else if (this.pasteOption == 1) + { + for (int i = 1; i < numRuns + 1; i++) + { + if (in.readBoolean()) + { + final int numLoops = in.readByte() + 128; + id = (in.readByte() + 128); + data = (in.readByte() + 128); + for (int j = 0; j < numLoops; j++) + { + if (id != 0 && this.clampY(this.getTargetBlock().getX() + currX, this.getTargetBlock().getY() + currY, this.getTargetBlock().getZ() + currZ).isEmpty()) + { // no reason to paste air over + // air, and it prevents us + // most of the time from + // having to even check the + // block. + undo.put(this.clampY(this.getTargetBlock().getX() + currX, this.getTargetBlock().getY() + currY, this.getTargetBlock().getZ() + currZ)); + this.clampY(this.getTargetBlock().getX() + currX, this.getTargetBlock().getY() + currY, this.getTargetBlock().getZ() + currZ).setTypeIdAndPropertyId(id, (data), false); + } + currZ++; + if (currZ == this.x - this.xRef) + { + currZ = -this.xRef; + currX--; + if (currX == -this.z + this.zRef) + { + currX = +this.zRef; + currY++; + } + } + } + } + else + { + id = (in.readByte() + 128); + data = (in.readByte() + 128); + if (id != 0 && this.clampY(this.getTargetBlock().getX() + currX, this.getTargetBlock().getY() + currY, this.getTargetBlock().getZ() + currZ).isEmpty()) + { // no reason to paste air over + // air, and it prevents us most of + // the time from having to even + // check the block. + undo.put(this.clampY(this.getTargetBlock().getX() + currX, this.getTargetBlock().getY() + currY, this.getTargetBlock().getZ() + currZ)); + this.clampY(this.getTargetBlock().getX() + currX, this.getTargetBlock().getY() + currY, this.getTargetBlock().getZ() + currZ).setTypeIdAndPropertyId(id, (data), false); + } + currZ++; + if (currZ == this.x - this.xRef) + { + currZ = -this.xRef; + currX--; + if (currX == -this.z + this.zRef) + { + currX = +this.zRef; + currY++; + } + } + } + } + } + else + { // replace + for (int i = 1; i < numRuns + 1; i++) + { + if (in.readBoolean()) + { + final int numLoops = in.readByte() + 128; + id = (in.readByte() + 128); + data = (in.readByte() + 128); + for (int j = 0; j < (numLoops); j++) + { + if (id != 0) + { + undo.put(this.clampY(this.getTargetBlock().getX() + currX, this.getTargetBlock().getY() + currY, this.getTargetBlock().getZ() + currZ)); + this.clampY(this.getTargetBlock().getX() + currX, this.getTargetBlock().getY() + currY, this.getTargetBlock().getZ() + currZ).setTypeIdAndPropertyId(id, data, false); + } + currZ++; + if (currZ == this.x - this.xRef) + { + currZ = -this.xRef; + currX--; + if (currX == -this.z + this.zRef) + { + currX = +this.zRef; + currY++; + } + } + } + } + else + { + id = (in.readByte() + 128); + data = (in.readByte() + 128); + if (id != 0) + { + undo.put(this.clampY(this.getTargetBlock().getX() + currX, this.getTargetBlock().getY() + currY, this.getTargetBlock().getZ() + currZ)); + this.clampY(this.getTargetBlock().getX() + currX, this.getTargetBlock().getY() + currY, this.getTargetBlock().getZ() + currZ).setTypeIdAndPropertyId(id, data, false); + } + currZ++; + if (currZ == this.x - this.xRef) + { + currZ = -this.xRef; + currX--; + if (currX == -this.z + this.zRef) + { + currX = +this.zRef; + currY++; + } + } + } + } + } + in.close(); + v.owner().storeUndo(undo); + + } + catch (final Exception exception) + { + v.owner().getPlayer().sendMessage(ChatColor.RED + "Something went wrong."); + exception.printStackTrace(); + } + } + else + { + v.owner().getPlayer().sendMessage(ChatColor.RED + "You need to type a stencil name / your specified stencil does not exist."); + } + } + + @SuppressWarnings("deprecation") + private void stencilPaste90(final SnipeData v) + { + if (this.filename.matches("NoFileLoaded")) + { + v.sendMessage(ChatColor.RED + "You did not specify a filename for the list. This is required."); + return; + } + + final String stencilName = this.readRandomStencil(v); + + final Undo undo = new Undo(); + final File file = new File("plugins/VoxelSniper/stencils/" + stencilName + ".vstencil"); + + if (file.exists()) + { + try + { + final DataInputStream in = new DataInputStream(new BufferedInputStream(new FileInputStream(file))); + + this.x = in.readShort(); + this.z = in.readShort(); + this.y = in.readShort(); + + this.xRef = in.readShort(); + this.zRef = in.readShort(); + this.yRef = in.readShort(); + + final int numRuns = in.readInt(); + // Something here that checks ranks using sanker'world thingie he added to Sniper and boots you out with error message if too big. + final int volume = this.x * this.y * this.z; + v.sendMessage(ChatColor.AQUA + this.filename + " pasted. Volume is " + volume + " blocks."); + + int currX = -this.zRef; // so if your ref point is +5 x, you want to start pasting -5 blocks from the clicked point (the reference) to get the + // corner, for example. + int currZ = +this.xRef; + int currY = -this.yRef; + int id; + int data; + if (this.pasteOption == 0) + { + for (int i = 1; i < numRuns + 1; i++) + { + if (in.readBoolean()) + { + final int numLoops = in.readByte() + 128; + id = (in.readByte() + 128); + data = (in.readByte() + 128); + for (int j = 0; j < numLoops; j++) + { + undo.put(this.clampY(this.getTargetBlock().getX() + currX, this.getTargetBlock().getY() + currY, this.getTargetBlock().getZ() + currZ)); + this.clampY(this.getTargetBlock().getX() + currX, this.getTargetBlock().getY() + currY, this.getTargetBlock().getZ() + currZ).setTypeIdAndPropertyId(id, data, false); + currZ--; + if (currZ == -this.x + this.xRef) + { + currZ = this.xRef; + currX++; + if (currX == this.z - this.zRef) + { + currX = -this.zRef; + currY++; + } + } + } + } + else + { + undo.put(this.clampY(this.getTargetBlock().getX() + currX, this.getTargetBlock().getY() + currY, this.getTargetBlock().getZ() + currZ)); + this.clampY(this.getTargetBlock().getX() + currX, this.getTargetBlock().getY() + currY, this.getTargetBlock().getZ() + currZ).setTypeIdAndPropertyId((in.readByte() + 128), (in.readByte() + 128), false); + currZ--; + if (currZ == -this.x + this.xRef) + { + currZ = this.xRef; + currX++; + if (currX == this.z - this.zRef) + { + currX = -this.zRef; + currY++; + } + } + } + } + } + else if (this.pasteOption == 1) + { + for (int i = 1; i < numRuns + 1; i++) + { + if (in.readBoolean()) + { + final int numLoops = in.readByte() + 128; + id = (in.readByte() + 128); + data = (in.readByte() + 128); + for (int j = 0; j < numLoops; j++) + { + if (id != 0 && this.clampY(this.getTargetBlock().getX() + currX, this.getTargetBlock().getY() + currY, this.getTargetBlock().getZ() + currZ).isEmpty()) + { + undo.put(this.clampY(this.getTargetBlock().getX() + currX, this.getTargetBlock().getY() + currY, this.getTargetBlock().getZ() + currZ)); + this.clampY(this.getTargetBlock().getX() + currX, this.getTargetBlock().getY() + currY, this.getTargetBlock().getZ() + currZ).setTypeIdAndPropertyId(id, (data), false); + } + currZ--; + if (currZ == -this.x + this.xRef) + { + currZ = this.xRef; + currX++; + if (currX == this.z - this.zRef) + { + currX = -this.zRef; + currY++; + } + } + } + } + else + { + id = (in.readByte() + 128); + data = (in.readByte() + 128); + if (id != 0 && this.clampY(this.getTargetBlock().getX() + currX, this.getTargetBlock().getY() + currY, this.getTargetBlock().getZ() + currZ).isEmpty()) + { + undo.put(this.clampY(this.getTargetBlock().getX() + currX, this.getTargetBlock().getY() + currY, this.getTargetBlock().getZ() + currZ)); + this.clampY(this.getTargetBlock().getX() + currX, this.getTargetBlock().getY() + currY, this.getTargetBlock().getZ() + currZ).setTypeIdAndPropertyId(id, (data), false); + } + currZ--; + if (currZ == -this.x + this.xRef) + { + currZ = this.xRef; + currX++; + if (currX == this.z - this.zRef) + { + currX = -this.zRef; + currY++; + } + } + } + } + } + else + { // replace + for (int i = 1; i < numRuns + 1; i++) + { + if (in.readBoolean()) + { + final int numLoops = in.readByte() + 128; + id = (in.readByte() + 128); + data = (in.readByte() + 128); + for (int j = 0; j < (numLoops); j++) + { + if (id != 0) + { + undo.put(this.clampY(this.getTargetBlock().getX() + currX, this.getTargetBlock().getY() + currY, this.getTargetBlock().getZ() + currZ)); + this.clampY(this.getTargetBlock().getX() + currX, this.getTargetBlock().getY() + currY, this.getTargetBlock().getZ() + currZ).setTypeIdAndPropertyId(id, data, false); + } + currZ--; + if (currZ == -this.x + this.xRef) + { + currZ = this.xRef; + currX++; + if (currX == this.z - this.zRef) + { + currX = -this.zRef; + currY++; + } + } + } + } + else + { + id = (in.readByte() + 128); + data = (in.readByte() + 128); + if (id != 0) + { + undo.put(this.clampY(this.getTargetBlock().getX() + currX, this.getTargetBlock().getY() + currY, this.getTargetBlock().getZ() + currZ)); + this.clampY(this.getTargetBlock().getX() + currX, this.getTargetBlock().getY() + currY, this.getTargetBlock().getZ() + currZ).setTypeIdAndPropertyId(id, data, false); + } + currZ--; + if (currZ == -this.x + this.xRef) + { + currZ = this.xRef; + currX++; + if (currX == this.z - this.zRef) + { + currX = -this.zRef; + currY++; + } + } + } + } + } + in.close(); + v.owner().storeUndo(undo); + + } + catch (final Exception exception) + { + v.sendMessage(ChatColor.RED + "Something went wrong."); + exception.printStackTrace(); + } + } + else + { + v.owner().getPlayer().sendMessage(ChatColor.RED + "You need to type a stencil name / your specified stencil does not exist."); + } + } + + private void stencilPasteRotation(final SnipeData v) + { + // just randomly chooses a rotation and then calls stencilPaste. + this.readStencilList(this.filename, v); + final double random = Math.random(); + if (random < 0.26) + { + this.stencilPaste(v); + } + else if (random < 0.51) + { + this.stencilPaste90(v); + } + else if (random < 0.76) + { + this.stencilPaste180(v); + } + else + { + this.stencilPaste270(v); + } + + } + + @Override + protected final void arrow(final SnipeData v) + { + this.stencilPaste(v); + } + + @Override + protected final void powder(final SnipeData v) + { + this.stencilPasteRotation(v); + } + + + @Override + public final void info(final Message vm) + { + vm.brushName(this.getName()); + vm.custom("File loaded: " + this.filename); + } + + @Override + public final void parameters(final String[] par, final SnipeData v) + { + if (par[1].equalsIgnoreCase("info")) + { + v.sendMessage(ChatColor.GOLD + "Stencil List brush Parameters:"); + v.sendMessage(ChatColor.AQUA + "/b schem [optional: 'full' 'fill' or 'replace', with fill as default] [name] -- Loads the specified stencil list. Full/fill/replace must come first. Full = paste all blocks, fill = paste only into air blocks, replace = paste full blocks in only, but replace anything in their way."); + return; + } + else if (par[1].equalsIgnoreCase("full")) + { + this.pasteOption = 0; + this.pasteParam = 1; + } + else if (par[1].equalsIgnoreCase("fill")) + { + this.pasteOption = 1; + this.pasteParam = 1; + } + else if (par[1].equalsIgnoreCase("replace")) + { + this.pasteOption = 2; + this.pasteParam = 1; + } + try + { + this.filename = par[1 + this.pasteParam]; + final File file = new File("plugins/VoxelSniper/stencilLists/" + this.filename + ".txt"); + if (file.exists()) + { + v.sendMessage(ChatColor.RED + "Stencil List '" + this.filename + "' exists and was loaded."); + this.readStencilList(this.filename, v); + } + else + { + v.sendMessage(ChatColor.AQUA + "Stencil List '" + this.filename + "' does not exist. This brush will not function without a valid stencil list."); + this.filename = "NoFileLoaded"; + } + } + catch (final Exception exception) + { + v.sendMessage(ChatColor.RED + "You need to type a stencil name."); + } + } + + @Override + public String getPermissionNode() + { + return "voxelsniper.brush.stencillist"; + } +} diff --git a/favs/src/main/java/com/thevoxelbox/voxelsniper/brush/ThreePointCircleBrush.java b/favs/src/main/java/com/thevoxelbox/voxelsniper/brush/ThreePointCircleBrush.java new file mode 100644 index 000000000..e3477b04b --- /dev/null +++ b/favs/src/main/java/com/thevoxelbox/voxelsniper/brush/ThreePointCircleBrush.java @@ -0,0 +1,238 @@ +package com.thevoxelbox.voxelsniper.brush; + +import com.thevoxelbox.voxelsniper.Message; +import com.thevoxelbox.voxelsniper.SnipeData; +import com.thevoxelbox.voxelsniper.brush.perform.PerformBrush; +import org.bukkit.ChatColor; +import org.bukkit.util.NumberConversions; +import org.bukkit.util.Vector; + +/** + * http://www.voxelwiki.com/minecraft/Voxelsniper#Three-Point_Circle_Brush + * + * @author Giltwist + */ +public class ThreePointCircleBrush extends PerformBrush +{ + private Vector coordsOne; + private Vector coordsTwo; + private Vector coordsThree; + private Tolerance tolerance = Tolerance.DEFAULT; + + /** + * Default Constructor. + */ + public ThreePointCircleBrush() + { + this.setName("3-Point Circle"); + } + + @Override + protected final void arrow(final SnipeData v) + { + if (this.coordsOne == null) + { + this.coordsOne = this.getTargetBlock().getLocation().toVector(); + v.sendMessage(ChatColor.GRAY + "First Corner set."); + } + else if (this.coordsTwo == null) + { + this.coordsTwo = this.getTargetBlock().getLocation().toVector(); + v.sendMessage(ChatColor.GRAY + "Second Corner set."); + } + else if (this.coordsThree == null) + { + this.coordsThree = this.getTargetBlock().getLocation().toVector(); + v.sendMessage(ChatColor.GRAY + "Third Corner set."); + } + else + { + this.coordsOne = this.getTargetBlock().getLocation().toVector(); + this.coordsTwo = null; + this.coordsThree = null; + v.sendMessage(ChatColor.GRAY + "First Corner set."); + } + } + + @Override + protected final void powder(final SnipeData v) + { + if (this.coordsOne == null || this.coordsTwo == null || this.coordsThree == null) + { + return; + } + + // Calculate triangle defining vectors + final Vector vectorOne = this.coordsTwo.clone(); + vectorOne.subtract(this.coordsOne); + final Vector vectorTwo = this.coordsThree.clone(); + vectorTwo.subtract(this.coordsOne); + final Vector vectorThree = this.coordsThree.clone(); + vectorThree.subtract(vectorTwo); + + // Redundant data check + if (vectorOne.length() == 0 || vectorTwo.length() == 0 || vectorThree.length() == 0 || vectorOne.angle(vectorTwo) == 0 || vectorOne.angle(vectorThree) == 0 || vectorThree.angle(vectorTwo) == 0) + { + + v.sendMessage(ChatColor.RED + "ERROR: Invalid points, try again."); + this.coordsOne = null; + this.coordsTwo = null; + this.coordsThree = null; + return; + } + + // Calculate normal vector of the plane. + final Vector normalVector = vectorOne.clone(); + normalVector.crossProduct(vectorTwo); + + // Calculate constant term of the plane. + final double planeConstant = normalVector.getX() * this.coordsOne.getX() + normalVector.getY() * this.coordsOne.getY() + normalVector.getZ() * this.coordsOne.getZ(); + + final Vector midpointOne = this.coordsOne.getMidpoint(this.coordsTwo); + final Vector midpointTwo = this.coordsOne.getMidpoint(this.coordsThree); + + // Find perpendicular vectors to two sides in the plane + final Vector perpendicularOne = normalVector.clone(); + perpendicularOne.crossProduct(vectorOne); + final Vector perpendicularTwo = normalVector.clone(); + perpendicularTwo.crossProduct(vectorTwo); + + // determine value of parametric variable at intersection of two perpendicular bisectors + final Vector tNumerator = midpointTwo.clone(); + tNumerator.subtract(midpointOne); + tNumerator.crossProduct(perpendicularTwo); + final Vector tDenominator = perpendicularOne.clone(); + tDenominator.crossProduct(perpendicularTwo); + final double t = tNumerator.length() / tDenominator.length(); + + // Calculate Circumcenter and Brushcenter. + final Vector circumcenter = new Vector(); + circumcenter.copy(perpendicularOne); + circumcenter.multiply(t); + circumcenter.add(midpointOne); + + final Vector brushCenter = new Vector(Math.round(circumcenter.getX()), Math.round(circumcenter.getY()), Math.round(circumcenter.getZ())); + + // Calculate radius of circumcircle and determine brushsize + final double radius = circumcenter.distance(new Vector(this.coordsOne.getX(), this.coordsOne.getY(), this.coordsOne.getZ())); + final int brushSize = NumberConversions.ceil(radius) + 1; + + for (int x = -brushSize; x <= brushSize; x++) + { + for (int y = -brushSize; y <= brushSize; y++) + { + for (int z = -brushSize; z <= brushSize; z++) + { + // Calculate distance from center + final double tempDistance = Math.pow(Math.pow(x, 2) + Math.pow(y, 2) + Math.pow(z, 2), .5); + + // gets corner-on blocks + final double cornerConstant = normalVector.getX() * (circumcenter.getX() + x) + normalVector.getY() * (circumcenter.getY() + y) + normalVector.getZ() * (circumcenter.getZ() + z); + + // gets center-on blocks + final double centerConstant = normalVector.getX() * (circumcenter.getX() + x + .5) + normalVector.getY() * (circumcenter.getY() + y + .5) + normalVector.getZ() * (circumcenter.getZ() + z + .5); + + // Check if point is within sphere and on plane (some tolerance given) + if (tempDistance <= radius && (Math.abs(cornerConstant - planeConstant) < this.tolerance.getValue() || Math.abs(centerConstant - planeConstant) < this.tolerance.getValue())) + { + this.current.perform(this.clampY(brushCenter.getBlockX() + x, brushCenter.getBlockY() + y, brushCenter.getBlockZ() + z)); + } + + } + } + } + + v.sendMessage(ChatColor.GREEN + "Done."); + v.owner().storeUndo(this.current.getUndo()); + + // Reset Brush + this.coordsOne = null; + this.coordsTwo = null; + this.coordsThree = null; + + } + + @Override + public final void info(final Message vm) + { + vm.brushName(this.getName()); + switch (this.tolerance) + { + case ACCURATE: + vm.custom(ChatColor.GOLD + "Mode: Accurate"); + break; + case DEFAULT: + vm.custom(ChatColor.GOLD + "Mode: Default"); + break; + case SMOOTH: + vm.custom(ChatColor.GOLD + "Mode: Smooth"); + break; + default: + vm.custom(ChatColor.GOLD + "Mode: Unknown"); + break; + } + + } + + @Override + public final void parameters(final String[] par, final SnipeData v) + { + if (par[1].equalsIgnoreCase("info")) + { + v.sendMessage(ChatColor.YELLOW + "3-Point Circle Brush instructions: Select three corners with the arrow brush, then generate the Circle with the powder brush."); + String toleranceOptions = ""; + for (final Tolerance tolerance : Tolerance.values()) + { + if (!toleranceOptions.isEmpty()) + { + toleranceOptions += "|"; + } + toleranceOptions += tolerance.name().toLowerCase(); + } + v.sendMessage(ChatColor.GOLD + "/b tpc " + toleranceOptions + " -- Toggle the calculations to emphasize accuracy or smoothness"); + return; + } + + for (int i = 1; i < par.length; i++) + { + final String parameter = par[i].toUpperCase(); + try + { + this.tolerance = Tolerance.valueOf(parameter); + v.sendMessage(ChatColor.AQUA + "Brush set to " + this.tolerance.name().toLowerCase() + " tolerance."); + return; + } + catch (final IllegalArgumentException exception) + { + v.getVoxelMessage().brushMessage("No such tolerance."); + } + } + } + + /** + * Enumeration on Tolerance values. + * + * @author MikeMatrix + */ + private enum Tolerance + { + DEFAULT(1000), ACCURATE(10), SMOOTH(2000); + private int value; + + Tolerance(final int value) + { + this.value = value; + } + + public int getValue() + { + return this.value; + } + } + + @Override + public String getPermissionNode() + { + return "voxelsniper.brush.threepointcircle"; + } +} diff --git a/favs/src/main/java/com/thevoxelbox/voxelsniper/brush/TreeSnipeBrush.java b/favs/src/main/java/com/thevoxelbox/voxelsniper/brush/TreeSnipeBrush.java new file mode 100644 index 000000000..fc4e01e27 --- /dev/null +++ b/favs/src/main/java/com/thevoxelbox/voxelsniper/brush/TreeSnipeBrush.java @@ -0,0 +1,132 @@ +package com.thevoxelbox.voxelsniper.brush; + +import com.boydti.fawe.bukkit.wrapper.AsyncBlock; +import com.boydti.fawe.bukkit.wrapper.AsyncBlockState; +import com.google.common.base.Objects; +import com.thevoxelbox.voxelsniper.Message; +import com.thevoxelbox.voxelsniper.SnipeData; +import com.thevoxelbox.voxelsniper.Undo; +import com.thevoxelbox.voxelsniper.util.UndoDelegate; +import org.bukkit.ChatColor; +import org.bukkit.Material; +import org.bukkit.TreeType; +import org.bukkit.block.Block; +import org.bukkit.block.BlockFace; +import org.bukkit.block.BlockState; + + +/** + * http://www.voxelwiki.com/minecraft/Voxelsniper#The_Tree_Brush + * + * @author Mick + */ +public class TreeSnipeBrush extends Brush +{ + private TreeType treeType = TreeType.TREE; + + /** + * + */ + public TreeSnipeBrush() + { + this.setName("Tree Snipe"); + } + + @SuppressWarnings("deprecation") + private void single(final SnipeData v, AsyncBlock targetBlock) + { + UndoDelegate undoDelegate = new UndoDelegate(targetBlock.getWorld()); + AsyncBlock blockBelow = targetBlock.getRelative(BlockFace.DOWN); + AsyncBlockState currentState = blockBelow.getState(); + undoDelegate.setBlock(blockBelow); + blockBelow.setType(Material.GRASS); + this.getWorld().generateTree(targetBlock.getLocation(), this.treeType, undoDelegate); + Undo undo = undoDelegate.getUndo(); + blockBelow.setTypeIdAndPropertyId(currentState.getTypeId(), currentState.getPropertyId(), true); + undo.put(blockBelow); + v.owner().storeUndo(undo); + } + + private int getYOffset() + { + for (int i = 1; i < (getTargetBlock().getWorld().getMaxHeight() - 1 - getTargetBlock().getY()); i++) + { + if (Objects.equal(getTargetBlock().getRelative(0, i + 1, 0).getType(), Material.AIR)) + { + return i; + } + } + return 0; + } + + private void printTreeType(final Message vm) + { + String printout = ""; + + boolean delimiterHelper = true; + for (final TreeType treeType : TreeType.values()) + { + if (delimiterHelper) + { + delimiterHelper = false; + } + else + { + printout += ", "; + } + printout += ((treeType.equals(this.treeType)) ? ChatColor.GRAY + treeType.name().toLowerCase() : ChatColor.DARK_GRAY + treeType.name().toLowerCase()) + ChatColor.WHITE; + } + + vm.custom(printout); + } + + @Override + protected final void arrow(final SnipeData v) + { + AsyncBlock targetBlock = getTargetBlock().getRelative(0, getYOffset(), 0); + this.single(v, targetBlock); + } + + @Override + protected final void powder(final SnipeData v) + { + this.single(v, getTargetBlock()); + } + + @Override + public final void info(final Message vm) + { + vm.brushName(this.getName()); + this.printTreeType(vm); + } + + @Override + public final void parameters(final String[] par, final SnipeData v) + { + for (int i = 1; i < par.length; i++) + { + if (par[i].equalsIgnoreCase("info")) + { + v.sendMessage(ChatColor.GOLD + "Tree snipe brush:"); + v.sendMessage(ChatColor.AQUA + "/b t treetype"); + this.printTreeType(v.getVoxelMessage()); + return; + } + try + { + this.treeType = TreeType.valueOf(par[i].toUpperCase()); + this.printTreeType(v.getVoxelMessage()); + } + catch (final IllegalArgumentException exception) + { + v.getVoxelMessage().brushMessage("No such tree type."); + } + } + } + + @Override + public String getPermissionNode() + { + return "voxelsniper.brush.treesnipe"; + } +} diff --git a/favs/src/main/java/com/thevoxelbox/voxelsniper/brush/TriangleBrush.java b/favs/src/main/java/com/thevoxelbox/voxelsniper/brush/TriangleBrush.java new file mode 100644 index 000000000..3343880f5 --- /dev/null +++ b/favs/src/main/java/com/thevoxelbox/voxelsniper/brush/TriangleBrush.java @@ -0,0 +1,334 @@ +package com.thevoxelbox.voxelsniper.brush; + +import com.thevoxelbox.voxelsniper.Message; +import com.thevoxelbox.voxelsniper.SnipeData; +import com.thevoxelbox.voxelsniper.brush.perform.PerformBrush; +import org.bukkit.ChatColor; + +/** + * http://www.voxelwiki.com/minecraft/Voxelsniper#Triangle_Brush + * + * @author Giltwist + */ +public class TriangleBrush extends PerformBrush +{ + private double[] coordsOne = new double[3]; // Three corners + private double[] coordsTwo = new double[3]; + private double[] coordsThree = new double[3]; + private int cornernumber = 1; + private double[] currentCoords = new double[3]; // For loop tracking + private double[] vectorOne = new double[3]; // Point 1 to 2 + private double[] vectorTwo = new double[3]; // Point 1 to 3 + private double[] vectorThree = new double[3]; // Point 2 to 3, for area calculations + private double[] normalVector = new double[3]; + + /** + * + */ + public TriangleBrush() + { + this.setName("Triangle"); + } + + private void triangleA(final SnipeData v) + { + switch (this.cornernumber) + { + case 1: + this.coordsOne[0] = this.getTargetBlock().getX() + .5 * this.getTargetBlock().getX() / Math.abs(this.getTargetBlock().getX()); // I hate you sometimes, Notch. Really? Every quadrant is + // different? + this.coordsOne[1] = this.getTargetBlock().getY() + .5; + this.coordsOne[2] = this.getTargetBlock().getZ() + .5 * this.getTargetBlock().getZ() / Math.abs(this.getTargetBlock().getZ()); + this.cornernumber = 2; + v.sendMessage(ChatColor.GRAY + "First Corner set."); + break; + case 2: + this.coordsTwo[0] = this.getTargetBlock().getX() + .5 * this.getTargetBlock().getX() / Math.abs(this.getTargetBlock().getX()); // I hate you sometimes, Notch. Really? Every quadrant is + // different? + this.coordsTwo[1] = this.getTargetBlock().getY() + .5; + this.coordsTwo[2] = this.getTargetBlock().getZ() + .5 * this.getTargetBlock().getZ() / Math.abs(this.getTargetBlock().getZ()); + this.cornernumber = 3; + v.sendMessage(ChatColor.GRAY + "Second Corner set."); + break; + case 3: + this.coordsThree[0] = this.getTargetBlock().getX() + .5 * this.getTargetBlock().getX() / Math.abs(this.getTargetBlock().getX()); // I hate you sometimes, Notch. Really? Every quadrant is + // different? + this.coordsThree[1] = this.getTargetBlock().getY() + .5; + this.coordsThree[2] = this.getTargetBlock().getZ() + .5 * this.getTargetBlock().getZ() / Math.abs(this.getTargetBlock().getZ()); + this.cornernumber = 1; + v.sendMessage(ChatColor.GRAY + "Third Corner set."); + break; + default: + break; + + } + + } + + private void triangleP(final SnipeData v) + { + double lengthOne = 0; + double lengthTwo = 0; + double lengthThree = 0; + double heronBig = 0; + + // Calculate slope vectors + for (int i = 0; i < 3; i++) + { + this.vectorOne[i] = this.coordsTwo[i] - this.coordsOne[i]; + this.vectorTwo[i] = this.coordsThree[i] - this.coordsOne[i]; + this.vectorThree[i] = this.coordsThree[i] - this.coordsTwo[i]; + } + + // Calculate the cross product of vectorone and vectortwo + this.normalVector[0] = this.vectorOne[1] * this.vectorTwo[2] - this.vectorOne[2] * this.vectorTwo[1]; + this.normalVector[1] = this.vectorOne[2] * this.vectorTwo[0] - this.vectorOne[0] * this.vectorTwo[2]; + this.normalVector[2] = this.vectorOne[0] * this.vectorTwo[1] - this.vectorOne[1] * this.vectorTwo[0]; + + // Calculate magnitude of slope vectors + lengthOne = Math.pow(Math.pow(this.vectorOne[0], 2) + Math.pow(this.vectorOne[1], 2) + Math.pow(this.vectorOne[2], 2), .5); + lengthTwo = Math.pow(Math.pow(this.vectorTwo[0], 2) + Math.pow(this.vectorTwo[1], 2) + Math.pow(this.vectorTwo[2], 2), .5); + lengthThree = Math.pow(Math.pow(this.vectorThree[0], 2) + Math.pow(this.vectorThree[1], 2) + Math.pow(this.vectorThree[2], 2), .5); + + // Bigger vector determines brush size + final int brushSize = (int) Math.ceil((lengthOne > lengthTwo) ? lengthOne : lengthTwo); + + // Calculate constant term + final double planeConstant = this.normalVector[0] * this.coordsOne[0] + this.normalVector[1] * this.coordsOne[1] + this.normalVector[2] * this.coordsOne[2]; + + // Calculate the area of the full triangle + heronBig = .25 * Math.pow(Math.pow(Math.pow(lengthOne, 2) + Math.pow(lengthTwo, 2) + Math.pow(lengthThree, 2), 2) - 2 * (Math.pow(lengthOne, 4) + Math.pow(lengthTwo, 4) + Math.pow(lengthThree, 4)), .5); + + if (lengthOne == 0 || lengthTwo == 0 || (this.coordsOne[0] == 0 && this.coordsOne[1] == 0 && this.coordsOne[2] == 0) || (this.coordsTwo[0] == 0 && this.coordsTwo[1] == 0 && this.coordsTwo[2] == 0) || (this.coordsThree[0] == 0 && this.coordsThree[1] == 0 && this.coordsThree[2] == 0)) + { + v.sendMessage(ChatColor.RED + "ERROR: Invalid corners, please try again."); + } + else + { + // Make the Changes + final double[] cVectorOne = new double[3]; + final double[] cVectorTwo = new double[3]; + final double[] cVectorThree = new double[3]; + + for (int y = -brushSize; y <= brushSize; y++) + { // X DEPENDENT + for (int z = -brushSize; z <= brushSize; z++) + { + this.currentCoords[1] = this.coordsOne[1] + y; + this.currentCoords[2] = this.coordsOne[2] + z; + this.currentCoords[0] = (planeConstant - this.normalVector[1] * this.currentCoords[1] - this.normalVector[2] * this.currentCoords[2]) / this.normalVector[0]; + + // Area of triangle currentcoords, coordsone, coordstwo + for (int i = 0; i < 3; i++) + { + cVectorOne[i] = this.coordsTwo[i] - this.coordsOne[i]; + cVectorTwo[i] = this.currentCoords[i] - this.coordsOne[i]; + cVectorThree[i] = this.currentCoords[i] - this.coordsTwo[i]; + } + double cLengthOne = Math.pow(Math.pow(cVectorOne[0], 2) + Math.pow(cVectorOne[1], 2) + Math.pow(cVectorOne[2], 2), .5); + double cLengthTwo = Math.pow(Math.pow(cVectorTwo[0], 2) + Math.pow(cVectorTwo[1], 2) + Math.pow(cVectorTwo[2], 2), .5); + double cLengthThree = Math.pow(Math.pow(cVectorThree[0], 2) + Math.pow(cVectorThree[1], 2) + Math.pow(cVectorThree[2], 2), .5); + + final double heronOne = .25 * Math.pow(Math.pow(Math.pow(cLengthOne, 2) + Math.pow(cLengthTwo, 2) + Math.pow(cLengthThree, 2), 2) - 2 * (Math.pow(cLengthOne, 4) + Math.pow(cLengthTwo, 4) + Math.pow(cLengthThree, 4)), .5); + + // Area of triangle currentcoords, coordsthree, coordstwo + for (int i = 0; i < 3; i++) + { + cVectorOne[i] = this.coordsTwo[i] - this.coordsThree[i]; + cVectorTwo[i] = this.currentCoords[i] - this.coordsThree[i]; + cVectorThree[i] = this.currentCoords[i] - this.coordsTwo[i]; + } + cLengthOne = Math.pow(Math.pow(cVectorOne[0], 2) + Math.pow(cVectorOne[1], 2) + Math.pow(cVectorOne[2], 2), .5); + cLengthTwo = Math.pow(Math.pow(cVectorTwo[0], 2) + Math.pow(cVectorTwo[1], 2) + Math.pow(cVectorTwo[2], 2), .5); + cLengthThree = Math.pow(Math.pow(cVectorThree[0], 2) + Math.pow(cVectorThree[1], 2) + Math.pow(cVectorThree[2], 2), .5); + final double heronTwo = .25 * Math.pow(Math.pow(Math.pow(cLengthOne, 2) + Math.pow(cLengthTwo, 2) + Math.pow(cLengthThree, 2), 2) - 2 * (Math.pow(cLengthOne, 4) + Math.pow(cLengthTwo, 4) + Math.pow(cLengthThree, 4)), .5); + + // Area of triangle currentcoords, coordsthree, coordsone + for (int i = 0; i < 3; i++) + { + cVectorOne[i] = this.coordsOne[i] - this.coordsThree[i]; + cVectorTwo[i] = this.currentCoords[i] - this.coordsThree[i]; + cVectorThree[i] = this.currentCoords[i] - this.coordsOne[i]; + } + cLengthOne = Math.pow(Math.pow(cVectorOne[0], 2) + Math.pow(cVectorOne[1], 2) + Math.pow(cVectorOne[2], 2), .5); + cLengthTwo = Math.pow(Math.pow(cVectorTwo[0], 2) + Math.pow(cVectorTwo[1], 2) + Math.pow(cVectorTwo[2], 2), .5); + cLengthThree = Math.pow(Math.pow(cVectorThree[0], 2) + Math.pow(cVectorThree[1], 2) + Math.pow(cVectorThree[2], 2), .5); + final double heronThree = .25 * Math.pow(Math.pow(Math.pow(cLengthOne, 2) + Math.pow(cLengthTwo, 2) + Math.pow(cLengthThree, 2), 2) - 2 * (Math.pow(cLengthOne, 4) + Math.pow(cLengthTwo, 4) + Math.pow(cLengthThree, 4)), .5); + + final double barycentric = (heronOne + heronTwo + heronThree) / heronBig; + + if (barycentric <= 1.1) + { + + this.current.perform(this.clampY((int) this.currentCoords[0], (int) this.currentCoords[1], (int) this.currentCoords[2])); + + } + + } + } // END X DEPENDENT + + for (int x = -brushSize; x <= brushSize; x++) + { // Y DEPENDENT + for (int z = -brushSize; z <= brushSize; z++) + { + this.currentCoords[0] = this.coordsOne[0] + x; + this.currentCoords[2] = this.coordsOne[2] + z; + this.currentCoords[1] = (planeConstant - this.normalVector[0] * this.currentCoords[0] - this.normalVector[2] * this.currentCoords[2]) / this.normalVector[1]; + + // Area of triangle currentcoords, coordsone, coordstwo + for (int i = 0; i < 3; i++) + { + cVectorOne[i] = this.coordsTwo[i] - this.coordsOne[i]; + cVectorTwo[i] = this.currentCoords[i] - this.coordsOne[i]; + cVectorThree[i] = this.currentCoords[i] - this.coordsTwo[i]; + } + double cLengthOne = Math.pow(Math.pow(cVectorOne[0], 2) + Math.pow(cVectorOne[1], 2) + Math.pow(cVectorOne[2], 2), .5); + double cLengthTwo = Math.pow(Math.pow(cVectorTwo[0], 2) + Math.pow(cVectorTwo[1], 2) + Math.pow(cVectorTwo[2], 2), .5); + double cLengthThree = Math.pow(Math.pow(cVectorThree[0], 2) + Math.pow(cVectorThree[1], 2) + Math.pow(cVectorThree[2], 2), .5); + + final double heronOne = .25 * Math.pow(Math.pow(Math.pow(cLengthOne, 2) + Math.pow(cLengthTwo, 2) + Math.pow(cLengthThree, 2), 2) - 2 * (Math.pow(cLengthOne, 4) + Math.pow(cLengthTwo, 4) + Math.pow(cLengthThree, 4)), .5); + + // Area of triangle currentcoords, coordsthree, coordstwo + for (int i = 0; i < 3; i++) + { + cVectorOne[i] = this.coordsTwo[i] - this.coordsThree[i]; + cVectorTwo[i] = this.currentCoords[i] - this.coordsThree[i]; + cVectorThree[i] = this.currentCoords[i] - this.coordsTwo[i]; + } + cLengthOne = Math.pow(Math.pow(cVectorOne[0], 2) + Math.pow(cVectorOne[1], 2) + Math.pow(cVectorOne[2], 2), .5); + cLengthTwo = Math.pow(Math.pow(cVectorTwo[0], 2) + Math.pow(cVectorTwo[1], 2) + Math.pow(cVectorTwo[2], 2), .5); + cLengthThree = Math.pow(Math.pow(cVectorThree[0], 2) + Math.pow(cVectorThree[1], 2) + Math.pow(cVectorThree[2], 2), .5); + final double heronTwo = .25 * Math.pow(Math.pow(Math.pow(cLengthOne, 2) + Math.pow(cLengthTwo, 2) + Math.pow(cLengthThree, 2), 2) - 2 * (Math.pow(cLengthOne, 4) + Math.pow(cLengthTwo, 4) + Math.pow(cLengthThree, 4)), .5); + + // Area of triangle currentcoords, coordsthree, coordsone + for (int i = 0; i < 3; i++) + { + cVectorOne[i] = this.coordsOne[i] - this.coordsThree[i]; + cVectorTwo[i] = this.currentCoords[i] - this.coordsThree[i]; + cVectorThree[i] = this.currentCoords[i] - this.coordsOne[i]; + } + cLengthOne = Math.pow(Math.pow(cVectorOne[0], 2) + Math.pow(cVectorOne[1], 2) + Math.pow(cVectorOne[2], 2), .5); + cLengthTwo = Math.pow(Math.pow(cVectorTwo[0], 2) + Math.pow(cVectorTwo[1], 2) + Math.pow(cVectorTwo[2], 2), .5); + cLengthThree = Math.pow(Math.pow(cVectorThree[0], 2) + Math.pow(cVectorThree[1], 2) + Math.pow(cVectorThree[2], 2), .5); + final double heronThree = .25 * Math.pow(Math.pow(Math.pow(cLengthOne, 2) + Math.pow(cLengthTwo, 2) + Math.pow(cLengthThree, 2), 2) - 2 * (Math.pow(cLengthOne, 4) + Math.pow(cLengthTwo, 4) + Math.pow(cLengthThree, 4)), .5); + + final double barycentric = (heronOne + heronTwo + heronThree) / heronBig; + + if (barycentric <= 1.1) + { + + this.current.perform(this.clampY((int) this.currentCoords[0], (int) this.currentCoords[1], (int) this.currentCoords[2])); + + } + + } + } // END Y DEPENDENT + for (int x = -brushSize; x <= brushSize; x++) + { // Z DEPENDENT + for (int y = -brushSize; y <= brushSize; y++) + { + this.currentCoords[0] = this.coordsOne[0] + x; + this.currentCoords[1] = this.coordsOne[1] + y; + this.currentCoords[2] = (planeConstant - this.normalVector[0] * this.currentCoords[0] - this.normalVector[1] * this.currentCoords[1]) / this.normalVector[2]; + + // Area of triangle currentcoords, coordsone, coordstwo + for (int i = 0; i < 3; i++) + { + cVectorOne[i] = this.coordsTwo[i] - this.coordsOne[i]; + cVectorTwo[i] = this.currentCoords[i] - this.coordsOne[i]; + cVectorThree[i] = this.currentCoords[i] - this.coordsTwo[i]; + } + double cLengthOne = Math.pow(Math.pow(cVectorOne[0], 2) + Math.pow(cVectorOne[1], 2) + Math.pow(cVectorOne[2], 2), .5); + double cLengthTwo = Math.pow(Math.pow(cVectorTwo[0], 2) + Math.pow(cVectorTwo[1], 2) + Math.pow(cVectorTwo[2], 2), .5); + double cLengthThree = Math.pow(Math.pow(cVectorThree[0], 2) + Math.pow(cVectorThree[1], 2) + Math.pow(cVectorThree[2], 2), .5); + + final double heronOne = .25 * Math.pow(Math.pow(Math.pow(cLengthOne, 2) + Math.pow(cLengthTwo, 2) + Math.pow(cLengthThree, 2), 2) - 2 * (Math.pow(cLengthOne, 4) + Math.pow(cLengthTwo, 4) + Math.pow(cLengthThree, 4)), .5); + + // Area of triangle currentcoords, coordsthree, coordstwo + for (int i = 0; i < 3; i++) + { + cVectorOne[i] = this.coordsTwo[i] - this.coordsThree[i]; + cVectorTwo[i] = this.currentCoords[i] - this.coordsThree[i]; + cVectorThree[i] = this.currentCoords[i] - this.coordsTwo[i]; + } + cLengthOne = Math.pow(Math.pow(cVectorOne[0], 2) + Math.pow(cVectorOne[1], 2) + Math.pow(cVectorOne[2], 2), .5); + cLengthTwo = Math.pow(Math.pow(cVectorTwo[0], 2) + Math.pow(cVectorTwo[1], 2) + Math.pow(cVectorTwo[2], 2), .5); + cLengthThree = Math.pow(Math.pow(cVectorThree[0], 2) + Math.pow(cVectorThree[1], 2) + Math.pow(cVectorThree[2], 2), .5); + final double heronTwo = .25 * Math.pow(Math.pow(Math.pow(cLengthOne, 2) + Math.pow(cLengthTwo, 2) + Math.pow(cLengthThree, 2), 2) - 2 * (Math.pow(cLengthOne, 4) + Math.pow(cLengthTwo, 4) + Math.pow(cLengthThree, 4)), .5); + + // Area of triangle currentcoords, coordsthree, coordsone + for (int i = 0; i < 3; i++) + { + cVectorOne[i] = this.coordsOne[i] - this.coordsThree[i]; + cVectorTwo[i] = this.currentCoords[i] - this.coordsThree[i]; + cVectorThree[i] = this.currentCoords[i] - this.coordsOne[i]; + } + cLengthOne = Math.pow(Math.pow(cVectorOne[0], 2) + Math.pow(cVectorOne[1], 2) + Math.pow(cVectorOne[2], 2), .5); + cLengthTwo = Math.pow(Math.pow(cVectorTwo[0], 2) + Math.pow(cVectorTwo[1], 2) + Math.pow(cVectorTwo[2], 2), .5); + cLengthThree = Math.pow(Math.pow(cVectorThree[0], 2) + Math.pow(cVectorThree[1], 2) + Math.pow(cVectorThree[2], 2), .5); + final double heronThree = .25 * Math.pow(Math.pow(Math.pow(cLengthOne, 2) + Math.pow(cLengthTwo, 2) + Math.pow(cLengthThree, 2), 2) - 2 * (Math.pow(cLengthOne, 4) + Math.pow(cLengthTwo, 4) + Math.pow(cLengthThree, 4)), .5); + + final double barycentric = (heronOne + heronTwo + heronThree) / heronBig; + + // VoxelSniper.log.info("Bary: "+barycentric+", hb: "+heronbig+", h1: "+heronone+", h2: "+herontwo+", h3: "+heronthree); + + if (barycentric <= 1.1) + { + this.current.perform(this.clampY((int) this.currentCoords[0], (int) this.currentCoords[1], (int) this.currentCoords[2])); + } + } + } // END Z DEPENDENT + + v.owner().storeUndo(this.current.getUndo()); + + } + + // RESET BRUSH + this.coordsOne[0] = 0; + this.coordsOne[1] = 0; + this.coordsOne[2] = 0; + this.coordsTwo[0] = 0; + this.coordsTwo[1] = 0; + this.coordsTwo[2] = 0; + this.coordsThree[0] = 0; + this.coordsThree[1] = 0; + this.coordsThree[2] = 0; + + this.cornernumber = 1; + + } + + @Override + protected final void arrow(final SnipeData v) + { + this.triangleA(v); + } + + @Override + protected final void powder(final SnipeData v) + { // Add a point + this.triangleP(v); + } + + + @Override + public final void info(final Message vm) + { // Make the triangle + vm.brushName(this.getName()); + } + + @Override + public final void parameters(final String[] par, final SnipeData v) + { + if (par[1].equalsIgnoreCase("info")) + { + v.sendMessage(ChatColor.GOLD + "Triangle Brush instructions: Select three corners with the arrow brush, then generate the triangle with the powder brush."); + } + } + + @Override + public String getPermissionNode() + { + return "voxelsniper.brush.triangle"; + } +} diff --git a/favs/src/main/java/com/thevoxelbox/voxelsniper/brush/UnderlayBrush.java b/favs/src/main/java/com/thevoxelbox/voxelsniper/brush/UnderlayBrush.java new file mode 100644 index 000000000..7311e7e3b --- /dev/null +++ b/favs/src/main/java/com/thevoxelbox/voxelsniper/brush/UnderlayBrush.java @@ -0,0 +1,198 @@ +package com.thevoxelbox.voxelsniper.brush; + +import com.sk89q.worldedit.blocks.BlockMaterial; +import com.sk89q.worldedit.world.block.BlockTypes; +import com.thevoxelbox.voxelsniper.Message; +import com.thevoxelbox.voxelsniper.SnipeData; +import com.thevoxelbox.voxelsniper.brush.perform.PerformBrush; +import org.bukkit.ChatColor; + +/** + * http://www.voxelwiki.com/minecraft/Voxelsniper#Underlay_Brush + * + * @author jmck95 Credit to GavJenks for framework and 95 of code. Big Thank you to GavJenks + */ + +public class UnderlayBrush extends PerformBrush +{ + private static final int DEFAULT_DEPTH = 3; + private int depth = DEFAULT_DEPTH; + private boolean allBlocks = false; + + /** + * + */ + public UnderlayBrush() + { + this.setName("Underlay (Reverse Overlay)"); + } + + @SuppressWarnings("deprecation") + private void underlay(final SnipeData v) + { + final int[][] memory = new int[v.getBrushSize() * 2 + 1][v.getBrushSize() * 2 + 1]; + final double brushSizeSquared = Math.pow(v.getBrushSize() + 0.5, 2); + + for (int z = v.getBrushSize(); z >= -v.getBrushSize(); z--) + { + for (int x = v.getBrushSize(); x >= -v.getBrushSize(); x--) + { + for (int y = this.getTargetBlock().getY(); y < this.getTargetBlock().getY() + this.depth; y++) + { // start scanning from the height you clicked at + if (memory[x + v.getBrushSize()][z + v.getBrushSize()] != 1) + { // if haven't already found the surface in this column + if ((Math.pow(x, 2) + Math.pow(z, 2)) <= brushSizeSquared) + { // if inside of the column... + if (!this.allBlocks) + { // if the override parameter has not been activated, go to the switch that filters out manmade stuff. + int id = this.getBlockIdAt(this.getTargetBlock().getX() + x, y, this.getTargetBlock().getZ() + z); + BlockMaterial mat = BlockTypes.get(id).getMaterial(); + if (!mat.isReplacedDuringPlacement() && mat.isFullCube()) { + for (int d = 0; (d < this.depth); d++) { + if (this.clampY(this.getTargetBlock().getX() + x, y + d, this.getTargetBlock().getZ() + z).getTypeId() != 0) { + this.current.perform(this.clampY(this.getTargetBlock().getX() + x, y + d, this.getTargetBlock().getZ() + z)); // fills down as many layers as you specify in + // parameters + memory[x + v.getBrushSize()][z + v.getBrushSize()] = 1; // stop it from checking any other blocks in this vertical 1x1 column. + } + } + break; + + } else { + continue; + } + } + else + { + for (int d = 0; (d < this.depth); d++) + { + if (this.clampY(this.getTargetBlock().getX() + x, y + d, this.getTargetBlock().getZ() + z).getTypeId() != 0) + { + this.current.perform(this.clampY(this.getTargetBlock().getX() + x, y + d, this.getTargetBlock().getZ() + z)); // fills down as many layers as you specify in + // parameters + memory[x + v.getBrushSize()][z + v.getBrushSize()] = 1; // stop it from checking any other blocks in this vertical 1x1 column. + } + } + } + } + + } + } + } + } + + v.owner().storeUndo(this.current.getUndo()); + } + + private void underlay2(final SnipeData v) + { + final int[][] memory = new int[v.getBrushSize() * 2 + 1][v.getBrushSize() * 2 + 1]; + final double brushSizeSquared = Math.pow(v.getBrushSize() + 0.5, 2); + + for (int z = v.getBrushSize(); z >= -v.getBrushSize(); z--) + { + for (int x = v.getBrushSize(); x >= -v.getBrushSize(); x--) + { + for (int y = this.getTargetBlock().getY(); y < this.getTargetBlock().getY() + this.depth; y++) + { // start scanning from the height you clicked at + if (memory[x + v.getBrushSize()][z + v.getBrushSize()] != 1) + { // if haven't already found the surface in this column + if ((Math.pow(x, 2) + Math.pow(z, 2)) <= brushSizeSquared) + { // if inside of the column... + + if (!this.allBlocks) + { // if the override parameter has not been activated, go to the switch that filters out manmade stuff. + + int id = this.getBlockIdAt(this.getTargetBlock().getX() + x, y, this.getTargetBlock().getZ() + z); + BlockMaterial mat = BlockTypes.get(id).getMaterial(); + if (!mat.isReplacedDuringPlacement() && mat.isFullCube()) { + for (int d = -1; (d < this.depth - 1); d++) { + this.current.perform(this.clampY(this.getTargetBlock().getX() + x, y - d, this.getTargetBlock().getZ() + z)); // fills down as many layers as you specify in + // parameters + memory[x + v.getBrushSize()][z + v.getBrushSize()] = 1; // stop it from checking any other blocks in this vertical 1x1 column. + } + break; + } else { + continue; + } + } + else + { + for (int d = -1; (d < this.depth - 1); d++) + { + this.current.perform(this.clampY(this.getTargetBlock().getX() + x, y - d, this.getTargetBlock().getZ() + z)); // fills down as many layers as you specify in + // parameters + memory[x + v.getBrushSize()][z + v.getBrushSize()] = 1; // stop it from checking any other blocks in this vertical 1x1 column. + } + } + } + } + } + } + } + + v.owner().storeUndo(this.current.getUndo()); + } + + @Override + public final void arrow(final SnipeData v) + { + this.underlay(v); + } + + @Override + public final void powder(final SnipeData v) + { + this.underlay2(v); + } + + @Override + public final void info(final Message vm) + { + vm.brushName(this.getName()); + vm.size(); + } + + @Override + public final void parameters(final String[] par, final SnipeData v) + { + for (int i = 1; i < par.length; i++) + { + if (par[i].equalsIgnoreCase("info")) + { + v.owner().getPlayer().sendMessage(ChatColor.GOLD + "Reverse Overlay brush parameters:"); + v.owner().getPlayer().sendMessage(ChatColor.AQUA + "d[number] (ex: d3) The number of blocks thick to change."); + v.owner().getPlayer().sendMessage(ChatColor.BLUE + "all (ex: /b reover all) Sets the brush to affect ALL materials"); + if (this.depth < 1) + { + this.depth = 1; + } + return; + } + if (par[i].startsWith("d")) + { + this.depth = Integer.parseInt(par[i].replace("d", "")); + v.owner().getPlayer().sendMessage(ChatColor.AQUA + "Depth set to " + this.depth); + } + else if (par[i].startsWith("all")) + { + this.allBlocks = true; + v.owner().getPlayer().sendMessage(ChatColor.BLUE + "Will underlay over any block." + this.depth); + } + else if (par[i].startsWith("some")) + { + this.allBlocks = false; + v.owner().getPlayer().sendMessage(ChatColor.BLUE + "Will underlay only natural block types." + this.depth); + } + else + { + v.owner().getPlayer().sendMessage(ChatColor.RED + "Invalid brush parameters! use the info parameter to display parameter info."); + } + } + } + + @Override + public String getPermissionNode() + { + return "voxelsniper.brush.underlay"; + } +} diff --git a/favs/src/main/java/com/thevoxelbox/voxelsniper/brush/VoltMeterBrush.java b/favs/src/main/java/com/thevoxelbox/voxelsniper/brush/VoltMeterBrush.java new file mode 100644 index 000000000..a4fc280d7 --- /dev/null +++ b/favs/src/main/java/com/thevoxelbox/voxelsniper/brush/VoltMeterBrush.java @@ -0,0 +1,71 @@ +package com.thevoxelbox.voxelsniper.brush; + +import com.boydti.fawe.bukkit.wrapper.AsyncBlock; +import com.thevoxelbox.voxelsniper.Message; +import com.thevoxelbox.voxelsniper.SnipeData; +import org.bukkit.ChatColor; +import org.bukkit.block.Block; +import org.bukkit.block.BlockFace; + +/** + * http://www.voxelwiki.com/minecraft/Voxelsniper#The_Volt-Meter_Brush + * + * @author Gavjenks + */ +public class VoltMeterBrush extends Brush +{ + /** + * + */ + public VoltMeterBrush() + { + this.setName("VoltMeter"); + } + + @SuppressWarnings("deprecation") + private void data(final SnipeData v) + { + final AsyncBlock block = this.clampY(this.getTargetBlock().getX(), this.getTargetBlock().getY(), this.getTargetBlock().getZ()); + final int data = block.getPropertyId(); + v.sendMessage(ChatColor.AQUA + "Blocks until repeater needed: " + data); + } + + private void volt(final SnipeData v) + { + final Block block = this.clampY(this.getTargetBlock().getX(), this.getTargetBlock().getY(), this.getTargetBlock().getZ()); + final boolean indirect = block.isBlockIndirectlyPowered(); + final boolean direct = block.isBlockPowered(); + v.sendMessage(ChatColor.AQUA + "Direct Power? " + direct + " Indirect Power? " + indirect); + v.sendMessage(ChatColor.BLUE + "Top Direct? " + block.isBlockFacePowered(BlockFace.UP) + " Top Indirect? " + block.isBlockFaceIndirectlyPowered(BlockFace.UP)); + v.sendMessage(ChatColor.BLUE + "Bottom Direct? " + block.isBlockFacePowered(BlockFace.DOWN) + " Bottom Indirect? " + block.isBlockFaceIndirectlyPowered(BlockFace.DOWN)); + v.sendMessage(ChatColor.BLUE + "East Direct? " + block.isBlockFacePowered(BlockFace.EAST) + " East Indirect? " + block.isBlockFaceIndirectlyPowered(BlockFace.EAST)); + v.sendMessage(ChatColor.BLUE + "West Direct? " + block.isBlockFacePowered(BlockFace.WEST) + " West Indirect? " + block.isBlockFaceIndirectlyPowered(BlockFace.WEST)); + v.sendMessage(ChatColor.BLUE + "North Direct? " + block.isBlockFacePowered(BlockFace.NORTH) + " North Indirect? " + block.isBlockFaceIndirectlyPowered(BlockFace.NORTH)); + v.sendMessage(ChatColor.BLUE + "South Direct? " + block.isBlockFacePowered(BlockFace.SOUTH) + " South Indirect? " + block.isBlockFaceIndirectlyPowered(BlockFace.SOUTH)); + } + + @Override + protected final void arrow(final SnipeData v) + { + this.volt(v); + } + + @Override + protected final void powder(final SnipeData v) + { + this.data(v); + } + + @Override + public final void info(final Message vm) + { + vm.brushName(this.getName()); + vm.brushMessage("Right click with arrow to see if blocks/faces are powered. Powder measures wire current."); + } + + @Override + public String getPermissionNode() + { + return "voxelsniper.brush.voltmeter"; + } +} diff --git a/favs/src/main/java/com/thevoxelbox/voxelsniper/brush/VoxelBrush.java b/favs/src/main/java/com/thevoxelbox/voxelsniper/brush/VoxelBrush.java new file mode 100644 index 000000000..98cfd89cd --- /dev/null +++ b/favs/src/main/java/com/thevoxelbox/voxelsniper/brush/VoxelBrush.java @@ -0,0 +1,61 @@ +package com.thevoxelbox.voxelsniper.brush; + +import com.thevoxelbox.voxelsniper.Message; +import com.thevoxelbox.voxelsniper.SnipeData; +import com.thevoxelbox.voxelsniper.brush.perform.PerformBrush; + +/** + * http://www.voxelwiki.com/minecraft/Voxelsniper#The_Voxel_Brush + * + * @author Piotr + */ +public class VoxelBrush extends PerformBrush +{ + /** + * + */ + public VoxelBrush() + { + this.setName("Voxel"); + } + + private void voxel(final SnipeData v) + { + for (int z = v.getBrushSize(); z >= -v.getBrushSize(); z--) + { + for (int x = v.getBrushSize(); x >= -v.getBrushSize(); x--) + { + for (int y = v.getBrushSize(); y >= -v.getBrushSize(); y--) + { + this.current.perform(this.clampY(this.getTargetBlock().getX() + x, this.getTargetBlock().getY() + z, this.getTargetBlock().getZ() + y)); + } + } + } + v.owner().storeUndo(this.current.getUndo()); + } + + @Override + protected final void arrow(final SnipeData v) + { + this.voxel(v); + } + + @Override + protected final void powder(final SnipeData v) + { + this.voxel(v); + } + + @Override + public final void info(final Message vm) + { + vm.brushName(this.getName()); + vm.size(); + } + + @Override + public String getPermissionNode() + { + return "voxelsniper.brush.voxel"; + } +} diff --git a/favs/src/main/java/com/thevoxelbox/voxelsniper/brush/VoxelDiscBrush.java b/favs/src/main/java/com/thevoxelbox/voxelsniper/brush/VoxelDiscBrush.java new file mode 100644 index 000000000..3c866f90f --- /dev/null +++ b/favs/src/main/java/com/thevoxelbox/voxelsniper/brush/VoxelDiscBrush.java @@ -0,0 +1,60 @@ +package com.thevoxelbox.voxelsniper.brush; + +import com.boydti.fawe.bukkit.wrapper.AsyncBlock; +import com.thevoxelbox.voxelsniper.Message; +import com.thevoxelbox.voxelsniper.SnipeData; +import com.thevoxelbox.voxelsniper.brush.perform.PerformBrush; +import org.bukkit.block.Block; + +/** + * http://www.voxelwiki.com/minecraft/Voxelsniper#The_Voxel_Disc_Brush + * + * @author Voxel + */ +public class VoxelDiscBrush extends PerformBrush +{ + /** + * + */ + public VoxelDiscBrush() + { + this.setName("Voxel Disc"); + } + + private void disc(final SnipeData v, AsyncBlock targetBlock) + { + for (int x = v.getBrushSize(); x >= -v.getBrushSize(); x--) + { + for (int z = v.getBrushSize(); z >= -v.getBrushSize(); z--) + { + current.perform(targetBlock.getRelative(x, 0, z)); + } + } + v.owner().storeUndo(this.current.getUndo()); + } + + @Override + protected final void arrow(final SnipeData v) + { + this.disc(v, this.getTargetBlock()); + } + + @Override + protected final void powder(final SnipeData v) + { + this.disc(v, this.getLastBlock()); + } + + @Override + public final void info(final Message vm) + { + vm.brushName(this.getName()); + vm.size(); + } + + @Override + public String getPermissionNode() + { + return "voxelsniper.brush.voxeldisc"; + } +} diff --git a/favs/src/main/java/com/thevoxelbox/voxelsniper/brush/VoxelDiscFaceBrush.java b/favs/src/main/java/com/thevoxelbox/voxelsniper/brush/VoxelDiscFaceBrush.java new file mode 100644 index 000000000..70ec71714 --- /dev/null +++ b/favs/src/main/java/com/thevoxelbox/voxelsniper/brush/VoxelDiscFaceBrush.java @@ -0,0 +1,115 @@ +package com.thevoxelbox.voxelsniper.brush; + +import com.thevoxelbox.voxelsniper.Message; +import com.thevoxelbox.voxelsniper.SnipeData; +import com.thevoxelbox.voxelsniper.brush.perform.PerformBrush; +import org.bukkit.block.Block; +import org.bukkit.block.BlockFace; + +/** + * http://www.voxelwiki.com/minecraft/Voxelsniper#The_Voxel_Disc_Face_Brush + * + * @author Voxel + */ +public class VoxelDiscFaceBrush extends PerformBrush +{ + /** + * + */ + public VoxelDiscFaceBrush() + { + this.setName("Voxel Disc Face"); + } + + private void disc(final SnipeData v, Block targetBlock) + { + for (int x = v.getBrushSize(); x >= -v.getBrushSize(); x--) + { + for (int y = v.getBrushSize(); y >= -v.getBrushSize(); y--) + { + this.current.perform(this.clampY(targetBlock.getX() + x, targetBlock.getY(), targetBlock.getZ() + y)); + } + } + + v.owner().storeUndo(this.current.getUndo()); + } + + private void discNS(final SnipeData v, Block targetBlock) + { + for (int x = v.getBrushSize(); x >= -v.getBrushSize(); x--) + { + for (int y = v.getBrushSize(); y >= -v.getBrushSize(); y--) + { + this.current.perform(this.clampY(targetBlock.getX() + x, targetBlock.getY() + y, targetBlock.getZ())); + } + } + + v.owner().storeUndo(this.current.getUndo()); + } + + private void discEW(final SnipeData v, Block targetBlock) + { + for (int x = v.getBrushSize(); x >= -v.getBrushSize(); x--) + { + for (int y = v.getBrushSize(); y >= -v.getBrushSize(); y--) + { + this.current.perform(this.clampY(targetBlock.getX(), targetBlock.getY() + x, targetBlock.getZ() + y)); + } + } + + v.owner().storeUndo(this.current.getUndo()); + } + + private void pre(final SnipeData v, final BlockFace bf, Block targetBlock) + { + if (bf == null) + { + return; + } + switch (bf) + { + case NORTH: + case SOUTH: + this.discNS(v, targetBlock); + break; + + case EAST: + case WEST: + this.discEW(v, targetBlock); + break; + + case UP: + case DOWN: + this.disc(v, targetBlock); + break; + + default: + break; + } + } + + @Override + protected final void arrow(final SnipeData v) + { + this.pre(v, this.getTargetBlock().getFace(this.getLastBlock()), this.getTargetBlock()); + } + + @Override + protected final void powder(final SnipeData v) + { + this.pre(v, this.getTargetBlock().getFace(this.getLastBlock()), this.getLastBlock()); + } + + @Override + public final void info(final Message vm) + { + vm.brushName(this.getName()); + vm.size(); + } + + @Override + public String getPermissionNode() + { + return "voxelsniper.brush.voxeldiscface"; + } +} diff --git a/favs/src/main/java/com/thevoxelbox/voxelsniper/brush/WarpBrush.java b/favs/src/main/java/com/thevoxelbox/voxelsniper/brush/WarpBrush.java new file mode 100644 index 000000000..bb194e919 --- /dev/null +++ b/favs/src/main/java/com/thevoxelbox/voxelsniper/brush/WarpBrush.java @@ -0,0 +1,97 @@ +/** + This file is part of VoxelSniper, licensed under the MIT License (MIT). + + Copyright (c) The VoxelBox + Copyright (c) contributors + + Permission is hereby granted, free of charge, to any person obtaining a copy + of this software and associated documentation files (the "Software"), to deal + in the Software without restriction, including without limitation the rights + to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + copies of the Software, and to permit persons to whom the Software is + furnished to do so, subject to the following conditions: + + The above copyright notice and this permission notice shall be included in + all copies or substantial portions of the Software. + + THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + THE SOFTWARE. + */ +package com.thevoxelbox.voxelsniper.brush; + +import com.boydti.fawe.object.RunnableVal; +import com.boydti.fawe.util.TaskManager; +import com.thevoxelbox.voxelsniper.Message; +import com.thevoxelbox.voxelsniper.SnipeData; +import org.bukkit.Bukkit; +import org.bukkit.Location; +import org.bukkit.entity.Player; + +/** + * @author MikeMatrix + */ +public class WarpBrush extends Brush +{ + /** + * + */ + public WarpBrush() + { + this.setName("Warp"); + } + + @Override + public final void info(final Message vm) + { + vm.brushName(this.getName()); + } + + @Override + protected final void arrow(final SnipeData v) + { + Player player = v.owner().getPlayer(); + Location location = this.getLastBlock().getLocation(); + Location playerLocation = player.getLocation(); + location.setPitch(playerLocation.getPitch()); + location.setYaw(playerLocation.getYaw()); + location.setWorld(Bukkit.getWorld(location.getWorld().getName())); + TaskManager.IMP.sync(new RunnableVal() { + @Override + public void run(Object value) { + player.teleport(location); + } + }); + } + + @Override + protected final void powder(final SnipeData v) + { + Player player = v.owner().getPlayer(); + Location location = this.getLastBlock().getLocation(); + Location playerLocation = player.getLocation(); + location.setPitch(playerLocation.getPitch()); + location.setYaw(playerLocation.getYaw()); + location.setWorld(Bukkit.getWorld(location.getWorld().getName())); + TaskManager.IMP.sync(new RunnableVal() { + @Override + public void run(Object value) { + player.teleport(location); + } + }); + } + + @Override + public String getPermissionNode() + { + return "voxelsniper.brush.warp"; + } + + public static Class inject() { + return WarpBrush.class; + } +} \ No newline at end of file diff --git a/favs/src/main/java/com/thevoxelbox/voxelsniper/brush/perform/PatternPerformer.java b/favs/src/main/java/com/thevoxelbox/voxelsniper/brush/perform/PatternPerformer.java new file mode 100644 index 000000000..aade828fa --- /dev/null +++ b/favs/src/main/java/com/thevoxelbox/voxelsniper/brush/perform/PatternPerformer.java @@ -0,0 +1,43 @@ +package com.thevoxelbox.voxelsniper.brush.perform; + +import com.boydti.fawe.bukkit.wrapper.AsyncBlock; +import com.boydti.fawe.object.pattern.PatternTraverser; +import com.sk89q.worldedit.MutableBlockVector; +import com.sk89q.worldedit.WorldEditException; +import com.sk89q.worldedit.extent.Extent; +import com.sk89q.worldedit.function.pattern.Pattern; +import com.thevoxelbox.voxelsniper.Message; +import com.thevoxelbox.voxelsniper.SnipeData; +import org.bukkit.block.Block; + +public class PatternPerformer extends vPerformer { + private String info; + private Pattern pattern; + private Extent extent; + private MutableBlockVector mutable = new MutableBlockVector(); + + @Override + public void info(Message vm) { + vm.performerName(this.name + ": " + info); + vm.voxel(); + } + + @Override + public void init(SnipeData snipeData) { + this.w = snipeData.getWorld(); + this.extent = snipeData.getExtent(); + this.info = snipeData.getPatternInfo(); + this.pattern = snipeData.getPattern(); + new PatternTraverser(pattern).reset(extent); + } + + @Override + public void perform(AsyncBlock block) { + mutable.setComponents(block.getX(), block.getY(), block.getZ()); + try { + pattern.apply(extent, mutable, mutable); + } catch (WorldEditException e) { + throw new RuntimeException(e); + } + } +} diff --git a/favs/src/main/java/com/thevoxelbox/voxelsniper/brush/perform/PerformBrush.java b/favs/src/main/java/com/thevoxelbox/voxelsniper/brush/perform/PerformBrush.java new file mode 100644 index 000000000..1c690d594 --- /dev/null +++ b/favs/src/main/java/com/thevoxelbox/voxelsniper/brush/perform/PerformBrush.java @@ -0,0 +1,100 @@ +/** + This file is part of VoxelSniper, licensed under the MIT License (MIT). + + Copyright (c) The VoxelBox + Copyright (c) contributors + + Permission is hereby granted, free of charge, to any person obtaining a copy + of this software and associated documentation files (the "Software"), to deal + in the Software without restriction, including without limitation the rights + to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + copies of the Software, and to permit persons to whom the Software is + furnished to do so, subject to the following conditions: + + The above copyright notice and this permission notice shall be included in + all copies or substantial portions of the Software. + + THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + THE SOFTWARE. + */ +package com.thevoxelbox.voxelsniper.brush.perform; + +import com.sk89q.worldedit.function.pattern.Pattern; +import com.thevoxelbox.voxelsniper.Message; +import com.thevoxelbox.voxelsniper.SnipeData; +import com.thevoxelbox.voxelsniper.brush.Brush; +import com.thevoxelbox.voxelsniper.event.SniperBrushChangedEvent; +import java.util.Arrays; +import org.bukkit.Bukkit; + +public abstract class PerformBrush extends Brush implements Performer { + protected vPerformer current = new pMaterial(); + + public PerformBrush() { + } + + public vPerformer getCurrentPerformer() { + return this.current; + } + + public void parse(String[] args, SnipeData v) { + String handle = args[0]; + if(PerformerE.has(handle)) { + vPerformer p = PerformerE.getPerformer(handle); + if(p != null) { + this.current = p; + SniperBrushChangedEvent event = new SniperBrushChangedEvent(v.owner(), v.owner().getCurrentToolId(), this, this); + Bukkit.getPluginManager().callEvent(event); + this.info(v.getVoxelMessage()); + this.current.info(v.getVoxelMessage()); + if(args.length > 1) { + String[] additionalArguments = (String[])Arrays.copyOfRange(args, 1, args.length); + this.parameters(this.hackTheArray(additionalArguments), v); + } + } else { + this.parameters(this.hackTheArray(args), v); + } + } else { + this.parameters(this.hackTheArray(args), v); + } + + } + + private String[] hackTheArray(String[] args) { + String[] returnValue = new String[args.length + 1]; + int i = 0; + + for(int argsLength = args.length; i < argsLength; ++i) { + String arg = args[i]; + returnValue[i + 1] = arg; + } + + return returnValue; + } + + public void initP(SnipeData v) { + Pattern pattern = v.getPattern(); + if (pattern != null) { + if (!(current instanceof PatternPerformer)) { + current = new PatternPerformer(); + } + } else if (current instanceof PatternPerformer) { + current = new pMaterial(); + } + this.current.init(v); + this.current.setUndo(); + } + + public void showInfo(Message vm) { + this.current.info(vm); + } + + public static Class inject() { + return PerformBrush.class; + } +} diff --git a/favs/src/main/java/com/thevoxelbox/voxelsniper/brush/perform/Performer.java b/favs/src/main/java/com/thevoxelbox/voxelsniper/brush/perform/Performer.java new file mode 100644 index 000000000..01a2a07c5 --- /dev/null +++ b/favs/src/main/java/com/thevoxelbox/voxelsniper/brush/perform/Performer.java @@ -0,0 +1,18 @@ +/* + * To change this template, choose Tools | Templates + * and open the template in the editor. + */ +package com.thevoxelbox.voxelsniper.brush.perform; + +import com.thevoxelbox.voxelsniper.Message; + +/** + * @author Voxel + */ +public interface Performer +{ + + public void parse(String[] args, com.thevoxelbox.voxelsniper.SnipeData v); + + public void showInfo(Message vm); +} diff --git a/favs/src/main/java/com/thevoxelbox/voxelsniper/brush/perform/PerformerE.java b/favs/src/main/java/com/thevoxelbox/voxelsniper/brush/perform/PerformerE.java new file mode 100644 index 000000000..ef0ff7e5a --- /dev/null +++ b/favs/src/main/java/com/thevoxelbox/voxelsniper/brush/perform/PerformerE.java @@ -0,0 +1,179 @@ +/* + * To change this template, choose Tools | Templates + * and open the template in the editor. + */ +package com.thevoxelbox.voxelsniper.brush.perform; + +import java.lang.reflect.InvocationTargetException; +import java.util.Map; +import java.util.TreeMap; +import java.util.logging.Level; +import java.util.logging.Logger; + +import org.bukkit.ChatColor; + +/** + * @author Voxel + */ + +/* The m/i/c system of naming performers: [replacement-option][extras] + * + * placement-option is mandatory and can be material(m) [for /v], ink(i) [for /vi] or combo(c) [for both] + * replacement-option is optional and can be m [for /vr], i [for /vir] or c [for both] + * extras is optional and can be update(u) [for graphical glitch], physics(p) [for no-phys] or up [for both] + * + * new extra: n = no undo + * + * The main benefit of this system is that it provides the least possible number of characters in the paramaters + * while guaranteeing that all sensible combinations will be made. Additionally, the names will be VERY consistent + * + * EX Old System: /b b isrcup (use /v, /vi, /vr and /vir, update graphics and no physics) + * EX New System: /b b ccup (two characters shorter, good because snipers have been complaing about keystrokes) + * + */ + +/* This enum is getting REALLY Long, would it be possible to algorithmically generate the full performer + * from the pieces? So if the performer name is of the for m*, you'll setTypeId whereas if it is of the + * form c* you'd setTypeIdAndPropertyId? Similarly, if the performer is of the form *p, any setTypeId's or setTypeIdAndPropertyId's + * will be set to false instead of true? The middle bits might be tougher, being of the form _m* perhaps? + * Regex to the rescue, am I right? - Giltwist + */ + +public enum PerformerE +{ + + MATERIAL(pMaterial.class, "m", "material"), + MATERIAL_NOPHYS(pMaterialNoPhys.class, "mp", "mat-nophys"), + MAT_MAT(pMatMat.class, "mm", "mat-mat"), + MAT_MAT_NOPHYS(pMatMatNoPhys.class, "mmp", "mat-mat-nophys"), + MAT_INK(pMatInk.class, "mi", "mat-ink"), + MAT_INK_NOPHYS(pMatInkNoPhys.class, "mip", "mat-ink-nophys"), + MAT_COMBO(pMatCombo.class, "mc", "mat-combo"), + MAT_COMBO_NOPHYS(pMatComboNophys.class, "mcp", "mat-combo-nophys"), + INK(pInk.class, "i", "ink"), + INK_MAT(pInkMat.class, "im", "ink-mat"), + INK_INK(pInkInk.class, "ii", "ink-ink"), + INK_COMBO(pInkCombo.class, "ic", "ink-combo"), + INK_INK_NOPHYS(pInkInkNoPhys.class, "iip", "ink-ink-nophys"), + INK_NOPHYS(pInkNoPhys.class, "ip", "ink-nophys"), + INK_MAT_NOPHYS(pInkMatNoPhys.class, "imp", "ink-mat-nophys"), + INK_COMBO_NOPHYS(pInkComboNoPhys.class, "icp", "ink-combo-nophys"), + COMBO(pCombo.class, "c", "combo"), + COMBO_NOPHYS(pComboNoPhys.class, "cp", "combo-nophys"), + COMBO_MAT(pComboMat.class, "cm", "combo-mat"), + COMBO_MAT_NOPHYS(pComboMatNoPhys.class, "cmp", "combo-mat-nophys"), + COMBO_INK(pComboInk.class, "ci", "combo-ink"), + COMBO_INK_NOPHYS(pComboInkNoPhys.class, "cip", "combo-ink-nophys"), + COMBO_COMBO(pComboCombo.class, "cc", "combo-combo"), + COMBO_COMBO_NOPHYS(pComboComboNoPhys.class, "ccp", "combo-combo-nophys"), + EXCLUDE_MATERIAL(pExcludeMat.class, "xm", "exclude-mat"), + EXCLUDE_INK(pExcludeInk.class, "xi", "exclude-ink"), + EXCLUDE_COMBO(pExcludeCombo.class, "xc", "exclude-combo"), + INCLUDE_MATERIAL(pIncludeMat.class, "nm", "include-mat"), + INCLUDE_INK(pIncludeInk.class, "ni", "include-ink"), + INCLUDE_COMBO(pIncludeCombo.class, "nc", "include-combo"), + MAT_NO_UNDO(pNoUndo.class, "noundo", "noundo"); + //Other Performers which don't exist yet but are required for a full set of possibilities that actually could potentially do something: + //List does not include any no-physics, unless materials are being placed (or combo), or any update unless ink is being placed (or combo) -Gavjenks + + //MAT_MAT_UPDATE( pMatMatUpdate.class, "mmu", "mat-mat-update" ), // place mat, replace mat, graphical update + //MAT_COMBO_UPDATE( pMatComboUpdate.class, "mcu", "mat-combo-update" ), // place mat, replace combo, graphical update + //MAT_COMBO_NOPHYS_UPDATE( pMatComboNoPhysUpdate.class, "mcup", "mat-combo-update-nophys"), // place mat, replace combo, update, no physics + //MAT_INK_UPDATE( pMatInkUpdate.class, "miu", "mat-ink-update"), // place mat, replace ink, graphical update + //MAT_INK_NOPHYS_UPDATE( pMatInkNoPhysUpdate.class, "miup", "mat-ink-update-nophys"), // place mat, replace ink, graphical update no physics + //INK_MAT_UPDATE( pInkMatUpdate.class, "imu", "ink-mat-update"), // place ink, replace mat, graphical update + //INK_INK_UPDATE( pInkInkUpdate.class, "iiu", "ink-ink-update"), // place ink, replace ink, graphical update + //INK_COMBO_UPDATE( pInkComboUpdate.class, "icu", "ink-combo-update"), // place ink, replace combo, graphical update + //COMBO_MAT_UPDATE( pComboMatUpdate.class, "cmu", "combo-mat-update"), // place combo, replace mat, graphical update + //COMBO_MAT_NOPHYS_UPDATE( pComboMatNoPhysUpdate.class, "cmup", "combo-mat-update-nophys"), // place combo, replace mat, graphical update, no physics + //COMBO_INK_UPDATE( pComboInkUpdate.class, "ciu", "combo-ink-update"), // place combo, replace ink, graphical update + //COMBO_INK_NOPHYS_UPDATE( pComboInkNoPhysUpdate.class, "ciup", "combo-ink-update-nophys"), // place combo, replace ink, graphical update, no physics + //COMBO_COMBO_UPDATE( pComboComboUpdate.class, "ccu", "combo-combo-update"), // place combo, replace combo, graphical update + //COMBO_COMBO_NOPHYS_UPDATE(pComboComboNoPhysUpdate.class, "ccup", "combo-combo-update-nophys"),// place combo, replace combo, graphical update, no physics + + private static Map performers; + private static Map long_names; + private Class pclass; + private String short_name; + private String long_name; + public static String performer_list_short = ""; + public static String performer_list_long = ""; + + private PerformerE(Class c, String s, String l) + { + pclass = c; + short_name = s; + long_name = l; + } + + private vPerformer getPerformer() + { + vPerformer p; + try + { + try + { + p = pclass.getConstructor().newInstance(); + return p; + } + catch (InstantiationException ex) + { + Logger.getLogger(PerformerE.class.getName()).log(Level.SEVERE, null, ex); + } + catch (IllegalAccessException ex) + { + Logger.getLogger(PerformerE.class.getName()).log(Level.SEVERE, null, ex); + } + catch (IllegalArgumentException ex) + { + Logger.getLogger(PerformerE.class.getName()).log(Level.SEVERE, null, ex); + } + catch (InvocationTargetException ex) + { + Logger.getLogger(PerformerE.class.getName()).log(Level.SEVERE, null, ex); + } + } + catch (NoSuchMethodException ex) + { + Logger.getLogger(PerformerE.class.getName()).log(Level.SEVERE, null, ex); + } + catch (SecurityException ex) + { + Logger.getLogger(PerformerE.class.getName()).log(Level.SEVERE, null, ex); + } + return null; + } + + public static vPerformer getPerformer(String s) + { + if (performers.containsKey(s)) + { + return performers.get(s); + } + else + { + return performers.get(long_names.get(s)); + } + } + + public static boolean has(String s) + { + return performers.containsKey(s); + } + + static + { + performers = new TreeMap(); + long_names = new TreeMap(); + + for (PerformerE pe : values()) + { + performers.put(pe.short_name, pe.getPerformer()); + long_names.put(pe.long_name, pe.short_name); + performer_list_short = performer_list_short + ChatColor.GREEN + pe.short_name + ChatColor.RED + ", "; + performer_list_long = performer_list_long + ChatColor.GREEN + pe.long_name + ChatColor.RED + ", "; + } + performer_list_short = performer_list_short.substring(0, performer_list_short.length() - 2); + performer_list_long = performer_list_long.substring(0, performer_list_long.length() - 2); + } +} diff --git a/favs/src/main/java/com/thevoxelbox/voxelsniper/brush/perform/pCombo.java b/favs/src/main/java/com/thevoxelbox/voxelsniper/brush/perform/pCombo.java new file mode 100644 index 000000000..3f0a97b5c --- /dev/null +++ b/favs/src/main/java/com/thevoxelbox/voxelsniper/brush/perform/pCombo.java @@ -0,0 +1,47 @@ +/* + * To change this template, choose Tools | Templates + * and open the template in the editor. + */ +package com.thevoxelbox.voxelsniper.brush.perform; + +import com.boydti.fawe.bukkit.wrapper.AsyncBlock; +import com.thevoxelbox.voxelsniper.Message; + +/** + * @author Voxel + */ +public class pCombo extends vPerformer +{ + + private int i; + private int d; + + public pCombo() + { + name = "Combo"; + } + + @Override + public void info(Message vm) + { + vm.performerName(name); + vm.voxel(); + vm.data(); + } + + @Override + public void init(com.thevoxelbox.voxelsniper.SnipeData v) + { + w = v.getWorld(); + i = v.getVoxelId(); + d = v.getPropertyId(); + } + + @SuppressWarnings("deprecation") + @Override + public void perform(AsyncBlock b) + { + h.put(b); + b.setTypeIdAndPropertyId(i, d, true); + } +} diff --git a/favs/src/main/java/com/thevoxelbox/voxelsniper/brush/perform/pComboCombo.java b/favs/src/main/java/com/thevoxelbox/voxelsniper/brush/perform/pComboCombo.java new file mode 100644 index 000000000..f179955e7 --- /dev/null +++ b/favs/src/main/java/com/thevoxelbox/voxelsniper/brush/perform/pComboCombo.java @@ -0,0 +1,62 @@ +/* + * To change this template, choose Tools | Templates + * and open the template in the editor. + */ +package com.thevoxelbox.voxelsniper.brush.perform; + +import com.boydti.fawe.bukkit.wrapper.AsyncBlock; +import com.thevoxelbox.voxelsniper.Message; + +/** + * @author Voxel + */ +public class pComboCombo extends vPerformer +{ + + private int d; + private int dr; + private int i; + private int ir; + + public pComboCombo() + { + name = "Combo-Combo"; + } + + @Override + public void init(com.thevoxelbox.voxelsniper.SnipeData v) + { + w = v.getWorld(); + d = v.getPropertyId(); + dr = v.getReplaceData(); + i = v.getVoxelId(); + ir = v.getReplaceId(); + } + + @Override + public void info(Message vm) + { + vm.performerName(name); + vm.voxel(); + vm.replace(); + vm.data(); + vm.replaceData(); + } + + @SuppressWarnings("deprecation") + @Override + public void perform(AsyncBlock b) + { + if (b.getTypeId() == ir && b.getPropertyId() == dr) + { + h.put(b); + b.setTypeIdAndPropertyId(i, d, true); + } + } + + @Override + public boolean isUsingReplaceMaterial() + { + return true; + } +} diff --git a/favs/src/main/java/com/thevoxelbox/voxelsniper/brush/perform/pComboComboNoPhys.java b/favs/src/main/java/com/thevoxelbox/voxelsniper/brush/perform/pComboComboNoPhys.java new file mode 100644 index 000000000..305fc5f94 --- /dev/null +++ b/favs/src/main/java/com/thevoxelbox/voxelsniper/brush/perform/pComboComboNoPhys.java @@ -0,0 +1,63 @@ +/* + * To change this template, choose Tools | Templates + * and open the template in the editor. + */ +package com.thevoxelbox.voxelsniper.brush.perform; + +import com.boydti.fawe.bukkit.wrapper.AsyncBlock; +import com.thevoxelbox.voxelsniper.Message; + +/** + * @author Voxel + */ +public class pComboComboNoPhys extends vPerformer +{ + + private int d; + private int dr; + private int i; + private int ir; + + public pComboComboNoPhys() + { + name = "Combo-Combo No-Physics"; + } + + @Override + public void init(com.thevoxelbox.voxelsniper.SnipeData v) + { + w = v.getWorld(); + d = v.getPropertyId(); + dr = v.getReplaceData(); + i = v.getVoxelId(); + ir = v.getReplaceId(); + } + + @Override + public void info(Message vm) + { + vm.performerName(name); + vm.voxel(); + vm.replace(); + vm.data(); + vm.replaceData(); + } + + @SuppressWarnings("deprecation") + @Override + public void perform(AsyncBlock b) + { + if (b.getTypeId() == ir && b.getPropertyId() == dr) + { + h.put(b); + b.setTypeId(i); + b.setPropertyId(d); + } + } + + @Override + public boolean isUsingReplaceMaterial() + { + return true; + } +} \ No newline at end of file diff --git a/favs/src/main/java/com/thevoxelbox/voxelsniper/brush/perform/pComboInk.java b/favs/src/main/java/com/thevoxelbox/voxelsniper/brush/perform/pComboInk.java new file mode 100644 index 000000000..8a056bd98 --- /dev/null +++ b/favs/src/main/java/com/thevoxelbox/voxelsniper/brush/perform/pComboInk.java @@ -0,0 +1,59 @@ +/* + * To change this template, choose Tools | Templates + * and open the template in the editor. + */ +package com.thevoxelbox.voxelsniper.brush.perform; + +import com.boydti.fawe.bukkit.wrapper.AsyncBlock; +import com.thevoxelbox.voxelsniper.Message; + +/** + * @author Voxel + */ +public class pComboInk extends vPerformer +{ + + private int d; + private int dr; + private int i; + + public pComboInk() + { + name = "Combo-Ink"; + } + + @Override + public void init(com.thevoxelbox.voxelsniper.SnipeData v) + { + w = v.getWorld(); + d = v.getPropertyId(); + dr = v.getReplaceData(); + i = v.getVoxelId(); + } + + @Override + public void info(Message vm) + { + vm.performerName(name); + vm.voxel(); + vm.data(); + vm.replaceData(); + } + + @SuppressWarnings("deprecation") + @Override + public void perform(AsyncBlock b) + { + if (b.getPropertyId() == dr) + { + h.put(b); + b.setTypeIdAndPropertyId(i, d, true); + } + } + + @Override + public boolean isUsingReplaceMaterial() + { + return true; + } +} diff --git a/favs/src/main/java/com/thevoxelbox/voxelsniper/brush/perform/pComboInkNoPhys.java b/favs/src/main/java/com/thevoxelbox/voxelsniper/brush/perform/pComboInkNoPhys.java new file mode 100644 index 000000000..01ee923ce --- /dev/null +++ b/favs/src/main/java/com/thevoxelbox/voxelsniper/brush/perform/pComboInkNoPhys.java @@ -0,0 +1,59 @@ +/* + * To change this template, choose Tools | Templates + * and open the template in the editor. + */ +package com.thevoxelbox.voxelsniper.brush.perform; + +import com.boydti.fawe.bukkit.wrapper.AsyncBlock; +import com.thevoxelbox.voxelsniper.Message; + +/** + * @author Voxel + */ +public class pComboInkNoPhys extends vPerformer +{ + + private int d; + private int dr; + private int i; + + public pComboInkNoPhys() + { + name = "Combo-Ink, No Physics"; + } + + @Override + public void init(com.thevoxelbox.voxelsniper.SnipeData v) + { + w = v.getWorld(); + d = v.getPropertyId(); + dr = v.getReplaceData(); + i = v.getVoxelId(); + } + + @Override + public void info(Message vm) + { + vm.performerName(name); + vm.voxel(); + vm.data(); + vm.replaceData(); + } + + @SuppressWarnings("deprecation") + @Override + public void perform(AsyncBlock b) + { + if (b.getPropertyId() == dr) + { + h.put(b); + b.setTypeIdAndPropertyId(i, d, false); + } + } + + @Override + public boolean isUsingReplaceMaterial() + { + return true; + } +} diff --git a/favs/src/main/java/com/thevoxelbox/voxelsniper/brush/perform/pComboMat.java b/favs/src/main/java/com/thevoxelbox/voxelsniper/brush/perform/pComboMat.java new file mode 100644 index 000000000..6f581f804 --- /dev/null +++ b/favs/src/main/java/com/thevoxelbox/voxelsniper/brush/perform/pComboMat.java @@ -0,0 +1,59 @@ +/* + * To change this template, choose Tools | Templates + * and open the template in the editor. + */ +package com.thevoxelbox.voxelsniper.brush.perform; + +import com.boydti.fawe.bukkit.wrapper.AsyncBlock; +import com.thevoxelbox.voxelsniper.Message; + +/** + * @author Voxel + */ +public class pComboMat extends vPerformer +{ + + private int d; + private int i; + private int ir; + + public pComboMat() + { + name = "Combo-Mat"; + } + + @Override + public void init(com.thevoxelbox.voxelsniper.SnipeData v) + { + w = v.getWorld(); + d = v.getPropertyId(); + i = v.getVoxelId(); + ir = v.getReplaceId(); + } + + @Override + public void info(Message vm) + { + vm.performerName(name); + vm.voxel(); + vm.replace(); + vm.data(); + } + + @SuppressWarnings("deprecation") + @Override + public void perform(AsyncBlock b) + { + if (b.getTypeId() == ir) + { + h.put(b); + b.setTypeIdAndPropertyId(i, d, true); + } + } + + @Override + public boolean isUsingReplaceMaterial() + { + return true; + } +} diff --git a/favs/src/main/java/com/thevoxelbox/voxelsniper/brush/perform/pComboMatNoPhys.java b/favs/src/main/java/com/thevoxelbox/voxelsniper/brush/perform/pComboMatNoPhys.java new file mode 100644 index 000000000..7679c9a17 --- /dev/null +++ b/favs/src/main/java/com/thevoxelbox/voxelsniper/brush/perform/pComboMatNoPhys.java @@ -0,0 +1,59 @@ +/* + * To change this template, choose Tools | Templates + * and open the template in the editor. + */ +package com.thevoxelbox.voxelsniper.brush.perform; + +import com.boydti.fawe.bukkit.wrapper.AsyncBlock; +import com.thevoxelbox.voxelsniper.Message; + +/** + * @author Voxel + */ +public class pComboMatNoPhys extends vPerformer +{ + + private int d; + private int i; + private int ir; + + public pComboMatNoPhys() + { + name = "Combo-Mat, No Physics"; + } + + @Override + public void init(com.thevoxelbox.voxelsniper.SnipeData v) + { + w = v.getWorld(); + d = v.getPropertyId(); + i = v.getVoxelId(); + ir = v.getReplaceId(); + } + + @Override + public void info(Message vm) + { + vm.performerName(name); + vm.voxel(); + vm.replace(); + vm.data(); + } + + @SuppressWarnings("deprecation") + @Override + public void perform(AsyncBlock b) + { + if (b.getTypeId() == ir) + { + h.put(b); + b.setTypeIdAndPropertyId(i, d, false); + } + } + + @Override + public boolean isUsingReplaceMaterial() + { + return true; + } +} diff --git a/favs/src/main/java/com/thevoxelbox/voxelsniper/brush/perform/pComboNoPhys.java b/favs/src/main/java/com/thevoxelbox/voxelsniper/brush/perform/pComboNoPhys.java new file mode 100644 index 000000000..c8514f56f --- /dev/null +++ b/favs/src/main/java/com/thevoxelbox/voxelsniper/brush/perform/pComboNoPhys.java @@ -0,0 +1,47 @@ +/* + * To change this template, choose Tools | Templates + * and open the template in the editor. + */ +package com.thevoxelbox.voxelsniper.brush.perform; + +import com.boydti.fawe.bukkit.wrapper.AsyncBlock; +import com.thevoxelbox.voxelsniper.Message; + +/** + * @author Voxel + */ +public class pComboNoPhys extends vPerformer +{ + + private int i; + private int d; + + public pComboNoPhys() + { + name = "Combo NoPhysics"; + } + + @Override + public void info(Message vm) + { + vm.performerName(name); + vm.voxel(); + vm.data(); + } + + @Override + public void init(com.thevoxelbox.voxelsniper.SnipeData v) + { + w = v.getWorld(); + i = v.getVoxelId(); + d = v.getPropertyId(); + } + + @SuppressWarnings("deprecation") + @Override + public void perform(AsyncBlock b) + { + h.put(b); + b.setTypeIdAndPropertyId(i, d, false); + } +} diff --git a/favs/src/main/java/com/thevoxelbox/voxelsniper/brush/perform/pComboNoUndo.java b/favs/src/main/java/com/thevoxelbox/voxelsniper/brush/perform/pComboNoUndo.java new file mode 100644 index 000000000..bf5b7e1e5 --- /dev/null +++ b/favs/src/main/java/com/thevoxelbox/voxelsniper/brush/perform/pComboNoUndo.java @@ -0,0 +1,49 @@ +/* + * To change this template, choose Tools | Templates + * and open the template in the editor. + */ +package com.thevoxelbox.voxelsniper.brush.perform; + +import com.boydti.fawe.bukkit.wrapper.AsyncBlock; +import com.thevoxelbox.voxelsniper.Message; + +/** + * @author Voxel + */ +public class pComboNoUndo extends vPerformer +{ + + private int i; + private int d; + + public pComboNoUndo() + { + name = "Combo, No-Undo"; // made name more descriptive - Giltwist + } + + @Override + public void init(com.thevoxelbox.voxelsniper.SnipeData v) + { + w = v.getWorld(); + i = v.getVoxelId(); + d = v.getPropertyId(); + } + + @Override + public void info(Message vm) + { + vm.performerName(name); + vm.voxel(); + vm.data(); + } + + @SuppressWarnings("deprecation") + @Override + public void perform(AsyncBlock b) + { + if (b.getTypeId() != i || b.getPropertyId() != d) + { + b.setTypeIdAndPropertyId(i, d, true); + } + } +} \ No newline at end of file diff --git a/favs/src/main/java/com/thevoxelbox/voxelsniper/brush/perform/pExcludeCombo.java b/favs/src/main/java/com/thevoxelbox/voxelsniper/brush/perform/pExcludeCombo.java new file mode 100644 index 000000000..ec8dad7a9 --- /dev/null +++ b/favs/src/main/java/com/thevoxelbox/voxelsniper/brush/perform/pExcludeCombo.java @@ -0,0 +1,54 @@ +/* + * To change this template, choose Tools | Templates + * and open the template in the editor. + */ +package com.thevoxelbox.voxelsniper.brush.perform; + +import com.boydti.fawe.bukkit.wrapper.AsyncBlock; +import com.thevoxelbox.voxelsniper.Message; +import com.thevoxelbox.voxelsniper.util.VoxelList; + +/** + * @author Voxel + */ +public class pExcludeCombo extends vPerformer +{ + + private VoxelList excludeList; + private int id; + private int data; + + public pExcludeCombo() + { + name = "Exclude Combo"; + } + + @Override + public void info(Message vm) + { + vm.performerName(name); + vm.voxelList(); + vm.voxel(); + vm.data(); + } + + @Override + public void init(com.thevoxelbox.voxelsniper.SnipeData v) + { + w = v.getWorld(); + id = v.getVoxelId(); + data = v.getPropertyId(); + excludeList = v.getVoxelList(); + } + + @SuppressWarnings("deprecation") + @Override + public void perform(AsyncBlock b) + { + if (!excludeList.contains(b.getBlockData())) + { + h.put(b); + b.setTypeIdAndPropertyId(id, data, true); + } + } +} diff --git a/favs/src/main/java/com/thevoxelbox/voxelsniper/brush/perform/pExcludeInk.java b/favs/src/main/java/com/thevoxelbox/voxelsniper/brush/perform/pExcludeInk.java new file mode 100644 index 000000000..480cead89 --- /dev/null +++ b/favs/src/main/java/com/thevoxelbox/voxelsniper/brush/perform/pExcludeInk.java @@ -0,0 +1,51 @@ +/* + * To change this template, choose Tools | Templates + * and open the template in the editor. + */ +package com.thevoxelbox.voxelsniper.brush.perform; + +import com.boydti.fawe.bukkit.wrapper.AsyncBlock; +import com.thevoxelbox.voxelsniper.Message; +import com.thevoxelbox.voxelsniper.util.VoxelList; + +/** + * @author Voxel + */ +public class pExcludeInk extends vPerformer +{ + + private VoxelList excludeList; + private int data; + + public pExcludeInk() + { + name = "Exclude Ink"; + } + + @Override + public void info(Message vm) + { + vm.performerName(name); + vm.voxelList(); + vm.data(); + } + + @Override + public void init(com.thevoxelbox.voxelsniper.SnipeData v) + { + w = v.getWorld(); + data = v.getPropertyId(); + excludeList = v.getVoxelList(); + } + + @SuppressWarnings("deprecation") + @Override + public void perform(AsyncBlock b) + { + if (!excludeList.contains(b.getBlockData())) + { + h.put(b); + b.setPropertyId(data); + } + } +} diff --git a/favs/src/main/java/com/thevoxelbox/voxelsniper/brush/perform/pExcludeMat.java b/favs/src/main/java/com/thevoxelbox/voxelsniper/brush/perform/pExcludeMat.java new file mode 100644 index 000000000..202f744ad --- /dev/null +++ b/favs/src/main/java/com/thevoxelbox/voxelsniper/brush/perform/pExcludeMat.java @@ -0,0 +1,53 @@ +/* + * To change this template, choose Tools | Templates + * and open the template in the editor. + */ +package com.thevoxelbox.voxelsniper.brush.perform; + +import com.boydti.fawe.bukkit.wrapper.AsyncBlock; +import com.thevoxelbox.voxelsniper.Message; +import com.thevoxelbox.voxelsniper.util.VoxelList; + +import org.bukkit.block.Block; + +/** + * @author Voxel + */ +public class pExcludeMat extends vPerformer +{ + + private VoxelList excludeList; + private int id; + + public pExcludeMat() + { + name = "Exclude Material"; + } + + @Override + public void info(Message vm) + { + vm.performerName(name); + vm.voxelList(); + vm.voxel(); + } + + @Override + public void init(com.thevoxelbox.voxelsniper.SnipeData v) + { + w = v.getWorld(); + id = v.getVoxelId(); + excludeList = v.getVoxelList(); + } + + @SuppressWarnings("deprecation") + @Override + public void perform(AsyncBlock b) + { + if (!excludeList.contains(b.getBlockData())) + { + h.put(b); + b.setTypeId(id); + } + } +} diff --git a/favs/src/main/java/com/thevoxelbox/voxelsniper/brush/perform/pIncludeCombo.java b/favs/src/main/java/com/thevoxelbox/voxelsniper/brush/perform/pIncludeCombo.java new file mode 100644 index 000000000..4e5a5703c --- /dev/null +++ b/favs/src/main/java/com/thevoxelbox/voxelsniper/brush/perform/pIncludeCombo.java @@ -0,0 +1,54 @@ +/* + * To change this template, choose Tools | Templates + * and open the template in the editor. + */ +package com.thevoxelbox.voxelsniper.brush.perform; + +import com.boydti.fawe.bukkit.wrapper.AsyncBlock; +import com.thevoxelbox.voxelsniper.Message; +import com.thevoxelbox.voxelsniper.util.VoxelList; + +/** + * @author Voxel + */ +public class pIncludeCombo extends vPerformer +{ + + private VoxelList includeList; + private int id; + private int data; + + public pIncludeCombo() + { + name = "Include Combo"; + } + + @Override + public void info(Message vm) + { + vm.performerName(name); + vm.voxelList(); + vm.voxel(); + vm.data(); + } + + @Override + public void init(com.thevoxelbox.voxelsniper.SnipeData v) + { + w = v.getWorld(); + id = v.getVoxelId(); + data = v.getPropertyId(); + includeList = v.getVoxelList(); + } + + @SuppressWarnings("deprecation") + @Override + public void perform(AsyncBlock b) + { + if (includeList.contains(b.getBlockData())) + { + h.put(b); + b.setTypeIdAndPropertyId(id, data, true); + } + } +} diff --git a/favs/src/main/java/com/thevoxelbox/voxelsniper/brush/perform/pIncludeInk.java b/favs/src/main/java/com/thevoxelbox/voxelsniper/brush/perform/pIncludeInk.java new file mode 100644 index 000000000..37dc85214 --- /dev/null +++ b/favs/src/main/java/com/thevoxelbox/voxelsniper/brush/perform/pIncludeInk.java @@ -0,0 +1,51 @@ +/* + * To change this template, choose Tools | Templates + * and open the template in the editor. + */ +package com.thevoxelbox.voxelsniper.brush.perform; + +import com.boydti.fawe.bukkit.wrapper.AsyncBlock; +import com.thevoxelbox.voxelsniper.Message; +import com.thevoxelbox.voxelsniper.util.VoxelList; + +/** + * @author Voxel + */ +public class pIncludeInk extends vPerformer +{ + + private VoxelList includeList; + private int data; + + public pIncludeInk() + { + name = "Include Ink"; + } + + @Override + public void info(Message vm) + { + vm.performerName(name); + vm.voxelList(); + vm.data(); + } + + @Override + public void init(com.thevoxelbox.voxelsniper.SnipeData v) + { + w = v.getWorld(); + data = v.getPropertyId(); + includeList = v.getVoxelList(); + } + + @SuppressWarnings("deprecation") + @Override + public void perform(AsyncBlock b) + { + if (includeList.contains(b.getBlockData())) + { + h.put(b); + b.setPropertyId(data); + } + } +} diff --git a/favs/src/main/java/com/thevoxelbox/voxelsniper/brush/perform/pIncludeMat.java b/favs/src/main/java/com/thevoxelbox/voxelsniper/brush/perform/pIncludeMat.java new file mode 100644 index 000000000..54c537849 --- /dev/null +++ b/favs/src/main/java/com/thevoxelbox/voxelsniper/brush/perform/pIncludeMat.java @@ -0,0 +1,53 @@ +/* + * To change this template, choose Tools | Templates + * and open the template in the editor. + */ +package com.thevoxelbox.voxelsniper.brush.perform; + +import com.boydti.fawe.bukkit.wrapper.AsyncBlock; +import com.thevoxelbox.voxelsniper.Message; +import com.thevoxelbox.voxelsniper.util.VoxelList; + +import org.bukkit.block.Block; + +/** + * @author Voxel + */ +public class pIncludeMat extends vPerformer +{ + + private VoxelList includeList; + private int id; + + public pIncludeMat() + { + name = "Include Material"; + } + + @Override + public void info(Message vm) + { + vm.performerName(name); + vm.voxelList(); + vm.voxel(); + } + + @Override + public void init(com.thevoxelbox.voxelsniper.SnipeData v) + { + w = v.getWorld(); + id = v.getVoxelId(); + includeList = v.getVoxelList(); + } + + @SuppressWarnings("deprecation") + @Override + public void perform(AsyncBlock b) + { + if (includeList.contains(b.getBlockData())) + { + h.put(b); + b.setTypeId(id); + } + } +} diff --git a/favs/src/main/java/com/thevoxelbox/voxelsniper/brush/perform/pInk.java b/favs/src/main/java/com/thevoxelbox/voxelsniper/brush/perform/pInk.java new file mode 100644 index 000000000..a055a451d --- /dev/null +++ b/favs/src/main/java/com/thevoxelbox/voxelsniper/brush/perform/pInk.java @@ -0,0 +1,44 @@ +/* + * To change this template, choose Tools | Templates + * and open the template in the editor. + */ +package com.thevoxelbox.voxelsniper.brush.perform; + +import com.boydti.fawe.bukkit.wrapper.AsyncBlock; +import com.thevoxelbox.voxelsniper.Message; + +/** + * @author Voxel + */ +public class pInk extends vPerformer +{ + + private int d; + + public pInk() + { + name = "Ink"; + } + + @Override + public void init(com.thevoxelbox.voxelsniper.SnipeData v) + { + w = v.getWorld(); + d = v.getPropertyId(); + } + + @Override + public void info(Message vm) + { + vm.performerName(name); + vm.data(); + } + + @SuppressWarnings("deprecation") + @Override + public void perform(AsyncBlock b) + { + h.put(b); + b.setPropertyId(d); + } +} diff --git a/favs/src/main/java/com/thevoxelbox/voxelsniper/brush/perform/pInkCombo.java b/favs/src/main/java/com/thevoxelbox/voxelsniper/brush/perform/pInkCombo.java new file mode 100644 index 000000000..26bd8c829 --- /dev/null +++ b/favs/src/main/java/com/thevoxelbox/voxelsniper/brush/perform/pInkCombo.java @@ -0,0 +1,59 @@ +/* + * To change this template, choose Tools | Templates + * and open the template in the editor. + */ +package com.thevoxelbox.voxelsniper.brush.perform; + +import com.boydti.fawe.bukkit.wrapper.AsyncBlock; +import com.thevoxelbox.voxelsniper.Message; + +/** + * @author Voxel + */ +public class pInkCombo extends vPerformer +{ + + private int d; + private int dr; + private int ir; + + public pInkCombo() + { + name = "Ink-Combo"; + } + + @Override + public void init(com.thevoxelbox.voxelsniper.SnipeData v) + { + w = v.getWorld(); + d = v.getPropertyId(); + dr = v.getReplaceData(); + ir = v.getReplaceId(); + } + + @Override + public void info(Message vm) + { + vm.performerName(name); + vm.replace(); + vm.data(); + vm.replaceData(); + } + + @SuppressWarnings("deprecation") + @Override + public void perform(AsyncBlock b) + { + if (b.getTypeId() == ir && b.getPropertyId() == dr) + { + h.put(b); + b.setPropertyId(d); + } + } + + @Override + public boolean isUsingReplaceMaterial() + { + return true; + } +} diff --git a/favs/src/main/java/com/thevoxelbox/voxelsniper/brush/perform/pInkComboNoPhys.java b/favs/src/main/java/com/thevoxelbox/voxelsniper/brush/perform/pInkComboNoPhys.java new file mode 100644 index 000000000..4b7fe1964 --- /dev/null +++ b/favs/src/main/java/com/thevoxelbox/voxelsniper/brush/perform/pInkComboNoPhys.java @@ -0,0 +1,55 @@ +package com.thevoxelbox.voxelsniper.brush.perform; + +import com.boydti.fawe.bukkit.wrapper.AsyncBlock; +import com.thevoxelbox.voxelsniper.Message; + +/** + * @author Voxel + */ +public class pInkComboNoPhys extends vPerformer +{ + + private int d; + private int dr; + private int ir; + + public pInkComboNoPhys() + { + name = "Ink-Combo, No Physics"; + } + + @Override + public void init(com.thevoxelbox.voxelsniper.SnipeData v) + { + w = v.getWorld(); + d = v.getPropertyId(); + dr = v.getReplaceData(); + ir = v.getReplaceId(); + } + + @Override + public void info(Message vm) + { + vm.performerName(name); + vm.replace(); + vm.data(); + vm.replaceData(); + } + + @SuppressWarnings("deprecation") + @Override + public void perform(AsyncBlock b) + { + if (b.getTypeId() == ir && b.getPropertyId() == dr) + { + h.put(b); + b.setPropertyId(d); + } + } + + @Override + public boolean isUsingReplaceMaterial() + { + return true; + } +} \ No newline at end of file diff --git a/favs/src/main/java/com/thevoxelbox/voxelsniper/brush/perform/pInkInk.java b/favs/src/main/java/com/thevoxelbox/voxelsniper/brush/perform/pInkInk.java new file mode 100644 index 000000000..68dde46a7 --- /dev/null +++ b/favs/src/main/java/com/thevoxelbox/voxelsniper/brush/perform/pInkInk.java @@ -0,0 +1,56 @@ +/* + * To change this template, choose Tools | Templates + * and open the template in the editor. + */ +package com.thevoxelbox.voxelsniper.brush.perform; + +import com.boydti.fawe.bukkit.wrapper.AsyncBlock; +import com.thevoxelbox.voxelsniper.Message; + +/** + * @author Voxel + */ +public class pInkInk extends vPerformer +{ + + private int d; + private int dr; + + public pInkInk() + { + name = "Ink-Ink"; + } + + @Override + public void init(com.thevoxelbox.voxelsniper.SnipeData v) + { + w = v.getWorld(); + d = v.getPropertyId(); + dr = v.getReplaceData(); + } + + @Override + public void info(Message vm) + { + vm.performerName(name); + vm.data(); + vm.replaceData(); + } + + @SuppressWarnings("deprecation") + @Override + public void perform(AsyncBlock b) + { + if (b.getPropertyId() == dr) + { + h.put(b); + b.setPropertyId(d); + } + } + + @Override + public boolean isUsingReplaceMaterial() + { + return true; + } +} diff --git a/favs/src/main/java/com/thevoxelbox/voxelsniper/brush/perform/pInkInkNoPhys.java b/favs/src/main/java/com/thevoxelbox/voxelsniper/brush/perform/pInkInkNoPhys.java new file mode 100644 index 000000000..60f720703 --- /dev/null +++ b/favs/src/main/java/com/thevoxelbox/voxelsniper/brush/perform/pInkInkNoPhys.java @@ -0,0 +1,52 @@ +package com.thevoxelbox.voxelsniper.brush.perform; + +import com.boydti.fawe.bukkit.wrapper.AsyncBlock; +import com.thevoxelbox.voxelsniper.Message; + +/** + * @author Voxel + */ +public class pInkInkNoPhys extends vPerformer +{ + + private int d; + private int dr; + + public pInkInkNoPhys() + { + name = "Ink-Ink, No Physics"; + } + + @Override + public void init(com.thevoxelbox.voxelsniper.SnipeData v) + { + w = v.getWorld(); + d = v.getPropertyId(); + dr = v.getReplaceData(); + } + + @Override + public void info(Message vm) + { + vm.performerName(name); + vm.data(); + vm.replaceData(); + } + + @SuppressWarnings("deprecation") + @Override + public void perform(AsyncBlock b) + { + if (b.getPropertyId() == dr) + { + h.put(b); + b.setPropertyId(d); + } + } + + @Override + public boolean isUsingReplaceMaterial() + { + return true; + } +} \ No newline at end of file diff --git a/favs/src/main/java/com/thevoxelbox/voxelsniper/brush/perform/pInkMat.java b/favs/src/main/java/com/thevoxelbox/voxelsniper/brush/perform/pInkMat.java new file mode 100644 index 000000000..091ed4d29 --- /dev/null +++ b/favs/src/main/java/com/thevoxelbox/voxelsniper/brush/perform/pInkMat.java @@ -0,0 +1,56 @@ +/* + * To change this template, choose Tools | Templates + * and open the template in the editor. + */ +package com.thevoxelbox.voxelsniper.brush.perform; + +import com.boydti.fawe.bukkit.wrapper.AsyncBlock; +import com.thevoxelbox.voxelsniper.Message; + +/** + * @author Voxel + */ +public class pInkMat extends vPerformer +{ + + private int d; + private int ir; + + public pInkMat() + { + name = "Ink-Mat"; + } + + @Override + public void init(com.thevoxelbox.voxelsniper.SnipeData v) + { + w = v.getWorld(); + d = v.getPropertyId(); + ir = v.getReplaceId(); + } + + @Override + public void info(Message vm) + { + vm.performerName(name); + vm.data(); + vm.replace(); + } + + @SuppressWarnings("deprecation") + @Override + public void perform(AsyncBlock b) + { + if (b.getTypeId() == ir) + { + h.put(b); + b.setPropertyId(d); + } + } + + @Override + public boolean isUsingReplaceMaterial() + { + return true; + } +} diff --git a/favs/src/main/java/com/thevoxelbox/voxelsniper/brush/perform/pInkMatNoPhys.java b/favs/src/main/java/com/thevoxelbox/voxelsniper/brush/perform/pInkMatNoPhys.java new file mode 100644 index 000000000..71b82ee3c --- /dev/null +++ b/favs/src/main/java/com/thevoxelbox/voxelsniper/brush/perform/pInkMatNoPhys.java @@ -0,0 +1,52 @@ +package com.thevoxelbox.voxelsniper.brush.perform; + +import com.boydti.fawe.bukkit.wrapper.AsyncBlock; +import com.thevoxelbox.voxelsniper.Message; + +/** + * @author Voxel + */ +public class pInkMatNoPhys extends vPerformer +{ + + private int d; + private int ir; + + public pInkMatNoPhys() + { + name = "Ink-Mat, No Physics"; + } + + @Override + public void init(com.thevoxelbox.voxelsniper.SnipeData v) + { + w = v.getWorld(); + d = v.getPropertyId(); + ir = v.getReplaceId(); + } + + @Override + public void info(Message vm) + { + vm.performerName(name); + vm.data(); + vm.replace(); + } + + @SuppressWarnings("deprecation") + @Override + public void perform(AsyncBlock b) + { + if (b.getTypeId() == ir) + { + h.put(b); + b.setPropertyId(d); + } + } + + @Override + public boolean isUsingReplaceMaterial() + { + return true; + } +} \ No newline at end of file diff --git a/favs/src/main/java/com/thevoxelbox/voxelsniper/brush/perform/pInkNoPhys.java b/favs/src/main/java/com/thevoxelbox/voxelsniper/brush/perform/pInkNoPhys.java new file mode 100644 index 000000000..30b766a83 --- /dev/null +++ b/favs/src/main/java/com/thevoxelbox/voxelsniper/brush/perform/pInkNoPhys.java @@ -0,0 +1,40 @@ +package com.thevoxelbox.voxelsniper.brush.perform; + +import com.boydti.fawe.bukkit.wrapper.AsyncBlock; +import com.thevoxelbox.voxelsniper.Message; + +/** + * @author Voxel + */ +public class pInkNoPhys extends vPerformer +{ + + private int d; + + public pInkNoPhys() + { + name = "Ink, No Physics"; + } + + @Override + public void init(com.thevoxelbox.voxelsniper.SnipeData v) + { + w = v.getWorld(); + d = v.getPropertyId(); + } + + @Override + public void info(Message vm) + { + vm.performerName(name); + vm.data(); + } + + @SuppressWarnings("deprecation") + @Override + public void perform(AsyncBlock b) + { + h.put(b); + b.setPropertyId(d); + } +} diff --git a/favs/src/main/java/com/thevoxelbox/voxelsniper/brush/perform/pInkNoUndo.java b/favs/src/main/java/com/thevoxelbox/voxelsniper/brush/perform/pInkNoUndo.java new file mode 100644 index 000000000..99d65ec48 --- /dev/null +++ b/favs/src/main/java/com/thevoxelbox/voxelsniper/brush/perform/pInkNoUndo.java @@ -0,0 +1,46 @@ +/* + * To change this template, choose Tools | Templates + * and open the template in the editor. + */ +package com.thevoxelbox.voxelsniper.brush.perform; + +import com.boydti.fawe.bukkit.wrapper.AsyncBlock; +import com.thevoxelbox.voxelsniper.Message; + +/** + * @author Voxel + */ +public class pInkNoUndo extends vPerformer +{ + + private int d; + + public pInkNoUndo() + { + name = "Ink, No-Undo"; // made name more descriptive - Giltwist + } + + @Override + public void init(com.thevoxelbox.voxelsniper.SnipeData v) + { + w = v.getWorld(); + d = v.getPropertyId(); + } + + @Override + public void info(Message vm) + { + vm.performerName(name); + vm.data(); + } + + @SuppressWarnings("deprecation") + @Override + public void perform(AsyncBlock b) + { + if (b.getPropertyId() != d) + { + b.setPropertyId(d); + } + } +} \ No newline at end of file diff --git a/favs/src/main/java/com/thevoxelbox/voxelsniper/brush/perform/pMatCombo.java b/favs/src/main/java/com/thevoxelbox/voxelsniper/brush/perform/pMatCombo.java new file mode 100644 index 000000000..539156004 --- /dev/null +++ b/favs/src/main/java/com/thevoxelbox/voxelsniper/brush/perform/pMatCombo.java @@ -0,0 +1,61 @@ +/* + * To change this template, choose Tools | Templates + * and open the template in the editor. + */ +package com.thevoxelbox.voxelsniper.brush.perform; + +import com.boydti.fawe.bukkit.wrapper.AsyncBlock; +import com.thevoxelbox.voxelsniper.Message; + +import org.bukkit.block.Block; + +/** + * @author Voxel + */ +public class pMatCombo extends vPerformer +{ + + private int dr; + private int i; + private int ir; + + public pMatCombo() + { + name = "Mat-Combo"; + } + + @Override + public void init(com.thevoxelbox.voxelsniper.SnipeData v) + { + w = v.getWorld(); + dr = v.getReplaceData(); + i = v.getVoxelId(); + ir = v.getReplaceId(); + } + + @Override + public void info(Message vm) + { + vm.performerName(name); + vm.voxel(); + vm.replace(); + vm.replaceData(); + } + + @SuppressWarnings("deprecation") + @Override + public void perform(AsyncBlock b) + { + if (b.getTypeId() == ir && b.getPropertyId() == dr) + { + h.put(b); + b.setTypeId(i); + } + } + + @Override + public boolean isUsingReplaceMaterial() + { + return true; + } +} diff --git a/favs/src/main/java/com/thevoxelbox/voxelsniper/brush/perform/pMatComboNophys.java b/favs/src/main/java/com/thevoxelbox/voxelsniper/brush/perform/pMatComboNophys.java new file mode 100644 index 000000000..a0a7164bb --- /dev/null +++ b/favs/src/main/java/com/thevoxelbox/voxelsniper/brush/perform/pMatComboNophys.java @@ -0,0 +1,61 @@ +/* + * To change this template, choose Tools | Templates + * and open the template in the editor. + */ +package com.thevoxelbox.voxelsniper.brush.perform; + +import com.boydti.fawe.bukkit.wrapper.AsyncBlock; +import com.thevoxelbox.voxelsniper.Message; + +import org.bukkit.block.Block; + +/** + * @author Voxel + */ +public class pMatComboNophys extends vPerformer +{ + + private int dr; + private int i; + private int ir; + + public pMatComboNophys() + { + name = "Mat-Combo, No Physics"; + } + + @Override + public void init(com.thevoxelbox.voxelsniper.SnipeData v) + { + w = v.getWorld(); + dr = v.getReplaceData(); + i = v.getVoxelId(); + ir = v.getReplaceId(); + } + + @Override + public void info(Message vm) + { + vm.performerName(name); + vm.voxel(); + vm.replace(); + vm.replaceData(); + } + + @SuppressWarnings("deprecation") + @Override + public void perform(AsyncBlock b) + { + if (b.getTypeId() == ir && b.getPropertyId() == dr) + { + h.put(b); + b.setTypeId(i); + } + } + + @Override + public boolean isUsingReplaceMaterial() + { + return true; + } +} diff --git a/favs/src/main/java/com/thevoxelbox/voxelsniper/brush/perform/pMatInk.java b/favs/src/main/java/com/thevoxelbox/voxelsniper/brush/perform/pMatInk.java new file mode 100644 index 000000000..c61c236bc --- /dev/null +++ b/favs/src/main/java/com/thevoxelbox/voxelsniper/brush/perform/pMatInk.java @@ -0,0 +1,58 @@ +/* + * To change this template, choose Tools | Templates + * and open the template in the editor. + */ +package com.thevoxelbox.voxelsniper.brush.perform; + +import com.boydti.fawe.bukkit.wrapper.AsyncBlock; +import com.thevoxelbox.voxelsniper.Message; + +import org.bukkit.block.Block; + +/** + * @author Voxel + */ +public class pMatInk extends vPerformer +{ + + private int i; + private int dr; + + public pMatInk() + { + name = "Mat-Ink"; + } + + @Override + public void init(com.thevoxelbox.voxelsniper.SnipeData v) + { + w = v.getWorld(); + i = v.getVoxelId(); + dr = v.getReplaceData(); + } + + @Override + public void info(Message vm) + { + vm.performerName(name); + vm.voxel(); + vm.replaceData(); + } + + @SuppressWarnings("deprecation") + @Override + public void perform(AsyncBlock b) + { + if (b.getPropertyId() == dr) + { + h.put(b); + b.setTypeId(i); + } + } + + @Override + public boolean isUsingReplaceMaterial() + { + return true; + } +} diff --git a/favs/src/main/java/com/thevoxelbox/voxelsniper/brush/perform/pMatInkNoPhys.java b/favs/src/main/java/com/thevoxelbox/voxelsniper/brush/perform/pMatInkNoPhys.java new file mode 100644 index 000000000..dce33eb40 --- /dev/null +++ b/favs/src/main/java/com/thevoxelbox/voxelsniper/brush/perform/pMatInkNoPhys.java @@ -0,0 +1,58 @@ +/* + * To change this template, choose Tools | Templates + * and open the template in the editor. + */ +package com.thevoxelbox.voxelsniper.brush.perform; + +import com.boydti.fawe.bukkit.wrapper.AsyncBlock; +import com.thevoxelbox.voxelsniper.Message; + +import org.bukkit.block.Block; + +/** + * @author Voxel + */ +public class pMatInkNoPhys extends vPerformer +{ + + private int i; + private int dr; + + public pMatInkNoPhys() + { + name = "Mat-Ink, No Physics"; + } + + @Override + public void init(com.thevoxelbox.voxelsniper.SnipeData v) + { + w = v.getWorld(); + i = v.getVoxelId(); + dr = v.getReplaceData(); + } + + @Override + public void info(Message vm) + { + vm.performerName(name); + vm.voxel(); + vm.replaceData(); + } + + @SuppressWarnings("deprecation") + @Override + public void perform(AsyncBlock b) + { + if (b.getPropertyId() == dr) + { + h.put(b); + b.setTypeId(i); + } + } + + @Override + public boolean isUsingReplaceMaterial() + { + return true; + } +} diff --git a/favs/src/main/java/com/thevoxelbox/voxelsniper/brush/perform/pMatMat.java b/favs/src/main/java/com/thevoxelbox/voxelsniper/brush/perform/pMatMat.java new file mode 100644 index 000000000..b583ff8cc --- /dev/null +++ b/favs/src/main/java/com/thevoxelbox/voxelsniper/brush/perform/pMatMat.java @@ -0,0 +1,58 @@ +/* + * To change this template, choose Tools | Templates + * and open the template in the editor. + */ +package com.thevoxelbox.voxelsniper.brush.perform; + +import com.boydti.fawe.bukkit.wrapper.AsyncBlock; +import com.thevoxelbox.voxelsniper.Message; + +import org.bukkit.block.Block; + +/** + * @author Voxel + */ +public class pMatMat extends vPerformer +{ + + private int i; + private int r; + + public pMatMat() + { + name = "Mat-Mat"; + } + + @Override + public void init(com.thevoxelbox.voxelsniper.SnipeData v) + { + w = v.getWorld(); + i = v.getVoxelId(); + r = v.getReplaceId(); + } + + @Override + public void info(Message vm) + { + vm.performerName(name); + vm.voxel(); + vm.replace(); + } + + @SuppressWarnings("deprecation") + @Override + public void perform(AsyncBlock b) + { + if (b.getTypeId() == r) + { + h.put(b); + b.setTypeId(i); + } + } + + @Override + public boolean isUsingReplaceMaterial() + { + return true; + } +} diff --git a/favs/src/main/java/com/thevoxelbox/voxelsniper/brush/perform/pMatMatNoPhys.java b/favs/src/main/java/com/thevoxelbox/voxelsniper/brush/perform/pMatMatNoPhys.java new file mode 100644 index 000000000..500162bb3 --- /dev/null +++ b/favs/src/main/java/com/thevoxelbox/voxelsniper/brush/perform/pMatMatNoPhys.java @@ -0,0 +1,58 @@ +/* + * To change this template, choose Tools | Templates + * and open the template in the editor. + */ +package com.thevoxelbox.voxelsniper.brush.perform; + +import com.boydti.fawe.bukkit.wrapper.AsyncBlock; +import com.thevoxelbox.voxelsniper.Message; + +import org.bukkit.block.Block; + +/** + * @author Voxel + */ +public class pMatMatNoPhys extends vPerformer +{ + + private int i; + private int r; + + public pMatMatNoPhys() + { + name = "Mat-Mat No-Physics"; + } + + @Override + public void init(com.thevoxelbox.voxelsniper.SnipeData v) + { + w = v.getWorld(); + i = v.getVoxelId(); + r = v.getReplaceId(); + } + + @Override + public void info(Message vm) + { + vm.performerName(name); + vm.voxel(); + vm.replace(); + } + + @SuppressWarnings("deprecation") + @Override + public void perform(AsyncBlock b) + { + if (b.getTypeId() == r) + { + h.put(b); + b.setTypeId(i); + } + } + + @Override + public boolean isUsingReplaceMaterial() + { + return true; + } +} diff --git a/favs/src/main/java/com/thevoxelbox/voxelsniper/brush/perform/pMaterial.java b/favs/src/main/java/com/thevoxelbox/voxelsniper/brush/perform/pMaterial.java new file mode 100644 index 000000000..f4fc87ed1 --- /dev/null +++ b/favs/src/main/java/com/thevoxelbox/voxelsniper/brush/perform/pMaterial.java @@ -0,0 +1,49 @@ +/* + * To change this template, choose Tools | Templates + * and open the template in the editor. + */ +package com.thevoxelbox.voxelsniper.brush.perform; + +import com.boydti.fawe.bukkit.wrapper.AsyncBlock; +import com.thevoxelbox.voxelsniper.Message; + +import org.bukkit.block.Block; + +/** + * @author Voxel + */ +public class pMaterial extends vPerformer +{ + + private int i; + + public pMaterial() + { + name = "Material"; + } + + @Override + public void init(com.thevoxelbox.voxelsniper.SnipeData v) + { + w = v.getWorld(); + i = v.getVoxelId(); + } + + @Override + public void info(Message vm) + { + vm.performerName(name); + vm.voxel(); + } + + @SuppressWarnings("deprecation") + @Override + public void perform(AsyncBlock b) + { + if (b.getTypeId() != i) + { + h.put(b); + b.setTypeId(i); + } + } +} diff --git a/favs/src/main/java/com/thevoxelbox/voxelsniper/brush/perform/pMaterialNoPhys.java b/favs/src/main/java/com/thevoxelbox/voxelsniper/brush/perform/pMaterialNoPhys.java new file mode 100644 index 000000000..e7bfc06d5 --- /dev/null +++ b/favs/src/main/java/com/thevoxelbox/voxelsniper/brush/perform/pMaterialNoPhys.java @@ -0,0 +1,48 @@ +/* + * To change this template, choose Tools | Templates + * and open the template in the editor. + */ +package com.thevoxelbox.voxelsniper.brush.perform; + +import com.boydti.fawe.bukkit.wrapper.AsyncBlock; +import com.thevoxelbox.voxelsniper.Message; + +import org.bukkit.block.Block; + +/** + * @author Voxel + */ +public class pMaterialNoPhys extends vPerformer +{ + private int i; + + public pMaterialNoPhys() + { + name = "Set, No-Physics"; + } + + @Override + public void init(com.thevoxelbox.voxelsniper.SnipeData v) + { + w = v.getWorld(); + i = v.getVoxelId(); + } + + @Override + public void info(Message vm) + { + vm.performerName(name); + vm.voxel(); + } + + @SuppressWarnings("deprecation") + @Override + public void perform(AsyncBlock b) + { + if (b.getTypeId() != i) + { + h.put(b); + b.setTypeId(i); + } + } +} diff --git a/favs/src/main/java/com/thevoxelbox/voxelsniper/brush/perform/pNoUndo.java b/favs/src/main/java/com/thevoxelbox/voxelsniper/brush/perform/pNoUndo.java new file mode 100644 index 000000000..5c4b5bd6a --- /dev/null +++ b/favs/src/main/java/com/thevoxelbox/voxelsniper/brush/perform/pNoUndo.java @@ -0,0 +1,48 @@ +/* + * To change this template, choose Tools | Templates + * and open the template in the editor. + */ +package com.thevoxelbox.voxelsniper.brush.perform; + +import com.boydti.fawe.bukkit.wrapper.AsyncBlock; +import com.thevoxelbox.voxelsniper.Message; + +import org.bukkit.block.Block; + +/** + * @author Voxel + */ +public class pNoUndo extends vPerformer +{ + + private int i; + + public pNoUndo() + { + name = "BOMB SQUAD"; + } + + @Override + public void init(com.thevoxelbox.voxelsniper.SnipeData v) + { + w = v.getWorld(); + i = v.getVoxelId(); + } + + @Override + public void info(Message vm) + { + vm.performerName(name); + vm.voxel(); + } + + @SuppressWarnings("deprecation") + @Override + public void perform(AsyncBlock b) + { + if (b.getTypeId() != i) + { + b.setTypeId(i); + } + } +} \ No newline at end of file diff --git a/favs/src/main/java/com/thevoxelbox/voxelsniper/brush/perform/vPerformer.java b/favs/src/main/java/com/thevoxelbox/voxelsniper/brush/perform/vPerformer.java new file mode 100644 index 000000000..339a9dab3 --- /dev/null +++ b/favs/src/main/java/com/thevoxelbox/voxelsniper/brush/perform/vPerformer.java @@ -0,0 +1,45 @@ +/* + * To change this template, choose Tools | Templates + * and open the template in the editor. + */ +package com.thevoxelbox.voxelsniper.brush.perform; + +import com.boydti.fawe.bukkit.wrapper.AsyncBlock; +import com.thevoxelbox.voxelsniper.Message; +import com.thevoxelbox.voxelsniper.Undo; +import org.bukkit.World; +import org.bukkit.block.Block; + +/** + * @author Voxel + */ +public abstract class vPerformer +{ + + public String name = "Performer"; + protected Undo h; + protected World w; + + public abstract void info(Message vm); + + public abstract void init(com.thevoxelbox.voxelsniper.SnipeData v); + + public void setUndo() + { + h = new Undo(); + } + + public abstract void perform(AsyncBlock b); + + public Undo getUndo() + { + Undo temp = h; + h = null; + return temp; + } + + public boolean isUsingReplaceMaterial() + { + return false; + } +} diff --git a/favs/src/main/java/com/thevoxelbox/voxelsniper/command/VoxelBrushCommand.java b/favs/src/main/java/com/thevoxelbox/voxelsniper/command/VoxelBrushCommand.java new file mode 100644 index 000000000..4697a3ee0 --- /dev/null +++ b/favs/src/main/java/com/thevoxelbox/voxelsniper/command/VoxelBrushCommand.java @@ -0,0 +1,93 @@ +package com.thevoxelbox.voxelsniper.command; + +import com.thevoxelbox.voxelsniper.SnipeData; +import com.thevoxelbox.voxelsniper.Sniper; +import com.thevoxelbox.voxelsniper.VoxelSniper; +import com.thevoxelbox.voxelsniper.brush.IBrush; +import com.thevoxelbox.voxelsniper.brush.perform.Performer; +import com.thevoxelbox.voxelsniper.api.command.VoxelCommand; +import com.thevoxelbox.voxelsniper.event.SniperBrushChangedEvent; +import com.thevoxelbox.voxelsniper.event.SniperBrushSizeChangedEvent; +import org.bukkit.Bukkit; +import org.bukkit.entity.Player; + +import java.util.Arrays; + +public class VoxelBrushCommand extends VoxelCommand +{ + public VoxelBrushCommand(final VoxelSniper plugin) + { + super("VoxelBrush", plugin); + setIdentifier("b"); + setPermission("voxelsniper.sniper"); + } + + @Override + public boolean onCommand(Player player, String[] args) + { + Sniper sniper = plugin.getSniperManager().getSniperForPlayer(player); + String currentToolId = sniper.getCurrentToolId(); + SnipeData snipeData = sniper.getSnipeData(currentToolId); + + if (args == null || args.length == 0) + { + sniper.previousBrush(currentToolId); + sniper.displayInfo(); + return true; + } + else if (args.length > 0) + { + try + { + int newBrushSize = Integer.parseInt(args[0]); + if (!player.hasPermission("voxelsniper.ignorelimitations") && newBrushSize > plugin.getVoxelSniperConfiguration().getLiteSniperMaxBrushSize()) + { + player.sendMessage("Size is restricted to " + plugin.getVoxelSniperConfiguration().getLiteSniperMaxBrushSize() + " for you."); + newBrushSize = plugin.getVoxelSniperConfiguration().getLiteSniperMaxBrushSize(); + } + int originalSize = snipeData.getBrushSize(); + snipeData.setBrushSize(newBrushSize); + SniperBrushSizeChangedEvent event = new SniperBrushSizeChangedEvent(sniper, currentToolId, originalSize, snipeData.getBrushSize()); + Bukkit.getPluginManager().callEvent(event); + snipeData.getVoxelMessage().size(); + return true; + } + catch (NumberFormatException ingored) + { + } + + Class brush = plugin.getBrushManager().getBrushForHandle(args[0]); + if (brush != null) + { + IBrush orignalBrush = sniper.getBrush(currentToolId); + sniper.setBrush(currentToolId, brush); + + if (args.length > 1) + { + IBrush currentBrush = sniper.getBrush(currentToolId); + if (currentBrush instanceof Performer) + { + String[] parameters = Arrays.copyOfRange(args, 1, args.length); + ((Performer) currentBrush).parse(parameters, snipeData); + return true; + } + else + { + String[] parameters = hackTheArray(Arrays.copyOfRange(args, 1, args.length)); + currentBrush.parameters(parameters, snipeData); + return true; + } + } + SniperBrushChangedEvent event = new SniperBrushChangedEvent(sniper, currentToolId, orignalBrush, sniper.getBrush(currentToolId)); + sniper.displayInfo(); + return true; + } + else + { + player.sendMessage("Couldn't find Brush for brush handle \"" + args[0] + "\""); + return true; + } + } + return false; + } +} diff --git a/favs/src/main/java/com/thevoxelbox/voxelsniper/command/VoxelBrushToolCommand.java b/favs/src/main/java/com/thevoxelbox/voxelsniper/command/VoxelBrushToolCommand.java new file mode 100644 index 000000000..b50a7106a --- /dev/null +++ b/favs/src/main/java/com/thevoxelbox/voxelsniper/command/VoxelBrushToolCommand.java @@ -0,0 +1,91 @@ +package com.thevoxelbox.voxelsniper.command; + +import com.thevoxelbox.voxelsniper.SnipeAction; +import com.thevoxelbox.voxelsniper.Sniper; +import com.thevoxelbox.voxelsniper.VoxelSniper; +import com.thevoxelbox.voxelsniper.api.command.VoxelCommand; +import org.bukkit.Material; +import org.bukkit.entity.Player; + +public class VoxelBrushToolCommand extends VoxelCommand +{ + public VoxelBrushToolCommand(final VoxelSniper plugin) + { + super("VoxelBrushTool", plugin); + setIdentifier("btool"); + setPermission("voxelsniper.sniper"); + } + + @Override + public boolean onCommand(Player player, String[] args) + { + Sniper sniper = plugin.getSniperManager().getSniperForPlayer(player); + + if (args != null && args.length > 0) + { + if (args[0].equalsIgnoreCase("assign")) + { + SnipeAction action; + if (args[1].equalsIgnoreCase("arrow")) + { + action = SnipeAction.ARROW; + } + else if (args[1].equalsIgnoreCase("powder")) + { + action = SnipeAction.GUNPOWDER; + } + else + { + player.sendMessage("/btool assign "); + return true; + } + + if (args.length == 3 && args[2] != null && !args[2].isEmpty()) + { + Material itemInHand = (player.getItemInHand() != null) ? player.getItemInHand().getType() : null; + if (itemInHand == null) + { + player.sendMessage("/btool assign "); + return true; + } + if (sniper.setTool(args[2], action, itemInHand)) + { + player.sendMessage(itemInHand.name() + " has been assigned to '" + args[2] + "' as action " + action.name() + "."); + } + else + { + player.sendMessage("Couldn't assign tool."); + } + return true; + } + } + else if (args[0].equalsIgnoreCase("remove")) + { + if (args.length == 2 && args[1] != null && !args[1].isEmpty()) + { + sniper.removeTool(args[1]); + return true; + } + else + { + Material itemInHand = (player.getItemInHand() != null) ? player.getItemInHand().getType() : null; + if (itemInHand == null) + { + player.sendMessage("Can't unassign empty hands."); + return true; + } + if (sniper.getCurrentToolId() == null) + { + player.sendMessage("Can't unassign default tool."); + return true; + } + sniper.removeTool(sniper.getCurrentToolId(), itemInHand); + return true; + } + } + } + player.sendMessage("/btool assign "); + player.sendMessage("/btool remove [toolid]"); + return true; + } +} diff --git a/favs/src/main/java/com/thevoxelbox/voxelsniper/command/VoxelCenterCommand.java b/favs/src/main/java/com/thevoxelbox/voxelsniper/command/VoxelCenterCommand.java new file mode 100644 index 000000000..d5d6e6ff8 --- /dev/null +++ b/favs/src/main/java/com/thevoxelbox/voxelsniper/command/VoxelCenterCommand.java @@ -0,0 +1,38 @@ +package com.thevoxelbox.voxelsniper.command; + +import com.thevoxelbox.voxelsniper.SnipeData; +import com.thevoxelbox.voxelsniper.Sniper; +import com.thevoxelbox.voxelsniper.VoxelSniper; +import com.thevoxelbox.voxelsniper.api.command.VoxelCommand; +import org.bukkit.ChatColor; +import org.bukkit.entity.Player; + +public class VoxelCenterCommand extends VoxelCommand +{ + public VoxelCenterCommand(final VoxelSniper plugin) + { + super("VoxelCenter", plugin); + setIdentifier("vc"); + setPermission("voxelsniper.sniper"); + } + + @Override + public boolean onCommand(Player player, String[] args) + { + Sniper sniper = plugin.getSniperManager().getSniperForPlayer(player); + SnipeData snipeData = sniper.getSnipeData(sniper.getCurrentToolId()); + + try + { + int center = Integer.parseInt(args[0]); + snipeData.setcCen(center); + snipeData.getVoxelMessage().center(); + return true; + } + catch (final Exception exception) + { + player.sendMessage(ChatColor.RED + "Invalid input."); + return true; + } + } +} diff --git a/favs/src/main/java/com/thevoxelbox/voxelsniper/command/VoxelChunkCommand.java b/favs/src/main/java/com/thevoxelbox/voxelsniper/command/VoxelChunkCommand.java new file mode 100644 index 000000000..231a5fe9b --- /dev/null +++ b/favs/src/main/java/com/thevoxelbox/voxelsniper/command/VoxelChunkCommand.java @@ -0,0 +1,21 @@ +package com.thevoxelbox.voxelsniper.command; + +import com.thevoxelbox.voxelsniper.VoxelSniper; +import com.thevoxelbox.voxelsniper.api.command.VoxelCommand; +import org.bukkit.entity.Player; + +public class VoxelChunkCommand extends VoxelCommand +{ + public VoxelChunkCommand(final VoxelSniper plugin) + { + super("VoxelChunk", plugin); + setIdentifier("vchunk"); + } + + @Override + public boolean onCommand(Player player, String[] args) + { + player.getWorld().refreshChunk(player.getLocation().getBlockX(), player.getLocation().getBlockZ()); + return true; + } +} diff --git a/favs/src/main/java/com/thevoxelbox/voxelsniper/command/VoxelDefaultCommand.java b/favs/src/main/java/com/thevoxelbox/voxelsniper/command/VoxelDefaultCommand.java new file mode 100644 index 000000000..507375629 --- /dev/null +++ b/favs/src/main/java/com/thevoxelbox/voxelsniper/command/VoxelDefaultCommand.java @@ -0,0 +1,27 @@ +package com.thevoxelbox.voxelsniper.command; + +import com.thevoxelbox.voxelsniper.Sniper; +import com.thevoxelbox.voxelsniper.VoxelSniper; +import com.thevoxelbox.voxelsniper.api.command.VoxelCommand; +import org.bukkit.ChatColor; +import org.bukkit.entity.Player; + +public class VoxelDefaultCommand extends VoxelCommand +{ + public VoxelDefaultCommand(final VoxelSniper plugin) + { + super("VoxelDefault", plugin); + setIdentifier("d"); + setPermission("voxelsniper.sniper"); + } + + @Override + public boolean onCommand(Player player, String[] args) + { + Sniper sniper = plugin.getSniperManager().getSniperForPlayer(player); + + sniper.reset(sniper.getCurrentToolId()); + player.sendMessage(ChatColor.AQUA + "Brush settings reset to their default values."); + return true; + } +} diff --git a/favs/src/main/java/com/thevoxelbox/voxelsniper/command/VoxelGoToCommand.java b/favs/src/main/java/com/thevoxelbox/voxelsniper/command/VoxelGoToCommand.java new file mode 100644 index 000000000..9fa440250 --- /dev/null +++ b/favs/src/main/java/com/thevoxelbox/voxelsniper/command/VoxelGoToCommand.java @@ -0,0 +1,35 @@ +package com.thevoxelbox.voxelsniper.command; + +import com.thevoxelbox.voxelsniper.VoxelSniper; +import com.thevoxelbox.voxelsniper.api.command.VoxelCommand; +import org.bukkit.ChatColor; +import org.bukkit.Location; +import org.bukkit.entity.Player; + +public class VoxelGoToCommand extends VoxelCommand +{ + public VoxelGoToCommand(final VoxelSniper plugin) + { + super("VoxelGoTo", plugin); + setIdentifier("goto"); + setPermission("voxelsniper.sniper"); + } + + @Override + public boolean onCommand(Player player, String[] args) + { + try + { + final int x = Integer.parseInt(args[0]); + final int z = Integer.parseInt(args[1]); + player.teleport(new Location(player.getWorld(), x, player.getWorld().getHighestBlockYAt(x, z), z)); + player.sendMessage(ChatColor.GREEN + "Woosh!"); + return true; + } + catch (final Exception exception) + { + player.sendMessage(ChatColor.RED + "Invalid syntax."); + return true; + } + } +} diff --git a/favs/src/main/java/com/thevoxelbox/voxelsniper/command/VoxelHeightCommand.java b/favs/src/main/java/com/thevoxelbox/voxelsniper/command/VoxelHeightCommand.java new file mode 100644 index 000000000..4785be95f --- /dev/null +++ b/favs/src/main/java/com/thevoxelbox/voxelsniper/command/VoxelHeightCommand.java @@ -0,0 +1,38 @@ +package com.thevoxelbox.voxelsniper.command; + +import com.thevoxelbox.voxelsniper.SnipeData; +import com.thevoxelbox.voxelsniper.Sniper; +import com.thevoxelbox.voxelsniper.VoxelSniper; +import com.thevoxelbox.voxelsniper.api.command.VoxelCommand; +import org.bukkit.ChatColor; +import org.bukkit.entity.Player; + +public class VoxelHeightCommand extends VoxelCommand +{ + public VoxelHeightCommand(final VoxelSniper plugin) + { + super("VoxelHeight", plugin); + setIdentifier("vh"); + setPermission("voxelsniper.sniper"); + } + + @Override + public boolean onCommand(Player player, String[] args) + { + Sniper sniper = plugin.getSniperManager().getSniperForPlayer(player); + SnipeData snipeData = sniper.getSnipeData(sniper.getCurrentToolId()); + + try + { + int height = Integer.parseInt(args[0]); + snipeData.setVoxelHeight(height); + snipeData.getVoxelMessage().height(); + return true; + } + catch (final Exception exception) + { + player.sendMessage(ChatColor.RED + "Invalid input."); + return true; + } + } +} diff --git a/favs/src/main/java/com/thevoxelbox/voxelsniper/command/VoxelInkCommand.java b/favs/src/main/java/com/thevoxelbox/voxelsniper/command/VoxelInkCommand.java new file mode 100644 index 000000000..f55b11228 --- /dev/null +++ b/favs/src/main/java/com/thevoxelbox/voxelsniper/command/VoxelInkCommand.java @@ -0,0 +1,64 @@ +package com.thevoxelbox.voxelsniper.command; + +import com.boydti.fawe.bukkit.wrapper.AsyncBlock; +import com.sk89q.worldedit.world.block.BlockState; +import com.thevoxelbox.voxelsniper.RangeBlockHelper; +import com.thevoxelbox.voxelsniper.SnipeData; +import com.thevoxelbox.voxelsniper.Sniper; +import com.thevoxelbox.voxelsniper.VoxelSniper; +import com.thevoxelbox.voxelsniper.api.command.VoxelCommand; +import org.bukkit.block.Block; +import org.bukkit.entity.Player; + +public class VoxelInkCommand extends VoxelCommand +{ + public VoxelInkCommand(final VoxelSniper plugin) + { + super("VoxelInk", plugin); + setIdentifier("vi"); + setPermission("voxelsniper.sniper"); + } + + @Override + public boolean onCommand(Player player, String[] args) + { + Sniper sniper = plugin.getSniperManager().getSniperForPlayer(player); + + int dataValue; + + if (args.length == 0) + { + AsyncBlock targetBlock = new RangeBlockHelper(player, sniper.getWorld()).getTargetBlock(); + if (targetBlock != null) + { + dataValue = targetBlock.getPropertyId(); + } + else + { + return true; + } + } + else + { + try + { + dataValue = Integer.parseInt(args[0]); + } + catch (NumberFormatException exception) + { + BlockState state = BlockState.get(args[0]); + if (state == null) { + player.sendMessage("Couldn't parse input."); + return true; + } else { + dataValue = state.getInternalPropertiesId(); + } + } + } + + SnipeData snipeData = sniper.getSnipeData(sniper.getCurrentToolId()); + snipeData.setData(dataValue); + snipeData.getVoxelMessage().data(); + return true; + } +} diff --git a/favs/src/main/java/com/thevoxelbox/voxelsniper/command/VoxelInkReplaceCommand.java b/favs/src/main/java/com/thevoxelbox/voxelsniper/command/VoxelInkReplaceCommand.java new file mode 100644 index 000000000..fe8f2f67a --- /dev/null +++ b/favs/src/main/java/com/thevoxelbox/voxelsniper/command/VoxelInkReplaceCommand.java @@ -0,0 +1,64 @@ +package com.thevoxelbox.voxelsniper.command; + +import com.boydti.fawe.bukkit.wrapper.AsyncBlock; +import com.sk89q.worldedit.world.block.BlockState; +import com.thevoxelbox.voxelsniper.RangeBlockHelper; +import com.thevoxelbox.voxelsniper.SnipeData; +import com.thevoxelbox.voxelsniper.Sniper; +import com.thevoxelbox.voxelsniper.VoxelSniper; +import com.thevoxelbox.voxelsniper.api.command.VoxelCommand; +import org.bukkit.block.Block; +import org.bukkit.entity.Player; + +public class VoxelInkReplaceCommand extends VoxelCommand +{ + public VoxelInkReplaceCommand(final VoxelSniper plugin) + { + super("VoxelInkReplace", plugin); + setIdentifier("vir"); + setPermission("voxelsniper.sniper"); + } + + @Override + public boolean onCommand(Player player, String[] args) + { + Sniper sniper = plugin.getSniperManager().getSniperForPlayer(player); + + int dataValue; + + if (args.length == 0) + { + AsyncBlock targetBlock = new RangeBlockHelper(player, sniper.getWorld()).getTargetBlock(); + if (targetBlock != null) + { + dataValue = targetBlock.getPropertyId(); + } + else + { + return true; + } + } + else + { + try + { + dataValue = Integer.parseInt(args[0]); + } + catch (NumberFormatException exception) + { + BlockState state = BlockState.get(args[0]); + if (state == null) { + player.sendMessage("Couldn't parse input."); + return true; + } else { + dataValue = state.getInternalPropertiesId(); + } + } + } + + SnipeData snipeData = sniper.getSnipeData(sniper.getCurrentToolId()); + snipeData.setReplaceData(dataValue); + snipeData.getVoxelMessage().replaceData(); + return true; + } +} diff --git a/favs/src/main/java/com/thevoxelbox/voxelsniper/command/VoxelListCommand.java b/favs/src/main/java/com/thevoxelbox/voxelsniper/command/VoxelListCommand.java new file mode 100644 index 000000000..c003ba9e8 --- /dev/null +++ b/favs/src/main/java/com/thevoxelbox/voxelsniper/command/VoxelListCommand.java @@ -0,0 +1,74 @@ +package com.thevoxelbox.voxelsniper.command; + +import com.boydti.fawe.bukkit.wrapper.AsyncBlock; +import com.boydti.fawe.object.FawePlayer; +import com.sk89q.worldedit.WorldEdit; +import com.sk89q.worldedit.bukkit.BukkitAdapter; +import com.sk89q.worldedit.extension.factory.MaskFactory; +import com.sk89q.worldedit.extension.input.ParserContext; +import com.sk89q.worldedit.extent.NullExtent; +import com.sk89q.worldedit.function.mask.BlockMask; +import com.sk89q.worldedit.function.mask.BlockMaskBuilder; +import com.sk89q.worldedit.function.mask.Mask; +import com.sk89q.worldedit.world.block.BlockState; +import com.sk89q.worldedit.world.block.BlockTypes; +import com.thevoxelbox.voxelsniper.RangeBlockHelper; +import com.thevoxelbox.voxelsniper.SnipeData; +import com.thevoxelbox.voxelsniper.Sniper; +import com.thevoxelbox.voxelsniper.VoxelSniper; +import com.thevoxelbox.voxelsniper.api.command.VoxelCommand; +import org.bukkit.Material; +import org.bukkit.block.Block; +import org.bukkit.entity.Player; + +public class VoxelListCommand extends VoxelCommand +{ + public VoxelListCommand(final VoxelSniper plugin) + { + super("VoxelList", plugin); + setIdentifier("vl"); + setPermission("voxelsniper.sniper"); + } + + @Override + public boolean onCommand(Player player, String[] args) + { + Sniper sniper = plugin.getSniperManager().getSniperForPlayer(player); + + SnipeData snipeData = sniper.getSnipeData(sniper.getCurrentToolId()); + if (args.length == 0) + { + final RangeBlockHelper rangeBlockHelper = new RangeBlockHelper(player, sniper.getWorld()); + final AsyncBlock targetBlock = rangeBlockHelper.getTargetBlock(); + snipeData.getVoxelList().add(BukkitAdapter.adapt(targetBlock.getBlockData())); + snipeData.getVoxelMessage().voxelList(); + return true; + } + else + { + if (args[0].equalsIgnoreCase("clear")) + { + snipeData.getVoxelList().clear(); + snipeData.getVoxelMessage().voxelList(); + return true; + } + } + + for (String string : args) + { + boolean remove = false; + if (string.charAt(0) == '-') { + string = string.substring(1); + remove = true; + } + BlockMaskBuilder builder = new BlockMaskBuilder().addRegex(string); + BlockMask mask = builder.build(new NullExtent()); + if (remove) { + snipeData.getVoxelList().removeValue(mask); + } else { + snipeData.getVoxelList().add(mask); + } + } + return true; + } +} diff --git a/favs/src/main/java/com/thevoxelbox/voxelsniper/command/VoxelPaintCommand.java b/favs/src/main/java/com/thevoxelbox/voxelsniper/command/VoxelPaintCommand.java new file mode 100644 index 000000000..780a9a04c --- /dev/null +++ b/favs/src/main/java/com/thevoxelbox/voxelsniper/command/VoxelPaintCommand.java @@ -0,0 +1,48 @@ +package com.thevoxelbox.voxelsniper.command; + +import com.thevoxelbox.voxelsniper.PaintingWrapper; +import com.thevoxelbox.voxelsniper.VoxelSniper; +import com.thevoxelbox.voxelsniper.api.command.VoxelCommand; +import org.bukkit.ChatColor; +import org.bukkit.entity.Player; + +public class VoxelPaintCommand extends VoxelCommand +{ + public VoxelPaintCommand(final VoxelSniper plugin) + { + super("VoxelPaint", plugin); + setIdentifier("paint"); + setPermission("voxelsniper.paint"); + } + + @Override + public boolean onCommand(Player player, String[] args) + { + if (args.length == 1) + { + if (args[0].equalsIgnoreCase("back")) + { + PaintingWrapper.paint(player, true, true, 0); + return true; + } + else + { + try + { + PaintingWrapper.paint(player, false, false, Integer.parseInt(args[0])); + return true; + } + catch (final Exception exception) + { + player.sendMessage(ChatColor.RED + "Invalid input."); + return true; + } + } + } + else + { + PaintingWrapper.paint(player, true, false, 0); + return true; + } + } +} diff --git a/favs/src/main/java/com/thevoxelbox/voxelsniper/command/VoxelPerformerCommand.java b/favs/src/main/java/com/thevoxelbox/voxelsniper/command/VoxelPerformerCommand.java new file mode 100644 index 000000000..d9cf46fc4 --- /dev/null +++ b/favs/src/main/java/com/thevoxelbox/voxelsniper/command/VoxelPerformerCommand.java @@ -0,0 +1,62 @@ +package com.thevoxelbox.voxelsniper.command; + +import com.thevoxelbox.voxelsniper.SnipeData; +import com.thevoxelbox.voxelsniper.Sniper; +import com.thevoxelbox.voxelsniper.VoxelSniper; +import com.thevoxelbox.voxelsniper.brush.IBrush; +import com.thevoxelbox.voxelsniper.brush.perform.Performer; +import com.thevoxelbox.voxelsniper.api.command.VoxelCommand; +import org.bukkit.entity.Player; + +import java.util.logging.Level; + +public class VoxelPerformerCommand extends VoxelCommand +{ + public VoxelPerformerCommand(final VoxelSniper plugin) + { + super("VoxelPerformer", plugin); + setIdentifier("p"); + setPermission("voxelsniper.sniper"); + } + + @Override + public boolean onCommand(Player player, String[] args) + { + Sniper sniper = plugin.getSniperManager().getSniperForPlayer(player); + SnipeData snipeData = sniper.getSnipeData(sniper.getCurrentToolId()); + + try + { + if (args == null || args.length == 0) + { + IBrush brush = sniper.getBrush(sniper.getCurrentToolId()); + if (brush instanceof Performer) + { + ((Performer) brush).parse(new String[]{ "m" }, snipeData); + } + else + { + player.sendMessage("This brush is not a performer brush."); + } + } + else + { + IBrush brush = sniper.getBrush(sniper.getCurrentToolId()); + if (brush instanceof Performer) + { + ((Performer) brush).parse(args, snipeData); + } + else + { + player.sendMessage("This brush is not a performer brush."); + } + } + return true; + } + catch (Exception exception) + { + plugin.getLogger().log(Level.WARNING, "Command error from " + player.getName(), exception); + return true; + } + } +} diff --git a/favs/src/main/java/com/thevoxelbox/voxelsniper/command/VoxelReplaceCommand.java b/favs/src/main/java/com/thevoxelbox/voxelsniper/command/VoxelReplaceCommand.java new file mode 100644 index 000000000..d3674f374 --- /dev/null +++ b/favs/src/main/java/com/thevoxelbox/voxelsniper/command/VoxelReplaceCommand.java @@ -0,0 +1,51 @@ +package com.thevoxelbox.voxelsniper.command; + +import com.bekvon.bukkit.residence.commands.material; +import com.boydti.fawe.bukkit.wrapper.AsyncBlock; +import com.sk89q.worldedit.world.block.BlockTypes; +import com.thevoxelbox.voxelsniper.RangeBlockHelper; +import com.thevoxelbox.voxelsniper.SnipeData; +import com.thevoxelbox.voxelsniper.Sniper; +import com.thevoxelbox.voxelsniper.VoxelSniper; +import com.thevoxelbox.voxelsniper.api.command.VoxelCommand; +import org.bukkit.ChatColor; +import org.bukkit.Material; +import org.bukkit.block.Block; +import org.bukkit.entity.Player; + +public class VoxelReplaceCommand extends VoxelCommand +{ + public VoxelReplaceCommand(final VoxelSniper plugin) + { + super("VoxelReplace", plugin); + setIdentifier("vr"); + setPermission("voxelsniper.sniper"); + } + + @Override + public boolean onCommand(Player player, String[] args) + { + Sniper sniper = plugin.getSniperManager().getSniperForPlayer(player); + SnipeData snipeData = sniper.getSnipeData(sniper.getCurrentToolId()); + + if (args.length == 0) + { + AsyncBlock targetBlock = new RangeBlockHelper(player, sniper.getWorld()).getTargetBlock(); + if (targetBlock != null) + { + snipeData.setReplaceId(targetBlock.getTypeId()); + snipeData.getVoxelMessage().replace(); + } + return true; + } + + BlockTypes weType = BlockTypes.parse(args[0]); + if (weType != null) + { + snipeData.setReplaceId(weType.getInternalId()); + snipeData.getVoxelMessage().replace(); + return true; + } + return false; + } +} diff --git a/favs/src/main/java/com/thevoxelbox/voxelsniper/command/VoxelSniperCommand.java b/favs/src/main/java/com/thevoxelbox/voxelsniper/command/VoxelSniperCommand.java new file mode 100644 index 000000000..5b9c839da --- /dev/null +++ b/favs/src/main/java/com/thevoxelbox/voxelsniper/command/VoxelSniperCommand.java @@ -0,0 +1,111 @@ +package com.thevoxelbox.voxelsniper.command; + +import com.google.common.base.Joiner; +import com.google.common.collect.Lists; +import com.google.common.collect.Multimap; +import com.thevoxelbox.voxelsniper.SnipeData; +import com.thevoxelbox.voxelsniper.Sniper; +import com.thevoxelbox.voxelsniper.VoxelSniper; +import com.thevoxelbox.voxelsniper.brush.IBrush; +import com.thevoxelbox.voxelsniper.api.command.VoxelCommand; +import com.thevoxelbox.voxelsniper.brush.perform.PerformerE; +import org.bukkit.ChatColor; +import org.bukkit.entity.Player; + +import java.util.List; + +public class VoxelSniperCommand extends VoxelCommand +{ + + public VoxelSniperCommand(final VoxelSniper plugin) + { + + super("VoxelSniper", plugin); + setIdentifier("vs"); + setPermission("voxelsniper.sniper"); + } + + @Override + public boolean onCommand(Player player, String[] args) + { + Sniper sniper = VoxelSniper.getInstance().getSniperManager().getSniperForPlayer(player); + + if (args.length >= 1) + { + if (args[0].equalsIgnoreCase("brushes")) + { + Multimap, String> registeredBrushesMultimap = VoxelSniper.getInstance().getBrushManager().getRegisteredBrushesMultimap(); + List allHandles = Lists.newLinkedList(); + for (Class brushClass : registeredBrushesMultimap.keySet()) + { + allHandles.addAll(registeredBrushesMultimap.get(brushClass)); + } + player.sendMessage(Joiner.on(", ").skipNulls().join(allHandles)); + return true; + } + else if (args[0].equalsIgnoreCase("range")) + { + SnipeData snipeData = sniper.getSnipeData(sniper.getCurrentToolId()); + if (args.length == 2) + { + try + { + int range = Integer.parseInt(args[1]); + if (range < 0) + { + player.sendMessage("Negative values are not allowed."); + } + snipeData.setRange(range); + snipeData.setRanged(true); + snipeData.getVoxelMessage().toggleRange(); + + } + catch (NumberFormatException exception) + { + player.sendMessage("Can't parse number."); + } + return true; + } + else + { + snipeData.setRanged(!snipeData.isRanged()); + snipeData.getVoxelMessage().toggleRange(); + return true; + } + } + else if (args[0].equalsIgnoreCase("perf")) + { + player.sendMessage(ChatColor.AQUA + "Available performers (abbreviated):"); + player.sendMessage(PerformerE.performer_list_short); + return true; + } + else if (args[0].equalsIgnoreCase("perflong")) + { + player.sendMessage(ChatColor.AQUA + "Available performers:"); + player.sendMessage(PerformerE.performer_list_long); + return true; + } + else if (args[0].equalsIgnoreCase("enable")) + { + sniper.setEnabled(true); + player.sendMessage("VoxelSniper is " + (sniper.isEnabled() ? "enabled" : "disabled")); + return true; + } + else if (args[0].equalsIgnoreCase("disable")) + { + sniper.setEnabled(false); + player.sendMessage("VoxelSniper is " + (sniper.isEnabled() ? "enabled" : "disabled")); + return true; + } + else if (args[0].equalsIgnoreCase("toggle")) + { + sniper.setEnabled(!sniper.isEnabled()); + player.sendMessage("VoxelSniper is " + (sniper.isEnabled() ? "enabled" : "disabled")); + return true; + } + } + player.sendMessage(ChatColor.DARK_RED + "VoxelSniper - Current Brush Settings:"); + sniper.displayInfo(); + return true; + } +} diff --git a/favs/src/main/java/com/thevoxelbox/voxelsniper/command/VoxelUndoCommand.java b/favs/src/main/java/com/thevoxelbox/voxelsniper/command/VoxelUndoCommand.java new file mode 100644 index 000000000..c551b0dd8 --- /dev/null +++ b/favs/src/main/java/com/thevoxelbox/voxelsniper/command/VoxelUndoCommand.java @@ -0,0 +1,41 @@ +package com.thevoxelbox.voxelsniper.command; + +import com.thevoxelbox.voxelsniper.Sniper; +import com.thevoxelbox.voxelsniper.VoxelSniper; +import com.thevoxelbox.voxelsniper.api.command.VoxelCommand; +import org.bukkit.entity.Player; + +public class VoxelUndoCommand extends VoxelCommand +{ + public VoxelUndoCommand(final VoxelSniper plugin) + { + super("VoxelUndo", plugin); + setIdentifier("u"); + setPermission("voxelsniper.sniper"); + } + + @Override + public boolean onCommand(Player player, String[] args) + { + Sniper sniper = plugin.getSniperManager().getSniperForPlayer(player); + + if (args.length == 1) + { + try + { + int amount = Integer.parseInt(args[0]); + sniper.undo(amount); + } + catch (NumberFormatException exception) + { + player.sendMessage("Error while parsing amount of undo. Number format exception."); + } + } + else + { + sniper.undo(); + } + plugin.getLogger().info("Player \"" + player.getName() + "\" used /u"); + return true; + } +} diff --git a/favs/src/main/java/com/thevoxelbox/voxelsniper/command/VoxelUndoUserCommand.java b/favs/src/main/java/com/thevoxelbox/voxelsniper/command/VoxelUndoUserCommand.java new file mode 100644 index 000000000..ad5ca4433 --- /dev/null +++ b/favs/src/main/java/com/thevoxelbox/voxelsniper/command/VoxelUndoUserCommand.java @@ -0,0 +1,32 @@ +package com.thevoxelbox.voxelsniper.command; + +import com.thevoxelbox.voxelsniper.VoxelSniper; +import com.thevoxelbox.voxelsniper.api.command.VoxelCommand; +import org.bukkit.Bukkit; +import org.bukkit.ChatColor; +import org.bukkit.entity.Player; + +public class VoxelUndoUserCommand extends VoxelCommand +{ + public VoxelUndoUserCommand(final VoxelSniper plugin) + { + super("VoxelUndoUser", plugin); + setIdentifier("uu"); + setPermission("voxelsniper.sniper"); + } + + @Override + public boolean onCommand(Player player, String[] args) + { + try + { + plugin.getSniperManager().getSniperForPlayer(Bukkit.getPlayer(args[0])).undo(); + return true; + } + catch (final Exception exception) + { + player.sendMessage(ChatColor.GREEN + "Player not found."); + return true; + } + } +} diff --git a/favs/src/main/java/com/thevoxelbox/voxelsniper/command/VoxelVoxelCommand.java b/favs/src/main/java/com/thevoxelbox/voxelsniper/command/VoxelVoxelCommand.java new file mode 100644 index 000000000..cbd8b52fe --- /dev/null +++ b/favs/src/main/java/com/thevoxelbox/voxelsniper/command/VoxelVoxelCommand.java @@ -0,0 +1,89 @@ +/** + This file is part of VoxelSniper, licensed under the MIT License (MIT). + + Copyright (c) The VoxelBox + Copyright (c) contributors + + Permission is hereby granted, free of charge, to any person obtaining a copy + of this software and associated documentation files (the "Software"), to deal + in the Software without restriction, including without limitation the rights + to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + copies of the Software, and to permit persons to whom the Software is + furnished to do so, subject to the following conditions: + + The above copyright notice and this permission notice shall be included in + all copies or substantial portions of the Software. + + THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + THE SOFTWARE. + */ + +package com.thevoxelbox.voxelsniper.command; + +import com.bekvon.bukkit.residence.commands.material; +import com.boydti.fawe.bukkit.favs.PatternUtil; +import com.sk89q.worldedit.WorldEdit; +import com.sk89q.worldedit.bukkit.BukkitAdapter; +import com.sk89q.worldedit.world.block.BlockTypes; +import com.thevoxelbox.voxelsniper.RangeBlockHelper; +import com.thevoxelbox.voxelsniper.SnipeData; +import com.thevoxelbox.voxelsniper.Sniper; +import com.thevoxelbox.voxelsniper.VoxelSniper; +import com.thevoxelbox.voxelsniper.api.command.VoxelCommand; +import org.bukkit.Material; +import org.bukkit.block.Block; +import org.bukkit.entity.Player; + +public class VoxelVoxelCommand extends VoxelCommand { + public VoxelVoxelCommand(VoxelSniper plugin) { + super("VoxelVoxel", plugin); + this.setIdentifier("v"); + this.setPermission("voxelsniper.sniper"); + } + + public boolean onCommand(Player player, String[] args) { + Sniper sniper = this.plugin.getSniperManager().getSniperForPlayer(player); + SnipeData snipeData = sniper.getSnipeData(sniper.getCurrentToolId()); + if(args.length == 0) { + Block block = (new RangeBlockHelper(player, sniper.getWorld())).getTargetBlock(); + Material blockType = block.getType(); + + BlockTypes weType = BukkitAdapter.adapt(blockType); + if(!player.hasPermission("voxelsniper.ignorelimitations") && WorldEdit.getInstance().getConfiguration().disallowedBlocks.contains(weType)) { + player.sendMessage("You are not allowed to use " + blockType.name() + ". (WorldEdit config.yml)"); + return true; + } + + snipeData.setVoxelId(weType.getInternalId()); + snipeData.getVoxelMessage().voxel(); + snipeData.setPattern(null, null); + + return true; + } else { + BlockTypes weType = BlockTypes.parse(args[0]); + if(weType != null) { + if(!player.hasPermission("voxelsniper.ignorelimitations") && WorldEdit.getInstance().getConfiguration().disallowedBlocks.contains(weType)) { + player.sendMessage("You are not allowed to use " + weType + "."); + return true; + } else { + snipeData.setVoxelId(weType.getInternalId()); + snipeData.getVoxelMessage().voxel(); + snipeData.setPattern(null, null); + return true; + } + } else { + PatternUtil.parsePattern(player, snipeData, args[0]); + return true; + } + } + } + + public static Class inject() { + return VoxelVoxelCommand.class; + } +} diff --git a/favs/src/main/java/com/thevoxelbox/voxelsniper/event/SniperBrushChangedEvent.java b/favs/src/main/java/com/thevoxelbox/voxelsniper/event/SniperBrushChangedEvent.java new file mode 100644 index 000000000..3dd2b954b --- /dev/null +++ b/favs/src/main/java/com/thevoxelbox/voxelsniper/event/SniperBrushChangedEvent.java @@ -0,0 +1,75 @@ +/** + This file is part of VoxelSniper, licensed under the MIT License (MIT). + + Copyright (c) The VoxelBox + Copyright (c) contributors + + Permission is hereby granted, free of charge, to any person obtaining a copy + of this software and associated documentation files (the "Software"), to deal + in the Software without restriction, including without limitation the rights + to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + copies of the Software, and to permit persons to whom the Software is + furnished to do so, subject to the following conditions: + + The above copyright notice and this permission notice shall be included in + all copies or substantial portions of the Software. + + THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + THE SOFTWARE. + */ +package com.thevoxelbox.voxelsniper.event; + +import com.boydti.fawe.Fawe; +import com.thevoxelbox.voxelsniper.Sniper; +import com.thevoxelbox.voxelsniper.brush.IBrush; +import org.bukkit.event.Event; +import org.bukkit.event.HandlerList; + +public class SniperBrushChangedEvent extends Event { + private static final HandlerList handlers = new HandlerList(); + private final Sniper sniper; + private final IBrush originalBrush; + private final IBrush newBrush; + private final String toolId; + + public SniperBrushChangedEvent(Sniper sniper, String toolId, IBrush originalBrush, IBrush newBrush) { + super(!Fawe.isMainThread()); + this.sniper = sniper; + this.originalBrush = originalBrush; + this.newBrush = newBrush; + this.toolId = toolId; + } + + public static HandlerList getHandlerList() { + return handlers; + } + + public IBrush getOriginalBrush() { + return this.originalBrush; + } + + public IBrush getNewBrush() { + return this.newBrush; + } + + public Sniper getSniper() { + return this.sniper; + } + + public String getToolId() { + return this.toolId; + } + + public HandlerList getHandlers() { + return handlers; + } + + public static Class inject() { + return SniperBrushChangedEvent.class; + } +} diff --git a/favs/src/main/java/com/thevoxelbox/voxelsniper/event/SniperBrushSizeChangedEvent.java b/favs/src/main/java/com/thevoxelbox/voxelsniper/event/SniperBrushSizeChangedEvent.java new file mode 100644 index 000000000..4d373dc07 --- /dev/null +++ b/favs/src/main/java/com/thevoxelbox/voxelsniper/event/SniperBrushSizeChangedEvent.java @@ -0,0 +1,57 @@ +package com.thevoxelbox.voxelsniper.event; + +import com.thevoxelbox.voxelsniper.Sniper; +import org.bukkit.event.Cancellable; +import org.bukkit.event.Event; +import org.bukkit.event.HandlerList; + +/** + * + */ +public class SniperBrushSizeChangedEvent extends Event +{ + private static final HandlerList handlers = new HandlerList(); + private final Sniper sniper; + private final int originalSize; + private final int newSize; + private final String toolId; + + public SniperBrushSizeChangedEvent(Sniper sniper, String toolId, int originalSize, int newSize) + { + this.sniper = sniper; + this.originalSize = originalSize; + this.newSize = newSize; + this.toolId = toolId; + } + + public static HandlerList getHandlerList() + { + return handlers; + } + + public int getOriginalSize() + { + return originalSize; + } + + public int getNewSize() + { + return newSize; + } + + public Sniper getSniper() + { + return sniper; + } + + public String getToolId() + { + return toolId; + } + + @Override + public HandlerList getHandlers() + { + return handlers; + } +} diff --git a/favs/src/main/java/com/thevoxelbox/voxelsniper/event/SniperMaterialChangedEvent.java b/favs/src/main/java/com/thevoxelbox/voxelsniper/event/SniperMaterialChangedEvent.java new file mode 100644 index 000000000..e7801eb74 --- /dev/null +++ b/favs/src/main/java/com/thevoxelbox/voxelsniper/event/SniperMaterialChangedEvent.java @@ -0,0 +1,77 @@ +/** + This file is part of VoxelSniper, licensed under the MIT License (MIT). + + Copyright (c) The VoxelBox + Copyright (c) contributors + + Permission is hereby granted, free of charge, to any person obtaining a copy + of this software and associated documentation files (the "Software"), to deal + in the Software without restriction, including without limitation the rights + to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + copies of the Software, and to permit persons to whom the Software is + furnished to do so, subject to the following conditions: + + The above copyright notice and this permission notice shall be included in + all copies or substantial portions of the Software. + + THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + THE SOFTWARE. + */ + +package com.thevoxelbox.voxelsniper.event; + +import com.boydti.fawe.Fawe; +import com.thevoxelbox.voxelsniper.Sniper; +import org.bukkit.block.data.BlockData; +import org.bukkit.event.Event; +import org.bukkit.event.HandlerList; +import org.bukkit.material.MaterialData; + +public class SniperMaterialChangedEvent extends Event { + private static final HandlerList handlers = new HandlerList(); + private final Sniper sniper; + private final BlockData originalMaterial; + private final BlockData newMaterial; + private final String toolId; + + public SniperMaterialChangedEvent(Sniper sniper, String toolId, BlockData originalMaterial, BlockData newMaterial) { + super(!Fawe.get().isMainThread()); + this.sniper = sniper; + this.originalMaterial = originalMaterial; + this.newMaterial = newMaterial; + this.toolId = toolId; + } + + public static HandlerList getHandlerList() { + return handlers; + } + + public BlockData getOriginalMaterial() { + return this.originalMaterial; + } + + public BlockData getNewMaterial() { + return this.newMaterial; + } + + public Sniper getSniper() { + return this.sniper; + } + + public String getToolId() { + return this.toolId; + } + + public HandlerList getHandlers() { + return handlers; + } + + public static Class inject() { + return SniperMaterialChangedEvent.class; + } +} diff --git a/favs/src/main/java/com/thevoxelbox/voxelsniper/event/SniperReplaceMaterialChangedEvent.java b/favs/src/main/java/com/thevoxelbox/voxelsniper/event/SniperReplaceMaterialChangedEvent.java new file mode 100644 index 000000000..46bc22607 --- /dev/null +++ b/favs/src/main/java/com/thevoxelbox/voxelsniper/event/SniperReplaceMaterialChangedEvent.java @@ -0,0 +1,30 @@ +package com.thevoxelbox.voxelsniper.event; + +import com.thevoxelbox.voxelsniper.Sniper; +import org.bukkit.block.data.BlockData; +import org.bukkit.event.HandlerList; +import org.bukkit.material.MaterialData; + +/** + * + */ +public class SniperReplaceMaterialChangedEvent extends SniperMaterialChangedEvent +{ + private static final HandlerList handlers = new HandlerList(); + + public SniperReplaceMaterialChangedEvent(Sniper sniper, String toolId, BlockData originalMaterial, BlockData newMaterial) + { + super(sniper, toolId, originalMaterial, newMaterial); + } + + public static HandlerList getHandlerList() + { + return handlers; + } + + @Override + public HandlerList getHandlers() + { + return handlers; + } +} diff --git a/favs/src/main/java/com/thevoxelbox/voxelsniper/jsap/HelpJSAP.java b/favs/src/main/java/com/thevoxelbox/voxelsniper/jsap/HelpJSAP.java new file mode 100644 index 000000000..17a01b81c --- /dev/null +++ b/favs/src/main/java/com/thevoxelbox/voxelsniper/jsap/HelpJSAP.java @@ -0,0 +1,205 @@ +package com.thevoxelbox.voxelsniper.jsap; + +import java.io.IOException; +import java.net.URL; +import java.util.Collections; +import java.util.Iterator; +import java.util.LinkedList; +import java.util.List; + +import com.martiansoftware.jsap.JSAP; +import com.martiansoftware.jsap.JSAPException; +import com.martiansoftware.jsap.JSAPResult; +import com.martiansoftware.jsap.Switch; +import com.martiansoftware.util.StringUtils; + +import org.bukkit.ChatColor; + +/** + * JSAP parser with help generating code. + * + * @author MikeMatrix + */ +public class HelpJSAP extends JSAP +{ + + private String name; + private String explanation; + private int screenWidth; + + /** + * @param name + * @param explanation + * @param screenWidth + */ + public HelpJSAP(final String name, final String explanation, final int screenWidth) + { + super(); + + this.name = name; + this.explanation = explanation; + this.screenWidth = screenWidth; + + try + { + this.registerParameter(new Switch("help", JSAP.NO_SHORTFLAG, "help", "Displays this help page.")); + } + catch (final JSAPException e) + { + } + } + + /** + * @param name + * @param explanation + * @param screenWidth + * @param resourceName + * + * @throws java.io.IOException + * if an I/O error occurs + * @throws com.martiansoftware.jsap.JSAPException + * if the configuration is not valid + */ + public HelpJSAP(final String name, final String explanation, final int screenWidth, final String resourceName) throws IOException, JSAPException + { + super(resourceName); + + this.name = name; + this.explanation = explanation; + this.screenWidth = screenWidth; + + try + { + this.registerParameter(new Switch("help", JSAP.NO_SHORTFLAG, "help", "Displays this help page.")); + } + catch (final JSAPException e) + { + } + } + + /** + * @param name + * @param explanation + * @param screenWidth + * @param jsapXML + * + * @throws java.io.IOException + * if an I/O error occurs + * @throws com.martiansoftware.jsap.JSAPException + * if the configuration is not valid + */ + public HelpJSAP(final String name, final String explanation, final int screenWidth, final URL jsapXML) throws IOException, JSAPException + { + super(jsapXML); + + this.name = name; + this.explanation = explanation; + this.screenWidth = screenWidth; + + try + { + this.registerParameter(new Switch("help", JSAP.NO_SHORTFLAG, "help", "Displays this help page.")); + } + catch (final JSAPException e) + { + } + } + + /** + * @return the explanation + */ + public final String getExplanation() + { + return this.explanation; + } + + /** + * @param explanation + * the explanation to set + */ + public final void setExplanation(final String explanation) + { + this.explanation = explanation; + } + + /** + * @return the name + */ + public final String getName() + { + return this.name; + } + + /** + * @param name + * the name to set + */ + public final void setName(final String name) + { + this.name = name; + } + + /** + * @return the screenWidth + */ + public final int getScreenWidth() + { + return this.screenWidth; + } + + /** + * @param screenWidth + * the screenWidth to set + */ + public final void setScreenWidth(final int screenWidth) + { + this.screenWidth = screenWidth; + } + + /** + * @param jsapResult + * + * @return if something has been written on writer. + */ + public final List writeHelpOrErrorMessageIfRequired(final JSAPResult jsapResult) + { + if (!(jsapResult.success()) || jsapResult.getBoolean("help")) + { + List returnValue = new LinkedList(); + // To avoid spurious missing argument errors we never print errors if help is required. + if (!jsapResult.getBoolean("help")) + { + for (final Iterator err = jsapResult.getErrorMessageIterator(); err.hasNext(); ) + { + returnValue.add(ChatColor.RED + "Error: " + ChatColor.DARK_RED + err.next()); + } + + return returnValue; + } + returnValue.add(ChatColor.GOLD + "Usage:"); + + List l = StringUtils.wrapToList(this.name + " " + this.getUsage(), this.screenWidth); + for (final Object aL : l) + { + returnValue.add(" " + aL.toString()); + } + + if (this.explanation != null) + { + returnValue.add(""); + l = StringUtils.wrapToList(this.explanation, this.screenWidth); + for (final Object aL : l) + { + final String next = (String) aL; + returnValue.add(ChatColor.AQUA + next); + } + } + + returnValue.add(""); + returnValue.add(this.getHelp(this.screenWidth)); + return returnValue; + } + + return Collections.emptyList(); + } +} diff --git a/favs/src/main/java/com/thevoxelbox/voxelsniper/jsap/NullableIntegerStringParser.java b/favs/src/main/java/com/thevoxelbox/voxelsniper/jsap/NullableIntegerStringParser.java new file mode 100644 index 000000000..30d196bff --- /dev/null +++ b/favs/src/main/java/com/thevoxelbox/voxelsniper/jsap/NullableIntegerStringParser.java @@ -0,0 +1,75 @@ +package com.thevoxelbox.voxelsniper.jsap; + +import com.martiansoftware.jsap.ParseException; +import com.martiansoftware.jsap.StringParser; + +/** + * A {@link com.martiansoftware.jsap.StringParser} for parsing Integers. The parse() method delegates the actual parsing to Integer.decode(String). + * + * @author Marty Lamb + * @see com.martiansoftware.jsap.StringParser + * @see Integer + */ +public class NullableIntegerStringParser extends StringParser +{ + + @SuppressWarnings("unused") + private static final NullableIntegerStringParser INSTANCE = new NullableIntegerStringParser(); + + /** + * Returns a {@link com.thevoxelbox.voxelsniper.jsap.NullableIntegerStringParser}. + * + * + * Convenient access to the only instance returned by this method is available through {@link com.martiansoftware.jsap.JSAP#INTEGER_PARSER}. + * + * @return a {@link com.thevoxelbox.voxelsniper.jsap.NullableIntegerStringParser}. + */ + public static NullableIntegerStringParser getParser() + { + return new NullableIntegerStringParser(); + } + + /** + * Creates a new IntegerStringParser. + * + * @deprecated Use {@link #getParser()} or, even better, {@link com.martiansoftware.jsap.JSAP#INTEGER_PARSER}. + */ + public NullableIntegerStringParser() + { + super(); + } + + /** + * Parses the specified argument into an Integer. This method delegates the parsing to Integer.decode(arg). If Integer.decode() + * throws a NumberFormatException, it is encapsulated into a ParseException and re-thrown. + * + * @param arg + * the argument to parse + * + * @return an Integer object with the value contained in the specified argument. + * + * @throws com.martiansoftware.jsap.ParseException + * if Integer.decode(arg) throws a NumberFormatException. + * @see Integer + * @see com.martiansoftware.jsap.StringParser#parse(String) + */ + @Override + public final Object parse(final String arg) throws ParseException + { + if (arg == null) + { + return null; + } + + Integer result; + try + { + result = Integer.decode(arg); + } + catch (NumberFormatException nfe) + { + throw (new ParseException("Unable to convert '" + arg + "' to an Integer.", nfe)); + } + return (result); + } +} diff --git a/favs/src/main/java/com/thevoxelbox/voxelsniper/util/BlockWrapper.java b/favs/src/main/java/com/thevoxelbox/voxelsniper/util/BlockWrapper.java new file mode 100644 index 000000000..997ccc1e3 --- /dev/null +++ b/favs/src/main/java/com/thevoxelbox/voxelsniper/util/BlockWrapper.java @@ -0,0 +1,134 @@ +package com.thevoxelbox.voxelsniper.util; + +import com.boydti.fawe.bukkit.wrapper.AsyncBlock; +import org.bukkit.World; + +/** + * @author MikeMatrix + */ +public class BlockWrapper +{ + + private int id; + private int x; + private int y; + private int z; + private int data; + private World world; + + /** + * @param block + */ + @SuppressWarnings("deprecation") + public BlockWrapper(final AsyncBlock block) + { + this.setId(block.getTypeId()); + this.setX(block.getX()); + this.setY(block.getY()); + this.setZ(block.getZ()); + this.setPropertyId(block.getPropertyId()); + this.setWorld(block.getWorld()); + } + + /** + * @return the data + */ + public final int getPropertyId() + { + return this.data; + } + + /** + * @return the id + */ + public final int getId() + { + return this.id; + } + + /** + * @return the world + */ + public final World getWorld() + { + return this.world; + } + + /** + * @return the x + */ + public final int getX() + { + return this.x; + } + + /** + * @return the y + */ + public final int getY() + { + return this.y; + } + + /** + * @return the z + */ + public final int getZ() + { + return this.z; + } + + /** + * @param data + * the data to set + */ + public final void setPropertyId(final int data) + { + this.data = data; + } + + /** + * @param id + * the id to set + */ + public final void setId(final int id) + { + this.id = id; + } + + /** + * @param world + * the world to set + */ + public final void setWorld(final World world) + { + this.world = world; + } + + /** + * @param x + * the x to set + */ + public final void setX(final int x) + { + this.x = x; + } + + /** + * @param y + * the y to set + */ + public final void setY(final int y) + { + this.y = y; + } + + /** + * @param z + * the z to set + */ + public final void setZ(final int z) + { + this.z = z; + } +} diff --git a/favs/src/main/java/com/thevoxelbox/voxelsniper/util/UndoDelegate.java b/favs/src/main/java/com/thevoxelbox/voxelsniper/util/UndoDelegate.java new file mode 100644 index 000000000..685dca303 --- /dev/null +++ b/favs/src/main/java/com/thevoxelbox/voxelsniper/util/UndoDelegate.java @@ -0,0 +1,61 @@ + +package com.thevoxelbox.voxelsniper.util; + +import com.thevoxelbox.voxelsniper.Undo; +import org.bukkit.BlockChangeDelegate; +import org.bukkit.World; +import org.bukkit.block.Block; +import org.bukkit.block.data.BlockData; + +/** + * + */ +public class UndoDelegate implements BlockChangeDelegate +{ + private final World targetWorld; + private Undo currentUndo; + + public Undo getUndo() + { + final Undo pastUndo = currentUndo; + currentUndo = new Undo(); + return pastUndo; + } + + public UndoDelegate(World targetWorld) + { + this.targetWorld = targetWorld; + this.currentUndo = new Undo(); + } + @SuppressWarnings("deprecation") + public boolean setBlock(Block b) + { + this.currentUndo.put(this.targetWorld.getBlockAt(b.getLocation())); + this.targetWorld.getBlockAt(b.getLocation()).setBlockData(b.getBlockData()); + return true; + } + + @Override + public boolean setBlockData(int x, int y, int z, BlockData blockData) { + this.currentUndo.put(this.targetWorld.getBlockAt(x, y, z)); + this.targetWorld.getBlockAt(x, y, z).setBlockData(blockData); + return true; + } + + @Override + public BlockData getBlockData(int x, int y, int z) { + return this.targetWorld.getBlockAt(x, y, z).getBlockData(); + } + + @Override + public int getHeight() + { + return this.targetWorld.getMaxHeight(); + } + + @Override + public boolean isEmpty(int x, int y, int z) + { + return this.targetWorld.getBlockAt(x, y, z).isEmpty(); + } +} diff --git a/favs/src/main/java/com/thevoxelbox/voxelsniper/util/VoxelList.java b/favs/src/main/java/com/thevoxelbox/voxelsniper/util/VoxelList.java new file mode 100644 index 000000000..1e34d5812 --- /dev/null +++ b/favs/src/main/java/com/thevoxelbox/voxelsniper/util/VoxelList.java @@ -0,0 +1,95 @@ +package com.thevoxelbox.voxelsniper.util; + +import com.google.common.collect.ImmutableList; +import com.sk89q.worldedit.bukkit.BukkitAdapter; +import com.sk89q.worldedit.extent.NullExtent; +import com.sk89q.worldedit.function.mask.BlockMask; +import com.sk89q.worldedit.function.mask.BlockMaskBuilder; +import com.sk89q.worldedit.world.block.BlockState; +import org.bukkit.Material; +import org.bukkit.block.data.BlockData; + +import java.util.ArrayList; +import java.util.Iterator; +import java.util.List; + +/** + * Container class for multiple ID/Datavalue pairs. + */ +public class VoxelList +{ + + private BlockMask mask = new BlockMask(NullExtent.INSTANCE); + + /** + * Adds the specified id, data value pair to the VoxelList. A data value of -1 will operate on all data values of that id. + * + * @param i + */ + public void add(BlockState i) + { + this.mask = mask.toBuilder().add(i).build(NullExtent.INSTANCE); + } + + public void add(BlockMask mask) + { + + this.mask = (BlockMask) mask.and(mask); + } + + /** + * Removes the specified id, data value pair from the VoxelList. + * + * @return true if this list contained the specified element + */ + public boolean removeValue(final BlockState state) + { + this.mask = mask.toBuilder().remove(state).build(NullExtent.INSTANCE); + return true; + } + + public boolean removeValue(final BlockMask state) + { + this.mask = (BlockMask) mask.and(state.inverse()); + return true; + } + + /** + * @param i + * @return true if this list contains the specified element + */ + public boolean contains(final BlockData i) + { + return mask.test(BukkitAdapter.adapt(i)); + } + + /** + * Clears the VoxelList. + */ + public void clear() + { + mask = mask.toBuilder().clear().build(NullExtent.INSTANCE); + } + + /** + * Returns true if this list contains no elements. + * + * @return true if this list contains no elements + */ + public boolean isEmpty() + { + return mask.toBuilder().isEmpty(); + } + + /** + * Returns a defensive copy of the List with pairs. + * + * @return defensive copy of the List with pairs + */ + public String toString() + { + return mask.toString(); + } + + +} diff --git a/favs/src/main/resources/LICENSE b/favs/src/main/resources/LICENSE new file mode 100644 index 000000000..612e425d2 --- /dev/null +++ b/favs/src/main/resources/LICENSE @@ -0,0 +1,53 @@ +License + +THE WORK (AS DEFINED BELOW) IS PROVIDED UNDER THE TERMS OF THIS CREATIVE COMMONS PUBLIC LICENSE ("CCPL" OR "LICENSE"). THE WORK IS PROTECTED BY COPYRIGHT AND/OR OTHER APPLICABLE LAW. ANY USE OF THE WORK OTHER THAN AS AUTHORIZED UNDER THIS LICENSE OR COPYRIGHT LAW IS PROHIBITED. + +BY EXERCISING ANY RIGHTS TO THE WORK PROVIDED HERE, YOU ACCEPT AND AGREE TO BE BOUND BY THE TERMS OF THIS LICENSE. TO THE EXTENT THIS LICENSE MAY BE CONSIDERED TO BE A CONTRACT, THE LICENSOR GRANTS YOU THE RIGHTS CONTAINED HERE IN CONSIDERATION OF YOUR ACCEPTANCE OF SUCH TERMS AND CONDITIONS. + +1. Definitions + +"Adaptation" means a work based upon the Work, or upon the Work and other pre-existing works, such as a translation, adaptation, derivative work, arrangement of music or other alterations of a literary or artistic work, or phonogram or performance and includes cinematographic adaptations or any other form in which the Work may be recast, transformed, or adapted including in any form recognizably derived from the original, except that a work that constitutes a Collection will not be considered an Adaptation for the purpose of this License. For the avoidance of doubt, where the Work is a musical work, performance or phonogram, the synchronization of the Work in timed-relation with a moving image ("synching") will be considered an Adaptation for the purpose of this License. +"Collection" means a collection of literary or artistic works, such as encyclopedias and anthologies, or performances, phonograms or broadcasts, or other works or subject matter other than works listed in Section 1(f) below, which, by reason of the selection and arrangement of their contents, constitute intellectual creations, in which the Work is included in its entirety in unmodified form along with one or more other contributions, each constituting separate and independent works in themselves, which together are assembled into a collective whole. A work that constitutes a Collection will not be considered an Adaptation (as defined above) for the purposes of this License. +"Distribute" means to make available to the public the original and copies of the Work through sale or other transfer of ownership. +"Licensor" means the individual, individuals, entity or entities that offer(s) the Work under the terms of this License. +"Original Author" means, in the case of a literary or artistic work, the individual, individuals, entity or entities who created the Work or if no individual or entity can be identified, the publisher; and in addition (i) in the case of a performance the actors, singers, musicians, dancers, and other persons who act, sing, deliver, declaim, play in, interpret or otherwise perform literary or artistic works or expressions of folklore; (ii) in the case of a phonogram the producer being the person or legal entity who first fixes the sounds of a performance or other sounds; and, (iii) in the case of broadcasts, the organization that transmits the broadcast. +"Work" means the literary and/or artistic work offered under the terms of this License including without limitation any production in the literary, scientific and artistic domain, whatever may be the mode or form of its expression including digital form, such as a book, pamphlet and other writing; a lecture, address, sermon or other work of the same nature; a dramatic or dramatico-musical work; a choreographic work or entertainment in dumb show; a musical composition with or without words; a cinematographic work to which are assimilated works expressed by a process analogous to cinematography; a work of drawing, painting, architecture, sculpture, engraving or lithography; a photographic work to which are assimilated works expressed by a process analogous to photography; a work of applied art; an illustration, map, plan, sketch or three-dimensional work relative to geography, topography, architecture or science; a performance; a broadcast; a phonogram; a compilation of data to the extent it is protected as a copyrightable work; or a work performed by a variety or circus performer to the extent it is not otherwise considered a literary or artistic work. +"You" means an individual or entity exercising rights under this License who has not previously violated the terms of this License with respect to the Work, or who has received express permission from the Licensor to exercise rights under this License despite a previous violation. +"Publicly Perform" means to perform public recitations of the Work and to communicate to the public those public recitations, by any means or process, including by wire or wireless means or public digital performances; to make available to the public Works in such a way that members of the public may access these Works from a place and at a place individually chosen by them; to perform the Work to the public by any means or process and the communication to the public of the performances of the Work, including by public digital performance; to broadcast and rebroadcast the Work by any means including signs, sounds or images. +"Reproduce" means to make copies of the Work by any means including without limitation by sound or visual recordings and the right of fixation and reproducing fixations of the Work, including storage of a protected performance or phonogram in digital form or other electronic medium. +2. Fair Dealing Rights. Nothing in this License is intended to reduce, limit, or restrict any uses free from copyright or rights arising from limitations or exceptions that are provided for in connection with the copyright protection under copyright law or other applicable laws. + +3. License Grant. Subject to the terms and conditions of this License, Licensor hereby grants You a worldwide, royalty-free, non-exclusive, perpetual (for the duration of the applicable copyright) license to exercise the rights in the Work as stated below: + +to Reproduce the Work, to incorporate the Work into one or more Collections, and to Reproduce the Work as incorporated in the Collections; and, +to Distribute and Publicly Perform the Work including as incorporated in Collections. +The above rights may be exercised in all media and formats whether now known or hereafter devised. The above rights include the right to make such modifications as are technically necessary to exercise the rights in other media and formats, but otherwise you have no rights to make Adaptations. Subject to 8(f), all rights not expressly granted by Licensor are hereby reserved, including but not limited to the rights set forth in Section 4(d). + +4. Restrictions. The license granted in Section 3 above is expressly made subject to and limited by the following restrictions: + +You may Distribute or Publicly Perform the Work only under the terms of this License. You must include a copy of, or the Uniform Resource Identifier (URI) for, this License with every copy of the Work You Distribute or Publicly Perform. You may not offer or impose any terms on the Work that restrict the terms of this License or the ability of the recipient of the Work to exercise the rights granted to that recipient under the terms of the License. You may not sublicense the Work. You must keep intact all notices that refer to this License and to the disclaimer of warranties with every copy of the Work You Distribute or Publicly Perform. When You Distribute or Publicly Perform the Work, You may not impose any effective technological measures on the Work that restrict the ability of a recipient of the Work from You to exercise the rights granted to that recipient under the terms of the License. This Section 4(a) applies to the Work as incorporated in a Collection, but this does not require the Collection apart from the Work itself to be made subject to the terms of this License. If You create a Collection, upon notice from any Licensor You must, to the extent practicable, remove from the Collection any credit as required by Section 4(c), as requested. +You may not exercise any of the rights granted to You in Section 3 above in any manner that is primarily intended for or directed toward commercial advantage or private monetary compensation. The exchange of the Work for other copyrighted works by means of digital file-sharing or otherwise shall not be considered to be intended for or directed toward commercial advantage or private monetary compensation, provided there is no payment of any monetary compensation in connection with the exchange of copyrighted works. +If You Distribute, or Publicly Perform the Work or Collections, You must, unless a request has been made pursuant to Section 4(a), keep intact all copyright notices for the Work and provide, reasonable to the medium or means You are utilizing: (i) the name of the Original Author (or pseudonym, if applicable) if supplied, and/or if the Original Author and/or Licensor designate another party or parties (e.g., a sponsor institute, publishing entity, journal) for attribution ("Attribution Parties") in Licensor's copyright notice, terms of service or by other reasonable means, the name of such party or parties; (ii) the title of the Work if supplied; (iii) to the extent reasonably practicable, the URI, if any, that Licensor specifies to be associated with the Work, unless such URI does not refer to the copyright notice or licensing information for the Work. The credit required by this Section 4(c) may be implemented in any reasonable manner; provided, however, that in the case of a Collection, at a minimum such credit will appear, if a credit for all contributing authors of Collection appears, then as part of these credits and in a manner at least as prominent as the credits for the other contributing authors. For the avoidance of doubt, You may only use the credit required by this Section for the purpose of attribution in the manner set out above and, by exercising Your rights under this License, You may not implicitly or explicitly assert or imply any connection with, sponsorship or endorsement by the Original Author, Licensor and/or Attribution Parties, as appropriate, of You or Your use of the Work, without the separate, express prior written permission of the Original Author, Licensor and/or Attribution Parties. +For the avoidance of doubt: + +Non-waivable Compulsory License Schemes. In those jurisdictions in which the right to collect royalties through any statutory or compulsory licensing scheme cannot be waived, the Licensor reserves the exclusive right to collect such royalties for any exercise by You of the rights granted under this License; +Waivable Compulsory License Schemes. In those jurisdictions in which the right to collect royalties through any statutory or compulsory licensing scheme can be waived, the Licensor reserves the exclusive right to collect such royalties for any exercise by You of the rights granted under this License if Your exercise of such rights is for a purpose or use which is otherwise than noncommercial as permitted under Section 4(b) and otherwise waives the right to collect royalties through any statutory or compulsory licensing scheme; and, +Voluntary License Schemes. The Licensor reserves the right to collect royalties, whether individually or, in the event that the Licensor is a member of a collecting society that administers voluntary licensing schemes, via that society, from any exercise by You of the rights granted under this License that is for a purpose or use which is otherwise than noncommercial as permitted under Section 4(b). +Except as otherwise agreed in writing by the Licensor or as may be otherwise permitted by applicable law, if You Reproduce, Distribute or Publicly Perform the Work either by itself or as part of any Collections, You must not distort, mutilate, modify or take other derogatory action in relation to the Work which would be prejudicial to the Original Author's honor or reputation. +5. Representations, Warranties and Disclaimer + +UNLESS OTHERWISE MUTUALLY AGREED BY THE PARTIES IN WRITING, LICENSOR OFFERS THE WORK AS-IS AND MAKES NO REPRESENTATIONS OR WARRANTIES OF ANY KIND CONCERNING THE WORK, EXPRESS, IMPLIED, STATUTORY OR OTHERWISE, INCLUDING, WITHOUT LIMITATION, WARRANTIES OF TITLE, MERCHANTIBILITY, FITNESS FOR A PARTICULAR PURPOSE, NONINFRINGEMENT, OR THE ABSENCE OF LATENT OR OTHER DEFECTS, ACCURACY, OR THE PRESENCE OF ABSENCE OF ERRORS, WHETHER OR NOT DISCOVERABLE. SOME JURISDICTIONS DO NOT ALLOW THE EXCLUSION OF IMPLIED WARRANTIES, SO SUCH EXCLUSION MAY NOT APPLY TO YOU. + +6. Limitation on Liability. EXCEPT TO THE EXTENT REQUIRED BY APPLICABLE LAW, IN NO EVENT WILL LICENSOR BE LIABLE TO YOU ON ANY LEGAL THEORY FOR ANY SPECIAL, INCIDENTAL, CONSEQUENTIAL, PUNITIVE OR EXEMPLARY DAMAGES ARISING OUT OF THIS LICENSE OR THE USE OF THE WORK, EVEN IF LICENSOR HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGES. + +7. Termination + +This License and the rights granted hereunder will terminate automatically upon any breach by You of the terms of this License. Individuals or entities who have received Collections from You under this License, however, will not have their licenses terminated provided such individuals or entities remain in full compliance with those licenses. Sections 1, 2, 5, 6, 7, and 8 will survive any termination of this License. +Subject to the above terms and conditions, the license granted here is perpetual (for the duration of the applicable copyright in the Work). Notwithstanding the above, Licensor reserves the right to release the Work under different license terms or to stop distributing the Work at any time; provided, however that any such election will not serve to withdraw this License (or any other license that has been, or is required to be, granted under the terms of this License), and this License will continue in full force and effect unless terminated as stated above. +8. Miscellaneous + +Each time You Distribute or Publicly Perform the Work or a Collection, the Licensor offers to the recipient a license to the Work on the same terms and conditions as the license granted to You under this License. +If any provision of this License is invalid or unenforceable under applicable law, it shall not affect the validity or enforceability of the remainder of the terms of this License, and without further action by the parties to this agreement, such provision shall be reformed to the minimum extent necessary to make such provision valid and enforceable. +No term or provision of this License shall be deemed waived and no breach consented to unless such waiver or consent shall be in writing and signed by the party to be charged with such waiver or consent. +This License constitutes the entire agreement between the parties with respect to the Work licensed here. There are no understandings, agreements or representations with respect to the Work not specified here. Licensor shall not be bound by any additional provisions that may appear in any communication from You. This License may not be modified without the mutual written agreement of the Licensor and You. +The rights granted under, and the subject matter referenced, in this License were drafted utilizing the terminology of the Berne Convention for the Protection of Literary and Artistic Works (as amended on September 28, 1979), the Rome Convention of 1961, the WIPO Copyright Treaty of 1996, the WIPO Performances and Phonograms Treaty of 1996 and the Universal Copyright Convention (as revised on July 24, 1971). These rights and subject matter take effect in the relevant jurisdiction in which the License terms are sought to be enforced according to the corresponding provisions of the implementation of those treaty provisions in the applicable national law. If the standard suite of rights granted under applicable copyright law includes additional rights not granted under this License, such additional rights are deemed to be included in the License; this License is not intended to restrict the license of any rights under applicable law. diff --git a/favs/src/main/resources/config.yml b/favs/src/main/resources/config.yml new file mode 100644 index 000000000..0f9d5b5a4 --- /dev/null +++ b/favs/src/main/resources/config.yml @@ -0,0 +1,3 @@ +litesniper-max-brush-size: 5 +undo-cache-size: 20 +message-on-login-enabled: true \ No newline at end of file diff --git a/favs/src/main/resources/plugin.yml b/favs/src/main/resources/plugin.yml new file mode 100644 index 000000000..fa6b1e7b1 --- /dev/null +++ b/favs/src/main/resources/plugin.yml @@ -0,0 +1,437 @@ +name: FastAsyncVoxelSniper +main: com.thevoxelbox.voxelsniper.VoxelSniper +version: ${version} +description: Fast Async VoxelSniper +authors: [Empire92] +load: STARTUP +database: false +depend: [WorldEdit] +api-version: 1.13 +#softdepend: [WorldGuard, PlotSquared, MCore, Factions, GriefPrevention, Residence, Towny, PlotMe, PreciousStones] +commands: + '/p': + description: VoxelSniper perform command + aliases: [perform,/perform] + '/d': + description: VoxelSniper default command + aliases: [default,/default] + paint: + description: Change the selected painting to another painting. + usage: | + / + Example: / -- Cycles through paintings. You must be adjacent to the painting and aiming at it. + goto: + description: Warps to the specified coordinates. + permission: voxelsniper.goto + usage: | + / [X] [Z] + Example: / 100 -100 -- Takes the user to the coordinates X: 100, Z: -100. The Y-coordinate will always be 1 more than the Y-coordinate of the highest block at the X and Z-coordinates provided. + u: + description: Undoes the last snipe. + permission: voxelsniper.sniper + usage: | + / + Example: / -- Undoes your most recent snipe. + uu: + description: UndoUser undoes another sniper user's snipes. + permission: voxelsniper.sniper + usage: | + / [playername] + Example: / bads -- Undoes BadSniper's last snipe. BadSniper must be online for name detection to function. Truncation allowed. + d: + description: VoxelSniper Default. + permission: voxelsniper.sniper + usage: | + / + Example: / -- Resets the brush settings to their default values. + p: + description: Voxelsniper performer. + permission: voxelsniper.sniper + aliases: [perf, performer] + usage: | + / + Example: / -- Sets the performer of the current brush to "m". + / + Example: / -- Sets the performer of the current brush to . + vs: + description: VoxelSniper Settings. + permission: voxelsniper.sniper + usage: | + / + Example: / -- Returns the current brush settings. + vc: + description: VoxelCentroid. + permission: voxelsniper.sniper + usage: | + / + Example: / -1 -- Sets the Clone Cylinder's Y value for the base relative to the Clone Point. + vh: + description: VoxelHeight. + permission: voxelsniper.sniper + usage: | + / [voxel-height] + Example: / -- Sets the brush height. + vi: + description: VoxelInk (Data Value). + permission: voxelsniper.sniper + usage: | + / [0-16] + Example: / -- sets a data value of 6 (e.g. pink wool). + vr: + description: VoxelReplace. + permission: voxelsniper.sniper + usage: | + / [0-159] + Example: / 12 -- Sets a replace brush to select sand blocks for replacement. + vl: + description: VoxelBlockExclusion list + permission: voxelsniper.sniper + usage: | + / + Example: / 89 -5 -- Adds glowstone to the voxel list and removes planks from the voxel list. + vir: + description: VoxelInkReplace. + permission: voxelsniper.sniper + usage: | + / [0-16] + Example: / 12 -- Sets a replace ink brush to select data 6 blocks for replacement. + v: + description: Voxel input. + permission: voxelsniper.sniper + usage: | + / [0-159] + Example: / 1 -- Loads the sniper with Stone blocks. + b: + description: Brush. + permission: voxelsniper.sniper + usage: | + / [brush-size] + Example: / 5 -- Sets a brush radius size of 5 (11 spaces across). + Example: / b cm -- Sets your brush to the Ball Brush with the combo-mat performer. + btool: + description: Brush Tool Command. + permission: voxelsniper.sniper + usage : | + / -- Prints out command usage information. + vchunk: + description: Update the chunk you are standing in. + usage: | + / + Example: / -- Loads the chunk you're standing in. +permissions: + fawe.voxelbrush: + default: op + children: + voxelsniper.brush.ball: true + voxelsniper.brush.biome: true + voxelsniper.brush.blendball: true + voxelsniper.brush.blenddisc: true + voxelsniper.brush.blendvoxel: true + voxelsniper.brush.blendvoxeldisc: true + voxelsniper.brush.blob: true + voxelsniper.brush.blockreset: true + voxelsniper.brush.blockresetsurface: true + voxelsniper.brush.canyon: true + voxelsniper.brush.canyonselection: true + voxelsniper.brush.checkervoxeldisc: true + voxelsniper.brush.cleansnow: true + voxelsniper.brush.clonestamp: true + voxelsniper.brush.copypasta: true + voxelsniper.brush.cylinder: true + voxelsniper.brush.disc: true + voxelsniper.brush.discface: true + voxelsniper.brush.dome: true + voxelsniper.brush.drain: true + voxelsniper.brush.ellipse: true + voxelsniper.brush.ellipsoid: true + voxelsniper.brush.eraser: true + voxelsniper.brush.erode: true + voxelsniper.brush.extrude: true + voxelsniper.brush.filldown: true + voxelsniper.brush.flatocean: true + voxelsniper.brush.heatray: true + voxelsniper.brush.jaggedline: true + voxelsniper.brush.line: true + voxelsniper.brush.move: true + voxelsniper.brush.ocean: true + voxelsniper.brush.overlay: true + voxelsniper.brush.pull: true + voxelsniper.brush.randomerode: true + voxelsniper.brush.ring: true + voxelsniper.brush.rot2d: true + voxelsniper.brush.rot2dvert: true + voxelsniper.brush.rot3d: true + voxelsniper.brush.ruler: true + voxelsniper.brush.scanner: true + voxelsniper.brush.set: true + voxelsniper.brush.setredstoneflip: true + voxelsniper.brush.setredstonerotate: true + voxelsniper.brush.shellball: true + voxelsniper.brush.shellset: true + voxelsniper.brush.shellvoxel: true + voxelsniper.brush.signoverwrite: true + voxelsniper.brush.snipe: true + voxelsniper.brush.snowcone: true + voxelsniper.brush.spiralstaircase: true + voxelsniper.brush.splatterball: true + voxelsniper.brush.splatterdisc: true + voxelsniper.brush.splatteroverlay: true + voxelsniper.brush.splattervoxel: true + voxelsniper.brush.splattervoxeldisc: true + voxelsniper.brush.spline: true + voxelsniper.brush.stamp: true + voxelsniper.brush.stencil: true + voxelsniper.brush.stencillist: true + voxelsniper.brush.threepointcircle: true + voxelsniper.brush.triangle: true + voxelsniper.brush.underlay: true + voxelsniper.brush.voltmeter: true + voxelsniper.brush.voxel: true + voxelsniper.brush.voxeldisc: true + voxelsniper.brush.voxeldiscface: true + voxelsniper.brush.warp: true + voxelsniper.goto: true + voxelsniper.sniper: true + voxelsniper.sniper: + default: op + voxelsniper.ignorelimitations: + default: op + voxelsniper.goto: + default: op + voxelsniper.brush.*: + default: op + children: + voxelsniper.brush.ball: true + voxelsniper.brush.biome: true + voxelsniper.brush.blendball: true + voxelsniper.brush.blenddisc: true + voxelsniper.brush.blendvoxel: true + voxelsniper.brush.blendvoxeldisc: true + voxelsniper.brush.blob: true + voxelsniper.brush.blockreset: true + voxelsniper.brush.blockresetsurface: true + voxelsniper.brush.canyon: true + voxelsniper.brush.canyonselection: true + voxelsniper.brush.checkervoxeldisc: true + voxelsniper.brush.cleansnow: true + voxelsniper.brush.clonestamp: true + voxelsniper.brush.comet: true + voxelsniper.brush.copypasta: true + voxelsniper.brush.cylinder: true + voxelsniper.brush.disc: true + voxelsniper.brush.discface: true + voxelsniper.brush.dome: true + voxelsniper.brush.drain: true + voxelsniper.brush.ellipse: true + voxelsniper.brush.ellipsoid: true + voxelsniper.brush.entity: true + voxelsniper.brush.entityremoval: true + voxelsniper.brush.eraser: true + voxelsniper.brush.erode: true + voxelsniper.brush.extrude: true + voxelsniper.brush.filldown: true + voxelsniper.brush.flatocean: true + voxelsniper.brush.generatetree: true + voxelsniper.brush.heatray: true + voxelsniper.brush.jaggedline: true + voxelsniper.brush.jockey: true + voxelsniper.brush.lightning: true + voxelsniper.brush.line: true + voxelsniper.brush.move: true + voxelsniper.brush.ocean: true + voxelsniper.brush.overlay: true + voxelsniper.brush.painting: true + voxelsniper.brush.pull: true + voxelsniper.brush.punish: true + voxelsniper.brush.randomerode: true + voxelsniper.brush.regeneratechunk: true + voxelsniper.brush.ring: true + voxelsniper.brush.rot2d: true + voxelsniper.brush.rot2dvert: true + voxelsniper.brush.rot3d: true + voxelsniper.brush.ruler: true + voxelsniper.brush.scanner: true + voxelsniper.brush.set: true + voxelsniper.brush.setredstoneflip: true + voxelsniper.brush.setredstonerotate: true + voxelsniper.brush.shellball: true + voxelsniper.brush.shellset: true + voxelsniper.brush.shellvoxel: true + voxelsniper.brush.signoverwrite: true + voxelsniper.brush.snipe: true + voxelsniper.brush.snowcone: true + voxelsniper.brush.spiralstaircase: true + voxelsniper.brush.splatterball: true + voxelsniper.brush.splatterdisc: true + voxelsniper.brush.splatteroverlay: true + voxelsniper.brush.splattervoxel: true + voxelsniper.brush.splattervoxeldisc: true + voxelsniper.brush.spline: true + voxelsniper.brush.stamp: true + voxelsniper.brush.stencil: true + voxelsniper.brush.stencillist: true + voxelsniper.brush.threepointcircle: true + voxelsniper.brush.treesnipe: true + voxelsniper.brush.triangle: true + voxelsniper.brush.underlay: true + voxelsniper.brush.voltmeter: true + voxelsniper.brush.voxel: true + voxelsniper.brush.voxeldisc: true + voxelsniper.brush.voxeldiscface: true + voxelsniper.brush.warp: true + voxelsniper.brush.ball: + default: op + voxelsniper.brush.biome: + default: op + voxelsniper.brush.blendball: + default: op + voxelsniper.brush.blenddisc: + default: op + voxelsniper.brush.blendvoxel: + default: op + voxelsniper.brush.blendvoxeldisc: + default: op + voxelsniper.brush.blob: + default: op + voxelsniper.brush.blockreset: + default: op + voxelsniper.brush.blockresetsurface: + default: op + voxelsniper.brush.canyon: + default: op + voxelsniper.brush.canyonselection: + default: op + voxelsniper.brush.checkervoxeldisc: + default: op + voxelsniper.brush.cleansnow: + default: op + voxelsniper.brush.clonestamp: + default: op + voxelsniper.brush.comet: + default: op + voxelsniper.brush.copypasta: + default: op + voxelsniper.brush.cylinder: + default: op + voxelsniper.brush.disc: + default: op + voxelsniper.brush.discface: + default: op + voxelsniper.brush.dome: + default: op + voxelsniper.brush.drain: + default: op + voxelsniper.brush.ellipse: + default: op + voxelsniper.brush.ellipsoid: + default: op + voxelsniper.brush.entity: + default: op + voxelsniper.brush.entityremoval: + default: op + voxelsniper.brush.eraser: + default: op + voxelsniper.brush.erode: + default: op + voxelsniper.brush.extrude: + default: op + voxelsniper.brush.filldown: + default: op + voxelsniper.brush.flatocean: + default: op + voxelsniper.brush.generatetree: + default: op + voxelsniper.brush.heatray: + default: op + voxelsniper.brush.jaggedline: + default: op + voxelsniper.brush.jockey: + default: op + voxelsniper.brush.lightning: + default: op + voxelsniper.brush.line: + default: op + voxelsniper.brush.move: + default: op + voxelsniper.brush.ocean: + default: op + voxelsniper.brush.overlay: + default: op + voxelsniper.brush.painting: + default: op + voxelsniper.brush.pull: + default: op + voxelsniper.brush.punish: + default: op + voxelsniper.brush.randomerode: + default: op + voxelsniper.brush.regeneratechunk: + default: op + voxelsniper.brush.ring: + default: op + voxelsniper.brush.rot2d: + default: op + voxelsniper.brush.rot2dvert: + default: op + voxelsniper.brush.rot3d: + default: op + voxelsniper.brush.ruler: + default: op + voxelsniper.brush.scanner: + default: op + voxelsniper.brush.set: + default: op + voxelsniper.brush.setredstoneflip: + default: op + voxelsniper.brush.setredstonerotate: + default: op + voxelsniper.brush.shellball: + default: op + voxelsniper.brush.shellset: + default: op + voxelsniper.brush.shellvoxel: + default: op + voxelsniper.brush.signoverwrite: + default: op + voxelsniper.brush.snipe: + default: op + voxelsniper.brush.snowcone: + default: op + voxelsniper.brush.spiralstaircase: + default: op + voxelsniper.brush.splatterball: + default: op + voxelsniper.brush.splatterdisc: + default: op + voxelsniper.brush.splatteroverlay: + default: op + voxelsniper.brush.splattervoxel: + default: op + voxelsniper.brush.splattervoxeldisc: + default: op + voxelsniper.brush.spline: + default: op + voxelsniper.brush.stamp: + default: op + voxelsniper.brush.stencil: + default: op + voxelsniper.brush.stencillist: + default: op + voxelsniper.brush.threepointcircle: + default: op + voxelsniper.brush.treesnipe: + default: op + voxelsniper.brush.triangle: + default: op + voxelsniper.brush.underlay: + default: op + voxelsniper.brush.voltmeter: + default: op + voxelsniper.brush.voxel: + default: op + voxelsniper.brush.voxeldisc: + default: op + voxelsniper.brush.voxeldiscface: + default: op + voxelsniper.brush.warp: + default: op \ No newline at end of file diff --git a/settings.gradle b/settings.gradle index f28bdc6e1..4c96db613 100644 --- a/settings.gradle +++ b/settings.gradle @@ -1,3 +1,3 @@ rootProject.name = 'FastAsyncWorldEdit' -include 'worldedit-core', 'worldedit-bukkit' \ No newline at end of file +include 'worldedit-core', 'worldedit-bukkit', 'favs' \ No newline at end of file diff --git a/worldedit-bukkit/src/main/java/com/boydti/fawe/bukkit/v0/BukkitQueue_All.java b/worldedit-bukkit/src/main/java/com/boydti/fawe/bukkit/v0/BukkitQueue_All.java index df02eb8d2..d21e64bcd 100644 --- a/worldedit-bukkit/src/main/java/com/boydti/fawe/bukkit/v0/BukkitQueue_All.java +++ b/worldedit-bukkit/src/main/java/com/boydti/fawe/bukkit/v0/BukkitQueue_All.java @@ -26,6 +26,7 @@ import java.util.function.Supplier; import com.sk89q.worldedit.bukkit.BukkitAdapter; import com.sk89q.worldedit.world.block.BlockStateHolder; +import com.sk89q.worldedit.world.block.BlockTypes; import org.bukkit.Chunk; import org.bukkit.ChunkSnapshot; import org.bukkit.Location; @@ -237,7 +238,7 @@ public class BukkitQueue_All extends BukkitQueue_0> 4)) { - return 0; + return BlockTypes.AIR.getInternalId(); } BlockData blockData = chunk.getBlockData(x & 15, y, z & 15); return BukkitAdapter.adapt(blockData).getInternalId(); diff --git a/worldedit-bukkit/src/main/java/com/boydti/fawe/bukkit/wrapper/AsyncBlock.java b/worldedit-bukkit/src/main/java/com/boydti/fawe/bukkit/wrapper/AsyncBlock.java index 849b50609..8ea8e6255 100644 --- a/worldedit-bukkit/src/main/java/com/boydti/fawe/bukkit/wrapper/AsyncBlock.java +++ b/worldedit-bukkit/src/main/java/com/boydti/fawe/bukkit/wrapper/AsyncBlock.java @@ -48,18 +48,30 @@ public class AsyncBlock implements Block { return (byte) (queue.getCachedCombinedId4Data(x, y, z, BlockTypes.AIR.getInternalId()) & 0xF); } + public int getPropertyId() { + return (queue.getCachedCombinedId4Data(x, y, z, BlockTypes.AIR.getInternalId()) >> BlockTypes.BIT_OFFSET); + } + + public int getCombinedId() { + return queue.getCachedCombinedId4Data(x, y, z, BlockTypes.AIR.getInternalId()); + } + + public int getTypeId() { + return (queue.getCachedCombinedId4Data(x, y, z, BlockTypes.AIR.getInternalId()) & BlockTypes.BIT_MASK); + } + @Override - public Block getRelative(int modX, int modY, int modZ) { + public AsyncBlock getRelative(int modX, int modY, int modZ) { return new AsyncBlock(world, queue, x + modX, y + modY, z + modZ); } @Override - public Block getRelative(BlockFace face) { + public AsyncBlock getRelative(BlockFace face) { return this.getRelative(face.getModX(), face.getModY(), face.getModZ()); } @Override - public Block getRelative(BlockFace face, int distance) { + public AsyncBlock getRelative(BlockFace face, int distance) { return this.getRelative(face.getModX() * distance, face.getModY() * distance, face.getModZ() * distance); } @@ -73,6 +85,31 @@ public class AsyncBlock implements Block { return BukkitAdapter.getBlockData(queue.getCachedCombinedId4Data(x, y, z, BlockTypes.AIR.getInternalId())); } + @Deprecated + public boolean setTypeIdAndPropertyId(int id, int propertyId, boolean physics) { + return setTypeIdAndPropertyId(id, propertyId); + } + + @Deprecated + public boolean setCombinedId(int combinedId) { + return queue.setBlock(x, y, z, combinedId); + } + + @Deprecated + public boolean setTypeIdAndPropertyId(int id, int propertyId) { + return setCombinedId(id + (propertyId << BlockTypes.BIT_OFFSET)); + } + + @Deprecated + public boolean setTypeId(int typeId) { + return queue.setBlock(x, y, z, BlockTypes.get(typeId).getDefaultState()); + } + + @Deprecated + public boolean setPropertyId(int propertyId) { + return setTypeIdAndPropertyId(getTypeId(), propertyId); + } + @Override public byte getLightLevel() { return (byte) queue.getLight(x, y, z); @@ -89,7 +126,7 @@ public class AsyncBlock implements Block { } @Override - public World getWorld() { + public AsyncWorld getWorld() { return world; } @@ -125,7 +162,7 @@ public class AsyncBlock implements Block { } @Override - public Chunk getChunk() { + public AsyncChunk getChunk() { return world.getChunkAt(x >> 4, z >> 4); } @@ -170,7 +207,7 @@ public class AsyncBlock implements Block { } @Override - public BlockState getState() { + public AsyncBlockState getState() { int combined = queue.getCombinedId4Data(x, y, z, 0); BlockTypes type = BlockTypes.getFromStateId(combined); switch (type) { @@ -182,7 +219,7 @@ public class AsyncBlock implements Block { } @Override - public BlockState getState(boolean useSnapshot) { + public AsyncBlockState getState(boolean useSnapshot) { return getState(); } diff --git a/worldedit-bukkit/src/main/java/com/boydti/fawe/bukkit/wrapper/AsyncBlockState.java b/worldedit-bukkit/src/main/java/com/boydti/fawe/bukkit/wrapper/AsyncBlockState.java index e91548c1b..4d36f64bf 100644 --- a/worldedit-bukkit/src/main/java/com/boydti/fawe/bukkit/wrapper/AsyncBlockState.java +++ b/worldedit-bukkit/src/main/java/com/boydti/fawe/bukkit/wrapper/AsyncBlockState.java @@ -38,6 +38,14 @@ public class AsyncBlockState implements BlockState { } } + public int getTypeId() { + return combinedId & BlockTypes.BIT_MASK; + } + + public int getPropertyId() { + return combinedId >> BlockTypes.BIT_OFFSET; + } + @Override public Block getBlock() { return block; @@ -64,7 +72,7 @@ public class AsyncBlockState implements BlockState { } @Override - public World getWorld() { + public AsyncWorld getWorld() { return block.world; } @@ -152,7 +160,7 @@ public class AsyncBlockState implements BlockState { @Override public void setRawData(byte data) { - this.combinedId = (combinedId & BlockTypes.BIT_MASK) + data; + this.combinedId = (combinedId & BlockTypes.BIT_MASK) + (data << BlockTypes.BIT_OFFSET); this.blockData = BukkitAdapter.getBlockData(this.combinedId); } diff --git a/worldedit-bukkit/src/main/java/com/boydti/fawe/bukkit/wrapper/AsyncChunk.java b/worldedit-bukkit/src/main/java/com/boydti/fawe/bukkit/wrapper/AsyncChunk.java index e4e8037ba..3ee6c4123 100644 --- a/worldedit-bukkit/src/main/java/com/boydti/fawe/bukkit/wrapper/AsyncChunk.java +++ b/worldedit-bukkit/src/main/java/com/boydti/fawe/bukkit/wrapper/AsyncChunk.java @@ -52,12 +52,12 @@ public class AsyncChunk implements Chunk { } @Override - public World getWorld() { + public AsyncWorld getWorld() { return world; } @Override - public Block getBlock(int x, int y, int z) { + public AsyncBlock getBlock(int x, int y, int z) { return new AsyncBlock(world, queue, (this.x << 4) + x, y, (this.z << 4) + z); } diff --git a/worldedit-bukkit/src/main/java/com/boydti/fawe/bukkit/wrapper/AsyncWorld.java b/worldedit-bukkit/src/main/java/com/boydti/fawe/bukkit/wrapper/AsyncWorld.java index 1224be4f2..5671474b6 100644 --- a/worldedit-bukkit/src/main/java/com/boydti/fawe/bukkit/wrapper/AsyncWorld.java +++ b/worldedit-bukkit/src/main/java/com/boydti/fawe/bukkit/wrapper/AsyncWorld.java @@ -258,12 +258,12 @@ public class AsyncWorld extends DelegateFaweQueue implements World, HasFaweQueue } @Override - public Block getBlockAt(final int x, final int y, final int z) { + public AsyncBlock getBlockAt(final int x, final int y, final int z) { return new AsyncBlock(this, queue, x, y, z); } @Override - public Block getBlockAt(Location loc) { + public AsyncBlock getBlockAt(Location loc) { return getBlockAt(loc.getBlockX(), loc.getBlockY(), loc.getBlockZ()); } @@ -283,28 +283,28 @@ public class AsyncWorld extends DelegateFaweQueue implements World, HasFaweQueue } @Override - public Block getHighestBlockAt(int x, int z) { + public AsyncBlock getHighestBlockAt(int x, int z) { int y = getHighestBlockYAt(x, z); return getBlockAt(x, y, z); } @Override - public Block getHighestBlockAt(Location loc) { + public AsyncBlock getHighestBlockAt(Location loc) { return getHighestBlockAt(loc.getBlockX(), loc.getBlockZ()); } @Override - public Chunk getChunkAt(int x, int z) { + public AsyncChunk getChunkAt(int x, int z) { return new AsyncChunk(this, queue, x, z); } @Override - public Chunk getChunkAt(Location location) { + public AsyncChunk getChunkAt(Location location) { return getChunkAt(location.getBlockX(), location.getBlockZ()); } @Override - public Chunk getChunkAt(Block block) { + public AsyncChunk getChunkAt(Block block) { return getChunkAt(block.getX(), block.getZ()); } diff --git a/worldedit-bukkit/src/main/java/com/sk89q/worldedit/bukkit/CachedBukkitAdapter.java b/worldedit-bukkit/src/main/java/com/sk89q/worldedit/bukkit/CachedBukkitAdapter.java index 7257c0ca0..08e55644d 100644 --- a/worldedit-bukkit/src/main/java/com/sk89q/worldedit/bukkit/CachedBukkitAdapter.java +++ b/worldedit-bukkit/src/main/java/com/sk89q/worldedit/bukkit/CachedBukkitAdapter.java @@ -36,6 +36,7 @@ public class CachedBukkitAdapter { itemTypes[i] = ItemTypes.get(id); } } + blockDataCache[0] = new BlockData[] {Material.AIR.createBlockData()}; } /** diff --git a/worldedit-core/src/main/java/com/boydti/fawe/example/MappedFaweQueue.java b/worldedit-core/src/main/java/com/boydti/fawe/example/MappedFaweQueue.java index ce0d5a450..e96b80ae7 100644 --- a/worldedit-core/src/main/java/com/boydti/fawe/example/MappedFaweQueue.java +++ b/worldedit-core/src/main/java/com/boydti/fawe/example/MappedFaweQueue.java @@ -387,7 +387,7 @@ public abstract class MappedFaweQueue impl CHUNKSECTIONS sections = getSections(lastChunk); SECTION section = getCachedSection(sections, y >> 4); if (section == null) { - return 0; + return BlockTypes.AIR.getInternalId(); } return getCombinedId4Data(lastSection, x, y, z); } @@ -723,17 +723,17 @@ public abstract class MappedFaweQueue impl lastSection = getCachedSection(lastChunkSections, cy); } else { lastChunkSections = null; - return 0; + return BlockTypes.AIR.getInternalId(); } } else if (cy != lastSectionY) { if (lastChunkSections != null) { lastSection = getCachedSection(lastChunkSections, cy); } else { - return 0; + return BlockTypes.AIR.getInternalId(); } } if (lastSection == null) { - return 0; + return BlockTypes.AIR.getInternalId(); } return getCombinedId4Data(lastSection, x, y, z); } @@ -752,17 +752,17 @@ public abstract class MappedFaweQueue impl lastSection = getCachedSection(lastChunkSections, cy); } else { lastChunkSections = null; - return 0; + return BlockTypes.AIR.getInternalId(); } } else if (cy != lastSectionY) { if (lastChunkSections != null) { lastSection = getCachedSection(lastChunkSections, cy); } else { - return 0; + return BlockTypes.AIR.getInternalId(); } } if (lastSection == null) { - return 0; + return BlockTypes.AIR.getInternalId(); } return getCombinedId4Data(lastSection, x, y, z); } diff --git a/worldedit-core/src/main/java/com/boydti/fawe/example/NMSMappedFaweQueue.java b/worldedit-core/src/main/java/com/boydti/fawe/example/NMSMappedFaweQueue.java index 5f3aa8d2a..7c12c2878 100644 --- a/worldedit-core/src/main/java/com/boydti/fawe/example/NMSMappedFaweQueue.java +++ b/worldedit-core/src/main/java/com/boydti/fawe/example/NMSMappedFaweQueue.java @@ -141,10 +141,10 @@ public abstract class NMSMappedFaweQueue ex public int getId(final char[][] sections, final int x, final int y, final int z) { if ((x < 0) || (x > 15) || (z < 0) || (z > 15)) { - return 1; + return BlockTypes.AIR.getInternalId(); } if ((y < 0) || (y > maxY)) { - return 1; + return BlockTypes.AIR.getInternalId(); } final int i = FaweCache.CACHE_I[y][z][x]; final char[] section = sections[i]; diff --git a/worldedit-core/src/main/java/com/boydti/fawe/example/NullFaweChunk.java b/worldedit-core/src/main/java/com/boydti/fawe/example/NullFaweChunk.java index 80d38e4cf..22c639203 100644 --- a/worldedit-core/src/main/java/com/boydti/fawe/example/NullFaweChunk.java +++ b/worldedit-core/src/main/java/com/boydti/fawe/example/NullFaweChunk.java @@ -4,6 +4,8 @@ import com.boydti.fawe.object.FaweChunk; import com.boydti.fawe.object.FaweQueue; import com.sk89q.jnbt.CompoundTag; import com.sk89q.worldedit.world.biome.BaseBiome; +import com.sk89q.worldedit.world.block.BlockTypes; + import java.util.HashMap; import java.util.HashSet; import java.util.Map; @@ -46,7 +48,7 @@ public class NullFaweChunk extends FaweChunk { @Override public int getBlockCombinedId(int x, int y, int z) { - return 0; + return BlockTypes.AIR.getInternalId(); } @Override diff --git a/worldedit-core/src/main/java/com/boydti/fawe/object/FaweQueue.java b/worldedit-core/src/main/java/com/boydti/fawe/object/FaweQueue.java index da04123e4..736305020 100644 --- a/worldedit-core/src/main/java/com/boydti/fawe/object/FaweQueue.java +++ b/worldedit-core/src/main/java/com/boydti/fawe/object/FaweQueue.java @@ -455,7 +455,8 @@ public interface FaweQueue extends HasFaweQueue, Extent { session.debug(BBC.WORLDEDIT_FAILED_LOAD_CHUNK, x >> 4, z >> 4); return def; } catch (Throwable e) { - return 0; + e.printStackTrace(); + return BlockTypes.AIR.getInternalId(); } } diff --git a/worldedit-core/src/main/java/com/boydti/fawe/object/queue/FaweQueueDelegateExtent.java b/worldedit-core/src/main/java/com/boydti/fawe/object/queue/FaweQueueDelegateExtent.java new file mode 100644 index 000000000..b71e76e28 --- /dev/null +++ b/worldedit-core/src/main/java/com/boydti/fawe/object/queue/FaweQueueDelegateExtent.java @@ -0,0 +1,101 @@ +package com.boydti.fawe.object.queue; + +import com.boydti.fawe.FaweCache; +import com.boydti.fawe.object.FaweQueue; +import com.boydti.fawe.object.exception.FaweException; +import com.sk89q.jnbt.CompoundTag; +import com.sk89q.worldedit.MutableBlockVector2D; +import com.sk89q.worldedit.Vector; +import com.sk89q.worldedit.Vector2D; +import com.sk89q.worldedit.WorldEditException; +import com.sk89q.worldedit.blocks.BaseBlock; +import com.sk89q.worldedit.extent.Extent; +import com.sk89q.worldedit.world.biome.BaseBiome; +import com.sk89q.worldedit.world.block.BlockState; +import com.sk89q.worldedit.world.block.BlockStateHolder; + +import static com.google.common.base.Preconditions.checkNotNull; + +public class FaweQueueDelegateExtent extends DelegateFaweQueue { + private final FaweQueue parentQueue; + private final Extent parentExtent; + private final MutableBlockVector2D mutable2d = new MutableBlockVector2D(); + + public FaweQueueDelegateExtent(FaweQueue parentQueue, Extent parentExtent) { + super(parentQueue); + checkNotNull(parentExtent); + checkNotNull(parentQueue); + this.parentQueue = parentQueue; + this.parentExtent = parentExtent; + } + + @Override + public boolean setBlock(int x, int y, int z, int combinedId) { + return setBlock(x, y, z, BlockState.get(combinedId)); + } + + @Override + public boolean setBlock(int x, int y, int z, int combinedId, CompoundTag nbt) { + if (nbt != null) { + return setBlock(x, y, z, BaseBlock.getFromInternalId(combinedId, nbt)); + } + return setBlock(x, y, z, BlockState.get(combinedId)); + } + + @Override + public int getCachedCombinedId4Data(int x, int y, int z) throws FaweException.FaweChunkLoadException { + return getCombinedId4Data(x, y, z); + } + + @Override + public int getCombinedId4Data(int x, int y, int z) throws FaweException.FaweChunkLoadException { + return getLazyBlock(x, y, z).getInternalId(); + } + + @Override + public CompoundTag getTileEntity(int x, int y, int z) throws FaweException.FaweChunkLoadException { + return getLazyBlock(x, y, z).getNbtData(); + } + + @Override + public int getBiomeId(int x, int z) throws FaweException.FaweChunkLoadException { + return parentExtent.getBiome(mutable2d.setComponents(x, z)).getId(); + } + + @Override + public boolean setBiome(Vector2D position, BaseBiome biome) { + return parentExtent.setBiome(position, biome); + } + + @Override + public BlockState getBlock(Vector position) { + return parentExtent.getBlock(position); + } + + @Override + public BaseBiome getBiome(Vector2D position) { + return parentExtent.getBiome(position); + } + + @Override + public boolean setBlock(Vector position, BlockStateHolder block) throws WorldEditException { + return parentExtent.setBlock(position, block); + } + + @Override + public boolean setBlock(int x, int y, int z, BlockStateHolder block) throws WorldEditException { + return parentExtent.setBlock(x, y, z, block); + } + + @Override + public BlockState getLazyBlock(Vector position) { + return parentExtent.getLazyBlock(position); + } + + @Override + public BlockState getLazyBlock(int x, int y, int z) { + return parentExtent.getLazyBlock(x, y, z); + } + + +} diff --git a/worldedit-core/src/main/java/com/sk89q/worldedit/function/mask/BlockMask.java b/worldedit-core/src/main/java/com/sk89q/worldedit/function/mask/BlockMask.java index d4c802a55..7e1f832d5 100644 --- a/worldedit-core/src/main/java/com/sk89q/worldedit/function/mask/BlockMask.java +++ b/worldedit-core/src/main/java/com/sk89q/worldedit/function/mask/BlockMask.java @@ -4,6 +4,7 @@ import com.boydti.fawe.Fawe; import com.boydti.fawe.FaweCache; import com.boydti.fawe.object.collection.FastBitSet; import com.boydti.fawe.util.MainUtil; +import com.boydti.fawe.util.StringMan; import com.sk89q.worldedit.Vector; import com.sk89q.worldedit.blocks.BaseBlock; import com.sk89q.worldedit.world.block.BlockState; @@ -15,6 +16,7 @@ import com.sk89q.worldedit.world.block.BlockType; import com.sk89q.worldedit.world.block.BlockTypes; import javax.annotation.Nullable; +import java.util.ArrayList; import java.util.HashMap; import java.util.List; import java.util.Map; @@ -43,6 +45,31 @@ public class BlockMask extends AbstractExtentMask { this.bitSets = bitSets; } + public BlockMaskBuilder toBuilder() { + return new BlockMaskBuilder(this.bitSets); + } + + @Override + public String toString() { + List strings = new ArrayList<>(); + for (int i = 0; i < bitSets.length; i++) { + if (bitSets[i] != null) { + long[] set = bitSets[i]; + BlockTypes type = BlockTypes.get(i); + if (set == ALL) { + strings.add(type.getId()); + } else { + for (BlockState state : type.getStates()) { + if (test(state)) { + strings.add(state.getAsString()); + } + } + } + } + } + return StringMan.join(strings, ","); + } + @Override public Mask optimize() { Map states = new HashMap<>(); @@ -179,6 +206,13 @@ public class BlockMask extends AbstractExtentMask { return this; } + public boolean test(BlockState block) { + long[] bitSet = bitSets[block.getInternalBlockTypeId()]; + if (bitSet == null) return false; + if (bitSet.length == 0) return true; + return FastBitSet.get(bitSet, block.getInternalPropertiesId()); + } + @Override public boolean test(Vector vector) { BlockStateHolder block = getExtent().getBlock(vector); diff --git a/worldedit-core/src/main/java/com/sk89q/worldedit/function/mask/BlockMaskBuilder.java b/worldedit-core/src/main/java/com/sk89q/worldedit/function/mask/BlockMaskBuilder.java index 9398c4e0a..cc4bf7b19 100644 --- a/worldedit-core/src/main/java/com/sk89q/worldedit/function/mask/BlockMaskBuilder.java +++ b/worldedit-core/src/main/java/com/sk89q/worldedit/function/mask/BlockMaskBuilder.java @@ -553,7 +553,7 @@ public class BlockMaskBuilder { return this.bitSets; } - public Mask build(Extent extent) { + public BlockMask build(Extent extent) { optimize(); return new BlockMask(extent, bitSets); } diff --git a/worldedit-core/src/main/java/com/sk89q/worldedit/world/block/BlockTypes.java b/worldedit-core/src/main/java/com/sk89q/worldedit/world/block/BlockTypes.java index b58878bf9..c94480115 100644 --- a/worldedit-core/src/main/java/com/sk89q/worldedit/world/block/BlockTypes.java +++ b/worldedit-core/src/main/java/com/sk89q/worldedit/world/block/BlockTypes.java @@ -775,6 +775,24 @@ public enum BlockTypes implements BlockType { return state; } + /** + * Slow + * @return collection of states + */ + @Deprecated + public Collection getStates() { + if (this.settings.states == null || this.settings.states.length <= 1) { + return Collections.singletonList(getDefaultState()); + } + ArrayList states = new ArrayList<>(); + for (BlockState state : settings.states) { + if (state != null) { + states.add(state); + } + } + return states; + } + @Deprecated public int getMaxStateId() { return settings.permutations;