package com.flansmod.apocalypse.common; import java.io.File; import java.util.EnumSet; import java.util.HashMap; import java.util.List; import com.flansmod.apocalypse.common.entity.EntityAIMecha; import com.flansmod.apocalypse.common.entity.EntityFakePlayer; import com.flansmod.apocalypse.common.entity.EntityFlyByPlane; import com.flansmod.apocalypse.common.entity.EntityNukeDrop; import com.flansmod.apocalypse.common.entity.EntitySurvivor; import com.flansmod.apocalypse.common.entity.EntityTeleporter; import com.flansmod.apocalypse.common.network.PacketApocalypseCountdown; import com.flansmod.apocalypse.common.world.BiomeGenApocalypse; import com.flansmod.apocalypse.common.world.TeleporterApocalypse; import com.flansmod.apocalypse.common.world.buildings.StructureAbandonedVillagePieces; import com.flansmod.common.FlansMod; import com.flansmod.common.driveables.DriveableData; import com.flansmod.common.driveables.EntitySeat; import com.flansmod.common.driveables.EnumDriveablePart; import com.flansmod.common.driveables.PlaneType; import com.flansmod.common.driveables.mechas.EntityMecha; import com.flansmod.common.parts.PartType; import com.flansmod.common.teams.EntityGunItem; import net.minecraft.client.Minecraft; import net.minecraft.entity.Entity; import net.minecraft.entity.EnumCreatureType; import net.minecraft.entity.monster.EntitySkeleton; import net.minecraft.entity.player.EntityPlayer; import net.minecraft.entity.player.EntityPlayerMP; import net.minecraft.init.Blocks; import net.minecraft.init.Items; import net.minecraft.item.ItemStack; import net.minecraft.nbt.NBTTagCompound; import net.minecraft.network.play.server.S08PacketPlayerPosLook; import net.minecraft.server.MinecraftServer; import net.minecraft.tileentity.TileEntityChest; import net.minecraft.util.BlockPos; import net.minecraft.world.World; import net.minecraft.world.WorldServer; import net.minecraftforge.common.DimensionManager; import net.minecraftforge.common.MinecraftForge; import net.minecraftforge.event.entity.EntityJoinWorldEvent; import net.minecraftforge.event.entity.living.LivingDeathEvent; import net.minecraftforge.event.entity.living.LivingSpawnEvent; import net.minecraftforge.event.world.WorldEvent; import net.minecraftforge.fml.common.FMLCommonHandler; import net.minecraftforge.fml.common.event.FMLInitializationEvent; import net.minecraftforge.fml.common.event.FMLPostInitializationEvent; import net.minecraftforge.fml.common.event.FMLPreInitializationEvent; import net.minecraftforge.fml.common.eventhandler.Event.Result; import net.minecraftforge.fml.common.eventhandler.SubscribeEvent; import net.minecraftforge.fml.common.gameevent.PlayerEvent.PlayerRespawnEvent; import net.minecraftforge.fml.common.gameevent.TickEvent; import net.minecraftforge.fml.common.registry.EntityRegistry; public class CommonProxyApocalypse { private int apocalypseCountdown = 0; /** The mecha that started all this */ private EntityMecha apocalypseMecha = null; public ApocalypseData data; private static HashMap<EntityPlayer, BlockPos> deathPoints = new HashMap<EntityPlayer, BlockPos>(); public void preInit(FMLPreInitializationEvent event) { MinecraftForge.EVENT_BUS.register(this); MinecraftForge.EVENT_BUS.register(data = new ApocalypseData()); FMLCommonHandler.instance().bus().register(this); BiomeGenApocalypse.registerBiomes(); StructureAbandonedVillagePieces.registerVillagePieces(); } public void init(FMLInitializationEvent event) { EntityRegistry.registerGlobalEntityID(EntitySurvivor.class, "Survivor", EntityRegistry.findGlobalUniqueEntityId(), 0x588225, 0x875C37); EntityRegistry.registerGlobalEntityID(EntityTeleporter.class, "Teleporter", EntityRegistry.findGlobalUniqueEntityId()); EntityRegistry.registerModEntity(EntityTeleporter.class, "Teleporter", 113, FlansModApocalypse.INSTANCE, 100, 20, true); EntityRegistry.registerGlobalEntityID(EntityAIMecha.class, "AIMecha", EntityRegistry.findGlobalUniqueEntityId()); EntityRegistry.registerModEntity(EntityAIMecha.class, "AIMecha", 114, FlansModApocalypse.INSTANCE, 250, 20, false); EntityRegistry.registerGlobalEntityID(EntityFakePlayer.class, "FakePlayer", EntityRegistry.findGlobalUniqueEntityId()); EntityRegistry.registerModEntity(EntityFakePlayer.class, "FakePlayer", 115, FlansModApocalypse.INSTANCE, 250, 20, false); EntityRegistry.registerGlobalEntityID(EntityNukeDrop.class, "NukeDrop", EntityRegistry.findGlobalUniqueEntityId()); EntityRegistry.registerModEntity(EntityNukeDrop.class, "NukeDrop", 116, FlansModApocalypse.INSTANCE, 250, 20, false); FlansMod.getPacketHandler().registerPacket(PacketApocalypseCountdown.class); } public void postInit(FMLPostInitializationEvent event) { } /** Tick hook for server */ @SubscribeEvent public void tick(TickEvent.ServerTickEvent event) { if(event.phase == TickEvent.Phase.START) { //Countdown to 0 and on 0, do apocalypse things if(getApocalypseCountdown() > 0) { if(apocalypseMecha == null || apocalypseMecha.isDead()) { setApocalypseCountdown(0); } else { setApocalypseCountdown(getApocalypseCountdown() - 1); //Wiggle the apocalypse mecha apocalypseMecha.seats[0].prevLooking = apocalypseMecha.seats[0].looking.clone(); apocalypseMecha.seats[0].looking.rotateGlobalYaw(apocalypseMecha.worldObj.rand.nextFloat() * 10F); apocalypseMecha.seats[0].looking.rotateGlobalPitch((float)apocalypseMecha.worldObj.rand.nextGaussian() * 3F); //Drop nukes if(getApocalypseCountdown() % 20 == 0) { World world = apocalypseMecha.worldObj; float range = 150F; world.spawnEntityInWorld(new EntityNukeDrop(world, apocalypseMecha.posX + world.rand.nextGaussian() * range, 256, apocalypseMecha.posZ + world.rand.nextGaussian() * range)); } //Start the apocalypse if(getApocalypseCountdown() == 0) { FlansMod.log("The apocalypse has begun!"); EntityPlayer placer = apocalypseMecha.placer; switch(FlansModApocalypse.OPTION) { case DIM: for(int i = 0; i < placer.worldObj.playerEntities.size(); i++) if(((Entity)placer.worldObj.playerEntities.get(i)).dimension == 0) sendPlayerToApocalypse((EntityPlayer)placer.worldObj.playerEntities.get(i)); break; case DIM_OPT_IN: break; case NEARBY: for(Object player : placer.worldObj.playerEntities) if(((Entity)player).dimension == 0 && ((Entity)player).getDistanceToEntity(placer) < 50) sendPlayerToApocalypse((EntityPlayer)player); break; case NEARBY_OPT_IN: break; case PLACER_ONLY: sendPlayerToApocalypse(placer); break; } apocalypseMecha.setDead(); } } } WorldServer world = MinecraftServer.getServer().worldServerForDimension(FlansModApocalypse.dimensionID); if(world != null) { for(int i = 0; i < world.playerEntities.size(); i++) { EntityPlayer player = (EntityPlayer)world.playerEntities.get(i); //MinecraftServer.getServer().getConfigurationManager().transferPlayerToDimension((EntityPlayerMP)player, 0, new TeleporterApocalypse(MinecraftServer.getServer().worldServerForDimension(FlansModApocalypse.dimensionID))); if(world.rand.nextInt(5000) == 0) { double dX = world.rand.nextFloat() - 0.5F; double dZ = world.rand.nextFloat() - 0.5F; double mag = Math.sqrt(dX * dX + dZ * dZ); dX /= mag; dZ /= mag; double dist = 200D; dX *= dist; dZ *= dist; PlaneType type = FlansModApocalypse.getLootGenerator().getRandomPlane(world.rand); NBTTagCompound tags = new NBTTagCompound(); tags.setString("Engine", FlansModApocalypse.getLootGenerator().getRandomEngine(type, world.rand).shortName); tags.setString("Type", type.shortName); for(EnumDriveablePart part : EnumDriveablePart.values()) { tags.setInteger(part.getShortName() + "_Health", type.health.get(part) == null ? 0 : type.health.get(part).health); tags.setBoolean(part.getShortName() + "_Fire", false); } DriveableData data = new DriveableData(tags); EntityFlyByPlane plane = new EntityFlyByPlane(world, player.posX + dX, 120, player.posZ + dZ, type, data); plane.throttle = 1F; world.spawnEntityInWorld(plane); float yaw = 180F + (float)Math.atan2(dZ, dX) * 180F / 3.14159F; plane.seats[0].looking.setAngles(yaw, 0F, 0F); plane.seats[0].prevLooking.setAngles(yaw, 0F, 0F); plane.axes.setAngles(yaw, 0F, 0F); plane.prevAxes.setAngles(yaw, 0F, 0F); Entity pilot = new EntitySkeleton(world); pilot.setPosition(plane.posX, plane.posY, plane.posZ); world.spawnEntityInWorld(pilot); pilot.mountEntity(plane.seats[0]); } if(world.rand.nextInt(FlansModApocalypse.WANDERING_SURVIVOR_RARITY) == 0 && !world.provider.isDaytime()) { double angle = world.rand.nextFloat() * 3.14159F * 2F; double dist = 50D; double dX = Math.cos(angle) * dist; double dZ = Math.sin(angle) * dist; EntitySurvivor survivor = new EntitySurvivor(world); survivor.setPosition(player.posX + dX, world.getTopSolidOrLiquidBlock(new BlockPos(player.posX + dX, 0, player.posZ + dZ)).getY() + 1D, player.posZ + dZ); world.spawnEntityInWorld(survivor); } } } } } private void sendPlayerToApocalypse(EntityPlayer player) { //Make a copy of the player to hold their inventory and hang around until they get back EntityFakePlayer fakePlayer = new EntityFakePlayer(player.worldObj, player); player.worldObj.spawnEntityInWorld(fakePlayer); player.inventory.clear(); //Teleport them, making note of where they got in player.timeUntilPortal = 10; data.entryPoints.put(player.getPersistentID(), new BlockPos(apocalypseMecha.posX, apocalypseMecha.posY, apocalypseMecha.posZ)); BlockPos exitPoint = new BlockPos(apocalypseMecha.posX, 128, apocalypseMecha.posZ); for(; MinecraftServer.getServer().worldServerForDimension(FlansModApocalypse.dimensionID).isAirBlock(exitPoint); exitPoint = exitPoint.down()) {} MinecraftServer.getServer().getConfigurationManager().transferPlayerToDimension((EntityPlayerMP)player, FlansModApocalypse.dimensionID, new TeleporterApocalypse(MinecraftServer.getServer().worldServerForDimension(FlansModApocalypse.dimensionID), exitPoint.add(0, 1, 0))); giveStarterKit(player); } private void giveStarterKit(EntityPlayer player) { player.inventory.addItemStackToInventory(new ItemStack(Items.stone_pickaxe)); player.inventory.addItemStackToInventory(new ItemStack(Items.stone_shovel)); player.inventory.addItemStackToInventory(new ItemStack(Blocks.log, 8)); player.inventory.addItemStackToInventory(new ItemStack(Items.cooked_beef, 4)); } @SubscribeEvent public void itemPlaced(EntityJoinWorldEvent event) { if(!event.world.isRemote && event.entity instanceof EntityMecha && event.entity.dimension == 0) { EntityMecha mecha = (EntityMecha)event.entity; PartType engine = mecha.getDriveableData().engine; if(engine.isAIChip) { setApocalypseCountdown(FlansModApocalypse.apocalypseCountdownLength); apocalypseMecha = mecha; FlansMod.getPacketHandler().sendTo(new PacketApocalypseCountdown(getApocalypseCountdown()), (EntityPlayerMP)mecha.placer); } } } /** Take note of where the player died */ @SubscribeEvent public void playerDied(LivingDeathEvent event) { if(event.entityLiving.dimension == FlansModApocalypse.dimensionID && event.entityLiving instanceof EntityPlayer) { EntityPlayer player = (EntityPlayer)event.entityLiving; deathPoints.put(player, new BlockPos(player.posX, player.posY, player.posZ)); } } /** Respawn the player somewhere nearby where they died on the surface */ @SubscribeEvent public void playerRespawned(PlayerRespawnEvent event) { if(event.player.dimension == FlansModApocalypse.dimensionID) { BlockPos pos = deathPoints.get(event.player); if(pos != null) { EnumSet enumset = EnumSet.noneOf(S08PacketPlayerPosLook.EnumFlags.class); float angle = event.player.worldObj.rand.nextFloat() * 2F * 3.14159F; pos = pos.add((int)(Math.cos(angle) * FlansModApocalypse.SPAWN_RADIUS), 128 - pos.getY(), (int)(Math.sin(angle) * FlansModApocalypse.SPAWN_RADIUS)); for(; event.player.worldObj.isAirBlock(pos); pos = pos.down()) { } ((EntityPlayerMP)event.player).playerNetServerHandler.setPlayerLocation(pos.getX() + 0.5D, pos.getY() + 1.5D, pos.getZ() + 0.5D, 0F, 0F, enumset); event.player.posX = event.player.prevPosX = pos.getX() + 0.5D; event.player.posY = event.player.prevPosY = pos.getY() + 0.5D; event.player.posZ = event.player.prevPosZ = pos.getZ() + 0.5D; } } } public int getApocalypseCountdown() { return apocalypseCountdown; } private void setApocalypseCountdown(int apocalypseCountdown) { this.apocalypseCountdown = apocalypseCountdown; } }