Files
abysmal-isle/Ultima/Multis.cs
Unstable Kitsune b918192e4e Overwrite
Complete Overwrite of the Folder with the free shard. ServUO 57.3 has been added.
2023-11-28 23:20:26 -05:00

1305 lines
32 KiB
C#

#region References
using System;
using System.Collections.Generic;
using System.Drawing;
using System.Globalization;
using System.IO;
using System.Text;
using System.Text.RegularExpressions;
#endregion
namespace Ultima
{
public sealed class Multis
{
private static MultiComponentList[] m_Components = new MultiComponentList[0x2000];
private static FileIndex m_FileIndex = new FileIndex("Multi.idx", "Multi.mul", 0x2000, 14);
public enum ImportType
{
TXT,
UOA,
UOAB,
WSC,
MULTICACHE,
UOADESIGN
}
public static bool PostHSFormat { get; set; }
/// <summary>
/// ReReads multi.mul
/// </summary>
public static void Reload()
{
m_FileIndex = new FileIndex("Multi.idx", "Multi.mul", 0x2000, 14);
m_Components = new MultiComponentList[0x2000];
}
/// <summary>
/// Gets <see cref="MultiComponentList" /> of multi
/// </summary>
/// <param name="index"></param>
/// <returns></returns>
public static MultiComponentList GetComponents(int index)
{
MultiComponentList mcl;
index &= 0x1FFF;
if (index >= 0 && index < m_Components.Length)
{
mcl = m_Components[index];
if (mcl == null)
{
m_Components[index] = mcl = Load(index);
}
}
else
{
mcl = MultiComponentList.Empty;
}
return mcl;
}
public static MultiComponentList Load(int index)
{
try
{
int length, extra;
bool patched;
Stream stream = m_FileIndex.Seek(index, out length, out extra, out patched);
if (stream == null)
{
return MultiComponentList.Empty;
}
if (PostHSFormat || Art.IsUOAHS())
{
return new MultiComponentList(new BinaryReader(stream), length / 16);
}
else
{
return new MultiComponentList(new BinaryReader(stream), length / 12);
}
}
catch
{
return MultiComponentList.Empty;
}
}
public static void Remove(int index)
{
m_Components[index] = MultiComponentList.Empty;
}
public static void Add(int index, MultiComponentList comp)
{
m_Components[index] = comp;
}
public static MultiComponentList ImportFromFile(int index, string FileName, ImportType type)
{
try
{
return m_Components[index] = new MultiComponentList(FileName, type);
}
catch
{
return m_Components[index] = MultiComponentList.Empty;
}
}
public static MultiComponentList LoadFromFile(string FileName, ImportType type)
{
try
{
return new MultiComponentList(FileName, type);
}
catch
{
return MultiComponentList.Empty;
}
}
public static List<MultiComponentList> LoadFromCache(string FileName)
{
var multilist = new List<MultiComponentList>();
using (var ip = new StreamReader(FileName))
{
string line;
while ((line = ip.ReadLine()) != null)
{
string[] split = Regex.Split(line, @"\s+");
if (split.Length == 7)
{
int count = Convert.ToInt32(split[2]);
multilist.Add(new MultiComponentList(ip, count));
}
}
}
return multilist;
}
public static string ReadUOAString(BinaryReader bin)
{
byte flag = bin.ReadByte();
if (flag == 0)
{
return null;
}
else
{
return bin.ReadString();
}
}
public static List<Object[]> LoadFromDesigner(string FileName)
{
var multilist = new List<Object[]>();
string root = Path.GetFileNameWithoutExtension(FileName);
string idx = String.Format("{0}.idx", root);
string bin = String.Format("{0}.bin", root);
if ((!File.Exists(idx)) || (!File.Exists(bin)))
{
return multilist;
}
using (
FileStream idxfs = new FileStream(idx, FileMode.Open, FileAccess.Read, FileShare.Read),
binfs = new FileStream(bin, FileMode.Open, FileAccess.Read, FileShare.Read))
{
using (BinaryReader idxbin = new BinaryReader(idxfs), binbin = new BinaryReader(binfs))
{
int count = idxbin.ReadInt32();
int version = idxbin.ReadInt32();
for (int i = 0; i < count; ++i)
{
var data = new Object[2];
switch (version)
{
case 0:
data[0] = ReadUOAString(idxbin);
var arr = new List<MultiComponentList.MultiTileEntry>();
data[0] += "-" + ReadUOAString(idxbin);
data[0] += "-" + ReadUOAString(idxbin);
int width = idxbin.ReadInt32();
int height = idxbin.ReadInt32();
int uwidth = idxbin.ReadInt32();
int uheight = idxbin.ReadInt32();
long filepos = idxbin.ReadInt64();
int reccount = idxbin.ReadInt32();
binbin.BaseStream.Seek(filepos, SeekOrigin.Begin);
int index, x, y, z, level, hue;
for (int j = 0; j < reccount; ++j)
{
index = x = y = z = level = hue = 0;
int compVersion = binbin.ReadInt32();
switch (compVersion)
{
case 0:
index = binbin.ReadInt32();
x = binbin.ReadInt32();
y = binbin.ReadInt32();
z = binbin.ReadInt32();
level = binbin.ReadInt32();
break;
case 1:
index = binbin.ReadInt32();
x = binbin.ReadInt32();
y = binbin.ReadInt32();
z = binbin.ReadInt32();
level = binbin.ReadInt32();
hue = binbin.ReadInt32();
break;
}
var tempitem = new MultiComponentList.MultiTileEntry();
tempitem.m_ItemID = (ushort)index;
tempitem.m_Flags = TileFlag.Background;
tempitem.m_OffsetX = (short)x;
tempitem.m_OffsetY = (short)y;
tempitem.m_OffsetZ = (short)z;
arr.Add(tempitem);
}
data[1] = new MultiComponentList(arr);
break;
}
multilist.Add(data);
}
}
return multilist;
}
}
public static List<MultiComponentList.MultiTileEntry> RebuildTiles(MultiComponentList.MultiTileEntry[] tiles)
{
var newtiles = new List<MultiComponentList.MultiTileEntry>();
newtiles.AddRange(tiles);
if (newtiles[0].m_OffsetX == 0 && newtiles[0].m_OffsetY == 0 && newtiles[0].m_OffsetZ == 0) // found a centeritem
{
if (newtiles[0].m_ItemID != 0x1) // its a "good" one
{
for (int j = newtiles.Count - 1; j >= 0; --j) // remove all invis items
{
if (newtiles[j].m_ItemID == 0x1)
{
newtiles.RemoveAt(j);
}
}
return newtiles;
}
else // a bad one
{
for (int i = 1; i < newtiles.Count; ++i) // do we have a better one?
{
if (newtiles[i].m_OffsetX == 0 && newtiles[i].m_OffsetY == 0 && newtiles[i].m_ItemID != 0x1 &&
newtiles[i].m_OffsetZ == 0)
{
MultiComponentList.MultiTileEntry centeritem = newtiles[i];
newtiles.RemoveAt(i); // jep so save it
for (int j = newtiles.Count - 1; j >= 0; --j) // and remove all invis
{
if (newtiles[j].m_ItemID == 0x1)
{
newtiles.RemoveAt(j);
}
}
newtiles.Insert(0, centeritem);
return newtiles;
}
}
for (int j = newtiles.Count - 1; j >= 1; --j) // nothing found so remove all invis exept the first
{
if (newtiles[j].m_ItemID == 0x1)
{
newtiles.RemoveAt(j);
}
}
return newtiles;
}
}
for (int i = 0; i < newtiles.Count; ++i) // is there a good one
{
if (newtiles[i].m_OffsetX == 0 && newtiles[i].m_OffsetY == 0 && newtiles[i].m_ItemID != 0x1 &&
newtiles[i].m_OffsetZ == 0)
{
MultiComponentList.MultiTileEntry centeritem = newtiles[i];
newtiles.RemoveAt(i); // store it
for (int j = newtiles.Count - 1; j >= 0; --j) // remove all invis
{
if (newtiles[j].m_ItemID == 0x1)
{
newtiles.RemoveAt(j);
}
}
newtiles.Insert(0, centeritem);
return newtiles;
}
}
for (int j = newtiles.Count - 1; j >= 0; --j) // nothing found so remove all invis
{
if (newtiles[j].m_ItemID == 0x1)
{
newtiles.RemoveAt(j);
}
}
var invisitem = new MultiComponentList.MultiTileEntry();
invisitem.m_ItemID = 0x1; // and create a new invis
invisitem.m_OffsetX = 0;
invisitem.m_OffsetY = 0;
invisitem.m_OffsetZ = 0;
invisitem.m_Flags = 0;
newtiles.Insert(0, invisitem);
return newtiles;
}
public static void Save(string path)
{
bool isUOAHS = PostHSFormat || Art.IsUOAHS();
string idx = Path.Combine(path, "multi.idx");
string mul = Path.Combine(path, "multi.mul");
using (
FileStream fsidx = new FileStream(idx, FileMode.Create, FileAccess.Write, FileShare.Write),
fsmul = new FileStream(mul, FileMode.Create, FileAccess.Write, FileShare.Write))
{
using (BinaryWriter binidx = new BinaryWriter(fsidx), binmul = new BinaryWriter(fsmul))
{
for (int index = 0; index < 0x2000; ++index)
{
MultiComponentList comp = GetComponents(index);
if (comp == MultiComponentList.Empty)
{
binidx.Write(-1); // lookup
binidx.Write(-1); // length
binidx.Write(-1); // extra
}
else
{
List<MultiComponentList.MultiTileEntry> tiles = RebuildTiles(comp.SortedTiles);
binidx.Write((int)fsmul.Position); //lookup
if (isUOAHS)
{
binidx.Write((tiles.Count * 16)); //length
}
else
{
binidx.Write((tiles.Count * 12)); //length
}
binidx.Write(-1); //extra
for (int i = 0; i < tiles.Count; ++i)
{
binmul.Write(tiles[i].m_ItemID);
binmul.Write(tiles[i].m_OffsetX);
binmul.Write(tiles[i].m_OffsetY);
binmul.Write(tiles[i].m_OffsetZ);
if (isUOAHS)
{
binmul.Write((ulong)tiles[i].m_Flags);
}
else
{
binmul.Write((uint)tiles[i].m_Flags);
}
}
}
}
}
}
}
}
public sealed class MultiComponentList
{
private Point m_Min, m_Max, m_Center;
private int m_Width, m_Height;
private readonly int m_maxHeight;
private int m_Surface;
private MTile[][][] m_Tiles;
private readonly MultiTileEntry[] m_SortedTiles;
public static readonly MultiComponentList Empty = new MultiComponentList();
public Point Min { get { return m_Min; } }
public Point Max { get { return m_Max; } }
public Point Center { get { return m_Center; } }
public int Width { get { return m_Width; } }
public int Height { get { return m_Height; } }
public MTile[][][] Tiles { get { return m_Tiles; } }
public int maxHeight { get { return m_maxHeight; } }
public MultiTileEntry[] SortedTiles { get { return m_SortedTiles; } }
public int Surface { get { return m_Surface; } }
public struct MultiTileEntry
{
public ushort m_ItemID;
public short m_OffsetX, m_OffsetY, m_OffsetZ;
public TileFlag m_Flags;
}
/// <summary>
/// Returns Bitmap of Multi
/// </summary>
/// <returns></returns>
public Bitmap GetImage()
{
return GetImage(300);
}
/// <summary>
/// Returns Bitmap of Multi to maxheight
/// </summary>
/// <param name="maxheight"></param>
/// <returns></returns>
public Bitmap GetImage(int maxheight)
{
if (m_Width == 0 || m_Height == 0)
{
return null;
}
int xMin = 1000, yMin = 1000;
int xMax = -1000, yMax = -1000;
for (int x = 0; x < m_Width; ++x)
{
for (int y = 0; y < m_Height; ++y)
{
MTile[] tiles = m_Tiles[x][y];
for (int i = 0; i < tiles.Length; ++i)
{
Bitmap bmp = Art.GetStatic(tiles[i].ID);
if (bmp == null)
{
continue;
}
int px = (x - y) * 22;
int py = (x + y) * 22;
px -= (bmp.Width / 2);
py -= tiles[i].Z << 2;
py -= bmp.Height;
if (px < xMin)
{
xMin = px;
}
if (py < yMin)
{
yMin = py;
}
px += bmp.Width;
py += bmp.Height;
if (px > xMax)
{
xMax = px;
}
if (py > yMax)
{
yMax = py;
}
}
}
}
var canvas = new Bitmap(xMax - xMin, yMax - yMin);
Graphics gfx = Graphics.FromImage(canvas);
gfx.Clear(Color.White);
for (int x = 0; x < m_Width; ++x)
{
for (int y = 0; y < m_Height; ++y)
{
MTile[] tiles = m_Tiles[x][y];
for (int i = 0; i < tiles.Length; ++i)
{
Bitmap bmp = Art.GetStatic(tiles[i].ID);
if (bmp == null)
{
continue;
}
if ((tiles[i].Z) > maxheight)
{
continue;
}
int px = (x - y) * 22;
int py = (x + y) * 22;
px -= (bmp.Width / 2);
py -= tiles[i].Z << 2;
py -= bmp.Height;
px -= xMin;
py -= yMin;
gfx.DrawImageUnscaled(bmp, px, py, bmp.Width, bmp.Height);
}
int tx = (x - y) * 22;
int ty = (x + y) * 22;
tx -= xMin;
ty -= yMin;
}
}
gfx.Dispose();
return canvas;
}
public MultiComponentList(BinaryReader reader, int count)
{
bool useNewMultiFormat = Multis.PostHSFormat || Art.IsUOAHS();
m_Min = m_Max = Point.Empty;
m_SortedTiles = new MultiTileEntry[count];
for (int i = 0; i < count; ++i)
{
m_SortedTiles[i].m_ItemID = Art.GetLegalItemID(reader.ReadUInt16());
m_SortedTiles[i].m_OffsetX = reader.ReadInt16();
m_SortedTiles[i].m_OffsetY = reader.ReadInt16();
m_SortedTiles[i].m_OffsetZ = reader.ReadInt16();
if (useNewMultiFormat)
{
m_SortedTiles[i].m_Flags = (TileFlag)reader.ReadUInt64();
}
else
{
m_SortedTiles[i].m_Flags = (TileFlag)reader.ReadUInt32();
}
MultiTileEntry e = m_SortedTiles[i];
if (e.m_OffsetX < m_Min.X)
{
m_Min.X = e.m_OffsetX;
}
if (e.m_OffsetY < m_Min.Y)
{
m_Min.Y = e.m_OffsetY;
}
if (e.m_OffsetX > m_Max.X)
{
m_Max.X = e.m_OffsetX;
}
if (e.m_OffsetY > m_Max.Y)
{
m_Max.Y = e.m_OffsetY;
}
if (e.m_OffsetZ > m_maxHeight)
{
m_maxHeight = e.m_OffsetZ;
}
}
ConvertList();
reader.Close();
}
public MultiComponentList(string FileName, Multis.ImportType Type)
{
m_Min = m_Max = Point.Empty;
int itemcount;
switch (Type)
{
case Multis.ImportType.TXT:
itemcount = 0;
using (var ip = new StreamReader(FileName))
{
string line;
while ((line = ip.ReadLine()) != null)
{
itemcount++;
}
}
m_SortedTiles = new MultiTileEntry[itemcount];
itemcount = 0;
m_Min.X = 10000;
m_Min.Y = 10000;
using (var ip = new StreamReader(FileName))
{
string line;
while ((line = ip.ReadLine()) != null)
{
string[] split = line.Split(' ');
string tmp = split[0];
tmp = tmp.Replace("0x", "");
m_SortedTiles[itemcount].m_ItemID = ushort.Parse(tmp, NumberStyles.HexNumber);
m_SortedTiles[itemcount].m_OffsetX = Convert.ToInt16(split[1]);
m_SortedTiles[itemcount].m_OffsetY = Convert.ToInt16(split[2]);
m_SortedTiles[itemcount].m_OffsetZ = Convert.ToInt16(split[3]);
m_SortedTiles[itemcount].m_Flags = (TileFlag)Convert.ToUInt64(split[4]);
MultiTileEntry e = m_SortedTiles[itemcount];
if (e.m_OffsetX < m_Min.X)
{
m_Min.X = e.m_OffsetX;
}
if (e.m_OffsetY < m_Min.Y)
{
m_Min.Y = e.m_OffsetY;
}
if (e.m_OffsetX > m_Max.X)
{
m_Max.X = e.m_OffsetX;
}
if (e.m_OffsetY > m_Max.Y)
{
m_Max.Y = e.m_OffsetY;
}
if (e.m_OffsetZ > m_maxHeight)
{
m_maxHeight = e.m_OffsetZ;
}
itemcount++;
}
int centerx = m_Max.X - (int)(Math.Round((m_Max.X - m_Min.X) / 2.0));
int centery = m_Max.Y - (int)(Math.Round((m_Max.Y - m_Min.Y) / 2.0));
m_Min = m_Max = Point.Empty;
int i = 0;
for (; i < m_SortedTiles.Length; i++)
{
m_SortedTiles[i].m_OffsetX -= (short)centerx;
m_SortedTiles[i].m_OffsetY -= (short)centery;
if (m_SortedTiles[i].m_OffsetX < m_Min.X)
{
m_Min.X = m_SortedTiles[i].m_OffsetX;
}
if (m_SortedTiles[i].m_OffsetX > m_Max.X)
{
m_Max.X = m_SortedTiles[i].m_OffsetX;
}
if (m_SortedTiles[i].m_OffsetY < m_Min.Y)
{
m_Min.Y = m_SortedTiles[i].m_OffsetY;
}
if (m_SortedTiles[i].m_OffsetY > m_Max.Y)
{
m_Max.Y = m_SortedTiles[i].m_OffsetY;
}
}
}
break;
case Multis.ImportType.UOA:
itemcount = 0;
using (var ip = new StreamReader(FileName))
{
string line;
while ((line = ip.ReadLine()) != null)
{
++itemcount;
if (itemcount == 4)
{
string[] split = line.Split(' ');
itemcount = Convert.ToInt32(split[0]);
break;
}
}
}
m_SortedTiles = new MultiTileEntry[itemcount];
itemcount = 0;
m_Min.X = 10000;
m_Min.Y = 10000;
using (var ip = new StreamReader(FileName))
{
string line;
int i = -1;
while ((line = ip.ReadLine()) != null)
{
++i;
if (i < 4)
{
continue;
}
string[] split = line.Split(' ');
m_SortedTiles[itemcount].m_ItemID = Convert.ToUInt16(split[0]);
m_SortedTiles[itemcount].m_OffsetX = Convert.ToInt16(split[1]);
m_SortedTiles[itemcount].m_OffsetY = Convert.ToInt16(split[2]);
m_SortedTiles[itemcount].m_OffsetZ = Convert.ToInt16(split[3]);
m_SortedTiles[itemcount].m_Flags = (TileFlag)Convert.ToUInt64(split[4]);
MultiTileEntry e = m_SortedTiles[itemcount];
if (e.m_OffsetX < m_Min.X)
{
m_Min.X = e.m_OffsetX;
}
if (e.m_OffsetY < m_Min.Y)
{
m_Min.Y = e.m_OffsetY;
}
if (e.m_OffsetX > m_Max.X)
{
m_Max.X = e.m_OffsetX;
}
if (e.m_OffsetY > m_Max.Y)
{
m_Max.Y = e.m_OffsetY;
}
if (e.m_OffsetZ > m_maxHeight)
{
m_maxHeight = e.m_OffsetZ;
}
++itemcount;
}
int centerx = m_Max.X - (int)(Math.Round((m_Max.X - m_Min.X) / 2.0));
int centery = m_Max.Y - (int)(Math.Round((m_Max.Y - m_Min.Y) / 2.0));
m_Min = m_Max = Point.Empty;
i = 0;
for (; i < m_SortedTiles.Length; ++i)
{
m_SortedTiles[i].m_OffsetX -= (short)centerx;
m_SortedTiles[i].m_OffsetY -= (short)centery;
if (m_SortedTiles[i].m_OffsetX < m_Min.X)
{
m_Min.X = m_SortedTiles[i].m_OffsetX;
}
if (m_SortedTiles[i].m_OffsetX > m_Max.X)
{
m_Max.X = m_SortedTiles[i].m_OffsetX;
}
if (m_SortedTiles[i].m_OffsetY < m_Min.Y)
{
m_Min.Y = m_SortedTiles[i].m_OffsetY;
}
if (m_SortedTiles[i].m_OffsetY > m_Max.Y)
{
m_Max.Y = m_SortedTiles[i].m_OffsetY;
}
}
}
break;
case Multis.ImportType.UOAB:
using (var fs = new FileStream(FileName, FileMode.Open, FileAccess.Read, FileShare.Read))
{
using (var reader = new BinaryReader(fs))
{
if (reader.ReadInt16() != 1) //Version check
{
return;
}
string tmp;
tmp = Multis.ReadUOAString(reader); //Name
tmp = Multis.ReadUOAString(reader); //Category
tmp = Multis.ReadUOAString(reader); //Subsection
int width = reader.ReadInt32();
int height = reader.ReadInt32();
int uwidth = reader.ReadInt32();
int uheight = reader.ReadInt32();
int count = reader.ReadInt32();
itemcount = count;
m_SortedTiles = new MultiTileEntry[itemcount];
itemcount = 0;
m_Min.X = 10000;
m_Min.Y = 10000;
for (; itemcount < count; ++itemcount)
{
m_SortedTiles[itemcount].m_ItemID = (ushort)reader.ReadInt16();
m_SortedTiles[itemcount].m_OffsetX = reader.ReadInt16();
m_SortedTiles[itemcount].m_OffsetY = reader.ReadInt16();
m_SortedTiles[itemcount].m_OffsetZ = reader.ReadInt16();
reader.ReadInt16(); // level
m_SortedTiles[itemcount].m_Flags = TileFlag.Background;
reader.ReadInt16(); // hue
MultiTileEntry e = m_SortedTiles[itemcount];
if (e.m_OffsetX < m_Min.X)
{
m_Min.X = e.m_OffsetX;
}
if (e.m_OffsetY < m_Min.Y)
{
m_Min.Y = e.m_OffsetY;
}
if (e.m_OffsetX > m_Max.X)
{
m_Max.X = e.m_OffsetX;
}
if (e.m_OffsetY > m_Max.Y)
{
m_Max.Y = e.m_OffsetY;
}
if (e.m_OffsetZ > m_maxHeight)
{
m_maxHeight = e.m_OffsetZ;
}
}
int centerx = m_Max.X - (int)(Math.Round((m_Max.X - m_Min.X) / 2.0));
int centery = m_Max.Y - (int)(Math.Round((m_Max.Y - m_Min.Y) / 2.0));
m_Min = m_Max = Point.Empty;
itemcount = 0;
for (; itemcount < m_SortedTiles.Length; ++itemcount)
{
m_SortedTiles[itemcount].m_OffsetX -= (short)centerx;
m_SortedTiles[itemcount].m_OffsetY -= (short)centery;
if (m_SortedTiles[itemcount].m_OffsetX < m_Min.X)
{
m_Min.X = m_SortedTiles[itemcount].m_OffsetX;
}
if (m_SortedTiles[itemcount].m_OffsetX > m_Max.X)
{
m_Max.X = m_SortedTiles[itemcount].m_OffsetX;
}
if (m_SortedTiles[itemcount].m_OffsetY < m_Min.Y)
{
m_Min.Y = m_SortedTiles[itemcount].m_OffsetY;
}
if (m_SortedTiles[itemcount].m_OffsetY > m_Max.Y)
{
m_Max.Y = m_SortedTiles[itemcount].m_OffsetY;
}
}
}
}
break;
case Multis.ImportType.WSC:
itemcount = 0;
using (var ip = new StreamReader(FileName))
{
string line;
while ((line = ip.ReadLine()) != null)
{
line = line.Trim();
if (line.StartsWith("SECTION WORLDITEM"))
{
++itemcount;
}
}
}
m_SortedTiles = new MultiTileEntry[itemcount];
itemcount = 0;
m_Min.X = 10000;
m_Min.Y = 10000;
using (var ip = new StreamReader(FileName))
{
string line;
var tempitem = new MultiTileEntry();
tempitem.m_ItemID = 0xFFFF;
tempitem.m_Flags = TileFlag.Background;
while ((line = ip.ReadLine()) != null)
{
line = line.Trim();
if (line.StartsWith("SECTION WORLDITEM"))
{
if (tempitem.m_ItemID != 0xFFFF)
{
m_SortedTiles[itemcount] = tempitem;
++itemcount;
}
tempitem.m_ItemID = 0xFFFF;
}
else if (line.StartsWith("ID"))
{
line = line.Remove(0, 2);
line = line.Trim();
tempitem.m_ItemID = Convert.ToUInt16(line);
}
else if (line.StartsWith("X"))
{
line = line.Remove(0, 1);
line = line.Trim();
tempitem.m_OffsetX = Convert.ToInt16(line);
if (tempitem.m_OffsetX < m_Min.X)
{
m_Min.X = tempitem.m_OffsetX;
}
if (tempitem.m_OffsetX > m_Max.X)
{
m_Max.X = tempitem.m_OffsetX;
}
}
else if (line.StartsWith("Y"))
{
line = line.Remove(0, 1);
line = line.Trim();
tempitem.m_OffsetY = Convert.ToInt16(line);
if (tempitem.m_OffsetY < m_Min.Y)
{
m_Min.Y = tempitem.m_OffsetY;
}
if (tempitem.m_OffsetY > m_Max.Y)
{
m_Max.Y = tempitem.m_OffsetY;
}
}
else if (line.StartsWith("Z"))
{
line = line.Remove(0, 1);
line = line.Trim();
tempitem.m_OffsetZ = Convert.ToInt16(line);
if (tempitem.m_OffsetZ > m_maxHeight)
{
m_maxHeight = tempitem.m_OffsetZ;
}
}
}
if (tempitem.m_ItemID != 0xFFFF)
{
m_SortedTiles[itemcount] = tempitem;
}
int centerx = m_Max.X - (int)(Math.Round((m_Max.X - m_Min.X) / 2.0));
int centery = m_Max.Y - (int)(Math.Round((m_Max.Y - m_Min.Y) / 2.0));
m_Min = m_Max = Point.Empty;
int i = 0;
for (; i < m_SortedTiles.Length; i++)
{
m_SortedTiles[i].m_OffsetX -= (short)centerx;
m_SortedTiles[i].m_OffsetY -= (short)centery;
if (m_SortedTiles[i].m_OffsetX < m_Min.X)
{
m_Min.X = m_SortedTiles[i].m_OffsetX;
}
if (m_SortedTiles[i].m_OffsetX > m_Max.X)
{
m_Max.X = m_SortedTiles[i].m_OffsetX;
}
if (m_SortedTiles[i].m_OffsetY < m_Min.Y)
{
m_Min.Y = m_SortedTiles[i].m_OffsetY;
}
if (m_SortedTiles[i].m_OffsetY > m_Max.Y)
{
m_Max.Y = m_SortedTiles[i].m_OffsetY;
}
}
}
break;
}
ConvertList();
}
public MultiComponentList(List<MultiTileEntry> arr)
{
m_Min = m_Max = Point.Empty;
int itemcount = arr.Count;
m_SortedTiles = new MultiTileEntry[itemcount];
m_Min.X = 10000;
m_Min.Y = 10000;
int i = 0;
foreach (MultiTileEntry entry in arr)
{
if (entry.m_OffsetX < m_Min.X)
{
m_Min.X = entry.m_OffsetX;
}
if (entry.m_OffsetY < m_Min.Y)
{
m_Min.Y = entry.m_OffsetY;
}
if (entry.m_OffsetX > m_Max.X)
{
m_Max.X = entry.m_OffsetX;
}
if (entry.m_OffsetY > m_Max.Y)
{
m_Max.Y = entry.m_OffsetY;
}
if (entry.m_OffsetZ > m_maxHeight)
{
m_maxHeight = entry.m_OffsetZ;
}
m_SortedTiles[i] = entry;
++i;
}
arr.Clear();
int centerx = m_Max.X - (int)(Math.Round((m_Max.X - m_Min.X) / 2.0));
int centery = m_Max.Y - (int)(Math.Round((m_Max.Y - m_Min.Y) / 2.0));
m_Min = m_Max = Point.Empty;
for (i = 0; i < m_SortedTiles.Length; ++i)
{
m_SortedTiles[i].m_OffsetX -= (short)centerx;
m_SortedTiles[i].m_OffsetY -= (short)centery;
if (m_SortedTiles[i].m_OffsetX < m_Min.X)
{
m_Min.X = m_SortedTiles[i].m_OffsetX;
}
if (m_SortedTiles[i].m_OffsetX > m_Max.X)
{
m_Max.X = m_SortedTiles[i].m_OffsetX;
}
if (m_SortedTiles[i].m_OffsetY < m_Min.Y)
{
m_Min.Y = m_SortedTiles[i].m_OffsetY;
}
if (m_SortedTiles[i].m_OffsetY > m_Max.Y)
{
m_Max.Y = m_SortedTiles[i].m_OffsetY;
}
}
ConvertList();
}
public MultiComponentList(StreamReader stream, int count)
{
string line;
int itemcount = 0;
m_Min = m_Max = Point.Empty;
m_SortedTiles = new MultiTileEntry[count];
m_Min.X = 10000;
m_Min.Y = 10000;
while ((line = stream.ReadLine()) != null)
{
string[] split = Regex.Split(line, @"\s+");
m_SortedTiles[itemcount].m_ItemID = Convert.ToUInt16(split[0]);
m_SortedTiles[itemcount].m_Flags = (TileFlag)Convert.ToUInt64(split[1]);
m_SortedTiles[itemcount].m_OffsetX = Convert.ToInt16(split[2]);
m_SortedTiles[itemcount].m_OffsetY = Convert.ToInt16(split[3]);
m_SortedTiles[itemcount].m_OffsetZ = Convert.ToInt16(split[4]);
MultiTileEntry e = m_SortedTiles[itemcount];
if (e.m_OffsetX < m_Min.X)
{
m_Min.X = e.m_OffsetX;
}
if (e.m_OffsetY < m_Min.Y)
{
m_Min.Y = e.m_OffsetY;
}
if (e.m_OffsetX > m_Max.X)
{
m_Max.X = e.m_OffsetX;
}
if (e.m_OffsetY > m_Max.Y)
{
m_Max.Y = e.m_OffsetY;
}
if (e.m_OffsetZ > m_maxHeight)
{
m_maxHeight = e.m_OffsetZ;
}
++itemcount;
if (itemcount == count)
{
break;
}
}
int centerx = m_Max.X - (int)(Math.Round((m_Max.X - m_Min.X) / 2.0));
int centery = m_Max.Y - (int)(Math.Round((m_Max.Y - m_Min.Y) / 2.0));
m_Min = m_Max = Point.Empty;
int i = 0;
for (; i < m_SortedTiles.Length; i++)
{
m_SortedTiles[i].m_OffsetX -= (short)centerx;
m_SortedTiles[i].m_OffsetY -= (short)centery;
if (m_SortedTiles[i].m_OffsetX < m_Min.X)
{
m_Min.X = m_SortedTiles[i].m_OffsetX;
}
if (m_SortedTiles[i].m_OffsetX > m_Max.X)
{
m_Max.X = m_SortedTiles[i].m_OffsetX;
}
if (m_SortedTiles[i].m_OffsetY < m_Min.Y)
{
m_Min.Y = m_SortedTiles[i].m_OffsetY;
}
if (m_SortedTiles[i].m_OffsetY > m_Max.Y)
{
m_Max.Y = m_SortedTiles[i].m_OffsetY;
}
}
ConvertList();
}
private void ConvertList()
{
m_Center = new Point(-m_Min.X, -m_Min.Y);
m_Width = (m_Max.X - m_Min.X) + 1;
m_Height = (m_Max.Y - m_Min.Y) + 1;
var tiles = new MTileList[m_Width][];
m_Tiles = new MTile[m_Width][][];
for (int x = 0; x < m_Width; ++x)
{
tiles[x] = new MTileList[m_Height];
m_Tiles[x] = new MTile[m_Height][];
for (int y = 0; y < m_Height; ++y)
{
tiles[x][y] = new MTileList();
}
}
for (int i = 0; i < m_SortedTiles.Length; ++i)
{
int xOffset = m_SortedTiles[i].m_OffsetX + m_Center.X;
int yOffset = m_SortedTiles[i].m_OffsetY + m_Center.Y;
tiles[xOffset][yOffset]
.Add((m_SortedTiles[i].m_ItemID), (sbyte)m_SortedTiles[i].m_OffsetZ, m_SortedTiles[i].m_Flags);
}
m_Surface = 0;
for (int x = 0; x < m_Width; ++x)
{
for (int y = 0; y < m_Height; ++y)
{
m_Tiles[x][y] = tiles[x][y].ToArray();
for (int i = 0; i < m_Tiles[x][y].Length; ++i)
{
m_Tiles[x][y][i].Solver = i;
}
if (m_Tiles[x][y].Length > 1)
{
Array.Sort(m_Tiles[x][y]);
}
if (m_Tiles[x][y].Length > 0)
{
++m_Surface;
}
}
}
}
public MultiComponentList(MTileList[][] newtiles, int count, int width, int height)
{
m_Min = m_Max = Point.Empty;
m_SortedTiles = new MultiTileEntry[count];
m_Center = new Point((int)(Math.Round((width / 2.0))) - 1, (int)(Math.Round((height / 2.0))) - 1);
if (m_Center.X < 0)
{
m_Center.X = width / 2;
}
if (m_Center.Y < 0)
{
m_Center.Y = height / 2;
}
m_maxHeight = -128;
int counter = 0;
for (int x = 0; x < width; ++x)
{
for (int y = 0; y < height; ++y)
{
MTile[] tiles = newtiles[x][y].ToArray();
for (int i = 0; i < tiles.Length; ++i)
{
m_SortedTiles[counter].m_ItemID = (tiles[i].ID);
m_SortedTiles[counter].m_OffsetX = (short)(x - m_Center.X);
m_SortedTiles[counter].m_OffsetY = (short)(y - m_Center.Y);
m_SortedTiles[counter].m_OffsetZ = (short)(tiles[i].Z);
m_SortedTiles[counter].m_Flags = tiles[i].Flag;
if (m_SortedTiles[counter].m_OffsetX < m_Min.X)
{
m_Min.X = m_SortedTiles[counter].m_OffsetX;
}
if (m_SortedTiles[counter].m_OffsetX > m_Max.X)
{
m_Max.X = m_SortedTiles[counter].m_OffsetX;
}
if (m_SortedTiles[counter].m_OffsetY < m_Min.Y)
{
m_Min.Y = m_SortedTiles[counter].m_OffsetY;
}
if (m_SortedTiles[counter].m_OffsetY > m_Max.Y)
{
m_Max.Y = m_SortedTiles[counter].m_OffsetY;
}
if (m_SortedTiles[counter].m_OffsetZ > m_maxHeight)
{
m_maxHeight = m_SortedTiles[counter].m_OffsetZ;
}
++counter;
}
}
}
ConvertList();
}
private MultiComponentList()
{
m_Tiles = new MTile[0][][];
}
public void ExportToTextFile(string FileName)
{
using (
var Tex = new StreamWriter(
new FileStream(FileName, FileMode.Create, FileAccess.ReadWrite), Encoding.GetEncoding(1252)))
{
for (int i = 0; i < m_SortedTiles.Length; ++i)
{
Tex.WriteLine(
String.Format(
"0x{0:X} {1} {2} {3} {4}",
m_SortedTiles[i].m_ItemID,
m_SortedTiles[i].m_OffsetX,
m_SortedTiles[i].m_OffsetY,
m_SortedTiles[i].m_OffsetZ,
m_SortedTiles[i].m_Flags));
}
}
}
public void ExportToWscFile(string FileName)
{
using (
var Tex = new StreamWriter(
new FileStream(FileName, FileMode.Create, FileAccess.ReadWrite), Encoding.GetEncoding(1252)))
{
for (int i = 0; i < m_SortedTiles.Length; ++i)
{
Tex.WriteLine(String.Format("SECTION WORLDITEM {0}", i));
Tex.WriteLine("{");
Tex.WriteLine(String.Format("\tID\t{0}", m_SortedTiles[i].m_ItemID));
Tex.WriteLine(String.Format("\tX\t{0}", m_SortedTiles[i].m_OffsetX));
Tex.WriteLine(String.Format("\tY\t{0}", m_SortedTiles[i].m_OffsetY));
Tex.WriteLine(String.Format("\tZ\t{0}", m_SortedTiles[i].m_OffsetZ));
Tex.WriteLine("\tColor\t0");
Tex.WriteLine("}");
}
}
}
public void ExportToUOAFile(string FileName)
{
using (
var Tex = new StreamWriter(
new FileStream(FileName, FileMode.Create, FileAccess.ReadWrite), Encoding.GetEncoding(1252)))
{
Tex.WriteLine("6 version");
Tex.WriteLine("1 template id");
Tex.WriteLine("-1 item version");
Tex.WriteLine(String.Format("{0} num components", m_SortedTiles.Length));
for (int i = 0; i < m_SortedTiles.Length; ++i)
{
Tex.WriteLine(
String.Format(
"{0} {1} {2} {3} {4}",
m_SortedTiles[i].m_ItemID,
m_SortedTiles[i].m_OffsetX,
m_SortedTiles[i].m_OffsetY,
m_SortedTiles[i].m_OffsetZ,
m_SortedTiles[i].m_Flags));
}
}
}
}
}