Skip to content

Commit

Permalink
Merge pull request #201 from KevinDaGame/feat/stencil
Browse files Browse the repository at this point in the history
Feat/stencil
  • Loading branch information
KevinDaGame authored Jul 5, 2023
2 parents fa79ef9 + a5da483 commit f648d69
Show file tree
Hide file tree
Showing 13 changed files with 458 additions and 5 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,7 @@ public static VoxelBrushManager initialize() {
brushManager = getInstance();
}

brushManager.registerSniperBrush(schematicBrush());
brushManager.registerSniperBrush(ballBrush());
brushManager.registerSniperBrush(biomeBrush());
brushManager.registerSniperBrush(biomeBallBrush());
Expand Down Expand Up @@ -113,8 +114,11 @@ public static VoxelBrushManager initialize() {
return getInstance();
}


// region <Brush Registration methods>
private static BrushData schematicBrush() {
return new BrushBuilder().name("Schematic").alias("schematic", "schem", "stencil").setSupplier(SchematicBrush::new).setPermission("voxelsniper.brush.schematic").build();
}

private static BrushData ballBrush() {
return new PolyBrushBuilder().name("Ball").alias("b", "ball").permission("voxelsniper.brush.ball").shape(PolyBrushShape.BALL).build();
}
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,243 @@
package com.github.kevindagame.brush

import com.github.kevindagame.snipe.SnipeData
import com.github.kevindagame.util.Messages
import com.github.kevindagame.util.VoxelMessage
import com.github.kevindagame.util.brushOperation.BlockOperation
import com.github.kevindagame.util.schematic.SchematicReader
import com.github.kevindagame.util.schematic.VoxelSchematic
import com.github.kevindagame.util.schematic.VoxelSchematicBlock
import com.github.kevindagame.voxelsniper.location.BaseLocation
import com.github.kevindagame.voxelsniper.material.VoxelMaterial

