diff --git a/Core/src/main/java/fr/pandacube/lib/core/util/IteratorIterator.java b/Core/src/main/java/fr/pandacube/lib/core/util/IteratorIterator.java new file mode 100644 index 0000000..b1cb99c --- /dev/null +++ b/Core/src/main/java/fr/pandacube/lib/core/util/IteratorIterator.java @@ -0,0 +1,65 @@ +package fr.pandacube.lib.core.util; + +import java.util.ArrayList; +import java.util.Arrays; +import java.util.Collection; +import java.util.Iterator; +import java.util.NoSuchElementException; + +public class IteratorIterator implements Iterator { + + public static IteratorIterator ofCollectionOfIterable(Collection> coll) { + return new IteratorIterator<>(coll.stream().map(i -> i.iterator()).iterator()); + } + + public static IteratorIterator ofCollectionOfIterator(Collection> coll) { + return new IteratorIterator<>(new ArrayList<>(coll).iterator()); + } + + @SafeVarargs + public static IteratorIterator ofArrayOfIterable(Iterable... arr) { + return new IteratorIterator<>(Arrays.stream(arr).map(i -> i.iterator()).iterator()); + } + + @SafeVarargs + public static IteratorIterator ofArrayOfIterator(Iterator... arr) { + return new IteratorIterator<>(Arrays.asList(arr).iterator()); + } + + private Iterator> iterators; + + private Iterator currentIterator = null; + + private IteratorIterator(Iterator> iterators) { + this.iterators = iterators; + } + + private void fixCurrentIterator() { + if (currentIterator != null && !currentIterator.hasNext()) { + currentIterator = null; + } + } + private void fixState() { + fixCurrentIterator(); + while (currentIterator == null) { + if (iterators.hasNext()) { + currentIterator = iterators.next(); + fixCurrentIterator(); + } + } + } + + @Override + public boolean hasNext() { + fixState(); + return currentIterator != null && currentIterator.hasNext(); + } + + @Override + public T next() { + if (!hasNext()) + throw new NoSuchElementException("No next value found in iterator."); + return currentIterator.next(); + } + +} diff --git a/Core/src/main/java/fr/pandacube/lib/core/util/RandomUtil.java b/Core/src/main/java/fr/pandacube/lib/core/util/RandomUtil.java index 8262be3..5a5aa16 100644 --- a/Core/src/main/java/fr/pandacube/lib/core/util/RandomUtil.java +++ b/Core/src/main/java/fr/pandacube/lib/core/util/RandomUtil.java @@ -42,5 +42,31 @@ public class RandomUtil { } throw new RuntimeException("Should never go to this line of code"); } + + /** + * Return a value between 0 and the number of parameter minus 1, using the provided frequencies. + * + * The probability of each value to be returned depends of the frequencies provided. + * @param frequencies the frequencies of each entries + * @return the index of an entry, or -1 if it is unable to pick anything (all the frequencies are 0 or there is not provided frequency) + */ + public static int randomIndexOfFrequencies(double... frequencies) { + if (frequencies == null) + return -1; + double sum = 0; + for (double f : frequencies) + sum += f; + if (sum == 0) + return -1; + double r = rand.nextDouble() * sum; + int i = -1; + double limit = frequencies[++i]; + while (i < frequencies.length) { + if (r < limit) + return i; + limit += frequencies[++i]; + } + return frequencies.length - 1; + } } diff --git a/Paper/src/main/java/fr/pandacube/lib/paper/util/AABBBlock.java b/Paper/src/main/java/fr/pandacube/lib/paper/util/AABBBlock.java index 6abb985..2723909 100644 --- a/Paper/src/main/java/fr/pandacube/lib/paper/util/AABBBlock.java +++ b/Paper/src/main/java/fr/pandacube/lib/paper/util/AABBBlock.java @@ -18,6 +18,10 @@ import fr.pandacube.lib.core.util.RandomUtil; public class AABBBlock implements Iterable { public final Vector pos1, pos2; + + private final Vector center; + + private final long volume; public AABBBlock(Vector p1, Vector p2) { this(p1.getBlockX(), p1.getBlockY(), p1.getBlockZ(), p2.getBlockX(), p2.getBlockY(), p2.getBlockZ()); @@ -36,12 +40,18 @@ public class AABBBlock implements Iterable { * Prends les points extérieurs permettant de former un bouding box englobant * celui représenté par v1 et v2, et étant aligné au quadrillage des blocs. */ - pos1 = new Vector(Math.min(p1x, p2x), - Math.min(p1y, p2y), - Math.min(p1z, p2z)); - pos2 = new Vector(Math.max(p1x, p2x) + 1, - Math.max(p1y, p2y) + 1, - Math.max(p1z, p2z) + 1); + int p1x_ = Math.min(p1x, p2x); + int p1y_ = Math.min(p1y, p2y); + int p1z_ = Math.min(p1z, p2z); + int p2x_ = Math.max(p1x, p2x) + 1; + int p2y_ = Math.max(p1y, p2y) + 1; + int p2z_ = Math.max(p1z, p2z) + 1; + pos1 = new Vector(p1x_, p1y_, p1z_); + pos2 = new Vector(p2x_, p2y_, p2z_); + + center = new Vector((p1x_ + p2x_) / 2d, (p1y_ + p2y_) / 2d, (p1z_ + p2z_) / 2d); + + volume = Math.abs(p2x_ - p1x_) * Math.abs(p2x_ - p1x_) * Math.abs(p2x_ - p1x_); } @@ -56,7 +66,11 @@ public class AABBBlock implements Iterable { } public Vector getCenter() { - return pos1.clone().add(pos2).multiply(0.5); + return center.clone(); + } + + public long getVolume() { + return volume; } public BoundingBox asBukkitBoundingBox() { diff --git a/Paper/src/main/java/fr/pandacube/lib/paper/util/AABBBlockGroup.java b/Paper/src/main/java/fr/pandacube/lib/paper/util/AABBBlockGroup.java new file mode 100644 index 0000000..052b4c4 --- /dev/null +++ b/Paper/src/main/java/fr/pandacube/lib/paper/util/AABBBlockGroup.java @@ -0,0 +1,62 @@ +package fr.pandacube.lib.paper.util; + +import java.util.ArrayList; +import java.util.Arrays; +import java.util.Collection; +import java.util.Collections; +import java.util.Iterator; +import java.util.List; + +import org.bukkit.Location; +import org.bukkit.entity.Entity; +import org.bukkit.util.BlockVector; +import org.bukkit.util.Vector; + +import fr.pandacube.lib.core.util.IteratorIterator; +import fr.pandacube.lib.core.util.RandomUtil; + +public class AABBBlockGroup implements Iterable { + + public final List aabbBlocks; + + public AABBBlockGroup(Collection in) { + aabbBlocks = Collections.unmodifiableList(new ArrayList<>(in)); + } + + public AABBBlockGroup(AABBBlock... in) { + aabbBlocks = Collections.unmodifiableList(Arrays.asList(in)); + } + + + public boolean isInside(Vector v) { + for (AABBBlock b : aabbBlocks) + if (b.isInside(v)) + return true; + return false; + } + public boolean isInside(Location l) { + return isInside(l.toVector()); + } + public boolean isInside(Entity p) { + return isInside(p.getLocation()); + } + + public Vector getRandomPosition() { + double[] freq = aabbBlocks.stream().mapToDouble(b -> b.getVolume()).toArray(); + int i = RandomUtil.randomIndexOfFrequencies(freq); + return aabbBlocks.get(i).getRandomPosition(); + } + + public long getVolume() { + long v = 0; + for (AABBBlock b : aabbBlocks) + v += b.getVolume(); + return v; + } + + @Override + public Iterator iterator() { + return IteratorIterator.ofCollectionOfIterator(aabbBlocks.stream().map(b -> b.iterator()).toList()); + } + +}