package com.bergerkiller.bukkit.common.reflection.classes; import java.util.List; import java.util.Map; import org.bukkit.craftbukkit.util.CraftMagicNumbers; import com.bergerkiller.bukkit.common.reflection.ClassTemplate; import com.bergerkiller.bukkit.common.reflection.FieldAccessor; import com.bergerkiller.bukkit.common.reflection.MethodAccessor; import com.bergerkiller.bukkit.common.reflection.NMSClassTemplate; import com.bergerkiller.bukkit.common.reflection.SafeField; import com.bergerkiller.bukkit.common.utils.CommonUtil; import net.minecraft.server.Block; import net.minecraft.server.Chunk; import net.minecraft.server.EnumSkyBlock; public class ChunkRef { private static final Class<?> icp = CommonUtil.getNMSClass("IChunkProvider"); public static final int XZ_MASK = 0xf; public static final int Y_MASK = 0xff; public static final ClassTemplate<Object> TEMPLATE = new NMSClassTemplate("Chunk"); public static final FieldAccessor<Integer> x = TEMPLATE.getField("locX"); public static final FieldAccessor<Integer> z = TEMPLATE.getField("locZ"); public static final MethodAccessor<byte[]> biomeData = TEMPLATE.getMethod("m"); public static final MethodAccessor<Object[]> sections = TEMPLATE.getMethod("getSections"); public static final FieldAccessor<Boolean> seenByPlayer = TEMPLATE.getField("q"); private static final MethodAccessor<Void> addEntities = TEMPLATE.getMethod("addEntities"); private static final MethodAccessor<Void> loadNeighbours = TEMPLATE.getMethod("loadNearby", icp, icp, int.class, int.class); private static final MethodAccessor<Boolean> needsSaving = TEMPLATE.getMethod("a", boolean.class); public static final FieldAccessor<Object> world = TEMPLATE.getField("world"); public static final FieldAccessor<Map<?, ?>> tileEntities = TEMPLATE.getField("tileEntities"); public static final FieldAccessor<List<Object>[]> entitySlices = TEMPLATE.getField("entitySlices"); public static final FieldAccessor<Object> worldProvider = new SafeField<Object>(CommonUtil.getNMSClass("World"), "worldProvider"); public static final FieldAccessor<Boolean> hasSkyLight = new SafeField<Boolean>(CommonUtil.getNMSClass("WorldProvider"), "g"); public static void loadNeighbours(Object chunkHandle, Object chunkProvider1, Object chunkProvider2, int x, int z) { loadNeighbours.invoke(chunkHandle, chunkProvider1, chunkProvider2, x, z); } public static void addEntities(Object chunkHandle) { addEntities.invoke(chunkHandle); } /** * Whether saving is needed for a chunk * * @param chunkHandle to check * @return True if the chunk needs saving, False if not */ public static boolean needsSaving(Object chunkHandle) { return needsSaving.invoke(chunkHandle, false); } /** * Gets all chunk sections contained in a chunk */ public static Object[] getSections(Object chunkHandle) { return sections.invoke(chunkHandle); } /** * Gets the y-coordinate of the highest chunk section * * @param chunkHandle to get it from * @return chunk section highest y-position */ public static int getTopSectionY(Object chunkHandle) { return ((Chunk) chunkHandle).h(); } public static int getHeight(Object chunkHandle, int x, int z) { return ((Chunk) chunkHandle).b(x & XZ_MASK, z & XZ_MASK); } public static int getBlockLight(Object chunkHandle, int x, int y, int z) { return getBrightness(((Chunk) chunkHandle), x, y, z, EnumSkyBlock.BLOCK); } public static int getSkyLight(Object chunkHandle, int x, int y, int z) { return getBrightness(((Chunk) chunkHandle), x, y, z, EnumSkyBlock.SKY); } private static int getBrightness(Object chunkHandle, int x, int y, int z, EnumSkyBlock mode) { if (y < 0) { return 0; } else if (y >= ((Chunk) chunkHandle).world.getWorld().getMaxHeight()) { return mode.c; } return ((Chunk) chunkHandle).getBrightness(mode, x & XZ_MASK, y, z & XZ_MASK); } public static boolean setBlock(Object chunkHandle, int x, int y, int z, Object type, int data) { return ((Chunk) chunkHandle).a(x & XZ_MASK, y, z & XZ_MASK, (Block) type, data); } @Deprecated public static boolean setBlock(Object chunkHandle, int x, int y, int z, int typeId, int data) { return setBlock(chunkHandle, x, y, z, CraftMagicNumbers.getBlock(typeId), data); } public static int getData(Object chunkHandle, int x, int y, int z) { return ((Chunk) chunkHandle).getData(x & XZ_MASK, y, z & XZ_MASK); } public static Object getType(Object chunkHandle, int x, int y, int z) { return ((Chunk) chunkHandle).getType(x & XZ_MASK, y, z & XZ_MASK); } @Deprecated public static int getTypeId(Object chunkHandle, int x, int y, int z) { return CraftMagicNumbers.getId((Block) getType(chunkHandle, x, y, z)); } }