class SchematicBrush : AbstractBrush() {
private lateinit var schematicName: String
private lateinit var schematics: List<VoxelSchematic>
private var mode = PasteMode.FULL
private var rotation = RotateMode.DEGREES_0
private var flip = FlipMode.NONE

override fun info(vm: VoxelMessage) {
vm.brushName(this.name)
vm.custom(Messages.CHOSEN_SCHEMATIC.replace("%schematics%", if(this::schematics.isInitialized) schematics.joinToString(", ") { it.name } else "None"))
vm.custom(Messages.SCHEMATIC_MODE.replace("%mode%", mode.name.lowercase()))
vm.custom(Messages.SCHEMATIC_ROTATION.replace("%rotation%", rotation.name.lowercase().replace("degrees_", "")))
vm.custom(Messages.SCHEMATIC_FLIP.replace("%flip%", flip.name.lowercase()))
}

override fun arrow(v: SnipeData) {
paste(v)
}

override fun powder(v: SnipeData) {
paste(v)
}

/**
* paste a schematic
* if there is no schematic loaded, then it will send a message to the player
* if there is only one schematic loaded, then it will paste that schematic
* if there are multiple schematics loaded, then it will paste a random schematic from the loaded schematics
*/
private fun paste(v: SnipeData) {
if (!this::schematics.isInitialized || schematics.isEmpty()) {
v.owner().player.sendMessage("No schematic loaded")
return
}

if (schematics.size == 1) {
pasteSchematic(schematics[0])
return
}

val schematic = schematics.random()
pasteSchematic(schematic)
}

private fun pasteSchematic(schematic: VoxelSchematic) {
val blocks = rotateAndFlip(schematic.blocks)

for (block in blocks) {
val blockLocation = BaseLocation(world, block.x + targetBlock.x, block.y + targetBlock.y, block.z + targetBlock.z)
when(this.mode) {
PasteMode.FILL -> {
if (blockLocation.block.blockData.material.isAir) {
addOperation(BlockOperation(blockLocation, blockLocation.block.blockData, VoxelMaterial.getMaterial(block.blockData.block).createBlockData()))
}
}

PasteMode.FULL -> {
addOperation(BlockOperation(blockLocation, blockLocation.block.blockData, VoxelMaterial.getMaterial(block.blockData.block).createBlockData()))
}

PasteMode.REPLACE -> {
if (!blockLocation.block.blockData.material.isAir) {
addOperation(BlockOperation(blockLocation, blockLocation.block.blockData, VoxelMaterial.getMaterial(block.blockData.block).createBlockData()))
}
}
}
}
}

private fun rotateAndFlip(blocks: List<VoxelSchematicBlock>): MutableList<VoxelSchematicBlock> {
val rotationDegrees = when (this.rotation) {
RotateMode.DEGREES_0 -> 0
RotateMode.DEGREES_90 -> 90
RotateMode.DEGREES_180 -> 180
RotateMode.DEGREES_270 -> 270
RotateMode.DEGREES_RANDOM -> (listOf(90, 180, 270, 0)).random()
}

val newBlocks = mutableListOf<VoxelSchematicBlock>()

for (block in blocks) {
val newBlock = rotateBlock(block, rotationDegrees)
flipBlock(newBlock)
newBlocks.add(newBlock)
}

return newBlocks
}

private fun rotateBlock(
block: VoxelSchematicBlock,
rotationDegrees: Int
): VoxelSchematicBlock {
when (rotationDegrees) {
0 -> {
return VoxelSchematicBlock(block.x, block.y, block.z, block.blockData)
}

90 -> {
return VoxelSchematicBlock(-block.z, block.y, block.x, block.blockData)
}

180 -> {
return VoxelSchematicBlock(-block.x, block.y, -block.z, block.blockData)
}

270 -> {
return VoxelSchematicBlock(block.z, block.y, -block.x, block.blockData)
}

}
throw IllegalArgumentException("Invalid rotation degrees: $rotationDegrees")
}

private fun flipBlock(block: VoxelSchematicBlock) {
when (this.flip) {
FlipMode.NONE -> {
return
}

FlipMode.X -> {
block.x = -block.x
}

FlipMode.Y -> {
block.y = -block.y
}

FlipMode.Z -> {
block.z = -block.z
}
}
}

override fun parseParameters(triggerHandle: String, params: Array<String>, v: SnipeData) {
if (params.isNotEmpty()) {
when (params[0]) {
"list" -> {
v.sendMessage(Messages.SCHEMATIC_LIST.replace("%schematics%", SchematicReader.getPossibleNames().joinToString(", ")))
}

"schem" -> {
if (params.size > 1) {
try {
val schematics = SchematicReader.read(params[1])
this.schematicName = params[1]
this.schematics = schematics
if (schematics.size == 1) {
v.sendMessage(Messages.SCHEMATIC_LOADED_ONE.replace("%schematic%", this.schematics.first().name))
} else {
v.sendMessage(Messages.SCHEMATIC_LOADED_MULTIPLE.replace("%schematics%", this.schematics.joinToString(", ") { it.name }))
}
} catch (e: IllegalArgumentException) {
v.sendMessage(Messages.INVALID_BRUSH_PARAM)
}
}
}

"rotate" -> {
if (params.size > 1) {
try {
this.rotation = RotateMode.valueOf("DEGREES_${params[1].uppercase()}")
v.sendMessage(Messages.SCHEMATIC_SET_ROTATION.replace("%rotation%", this.rotation.name.lowercase().replace("degrees_", "")))
} catch (e: IllegalArgumentException) {
v.sendMessage(Messages.INVALID_BRUSH_PARAM)
}
}
}

"flip" -> {
if (params.size > 1) {
try {
this.flip = FlipMode.valueOf(params[1].uppercase())
v.sendMessage(Messages.SCHEMATIC_SET_FLIP.replace("%flip%", this.flip.name.lowercase()))
} catch (e: IllegalArgumentException) {
v.sendMessage(Messages.INVALID_BRUSH_PARAM)
}
}
}

"mode" -> {
if (params.size > 1) {
try {
this.mode = PasteMode.valueOf(params[1].uppercase())
v.sendMessage(Messages.SCHEMATIC_SET_MODE.replace("%mode%", this.mode.name.lowercase()))

} catch (e: IllegalArgumentException) {
v.sendMessage(Messages.INVALID_BRUSH_PARAM)
}
}
}

}
}
}

override fun registerArguments(): List<String> {
return listOf("schem", "rotate", "flip", "list", "mode")
}

override fun registerArgumentValues(): HashMap<String, List<String>> {
return hashMapOf(
"schem" to SchematicReader.getPossibleNames(),
"rotate" to RotateMode.values().map { it.name.lowercase().replace("degrees_", "") },
"flip" to FlipMode.values().map { it.name.lowercase() },
"mode" to PasteMode.values().map { it.name.lowercase() },
"list" to listOf(),
)
}
}

private enum class PasteMode {
FILL,
FULL,
REPLACE
}

private enum class FlipMode {
X,
Y,
Z,
NONE
}

private enum class RotateMode {
DEGREES_0,
DEGREES_90,
DEGREES_180,
DEGREES_270,
DEGREES_RANDOM
}
Original file line number Diff line number Diff line change
Expand Up @@ -360,6 +360,18 @@ public enum Messages implements ComponentLike {
ACTION_CANCELLED,
UPDATE_AVAILABLE,
BRUSH_SIZE_TOO_LARGE,

SCHEMATIC_BRUSH_MESSAGE,
CHOSEN_SCHEMATIC,
SCHEMATIC_MODE,
SCHEMATIC_ROTATION,
SCHEMATIC_FLIP,
SCHEMATIC_LIST,
SCHEMATIC_LOADED_ONE,
SCHEMATIC_LOADED_MULTIPLE,
SCHEMATIC_SET_ROTATION,
SCHEMATIC_SET_FLIP,
SCHEMATIC_SET_MODE,
;
//</editor-fold>

Expand Down
Loading

0 comments on commit f648d69

Please sign in to comment.