PlotSquared/Core/src/main/java/com/plotsquared/core/collection/QuadMap.java

325 lines
10 KiB
Java
Raw Normal View History

/*
* PlotSquared, a land and world management plugin for Minecraft.
* Copyright (C) IntellectualSites <https://intellectualsites.com>
* Copyright (C) IntellectualSites team and contributors
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <https://www.gnu.org/licenses/>.
*/
2020-04-15 21:26:54 +02:00
package com.plotsquared.core.collection;
2016-02-10 19:59:51 +01:00
2020-04-15 21:26:54 +02:00
import com.plotsquared.core.util.RegionUtil;
import com.sk89q.worldedit.regions.CuboidRegion;
2016-02-10 19:59:51 +01:00
import java.util.HashSet;
import java.util.Set;
public class QuadMap<T> {
2016-03-23 18:16:05 +01:00
2016-02-10 19:59:51 +01:00
public final int size;
public final int x;
public final int z;
private final int newsize;
private final int min;
2016-02-10 19:59:51 +01:00
public HashSet<T> objects;
public QuadMap<T> one;
public QuadMap<T> two;
public QuadMap<T> three;
public QuadMap<T> four;
public QuadMap<T> skip;
public QuadMap(int size, int x, int z) {
this.size = size;
this.x = x;
this.z = z;
this.newsize = size >> 1;
2016-03-23 18:16:05 +01:00
this.min = 512;
2016-02-10 19:59:51 +01:00
}
2016-03-23 18:16:05 +01:00
2016-02-10 19:59:51 +01:00
public QuadMap(int size, int x, int z, int min) {
this.size = size;
this.x = x;
this.z = z;
this.newsize = size >> 1;
this.min = min;
}
2016-03-23 18:16:05 +01:00
2016-02-10 19:59:51 +01:00
public int count() {
int size = countBelow();
2016-03-23 18:16:05 +01:00
if (this.objects != null) {
size += this.objects.size();
2016-02-10 19:59:51 +01:00
}
return size;
}
2016-03-23 18:16:05 +01:00
2016-02-10 19:59:51 +01:00
public Set<T> getAll() {
HashSet<T> all = new HashSet<>();
2016-03-23 18:16:05 +01:00
if (this.objects != null) {
all.addAll(this.objects);
2016-02-10 19:59:51 +01:00
}
2016-03-23 18:16:05 +01:00
if (this.skip != null) {
all.addAll(this.skip.getAll());
2016-02-10 19:59:51 +01:00
return all;
}
2016-03-23 18:16:05 +01:00
if (this.one != null) {
all.addAll(this.one.getAll());
2016-02-10 19:59:51 +01:00
}
2016-03-23 18:16:05 +01:00
if (this.two != null) {
all.addAll(this.two.getAll());
2016-02-10 19:59:51 +01:00
}
2016-03-23 18:16:05 +01:00
if (this.three != null) {
all.addAll(this.three.getAll());
2016-02-10 19:59:51 +01:00
}
2016-03-23 18:16:05 +01:00
if (this.four != null) {
all.addAll(this.four.getAll());
2016-02-10 19:59:51 +01:00
}
return all;
}
public int countCurrent() {
2016-03-23 18:16:05 +01:00
return this.objects == null ? 0 : this.objects.size();
2016-02-10 19:59:51 +01:00
}
public int countBelow() {
int size = 0;
2016-03-23 18:16:05 +01:00
if (this.one != null) {
size += this.one.count();
2016-02-10 19:59:51 +01:00
}
2016-03-23 18:16:05 +01:00
if (this.two != null) {
size += this.two.count();
2016-02-10 19:59:51 +01:00
}
2016-03-23 18:16:05 +01:00
if (this.three != null) {
size += this.three.count();
2016-02-10 19:59:51 +01:00
}
2016-03-23 18:16:05 +01:00
if (this.four != null) {
size += this.four.count();
2016-02-10 19:59:51 +01:00
}
return size;
}
public void add(T area) {
2016-03-23 18:16:05 +01:00
if (this.size <= this.min) {
2016-02-10 19:59:51 +01:00
if (this.objects == null) {
2016-03-23 18:16:05 +01:00
this.objects = new HashSet<>();
2016-02-10 19:59:51 +01:00
}
this.objects.add(area);
return;
}
CuboidRegion region = getRegion(area);
if (region.getMinimumPoint().getX() >= this.x) {
if (region.getMinimumPoint().getZ() >= this.z) {
2016-03-23 18:16:05 +01:00
if (this.one == null) {
2018-08-10 17:01:10 +02:00
this.one =
newInstance(this.newsize, this.x + this.newsize, this.z + this.newsize,
this.min
);
2016-02-10 19:59:51 +01:00
}
2016-03-23 18:16:05 +01:00
this.one.add(area);
2016-02-10 19:59:51 +01:00
recalculateSkip();
return;
} else if (region.getMaximumPoint().getZ() < this.z) {
2016-03-23 18:16:05 +01:00
if (this.two == null) {
2018-08-10 17:01:10 +02:00
this.two =
newInstance(this.newsize, this.x + this.newsize, this.z - this.newsize,
this.min
);
2016-02-10 19:59:51 +01:00
}
2016-03-23 18:16:05 +01:00
this.two.add(area);
2016-02-10 19:59:51 +01:00
recalculateSkip();
return;
}
} else if (region.getMaximumPoint().getX() < this.x) {
if (region.getMinimumPoint().getZ() >= this.z) {
2016-03-23 18:16:05 +01:00
if (this.four == null) {
2018-08-10 17:01:10 +02:00
this.four =
newInstance(this.newsize, this.x - this.newsize, this.z + this.newsize,
this.min
);
2016-02-10 19:59:51 +01:00
}
2016-03-23 18:16:05 +01:00
this.four.add(area);
2016-02-10 19:59:51 +01:00
recalculateSkip();
return;
} else if (region.getMaximumPoint().getZ() < this.z) {
2016-03-23 18:16:05 +01:00
if (this.three == null) {
2018-08-10 17:01:10 +02:00
this.three =
newInstance(this.newsize, this.x - this.newsize, this.z - this.newsize,
this.min
);
2016-02-10 19:59:51 +01:00
}
2016-03-23 18:16:05 +01:00
this.three.add(area);
2016-02-10 19:59:51 +01:00
recalculateSkip();
return;
}
}
if (this.objects == null) {
2016-03-23 18:16:05 +01:00
this.objects = new HashSet<>();
2016-02-10 19:59:51 +01:00
}
this.objects.add(area);
}
2016-03-23 18:16:05 +01:00
public CuboidRegion getRegion(T value) {
2016-02-10 20:02:54 +01:00
return null;
}
2016-03-23 18:16:05 +01:00
2016-02-10 19:59:51 +01:00
public QuadMap<T> newInstance(int newsize, int x, int z, int min) {
try {
return new QuadMap<T>(newsize, x, z, min) {
@Override
public CuboidRegion getRegion(T value) {
2016-02-10 19:59:51 +01:00
return QuadMap.this.getRegion(value);
}
};
} catch (Throwable e) {
e.printStackTrace();
return null;
}
}
2016-03-23 18:16:05 +01:00
2016-02-10 19:59:51 +01:00
public boolean remove(T area) {
2016-03-23 18:16:05 +01:00
if (this.objects != null) {
if (this.objects.remove(area)) {
return this.objects.isEmpty();
2016-02-10 19:59:51 +01:00
}
}
2016-03-23 18:16:05 +01:00
if (this.skip != null) {
if (this.skip.remove(area)) {
this.skip = null;
2016-02-10 19:59:51 +01:00
}
} else {
CuboidRegion region = getRegion(area);
if (region.getMinimumPoint().getX() >= this.x) {
if (region.getMinimumPoint().getZ() >= this.z) {
2016-03-23 18:16:05 +01:00
if (this.one != null) {
if (this.one.remove(area)) {
this.one = null;
2016-02-10 19:59:51 +01:00
}
return countCurrent() == 0;
}
} else {
2016-03-23 18:16:05 +01:00
if (this.two != null) {
if (this.two.remove(area)) {
this.two = null;
2016-02-10 19:59:51 +01:00
}
return countCurrent() == 0;
}
}
} else {
if (region.getMinimumPoint().getZ() >= this.z) {
2016-03-23 18:16:05 +01:00
if (this.four != null) {
if (this.four.remove(area)) {
this.four = null;
2016-02-10 19:59:51 +01:00
}
return countCurrent() == 0;
}
} else {
2016-03-23 18:16:05 +01:00
if (this.three != null) {
if (this.three.remove(area)) {
this.three = null;
2016-02-10 19:59:51 +01:00
}
return countCurrent() == 0;
}
}
}
}
return false;
}
2022-01-20 21:01:38 +01:00
@SuppressWarnings("unchecked")
2016-02-10 19:59:51 +01:00
public void recalculateSkip() {
QuadMap<T> map = null;
for (QuadMap<T> current : new QuadMap[]{this.one, this.two, this.three, this.four}) {
2016-02-10 19:59:51 +01:00
if (current != null) {
if (map != null) {
this.skip = null;
return;
}
map = current;
}
}
this.skip = map.skip == null ? map : map.skip;
}
2016-03-23 18:16:05 +01:00
public Set<T> get(CuboidRegion region) {
2016-02-10 19:59:51 +01:00
HashSet<T> set = new HashSet<>();
2016-03-23 18:16:05 +01:00
if (this.objects != null) {
for (T obj : this.objects) {
if (RegionUtil.intersects(getRegion(obj), region)) {
2016-02-10 19:59:51 +01:00
set.add(obj);
}
}
}
2016-03-23 18:16:05 +01:00
if (this.skip != null) {
if (this.skip.intersects(region)) {
set.addAll(this.skip.get(region));
2016-02-10 19:59:51 +01:00
}
} else {
2016-03-23 18:16:05 +01:00
if (this.one != null && this.one.intersects(region)) {
set.addAll(this.one.get(region));
2016-02-10 19:59:51 +01:00
}
2016-03-23 18:16:05 +01:00
if (this.two != null && this.two.intersects(region)) {
set.addAll(this.two.get(region));
2016-02-10 19:59:51 +01:00
}
2016-03-23 18:16:05 +01:00
if (this.three != null && this.three.intersects(region)) {
set.addAll(this.three.get(region));
2016-02-10 19:59:51 +01:00
}
2016-03-23 18:16:05 +01:00
if (this.four != null && this.four.intersects(region)) {
set.addAll(this.four.get(region));
2016-02-10 19:59:51 +01:00
}
}
return set;
}
2016-03-23 18:16:05 +01:00
public boolean intersects(CuboidRegion other) {
Pull/2693 (#2694) * Commit WIP flag work. * More ported flag types, and additions to the flag API. * Make PlotFlag more generic to allow generic flag creation * Pull Captions methods into a Caption interface. * Port MusicFlag * Port flight flag * Port UntrustedVisitFlag * Port DenyExitFlag * Remove paper suggestion * Make ListFlag lists immutable * Update Flag containers. Add javadocs. Add missing methods. * Port description flag * Port greeting and farewell flags * Port weather flag * Move getExample implementation to BooleanFlag * Port reserved flags * Port all boolean flags. * Remove unused flag types * Invert liquid-flow flag * Find the real (legacy) flag name * Change NOITFY -> NOTIFY in Captions * Make IntegerFlag extendable * Port integer flags * Update Flag command to current API state * Begin remaking flag command * Create DoubleFlag + extract common parsing stuff * Supply arguments in flag parse exceptions * Implement missing flag subcommands * Update Flag command to current API state * Implement PriceFlag * Port deny-teleport * Port gamemode flags * Port BreakFlag * Port PlaceFlag * Port UseFlag * Remove old unused flag constants * Port blocked-cmds flag * Fix entity util * Port TimeFlag * Use CaptionUtility for formatting * Port keep flag * Fix imports * Reformat code * Remove unused classes * Fix MainUtil.java * Remove FlagCmd * Add flag info header and footer * Comment out flag related stuff in SchematicHandler * Remove FlagManager * Finalize Plot.java * Finalize PlotArea.java * Finalize PlotListener * Fix API issues * Fix a bunch of compile errors * Fix `/plot flag remove` * Fix initialization of GlobalFlagContainer * Apply API changes to events * Update SQLManager to new API * Invert default value for DenyExitFlag * Replace flag.getValue().toString() with flag.toString() * Make FlagContainer instance in Plot final * Fix various command issues * Clean up PlotSettings * Don't show internal flags in flag list * Fix `/plot flag add` * Remove the info inventory as it's 100% broken * Add plot info entries and fix up the default format * Fix default flag state in Captions * 781c200 part 2 * Fix odd grammar in captions * Fix odd grammar in captions v2 * Add create table statements for plot_flags * Remove old flag references in SQLManager * Use the new plot_flags table * Add tab completion to `/plot flag` * Improve parse error handling * Make flag permission check recognize parse exceptions * Initial progress towards flag conversion * Fix minor issues * Don't validate flags during flag conversion * Allow unrecognized flags to be parsed * Filter out internal flags from command sugguestions * Use the wrong caption when there's no plot description set * Limit command suggestions for boolean flags * Make blocktypelistflags accept blockcategories * Require categories to be prefixed with '#' and fix some minor display issues * Fix plot database conversion * Update PlotFlagEvent.java Updated return description * Fix command annotation wrapping * Add FLAG_UPDATE event for FlagContainer listeners * Make getParentContainer nullable * Document castUnsafe in FlagContainer * Document FlagContainer constructors * Add missing documentation to FlagContainer * Document FlagParseException * Fix wording in FlagContainer javadoc * Document InternalFlag * Document PlotFlag * Minor changes * Remove revisit comments Co-authored-by: Hannes Greule <SirYwell@users.noreply.github.com> Co-authored-by: NotMyFault <mc.cache@web.de> Co-authored-by: Matt <4009945+MattBDev@users.noreply.github.com>
2020-02-24 18:42:02 +01:00
return (other.getMinimumPoint().getX() <= this.x + this.size) && (
other.getMaximumPoint().getX() >= this.x - this.size) && (other.getMinimumPoint().getZ()
<= this.z + this.size) && (other.getMaximumPoint().getZ() >= this.z - this.size);
2016-02-10 19:59:51 +01:00
}
public T get(int x, int z) {
2016-03-23 18:16:05 +01:00
if (this.objects != null) {
for (T obj : this.objects) {
if (RegionUtil.contains(getRegion(obj), x, z)) {
2016-02-10 19:59:51 +01:00
return obj;
}
}
}
2016-03-23 18:16:05 +01:00
if (this.skip != null) {
return this.skip.get(x, z);
2016-02-10 19:59:51 +01:00
} else {
if (x >= this.x) {
if (z >= this.z) {
2016-03-23 18:16:05 +01:00
if (this.one != null) {
return this.one.get(x, z);
2016-02-10 19:59:51 +01:00
}
} else {
2016-03-23 18:16:05 +01:00
if (this.two != null) {
return this.two.get(x, z);
2016-02-10 19:59:51 +01:00
}
}
} else {
if (z >= this.z) {
2016-03-23 18:16:05 +01:00
if (this.four != null) {
return this.four.get(x, z);
2016-02-10 19:59:51 +01:00
}
} else {
2016-03-23 18:16:05 +01:00
if (this.three != null) {
return this.three.get(x, z);
2016-02-10 19:59:51 +01:00
}
}
}
}
return null;
}
2016-02-10 19:59:51 +01:00
}