001/* 002 * PlotSquared, a land and world management plugin for Minecraft. 003 * Copyright (C) IntellectualSites <https://intellectualsites.com> 004 * Copyright (C) IntellectualSites team and contributors 005 * 006 * This program is free software: you can redistribute it and/or modify 007 * it under the terms of the GNU General Public License as published by 008 * the Free Software Foundation, either version 3 of the License, or 009 * (at your option) any later version. 010 * 011 * This program is distributed in the hope that it will be useful, 012 * but WITHOUT ANY WARRANTY; without even the implied warranty of 013 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 014 * GNU General Public License for more details. 015 * 016 * You should have received a copy of the GNU General Public License 017 * along with this program. If not, see <https://www.gnu.org/licenses/>. 018 */ 019package com.plotsquared.core.queue; 020 021import com.intellectualsites.annotations.NotPublic; 022import com.plotsquared.core.location.Location; 023import com.sk89q.jnbt.CompoundTag; 024import com.sk89q.worldedit.function.pattern.Pattern; 025import com.sk89q.worldedit.math.BlockVector3; 026import com.sk89q.worldedit.world.biome.BiomeType; 027import com.sk89q.worldedit.world.block.BaseBlock; 028import com.sk89q.worldedit.world.block.BlockState; 029import org.checkerframework.checker.nullness.qual.NonNull; 030import org.checkerframework.checker.nullness.qual.Nullable; 031 032/** 033 * {@link QueueCoordinator} that caches all blocks set to it in a given array of form BlockState[][][]. An offset can be 034 * applied to blocks set to it, and the scope limited. This should have blocks set to it one chunk at a time, based on the 035 * result of {@link BlockArrayCacheScopedQueueCoordinator#getMin()} and {@link BlockArrayCacheScopedQueueCoordinator#getMax()}. 036 * The min and max points of this queue are offset according to the minimum point given in the constructor, and the offsets set 037 * in {@link BlockArrayCacheScopedQueueCoordinator#setOffsetX(int)} and 038 * {@link BlockArrayCacheScopedQueueCoordinator#setOffsetZ(int)} 039 * <p> 040 * Internal use only. Subject to change at any time and created for specific use cases. 041 */ 042@NotPublic 043public class BlockArrayCacheScopedQueueCoordinator extends ZeroedDelegateScopedQueueCoordinator { 044 045 private final BlockState[][][] blockStates; 046 private final int height; 047 private final int width; 048 private final int length; 049 private final int minY; 050 private final int maxY; 051 private final int scopeMinX; 052 private final int scopeMinZ; 053 private final int scopeMaxX; 054 private final int scopeMaxZ; 055 private int offsetX = 0; 056 private int offsetZ = 0; 057 058 /** 059 * Construct a new instance 060 * 061 * @param min Inclusive location of the minimum point to limit the scope to. 062 * @param max Inclusive location of the maximum point to limit the scope to. 063 * @since 6.8.0 064 */ 065 public BlockArrayCacheScopedQueueCoordinator(Location min, Location max) { 066 super(null, min, max); 067 this.width = max.getX() - min.getX() + 1; 068 this.length = max.getZ() - min.getZ() + 1; 069 this.minY = min.getY(); 070 this.maxY = max.getY(); 071 this.height = maxY - minY + 1; 072 073 this.scopeMinX = min.getX() & 15; 074 this.scopeMinZ = min.getZ() & 15; 075 this.scopeMaxX = scopeMinX + width; 076 this.scopeMaxZ = scopeMinZ + length; 077 this.blockStates = new BlockState[height][width][length]; 078 } 079 080 public BlockState[][][] getBlockStates() { 081 return blockStates; 082 } 083 084 @Override 085 public boolean setBlock(int x, final int y, int z, final @NonNull BlockState id) { 086 x += offsetX; 087 z += offsetZ; 088 if (x >= scopeMinX && x < scopeMaxX && y >= minY && y <= maxY && z >= scopeMinZ && z < scopeMaxZ) { 089 blockStates[y - minY][x - scopeMinX][z - scopeMinZ] = id; 090 } 091 return false; 092 } 093 094 @Override 095 public boolean setBlock(final int x, final int y, final int z, @NonNull final Pattern pattern) { 096 int rx = x + offsetX; 097 int rz = z + offsetZ; 098 if (rx >= scopeMinX && rx < scopeMaxX && y >= minY && y <= maxY && rz >= scopeMinZ && rz < scopeMaxZ) { 099 BlockState state = pattern 100 .applyBlock(super.getMin().getBlockVector3().add(BlockVector3.at(x, y, z))) 101 .toImmutableState(); 102 blockStates[y - minY][rx - scopeMinX][rz - scopeMinZ] = state; 103 } 104 return false; 105 } 106 107 @Override 108 public @NonNull Location getMin() { 109 return super.getMin().add(offsetX - scopeMinX, 0, offsetZ - scopeMinZ); 110 } 111 112 @Override 113 public @NonNull Location getMax() { 114 return getMin().add(15, 0, 15).withY(maxY); 115 } 116 117 @Override 118 public boolean setBlock(int x, int y, int z, final @NonNull BaseBlock id) { 119 x += offsetX; 120 z += offsetZ; 121 if (x >= scopeMinX && x < scopeMaxX && y >= minY && y <= maxY && z >= scopeMinZ && z < scopeMaxZ) { 122 blockStates[y - minY][x - scopeMinX][z - scopeMinZ] = id.toImmutableState(); 123 } 124 return false; 125 } 126 127 @Override 128 public @Nullable BlockState getBlock(final int x, final int y, final int z) { 129 if (x >= 0 && x < width && y >= minY && y <= maxY && z >= 0 && z < length) { 130 return blockStates[y - minY][x][z]; 131 } 132 return null; 133 } 134 135 public void setOffsetX(final int offsetX) { 136 this.offsetX = offsetX; 137 } 138 139 public void setOffsetZ(final int offsetZ) { 140 this.offsetZ = offsetZ; 141 } 142 143 @Override 144 public int size() { 145 return height * width * length; 146 } 147 148 @Override 149 public boolean setBiome(final int x, final int z, @NonNull final BiomeType biome) { 150 //do nothing 151 return false; 152 } 153 154 @Override 155 public boolean setBiome(final int x, final int y, final int z, @NonNull final BiomeType biome) { 156 //do nothing 157 return false; 158 } 159 160 @Override 161 public void fillBiome(final BiomeType biome) { 162 //do nothing 163 } 164 165 @Override 166 public boolean setTile(final int x, final int y, final int z, @NonNull final CompoundTag tag) { 167 //do nothing 168 return false; 169 } 170 171}