public static Texture32 Of(Bitmap bd, bool alpha)
        {
            var t = new Texture32
            {
                Bitmap = bd,
            };

            t.alpha = alpha;
            t.Update();

            return t;
        }
        /// <summary>
        /// Generates the WallMap based on Map and Mappings
        /// </summary>
        public void Update()
        {
            if (_Map == null)
                return;

            if (_Textures == null)
                return;

            var w = new Texture32();
            var k = _Textures.Keys.ToList();

            for (int i = 0; i < Texture32.SizeConstant; i++)
                for (int j = 0; j < Texture32.SizeConstant; j++)
                {
                    var c = _Map[i, j];

                    if (k.Contains(c))
                        c = (uint)(k.IndexOf(c) + 1);
                    else
                    {
                        Console.WriteLine("unmapped: " + c);

                        if (i == 0 || j == 0 || i == Texture32.SizeConstant - 1 || j == Texture32.SizeConstant - 1)
                            c = 1;
                        else
                            c = 0;
                    }

                    w[i, j] = c;
                }

            _WallMap = w;

            if (Changed != null)
                Changed();
        }
		public void InitializeOtherEvents()
		{
			Events.ServerPlayerJoined +=
				e =>
				{
					Map.WriteLine("joined: " + e.name);

					Messages.PlayerAdvertise(MyIdentity.Value.name);
				};

			Events.UserPlayerAdvertise +=
				e =>
				{
					Map.WriteLine("present: " + e.name);

				};

			Events.ServerPlayerLeft +=
				e =>
				{
					Map.WriteLine("left: " + e.name);

				};

			Events.ServerSendMap +=
				e =>
				{
					// we have been chosen to tell the new guy about current map

					Map.WriteLine("we sent out a map");

					var ms = new MemoryStream();
					var mw = new BinaryWriter(ms);

					var wm = Map.EgoView.Map.WorldMap;

					mw.Write(wm.Values.Length);

					uint xor = 0;

					foreach (var v in wm.Values)
					{
						xor ^= v;

						mw.Write(v);
					}

					mw.Write(xor);

					Map.WriteLine("sent xor  " + new { xor });

					// we will waste 3 bytes - 0xffffff00 cuz memorystream isn't supported
					var MemoryStream_Int32 = ms.ToArray().Select(i => (int)i).ToArray();

					Messages.SendMap(MemoryStream_Int32);
				};

			Events.UserSendMap +=
				e =>
				{
					FirstMapLoader.Signal(
						delegate
						{
							Map.WriteLine("syncing map");

							// we need to 
							Map.RemoveAllEntities();

							var wm = new Texture32();
							
							var MemoryStream_UInt8 = e.bytestream.Select(i => (byte)i).ToArray();
							var ms = new MemoryStream(MemoryStream_UInt8);
							var mr = new BinaryReader(ms);

							var Values = mr.ReadInt32();

							if (Values != wm.Values.Length)
							{
								Map.WriteLine("wrong length");
							}
							else
							{
								uint xor = 0;

								for (int i = 0; i < Values; i++)
								{
									var v = mr.ReadUInt32();

									xor ^= v;

									wm[i] = v;
								}

								var xor_Expected = mr.ReadUInt32();

								if (xor == xor_Expected)
								{
									Map.WriteLine("xor ok " + new { xor, xor_Expected });

									Map.EgoView.Map.WorldMap = wm;

									Map.ResetEgoPosition();
								}
								else
								{
									Map.WriteLine("xor failed " + new { xor, xor_Expected });
								}
							}

						}
					);
				};

		}
		private void CreateMapFromMaze()
		{
			var Map = new Texture32();


			#region safe map
			for (int i = 0; i < 32; i++)
				for (int j = 0; j < 32; j++)
				{
					Map[i, j] = bluewall;
				}
			#endregion

			maze = new BlockMaze(new MazeGenerator(MazeSize, MazeSize, null));

			#region write walls to map
			var wall_counter = 0;

			for (int x = 1; x < maze.Width - 1; x++)
				for (int y = 1; y < maze.Height - 1; y++)
				{
					if (maze.Walls[x][y])
					{
						wall_counter++;

						var variant = graywall;

						if (y > maze.Height / 2)
						{
							variant = woodwall;

							if (wall_counter % 7 == 0)
								variant = woodwall_books;
							if (wall_counter % 11 == 0)
								variant = woodwall_achtung;
							else if (wall_counter % 13 == 0)
								variant = woodwall_verboten;
						}
						else
						{
							variant = graywall;

							if (wall_counter % 8 == 0)
								variant = graywall_achtung;
							else if (wall_counter % 9 == 0)
								variant = graywall_verboten;

						}

						Map[x, y] = variant;

					}
					else
						Map[x, y] = 0;
				}
			#endregion


			#region maze is smaller than 31
			for (int x = 1; x < maze.Width - 1; x++)
			{
				Map[x, maze.Height - 1] = greenwall;
			}

			for (int y = 1; y < maze.Height - 1; y++)
			{
				Map[maze.Width - 1, y] = greenwall;
			}
			#endregion


			EgoView.Map.WorldMap = Map;
		}
		private void InitializeMap()
		{
			#region fill map
			Assets.Default.stuff.ToBitmapDictionary(
				f =>
				{
					const uint graywall = 0xff0000;
					const uint graywall_achtung = 0xff0001;
					const uint graywall_verboten = 0xff0002;

					const uint woodwall = 0x7F3300;
					const uint woodwall_books = 0x7F33F0;
					const uint woodwall_achtung = 0x7F3301;
					const uint woodwall_verboten = 0x7F3302;


					const uint bluewall = 0x0000ff;
					const uint greenwall = 0x00ff00;

					var Map = new Texture32();


					#region safe map
					for (int i = 0; i < 32; i++)
						for (int j = 0; j < 32; j++)
						{
							Map[i, j] = bluewall;
						}
					#endregion

					maze = new BlockMaze(new MazeGenerator(MazeSize, MazeSize, null));

					#region write walls to map
					var wall_counter = 0;

					for (int x = 1; x < maze.Width - 1; x++)
						for (int y = 1; y < maze.Height - 1; y++)
						{
							if (maze.Walls[x][y])
							{
								wall_counter++;

								var variant = graywall;

								if (y > maze.Height / 2)
								{
									variant = woodwall;

									if (wall_counter % 7 == 0)
										variant = woodwall_books;
									if (wall_counter % 11 == 0)
										variant = woodwall_achtung;
									else if (wall_counter % 13 == 0)
										variant = woodwall_verboten;
								}
								else
								{
									variant = graywall;

									if (wall_counter % 8 == 0)
										variant = graywall_achtung;
									else if (wall_counter % 9 == 0)
										variant = graywall_verboten;

								}

								Map[x, y] = variant;

							}
							else
								Map[x, y] = 0;
						}
					#endregion


					#region maze is smaller than 31
					for (int x = 1; x < maze.Width - 1; x++)
					{
						Map[x, maze.Height - 1] = greenwall;
					}

					for (int y = 1; y < maze.Height - 1; y++)
					{
						Map[maze.Width - 1, y] = greenwall;
					}
					#endregion


					EgoView.Map.WorldMap = Map;


					Action<IEnumerator<Texture64.Entry>, Texture64, Action<SpriteInfoExtended>> AddSpriteByTexture =
							  (SpaceForStuff, tex, handler) =>
							  {
								  var p = SpaceForStuff.TakeOrDefault();

								  if (p == null)
									  return;

								  CreateDummy(tex).Do(handler).Position.To(p.XIndex + 0.5, p.YIndex + 0.5);

							  };



					var FreeSpaceForStuff = EgoView.Map.WorldMap.Entries.Where(i => i.Value == 0).Randomize().GetEnumerator();

					CreateGuards(FreeSpaceForStuff);


					var GoldTakenCounter = 0;

					#region gold

					var GoldSprites = new List<SpriteInfo>();

					#region nonblock
					Action AddNonBlockingItems =
						delegate
						{



							Assets.Default.nonblock.ToBitmapArray(
								sprites =>
								{
									for (int i = 0; i < 7; i++)
										foreach (var s in sprites)
										{
											// compiler bug: get a delegate to BCL class
											//AddSpriteByTexture(FreeSpaceForStuff, s, GoldSprites.Add);

											AddSpriteByTexture(FreeSpaceForStuff, s,
												k =>
												{
													k.Range = 0.5;
													//GoldSprites.Add(k);
												}
											);

										}
								}
							);


						};
					#endregion

					Assets.Default.gold.ToBitmapArray(
					   sprites =>
					   {

						   for (int i = 0; i < 6; i++)
							   foreach (var _s in sprites)
							   {
								   var s = _s;

								   // compiler bug: get a delegate to BCL class
								   //AddSpriteByTexture(FreeSpaceForStuff, s, GoldSprites.Add);

								   AddSpriteByTexture(FreeSpaceForStuff, s,
									   k =>
									   {
										   k.Range = 0.5;
										   k.ItemTaken +=
											   delegate
											   {
												   Assets.Default.treasure.play();
											   };

										   GoldSprites.Add(k);
									   }
								   );

							   }

						   var LastPosition = new Point();

						   EgoView.ViewPositionChanged +=
							   delegate
							   {
								   // only check for items each 0.5 distance travelled
								   if ((EgoView.ViewPosition - LastPosition).length < 0.5)
									   return;

								   Action Later = null;
								   Action ItemTaken = null;


								   foreach (var Item in EgoView.SpritesFromPointOfView)
								   {
									   var Item_Sprite = Item.Sprite as SpriteInfoExtended;

									   if (Item_Sprite != null)
										   if (!Item_Sprite.IsTaken)
											   if (Item.Distance < Item_Sprite.Range)
											   {
												   if (GoldSprites.Contains(Item_Sprite))
												   {
													   // ding-ding-ding!
													   Item_Sprite.IsTaken = true;

													   new Bitmap(new BitmapData(DefaultWidth, DefaultHeight, false, 0xffff00))
													   {
														   scaleX = DefaultScale,
														   scaleY = DefaultScale
													   }.AttachTo(this).FadeOutAndOrphanize(1000 / 24, 0.2);



													   if (Item_Sprite != null)
														   if (Item_Sprite.ItemTaken != null)
															   ItemTaken += () => Item_Sprite.ItemTaken();

													   GoldTakenCounter = (GoldTakenCounter + 1).Min(1);

													   Later +=
														   delegate
														   {
															   EgoView.Sprites.Remove(Item_Sprite);
															   GoldSprites.Remove(Item_Sprite);
														   };
												   }
											   }
								   }

								   if (Later != null)
									   Later();

								   LastPosition = EgoView.ViewPosition;

								   if (ItemTaken != null)
									   ItemTaken();
							   };

						   AddNonBlockingItems();

					   }
					);
					#endregion

					Func<string, Texture64> t =
						texname => f[texname + ".png"];

					Func<string, string, Texture64> mix =
						(a, b) =>
						{
							var ia = f[a + ".png"];
							var ib = f[b + ".png"];

							var u = new Bitmap(ia.bitmapData.clone());



							u.bitmapData.draw(ib);
							return u;
						};



					#region game goal
					TheGoldStack = CreateDummy(f["life.png"]);
					TheGoldStack.Position.To(maze.Width - 1.5, maze.Height - 1.5);
					TheGoldStack.Range = 0.5;
					TheGoldStack.ItemTaken +=
						delegate
						{
							if (EndLevelMode)
								return;


							// show stats

							EnterEndLevelMode();
						};
					GoldSprites.Add(TheGoldStack);


					#endregion


					EgoView.Map.Textures = new Dictionary<uint, Texture64>
                        {
                            {graywall_achtung, mix("graywall", "achtung")},
                            {graywall_verboten, mix("graywall", "verboten")},
                            {graywall, t("graywall")},


							{woodwall_achtung, mix("woodwall", "achtung")},
                            {woodwall_verboten, mix("woodwall", "verboten")},
                            {woodwall, t("woodwall")},
                            {woodwall_books, t("woodwall_books")},


                            {bluewall, t("bluewall")},
                            {greenwall, t("greenwall")},
                        };

					// EgoView.RenderScene();

					#region hand
					var hand = f["hand.png"];
					const int handsize = 4;

					var hand_x = (DefaultControlWidth - hand.width * handsize) / 2;
					var hand_y = DefaultControlHeight - hand.height * handsize;
					hand.x = hand_x;
					hand.y = hand_y;
					hand.scaleX = handsize;
					hand.scaleY = handsize;
					hand.AttachTo(HudContainer);

					(1000 / 24).AtInterval(
						tt =>
						{
							hand.x = hand_x + Math.Cos(tt.currentCount * 0.2) * 6;
							hand.y = hand_y + Math.Abs(Math.Sin(tt.currentCount * 0.2)) * 4;
						}
					);
					#endregion

					#region heads

					Assets.Default.head.Items.OrderBy(k => k.FileName).Select(k => k.Data).ToImages(
						heads =>
						{
							var head = default(Bitmap);

							1000.AtInterval(
								tt =>
								{
									if (head != null)
										head.Orphanize();

									if (heads.Length > 0)
									{
										if (GoldTakenCounter > 0)
										{
											GoldTakenCounter--;
											head = heads.Last();
										}
										else
											head = heads.AtModulus(tt.currentCount % 3);

										head.filters = new[] { new DropShadowFilter() };
										head.scaleX = 2;
										head.scaleY = 2;
										head.MoveTo(4, DefaultControlHeight - head.height - 4).AttachTo(HudContainer);
									}
								}
							);
						}
					);


					#endregion

					InitializeCompass();
					InitializeKeyboard();

					AttachMovementInput(EgoView, true, false);


					ResetEgoPosition();

					stage.enterFrame +=
						e =>
						{
							//if (EndLevelMode)
							//    return;

							EgoView.RenderScene();
						};

					//getpsyched.FadeOutAndOrphanize(1000 / 15, 0.1);

					this.EgoView.Image.FadeIn(
						delegate
						{
							//1500.AtDelayDo(
							//    delegate
							//    {
							//        this.HudContainer.FadeIn();
							//    }
							//);
						}
					);
				}
			);
			#endregion
		}
		private void ReadSync(int[] bytestream)
		{
			Map.WriteLine("sync ReadSync " + bytestream.Length);

			// we need to 
			Map.RemoveAllEntities();

			var wm = new Texture32();

			var MemoryStream_UInt8 = bytestream.Select(i => (byte)i).ToArray();
			var ms = new MemoryStream(MemoryStream_UInt8);
			var mr = new BinaryReader(ms);

			#region read map
			var Values = mr.ReadInt32();

			if (Values != wm.Values.Length)
			{
				Map.WriteLine("wrong length");
				return;
			}
			uint xor = 0;

			for (int i = 0; i < Values; i++)
			{
				var v = mr.ReadUInt32();

				xor ^= v;

				wm[i] = v;
			}

			var xor_Expected = mr.ReadUInt32();

			if (xor != xor_Expected)
			{
				Map.WriteLine("xor failed " + new { xor, xor_Expected });
				return;
			}

			//Map.WriteLine("xor ok " + new { xor, xor_Expected });
			#endregion

			Map.EgoView.Map.WorldMap = wm;
			Map.ResetEgoPosition();

			this.Map.CurrentLevel = mr.ReadInt32();
			this.Map.GoldTotal = mr.ReadInt32();
			this.Map.AmmoTotal = mr.ReadInt32();
			this.Map.NonblockingTotal = mr.ReadInt32();

			this.Map.GoldTotalCollected = 0;

			#region write goal pos

			this.Map.TheGoldStack.Position.x = mr.ReadDouble();
			this.Map.TheGoldStack.Position.y = mr.ReadDouble();

			// you can pick up the end goal, once it ise revealed
			this.Map.TheGoldStack.AddTo(this.Map.GoldSprites);
			#endregion


			#region read gold

			var GoldSprites_Count = mr.ReadInt32();

			//Map.WriteLine("gold: " + GoldSprites_Count);

			for (int i = 0; i < GoldSprites_Count; i++)
			{
				var ConstructorIndexForSync = mr.ReadInt32();

				var GoldSprite_x = mr.ReadDouble();
				var GoldSprite_y = mr.ReadDouble();

				Map.InsertGoldSprite(ConstructorIndexForSync, GoldSprite_x, GoldSprite_y);
			}

			#endregion


			#region read ammo

			var AmmoSprites_Count = mr.ReadInt32();

			//Map.WriteLine("ammo: " + AmmoSprites_Count);

			for (int i = 0; i < AmmoSprites_Count; i++)
			{
				var ConstructorIndexForSync = mr.ReadInt32();

				var AmmoSprite_x = mr.ReadDouble();
				var AmmoSprite_y = mr.ReadDouble();

				Map.InsertAmmoSprite(ConstructorIndexForSync, AmmoSprite_x, AmmoSprite_y);
			}

			#endregion


			#region read nonblock

			var NonblockSprites_Count = mr.ReadInt32();

			//Map.WriteLine("nonblock: " + NonblockSprites_Count);

			for (int i = 0; i < NonblockSprites_Count; i++)
			{
				var ConstructorIndexForSync = mr.ReadInt32();

				var NonblockSprite_x = mr.ReadDouble();
				var NonblockSprite_y = mr.ReadDouble();

				Map.InsertNonblockSprite(ConstructorIndexForSync, NonblockSprite_x, NonblockSprite_y);
			}

			#endregion

			#region read portals
			var Portals = mr.ReadInt32();
			var Portals_Positions = new List<Point>();

			for (int i = 0; i < Portals; i++)
			{
				Portals_Positions.Add(new Point(mr.ReadDouble(), mr.ReadDouble()));
				Portals_Positions.Add(new Point(mr.ReadDouble(), mr.ReadDouble()));

				Map.AddNextDualPortal();
			}




			Map.UpdatePortalPositions(Portals_Positions.GetEnumerator());
			Map.UpdatePortalTextures();
			#endregion

			#region read guards
			var GuardSpritesCount = mr.ReadInt32();

			this.Map.WriteLine("guards: " + GuardSpritesCount);

			var GuardPositions = new List<Point>();
			var GuardSetup = new List<Action<SpriteInfoExtended>>();

			for (int i = 0; i < GuardSpritesCount; i++)
			{
				var _i = i;
				var Index = mr.ReadInt32();
				var Health = mr.ReadDouble();
				var Direction = mr.ReadDouble();
				var Position = new Point(mr.ReadDouble(), mr.ReadDouble());

				GuardPositions.Add(Position);
				GuardSetup.Add(
					k =>
					{
						Map.WriteLine("init: guard # " + _i + " " + Index);

						k.Health = Health;
						k.Direction = Direction;
						k.ConstructorIndexForSync = Index;
					}
				);
				//...
			}

			if (GuardSpritesCount > 0)
				this.Map.CreateGuards(GuardPositions.GetEnumerator(), GuardSpritesCount, false).ForEach(GuardSetup);
			#endregion

			#region end of stream
			var Found_SyncEndOfStream = mr.ReadUInt32();
			var Expected_SyncEndOfStream = SyncEndOfStream;

			// TODO: fix compiler bug while comparing (var uint) vs (literal uint)

			if (Found_SyncEndOfStream != Expected_SyncEndOfStream)
			{
				Map.WriteLine("invalid SyncEndOfStream: " + new { Found_SyncEndOfStream, Expected_SyncEndOfStream });

				return;
			}
			#endregion





			RestoreCoPlayers();


			PlayerAdvertise();
		}