//The world can no longer be accessed, but stats will be kept. Irreversibly erases world!
		public void CloseWorld()
		{
			world = null;
		}
 public static World NewEmptyWorld()
 {
    World empty = new World();
    empty.worldData = new byte[0,0,0];
    empty.blockMeta = new long[0, 0];
    empty.acreMeta = new long[0, 0];
    return empty;
 }
		private bool TryMove(int newX, int newY, World world, bool teleport = false)
		{
			if (!world.ValidBlock(newX, newY))
				return false;

			Tuple<int, int> acres = world.ConvertToAcre(newX, newY);
			ExplorerConstants.Items.IDS newBlockItem = world.GetTopObject(newX, newY);
			ItemBlueprint newBlockInfo = ExplorerConstants.Items.AllBlueprints[newBlockItem];

			//First, go ahead and just get the item if we have autopickup turned on
			if (newBlockInfo.CanAutoPickup && GetOption(PlayerOptions.Autopickup) && !world.InLockedArea(LockID, acres.Item1, acres.Item2) &&
            newBlockInfo.StaminaRequired <= stamina && world.PickupObject(newX, newY))
			{
				GetItem(newBlockItem);
			}

			//If we still can't occupy the space, we need to stop
			if (!world.PlayerCanPass(newX, newY) && !(newBlockItem == ExplorerConstants.Items.IDS.Gate &&
				world.GetOwner(acres.Item1, acres.Item2) == playerID))
				return false;
			if (!teleport && stamina < newBlockInfo.StaminaRequired)
				return false;

			BlockX = newX;
			BlockY = newY;

			//Assume we moved one space
			if (!teleport)
			{
				stepsTaken++;
				EquippedSteps++;
				stamina -= newBlockInfo.StaminaRequired;
			}

			if(world.SetExplorer(playerID, acres.Item1, acres.Item2))
				score+=ExplorerConstants.Player.ExploreScore;

			return true;
		}
		private void LeaveCave(World world)
		{
			world.RemoveCave(inCaveLocation.Item1, inCaveLocation.Item2);
			world.ForceRemoval(ExplorerConstants.Map.Layers.ObjectLayer, inCaveLocation.Item1, inCaveLocation.Item2);
			RetreatWorldDepth();
			inCaveLocation = Tuple.Create(-1, -1);
		}
		public bool Teleport(Tuple<int, int> location, World world)
		{
			if (!world.MovePlayerToken(BlockX, BlockY, location.Item1, location.Item2))
				return false;

			return TryMove(location.Item1, location.Item2, world, true);
		}
		public bool Respawn(World world)
		{
			//Get the hell outta dodge
			int retreatCount = 0;
			while (RetreatWorldDepth())
				retreatCount++;

         //Get out of the cave you're in. Also remove that cave if... you know.
         if (world.HasCave(inCaveLocation.Item1, inCaveLocation.Item2))
            world.RemoveCave(inCaveLocation.Item1, inCaveLocation.Item2);

         inCaveLocation = Tuple.Create(-1, -1);
            
			Tuple<int, int> spawn = world.GetASpawn();

			//You only need to move the player token if they were still in the world when they respawned
			if (retreatCount == 0 && !world.MovePlayerToken(BlockX, BlockY, spawn.Item1, spawn.Item2))
				return false;

			return TryMove(spawn.Item1, spawn.Item2, world, true);
		}
		//Perform the given actions in the given world. Returns all the errors that occurred
		public string PerformActions(List<ExplorerConstants.Player.Actions> actions, World world, World baseWorld, out int getChatCoins)
		{
			getChatCoins = 0;
			bool stopActions = false;
			bool strafing = false;
			int oblockX = BlockX;
			int oblockY = BlockY;
         int lookaheadX = BlockX;
         int lookaheadY = BlockY;
			Tuple<int, int> acre;
			List<string> errorMessages = new List<string>();
			int beforeFruit = ItemAmount(ExplorerConstants.Items.IDS.Fruit) + ItemAmount(ExplorerConstants.Items.IDS.SuperFruit);

         Action<ExplorerConstants.Items.IDS> EatFruit = x =>
         {
            if (CanEat)
            {
               if(x == ExplorerConstants.Items.IDS.Fruit)
               {
                  RestoreStamina(ExplorerConstants.Items.FruitStaminaRestore);
               }
               else if (x == ExplorerConstants.Items.IDS.SuperFruit)
               {
                  RestoreStamina(ExplorerConstants.Items.SuperFruitStaminaRestore);
               }
               else
               {
                  errorMessages.Add("-You can't eat that!");
                  return;
               }

               fullness += FruitFullnessIncrease;

               if(EquippedItem == x)
               {
                  UseEquippedItem();
               }
               else
               {
                  if(!RemoveItem(x, 1))
                     errorMessages.Add("-Internal error: tried to eat fruit that you didn't have!");
               }
            }
            else
            {
               errorMessages.Add("-You can't eat anymore; you're full!");
            }
         };

			//Force the removal of your token so it doesn't get in the way
			if(!InCave)
				world.ForceRemoval(ExplorerConstants.Map.Layers.PlayerLayer, BlockX, BlockY);

			foreach (ExplorerConstants.Player.Actions action in actions)
			{
				if (stopActions)
				{
					break;
				}

				int facingX = BlockX;
				int facingY = BlockY;
				int newX = BlockX;
				int newY = BlockY;

				switch (facingDirection)
				{
					case ExplorerConstants.Player.Directions.Right:
						facingX++;
						break;
					case ExplorerConstants.Player.Directions.Left:
						facingX--;
						break;
					case ExplorerConstants.Player.Directions.Down:
						facingY++;
						break;
					case ExplorerConstants.Player.Directions.Up:
						facingY--;
						break;
				}

				ExplorerConstants.Items.IDS facingItem = ExplorerConstants.Items.IDS.Empty;
				if(world.ValidBlock(facingX, facingY))
					facingItem = world.GetObject(facingX, facingY, ExplorerConstants.Map.Layers.ObjectLayer);

				ItemBlueprint facingInfo = ExplorerConstants.Items.AllBlueprints[facingItem];

				switch (action)
				{
					case ExplorerConstants.Player.Actions.Pickup:
						if (!world.ValidBlock(facingX, facingY))
						{
							errorMessages.Add("-You cannot pickup items here");
						}
						else if (stamina >= facingInfo.StaminaRequired)
						{
							acre = world.ConvertToAcre(facingX, facingY);
							if (facingInfo.OwnedItem && world.GetOwner(acre.Item1, acre.Item2) != playerID && !world.IsCave)
							{
								errorMessages.Add("-You cannot pick up items that aren't yours!");
							}
							else if (world.InLockedArea(LockID, acre.Item1, acre.Item2))
							{
								errorMessages.Add("-You cannot pick up items in a locked area!");
							}
							else if (world.PickupObject(facingX, facingY))
							{
                        if (ExplorerConstants.Items.PickupTransformations.ContainsKey(facingItem))
                           GetItem(ExplorerConstants.Items.PickupTransformations[facingItem]);
                        else
                           GetItem(facingItem);
                        
								stamina -= facingInfo.StaminaRequired;
                        if (facingItem == ExplorerConstants.Items.IDS.Statue)
                        {
                           score -= ExplorerConstants.Player.StatueScore;
                        }
                        else if (facingItem == ExplorerConstants.Items.IDS.AreaLocker && !world.IsCave)
                        {
                           world.SetLocked(acre.Item1, acre.Item2, false);
                           errorMessages.Add("-You've unlocked acre " + acre.Item1 + "-" + acre.Item2 + " plus the surrounding acres");
                        }
                        else if (facingItem == ExplorerConstants.Items.IDS.Flag)
                        {
                           score += ExplorerConstants.Player.FlagScore;
                        }

								if (facingItem == ExplorerConstants.Items.IDS.ChatCoins)
								{
                           //This is just a temporary solution!
                           List<ExplorerConstants.Items.IDS> possiblePickups = new List<ExplorerConstants.Items.IDS> {
                              ExplorerConstants.Items.IDS.Coal,
                              ExplorerConstants.Items.IDS.Dirt,
                              ExplorerConstants.Items.IDS.Fence,
                              ExplorerConstants.Items.IDS.Flower,
                              ExplorerConstants.Items.IDS.Fruit,
                              ExplorerConstants.Items.IDS.Grass,
                              ExplorerConstants.Items.IDS.Iron,
                              ExplorerConstants.Items.IDS.Planks,
                              ExplorerConstants.Items.IDS.Sand,
                              ExplorerConstants.Items.IDS.Sapling,
                              ExplorerConstants.Items.IDS.Seed,
                              ExplorerConstants.Items.IDS.Stone,
                              ExplorerConstants.Items.IDS.Torch,
                              ExplorerConstants.Items.IDS.Wood
                           };
                           possiblePickups.Shuffle();
									int coins = ExplorerConstants.Probability.ChatCoinGetLow + random.Next(ExplorerConstants.Probability.ChatCoinRange);
                           GetItem(possiblePickups[0], coins);
                           errorMessages.Add("-You picked up " + coins + " " + ExplorerConstants.Items.AllBlueprints[possiblePickups[0]].DisplayName + "s! Cool!");
                           //errorMessages.Add("-You picked up " + coins + " chat coins! Cool!");
									//getChatCoins += coins;
								}

								//You picked up the cave item! We need to "collapse" the cave.
								if (ExplorerConstants.Items.CaveLoot.Contains(facingItem) && world.IsCave)
								{
									errorMessages.Add("-Picking up the " + facingInfo.DisplayName + " caused you to teleport out of the cave!");
									LeaveCave(baseWorld);
									world = baseWorld;
									stopActions = true;
								}
							}
							else
							{
								errorMessages.Add("-There was no object to pick up");
							}
						}
						break;
					case ExplorerConstants.Player.Actions.LookUp:
						facingDirection = ExplorerConstants.Player.Directions.Up;
						break;
					case ExplorerConstants.Player.Actions.LookDown:
						facingDirection = ExplorerConstants.Player.Directions.Down;
						break;
					case ExplorerConstants.Player.Actions.LookLeft:
						facingDirection = ExplorerConstants.Player.Directions.Left;
						break;
					case ExplorerConstants.Player.Actions.LookRight:
						facingDirection = ExplorerConstants.Player.Directions.Right;
						break;
               case ExplorerConstants.Player.Actions.MoveDown:
                  if (!strafing)
                     facingDirection = ExplorerConstants.Player.Directions.Down;
                  newY++;
                  lookaheadY = newY + 1;
						TryMove(newX, newY, world);
						break;
					case ExplorerConstants.Player.Actions.MoveUp:
						if (!strafing)
							facingDirection = ExplorerConstants.Player.Directions.Up;
						newY--;
                  lookaheadY = newY - 1;
						TryMove(newX, newY, world);
						break;
					case ExplorerConstants.Player.Actions.MoveLeft:
						if (!strafing)
							facingDirection = ExplorerConstants.Player.Directions.Left;
						newX--;
                  lookaheadX = newX - 1;
						TryMove(newX, newY, world);
						break;
					case ExplorerConstants.Player.Actions.MoveRight:
						if (!strafing)
							facingDirection = ExplorerConstants.Player.Directions.Right;
						newX++;
                  lookaheadX = newX + 1;
						TryMove(newX, newY, world);
						break;
					case ExplorerConstants.Player.Actions.Strafe:
						strafing = !strafing;
						break;
					case ExplorerConstants.Player.Actions.UseEquippedItem:
						acre = world.ConvertToAcre(facingX, facingY);
						if(equipped == ExplorerConstants.Items.IDS.Fruit || equipped == ExplorerConstants.Items.IDS.SuperFruit)
						{
                     EatFruit(equipped);
						}
						else if (equipped == ExplorerConstants.Items.IDS.MagicStone)
						{
							IncreaseMaxStamina(ExplorerConstants.Items.MagicStoneStaminaIncrease);
							UseEquippedItem();
							errorMessages.Add("-You used a " + ExplorerConstants.Items.AllBlueprints[equipped].DisplayName + " and increased your max stamina!");
						}
						else if (world.CanPutObject(equipped, facingX, facingY))
						{
							string claimProblems = world.CanClaim(acre.Item1, acre.Item2, playerID);
							ExplorerConstants.Items.IDS actualObject = equipped;

							if (ExplorerConstants.Items.Transformations.ContainsKey(equipped))
								actualObject = ExplorerConstants.Items.Transformations[equipped];

							ItemBlueprint objectInfo = ExplorerConstants.Items.AllBlueprints[actualObject];

							if (objectInfo.RequiresOwnedAcre &&
								world.GetOwner(acre.Item1, acre.Item2) != playerID)
							{
								errorMessages.Add("-You can't place the equipped item (" + objectInfo.DisplayName + ") in an acre you don't own!");
							}
							else if (objectInfo.CannotOwn && (world.GetOwner(acre.Item1, acre.Item2) > 0 || world.IsSpawn(acre.Item1, acre.Item2)))
							{
								errorMessages.Add("-You can't place the equipped item (" + objectInfo.DisplayName + ") in an owned or spawning acre!");
							}
							else if (actualObject == ExplorerConstants.Items.IDS.Tower &&
								!string.IsNullOrWhiteSpace(claimProblems))
							{
								errorMessages.Add("-You can't claim this acre! " + claimProblems);
							}
							else if (actualObject == world.GetObject(facingX, facingY, objectInfo.Layer))
							{
								errorMessages.Add("-You can't place the equipped item (" + objectInfo.DisplayName + "); it's already there!");
							}
							else if (world.InLockedArea(LockID, acre.Item1, acre.Item2))
							{
								errorMessages.Add("-You can't place items in a locked area!");
							}
							else if (world.GetLocked(acre.Item1, acre.Item2) && actualObject == ExplorerConstants.Items.IDS.AreaLocker)
							{
								errorMessages.Add("-You can't lock this acre! It's already locked!");
							}
							else if (world.PutObject(actualObject, facingX, facingY))
							{
								if (actualObject == ExplorerConstants.Items.IDS.Tower)
								{
									score += ExplorerConstants.Player.TowerScore;
									errorMessages.Add("-You claimed acre " + acre.Item1 + "-" + acre.Item2 + "!");
									world.SetOwner(playerID, acre.Item1, acre.Item2);
								}
								else if (actualObject == ExplorerConstants.Items.IDS.AreaLocker)
								{
									world.SetLocked(acre.Item1, acre.Item2, true);
									errorMessages.Add("-You locked acre " + acre.Item1 + "-" + acre.Item2 + " and the surrounding acres");
								}
								else if (actualObject == ExplorerConstants.Items.IDS.Statue)
								{
									score += ExplorerConstants.Player.StatueScore;
								}
								UseEquippedItem();
							}
						}
						else
						{
							if (equipped == ExplorerConstants.Items.IDS.Empty)
								errorMessages.Add("-You don't have anything equipped");
							else
								errorMessages.Add("-You can't use the equipped item: " + ExplorerConstants.Items.AllBlueprints[equipped].DisplayName);
						}
							
						break;
				}

				if (stamina < MaxStamina / 2 && GetOption(PlayerOptions.AutoFruit))
				{
					if (ItemAmount(ExplorerConstants.Items.IDS.Fruit) > 0)
					{
                  EatFruit(ExplorerConstants.Items.IDS.Fruit);
//						if (!RemoveItem(ExplorerConstants.Items.IDS.Fruit, 1))
//							errorMessages.Add("-Fatal error: Inconsistent item counts. Please report this bug!");
//						else
//							RestoreStamina(ExplorerConstants.Items.FruitStaminaRestore);
					}
					else if (ItemAmount(ExplorerConstants.Items.IDS.SuperFruit) > 0)
					{
                  EatFruit(ExplorerConstants.Items.IDS.SuperFruit);
//						if (!RemoveItem(ExplorerConstants.Items.IDS.SuperFruit, 1))
//							errorMessages.Add("-Fatal error: Inconsistent item counts. Please report this bug!");
//						else
//							RestoreStamina(ExplorerConstants.Items.SuperFruitStaminaRestore);
					}
				}

            //Torch reuse
				if (EquippedSteps >= ExplorerConstants.Items.TorchSteps &&
					equipped == ExplorerConstants.Items.IDS.Torch)
				{
					UseEquippedItem();
				}

				if (equipped != ExplorerConstants.Items.IDS.Empty && inventory[equipped] == 0)
				{
					errorMessages.Add("-You ran out of your equipped item (" + ExplorerConstants.Items.AllBlueprints[equipped].DisplayName + ")");
					equipped = ExplorerConstants.Items.IDS.Empty;
				}

				if (stamina == 0)
				{
					errorMessages.Add("-You're out of stamina! Refill it with Fruit or rest for a bit.");
					break;
				}
			}

			if ((oblockX != BlockX || oblockY != BlockY) && !world.PlayerCanHalt(BlockX, BlockY))
			{
				errorMessages.Add("-You halted in a block which cannot be occupied, so you have been moved to a nearby location");
				Tuple<int, int> newLocation = world.FindCloseHaltable(BlockX, BlockY, lookaheadX, lookaheadY);

				if (!TryMove(newLocation.Item1, newLocation.Item2, world, true))
					errorMessages.Add("-Fatal error! You could not be moved from the previous bad location!");
			}
			else if (world.GetObject(BlockX, BlockY, ExplorerConstants.Items.AllBlueprints[ExplorerConstants.Items.IDS.CaveEntrance].Layer) == ExplorerConstants.Items.IDS.CaveEntrance)
			{
				//Oh crap, we landed on a cave entrance! Try to enter the cave.
				if (world.HasCave(BlockX, BlockY))
				{
					//Get rid of your dang player token
					//world.ForceRemoval(ExplorerConstants.Map.Layers.PlayerLayer, BlockX, BlockY);

					//Get the cave and stick you right in there
					World cave = world.GetCave(BlockX, BlockY);
					inCaveLocation = Tuple.Create(BlockX, BlockY);
					AdvanceWorldDepth(cave.SpawnAcreX, cave.SpawnAcreY);
					
					//Put a block over the cave so people can't get in
					world.ForcePut(ExplorerConstants.Items.IDS.BlockingBlock, inCaveLocation.Item1, inCaveLocation.Item2);

					errorMessages.Add("-You entered a cave! Equip a torch!");
				}
				else
				{
					errorMessages.Add("-You tried to enter the cave, but the cave collapsed!");
					world.ForceRemoval(ExplorerConstants.Items.AllBlueprints[ExplorerConstants.Items.IDS.CaveEntrance].Layer, BlockX, BlockY);
				}
			}
			else if (world.GetObject(BlockX, BlockY, ExplorerConstants.Items.AllBlueprints[ExplorerConstants.Items.IDS.CaveExit].Layer) == ExplorerConstants.Items.IDS.CaveExit)
			{
				errorMessages.Add("-As you leave the cave, the entrance collapses behind you");
				LeaveCave(baseWorld);
				world = baseWorld;
			}

			if (beforeFruit > 0 && (ItemAmount(ExplorerConstants.Items.IDS.Fruit) + ItemAmount(ExplorerConstants.Items.IDS.SuperFruit)) == 0)
				errorMessages.Add("-You've run out of fruit");

			//Now put your player token back
			if(!InCave)
				world.ForcePut(ExplorerConstants.Items.IDS.PlayerToken, BlockX, BlockY);

			return string.Join("\n", errorMessages.Distinct());
		}
		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>();
		}