示例#1
0
        private void Parse()
        {
            PrefabNodes   = new List <TsPrefabNode>();
            SpawnPoints   = new List <TsSpawnPoint>();
            MapPoints     = new List <TsMapPoint>();
            TriggerPoints = new List <TsTriggerPoint>();

            var fileOffset = 0x0;

            var version = MemoryHelper.ReadInt32(_stream, fileOffset);

            if (version < 0x15)
            {
                Log.Msg($"{_filePath} file version ({version}) too low, min. is {0x15}");
                return;
            }

            var nodeCount         = BitConverter.ToInt32(_stream, fileOffset += 0x04);
            var spawnPointCount   = BitConverter.ToInt32(_stream, fileOffset += 0x10);
            var mapPointCount     = BitConverter.ToInt32(_stream, fileOffset += 0x0C);
            var triggerPointCount = BitConverter.ToInt32(_stream, fileOffset += 0x04);

            if (version > 0x15)
            {
                fileOffset += 0x04;                 // http://modding.scssoft.com/wiki/Games/ETS2/Modding_guides/1.30#Prefabs
            }
            var nodeOffset         = MemoryHelper.ReadInt32(_stream, fileOffset += 0x08);
            var spawnPointOffset   = MemoryHelper.ReadInt32(_stream, fileOffset += 0x10);
            var mapPointOffset     = MemoryHelper.ReadInt32(_stream, fileOffset += 0x10);
            var triggerPointOffset = MemoryHelper.ReadInt32(_stream, fileOffset += 0x04);

            for (var i = 0; i < nodeCount; i++)
            {
                var nodeBaseOffset = nodeOffset + (i * NodeBlockSize);
                var node           = new TsPrefabNode
                {
                    X    = MemoryHelper.ReadSingle(_stream, nodeBaseOffset + 0x10),
                    Z    = MemoryHelper.ReadSingle(_stream, nodeBaseOffset + 0x18),
                    RotX = MemoryHelper.ReadSingle(_stream, nodeBaseOffset + 0x1C),
                    RotZ = MemoryHelper.ReadSingle(_stream, nodeBaseOffset + 0x24),
                };
                PrefabNodes.Add(node);
            }

            for (var i = 0; i < spawnPointCount; i++)
            {
                var spawnPointBaseOffset = spawnPointOffset + (i * SpawnPointBlockSize);
                var spawnPoint           = new TsSpawnPoint
                {
                    X    = MemoryHelper.ReadSingle(_stream, spawnPointBaseOffset),
                    Z    = MemoryHelper.ReadSingle(_stream, spawnPointBaseOffset + 0x08),
                    Type = (TsSpawnPointType)MemoryHelper.ReadUInt32(_stream, spawnPointBaseOffset + 0x1C)
                };
                var pointInVicinity = SpawnPoints.FirstOrDefault(point => // check if any other spawn points with the same type are close
                                                                 point.Type == spawnPoint.Type &&
                                                                 ((spawnPoint.X > point.X - 4 && spawnPoint.X < point.X + 4) ||
                                                                  (spawnPoint.Z > point.Z - 4 && spawnPoint.Z < point.Z + 4)));
                if (pointInVicinity == null)
                {
                    SpawnPoints.Add(spawnPoint);
                }
                // Log.Msg($"Spawn point of type: {spawnPoint.Type} in {_filePath}");
            }

            for (var i = 0; i < mapPointCount; i++)
            {
                var mapPointBaseOffset = mapPointOffset + (i * MapPointBlockSize);
                var roadLookFlags      = MemoryHelper.ReadUint8(_stream, mapPointBaseOffset + 0x01);
                var laneTypeFlags      = (byte)(roadLookFlags & 0x0F);
                var laneOffsetFlags    = (byte)(roadLookFlags >> 4);
                int laneOffset;
                switch (laneOffsetFlags)
                {
                case 1: laneOffset = 1; break;

                case 2: laneOffset = 2; break;

                case 3: laneOffset = 5; break;

                case 4: laneOffset = 10; break;

                case 5: laneOffset = 15; break;

                case 6: laneOffset = 20; break;

                case 7: laneOffset = 25; break;

                default: laneOffset = 0; break;
                }
                int laneCount;
                switch (laneTypeFlags) // TODO: Change these (not really used atm)
                {
                case 0: laneCount = 1; break;

                case 1: laneCount = 2; break;

                case 2: laneCount = 4; break;

                case 3: laneCount = 6; break;

                case 4: laneCount = 8; break;

                case 5: laneCount = 5; break;

                case 6: laneCount = 7; break;

                case 8: laneCount = 3; break;

                case 13: laneCount = -1; break;

                case 14: laneCount = 2; break;     // auto ; temp set at 2

                default:
                    laneCount = 1;
                    // Log.Msg($"Unknown LaneType: {laneTypeFlags}");
                    break;
                }

                var prefabColorFlags = MemoryHelper.ReadUint8(_stream, mapPointBaseOffset + 0x02);

                var navFlags = MemoryHelper.ReadUint8(_stream, mapPointBaseOffset + 0x05);
                var hidden   = (navFlags & 0x02) != 0; // Map Point is Control Node

                var point = new TsMapPoint
                {
                    LaneCount        = laneCount,
                    LaneOffset       = laneOffset,
                    Hidden           = hidden,
                    PrefabColorFlags = prefabColorFlags,
                    X              = MemoryHelper.ReadSingle(_stream, mapPointBaseOffset + 0x08),
                    Z              = MemoryHelper.ReadSingle(_stream, mapPointBaseOffset + 0x10),
                    Neighbours     = new List <int>(),
                    NeighbourCount = MemoryHelper.ReadInt32(_stream, mapPointBaseOffset + 0x14 + (0x04 * 6))
                };

                for (var x = 0; x < point.NeighbourCount; x++)
                {
                    point.Neighbours.Add(MemoryHelper.ReadInt32(_stream, mapPointBaseOffset + 0x14 + (x * 0x04)));
                }

                MapPoints.Add(point);
            }

            for (var i = 0; i < triggerPointCount; i++)
            {
                var triggerPointBaseOffset = triggerPointOffset + (i * TriggerPointBlockSize);
                var triggerPoint           = new TsTriggerPoint
                {
                    TriggerId        = MemoryHelper.ReadUInt32(_stream, triggerPointBaseOffset),
                    TriggerActionUid = MemoryHelper.ReadUInt64(_stream, triggerPointBaseOffset + 0x04),
                    X = MemoryHelper.ReadSingle(_stream, triggerPointBaseOffset + 0x1C),
                    Z = MemoryHelper.ReadSingle(_stream, triggerPointBaseOffset + 0x24),
                };
                var pointInVicinity = TriggerPoints.FirstOrDefault(point => // check if any other trigger points with the same id are close
                                                                   point.TriggerActionUid == triggerPoint.TriggerActionUid &&
                                                                   ((triggerPoint.X > point.X - 20 && triggerPoint.X < point.X + 20) ||
                                                                    (triggerPoint.Z > point.Z - 20 && triggerPoint.Z < point.Z + 20)));
                if (pointInVicinity == null)
                {
                    TriggerPoints.Add(triggerPoint);
                }
            }

            _stream = null;
        }
