public override bool Poll() { if (Switching) return true; if (reader == null) return false; if (reader.HasExited) return false; if (!Valid) throw new InstanceException("FFXI could not be polled becuase the context is invalid.", InstanceExceptionType.InvalidContext); try { //grab the current zone id Int32 ZoneID = reader.ReadStruct<Int32>(pZoneID); if (ZoneID > 0xFF) ZoneID = ZoneID - 0x1BC; //stop all reading while the zone is in flux if (ZoneID == 0) { lastZone = -1; //make sure the data gets properly reset in case the player zones into the same zone (tractor, warp, etc) lastMapID = -1; return true; } //If the zone has changed, then clear out any old spawns and load the zone map if (ZoneID != lastZone || engine.Data.Empty) { //An edit to the map has been made. Inform the user they are about to lose thier changes // and give them a final opportunity to save them. if (engine.Data.Dirty) { //clone the map data MapData mapcopy = engine.Data.Clone(); //pass the closed data to another thread so the current zone can continue processing. DirtyZone(mapcopy); } zoneFinished = false; //get the zone name string shortName = ""; if (ZoneID < m_zoneNameShort.Count) shortName = m_zoneNameShort[ZoneID]; //grab the new zone name if (shortName == "") shortName = "Zone" + ZoneID.ToString(); //support unnamed zones, like the mog house //release zone resources consumed by the image map processor if (engine.ShowMapAlternative) { engine.MapAlternativeImage = null; m_imagemaps.ClearCache(lastZone); } //clear the old zone data and load in the new engine.Clear(); //clear both the spawn and map data engine.Data.ZoneName = shortName; engine.Data.LoadZone(shortName); //load the zone map lastZone = ZoneID; lastMapID = -1; } //read the pointer array in one big lump, and create spawns for any new id's detected Int32[] spawnList = reader.ReadStructArray<Int32>(pSpawnStart, listMax); //cant use intptr since its machine dependant for (uint i = 0; i < listMax; i++) { if (spawnList[i] > 0) { //only add new id's. each spawn is responsible for updating itself. if (!engine.Game.Spawns.ContainsIndex(i)) { //create the spawn and add it to the game data FFXISpawn spawn = new FFXISpawn(i, (IntPtr)spawnList[i], this); engine.Game.Spawns.Add(spawn); //spawn.DEBUGHOVER = "pointer: " + spawnList[i].ToString("X") + " index: " + i; //add the spawn to the server lookup table. this is used later to convert the claim id if (spawn.Type == SpawnType.Player) { if (m_ServerIDLookup.ContainsKey(spawn.ServerID)) m_ServerIDLookup[spawn.ServerID] = spawn; else m_ServerIDLookup.Add(spawn.ServerID, spawn); //add the server id to the lookup table } } } } //fill in the player and target UInt32 myID = reader.ReadStruct<UInt32>(pMyID); engine.Game.setPlayer(myID, true); UInt32 myTarget = reader.ReadStruct<UInt32>(pMyTarget); engine.Game.setTarget(myTarget, true); //force each spawn to self update engine.Game.Update(); //determine if the map image alternative requires processing if (engine.ShowMapAlternative && (lastPlayerLocation == null || (engine.Game.Player != null && !engine.Game.Player.Location.isEqual(lastPlayerLocation)))) { //Since the player has moved, determine if the map id has changed lastPlayerLocation = engine.Game.Player.Location.Clone(); curMap = m_imagemaps.GetCurrentMap(ZoneID, lastPlayerLocation); //only process if there is a map to display if (curMap != null) { /// IHM EDIT //Send the location in image coordinates to the engine. (I don't like doing it this way.) engine.LocInImage = curMap.Translate(engine.Game.Player.Location); //only process if the map has actually changed if (curMap.MapID != lastMapID) { engine.MapAlternativeImage = curMap.GetImage(); //set the background image RectangleF bounds = curMap.Bounds; //retrieve the map coodinate boundaries engine.MapAlternativeBounds = bounds; //set the origin/scale of the background image engine.Data.CheckBounds(bounds); //expand the map bounds (if necessary) to allow the map to be zoomed all the way out lastMapID = curMap.MapID; //set the map id so that the map isnt processed again until a change is made if (MapChanged != null) MapChanged(curMap, new EventArgs()); } } else if (engine.MapAlternativeImage != null) { //inform the engine that there is no map to display for the current location engine.MapAlternativeImage = null; lastMapID = -1; } } if (engine.Game.Spawns.Count > 0 && !zoneFinished) { zoneFinished = true; //automatically snap the range into view (if enabled) if (engine.AutoRangeSnap) engine.SnapToRange(); if (ZoneChanged != null) ZoneChanged(curMap, new EventArgs()); } return true; #if DEBUG } catch(Exception ex) { Debug.WriteLine("Error while polling the process: " + ex.Message); #else } catch { #endif return false; } }
private void DrawMap(FFXIImageMap map, Graphics g) { if (map == null) return; RectangleF bounds = map.Bounds; Image image = map.GetImage(); RectangleF dest = RectangleF.FromLTRB( window.Engine.CalcClientCoordX(bounds.Left), window.Engine.CalcClientCoordY(bounds.Top), window.Engine.CalcClientCoordX(bounds.Right), window.Engine.CalcClientCoordY(bounds.Bottom) ); if (image != null) { g.DrawImage(image, Rectangle.Round(dest), 0, 0, image.Width, image.Height, GraphicsUnit.Pixel); } else { g.FillRectangle(bTitleBG, dest); g.DrawLine(pHandleBorder, dest.Left, dest.Top, dest.Right, dest.Bottom); g.DrawLine(pHandleBorder, dest.Left, dest.Bottom, dest.Right, dest.Top); } string mapinfo = "Map " + map.MapID + " Scale: " + map.XScale + " Offset: " + map.XOffset + "," + map.YOffset; SizeF size = g.MeasureString(mapinfo, SystemFonts.DefaultFont); float x = engine.CalcClientCoordX(bounds.X); float y = engine.CalcClientCoordY(bounds.Y); g.FillRectangle(bTitleBG, x, y, size.Width + 2, size.Height + 2); g.DrawString(mapinfo, SystemFonts.DefaultFont, bTitle, x + 1, y + 1); }