package joshie.harvest.mining; import gnu.trove.set.TIntSet; import gnu.trove.set.hash.TIntHashSet; import joshie.harvest.api.calendar.Season; import joshie.harvest.core.HFTrackers; import joshie.harvest.core.helpers.EntityHelper; import joshie.harvest.mining.block.BlockPortal.Portal; import joshie.harvest.mining.gen.MiningProvider; import joshie.harvest.town.tracker.TownTracker; import net.minecraft.block.state.IBlockState; import net.minecraft.entity.Entity; import net.minecraft.entity.player.EntityPlayer; import net.minecraft.entity.player.EntityPlayerMP; import net.minecraft.item.ItemStack; import net.minecraft.server.MinecraftServer; import net.minecraft.util.ResourceLocation; import net.minecraft.util.Rotation; import net.minecraft.util.math.BlockPos; import net.minecraft.world.World; import net.minecraft.world.WorldServer; import net.minecraft.world.WorldServerMulti; import net.minecraft.world.storage.loot.LootContext; import net.minecraftforge.common.DimensionManager; import net.minecraftforge.fml.common.FMLCommonHandler; import net.minecraftforge.fml.relauncher.ReflectionHelper; import javax.annotation.Nonnull; import java.util.List; import java.util.Random; import static joshie.harvest.api.calendar.Season.WINTER; import static joshie.harvest.mining.HFMining.MINING_ID; import static joshie.harvest.mining.gen.MineManager.CHUNK_BOUNDARY; public class MiningHelper { private static final double WORLD_HEIGHT = 256D; public static final int CHICK_FLOORS = 7; public static final int CHICKEN_FLOORS = 11; public static final int SHEEP_FLOORS = 13; public static final int COW_FLOORS = 17; public static final int MYSTRIL_FLOOR = 127; public static final int GOLD_FLOOR = 85; public static final int SILVER_FLOOR = 43; public static final int COPPER_FLOOR = 0; public static final int MAX_Y = (int) WORLD_HEIGHT - 1; public static final int FLOOR_HEIGHT = 6; public static final int MAX_FLOORS = (int) Math.floor(WORLD_HEIGHT / FLOOR_HEIGHT); public static final int MAX_LOOP = (int) WORLD_HEIGHT - FLOOR_HEIGHT; public static final TIntSet HOLE_FLOORS = new TIntHashSet(); static { //2k to silver (2) //4k to gold (4) //8k to mystril(8) //15k to mythic (15) addFloors(21, 41);//Silver unlock, 2k addFloors(51, 61, 71, 81); //Gold unlock, 4k addFloors(90, 95, 100, 105, 110, 115, 120, 125); //mystril unlock, 8k addFloors(127, 129, 131, 133, 136, 140, 143, 145, 149, 150, 152, 156, 157, 163, 166); //15 fixed floors } private static void addFloors(int... ints) { HOLE_FLOORS.addAll(ints); } public static List<ItemStack> getLoot(ResourceLocation loot, World world, EntityPlayer player, float luck) { LootContext.Builder lootcontext$builder = new LootContext.Builder((WorldServer) world); lootcontext$builder.withLuck(player.getLuck() + luck); lootcontext$builder.withPlayer(player); return world.getLootTableManager().getLootTableFromLocation(loot).generateLootForPools(world.rand, lootcontext$builder.build()); } public static int getMineID(BlockPos pos) { return getMineID(pos.getZ() >> 4); } public static int getMineID(int chunkZ) { return (int) Math.floor(chunkZ / CHUNK_BOUNDARY); } private static void preloadChunks(WorldServer worldServer, int mineID, int floor) { MiningProvider provider = ((MiningProvider) worldServer.provider); if (!provider.areCoordinatesGenerated(mineID, floor)) { int xStart = (int) Math.floor((floor - 1) / MAX_FLOORS); for (int x = xStart * CHUNK_BOUNDARY; x < (xStart * CHUNK_BOUNDARY) + CHUNK_BOUNDARY; x++) { for (int z = mineID * CHUNK_BOUNDARY; z < (mineID * CHUNK_BOUNDARY) + CHUNK_BOUNDARY; z++) { worldServer.getChunkProvider().provideChunk(x, z); } } //Force a save if (worldServer instanceof WorldServerMulti) { ((WorldServerMulti) worldServer).saveAdditionalData(); } } } public static BlockPos modifySpawnAndEntityRotation(WorldServer dim, BlockPos spawn, Entity entity) { IBlockState actual = HFMining.PORTAL.getActualState(dim.getBlockState(spawn), dim, spawn); if (actual.getBlock() == HFMining.PORTAL) { Portal portal = HFMining.PORTAL.getEnumFromState(actual); for (int distance = 2; distance < 9; distance++) { if (portal.isEW()) { if (EntityHelper.isSpawnable(dim, spawn.north(distance))) { entity.rotationYaw = 180F; return spawn.north(distance); } else if (EntityHelper.isSpawnable(dim, spawn.south(distance))) { entity.rotationYaw = 0F; return spawn.south(distance); } } else { if (EntityHelper.isSpawnable(dim, spawn.east(distance))) { entity.rotationYaw = 270F; return spawn.east(distance); } else if (EntityHelper.isSpawnable(dim, spawn.west(distance))) { entity.rotationYaw = 90F; return spawn.west(distance); } } } } return spawn; } public static boolean teleportToMine(@Nonnull Entity entity) { int id = HFTrackers.getTowns(entity.worldObj).getMineIDFromCoordinates(new BlockPos(entity)); return id != -1 && teleportToMine(entity, id); } public static boolean teleportToMine(Entity entity, int mineID) { MinecraftServer server = FMLCommonHandler.instance().getMinecraftServerInstance(); WorldServer newWorld = server.worldServerForDimension(MINING_ID); preloadChunks(newWorld, mineID, 1); MiningProvider provider = ((MiningProvider) newWorld.provider); provider.onTeleportToMine(mineID); //Called to initiate after chunks are loaded BlockPos spawn = modifySpawnAndEntityRotation(newWorld, provider.getSpawnCoordinateForMine(mineID, 1), entity); newWorld.notifyBlockUpdate(spawn, newWorld.getBlockState(spawn), newWorld.getBlockState(spawn), 3); return EntityHelper.teleport(entity, MINING_ID, spawn); } public static boolean teleportToOverworld(Entity entity) { int mineID = getMineID((int) entity.posZ >> 4); TownTracker tracker = HFTrackers.getTowns(DimensionManager.getWorld(0)); BlockPos spawn = tracker.getCoordinatesForOverworldMine(entity, mineID); Rotation rotation = tracker.getMineOrientation(mineID); if (spawn == null) spawn = entity.worldObj.getSpawnPoint(); if (rotation == Rotation.NONE) { entity.rotationYaw = 270F; } else if (rotation == Rotation.CLOCKWISE_90) { entity.rotationYaw = 0F; } else if (rotation == Rotation.CLOCKWISE_180) { entity.rotationYaw = 90F; } else if (rotation == Rotation.COUNTERCLOCKWISE_90) { entity.rotationYaw = 180F; } return EntityHelper.teleport(entity, 0, spawn); } static void teleportToCoordinates(Entity entity, BlockPos spawn, float yaw) { if (entity instanceof EntityPlayerMP) { ReflectionHelper.setPrivateValue(EntityPlayerMP.class, (EntityPlayerMP) entity, true, "invulnerableDimensionChange", "field_184851_cj"); ((EntityPlayerMP) entity).connection.setPlayerLocation(spawn.getX() + 0.5D, spawn.getY(), spawn.getZ() + 0.5D, yaw, entity.rotationPitch); } else { entity.setLocationAndAngles(spawn.getX() + 0.5D, spawn.getY(), spawn.getZ() + 0.5D, yaw, entity.rotationPitch); } } public static boolean teleportBetweenMine(Entity entity) { int mineID = MiningHelper.getMineID((int) entity.posZ >> 4); //Current Mine int floor = getFloor((int) entity.posX >> 4, (int) entity.posY); //Current Floor boolean top = floor % MAX_FLOORS == 1; int newFloor = top ? floor - 1 : floor + 1; MinecraftServer server = FMLCommonHandler.instance().getMinecraftServerInstance(); WorldServer newWorld = server.worldServerForDimension(MINING_ID); preloadChunks(newWorld, mineID, newFloor); MiningProvider provider = ((MiningProvider) newWorld.provider); provider.onTeleportToMine(mineID); //Called to initiate after chunks are loaded BlockPos spawn = modifySpawnAndEntityRotation(newWorld, provider.getSpawnCoordinateForMine(mineID, newFloor), entity); if (entity.timeUntilPortal == 0) { entity.timeUntilPortal = 100; if (entity instanceof EntityPlayerMP) { ReflectionHelper.setPrivateValue(EntityPlayerMP.class, (EntityPlayerMP) entity, true, "invulnerableDimensionChange", "field_184851_cj"); } entity.setPositionAndUpdate(spawn.getX() + 0.5D, spawn.getY() + 0.1D, spawn.getZ() + 0.5D); } //Teleport complete return true; } public static int getFloor(BlockPos pos) { return getFloor(pos.getX() >> 4, pos.getY()); } public static int getFloor(int xPosition, int posY) { int chunkIndex = (int) Math.floor(((double) xPosition) / CHUNK_BOUNDARY); int floorIndex = (int) (MAX_FLOORS - Math.floor(((double) posY) / FLOOR_HEIGHT)); return (chunkIndex * MAX_FLOORS) + floorIndex; //Floor } public static int getOreChance(Season season, int floor, Random rand) { int lowerLimit = season == WINTER ? 6 : 8; int upperLimit = season == WINTER ? 14 : 18; int chance = season == WINTER ? 7 + rand.nextInt(9) : 10 + rand.nextInt(11); if (floor % COW_FLOORS == 0) { chance -= 5; } else if (floor % SHEEP_FLOORS == 0) { chance -= 3; } else if (floor % CHICKEN_FLOORS == 0) { chance -= 2; } else if (floor % CHICK_FLOORS == 0) { chance--; } //7 in winter < lowest, 15 max winter //10 in spring < lowest, 20 max spring if (chance >= upperLimit) chance = upperLimit; if (chance <= lowerLimit) chance = lowerLimit; return chance; } static int getDifference(BlockPos link1, BlockPos pos) { int floor1 = MiningHelper.getFloor(link1); int floor2 = MiningHelper.getFloor(pos); return floor1 >= floor2 ? floor1 - floor2 : floor2 - floor1; } }