public World GetCave(int blockX, int blockY)
		{
			CheckBlock(blockX, blockY);
			//Tuple<int, int> caveSpot = Tuple.Create(blockX, blockY);
         string caveSpot = WorldPoint.PointToKey(blockX, blockY);

         if (!caves.ContainsKey(caveSpot))
			{
				throw new Exception("There is no cave here");
			}

			if (caves[caveSpot].IsEmpty)
			{
				World cave = new World(true);
				cave.Generate();
				caves[caveSpot] = cave;
			}

			return caves[caveSpot];
		}
      public override List<ChatEssentials.JSONObject> ProcessCommand(UserCommand command, ChatEssentials.UserInfo user, Dictionary<int, ChatEssentials.UserInfo> users)
      {
         #region oneTimeProcess
         if(!oneTimeRun)
         {
            oneTimeRun = true;
            //Cheating = 
            ExplorerConstants.Simulation.FruitGrowthHours = GetOption<double>("fruitHours");
            ExplorerConstants.Simulation.TreeGrowthHours = GetOption<double>("treeHours");
            ExplorerConstants.Simulation.StoneGrowthHours = GetOption<double>("stoneHours");
            ExplorerConstants.Simulation.SuperFruitGrowthHours = GetOption<double>("superFruitHours");
            ExplorerConstants.Items.TorchSteps = GetOption<int>("torchSteps");
            ExplorerConstants.Probability.CaveChance = GetOption<double>("caveChance");
            ExplorerConstants.Player.HourlyStaminaRegain = GetOption<int>("hourlyStamina");
            //ExplorerConstants.Player.FruitFullnessIncrease = GetOption<double>("fullnessIncrease");
            ExplorerConstants.Player.FruitPerFullness = GetOption<double>("fruitPerFullness");
            ExplorerConstants.Player.FullnessDecayMinutes = GetOption<double>("fullnessDecayMinutes");
            ExplorerConstants.Items.ExtraFruitPerMagicStone = GetOption<double>("extraFruitPerMagicStone");

            string temp = GetOption<string>("player");
            if (temp.Length > 0)
               ExplorerConstants.Player.CurrentPlayerToken = temp[0];

            if (GetOption<bool>("cheating"))
               Commands.Add(new ModuleCommand("excheat", new List<CommandArgument>(), "Get a crapload of resources"));
         }
         #endregion

         #region fromPostProcess
         if (worlds.Count == 0)
         {
            GenerateWorld();
         }
            
         foreach (WorldInstance world in worlds)
            world.RefreshFullness((DateTime.Now - lastCommand).TotalMinutes / ExplorerConstants.Player.FullnessDecayMinutes);

         lastCommand = DateTime.Now;

         if ((DateTime.Now - lastRefresh).TotalHours >= 1.0 / ExplorerConstants.Player.HourlyStaminaRegain)
         {
            foreach (WorldInstance world in worlds)
               world.RefreshStamina((int)Math.Ceiling((DateTime.Now - lastRefresh).TotalHours * ExplorerConstants.Player.HourlyStaminaRegain));

            lastRefresh = DateTime.Now;
         }

         foreach (WorldInstance world in worlds)
            world.SimulateTime();
         #endregion

			Match match;
			Tuple<WorldInstance, string> results;

         TryRegister(user.UID);

			try
			{
            if(command.Command == "exmastertest")
            {
               if(!user.ChatControlExtended)
                  return FastMessage("You don't have access to this command", true);

               int worldType;
               if (!int.TryParse(command.Arguments[0], out worldType))
                  worldType = 0;

               World world = new World();
               world.Generate(worldType % ExplorerConstants.Generation.PresetBases.Count);
               world.GetFullMapImage(false).Save(StringExtensions.PathFixer(GetOption<string>("mapFolder")) + "test" + worldType + ".png");

               return FastMessage("Test " + worldType + " map: " + GetOption<string>("mapLink") + "/test" + worldType + ".png");
            }

            if(command.Command == "exmasterflagscatter")
            {
               if(!user.ChatControlExtended)
                  return FastMessage("You don't have access to this command", true);

               int amount, world;
               if (!int.TryParse(command.Arguments[0], out amount) || amount > 10000)
                  return FastMessage("You can't spawn that many flags!");
               if (!int.TryParse(command.Arguments[1], out world) || !worlds.Any(x => x.Operating && x.WorldID == world))
                  return FastMessage("The world you gave was invalid!");

               int actualCount = worlds.First(x => x.Operating && x.WorldID == world).WorldData.ScatterFlags(amount);

               ModuleJSONObject broadcast = new ModuleJSONObject("Hey, " + user.Username + " has just spawned " + actualCount +
                  " flags in exgame world " + world + "!");
               broadcast.broadcast = true;
               
               return new List<JSONObject>{ broadcast };
            }

				#region mastergenerate
				//match = Regex.Match(chunk.Message, @"^\s*/exmastergenerate\s*([0-9]+)?\s*$");
            if (command.Command == "exmastergenerate")
				{
               if(!user.ChatControlExtended)
                  return FastMessage("You don't have access to this command", true);

					int givenCode;
               if (!int.TryParse(command.Arguments[0], out givenCode))
						givenCode = 0;

					if (generateCode == -1)
					{
						generateCode = (int)(DateTime.Now.Ticks % 10000);
                  return FastMessage("If you wish to generate a new world, type in the same command with this code: " + generateCode);
					}
					else
					{
						if (generateCode != givenCode)
						{
							generateCode = -1;
                     return FastMessage("That was the wrong code. Code has been reset", true);
						}
						GenerateWorld();
						generateCode = -1;
                  return FastMessage("You've generated a new world!");
					}
				}
				#endregion

				#region masterclose
				//match = Regex.Match(chunk.Message, @"^\s*/exmasterclose\s+([0-9]+)\s*([0-9]+)?\s*$");
            if (command.Command == "exmasterclose")//match.Success)
				{
//					if (chunk.Username != Module.AllControlUsername)
//						return chunk.Username + ", you don't have access to this command";
               if(!user.ChatControlExtended)
                  return FastMessage("You don't have access to this command", true);

					int givenCode, givenWorld;

					if (!int.TryParse(command.Arguments[0], out givenWorld) || !worlds.Any(x => x.Operating && x.WorldID == givenWorld))
                  return FastMessage("The world you gave was invalid!", true);

               if (!int.TryParse(command.Arguments[1], out givenCode))
						givenCode = 0;

					if (closeCode == -1)
					{
						closeCode = (int)(DateTime.Now.Ticks % 10000);
						closeWorld = givenWorld;
                  return FastMessage("If you wish to close world " + closeWorld + " , type in the same command with this code: " + closeCode);
					}
					else
					{
						if (closeCode != givenCode || closeWorld != givenWorld)
						{
							closeCode = -1;
							closeWorld = -1;
                     return FastMessage("That was the wrong code or world. Code has been reset", true);
						}

						string output = "You've closed world " + closeWorld;
                  bool warning = false;
						WorldInstance world = worlds.FirstOrDefault(x => x.WorldID == closeWorld);
						if (world == null)
                  {
							output = "Something went wrong. No worlds have been closed";
                     warning = true;
                  }
						else
                  {
							world.CloseWorld();
                  }

						closeWorld = -1;
						closeCode = -1;

                  return FastMessage(output, warning);
					}
				}
				#endregion

				#region worldlist
            if (command.Command == "exworldlist")//Regex.IsMatch(chunk.Message, @"^\s*/exworldlist\s*$"))
				{
					string output = "List of all worlds:\n-------------------------------------";

					foreach (WorldInstance world in worlds)
					{
						if (world.CanPlay)
							output += "\n-World " + world.WorldID + " * " + world.GetOwnedAcres().Count + " acre".Pluralify(world.GetOwnedAcres().Count);
					}

               return StyledMessage(output);
				}
				#endregion

				#region setworld
				//match = Regex.Match(chunk.Message, @"^\s*/exsetworld\s+([0-9]+)\s*$");
            if (command.Command == "exsetworld")//match.Success)
				{
					int setWorld;

               if (!int.TryParse(command.Arguments[0], out setWorld))
                  return FastMessage("This is an invalid world selection", true);
					else if (!worlds.Any(x => x.WorldID == setWorld))
                  return FastMessage("There are no worlds with this ID", true);
               else if (allPlayers[user.UID].PlayingWorld == setWorld)
                  return FastMessage("You're already playing on this world", true);

					WorldInstance world = worlds.FirstOrDefault(x => x.WorldID == setWorld);
					if (!world.CanPlay)
                  return FastMessage("This world is unplayable", true);

               allPlayers[user.UID].PlayingWorld = setWorld;

               if (world.StartGame(user.UID, user.Username))
                  return FastMessage("You've entered World " + setWorld + " for the first time!");
					else
                  return FastMessage("You've switched over to World " + setWorld);
				}
				#endregion

				#region toggle
            match = Regex.Match(command.Command, @"extoggle([^\s]+)");
				if (match.Success)
				{
               if (!WorldCommandCheck(user.UID, out results))
                  return FastMessage(results.Item2, true);

               return FastMessage(results.Item1.ToggleOption(user.UID, match.Groups[1].Value));
				}
				#endregion

				#region go
				//match = Regex.Match(chunk.Message, @"^\s*/exgo\s*(.*)\s*$");
            if (command.Command == "exgo")//match.Success)
				{
               if (!WorldCommandCheck(user.UID, out results))
                  return FastMessage(results.Item2, true);

					int chatCoinGet = 0;
               string output = results.Item1.PerformActions(user.UID, command.Arguments[0]/*match.Groups[1].Value*/, out chatCoinGet);
//
//					if (chatCoinGet > 0)
//						StandardCalls_RequestCoinUpdate(chatCoinGet, chunk.Username);

               return StyledMessage(output);
				}
				#endregion

				#region cheat
            if (command.Command == "excheat")//Regex.IsMatch(chunk.Message, @"^\s*/excheat\s*$") && Cheating)
				{
               if (!WorldCommandCheck(user.UID, out results))
                  return FastMessage(results.Item2, true);

               results.Item1.Cheat(user.UID);

               return FastMessage("You cheated some resources into existence!");
				}
				#endregion

				#region itemlist
            if (command.Command == "exitemlist")//Regex.IsMatch(chunk.Message, @"^\s*/exitemlist\s*$"))
				{
					string output = "";

					foreach (ItemBlueprint item in ExplorerConstants.Items.AllBlueprints
						.Where(x => x.Key != ExplorerConstants.Items.IDS.ChatCoins).Select(x => x.Value)
						.Where(x => x.CanPickup && x.CanObtain || ExplorerConstants.Items.CraftingRecipes.ContainsKey(x.ID)))
					{
						output += item.ShorthandName + " (" + item.DisplayCharacter + ") - " + item.DisplayName + "\n";
					}

               return StyledMessage(output);
				}
				#endregion

				#region equip
				//match = Regex.Match(chunk.Message, @"^\s*/exequip\s+([a-zA-Z]+)\s*$");
            if (command.Command == "exequip")//match.Success)
				{
               if (!WorldCommandCheck(user.UID, out results))
                  return FastMessage(results.Item2, true);

               return FastMessage(results.Item1.EquipItem(user.UID, command.Arguments[0].Trim()));//match.Groups[1].Value.Trim());
				}
				#endregion

				#region craft
				//match = Regex.Match(chunk.Message, @"^\s*/excraft\s+([^0-9]+)\s*([0-9]*)\s*$");
            if (command.Command == "excraft")//match.Success)
				{
               if (!WorldCommandCheck(user.UID, out results))
                  return FastMessage(results.Item2, true);

					int amount;

               if (!int.TryParse(/*match.Groups[2].Value*/command.Arguments[1], out amount))
						amount = 1;

               return FastMessage(results.Item1.CraftItem(user.UID, command.Arguments[0].Trim()/*match.Groups[1].Value.Trim()*/, amount));
				}
				#endregion

				#region craftlist
            if (command.Command == "excraftlist")//Regex.IsMatch(chunk.Message, @"^\s*/excraftlist\s*$"))
				{
					string output = "";
					foreach (var craftRecipe in ExplorerConstants.Items.CraftingRecipes.OrderBy(x => x.Value.Values.Sum()))
					{
						output += ExplorerConstants.Items.AllBlueprints[craftRecipe.Key].ShorthandName + " - ";

						foreach (var craftIngredient in craftRecipe.Value)
						{
							output += ExplorerConstants.Items.AllBlueprints[craftIngredient.Key].ShorthandName + "*" + craftIngredient.Value + " ";
						}

						output += "\n";
					}

               return StyledMessage(output);
				}
				#endregion

				#region map
				//match = Regex.Match(chunk.Message, @"^\s*/exmap\s+([0-9]+)\s*$");
            if (command.Command == "exmap")//match.Success)
				{
               //return FastMessage("Not supported right now!", true);

					int worldID;

               if (!int.TryParse(command.Arguments[0], out worldID))
                  return FastMessage("That's not a valid number", true);

					if (!worlds.Any(x => x.WorldID == worldID))
                  return FastMessage("There's no world with this ID", true);

					try
					{
						SaveWorldImage(worlds.FirstOrDefault(x => x.WorldID == worldID));
					}
               catch (Exception e)
					{
                  return FastMessage("An error occurred while generating the map image! Please report this error to an admin." +
                     "\nError: " + e, true);
					}

               return FastMessage("World " + worldID + " map: " + GetOption<string>("mapLink") + "/world" + worldID + ".png");
				}
				#endregion

				#region top
            if (command.Command == "extop")//Regex.IsMatch(chunk.Message, @"^\s*/extop\s*$"))
				{
					List<string> scores = SortedModuleItems(users);
					//List<Tuple<string, int>> scores = allPlayers.Select(x => Tuple.Create(x.Key, worlds.Sum(y => y.GetScore(x.Key)))).ToList();
					string output = "The top explorers are:";

					for (int i = 0; i < 5; i++)
						if (i < scores.Count())
							output += "\n" + (i + 1) + ": " + scores[i];

               return FastMessage(output);
				}
				#endregion

				#region close
            if (command.Command == "exclose")//Regex.IsMatch(chunk.Message, @"^\s*/exclose\s*$"))
				{
					List<string> scores = SortedModuleItems(users);
					//List<Tuple<string, int>> scores = allPlayers.Select(x => Tuple.Create(x.Key, worlds.Sum(y => y.GetScore(x.Key)))).ToList();
               int index = scores.FindIndex(x => x.Contains(user.Username + " "));

					string output = "Your exploration competitors are:";

					for (int i = index - 2; i <= index + 2; i++)
						if (i < scores.Count() && i >= 0)
							output += "\n" + (i + 1) + ": " + scores[i];

               return FastMessage(output);
				}
				#endregion

				#region respawn
            if (command.Command == "exrespawn")//Regex.IsMatch(chunk.Message, @"^\s*/exrespawn\s*$"))
				{
               if (!WorldCommandCheck(user.UID, out results))
                  return FastMessage(results.Item2, true);

               return StyledMessage(results.Item1.Respawn(user.UID));
				}
				#endregion

				#region myacres
            if (command.Command == "exmyacres")//Regex.IsMatch(chunk.Message, @"^\s*/exmyacres\s*$"))
				{
               if (!WorldCommandCheck(user.UID, out results))
                  return FastMessage(results.Item2, true);

               return FastMessage(results.Item1.PlayerAcres(user.UID));
				}
				#endregion

				#region items
            if (command.Command == "exitems")//Regex.IsMatch(chunk.Message, @"^\s*/exitems\s*$"))
				{
               if (!WorldCommandCheck(user.UID, out results))
                  return FastMessage(results.Item2, true);

               return StyledMessage(results.Item1.PlayerItems(user.UID));
				}
				#endregion

            #region storage
            if (command.Command == "exstorage")//Regex.IsMatch(chunk.Message, @"^\s*/exitems\s*$"))
            {
               if (!WorldCommandCheck(user.UID, out results))
                  return FastMessage(results.Item2, true);

               return StyledMessage(results.Item1.PlayerStorage(user.UID));
            }
            #endregion

            #region store
            //match = Regex.Match(chunk.Message, @"^\s*/excraft\s+([^0-9]+)\s*([0-9]*)\s*$");
            if (command.Command == "exstore")//match.Success)
            {
               if (!WorldCommandCheck(user.UID, out results))
                  return FastMessage(results.Item2, true);

               int amount;

               if (!int.TryParse(/*match.Groups[2].Value*/command.Arguments[1], out amount))
                  amount = int.MaxValue;

               return FastMessage(results.Item1.StoreItems(user.UID, command.Arguments[0].Trim()/*match.Groups[1].Value.Trim()*/, amount));
            }
            #endregion

            #region store
            //match = Regex.Match(chunk.Message, @"^\s*/excraft\s+([^0-9]+)\s*([0-9]*)\s*$");
            if (command.Command == "extake")//match.Success)
            {
               if (!WorldCommandCheck(user.UID, out results))
                  return FastMessage(results.Item2, true);

               int amount;

               if (!int.TryParse(/*match.Groups[2].Value*/command.Arguments[1], out amount))
                  amount = int.MaxValue;

               return FastMessage(results.Item1.TakeItems(user.UID, command.Arguments[0].Trim()/*match.Groups[1].Value.Trim()*/, amount));
            }
            #endregion

				#region teleport
				//match = Regex.Match(chunk.Message, @"^\s*/exteleport\s+([0-9]+)\s*-\s*([0-9]+)\s*$");
            if (command.Command == "exteleport")//match.Success)
				{
               if (!WorldCommandCheck(user.UID, out results))
                  return FastMessage(results.Item2, true);

					int x, y;
               if (!int.TryParse(command.Arguments[0], out x) || !int.TryParse(command.Arguments[1], out y))
                  return FastMessage("Your acre was formatted incorrectly!", true);

               return StyledMessage(results.Item1.TeleportToTower(user.UID, Tuple.Create(x, y)));
				}
				#endregion
			}
			catch (Exception e)
			{
				return FastMessage("An exception occurred: " + e.Message + ". Please report to an admin\n" +
               "Stack trace: \n" + e.StackTrace, true);
			}

         return new List<JSONObject>();
		}