public CustomLevelSelectSection() { levelList = new List <CustomLevel>(); isLoading = true; isLoadingAnimation = 1f; ThreadPool.UnsafeQueueUserWorkItem(_ => { JsonParser json = new JsonParser(); try { string path = PathOp.Combine(DualityApp.DataDirectory, "Episodes", "unknown"); if (DirectoryOp.Exists(path)) { foreach (string levelPath in DirectoryOp.GetFiles(path)) { if (api == null) { break; } if (!levelPath.EndsWith(".level")) { continue; } IFileSystem levelPackage = new CompressedContent(levelPath); using ( Stream s = levelPackage.OpenFile(".res", FileAccessMode.Read)) { string levelToken = PathOp.GetFileNameWithoutExtension(levelPath); LevelConfigJson config = json.Parse <LevelConfigJson>(s); string icon = ""; #if DEBUG if ((config.Description.Flags & LevelFlags.FastCamera) != 0) { icon += " Fast"; } if ((config.Description.Flags & LevelFlags.HasPit) != 0) { icon += " Pit"; } #endif if ((config.Description.Flags & LevelFlags.Multiplayer) != 0 && (config.Description.Flags & (LevelFlags.MultiplayerRace | LevelFlags.MultiplayerFlags)) == 0) { icon += " Battle"; } if ((config.Description.Flags & LevelFlags.MultiplayerRace) != 0) { icon += " Race"; } if ((config.Description.Flags & LevelFlags.MultiplayerFlags) != 0) { icon += " CTF"; } levelList.Add(new CustomLevel(config.Description.Name, "unknown", levelToken, icon)); } } levelList.Sort((x, y) => { string xs = BitmapFont.StripFormatting(x.DisplayName); string ys = BitmapFont.StripFormatting(y.DisplayName); int i = string.Compare(xs, ys, StringComparison.InvariantCulture); if (i != 0) { return(i); } return(string.Compare(x.LevelName, y.LevelName, StringComparison.InvariantCulture)); }); } } catch { // ToDo: Handle exceptions } finally { isLoading = false; } }, null); }
private void PrerenderTexturedBackground() { try { // Try to use "The Secret Files" background string levelPath = PathOp.Combine(DualityApp.DataDirectory, "Episodes", "secretf", "01_easter1.level"); if (!FileOp.Exists(levelPath)) { // Try to use "Base Game" background levelPath = PathOp.Combine(DualityApp.DataDirectory, "Episodes", "prince", "03_carrot1.level"); if (!FileOp.Exists(levelPath)) { // Try to use "Holiday Hare '98" background levelPath = PathOp.Combine(DualityApp.DataDirectory, "Episodes", "xmas98", "03_xmas3.level"); if (!FileOp.Exists(levelPath)) { // Try to use "Christmas Chronicles" background levelPath = PathOp.Combine(DualityApp.DataDirectory, "Episodes", "xmas99", "03_xmas3.level"); if (!FileOp.Exists(levelPath)) { // Try to use "Shareware Demo" background; levelPath = PathOp.Combine(DualityApp.DataDirectory, "Episodes", "share", "02_share2.level"); if (!FileOp.Exists(levelPath)) { // No usable background found throw new FileNotFoundException(); } } } } } // Load metadata IFileSystem levelPackage = new CompressedContent(levelPath); LevelHandler.LevelConfigJson config; using (Stream s = levelPackage.OpenFile(".res", FileAccessMode.Read)) { config = ContentResolver.Current.Json.Parse <LevelHandler.LevelConfigJson>(s); } LevelHandler.LevelConfigJson.LayerSection layer; if (config.Layers.TryGetValue("Sky", out layer)) { if (layer.BackgroundColor != null && layer.BackgroundColor.Count >= 3) { horizonColor = new Vector4(layer.BackgroundColor[0] / 255f, layer.BackgroundColor[1] / 255f, layer.BackgroundColor[2] / 255f, 1f); } switch ((BackgroundStyle)layer.BackgroundStyle) { default: case BackgroundStyle.Sky: texturedBackgroundShader = ContentResolver.Current.RequestShader("TexturedBackground"); break; case BackgroundStyle.Circle: texturedBackgroundShader = ContentResolver.Current.RequestShader("TexturedBackgroundCircle"); break; } } // Render background layer to texture TileSet levelTileset = new TileSet(config.Description.DefaultTileset, true, null); if (!levelTileset.IsValid) { throw new InvalidDataException(); } using (Stream s = levelPackage.OpenFile("Sky.layer", FileAccessMode.Read)) { using (BinaryReader r = new BinaryReader(s)) { int width = r.ReadInt32(); int height = r.ReadInt32(); TileMapLayer newLayer = new TileMapLayer(); newLayer.Layout = new LayerTile[width * height]; for (int i = 0; i < newLayer.Layout.Length; i++) { ushort tileType = r.ReadUInt16(); byte flags = r.ReadByte(); if (flags == 0) { newLayer.Layout[i] = levelTileset.GetDefaultTile(tileType); continue; } bool isFlippedX = (flags & 0x01) > 0; bool isFlippedY = (flags & 0x02) > 0; bool isAnimated = (flags & 0x04) > 0; bool legacyTranslucent = (flags & 0x80) > 0; // Invalid tile numbers (higher than tileset tile amount) are silently changed to empty tiles if (tileType >= levelTileset.TileCount && !isAnimated) { tileType = 0; } LayerTile tile; // Copy the default tile and do stuff with it tile = levelTileset.GetDefaultTile(tileType); tile.IsFlippedX = isFlippedX; tile.IsFlippedY = isFlippedY; tile.IsAnimated = isAnimated; if (legacyTranslucent) { tile.MaterialAlpha = /*127*/ 140; } newLayer.Layout[i] = tile; } newLayer.LayoutWidth = width; RecreateTexturedBackground(levelTileset, ref newLayer); } } } catch (Exception ex) { Log.Write(LogType.Warning, "Cannot prerender textured background: " + ex); cachedTexturedBackground = new Texture(new Pixmap(new PixelData(2, 2, ColorRgba.Black))); } }
public void RequestTileset(string path, bool applyPalette, ColorRgba[] customPalette, out ContentRef<Material> materialRef, out PixelData mask) { IFileSystem tilesetPackage = new CompressedContent(PathOp.Combine(DualityApp.DataDirectory, "Tilesets", path + ".set")); // Palette if (applyPalette) { if (customPalette != null) { ApplyBasePalette(customPalette); } else if (tilesetPackage.FileExists("Main.palette")) { ApplyBasePalette(TileSet.LoadPalette(tilesetPackage.OpenFile("Main.palette", FileAccessMode.Read))); } } // Load textures PixelData texturePixels; using (Stream s = tilesetPackage.OpenFile("Diffuse.png", FileAccessMode.Read)) { texturePixels = new Png(s).GetPixelData(); } #if !DISABLE_NORMAL_MAPPING PixelData normalPixels; if (tilesetPackage.FileExists("Normals.png")) { using (Stream s = tilesetPackage.OpenFile("Normals.png", FileAccessMode.Read)) { normalPixels = new Png(s).GetPixelData(); } } else { normalPixels = null; } #endif using (Stream s = tilesetPackage.OpenFile("Mask.png", FileAccessMode.Read)) { mask = new Png(s).GetPixelData(); } // Apply palette to tileset ColorRgba[] palette = paletteTexture.Res.BasePixmap.Res.MainLayer.Data; ColorRgba[] data = texturePixels.Data; #if !DISABLE_ASYNC Parallel.ForEach(Partitioner.Create(0, data.Length), range => { for (int i = range.Item1; i < range.Item2; i++) { #else for (int i = 0; i < data.Length; i++) { #endif int colorIdx = data[i].R; data[i] = palette[colorIdx].WithAlpha(palette[colorIdx].A * data[i].A / (255f * 255f)); } #if !DISABLE_ASYNC }); #endif ContentRef<Texture> mainTex = new Texture(new Pixmap(texturePixels)); ContentRef<Texture> normalTex; #if !DISABLE_NORMAL_MAPPING if (normalPixels == null) { normalTex = DefaultNormalMap; } else { normalTex = new Texture(new Pixmap(normalPixels)); normalTex.Res.DetachSource(); } #else normalTex = DefaultNormalMap; #endif // Create material Material material = new Material(RequestShader("BasicNormal")); material.SetTexture("mainTex", mainTex); material.SetTexture("normalTex", normalTex); material.SetValue("normalMultiplier", Vector2.One); materialRef = material; }
private void LoadLevel(string level, string episode) { string levelPath = PathOp.Combine(DualityApp.DataDirectory, "Episodes", episode, level + ".level"); IFileSystem levelPackage = new CompressedContent(levelPath); // ToDo: Cache parser, move JSON parsing to ContentResolver JsonParser jsonParser = new JsonParser(); LevelConfigJson json; using (Stream s = levelPackage.OpenFile(".res", FileAccessMode.Read)) { json = jsonParser.Parse <LevelConfigJson>(s); } if (json.Version.LayerFormat > LayerFormatVersion || json.Version.EventSet > EventSetVersion) { throw new NotSupportedException("Level version not supported"); } App.Log("Loading level \"" + json.Description.Name + "\"..."); root.Title = BitmapFont.StripFormatting(json.Description.Name); root.Immersive = false; defaultNextLevel = json.Description.NextLevel; defaultSecretLevel = json.Description.SecretLevel; ambientLightDefault = json.Description.DefaultLight; ambientLightCurrent = ambientLightTarget = ambientLightDefault * 0.01f; if (json.Description.DefaultDarkness != null && json.Description.DefaultDarkness.Count >= 4) { darknessColor = new Vector4(json.Description.DefaultDarkness[0] / 255f, json.Description.DefaultDarkness[1] / 255f, json.Description.DefaultDarkness[2] / 255f, json.Description.DefaultDarkness[3] / 255f); } else { darknessColor = new Vector4(0, 0, 0, 1); } // Palette ColorRgba[] tileMapPalette; if (levelPackage.FileExists("Main.palette")) { using (Stream s = levelPackage.OpenFile("Main.palette", FileAccessMode.Read)) { tileMapPalette = TileSet.LoadPalette(s); } } else { tileMapPalette = null; } // Tileset tileMap = new TileMap(this, json.Description.DefaultTileset, tileMapPalette, (json.Description.Flags & LevelFlags.HasPit) != 0); // Additional tilesets if (json.Tilesets != null) { for (int i = 0; i < json.Tilesets.Count; i++) { LevelConfigJson.TilesetSection part = json.Tilesets[i]; tileMap.ReadTilesetPart(part.Name, part.Offset, part.Count); } } // Read all layers json.Layers.Add("Sprite", new LevelConfigJson.LayerSection { XSpeed = 1, YSpeed = 1 }); foreach (var layer in json.Layers.OrderBy(layer => layer.Value.Depth)) { LayerType type; if (layer.Key == "Sprite") { type = LayerType.Sprite; } else if (layer.Key == "Sky") { type = LayerType.Sky; //if (layer.Value.BackgroundStyle != 0 /*Plain*/ && layer.Value.BackgroundColor != null && layer.Value.BackgroundColor.Count >= 3) { // camera.GetComponent<Camera>().ClearColor = new ColorRgba((byte)layer.Value.BackgroundColor[0], (byte)layer.Value.BackgroundColor[1], (byte)layer.Value.BackgroundColor[2]); //} } else { type = LayerType.Other; } using (Stream s = levelPackage.OpenFile(layer.Key + ".layer", FileAccessMode.Read)) { tileMap.ReadLayerConfiguration(type, s, layer.Value); } } // Read animated tiles if (levelPackage.FileExists("Animated.tiles")) { using (Stream s = levelPackage.OpenFile("Animated.tiles", FileAccessMode.Read)) { tileMap.ReadAnimatedTiles(s); } } levelBounds = new Rect(tileMap.Size * tileMap.Tileset.TileSize); // Read events eventMap = new EventMap(this, tileMap.Size); if (levelPackage.FileExists("Events.layer")) { using (Stream s2 = levelPackage.OpenFile("Events.layer", FileAccessMode.Read)) { eventMap.ReadEvents(s2, json.Version.LayerFormat, difficulty); } } GameObject tilemapHandler = new GameObject(); tilemapHandler.Parent = rootObject; tilemapHandler.AddComponent(tileMap); // Load default music musicPath = PathOp.Combine(DualityApp.DataDirectory, "Music", json.Description.DefaultMusic); music = new OpenMptStream(musicPath, true); music.BeginFadeIn(0.5f); DualityApp.Sound.PlaySound(music); // Apply weather if (json.Description.DefaultWeather != WeatherType.None) { ApplyWeather( json.Description.DefaultWeather, json.Description.DefaultWeatherIntensity, json.Description.DefaultWeatherOutdoors); } // Load level text events levelTexts = json.TextEvents ?? new List <string>(); if (FileOp.Exists(levelPath + "." + i18n.Language)) { try { using (Stream s = FileOp.Open(levelPath + "." + i18n.Language, FileAccessMode.Read)) { json = jsonParser.Parse <LevelConfigJson>(s); if (json.TextEvents != null) { for (int i = 0; i < json.TextEvents.Count && i < levelTexts.Count; i++) { if (json.TextEvents[i] != null) { levelTexts[i] = json.TextEvents[i]; } } } } } catch (Exception ex) { App.Log("Cannot load i18n for this level: " + ex); } } }
private void LoadLevel(string level, string episode) { string levelPath = PathOp.Combine(DualityApp.DataDirectory, "Episodes", episode, level + ".level"); IFileSystem levelPackage = new CompressedContent(levelPath); LevelConfigJson json; using (Stream s = levelPackage.OpenFile(".res", FileAccessMode.Read)) { json = ContentResolver.Current.Json.Parse <LevelConfigJson>(s); } if (json.Version.LayerFormat > LayerFormatVersion || json.Version.EventSet > EventSetVersion) { throw new NotSupportedException("Level version not supported"); } Log.Write(LogType.Info, "Loading level \"" + json.Description.Name + "\"..."); levelFriendlyName = json.Description.Name; //defaultNextLevel = json.Description.NextLevel; //defaultSecretLevel = json.Description.SecretLevel; // Palette ColorRgba[] tileMapPalette; if (levelPackage.FileExists("Main.palette")) { using (Stream s = levelPackage.OpenFile("Main.palette", FileAccessMode.Read)) { tileMapPalette = TileSet.LoadPalette(s); } } else { tileMapPalette = null; } // Tileset tileMap = new TileMap(this, json.Description.DefaultTileset, tileMapPalette, (json.Description.Flags & LevelFlags.HasPit) != 0); // Additional tilesets if (json.Tilesets != null) { for (int i = 0; i < json.Tilesets.Count; i++) { LevelConfigJson.TilesetSection part = json.Tilesets[i]; tileMap.ReadTilesetPart(part.Name, part.Offset, part.Count); } } // Read all layers json.Layers.Add("Sprite", new LevelConfigJson.LayerSection { XSpeed = 1, YSpeed = 1 }); foreach (var layer in json.Layers.OrderBy(layer => layer.Value.Depth)) { LayerType type; if (layer.Key == "Sprite") { type = LayerType.Sprite; } else if (layer.Key == "Sky") { type = LayerType.Sky; //if (layer.Value.BackgroundStyle != 0 /*Plain*/ && layer.Value.BackgroundColor != null && layer.Value.BackgroundColor.Count >= 3) { // camera.GetComponent<Camera>().ClearColor = new ColorRgba((byte)layer.Value.BackgroundColor[0], (byte)layer.Value.BackgroundColor[1], (byte)layer.Value.BackgroundColor[2]); //} } else { type = LayerType.Other; } using (Stream s = levelPackage.OpenFile(layer.Key + ".layer", FileAccessMode.Read)) { tileMap.ReadLayerConfiguration(type, s, layer.Value); } } // Read animated tiles if (levelPackage.FileExists("Animated.tiles")) { using (Stream s = levelPackage.OpenFile("Animated.tiles", FileAccessMode.Read)) { tileMap.ReadAnimatedTiles(s); } } levelBounds = new Rect(tileMap.Size * tileMap.Tileset.TileSize); // Read events eventMap = new EventMap(this, tileMap.Size); if (levelPackage.FileExists("Events.layer")) { using (Stream s2 = levelPackage.OpenFile("Events.layer", FileAccessMode.Read)) { eventMap.ReadEvents(s2, json.Version.LayerFormat, difficulty); } } GameObject tilemapHandler = new GameObject(); tilemapHandler.Parent = rootObject; tilemapHandler.AddComponent(tileMap); // Apply weather if (json.Description.DefaultWeather != WeatherType.None) { ApplyWeather( json.Description.DefaultWeather, json.Description.DefaultWeatherIntensity, json.Description.DefaultWeatherOutdoors); } // Load level text events levelTexts = json.TextEvents ?? new List <string>(); /*if (FileOp.Exists(levelPath + "." + i18n.Language)) { * try { * using (Stream s = FileOp.Open(levelPath + "." + i18n.Language, FileAccessMode.Read)) { * json = ContentResolver.Current.Json.Parse<LevelConfigJson>(s); * if (json.TextEvents != null) { * for (int i = 0; i < json.TextEvents.Count && i < levelTexts.Count; i++) { * if (json.TextEvents[i] != null) { * levelTexts[i] = json.TextEvents[i]; * } * } * } * } * } catch (Exception ex) { * Log.Write(LogType.Warning, "Cannot load i18n for this level: " + ex); * } * }*/ eventMap.ActivateEvents(int.MinValue, int.MinValue, int.MaxValue, int.MaxValue, false); }
public bool ChangeLevel(string levelName, MultiplayerLevelType levelType) { string path = Path.Combine(DualityApp.DataDirectory, "Episodes", levelName + ".level"); if (!File.Exists(path)) { return(false); } IFileSystem levelPackage = new CompressedContent(path); lock (sync) { currentLevel = levelName; currentLevelType = levelType; // Load new level using (Stream s = levelPackage.OpenFile(".res", FileAccessMode.Read)) { // ToDo: Cache parser JsonParser json = new JsonParser(); LevelHandler.LevelConfigJson config = json.Parse <LevelHandler.LevelConfigJson>(s); if (config.Version.LayerFormat > LevelHandler.LayerFormatVersion || config.Version.EventSet > LevelHandler.EventSetVersion) { throw new NotSupportedException("Version not supported"); } currentLevelFriendlyName = BitmapFont.StripFormatting(config.Description.Name); Log.Write(LogType.Info, "Loading level \"" + currentLevelFriendlyName + "\" (" + currentLevelType + ")..."); Point2 tileMapSize; using (Stream s2 = levelPackage.OpenFile("Sprite.layer", FileAccessMode.Read)) using (BinaryReader r = new BinaryReader(s2)) { tileMapSize.X = r.ReadInt32(); tileMapSize.Y = r.ReadInt32(); } levelBounds = new Rect(tileMapSize * /*tileMap.Tileset.TileSize*/ 32); collisions = new DynamicTreeBroadPhase <ICollisionable>(); // Read events eventMap = new ServerEventMap(tileMapSize); if (levelPackage.FileExists("Events.layer")) { using (Stream s2 = levelPackage.OpenFile("Events.layer", FileAccessMode.Read)) { eventMap.ReadEvents(s2, config.Version.LayerFormat); } } } // Send request to change level to all players foreach (KeyValuePair <NetConnection, Player> pair in players) { pair.Value.State = PlayerState.NotReady; } playerConnections.Clear(); foreach (KeyValuePair <NetConnection, Player> pair in players) { Send(new LoadLevel { LevelName = currentLevel, LevelType = currentLevelType, AssignedPlayerIndex = pair.Value.Index }, 64, pair.Key, NetDeliveryMethod.ReliableUnordered, PacketChannels.Main); } } return(true); }