minecraft-source/src/net/minecraft/world/level/levelgen/Heightmap.java

181 lines
7.1 KiB
Java

package net.minecraft.world.level.levelgen;
import net.minecraft.Util;
import com.google.common.collect.Maps;
import net.minecraft.world.level.block.LeavesBlock;
import java.util.HashMap;
import java.util.Map;
import java.util.Iterator;
import it.unimi.dsi.fastutil.objects.ObjectListIterator;
import it.unimi.dsi.fastutil.objects.ObjectList;
import net.minecraft.world.level.block.Blocks;
import net.minecraft.core.BlockPos;
import it.unimi.dsi.fastutil.objects.ObjectArrayList;
import java.util.Set;
import net.minecraft.world.level.chunk.ChunkAccess;
import net.minecraft.util.BitStorage;
import net.minecraft.world.level.block.state.BlockState;
import java.util.function.Predicate;
public class Heightmap {
private static final Predicate<BlockState> NOT_AIR;
private static final Predicate<BlockState> MATERIAL_MOTION_BLOCKING;
private final BitStorage data;
private final Predicate<BlockState> isOpaque;
private final ChunkAccess chunk;
public Heightmap(final ChunkAccess bzv, final Types a) {
this.data = new BitStorage(9, 256);
this.isOpaque = a.isOpaque();
this.chunk = bzv;
}
public static void primeHeightmaps(final ChunkAccess bzv, final Set<Types> set) {
final int integer3 = set.size();
final ObjectList<Heightmap> objectList4 = (ObjectList<Heightmap>)new ObjectArrayList(integer3);
final ObjectListIterator<Heightmap> objectListIterator5 = (ObjectListIterator<Heightmap>)objectList4.iterator();
final int integer4 = bzv.getHighestSectionPosition() + 16;
try (final BlockPos.PooledMutableBlockPos b7 = BlockPos.PooledMutableBlockPos.acquire()) {
for (int integer5 = 0; integer5 < 16; ++integer5) {
for (int integer6 = 0; integer6 < 16; ++integer6) {
for (final Types a12 : set) {
objectList4.add(bzv.getOrCreateHeightmapUnprimed(a12));
}
for (int integer7 = integer4 - 1; integer7 >= 0; --integer7) {
b7.set(integer5, integer7, integer6);
final BlockState byg12 = bzv.getBlockState(b7);
if (byg12.getBlock() != Blocks.AIR) {
while (objectListIterator5.hasNext()) {
final Heightmap cbs13 = (Heightmap)objectListIterator5.next();
if (cbs13.isOpaque.test(byg12)) {
cbs13.setHeight(integer5, integer6, integer7 + 1);
objectListIterator5.remove();
}
}
if (objectList4.isEmpty()) {
break;
}
objectListIterator5.back(integer3);
}
}
}
}
}
}
public boolean update(final int integer1, final int integer2, final int integer3, final BlockState byg) {
final int integer4 = this.getFirstAvailable(integer1, integer3);
if (integer2 <= integer4 - 2) {
return false;
}
if (this.isOpaque.test(byg)) {
if (integer2 >= integer4) {
this.setHeight(integer1, integer3, integer2 + 1);
return true;
}
}
else if (integer4 - 1 == integer2) {
final BlockPos.MutableBlockPos a7 = new BlockPos.MutableBlockPos();
for (int integer5 = integer2 - 1; integer5 >= 0; --integer5) {
a7.set(integer1, integer5, integer3);
if (this.isOpaque.test(this.chunk.getBlockState(a7))) {
this.setHeight(integer1, integer3, integer5 + 1);
return true;
}
}
this.setHeight(integer1, integer3, 0);
return true;
}
return false;
}
public int getFirstAvailable(final int integer1, final int integer2) {
return this.getFirstAvailable(getIndex(integer1, integer2));
}
private int getFirstAvailable(final int integer) {
return this.data.get(integer);
}
private void setHeight(final int integer1, final int integer2, final int integer3) {
this.data.set(getIndex(integer1, integer2), integer3);
}
public void setRawData(final long[] arr) {
System.arraycopy(arr, 0, this.data.getRaw(), 0, arr.length);
}
public long[] getRawData() {
return this.data.getRaw();
}
private static int getIndex(final int integer1, final int integer2) {
return integer1 + integer2 * 16;
}
static {
NOT_AIR = (byg -> !byg.isAir());
MATERIAL_MOTION_BLOCKING = (byg -> byg.getMaterial().blocksMotion());
}
public enum Usage {
WORLDGEN,
LIVE_WORLD,
CLIENT;
}
public enum Types {
WORLD_SURFACE_WG("WORLD_SURFACE_WG", Usage.WORLDGEN, (Predicate<BlockState>)Heightmap.NOT_AIR),
WORLD_SURFACE("WORLD_SURFACE", Usage.CLIENT, (Predicate<BlockState>)Heightmap.NOT_AIR),
OCEAN_FLOOR_WG("OCEAN_FLOOR_WG", Usage.WORLDGEN, (Predicate<BlockState>)Heightmap.MATERIAL_MOTION_BLOCKING),
OCEAN_FLOOR("OCEAN_FLOOR", Usage.LIVE_WORLD, (Predicate<BlockState>)Heightmap.MATERIAL_MOTION_BLOCKING),
MOTION_BLOCKING("MOTION_BLOCKING", Usage.CLIENT, byg -> byg.getMaterial().blocksMotion() || !byg.getFluidState().isEmpty()),
MOTION_BLOCKING_NO_LEAVES("MOTION_BLOCKING_NO_LEAVES", Usage.LIVE_WORLD, byg -> (byg.getMaterial().blocksMotion() || !byg.getFluidState().isEmpty()) && !(byg.getBlock() instanceof LeavesBlock));
private final String serializationKey;
private final Usage usage;
private final Predicate<BlockState> isOpaque;
private static final Map<String, Types> REVERSE_LOOKUP;
private Types(final String string3, final Usage b, final Predicate<BlockState> predicate) {
this.serializationKey = string3;
this.usage = b;
this.isOpaque = predicate;
}
public String getSerializationKey() {
return this.serializationKey;
}
public boolean sendToClient() {
return this.usage == Usage.CLIENT;
}
public boolean keepAfterWorldgen() {
return this.usage != Usage.WORLDGEN;
}
public static Types getFromKey(final String string) {
return Types.REVERSE_LOOKUP.get(string);
}
public Predicate<BlockState> isOpaque() {
return this.isOpaque;
}
static {
final Types[] array;
int length;
int i = 0;
Types a5;
REVERSE_LOOKUP = Util.<Map<String, Types>>make(Maps.newHashMap(), hashMap -> {
values();
for (length = array.length; i < length; ++i) {
a5 = array[i];
hashMap.put(a5.serializationKey, a5);
}
});
}
}
}