public int JumpCompatibility(LevelMetadata level, string searchString) { int result = 0; switch (SortBy) { case SortBy.Creator: result = JumpCompatibility(level.Creator, searchString); break; case SortBy.Name: result = JumpCompatibility(level.Name, searchString); break; } return(result); }
public bool FindBrokenLink(ref LevelMetadata brokenLevel, ref bool forwardLink) { //initialize the out params - assume no broken link brokenLevel = null; forwardLink = false; //First, walk backwards to the first link LevelMetadata currentLink = this; LevelMetadata previousLink = null; LevelMetadata nextLink = null; while (currentLink.LinkedFromLevel != null) { //check to make sure the xml exists previousLink = currentLink.PreviousLink(); if (null == previousLink) { brokenLevel = currentLink; forwardLink = false; //broke walking backwards return(true); } currentLink = previousLink; } //first link now points to the beginning, walk forward to the end, ensuring we while (currentLink.LinkedToLevel != null) { //check to make sure the xml exists nextLink = currentLink.NextLink(); if (null == nextLink) { brokenLevel = currentLink; forwardLink = false; //broke walking backwards return(true); } currentLink = nextLink; } //if we made it this far, all of the links worked out return(false); }
internal void LevelAdded(int index, LevelMetadata level) { if (level.WorldId == desiredSelection && totalOpCount == 0) { // If we were looking for a specific level and the user hasn't explicitly moved the cursor, // move the cursor to point at the identified level. totalOpCount += 1; QueryPointer = index; } else if (totalOpCount > 0 && index <= QueryPointer && !Query.IsEmpty) { // If we want the cursor to remain on the current level, and the new level being added comes // before the current selection, this means the current level bumps forward in the query, so // adjust the selection to remain on the current level. QueryPointer += 1; } additionCallback(this, index - QueryPointer); }
private bool IsAlreadyDownloaded(LevelMetadata level) { string filename = BokuGame.Settings.MediaPath + BokuGame.DownloadsPath + level.WorldId.ToString() + @".Xml"; if (Storage4.FileExists(filename, StorageSource.UserSpace)) { XmlWorldData xml = XmlWorldData.Load(filename, XnaStorageHelper.Instance); if (xml != null) { LevelMetadata local = LevelMetadata.CreateFromXml(xml); return( local.WorldId == level.WorldId && local.Creator == level.Creator && local.LastWriteTime >= level.LastWriteTime); } } return(false); }
/// <summary> /// Start deleting a level from the community server. You must have adequate permissions or the server will deny your request. /// </summary> /// <param name="worldId"></param> /// <param name="callback"></param> /// <param name="param"></param> /// <returns></returns> public bool StartDeletingLevel( Guid worldId, Genres bucket, BokuAsyncCallback callback, object param) { int index = IndexOf(worldId); if (index >= 0) { LevelMetadata level = allLevels[index]; allLevels.RemoveAt(index); LevelRemoved(level); } return(0 != Web.Community.Async_DelWorldData2( worldId, Auth.Pin, callback, param)); }
public void StartDownloadingThumbnail(LevelMetadata level, ThumbnailDownloadCompleteEvent callback, bool lowPriority) { if (level != null && !level.Thumbnail.IsLoaded && !level.Thumbnail.Loading) { LevelBrowserState state = (LevelBrowserState)level.BrowserState; state.thumbnailCallback = callback; // If it already exists in the queue, move it to the end. queuedThumbnailLoads.Remove(level); queuedThumbnailLoads.Add(level); } // Only keep a max of 20 pending thumbnail loads, that way of we're just scrolling // to the end of the list, we can discard many of these requests as they pass out of view. while (queuedThumbnailLoads.Count > 20) { LevelBrowserState state = (LevelBrowserState)queuedThumbnailLoads[0].BrowserState; state.thumbnailCallback = null; queuedThumbnailLoads.RemoveAt(0); } }
public static LevelMetadata LoadMetadataByGenre(Guid worldId, Genres genres) { string bucket = BokuGame.MyWorldsPath; if (genres != 0) { bucket = Utils.FolderNameFromFlags(genres); } string fullPath = BokuGame.Settings.MediaPath + bucket + worldId.ToString() + @".Xml"; Xml.XmlWorldData xml = XmlWorldData.Load(fullPath, XnaStorageHelper.Instance); if (xml != null) { LevelMetadata data = new LevelMetadata(); data.FromXml(xml); //minor hackery - seems previous versions of kodu will sometimes leave the genres set to 0 //even though they should be updated for the bucket the level is in. Then at load time, a run-time //genre is set. This code will maintain that behavior for levels loaded through this helper if (bucket == BokuGame.DownloadsPath) { //ensure downloads always have the downloads flag data.Genres |= Genres.Downloads; } else if (bucket == BokuGame.BuiltInWorldsPath) { //ensure built in worlds always have the built in flag data.Genres |= Genres.BuiltInWorlds; } else if (bucket == BokuGame.MyWorldsPath) { data.Genres |= Genres.MyWorlds; } return(data); } return(null); }
public static LevelMetadata LoadMetadataUnknownGenre(Guid worldId) { LevelMetadata result = null; if (CheckWorldExistsByGenre(worldId, Genres.MyWorlds)) { result = LoadMetadataByGenre(worldId, Genres.MyWorlds); result.Genres |= Genres.MyWorlds; } else if (CheckWorldExistsByGenre(worldId, Genres.Downloads)) { result = LoadMetadataByGenre(worldId, Genres.Downloads); result.Genres |= Genres.Downloads; } else if (CheckWorldExistsByGenre(worldId, Genres.BuiltInWorlds)) { result = LoadMetadataByGenre(worldId, Genres.BuiltInWorlds); result.Genres |= Genres.BuiltInWorlds; } return(result); }
public void Update() { lock (Synch) { foreach (LevelSetQuery query in queries) { query.Update(); } } if (thumbnailLoadOpCount == 0 && queuedThumbnailLoads.Count > 0) { // Pull from the end of the list to service newer requests first. LevelMetadata level = queuedThumbnailLoads[queuedThumbnailLoads.Count - 1]; queuedThumbnailLoads.RemoveAt(queuedThumbnailLoads.Count - 1); thumbnailLoadOpCount += 1; Web.Community.Async_GetThumbnail( level.WorldId, level.Thumbnail, GotThumbnail, level); } }
public void MetadataUpdated(LevelMetadata level) { }
/// <summary> /// Delete a level from the local system. Returns false if not yet initialized. /// </summary> /// <param name="worldId"></param> /// <param name="callback"></param> /// <param name="param"></param> /// <returns></returns> public bool StartDeletingLevel( Guid worldId, Genres bucket, BokuAsyncCallback callback, object param) { bool deleted = false; bucket &= Genres.SharableBins; // Verify exactly one bucket is specified Debug.Assert(bucket != 0); Debug.Assert((int)bucket == int.MinValue || MyMath.IsPowerOfTwo((int)bucket)); string worldFilename = null; string stuffFilename = null; string thumbFilename = null; LevelMetadata record = null; string stuffPath = String.Empty; string worldPath = String.Empty; if (0 != (bucket & Genres.MyWorlds)) { stuffPath = BokuGame.MyWorldsStuffPath; worldPath = BokuGame.MyWorldsPath; } else if (0 != (bucket & Genres.Downloads)) { stuffPath = BokuGame.DownloadsStuffPath; worldPath = BokuGame.DownloadsPath; } lock (Synch) { for (int i = 0; i < allLevels.Count; ++i) { record = allLevels[i]; if (record.WorldId == worldId && (record.Genres & bucket) == bucket) { worldFilename = Path.Combine(BokuGame.Settings.MediaPath, worldPath + worldId.ToString() + @".Xml"); stuffFilename = Path.Combine(BokuGame.Settings.MediaPath, stuffPath + worldId.ToString() + @".Xml"); thumbFilename = Path.Combine(BokuGame.Settings.MediaPath, worldPath + worldId.ToString()); // Need to get the terrain file before we delete the main file. BUT the terrain should be // deleted after, otherwise the usage test will find the main file and always thing that // the terrain file is in use. string terrainFilename = null; try { // Only delete terrain file if no longer referenced. XmlWorldData xmlWorldData = XmlWorldData.Load(worldFilename, XnaStorageHelper.Instance); terrainFilename = xmlWorldData.xmlTerrainData2.virtualMapFile; } catch { } // Note : Delete() handles non-existent files just fine. Storage4.Delete(worldFilename); Storage4.Delete(stuffFilename); Storage4.Delete(thumbFilename + @".dds"); Storage4.Delete(thumbFilename + @".jpg"); Storage4.Delete(thumbFilename + @".png"); // Only deletes terrain file if no other world is using it. (including autosaves) DeleteTerrainFile(terrainFilename); LevelMetadata level = allLevels[i]; allLevels.RemoveAt(i); LevelRemoved_Synched(level); deleted = true; break; } } } AsyncResult result = new AsyncResult(); result.Success = deleted; result.Param = param; result.Seconds = 0; if (callback != null) { callback(result); } return(deleted); }
} //True allows server side to handle matches public bool Matches(LevelMetadata item) { return(true); }
/// <summary> /// Based on the current filter's tags, decides whether or not a level matches. /// Note that this logic must match the logic on the server side otherwise /// madness ensues. /// </summary> /// <param name="item"></param> /// <returns></returns> virtual public bool Matches(LevelMetadata item) { //check for server side matching if (ServerSideMatching) { return(true); } Genres itemGenres = item.Genres; if (FilterGenres == Genres.All) { return(true); } // If all the bucket tags are set, don't bother filtering on MyWorlds. Genres filterBuckets = FilterGenres & Genres.Buckets; if (filterBuckets != Genres.Buckets) { // If MyWorlds is set, filter out anything that the user didn't author. if ((FilterGenres & Genres.MyWorlds) != 0) { // First look for the right name. if (Auth.CreatorName == item.Creator && !string.IsNullOrEmpty(item.Checksum)) { if (!Auth.IsValidCreatorChecksum(item.Checksum, item.LastWriteTime)) { return(false); } } else { return(false); } } } // If no bucket bits are set, that means the bucket is All. if (filterBuckets == 0 || filterBuckets == Genres.Buckets) { // Must be All, so don't filter. } else { // If any bucket is set, filter out anything that doesn't match. if ((itemGenres & filterBuckets) == 0) { return(false); } } // Now that we've filtered on the buckets, we're left with filtering on // the individual tags so grab that subset. Genres filterTags = FilterGenres & Genres.NonBucket; if (filterTags == Genres.NonBucket) { // All set so everything passes. } else { // Look for any matches. if ((int)(filterTags & itemGenres) == 0) { // No match. return(false); } } return(true); }