From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 From: Ivan Pekov Date: Thu, 27 Aug 2020 10:46:17 +0300 Subject: [PATCH] Highly optimize VillagePlace filtering Replaced all streams I could. I expect this to be dropped in the next major release and reimplemented again if mojang changes stuff with villagers again. diff --git a/src/main/java/me/jellysquid/mods/lithium/common/util/Producer.java b/src/main/java/me/jellysquid/mods/lithium/common/util/Producer.java new file mode 100644 index 0000000000000000000000000000000000000000..e647624f4c9afe8bc603792ad88c807ed9f01250 --- /dev/null +++ b/src/main/java/me/jellysquid/mods/lithium/common/util/Producer.java @@ -0,0 +1,53 @@ +package me.jellysquid.mods.lithium.common.util; + +import java.util.List; +import java.util.Spliterator; +import java.util.Spliterators; +import java.util.function.Consumer; +import java.util.function.Function; +import java.util.stream.Stream; +import java.util.stream.StreamSupport; +import org.yatopiamc.yatopia.server.util.HoldingConsumer; + +public interface Producer { + /** + * Computes the next sequence of values in a collection. If a null value is passed for {@param consumer}, then + * the producer will only return whether or not elements existed. + * + * @param consumer The (nullable) consumer which will accept the computed values during this run. + * @return True if the producer produced any values, otherwise false + */ + boolean computeNext(Consumer consumer); + + default Producer map(Function mapper) { + return consumer -> { + Consumer con = (t) -> consumer.accept(mapper.apply(t)); + return Producer.this.computeNext(con); + }; + } + + static Stream asStream(Producer producer) { + return StreamSupport.stream(new Spliterators.AbstractSpliterator(Long.MAX_VALUE, Spliterator.ORDERED | Spliterator.NONNULL) { + @Override + public boolean tryAdvance(Consumer action) { + return producer.computeNext(action); + } + }, false); + } + + static void fillList(Producer producer, List list) { + HoldingConsumer consumer = new HoldingConsumer<>(); + while (producer.computeNext(consumer)) { + T value = consumer.getValue(); + if (value == null || list.contains(value)) { continue; } + list.add(value); + } + } + + Producer EMPTY_PRODUCER = consumer -> false; + + @SuppressWarnings("unchecked") + static Producer empty() { + return (Producer) EMPTY_PRODUCER; + } +} diff --git a/src/main/java/net/minecraft/server/BlockPosition.java b/src/main/java/net/minecraft/server/BlockPosition.java index 6fcc7ed7c129e6a33386d65b37cbba4a44e96f0f..aac055489291cd742bbbfd0aeb0b8face4040e17 100644 --- a/src/main/java/net/minecraft/server/BlockPosition.java +++ b/src/main/java/net/minecraft/server/BlockPosition.java @@ -341,6 +341,16 @@ public class BlockPosition extends BaseBlockPosition { return a(MathHelper.floor(axisalignedbb.minX), MathHelper.floor(axisalignedbb.minY), MathHelper.floor(axisalignedbb.minZ), MathHelper.floor(axisalignedbb.maxX), MathHelper.floor(axisalignedbb.maxY), MathHelper.floor(axisalignedbb.maxZ)); } + // Yatopia start + public static java.util.List getPositions(int i, int j, int k, int l, int i1, int j1) { + java.util.List ret = new java.util.ArrayList<>(); + Iterable iterable = b(i, j, k, l, i1, j1); + org.yatopiamc.yatopia.server.util.HoldingConsumer consumer = new org.yatopiamc.yatopia.server.util.HoldingConsumer<>(); + java.util.Spliterator spliterator = iterable.spliterator(); + while (spliterator.tryAdvance(consumer)) ret.add(consumer.getValue()); + return ret; + } + // Yatopia end public static Stream a(int i, int j, int k, int l, int i1, int j1) { return StreamSupport.stream(b(i, j, k, l, i1, j1).spliterator(), false); } diff --git a/src/main/java/net/minecraft/server/ChunkCoordIntPair.java b/src/main/java/net/minecraft/server/ChunkCoordIntPair.java index 271fddbbf73ca5c0e4e2722d7246c14b778d6072..860943989b10a4f65c0de345a56aaa00f0959214 100644 --- a/src/main/java/net/minecraft/server/ChunkCoordIntPair.java +++ b/src/main/java/net/minecraft/server/ChunkCoordIntPair.java @@ -118,6 +118,15 @@ public class ChunkCoordIntPair { return a(new ChunkCoordIntPair(chunkcoordintpair.x - i, chunkcoordintpair.z - i), new ChunkCoordIntPair(chunkcoordintpair.x + i, chunkcoordintpair.z + i)); } + // Yatopia start + public static java.util.List streamList(ChunkCoordIntPair center, int radius) { + return streamList(new ChunkCoordIntPair(center.x - radius, center.z - radius), new ChunkCoordIntPair(center.x + radius, center.z + radius)); + } + public static java.util.List streamList(ChunkCoordIntPair pos1, ChunkCoordIntPair pos2) { + return org.yatopiamc.yatopia.server.YatopiaChunkPos.asList(pos1, pos2); + } + // Yatopia end + public static Stream a(final ChunkCoordIntPair chunkcoordintpair, final ChunkCoordIntPair chunkcoordintpair1) { int i = Math.abs(chunkcoordintpair.x - chunkcoordintpair1.x) + 1; int j = Math.abs(chunkcoordintpair.z - chunkcoordintpair1.z) + 1; diff --git a/src/main/java/net/minecraft/server/EntityBee.java b/src/main/java/net/minecraft/server/EntityBee.java index f73641ddb3e82bc653732105ef0a3d41a28e845f..cd9b52d0233caa6ad60b90e2049c6247f6e1954b 100644 --- a/src/main/java/net/minecraft/server/EntityBee.java +++ b/src/main/java/net/minecraft/server/EntityBee.java @@ -720,15 +720,19 @@ public class EntityBee extends EntityAnimal implements IEntityAngerable, EntityB private List j() { BlockPosition blockposition = EntityBee.this.getChunkCoordinates(); VillagePlace villageplace = ((WorldServer) EntityBee.this.world).y(); - Stream stream = villageplace.c((villageplacetype) -> { + List stream = villageplace.cListPositions((villageplacetype) -> { // Yatopia return villageplacetype == VillagePlaceType.t || villageplacetype == VillagePlaceType.u; - }, blockposition, 20, VillagePlace.Occupancy.ANY); - + }, (record) -> i(record.getPosition()), blockposition, 20, VillagePlace.Occupancy.ANY); // Yatopia + // Yatopia start + stream.sort(Comparator.comparingDouble((pos1) -> pos1.distanceSquared(blockposition))); + return stream; + /* return (List) stream.map(VillagePlaceRecord::f).filter((blockposition1) -> { return EntityBee.this.i(blockposition1); }).sorted(Comparator.comparingDouble((blockposition1) -> { return blockposition1.j(blockposition); })).collect(Collectors.toList()); + */ // Yatopia end } } diff --git a/src/main/java/net/minecraft/server/PersistentRaid.java b/src/main/java/net/minecraft/server/PersistentRaid.java index 826dcf9f7eedc3664d66170b97b2a19552a0dc60..81f9b2ec160a015ce7e82ba33dd684e0b3932877 100644 --- a/src/main/java/net/minecraft/server/PersistentRaid.java +++ b/src/main/java/net/minecraft/server/PersistentRaid.java @@ -68,7 +68,7 @@ public class PersistentRaid extends PersistentBase { return null; } else { BlockPosition blockposition = entityplayer.getChunkCoordinates(); - List list = (List) this.b.y().c(VillagePlaceType.b, blockposition, 64, VillagePlace.Occupancy.IS_OCCUPIED).collect(Collectors.toList()); + List list = this.b.y().cList(VillagePlaceType.b, blockposition, 64, VillagePlace.Occupancy.IS_OCCUPIED); // Yatopia int i = 0; Vec3D vec3d = Vec3D.ORIGIN; diff --git a/src/main/java/net/minecraft/server/SectionPosition.java b/src/main/java/net/minecraft/server/SectionPosition.java index f95925f1c5d091f1a129d0437bb6e175c6ac080f..11ba5c18d761f6cc76faa3e0f5de3d5b4175749d 100644 --- a/src/main/java/net/minecraft/server/SectionPosition.java +++ b/src/main/java/net/minecraft/server/SectionPosition.java @@ -159,6 +159,7 @@ public class SectionPosition extends BaseBlockPosition { return this.p().b(8, 8, 8); } + public final ChunkCoordIntPair asChunkPos() { return r(); } // Yatopia - OBFHELPER public ChunkCoordIntPair r() { return new ChunkCoordIntPair(this.a(), this.c()); } @@ -173,10 +174,12 @@ public class SectionPosition extends BaseBlockPosition { return (((long) i & 4194303L) << 42) | (((long) j & 1048575L)) | (((long) k & 4194303L) << 20); // Paper - Simplify to reduce instruction count } + public final long asLong() { return s(); } // Yatopia - OBFHELPER public long s() { return (((long) getX() & 4194303L) << 42) | (((long) getY() & 1048575L)) | (((long) getZ() & 4194303L) << 20); // Paper - Simplify to reduce instruction count } + public java.util.List tList() { return BlockPosition.getPositions(d(), e(), f(), g(), h(), i()); } // Yatopia public Stream t() { return BlockPosition.a(this.d(), this.e(), this.f(), this.g(), this.h(), this.i()); } @@ -189,6 +192,18 @@ public class SectionPosition extends BaseBlockPosition { return a(chunkcoordintpair.x - i, 0, chunkcoordintpair.z - i, chunkcoordintpair.x + i, 15, chunkcoordintpair.z + i); // Paper - simplify/inline } + // Yatopia start + public static java.util.List getPosList(SectionPosition pos, int i) { + return getPosList(pos.getX() - i, pos.getY() - i, pos.getZ() - i, pos.getX() + i, pos.getY() + i, pos.getZ() + i); + } + public static java.util.List getPosList(ChunkCoordIntPair chunkPos, int i) { + return getPosList(chunkPos.x - i, 0, chunkPos.z - i, chunkPos.x + i, 15, chunkPos.z + i); + } + public static java.util.List getPosList(int i, int j, int k, int l, int i1, int j1) { + return org.yatopiamc.yatopia.server.YatopiaChunkSectionPos.getChunkSectionPosList(i, j, k, l, i1, j1); + } + // Yatopia end + public static Stream a(final int i, final int j, final int k, final int l, final int i1, final int j1) { return StreamSupport.stream(new AbstractSpliterator((long) ((l - i + 1) * (i1 - j + 1) * (j1 - k + 1)), 64) { final CursorPosition a = new CursorPosition(i, j, k, l, i1, j1); diff --git a/src/main/java/net/minecraft/server/VillagePlace.java b/src/main/java/net/minecraft/server/VillagePlace.java index 3c9668c9c30ea57c1608e32ece27ec56d580fc62..cd9c619dd038abafede98703946d37e53595af73 100644 --- a/src/main/java/net/minecraft/server/VillagePlace.java +++ b/src/main/java/net/minecraft/server/VillagePlace.java @@ -46,7 +46,7 @@ public class VillagePlace extends RegionFileSection { } public long a(Predicate predicate, BlockPosition blockposition, int i, VillagePlace.Occupancy villageplace_occupancy) { - return this.c(predicate, blockposition, i, villageplace_occupancy).count(); + return this.cList(predicate, blockposition, i, villageplace_occupancy).size(); // Yatopia } public boolean a(VillagePlaceType villageplacetype, BlockPosition blockposition) { @@ -67,6 +67,39 @@ public class VillagePlace extends RegionFileSection { }); } + // Yatopia start + public java.util.List bList(Predicate filter, BlockPosition pos, int i, VillagePlace.Occupancy occupancy) { + int j = org.apache.commons.math3.util.FastMath.floorDiv(i, 16) + 1; + + java.util.List list = ChunkCoordIntPair.streamList(new ChunkCoordIntPair(pos), j); + java.util.List ret = new java.util.ArrayList<>(); + for (ChunkCoordIntPair chunkPos : list) { + for (int k = 0; k < 16; k++) { // ITS THE LAW + this.d(SectionPosition.a(chunkPos, k).asLong()).ifPresent(section -> ret.addAll(section.aList(filter, occupancy))); + } + } + return ret; + } + public java.util.List cList(Predicate predicate, BlockPosition pos, int i, VillagePlace.Occupancy occupancy) { + int j = i * i; + java.util.List ret = new java.util.ArrayList<>(); + for (VillagePlaceRecord record : this.bList(predicate, pos, i, occupancy)) { + if (record.getPosition().distanceSquared(pos) <= j) { ret.add(record); } + } + return ret; + } + + public java.util.List cListPositions(Predicate predicate, Predicate recordFilter, BlockPosition pos, int i, VillagePlace.Occupancy occupancy) { + int j = i * i; + java.util.List ret = new java.util.ArrayList<>(); + for (VillagePlaceRecord record : this.bList(predicate, pos, i, occupancy)) { + BlockPosition recordPosition = record.getPosition(); + if (recordPosition.distanceSquared(pos) <= j && recordFilter.test(record)) { ret.add(recordPosition); } + } + return ret; + } + // Yatopia end + public Stream c(Predicate predicate, BlockPosition blockposition, int i, VillagePlace.Occupancy villageplace_occupancy) { int j = i * i; @@ -83,10 +116,28 @@ public class VillagePlace extends RegionFileSection { }); } + // Yatopia start + public java.util.List aList(Predicate predicate, Predicate posFilter, BlockPosition pos, int i, VillagePlace.Occupancy occupancy) { + java.util.List ret = new java.util.ArrayList<>(); + int j = i * i; + for (VillagePlaceRecord record : this.bList(predicate, pos, i, occupancy)) { + BlockPosition recordPosition = record.getPosition(); + if (recordPosition.distanceSquared(pos) <= j && posFilter.test(recordPosition)) { ret.add(recordPosition); } + } + return ret; + } + // Yatopia end public Stream a(Predicate predicate, Predicate predicate1, BlockPosition blockposition, int i, VillagePlace.Occupancy villageplace_occupancy) { return this.c(predicate, blockposition, i, villageplace_occupancy).map(VillagePlaceRecord::f).filter(predicate1); } + // Yatopia start + public java.util.List bList(Predicate predicate, Predicate posFilter, BlockPosition pos, int i, VillagePlace.Occupancy occupancy) { + java.util.List ret = aList(predicate, posFilter, pos, i, occupancy); + ret.sort(Comparator.comparingDouble((pos1) -> pos1.distanceSquared(pos))); + return ret; + } + // Yatopia end public Stream b(Predicate predicate, Predicate predicate1, BlockPosition blockposition, int i, VillagePlace.Occupancy villageplace_occupancy) { return this.a(predicate, predicate1, blockposition, i, villageplace_occupancy).sorted(Comparator.comparingDouble((blockposition1) -> { return blockposition1.j(blockposition); @@ -94,31 +145,68 @@ public class VillagePlace extends RegionFileSection { } public Optional c(Predicate predicate, Predicate predicate1, BlockPosition blockposition, int i, VillagePlace.Occupancy villageplace_occupancy) { - return this.a(predicate, predicate1, blockposition, i, villageplace_occupancy).findFirst(); + // Yatopia start + for (VillagePlaceRecord record : this.cList(predicate, blockposition, i, villageplace_occupancy)) { + BlockPosition recordPosition = record.getPosition(); + if (predicate1.test(recordPosition)) return Optional.of(recordPosition); + } + return Optional.empty(); + // Yatopia end } public Optional d(Predicate predicate, BlockPosition blockposition, int i, VillagePlace.Occupancy villageplace_occupancy) { + // Yatopia start + VillagePlaceRecord best = null; + for (VillagePlaceRecord record : cList(predicate, blockposition, i, villageplace_occupancy)) { + BlockPosition recordPos = record.getPosition(); + if (best == null || (recordPos.distanceSquared(blockposition) < best.getPosition().distanceSquared(blockposition))) { + best = record; + } + } + return best == null ? Optional.empty() : Optional.of(best.getPosition()); + /* return this.c(predicate, blockposition, i, villageplace_occupancy).map(VillagePlaceRecord::f).min(Comparator.comparingDouble((blockposition1) -> { return blockposition1.j(blockposition); })); + */ // Yatopia end } public Optional a(Predicate predicate, Predicate predicate1, BlockPosition blockposition, int i) { + // Yatopia start + int j = i * i; + for (VillagePlaceRecord record : this.bList(predicate, blockposition, i, VillagePlace.Occupancy.HAS_SPACE)) { + BlockPosition recordPos = record.getPosition(); + if (recordPos.distanceSquared(blockposition) <= j && predicate1.test(recordPos)) { + record.b(); + return Optional.of(recordPos); + } + } + return Optional.empty(); + /* return this.c(predicate, blockposition, i, VillagePlace.Occupancy.HAS_SPACE).filter((villageplacerecord) -> { return predicate1.test(villageplacerecord.f()); }).findFirst().map((villageplacerecord) -> { villageplacerecord.b(); return villageplacerecord.f(); }); + */ // Yatopia end } public Optional a(Predicate predicate, Predicate predicate1, VillagePlace.Occupancy villageplace_occupancy, BlockPosition blockposition, int i, Random random) { - List list = (List) this.c(predicate, blockposition, i, villageplace_occupancy).collect(Collectors.toList()); + List list = this.cList(predicate, blockposition, i, villageplace_occupancy); // Yatopia Collections.shuffle(list, random); + // Yatopia start - replace stream + for (VillagePlaceRecord record : list) { + BlockPosition recordPosition = record.getPosition(); + if (predicate1.test(recordPosition)) return Optional.of(recordPosition); + } + return Optional.empty(); + /* return list.stream().filter((villageplacerecord) -> { return predicate1.test(villageplacerecord.f()); }).findFirst().map(VillagePlaceRecord::f); + */ // Yatopia end } public boolean b(BlockPosition blockposition) { @@ -211,7 +299,7 @@ public class VillagePlace extends RegionFileSection { } private void a(ChunkSection chunksection, SectionPosition sectionposition, BiConsumer biconsumer) { - sectionposition.t().forEach((blockposition) -> { + sectionposition.tList().forEach((blockposition) -> { // Yatopia IBlockData iblockdata = chunksection.getType(SectionPosition.b(blockposition.getX()), SectionPosition.b(blockposition.getY()), SectionPosition.b(blockposition.getZ())); VillagePlaceType.b(iblockdata).ifPresent((villageplacetype) -> { @@ -221,6 +309,16 @@ public class VillagePlace extends RegionFileSection { } public void a(IWorldReader iworldreader, BlockPosition blockposition, int i) { + // Yatopia start - WHY? + java.util.List posList = SectionPosition.getPosList(new ChunkCoordIntPair(blockposition), org.apache.commons.math3.util.FastMath.floorDiv(i, 16)); + for (SectionPosition pos : posList) { + boolean shouldContinue = this.d(pos.asLong()).map(VillagePlaceSection::a).orElse(false); + if (shouldContinue) { + ChunkCoordIntPair chunkPos = pos.asChunkPos(); + if (b.add(chunkPos.pair())) { iworldreader.getChunkAt(chunkPos.x, chunkPos.z, ChunkStatus.EMPTY); } + } + } + /* SectionPosition.b(new ChunkCoordIntPair(blockposition), Math.floorDiv(i, 16)).map((sectionposition) -> { return Pair.of(sectionposition, this.d(sectionposition.s())); }).filter((pair) -> { @@ -232,6 +330,7 @@ public class VillagePlace extends RegionFileSection { }).forEach((chunkcoordintpair) -> { iworldreader.getChunkAt(chunkcoordintpair.x, chunkcoordintpair.z, ChunkStatus.EMPTY); }); + */ // Yatopia end } final class a extends LightEngineGraphSection { diff --git a/src/main/java/net/minecraft/server/VillagePlaceSection.java b/src/main/java/net/minecraft/server/VillagePlaceSection.java index f43bc1f7d693d63c6bbdba976c048d2d0c8767b1..15d2b2c21e61369b5c7897914ccf0aa950f44668 100644 --- a/src/main/java/net/minecraft/server/VillagePlaceSection.java +++ b/src/main/java/net/minecraft/server/VillagePlaceSection.java @@ -5,6 +5,10 @@ import com.google.common.collect.Maps; import com.google.common.collect.Sets; import com.mojang.serialization.Codec; import com.mojang.serialization.codecs.RecordCodecBuilder; +// Yatopia start +import it.unimi.dsi.fastutil.objects.ObjectOpenHashSet; +import it.unimi.dsi.fastutil.objects.Reference2ReferenceOpenHashMap; +// Yatopia end import it.unimi.dsi.fastutil.shorts.Short2ObjectMap; import it.unimi.dsi.fastutil.shorts.Short2ObjectOpenHashMap; import java.util.List; @@ -49,12 +53,23 @@ public class VillagePlaceSection { private VillagePlaceSection(Runnable runnable, boolean flag, List list) { this.b = new Short2ObjectOpenHashMap(); - this.c = Maps.newHashMap(); + this.c = new Reference2ReferenceOpenHashMap<>(); // Yatopia this.d = runnable; this.e = flag; list.forEach(this::a); } + // Yatopia start + public java.util.List aList(Predicate predicate, VillagePlace.Occupancy occupancy) { + java.util.List ret = new java.util.ArrayList<>(); + for (Map.Entry> entry : c.entrySet()) { + if (predicate.test(entry.getKey())) { + for (VillagePlaceRecord record : entry.getValue()) { if (occupancy.a().test(record)) ret.add(record); } + } + } + return ret; + } + // Yatopia end public Stream a(Predicate predicate, VillagePlace.Occupancy villageplace_occupancy) { return this.c.entrySet().stream().filter((entry) -> { return predicate.test(entry.getKey()); @@ -90,7 +105,7 @@ public class VillagePlaceSection { } else { this.b.put(short0, villageplacerecord); ((Set) this.c.computeIfAbsent(villageplacetype, (villageplacetype1) -> { - return Sets.newHashSet(); + return new ObjectOpenHashSet<>(); // Yatopia })).add(villageplacerecord); return true; } diff --git a/src/main/java/org/yatopiamc/yatopia/server/YatopiaChunkPos.java b/src/main/java/org/yatopiamc/yatopia/server/YatopiaChunkPos.java new file mode 100644 index 0000000000000000000000000000000000000000..de95cf5ca20abdc8f200806287fb0ba03eec1e7c --- /dev/null +++ b/src/main/java/org/yatopiamc/yatopia/server/YatopiaChunkPos.java @@ -0,0 +1,54 @@ +package org.yatopiamc.yatopia.server; + +import java.util.ArrayList; +import java.util.List; +import java.util.function.Consumer; +import me.jellysquid.mods.lithium.common.util.Producer; +import net.minecraft.server.ChunkCoordIntPair; + +public class YatopiaChunkPos { + + public static List asList(ChunkCoordIntPair pos1, ChunkCoordIntPair pos2) { + List list = new ArrayList<>(); + Producer.fillList(getStreamProducer(pos1, pos2), list); + return list; + } + + /** + * [VanillaCopy] but in a producer + * + * @param pos1 pos 1 + * @param pos2 pos 2 + * @return producer + */ + private static Producer getStreamProducer(ChunkCoordIntPair pos1, ChunkCoordIntPair pos2) { + final int k = pos1.x < pos2.x ? 1 : -1; + final int l = pos1.z < pos2.z ? 1 : -1; + + return new Producer() { + private ChunkCoordIntPair pair = null; + + @Override + public boolean computeNext(Consumer consumer) { + if (pair == null) { + pair = pos1; + } else { + int i1 = this.pair.x; + int j1 = this.pair.z; + + if (i1 == pos2.x) { + if (j1 == pos2.z) { + return false; + } + + this.pair = new ChunkCoordIntPair(pos1.x, j1 + l); + } else { + this.pair = new ChunkCoordIntPair(i1 + k, j1); + } + } + consumer.accept(pair); + return true; + } + }; + } +} diff --git a/src/main/java/org/yatopiamc/yatopia/server/YatopiaChunkSectionPos.java b/src/main/java/org/yatopiamc/yatopia/server/YatopiaChunkSectionPos.java new file mode 100644 index 0000000000000000000000000000000000000000..d298cf985def6d7adcc6156b1476f86c085ad5e7 --- /dev/null +++ b/src/main/java/org/yatopiamc/yatopia/server/YatopiaChunkSectionPos.java @@ -0,0 +1,32 @@ +package org.yatopiamc.yatopia.server; + +import java.util.ArrayList; +import java.util.List; +import java.util.function.Consumer; +import me.jellysquid.mods.lithium.common.util.Producer; +import net.minecraft.server.CursorPosition; +import net.minecraft.server.SectionPosition; + +public class YatopiaChunkSectionPos { + + public static List getChunkSectionPosList(int i, int j, int k, int l, int i1, int j1) { + List list = new ArrayList<>(); + Producer.fillList(getChunkSectionPosProducer(i, j, k, l, i1, j1), list); + return list; + } + + private static Producer getChunkSectionPosProducer(int i, int j, int k, int l, int i1, int j1) { + return new Producer() { + final CursorPosition cursorPos = new CursorPosition(i, j, k, l, i1, j1); + + @Override + public boolean computeNext(Consumer consumer) { + if (cursorPos.a()) { + consumer.accept(SectionPosition.a(cursorPos.b(), cursorPos.c(), cursorPos.d())); + return true; + } + return false; + } + }; + } +} diff --git a/src/main/java/org/yatopiamc/yatopia/server/util/HoldingConsumer.java b/src/main/java/org/yatopiamc/yatopia/server/util/HoldingConsumer.java new file mode 100644 index 0000000000000000000000000000000000000000..adcbe5a009ef8156945b48c4d29d171ebffc4bec --- /dev/null +++ b/src/main/java/org/yatopiamc/yatopia/server/util/HoldingConsumer.java @@ -0,0 +1,17 @@ +package org.yatopiamc.yatopia.server.util; + +import java.util.function.Consumer; + +public class HoldingConsumer implements Consumer { + + private T value; + + @Override + public void accept(T t) { + this.value = t; + } + + public T getValue() { + return value; + } +}