package com.hypixel.hytale.builtin.buildertools; import com.hypixel.hytale.builtin.buildertools.utils.Material; import com.hypixel.hytale.math.util.ChunkUtil; import com.hypixel.hytale.math.vector.Vector3i; import com.hypixel.hytale.server.core.prefab.selection.mask.BlockMask; import com.hypixel.hytale.server.core.prefab.selection.standard.BlockSelection; import com.hypixel.hytale.server.core.universe.world.World; import com.hypixel.hytale.server.core.universe.world.accessor.BlockAccessor; import com.hypixel.hytale.server.core.universe.world.accessor.LocalCachedChunkAccessor; import com.hypixel.hytale.server.core.universe.world.accessor.OverridableChunkAccessor; import javax.annotation.Nonnull; public class EditOperation { private final BlockMask blockMask; @Nonnull private final OverridableChunkAccessor accessor; @Nonnull private final BlockSelection before; @Nonnull private final BlockSelection after; private final Vector3i min; private final Vector3i max; public EditOperation(@Nonnull World world, int x, int y, int z, int editRange, Vector3i min, Vector3i max, BlockMask blockMask) { this.blockMask = blockMask; this.accessor = LocalCachedChunkAccessor.atWorldCoords(world, x, z, editRange); this.min = min; this.max = max; this.before = new BlockSelection(); this.before.setPosition(x, y, z); if (min != null && max != null) { this.before.setSelectionArea(min, max); } this.after = new BlockSelection(this.before); } public BlockMask getBlockMask() { return this.blockMask; } @Nonnull public BlockSelection getBefore() { return this.before; } @Nonnull public BlockSelection getAfter() { return this.after; } @Nonnull public OverridableChunkAccessor getAccessor() { return this.accessor; } public int getBlock(int x, int y, int z) { return this.accessor.getBlock(x, y, z); } public boolean setBlock(int x, int y, int z, int blockId) { return this.setBlock(x, y, z, blockId, 0); } public boolean setBlock(int x, int y, int z, int blockId, int rotation) { int currentBlock = this.getBlock(x, y, z); int currentFluid = this.getFluid(x, y, z); if (this.blockMask != null && this.blockMask.isExcluded(this.accessor, x, y, z, this.min, this.max, currentBlock, currentFluid)) { return false; } else { BlockAccessor blocks = this.accessor.getChunkIfInMemory(ChunkUtil.indexChunkFromBlock(x, z)); if (blocks == null) { return false; } else { if (!this.before.hasBlockAtWorldPos(x, y, z)) { this.before .addBlockAtWorldPos( x, y, z, currentBlock, blocks.getRotationIndex(x, y, z), blocks.getFiller(x, y, z), blocks.getSupportValue(x, y, z), blocks.getBlockComponentHolder(x, y, z) ); } this.after.addBlockAtWorldPos(x, y, z, blockId, rotation, 0, 0); if (blockId == 0) { this.setFluid(x, y, z, 0, (byte)0); } return true; } } } private boolean setFluid(int x, int y, int z, int fluidId, byte fluidLevel) { BlockAccessor chunk = this.accessor.getChunkIfInMemory(ChunkUtil.indexChunkFromBlock(x, z)); if (chunk == null) { return false; } else { int currentBlock = this.getBlock(x, y, z); int currentFluid = this.getFluid(x, y, z); if (this.blockMask != null && this.blockMask.isExcluded(this.accessor, x, y, z, this.min, this.max, currentBlock, currentFluid)) { return false; } else { int beforeFluid = this.before.getFluidAtWorldPos(x, y, z); if (beforeFluid < 0) { int originalFluidId = chunk.getFluidId(x, y, z); byte originalFluidLevel = chunk.getFluidLevel(x, y, z); this.before.addFluidAtWorldPos(x, y, z, originalFluidId, originalFluidLevel); } this.after.addFluidAtWorldPos(x, y, z, fluidId, fluidLevel); return true; } } } public int getFluid(int x, int y, int z) { BlockAccessor chunk = this.accessor.getChunkIfInMemory(ChunkUtil.indexChunkFromBlock(x, z)); return chunk != null ? chunk.getFluidId(x, y, z) : 0; } public boolean setMaterial(int x, int y, int z, @Nonnull Material material) { return material.isFluid() ? this.setFluid(x, y, z, material.getFluidId(), material.getFluidLevel()) : this.setBlock(x, y, z, material.getBlockId(), material.getRotation()); } }