示例#2
0
        public void Parse()
        {
            Version = BitConverter.ToInt32(Stream, 0x0);

            if (Version < 825)
            {
                Log.Msg($"{FilePath} version ({Version}) is too low, min. is 825");
                return;
            }

            var itemCount = BitConverter.ToUInt32(Stream, 0x10);

            if (itemCount == 0)
            {
                _empty = true;
            }
            if (_empty)
            {
                return;
            }

            var lastOffset = 0x14;

            for (var i = 0; i < itemCount; i++)
            {
                var type = (TsItemType)MemoryHelper.ReadUInt32(Stream, lastOffset);
                if (Version <= 825)
                {
                    type++;                 // after version 825 all types were pushed up 1
                }
                switch (type)
                {
                case TsItemType.Road:
                {
                    var item = new TsRoadItem(this, lastOffset);
                    lastOffset += item.BlockSize;
                    if (item.Valid)
                    {
                        Mapper.Roads.Add(item);
                    }
                    break;
                }

                case TsItemType.Prefab:
                {
                    var item = new TsPrefabItem(this, lastOffset);
                    lastOffset += item.BlockSize;
                    if (item.Valid)
                    {
                        Mapper.Prefabs.Add(item);
                    }
                    break;
                }

                case TsItemType.Company:
                {
                    var item = new TsCompanyItem(this, lastOffset);
                    lastOffset += item.BlockSize;
                    if (item.Valid)
                    {
                        Mapper.Companies.Add(item);
                    }
                    break;
                }

                case TsItemType.Service:
                {
                    var item = new TsServiceItem(this, lastOffset);
                    lastOffset += item.BlockSize;
                    break;
                }

                case TsItemType.CutPlane:
                {
                    var item = new TsCutPlaneItem(this, lastOffset);
                    lastOffset += item.BlockSize;
                    break;
                }

                case TsItemType.City:
                {
                    var item = new TsCityItem(this, lastOffset);
                    lastOffset += item.BlockSize;
                    if (item.Valid)
                    {
                        Mapper.Cities.Add(item);
                    }
                    break;
                }

                case TsItemType.MapOverlay:
                {
                    var item = new TsMapOverlayItem(this, lastOffset);
                    lastOffset += item.BlockSize;
                    if (item.Valid)
                    {
                        Mapper.MapOverlays.Add(item);
                    }
                    break;
                }

                case TsItemType.Ferry:
                {
                    var item = new TsFerryItem(this, lastOffset);
                    lastOffset += item.BlockSize;
                    if (item.Valid)
                    {
                        Mapper.FerryConnections.Add(item);
                    }
                    break;
                }

                case TsItemType.Garage:
                {
                    var item = new TsGarageItem(this, lastOffset);
                    lastOffset += item.BlockSize;
                    break;
                }

                case TsItemType.Trigger:
                {
                    var item = new TsTriggerItem(this, lastOffset);
                    lastOffset += item.BlockSize;
                    if (item.Valid)
                    {
                        Mapper.Triggers.Add(item);
                    }
                    break;
                }

                case TsItemType.FuelPump:
                {
                    var item = new TsFuelPumpItem(this, lastOffset);
                    lastOffset += item.BlockSize;
                    break;
                }

                case TsItemType.RoadSideItem:
                {
                    var item = new TsRoadSideItem(this, lastOffset);
                    lastOffset += item.BlockSize;
                    break;
                }

                case TsItemType.BusStop:
                {
                    var item = new TsBusStopItem(this, lastOffset);
                    lastOffset += item.BlockSize;
                    break;
                }

                case TsItemType.TrafficRule:
                {
                    var item = new TsTrafficRuleItem(this, lastOffset);
                    lastOffset += item.BlockSize;
                    break;
                }

                case TsItemType.TrajectoryItem:
                {
                    var item = new TsTrajectoryItem(this, lastOffset);
                    lastOffset += item.BlockSize;
                    break;
                }

                case TsItemType.MapArea:
                {
                    var item = new TsMapAreaItem(this, lastOffset);
                    lastOffset += item.BlockSize;
                    if (item.Valid)
                    {
                        Mapper.MapAreas.Add(item);
                    }
                    break;
                }

                default:
                {
                    Log.Msg($"Unknown Type: {type} in {Path.GetFileName(FilePath)} @ {lastOffset}");
                    break;
                }
                }
            }

            var nodeCount = MemoryHelper.ReadInt32(Stream, lastOffset);

            for (var i = 0; i < nodeCount; i++)
            {
                TsNode node = new TsNode(this, lastOffset += 0x04);
                Mapper.UpdateEdgeCoords(node);
                if (!Mapper.Nodes.ContainsKey(node.Uid))
                {
                    Mapper.Nodes.Add(node.Uid, node);
                }
                lastOffset += 0x34;
            }
        }
