package com.hypixel.hytale.builtin.buildertools.scriptedbrushes.operations.sequential; import com.hypixel.hytale.builtin.buildertools.scriptedbrushes.BrushConfig; import com.hypixel.hytale.builtin.buildertools.scriptedbrushes.BrushConfigCommandExecutor; import com.hypixel.hytale.builtin.buildertools.scriptedbrushes.BrushConfigEditStore; import com.hypixel.hytale.builtin.buildertools.scriptedbrushes.operations.system.SequenceBrushOperation; import com.hypixel.hytale.builtin.buildertools.utils.Material; import com.hypixel.hytale.codec.KeyedCodec; import com.hypixel.hytale.codec.builder.BuilderCodec; import com.hypixel.hytale.codec.codecs.EnumCodec; import com.hypixel.hytale.component.ComponentAccessor; import com.hypixel.hytale.component.Ref; import com.hypixel.hytale.math.vector.Vector3i; import com.hypixel.hytale.server.core.universe.world.storage.EntityStore; import it.unimi.dsi.fastutil.ints.Int2IntMap; import it.unimi.dsi.fastutil.ints.Int2IntOpenHashMap; import it.unimi.dsi.fastutil.ints.IntIterator; import javax.annotation.Nonnull; public class ErodeOperation extends SequenceBrushOperation { public static final BuilderCodec CODEC = BuilderCodec.builder(ErodeOperation.class, ErodeOperation::new) .append(new KeyedCodec<>("ErodePreset", new EnumCodec<>(ErodeOperation.ErodePreset.class)), (op, val) -> op.erodePresetArg = val, op -> op.erodePresetArg) .documentation("An erosion preset to use with the operation") .add() .documentation("Erodes blocks following a preset") .build(); private ErodeOperation.ErodePreset erodePresetArg = ErodeOperation.ErodePreset.Default; private static final Vector3i[] FACES_TO_CHECK = new Vector3i[]{ new Vector3i(0, -1, 0), new Vector3i(0, 1, 0), new Vector3i(0, 0, 1), new Vector3i(0, 0, -1), new Vector3i(1, 0, 0), new Vector3i(-1, 0, 0) }; int iterationIndex; public ErodeOperation() { super("erode", "Erodes blocks following a preset", true); } @Override public void modifyBrushConfig( @Nonnull Ref ref, @Nonnull BrushConfig brushConfig, @Nonnull BrushConfigCommandExecutor brushConfigCommandExecutor, @Nonnull ComponentAccessor componentAccessor ) { } @Override public boolean modifyBlocks( Ref ref, BrushConfig brushConfig, BrushConfigCommandExecutor brushConfigCommandExecutor, @Nonnull BrushConfigEditStore edit, int x, int y, int z, ComponentAccessor componentAccessor ) { if (this.iterationIndex < this.erodePresetArg.erosionIterations) { this.iterateErosion(edit, x, y, z); } else { this.iterateFill(edit, x, y, z); } return true; } @Override public void beginIterationIndex(int iterationIndex) { this.iterationIndex = iterationIndex; } @Override public int getNumModifyBlockIterations() { return this.erodePresetArg.erosionIterations + this.erodePresetArg.fillIterations; } private void iterateFill(@Nonnull BrushConfigEditStore edit, int x, int y, int z) { int block = edit.getBlock(x, y, z); if (block == 0) { int numFacesFound = 0; Int2IntMap blockCount = new Int2IntOpenHashMap(); for (Vector3i direction : FACES_TO_CHECK) { int blockAtRelativePosition = edit.getBlock(x + direction.x, y + direction.y, z + direction.z); if (blockAtRelativePosition != 0) { numFacesFound++; blockCount.put(blockAtRelativePosition, blockCount.getOrDefault(blockAtRelativePosition, 0) + 1); } } if (numFacesFound >= this.erodePresetArg.fillFaces) { int blockIdWithHighestQuantity = block; int blockIdWithHighestQuantityAmount = 0; IntIterator var15 = blockCount.keySet().iterator(); while (var15.hasNext()) { int blockId = (Integer)var15.next(); int countOfType = blockCount.get(blockId); if (countOfType > blockIdWithHighestQuantityAmount) { blockIdWithHighestQuantity = blockId; blockIdWithHighestQuantityAmount = countOfType; } } edit.setMaterial(x, y, z, Material.block(blockIdWithHighestQuantity)); } } } private void iterateErosion(@Nonnull BrushConfigEditStore edit, int x, int y, int z) { int block = edit.getBlock(x, y, z); if (block != 0) { int numFacesFound = 0; for (Vector3i direction : FACES_TO_CHECK) { int blockAtRelativePosition = edit.getBlock(x + direction.x, y + direction.y, z + direction.z); if (blockAtRelativePosition == 0) { numFacesFound++; } } if (numFacesFound >= this.erodePresetArg.erosionFaces) { edit.setMaterial(x, y, z, Material.EMPTY); } } } public static enum ErodePreset { Default(0, 1, 0, 1), Melt(2, 1, 5, 1), Fill(5, 1, 2, 1), Smooth(3, 1, 3, 1), Lift(6, 0, 1, 1), FloatClean(6, 1, 6, 1); public final int erosionFaces; public final int erosionIterations; public final int fillFaces; public final int fillIterations; private ErodePreset(int erosionFaces, int erosionIterations, int fillFaces, int fillIterations) { this.erosionFaces = erosionFaces; this.erosionIterations = erosionIterations; this.fillFaces = fillFaces; this.fillIterations = fillIterations; } } }