示例#3
0
        private void ParseDxt5() // https://msdn.microsoft.com/en-us/library/windows/desktop/bb694531
        {
            var fileOffset = 0x80;

            _pixelData = new Color8888[Width * Height];
            for (var y = 0; y < Height; y += 4)
            {
                for (var x = 0; x < Width; x += 4)
                {
                    var alphas = new byte[8];
                    alphas[0] = _stream[fileOffset];
                    alphas[1] = _stream[fileOffset += 0x01];

                    if (alphas[0] > alphas[1])
                    {
                        // 6 interpolated alpha values.
                        alphas[2] = (byte)((double)6 / 7 * alphas[0] + (double)1 / 7 * alphas[1]);    // bit code 010
                        alphas[3] = (byte)((double)5 / 7 * alphas[0] + (double)2 / 7 * alphas[1]);    // bit code 011
                        alphas[4] = (byte)((double)4 / 7 * alphas[0] + (double)3 / 7 * alphas[1]);    // bit code 100
                        alphas[5] = (byte)((double)3 / 7 * alphas[0] + (double)4 / 7 * alphas[1]);    // bit code 101
                        alphas[6] = (byte)((double)2 / 7 * alphas[0] + (double)5 / 7 * alphas[1]);    // bit code 110
                        alphas[7] = (byte)((double)1 / 7 * alphas[0] + (double)6 / 7 * alphas[1]);    // bit code 111
                    }
                    else
                    {
                        // 4 interpolated alpha values.
                        alphas[2] = (byte)((double)4 / 5 * alphas[0] + (double)1 / 5 * alphas[1]); // bit code 010
                        alphas[3] = (byte)((double)3 / 5 * alphas[0] + (double)2 / 5 * alphas[1]); // bit code 011
                        alphas[4] = (byte)((double)2 / 5 * alphas[0] + (double)3 / 5 * alphas[1]); // bit code 100
                        alphas[5] = (byte)((double)1 / 5 * alphas[0] + (double)4 / 5 * alphas[1]); // bit code 101
                        alphas[6] = 0;                                                             // bit code 110
                        alphas[7] = 255;                                                           // bit code 111
                    }

                    var alphaTexelUlongData = MemoryHelper.ReadUInt64(_stream, fileOffset += 0x01);

                    var alphaTexelData =
                        alphaTexelUlongData & 0xFFFFFFFFFFFF; // remove 2 excess bytes (read 8 bytes only need 6)

                    var alphaTexels = new byte[16];
                    for (var j = 0; j < 2; j++)
                    {
                        var alphaTexelRowData = (alphaTexelData >> (j * 0x18)) & 0xFFFFFF;
                        for (var i = 0; i < 8; i++)
                        {
                            var index = (alphaTexelRowData >> (i * 0x03)) & 0x07;
                            alphaTexels[i + j * 8] = alphas[index];
                        }
                    }

                    var color0 = new Color565(MemoryHelper.ReadUInt16(_stream, fileOffset += 0x06));
                    var color1 = new Color565(MemoryHelper.ReadUInt16(_stream, fileOffset += 0x02));

                    var color2 = (double)2 / 3 * color0 + (double)1 / 3 * color1;
                    var color3 = (double)1 / 3 * color0 + (double)2 / 3 * color1;

                    var colors = new[]
                    {
                        new Color8888(color0, 0xFF), // bit code 00
                        new Color8888(color1, 0xFF), // bit code 01
                        new Color8888(color2, 0xFF), // bit code 10
                        new Color8888(color3, 0xFF)  // bit code 11
                    };

                    var colorTexelData = MemoryHelper.ReadUInt32(_stream, fileOffset += 0x02);
                    for (var j = 3; j >= 0; j--)
                    {
                        var colorTexelRowData = (colorTexelData >> (j * 0x08)) & 0xFF;
                        for (var i = 0; i < 4; i++)
                        {
                            var index = (colorTexelRowData >> (i * 0x02)) & 0x03;
                            var pos   = (uint)(y * Width + j * Width + x + i);
                            _pixelData[pos] = colors[index];
                            _pixelData[pos].SetAlpha(alphaTexels[j * 4 + i]);
                        }
                    }
                    fileOffset += 0x04;
                }
            }
        }